Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > uninferred due to asynchronous read logic

Reply
Thread Tools

uninferred due to asynchronous read logic

 
 
Shannon
Guest
Posts: n/a
 
      05-12-2008
I'm really having a bad day and I hope you guys can help me out AGAIN.

I used altera's own template to instantiate a dual-port RAM. Pretty
straight forward really. I've used the single port ram before with no
problems. THIS time however when I compile it gives me some info:

Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
read logic

Hmm...ok so I go check the template. Yeah the read stuff is inside a
clocked process. Hmm maybe what I'm driving the RAM_we signal with is
asynchronous to the RAM clock. Nope. Looked at that and it is inside
a clocked process that is clocked by the same clock as the RAM. Then
I looked at the RTL viewer and sure enough the RAM_we signal is driven
by a D-flip flop that is clocked by the right clock. So what am I
missing?

Shannon

(I'm working on a sanitized version of the code that I can post here
but I figured maybe I was missing somethnig obvious and should post
first.)
 
Reply With Quote
 
 
 
 
Shannon
Guest
Posts: n/a
 
      05-12-2008
On May 12, 3:11*pm, Shannon <(E-Mail Removed)> wrote:
> I'm really having a bad day and I hope you guys can help me out AGAIN.
>
> I used altera's own template to instantiate a dual-port RAM. *Pretty
> straight forward really. *I've used the single port ram before with no
> problems. *THIS time however when I compile it gives me some info:
>
> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
> read logic
>
> Hmm...ok so I go check the template. *Yeah the read stuff is inside a
> clocked process. *Hmm maybe what I'm driving the RAM_we signal with is
> asynchronous to the RAM clock. *Nope. *Looked at that and it is inside
> a clocked process that is clocked by the same clock as the RAM. *Then
> I looked at the RTL viewer and sure enough the RAM_we signal is driven
> by a D-flip flop that is clocked by the right clock. *So what am I
> missing?
>
> Shannon
>
> (I'm working on a sanitized version of the code that I can post here
> but I figured maybe I was missing somethnig obvious and should post
> first.)


Ok, I thought I was on to something. The OTHER read signal was stuck
asserted all the time. This is actually what I want but nevermind
that. So what I did was made it synchronous just to see if the
problem went away. Nope. But when I look closer at the RTL viewer it
shows a "sync RAM" block that is being clocked by a single clock and
whose write enable / read enable signals are fed from d-FFs that are
clocked by the same clock. So, to me, it looks like the right thing.
However, it's clearly using FF's to do it and NOT the on board RAM.

Any ideas?
 
Reply With Quote
 
 
 
 
Mike Treseler
Guest
Posts: n/a
 
      05-13-2008
Shannon wrote:

>> I used altera's own template to instantiate a dual-port RAM. Pretty
>> straight forward really. I've used the single port ram before with no
>> problems. THIS time however when I compile it gives me some info:
>>
>> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
>> read log

> Any ideas?


Dual port rams by X and A have an inference problem with
simultaneous writes to the same address. It always requires
some extra logic to arbitrate and synch things up. The easiest fix is
something like this:

ram_access : process (clk) is
begin
if rising_edge(clk) then
if we = '1' then
mem(to_integer(wr_adr)) <= (data_i);
end if;
data_q <= mem(to_integer(read_adr));
end if;
end process ram_access;

-- Mike Treseler

 
Reply With Quote
 
Shannon
Guest
Posts: n/a
 
      05-13-2008
On May 12, 8:11*pm, Mike Treseler <(E-Mail Removed)> wrote:
> Shannon wrote:
> >> I used altera's own template to instantiate a dual-port RAM. *Pretty
> >> straight forward really. *I've used the single port ram before with no
> >> problems. *THIS time however when I compile it gives me some info:

>
> >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
> >> read log

> > Any ideas?

>
> Dual port rams by X and A have an inference problem with
> simultaneous writes to the same address. It always requires
> some extra logic to arbitrate and synch things up. The easiest fix is
> something like this:
>
> * * ram_access : process (clk) is
> * * begin
> * * * *if rising_edge(clk) then
> * * * * * if we = '1' then
> * * * * * * *mem(to_integer(wr_adr)) <= (data_i);
> * * * * * end if;
> * * * * * data_q <= mem(to_integer(read_adr));
> * * * *end if;
> * * end process ram_access;
>
> * -- Mike Treseler


The template that 'A' provides is quite close to what you are
suggesting:

-- 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;

They add the 'q_a <= data_a;' bit but otherwise it seems to be the
same as what you suggest. Other than you have separate write and read
address signals. Is that the part you are suggesting I add to their
template?

Actually as I'm typing this I'm reading their comments and becoming
even more confused about what they intended. If there is only one
"we_a" signal to control both reads AND writes, how is it POSSIBLE to
ever have a "Read-during-write" event?
 
Reply With Quote
 
KJ
Guest
Posts: n/a
 
      05-13-2008
On May 13, 10:52*am, Shannon <(E-Mail Removed)> wrote:
> On May 12, 8:11*pm, Mike Treseler <(E-Mail Removed)> wrote:
> > >> I used altera's own template to instantiate a dual-port RAM. *Pretty
> > >> straight forward really. *I've used the single port ram before with no
> > >> problems. *THIS time however when I compile it gives me some info:

>
> > >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
> > >> read log
> > > Any ideas?

>


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.

>
> The template that 'A' provides is quite close to what you are
> suggesting:
>
> -- 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;
>

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


>
> Actually as I'm typing this I'm reading their comments and becoming
> even more confused about what they intended. *If there is only one
> "we_a" signal to control both reads AND writes, how is it POSSIBLE to
> ever have a "Read-during-write" event?


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
 
Reply With Quote
 
KJ
Guest
Posts: n/a
 
      05-13-2008
Slight correction to previous post. What I said was...

You're always able to read whether you're reading or not.



What I meant to say was...

You're always able to read whether you're writing or not.

KJ
 
Reply With Quote
 
Shannon
Guest
Posts: n/a
 
      05-13-2008
On May 13, 9:22*am, KJ <(E-Mail Removed)> wrote:
> On May 13, 10:52*am, Shannon <(E-Mail Removed)> wrote:
>
> > On May 12, 8:11*pm, Mike Treseler <(E-Mail Removed)> wrote:
> > > >> I used altera's own template to instantiate a dual-port RAM. *Pretty
> > > >> straight forward really. *I've used the single port ram before with no
> > > >> problems. *THIS time however when I compile it gives me some info:

>
> > > >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
> > > >> read log
> > > > Any ideas?

>
> 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.
>
>
>
>
>
>
>
> > The template that 'A' provides is quite close to what you are
> > suggesting:

>
> > -- 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;

>
> 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
>
>
>
> > Actually as I'm typing this I'm reading their comments and becoming
> > even more confused about what they intended. *If there is only one
> > "we_a" signal to control both reads AND writes, how is it POSSIBLE to
> > ever have a "Read-during-write" event?

>
> 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
 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      05-13-2008
Shannon wrote:

> If there is only one
> "we_a" signal to control both reads AND writes, how is it POSSIBLE to
> ever have a "Read-during-write" event?


By having two data buses.
 
Reply With Quote
 
Shannon
Guest
Posts: n/a
 
      05-13-2008
On May 13, 9:34*am, Shannon <(E-Mail Removed)> wrote:
> On May 13, 9:22*am, KJ <(E-Mail Removed)> wrote:
>
>
>
>
>
> > On May 13, 10:52*am, Shannon <(E-Mail Removed)> wrote:

>
> > > On May 12, 8:11*pm, Mike Treseler <(E-Mail Removed)> wrote:
> > > > >> I used altera's own template to instantiate a dual-port RAM. *Pretty
> > > > >> straight forward really. *I've used the single port ram before with no
> > > > >> problems. *THIS time however when I compile it gives me some info:

>
> > > > >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
> > > > >> read log
> > > > > Any ideas?

>
> > 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.

>
> > > The template that 'A' provides is quite close to what you are
> > > suggesting:

>
> > > -- 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;

>
> > 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

>
> > > Actually as I'm typing this I'm reading their comments and becoming
> > > even more confused about what they intended. *If there is only one
> > > "we_a" signal to control both reads AND writes, how is it POSSIBLE to
> > > ever have a "Read-during-write" event?

>
> > 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- Hide quoted text -
>
> - Show quoted text -


First question. Is this "INFO" refering to something about the
template that I'm using or is it refering to my use of the DPRAM? In
other words, is Quartus complaining that something about the structure
of the RAM template is telling it to infer logic over RAM? OR.... Is
Quartus complaining that somewhere in MY code I'm performing an
asynchronous read of the RAM so it will have to synthesize the RAM
with logic to be able to deal with MY asynchronous behavior?

Shannon
 
Reply With Quote
 
Dave
Guest
Posts: n/a
 
      05-13-2008
On May 13, 12:34 pm, Shannon <(E-Mail Removed)> wrote:
> On May 13, 9:22 am, KJ <(E-Mail Removed)> wrote:
>
>
>
> > On May 13, 10:52 am, Shannon <(E-Mail Removed)> wrote:

>
> > > On May 12, 8:11 pm, Mike Treseler <(E-Mail Removed)> wrote:
> > > > >> I used altera's own template to instantiate a dual-port RAM. Pretty
> > > > >> straight forward really. I've used the single port ram before with no
> > > > >> problems. THIS time however when I compile it gives me some info:

>
> > > > >> Info: RAM logic "DPRAM:WIN_RAM|ram" uninferred due to asynchronous
> > > > >> read log
> > > > > Any ideas?

>
> > 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.

>
> > > The template that 'A' provides is quite close to what you are
> > > suggesting:

>
> > > -- 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;

>
> > 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

>
> > > Actually as I'm typing this I'm reading their comments and becoming
> > > even more confused about what they intended. If there is only one
> > > "we_a" signal to control both reads AND writes, how is it POSSIBLE to
> > > ever have a "Read-during-write" event?

>
> > 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


It might matter what particular chip you're targetting. I remember
some of the older Altera chips didn't have true dual-port RAM, but
instead had separate read and write ports. Could it be that the chip
you're targetting doesn't have a true dual-port RAM? What are you
targetting?

Dave
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Python Logic Map/Logic Flow Chart. (Example Provided) spike Python 8 02-09-2010 12:31 PM
Asynchronous Logic Gates and Analog Logic Gates Jyoti Ballabh Software 3 11-26-2009 06:48 PM
How to due with "warning LNK4075: ignoring '/INCREMENTAL' due to Fresh C++ 2 04-22-2008 09:03 PM
Can't Print Due to "RPC Server Unavailable" =?Utf-8?B?d2VsbHNpZQ==?= Wireless Networking 0 11-03-2005 07:21 PM
problem with the logic of read files Python 3 04-12-2005 10:12 PM



Advertisments