Thông báo

Collapse
No announcement yet.

Nhờ các bác xem xét code về Synchronous FIFO này em với,

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Nhờ các bác xem xét code về Synchronous FIFO này em với,

    Em đang tìm hiểu để code một cái synchronous FIFO 8x32, em có tìm được source code này nhưng khi dùng testbench mô phỏng thấy nó hơi khác. Mong các bác cho ý kiến xem source code này có đúng không? do thời gian gấp quá nên chưa nghiên cứu tự code được. Thanks!

    synchronous FIFO 8x32 code:

    Code:
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;
    
    entity FIFO8x32 is
      port (
        reset, clk, r, w : in  std_logic;
        empty, full      : out std_logic;
        d                : in  std_logic_vector(31 downto 0);
        q                : out std_logic_vector(31 downto 0));
    
    end FIFO8x32;
    
    architecture Behavioral of FIFO8x32 is
    
      constant m                   : integer := 8;
      constant n                   : integer := 32;
      signal   rcntr, wcntr        : std_logic_vector(2 downto 0);
      subtype  wrdtype is std_logic_vector(n - 1 downto 0);
      type     regtype is array(0 to m - 1) of wrdtype;
      signal   reg                 : regtype;
      signal   rw                  : std_logic_vector(1 downto 0);
      signal   full_buf, empty_buf : std_logic;
    
    begin
    
      rw <= r & w;
      seq : process(reset, clk)
      begin
        if reset = '1' then
          rcntr     <= (others => '0');
          wcntr     <= (others => '0');
          empty_buf <= '1';
          full_buf  <= '0';
          for j in 0 to m - 1 loop
            reg(j) <= (others => '0');
          end loop;
        elsif rising_edge(clk) then
          case rw is
            when "11" =>
                -- read and write at the same time
                if  empty_buf = '1' then
                    empty_buf<='0';
                elsif rcntr = m-1 then
                    empty_buf <= '1';
                end if;
                if full_buf = '0' then
                    -- not full
                    reg(conv_integer(wcntr)) <= d;
                    wcntr <= wcntr + 1;
                    rcntr <= rcntr + 1;
                else
                end if;
            
            when "10" =>
                -- only read
                if empty_buf = '0' then
                    -- not empty
                    if (rcntr + 1) = wcntr then
                        empty_buf <= '1';
                    end if;
                rcntr <= rcntr + 1;
                end if;
                full_buf <= '0';
                
            when "01" =>
                -- only write
                empty_buf <= '0';
                if full_buf = '0' then
                    -- not full
                    reg(conv_integer(wcntr)) <= d;
                    if (wcntr + 1) = rcntr then
                    full_buf <= '1';
                    end if;
                wcntr <= wcntr + 1;
                end if;
                
            when others => null;
              
          end case;
        end if;
      end process;
      --q     <= reg(conv_integer(rcntr)) ;
      q     <= reg(conv_integer(rcntr-1)) when rw="11" else reg(conv_integer(rcntr)) ;
      full  <= full_buf;
      empty <= empty_buf;
      
    end Behavioral;
    testbench
    Code:
    
    LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
    USE ieee.std_logic_unsigned.all;
    USE ieee.numeric_std.ALL;
    
    ENTITY tb_fifo832 IS
    
    port( empty : out std_logic;
           full  : out std_logic);
      
    END tb_fifo832;
    
    ARCHITECTURE behavior OF tb_fifo832 IS
    
        -- Component Declaration for the Unit Under Test (UUT)
    
        COMPONENT FIFO8x32
        PORT(
             reset : IN  std_logic;
             clk : IN  std_logic;
             r : IN  std_logic;
             w : IN  std_logic;
             empty : OUT  std_logic;
             full : OUT  std_logic;
             d : IN  std_logic_vector(31 downto 0);
             q : OUT  std_logic_vector(31 downto 0)
            );
        END COMPONENT;
       
    
       --Inputs
       signal reset : std_logic := '0';
       signal clk : std_logic := '0';
       signal r : std_logic := '1';
       signal w : std_logic := '1';
       signal d : std_logic_vector(31 downto 0) := (others => '0');
    
      --Outputs
    --   signal empty : std_logic;
    --   signal full : std_logic;
       signal q : std_logic_vector(31 downto 0);
    
       -- Clock period definitions
       constant clk_period : time := 20 ns;
    
    BEGIN
    
     -- Instantiate the Unit Under Test (UUT)
       uut: FIFO8x32 PORT MAP (
              reset => reset,
              clk => clk,
              r => r,
              w => w,
              empty => empty,
              full => full,
              d => d,
              q => q
            );
    
       -- Clock process definitions
       clk_process :process
       begin
      clk <= '1';
      wait for clk_period/2;
      clk <= '0';
      wait for clk_period/2;
       end process;
    
     
       process
      begin
     
        reset <='1' ; wait for 60 ns;
      
      reset <='0' ; wait;
     
      end process;
     
     process
       begin
       w <='1' ; wait for 240 ns;
       w <='0' ; wait for 160 ns;
       end process;
       process
       begin
       r <='0' ; wait for 180 ns;
       r <='1' ; wait for 220 ns;
       
       end process;
       process
         begin
     
           wait for 60 ns;
        	d <= "00000000000000000000000000000001"; WAIT FOR 20 ns;
        	d <= "00000000000000000000000000000010"; WAIT FOR 20 ns;
        	d <= "00000000000000000000000000000011"; WAIT FOR 20 ns;
        	d <= "00000000000000000000000000000100"; WAIT FOR 20 ns;
        	d <= "00000000000000000000000000000101"; WAIT FOR 20 ns;
        	d <= "00000000000000000000000000000110"; WAIT FOR 20 ns;
        	d <= "00000000000000000000000000000111"; WAIT FOR 20 ns;
        	d <= "00000000000000000000000000001000"; WAIT FOR 20 ns;
    	d <= "00000000000000000000000000001001"; WAIT FOR 20 ns;
    	d <= "00000000000000000000000000001010"; WAIT FOR 20 ns;
    	d <= "00000000000000000000000000001011"; WAIT FOR 20 ns;
    	d <= "00000000000000000000000000001100"; WAIT FOR 20 ns;
    	d <= "00000000000000000000000000001101"; WAIT FOR 20 ns;
    	d <= "00000000000000000000000000001110"; WAIT FOR 20 ns;
    	d <= "00000000000000000000000000001111"; WAIT FOR 20 ns;
    	d <= "00000000000000000000000000010000"; WAIT FOR 20 ns;
      
      end process;
     
    END;
    Kết quả mô phỏng

    Click image for larger version

Name:	Simulation.jpg
Views:	1
Size:	66.3 KB
ID:	1410120

  • #2
    Mình thấy nó kì kì vài chỗ:
    read write cùng lúc:
    if empty_buf = '1' then
    empty_buf<='0';
    elsif rcntr = m-1 then
    empty_buf <= '1';
    end if;
    if full_buf = '0' then
    -- not full
    reg(conv_integer(wcntr)) <= d;
    wcntr <= wcntr + 1;
    rcntr <= rcntr + 1;
    else
    Không hiểu tại sao lại có đoạn này:
    elsif rcntr = m-1 then
    empty_buf <= '1';
    sẽ sai nếu rdptr = 7 và wrptr = 3 (khi wrptr quay ngược lại), nếu vậy sau khi r = 1 and w=1 thì sẽ bị empty --> không đúng

    Ngoài ra, nếu trong trường hợp này nếu empty = 1 thì rdptr ko được tăng lên.
    Có vẻ code không đúng lắm :-s...

    Comment


    • #3
      Thôi bạn dùng code có sẵn của Xilinx hoặc altera đi.
      Còn nếu vì lý do gì đó không xài được thì bạn viết lại đi.
      Cũng đơn giản thôi.
      Bạn cần viết trước 1 block cho RAM có 2 công rd và wr, cổng wr thì có thêm cổng wr_enable
      Sau đó bạn viết top_level để điều khiển pointers: rdptr và wrpt
      wrptr <= wrptr + 1 if (wr && không full)
      rdptr <= rdptr + 1 if(rd && không empty)
      empty <= 1 khi (rdptr+1=wrptr && rd && not wr)
      rull <= 1 khi (wrptr+1 = rdptr && wr && not rd)
      bạn kiểm tra lại thử

      Comment


      • #4
        Nguyên văn bởi jefflieu Xem bài viết
        Thôi bạn dùng code có sẵn của Xilinx hoặc altera đi.
        Còn nếu vì lý do gì đó không xài được thì bạn viết lại đi.
        Cũng đơn giản thôi.
        Bạn cần viết trước 1 block cho RAM có 2 công rd và wr, cổng wr thì có thêm cổng wr_enable
        Sau đó bạn viết top_level để điều khiển pointers: rdptr và wrpt
        wrptr <= wrptr + 1 if (wr && không full)
        rdptr <= rdptr + 1 if(rd && không empty)
        empty <= 1 khi (rdptr+1=wrptr && rd && not wr)
        rull <= 1 khi (wrptr+1 = rdptr && wr && not rd)
        bạn kiểm tra lại thử
        Anh cho em hỏi chút là code VHDL sẵn về synchronous FIFO lấy ở đâu ạ. Em search trang chủ của Xilinx và Altera hay google thì ra cái file Pdf về Specification, datasheet của nó. Mới vào mấy lĩnh vực vi điện tử này có gì "ngu ngơ" mong các bác bỏ qua!

        Comment

        Về tác giả

        Collapse

        Gimemecs1315 Tìm hiểu thêm về Gimemecs1315

        Bài viết mới nhất

        Collapse

        Đang tải...
        X