You're not following the template is my idea. Although I've also had
problems with memory when it added unnecessary pass-thru logic because
it had mucked with the read address logic in some unusual fashion.
The work around there was to add the syn_preserve and syn_keep
attributes to the read address signal. After that it didn't add any
pass thru logic and implemented what it should have. That's not quite
the same thing as what you're having trouble with but thought I'd
share the info.
You might want to check where you got your template from. The
following is copy/pasted from the Quartus 2 manual from the heading
'Implementing Inferred RAM (VHDL). As you can see it matches Mike's
template, (and my template too for what it's worth).
-- Start of text from Quartus 2 manual
The example below shows ram_infer.vhd, a VHDL Design File that
implements a 32 x 32-bit single-clock RAM with separate read and write
addresses:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY ram_infer IS
PORT
(
clock: IN std_logic;
data: IN std_logic_vector (31 DOWNTO 0);
write_address: IN integer RANGE 0 to 31;
read_address: IN integer RANGE 0 to 31;
we: IN std_logic;
q: OUT std_logic_vector (31 DOWNTO 0)
);
END ram_infer;
ARCHITECTURE rtl OF ram_infer IS
TYPE mem IS ARRAY(0 TO 31) OF std_logic_vector(31 DOWNTO 0);
SIGNAL ram_block : mem;
BEGIN
PROCESS (clock)
BEGIN
IF (clock'event AND clock = '1') THEN
IF (we = '1') THEN
ram_block(write_address) <= data;
END IF;
q <= ram_block(read_address);
END IF;
END PROCESS;
END rtl;
-- End of text from Quartus 2 manual
Reads are always occurring, you don't really have an explicit 'read'
command to the memory. You're always able to read whether you're
reading or not. The issue has to do with if you're reading from the
same address that you're actively writing to (i.e. write_address =
read_address and we='1'). In that situation the data from the newly
written memory location won't show up until the clock cycle after the
write completes.
Kevin Jennings- Hide quoted text -
- Show quoted text -
I think I'm quickly getting in over my head. Thanks for the response
Kevin. I'm going to have to ponder what you're trying to tell me.
I got my template from within Quartus II itself. It has a handy pull-
down for "insert template". I'll paste it here:
-- Quartus II VHDL Template
-- True Dual-Port RAM with single clock
library ieee;
use ieee.std_logic_1164.all;
entity true_dual_port_ram_single_clock 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 true_dual_port_ram_single_clock;
architecture rtl of true_dual_port_ram_single_clock 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(addr_a'high downto 0) of word_t;
-- Declare the RAM signal.
signal ram : memory_t;
begin
-- Port A
process(clk)
begin
if(rising_edge(clk)) then
if(we_a = '1') then
ram(addr_a) <= data_a;
-- Read-during-write on the same port returns NEW data
q_a <= data_a;
else
-- Read-during-write on the mixed port returns OLD data
q_a <= ram(addr_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;
-- Read-during-write on the same port returns NEW data
q_b <= data_b;
else
-- Read-during-write on the mixed port returns OLD data
q_b <= ram(addr_b);
end if;
end if;
end process;
end rtl;
I do notice both you and Mike seem to be talking about something other
than a dual-port RAM (in my simple mind). Both of your examples SEEM
to me to be single-port rams with separate read and write address
ports. Maybe I am just not understanding what I'm saying when I say
dual-port RAM. I hope the cut and paste above from Quartus gives a
hint of what I was trying to accomplish. Basically I have one module
(a microP interface) that is reading OR writing whenever it wants.
Then I have another module that is reading from the same RAM pretty
much all the time. Ok, not ALL the time but it goes through bursts
where it is incrementing the address and reading every clock cycle.
I'll slowly read through your post and see if I can come up with
relevent questions. I'm sensing I have two problems. One, I don't
understand what a dual-port RAM is. And two I'm not understanding
what the info "RAM logic "DPRAM:WIN_RAM|ram" uninferred due to
asynchronous read logic" means.
Shannon