- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Have you got registered output? You can remove this register to reduce latency at the cost of max clock speed
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 )
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tried too but i don't know why there's a cycle where i get a zero as output
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm sorry for my delayed reply.
Here's my codelibrary 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
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page