Results 1 to 7 of 7

Thread: Question about True Dual Port RAM

  1. #1
    Join Date
    Oct 2016
    Posts
    29
    Rep Power
    1

    Default Question about True Dual Port RAM

    Hello,

    I'am using True dual port ram one port for write and the other one for read.

    When i change the content of an address i get the output on the read port delayed by two cycles.

    Is there a possibility to get the new value just one cycle after instead of two?

  2. #2
    Tricky is offline Moderator **Forum Master**
    Join Date
    Oct 2008
    Posts
    5,649
    Rep Power
    1

    Default Re: Question about True Dual Port RAM

    Have you got registered output? You can remove this register to reduce latency at the cost of max clock speed

  3. #3
    Join Date
    Oct 2016
    Posts
    29
    Rep Power
    1

    Default Re: Question about True Dual Port RAM

    can you please explain to me what does it mean to register an output or an input ? i searched the net but i can't find an example. I though that all the outputs when we do the assignment are called registered but i don't think this what it means isn't it ?
    And before i could understand what did you mean i changed in the code below to get what i want :
    Code:
    library ieee;
    use ieee.std_logic_1164.all;
    
    entity merger is
    
    	generic 
    	(
    		DATA_WIDTH : natural;
    		ADDR_WIDTH : natural 
    	);
    
    	port 
    	(
    		clk		: in std_logic;
    		addr_a	: in natural range 0 to 2**ADDR_WIDTH - 1;
    		addr_b	: in natural range 0 to 2**ADDR_WIDTH - 1;
    		data_a	: in std_logic_vector((DATA_WIDTH-1) downto 0);
    		data_b	: in std_logic_vector((DATA_WIDTH-1) downto 0);
    		we_a	: in std_logic :='1';
    		we_b	: in std_logic:='1';
    		q_a	: out std_logic_vector((DATA_WIDTH -1) downto 0);
    		q_b		: out std_logic_vector((DATA_WIDTH -1) downto 0)
    	);
    
    end merger;
    
    architecture rtl of merger is
    
    	-- Build a 2-D array type for the RAM
    	subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
    	type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;
    
    	-- Declare the RAM 
    	shared variable ram : memory_t;
    
    begin
    
    
    	-- Port A
    	process(clk)
    	begin
    	if(rising_edge(clk)) then 
    		if(we_a = '1') then
    			ram(addr_a) := data_a;
    			q_a <= data_a;
    		else
    			q_a<=data_b;
    		end if;
    			
    
    	end if;
    	
    	end process;
    
    	-- Port B 
    	process(clk)
    	begin
    	if(rising_edge(clk)) then 
    		if(we_b = '1') then
    			ram(addr_b) := data_b;
    		end if;
      	   q_b <= ram(addr_b);
    	end if;
    	end process;
     
    end rtl;
    Is it okay i wrote it like this ? i disable the we_a whenever i want to update the content of the address and read directly the new data ( data_b) (using flags from other modules )

  4. #4
    Tricky is offline Moderator **Forum Master**
    Join Date
    Oct 2008
    Posts
    5,649
    Rep Power
    1

    Default Re: Question about True Dual Port RAM

    To register input or output, you add registers to the pipeline in those input. That means putting the signals in a clocked process.

    Your code (lifted I see from the quartus handbook) registers the input and output. As long as you register the read address then the Q output doesnt have to be registered.

  5. #5
    Join Date
    Oct 2016
    Posts
    29
    Rep Power
    1

    Default Re: Question about True Dual Port RAM

    I tried too but i don't know why there's a cycle where i get a zero as output

  6. #6
    Tricky is offline Moderator **Forum Master**
    Join Date
    Oct 2008
    Posts
    5,649
    Rep Power
    1

    Default Re: Question about True Dual Port RAM

    If you post your code and your testbench, and give more details about the problem, maybe we can help. But we can only guess at the moment.

  7. #7
    Join Date
    Oct 2016
    Posts
    29
    Rep Power
    1

    Default Re: Question about True Dual Port RAM

    I'm sorry for my delayed reply.
    Here's my code
    Code:
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use ieee.std_logic_signed.all;
    use ieee.math_real.all;
    library std;
     
    
    entity association  is
    
        generic 
        (     DEPTH : natural:=2;
            LABEL_WIDTH : natural := 8;
            ADDR_WIDTH : natural := 6
        );
    
        port 
        (
            clk ,reset    , in_fv , in_dv    : in std_logic;
            in_data : in std_logic_vector((LABEL_WIDTH -1) downto 0);
            addr    : in natural range 0 to 2**ADDR_WIDTH - 1;
            q        : out std_logic_vector((LABEL_WIDTH -1) downto 0)
            
        );
    
    end association ;
    
    architecture rtl of association  is
    
     component row_buffer is 
        generic (
        PIPLINE_LENGHT    :    integer;
        WORD_SIZE    :    integer
        );
        
        port (
        clk_proc         :    in    std_logic;
        reset_n         :    in    std_logic;
        enable_i        :    in    std_logic;
        in_data            :    in    std_logic_vector (WORD_SIZE-1 downto 0);
        out_data        :    out    std_logic_vector (WORD_SIZE-1 downto 0)
        );
     end component;
     component merger is 
     
     generic 
        (
            DATA_WIDTH : natural := 8;
            ADDR_WIDTH : natural := 6
        );
    
        port 
        (
            clk        : in std_logic;
            addr_a    : in natural range 0 to 2**ADDR_WIDTH - 1;
            data_a    : in std_logic_vector((DATA_WIDTH-1) downto 0);
            we_a    : in std_logic := '1';
            q_a        : out std_logic_vector((DATA_WIDTH -1) downto 0)
            
        );
        
     end component;
     signal out1 , out2 : std_logic_vector((LABEL_WIDTH -1) downto 0);
     
    begin
     
     row_buffer_inst: row_buffer
     generic map (DEPTH,LABEL_WIDTH)
     port map (clk,reset,in_fv and in_dv, in_data,out1);
     merger_inst: merger 
     generic map (LABEL_WIDTH,ADDR_WIDTH)
     port map (clk,addr,out1,in_fv and in_dv,out2);
     
     q<=out2;
        
    end rtl;
    the row buffer is a simple shift register :
    Code:
    library ieee;
    use ieee.std_logic_1164.all;
    
    entity row_buffer  is
        generic (
        PIPLINE_LENGHT    :    integer;
        WORD_SIZE    :    integer
        );
        
        port (
        clk_proc         :    in    std_logic;
        reset_n         :    in    std_logic;
        enable_i        :    in    std_logic;
        in_data            :    in    std_logic_vector (WORD_SIZE-1 downto 0);
        out_data        :    out    std_logic_vector (WORD_SIZE-1 downto 0)
        );
    end row_buffer;
        
        
    architecture arch of row_buffer is
        
        type cell_t is array (0 to (PIPLINE_LENGHT-1)) of std_logic_vector ( (WORD_SIZE-1) downto 0);
        signal cell    :    cell_t;
        
        begin
        process(clk_proc,reset_n)
        variable i        :    integer := 0;
            begin
            
            if ( reset_n = '1' )    then 
                cell <= (others =>(others => '0'));
                
            elsif    (rising_edge(clk_proc))    then
                if    (enable_i='1') then
                    cell(0)     <=     in_data;
                    for i in 1 to  (PIPLINE_LENGHT-1) loop
                        cell(i)    <=    cell(i-1);
                    end loop;
                    
                    out_data<=    cell(PIPLINE_LENGHT - 1);
                    
                end if;
            end if;    
        end process;
    end arch;
    and here's the merger (true dual port ram ) :
    Code:
    library ieee;
    use ieee.std_logic_1164.all;
    
    
    entity merger is
    
    
        generic 
        (
            DATA_WIDTH : natural := 8;
            ADDR_WIDTH : natural := 6
        );
    
    
        port 
        (
            clk        : in std_logic;
            addr_a    : in natural range 0 to 2**ADDR_WIDTH - 1;
            addr_b    : in natural range 0 to 2**ADDR_WIDTH - 1;
            data_a    : in std_logic_vector((DATA_WIDTH-1) downto 0);
            data_b    : in std_logic_vector((DATA_WIDTH-1) downto 0);
            we_a    : in std_logic := '1';
            we_b    : in std_logic := '1';
            q_a        : out std_logic_vector((DATA_WIDTH -1) downto 0);
            q_b        : out std_logic_vector((DATA_WIDTH -1) downto 0)
        );
    
    
    end merger;
    
    
    architecture rtl of merger is
    
    
        -- Build a 2-D array type for the RAM
        subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
        type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;
    
    
        -- Declare the RAM 
        shared variable ram : memory_t;
    
    
    begin
    
    
    
    
        -- Port A
        process(clk)
        begin
        if(rising_edge(clk)) then 
            
            if(we_a = '1') then
                ram(addr_a) := data_a;
            end if;
            
        end if;
        end process;
    
    
        -- Port B 
        process(clk)
        begin
        if(rising_edge(clk)) then 
            if(we_b = '1') then
                ram(addr_b) := data_b;
            end if;
             
        end if;
        end process;
    q_a <= ram(addr_a);
     q_b <= ram(addr_b);
    end rtl;
    This is my testbench :
    Attached Images Attached Images
    Last edited by snouppie; December 23rd, 2016 at 12:42 PM.

Similar Threads

  1. True Dual Port RAM
    By Gio_Faz in forum IP Discussion
    Replies: 6
    Last Post: May 31st, 2013, 02:50 AM
  2. infer true dual port asynchronous ram
    By erik_dl in forum General Altera Discussion
    Replies: 9
    Last Post: June 15th, 2010, 01:08 PM
  3. Stratix II and M4K true dual port memory
    By joel in forum FPGA, Hardcopy, and CPLD Discussion
    Replies: 5
    Last Post: August 26th, 2009, 04:18 AM
  4. true dual port RAM
    By sgievounet in forum Quartus II and EDA Tools Discussion
    Replies: 7
    Last Post: March 31st, 2009, 04:02 AM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •