Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Altera_Forum
Honored Contributor I
1,494 Views

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?
0 Kudos
6 Replies
Altera_Forum
Honored Contributor I
30 Views

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

Altera_Forum
Honored Contributor I
30 Views

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 : 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 )
Altera_Forum
Honored Contributor I
30 Views

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.
Altera_Forum
Honored Contributor I
30 Views

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

Altera_Forum
Honored Contributor I
30 Views

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.

Altera_Forum
Honored Contributor I
30 Views

I'm sorry for my delayed reply.  

Here's my 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 : 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 ) : 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 :http://www.alteraforum.com/forum/attachment.php?attachmentid=13045&stc=1
Reply