Dual Port RAM Inference

R

rickman

I am using block rams in three places in my design. One of them is
what some call a pseudo dual port with a write port and a read port.
Another has a read/write port and a second read port. Both of these
have been successfully inferred using some code I found here.
However, the third block ram has two read/write ports although they
share a common clock. I have not been able to infer this third block
ram.

I did some searching here and found a number of posts on the subject.
But I still have not found anything that will infer full dual port
block ram.

Anyone else have success?

Rick
 
P

Peter Alfke

I am using block rams in three places in my design.  One of them is
what some call a pseudo dual port with a write port and a read port.
Another has a read/write port and a second read port.  Both of these
have been successfully inferred using some code I found here.
However, the third block ram has two read/write ports although they
share a common clock.  I have not been able to infer this third block
ram.

I did some searching here and found a number of posts on the subject.
But I still have not found anything that will infer full dual port
block ram.

Anyone else have success?

Rick

Rick, Xilinx uses the terms "true dual-port" when both ports are read/
write, and "simple dual-port" when one is read, the other write.
True dual port is obviously a superset of simple dual port, but there
is one limitation:
True dual-port cannot handle the widest data path (the one that simple
dual port can handle). The reason is that true dual port needs four
data buses to connect to the BRAM.
Hope this helps.
Peter Alfke, from home.
 
R

rickman

Rick, Xilinx uses the terms "true dual-port" when both ports are read/
write, and "simple dual-port" when one is read, the other write.
True dual port is obviously a superset of simple dual port, but there
is one limitation:
True dual-port cannot handle the widest data path (the one that simple
dual port can handle). The reason is that true dual port needs four
data buses to connect to the BRAM.
Hope this helps.
Peter Alfke, from home.

Thanks for the reply. I am only using 18 bit wide memory, so that
should still be workable with true dual port ram. I am also only
asking for half the size of a single block ram. I assume the tools
are capable of setting the high order address bit to a constant.

Just in case anyone would like to see the code...

DPT_INFR: process (SysClk)
begin
if (rising_edge(SysClk)) then
DatRdAddr <= DatAddr;
RetRdAddr <= RetAddr;
if (DatPop = '0') then
InstRAM(to_integer(unsigned(DatAddr))) <= std_logic_vector
(DatToS);
end if;
if (RetPop = '0') then
InstRAM(to_integer(unsigned(RetAddr))) <= std_logic_vector
(RetToS);
end if;
end if;
end process DPT_INFR;

DatMem <= InstRAM(to_integer(unsigned(DatRdAddr)));
RetMem <= InstRAM(to_integer(unsigned(RetRdAddr)));
 
R

rickman

No, I'm banging my head against the same issue right now.  
The XST User Guide for version 11 says it can be done,
but I haven't yet installed ISE11.  Can't seem to do it in
Quartus either.  Nor can I get Synplify or Precision
to understand it, though in fairness I haven't done
enough rummaging in the docs yet.

Back to the dreaded component wizards, I guess :-(

I seem to recall that a thread here just a few months ago came to the
same conclusion. But I also found info saying that it could be done,
they just didn't give examples that were for "Write First" read access
which I need.

I also recall that one of the problems was that most of the code
specifies some particular operation when both ports write to the same
address simultaneously while the ram operation is undefined. I think
there is a similar issue when one port writes to an address while the
other port reads the same address. Because of a possible mismatch
between synthesis and simulation, they don't infer a block ram or
infer a block ram with additional logic. In my case I'm getting 9000
FFs!

You would think if there were an inference solution, they would make
it crystal clear in the docs, wouldn't you?

Rick
 
P

Peter Alfke

OK, I take it all back, I was doing something
stupid - no change there then :)

Precision Synthesis correctly generated
write-first dual-port blockRAM in Spartan3
from this code:

  reg [DATA_BITS-1:0] mem [0:(1<<ADRS_BITS)-1];

  always @(posedge clock0) begin
    if (WrEna0) mem[adrs0] = dataWr0;
    dataRd0 <= mem[adrs0];
  end
  always @(posedge clock1) begin
    if (WrEna1) mem[adrs1] = dataWr1;
    dataRd1 <= mem[adrs1];
  end

but NOTE CAREFULLY that I kept the two clocks separate;
with a common clock, I got the anti-contention circuit
(equality check on addresses for simultaneous write).
So I don't know how this would pan out if I were to
put this block down into a bigger design where clock0
and clock1 happened to be the same signal.

XST gave me the right results for write-first (use <=
instead of = in the write assignments) even with a
single clock, but I haven't yet sorted out the read-first
form.

I'll try to do some more work on this with up-to-date
versions of the various tools and report back.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.

Here is a short Xiinx tutorial:
When you write, you also ("or free") perform a read operation on the
same port, at the same address.
Clock timing is internally manipulated such that you either read first
before writing, or write first before reading. You can also select to
not update the read output.
This can get tricky when you use both ports with a common address. The
small timing adjustment might not be big enough to cover up any
possible clock timing differences between the two ports.

All this is irrelevant if you do not care about the "free" read output
during a write access, or you know that you will never access the same
location from both ports "simultaneously".
Peter Alfke
 
R

rickman

OK, I take it all back, I was doing something
stupid - no change there then :)
Precision Synthesis correctly generated
write-first dual-port blockRAM in Spartan3
from this code:
  reg [DATA_BITS-1:0] mem [0:(1<<ADRS_BITS)-1];
  always @(posedge clock0) begin
    if (WrEna0) mem[adrs0] = dataWr0;
    dataRd0 <= mem[adrs0];
  end
  always @(posedge clock1) begin
    if (WrEna1) mem[adrs1] = dataWr1;
    dataRd1 <= mem[adrs1];
  end
but NOTE CAREFULLY that I kept the two clocks separate;
with a common clock, I got the anti-contention circuit
(equality check on addresses for simultaneous write).
So I don't know how this would pan out if I were to
put this block down into a bigger design where clock0
and clock1 happened to be the same signal.
XST gave me the right results for write-first (use <=
instead of = in the write assignments) even with a
single clock, but I haven't yet sorted out the read-first
form.
I'll try to do some more work on this with up-to-date
versions of the various tools and report back.
DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)://www.MYCOMPANY.com
The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.

Here is a short Xiinx tutorial:
When you write, you also ("or free") perform a read operation on the
same port, at the same address.
Clock timing is internally manipulated such that you either read first
before writing, or write first before reading. You can also select to
not update the read output.
This can get tricky when you use both ports with a common address. The
small timing adjustment might not be big enough to cover up any
possible clock timing differences between the two ports.

All this is irrelevant if you do not care about the "free" read output
during a write access, or you know that you will never access the same
location from both ports "simultaneously".
Peter Alfke

I don't think anyone has a problem understanding how the parts work.
The issue we are having is how to specify the hardware we want in the
HDL.

Rick
 
M

Mike Treseler

Jonathan said:
I haven't
yet seen a concise description of the right way to
cope with this across a range of synth tools, so
it's something I'd like to do anyway.

I long ago gave up trying, so I will be interested
to see your results.
If all else fails, I can grudgingly go back to
instantiation of wizard-generated components.
But I don't like doing that; it screws up my
design's portability, makes simulation tiresome
and slow, and makes the HDL code butt-ugly.

I agree with the downside,
but I stick with Peter's "simple dual-port" block rams
which are portable across vendors and tools,
with the same template.

This is all I need for fifos.
I use multiple instances and my own synchronous
controllers to make more complicated memories.

-- Mike Treseler
 
P

peter

I long ago gave up trying, so I will be interested
to see your results.


I agree with the downside,
but I stick with Peter's "simple dual-port" block rams
which are portable across vendors and tools,
with the same template.

This is all I need for fifos.
I use multiple instances and my own synchronous
controllers to make more complicated memories.

  -- Mike Treseler

This is not a Xilinx or Altera circuit design problem, nor is it a
VHDL problem.
It is a systems design issue.
My favorite solution is to clock the two ports on opposite clock
polarity edges.
"If you cannot solve it, avoid it."
Peter Alfke
 
M

Mike Treseler

This is not a Xilinx or Altera circuit design problem, nor is it a
VHDL problem.
It is a systems design issue.

Some existing FPGA structures like PLLs and dpram arbiters
can't be described by a synchronous process.
My synthesis code can either instance the netlist or use something else.
My favorite solution is to clock the two ports on opposite clock
polarity edges.

If I couldn't avoid two write ports, I would time slice one clock.
"If you cannot solve it, avoid it."

True. But I can't avoid talking about it ;)

.... and what is the time limit on 'cannot solve it'?


-- Mike Treseler
 
R

rickman

Rick is right, but Peter's explanation is perhaps
timely. It's comparatively easy to describe both
write-first and read-first behavior in HDL if there
is only one write port, but it's a lot more tricky
(especially in VHDL) if there are two write ports
with independent clocks. But the main problem is
as Peter pointed out: there are some corner cases
(for example, simultaneous write to the same location
from both write ports) whose behavior is ill-defined.
Of course, sensible designers will ensure that
their memory controller never allows those ill-defined
cases to occur. But you can't easily explain to
your synthesis tool that you have done so. As a result,
the synth tool must take your HDL description at face
value, and do whatever it takes to ensure that the
finished hardware obeys that description *in all
cases* - hence the nonsense with logic (which
wouldn't work right anyway) to avoid conflicting
writes to the same address, because your HDL says
that the behavior is well-defined but the memory
doesn't work quite like that.

As promised, I'll take this offline, do some work
on it over the weekend, and report back. I haven't
yet seen a concise description of the right way to
cope with this across a range of synth tools, so
it's something I'd like to do anyway.

If all else fails, I can grudgingly go back to
instantiation of wizard-generated components.
But I don't like doing that; it screws up my
design's portability, makes simulation tiresome
and slow, and makes the HDL code butt-ugly.

I don't like the instantiation approach either. But I don't pretend
to expect that inference is just a matter of finding the right way to
describe a dual port memory. If the chip makers and the tool vendors
can't tell us how to do it, then I can only assume that is because it
doesn't work. I think the way to solve this problem is not by trying
to be creative in writing code, rather a direct conversation with the
vendors is needed.

I tried looking in all sorts of Xilinx docs and the only one that has
example code for write first dual port block ram is the XST manual,
equivalent to the Verilog code shown earlier in the thread. I tried
that and got the following error...

ERROR:Xst - You are apparently trying to describe a RAM with several
write ports for signal <Mram_RAM>. This RAM cannot be implemented
using distributed resources.
-->

So it clearly understands what I am trying to do, but still wants to
use distributed ram!

One thing I find odd is that they are using a variable for the RAM and
perform the write before the read. But then they give two examples
for write first memory, one that has direct logic to mux the input
data and the memory data. The other uses the sequence of the
assignments to infer the write first behavior. Either way gives the
same error.

I guess I would have expected the vendors to know how to use their own
software.

Rick
 
P

Peter Alfke

With respect, Peter, it is definitely neither a circuit
design nor a system design problem.  Speaking for myself
(and for Rick too, I'm pretty sure) I know well enough
what the capabilities and limitations of the BRAMs are,
and how to work with them successfully.  I already
know what form of BRAM I want, and I can easily enough
instantiate it.  I have already chosen a set of
behaviours that I know are available in both Xilinx
and Altera BRAMs.

But I don't want the grotesque non-portable ugliness
of instantiated and/or wizard-generated BRAM components.

So I seek a way of writing VHDL and Verilog code that
correctly describes the memories' simulation behaviour,
at the appropriate level of abstraction, and that will
allow a range of synthesis tools to infer correctly the
BRAM properties that I need.  As has already been said by
others, it is not hard to do this for BRAM configurations
with only one write port.  As soon as you add a second
write port, things get much more vexatious and you
get significantly less help from the coding guidelines
in vendor documentation.  There are good reasons for
this, as have already been discussed; I made a promise
(which I aim to keep) to find out just what can be
done, and to write it up in a convenient vendor-neutral
form.  Systems design it ain't; it's all about finding
a valid HDL coding style that reliably gets a desired
result out of a range of different vendors' tools.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.

Why did I call it a systems problem?
The BRAM behaves like a synchronous two-port RAM should, common clock
or uncorrelated clocks, as long as you do not perform "simultaneous"
write and read operations on the same location.
Two writes with conflicting data will leave the content undefined,
while a write and a read can result in an undefined output. Two reads
are no problem.
Protecting against these system issues is quite complicated, and would
sacrifice performance.
What does the user community expect from us (Xilinx)?

Peter Alfke
 
M

Mike Treseler

Peter said:
Protecting against these system issues is quite complicated, and would
sacrifice performance.
What does the user community expect from us (Xilinx)?

What if we wrote you a vhdl and verilog model
that captures your English description above
and a testbench to demonstrate that modelsim agrees.

Then you would give the models to the right person
and see to it that ise will synthesize
a netlist that passes the same testbench.

-- Mike Treseler
 
F

Frank Buss

Peter said:
Why did I call it a systems problem?
The BRAM behaves like a synchronous two-port RAM should, common clock
or uncorrelated clocks, as long as you do not perform "simultaneous"
write and read operations on the same location.
Two writes with conflicting data will leave the content undefined,
while a write and a read can result in an undefined output. Two reads
are no problem.
Protecting against these system issues is quite complicated, and would
sacrifice performance.
What does the user community expect from us (Xilinx)?

I didn't need such a feature so far, but with Altera Quartus you can
specify for dual port RAMs, if you want to read the old content when
simultaneous writing at the same location, or you can speficy "I don't
care" (which I assume is faster). Maybe this features makes sense for some
projects.

But I don't think that it makes sense to specify the behaviour, if a BRAM
has two write ports and from both ports are written to the same address
simultaneously. And if it makes sense, it should be easy to catch this rare
case in user logic, e.g. a simple priority algorithm with static logic.
Implementing this for the write/read-case in user logic would be more
complicated and maybe slower than what is possible with low-level support.
 
R

rickman

Why did I call it a systems problem?
The BRAM behaves like a synchronous two-port RAM should, common clock
or uncorrelated clocks, as long as you do not perform "simultaneous"
write and read operations on the same location.
Two writes with conflicting data will leave the content undefined,
while a write and a read can result in an undefined output. Two reads
are no problem.
Protecting against these system issues is quite complicated, and would
sacrifice performance.
What does the user community expect from us (Xilinx)?

I'm not sure you are talking about the same problem that we are. We
don't have a problem with how the block ram works. We just want to be
able to use them without using instantiation, for a number of
reasons. Block rams can be inferred as long as they are used in
single port or pseudo dual port modes. But if they are needed with
two write ports, the tools have a lot of trouble inferring a dual port
block ram. The error message I got from XST 10.1 clearly showed that
the tools understood that I wanted a ram with two write ports, but it
could not figure out that I wanted it to use the block ram.

Or am I missing something about your statements that affect this
issue?

Actually, the VHDL description of a block ram that uses two processes
to write to the same memory also has undefined behavior. If both
processes write to the same location using the same clock edge, it is
undefined which process will run first and which will run second; so
the result written to the block ram is undefined... maybe not in the
same way as the hardware, but it is still undefined.

Rick
 
S

Sandro

Rick,
I hope this can help...
below you can find the code to infer dual port-ram with
both port sharing the same clock.
I suppose the secret could be using a shared variable (instead of a
signal) as RAM...

regards
Sandro


entity ramInference is
generic (
g_data_w : natural := 9;
g_addr_w : natural := 11
);
port (
i_clkA : in std_logic;
--i_clkB : in std_logic;
i_enA : std_logic;
i_weA : std_logic;
i_addrA : in std_logic_vector (g_addr_w - 1 downto 0);
i_dataA : in std_logic_vector (g_data_w - 1 downto 0);
o_dataA : out std_logic_vector (g_data_w - 1 downto 0);

i_enB : std_logic;
i_weB : std_logic;
i_addrB : in std_logic_vector (g_addr_w - 1 downto 0);
i_dataB : in std_logic_vector (g_data_w - 1 downto 0);
o_dataB : out std_logic_vector (g_data_w - 1 downto 0)
);
end ramInference;


architecture Behavioral of ramInference is

constant c_ram_sz : natural := 2**(g_addr_w);

type t_ram is array (c_ram_sz - 1 downto 0) of
std_logic_vector (g_data_w - 1 downto 0);

shared variable v_ram : t_ram := (
1 => X"05",
2 => X"08",
3 => X"1A",
-- ...
others => X"00"
);

begin

p_portA : process (i_clkA)
begin
if rising_edge(i_clkA) then
if (i_enA = '1') then
-- READ FIRST
o_dataA(g_data_w - 1 downto 0) <= v_ram(conv_integer
(i_addrA));
-- WRITE AFTER
if (i_weA = '1') then
v_ram(conv_integer(i_addrA)) := i_dataA(g_data_w - 1 downto
0);
end if;
end if;
end if;
end process;

p_portB : process (i_clkA)
begin
if rising_edge(i_clkA) then
if (i_enB = '1') then
-- WRITE FIRST
if (i_weB = '1') then
v_ram(conv_integer(i_addrB)) := i_dataB(g_data_w - 1 downto
0);
end if;
-- READ AFTER
o_dataB(g_data_w - 1 downto 0) <= v_ram(conv_integer
(i_addrB));
end if;
end if;
end process;

end Behavioral;
 
J

Jacko

The BRAM does not have the necessary dual address decoders. The best
option is to clock at half speed and multiplex. Read before write is
most usual.
 
P

Peter Alfke

The BRAM does not have the necessary dual address decoders. The best
option is to clock at half speed and multiplex. Read before write is
most usual.

All Xilinx BRAMs have dual address decoders, and each port also has
the option of read before or after write or retain previous output.
It seems there is no argument about the hardware, but there is about
the software...
Peter Alfke
 
S

Sandro

All Xilinx BRAMs have dual address decoders, and each port also has
the option of read before or after write or retain previous output.
It seems there is no argument about the hardware, but there is about
the software...
Peter Alfke

Peter,
This time... (quite) no argument about the software too (see my
previous post).
XST (your software [xilinx]) infers the bram with two r/w ports both
with "READ FIRST" and with "WRITE FIRST" options...

Maybe the only software (vhdl) argument could be "how to infer dual
port BRAM with
different bus sizes for the two ports"

regards
Sandro
 
B

Brian

Peter,
This time... (quite) no argument about the software too (see my
previous post).
XST (your software [xilinx]) infers the bram with two r/w ports both
with "READ FIRST" and with "WRITE FIRST" options...

Maybe the only software (vhdl) argument could be "how to infer dual
port BRAM with
different bus sizes for the two ports"

regards
Sandro

Thought I would chime in on some of the comments and observations from
this thread. Starting with the most recent comment, if you need
different port widths in either the read vs. write of the same port or
different widths on the dual port, you do need to instantiate.
Neither XST, Synplify or Precision support RAMs with different port
widths. I can comment from the XST side that we have investigated
this and plan to some day offer this however to date, have not been
able to include this capability.

As Sandro explains, you should be able to infer a common clock dual
port RAM (assuming same port widths) in any of the READ_FIRST,
WRITE_FIRST or NO_CHANGE modes. It is fairly straightforward in
verilog to code this however for VHDL as explained, you do need to use
a shared variable to accomplish this. I am more familiar with Verilog
than VHDL but my understanding is that the shared variable is
necessary for proper simulation when accessing the same array at the
same time. In terms of coding examples for these RAMs, most of the
coding examples can be found in the Xilinx Language Templates which
are accessible from Xilinx Project Navigator. Open the Templates and
look in VHDL or Verilog --> Synthesis Constructs --> Coding Examples --
RAM to see several examples. In the Single-Port descriptions you
can see the differences between READ_FIRST, WRITE_FIRST and NO_CHANGE
mode however unfortunately for the dual port not all have been adapted
there but in theory should work. I will see if in 11.2 we can get the
templates updated to include all of the dual port examples for these.
One other note, if you are inferring a BRAM in which you never plan to
read from the same port at the time you are writing, describe
NO_CHANGE mode. It will save power but not many realize this.

In terms of memory collisions (writing to the same memory address on a
dual port RAM as either reading or writing on the other) this
described in the device User Guides and the Synthesis and Simulation
Design Guide so I hope that most understand what it is and what should
be done to avoid them however as for inferring dual-port BRAM, you do
need to heed more caution. A behavioral RTL simulation will not alert
or model a collision so you can very well simulate a collision
behaviorally and get a seemingly valid result but the implementation
can give something different. This is not covered by static timing
analysis as this is a dynamic situation. It can be covered and
alerted by timing simulation however many choose not to do timing
simulations so in lieu of that some synthesis tools have decided to
arbitrate the access to the same memory locations with additional
logic around the BRAM. Both Synplicity and Precision do this however
XST does not. Most people who are aware of this, disable the addition
of the collision avoidance logic using a synthesis attribute as it can
slow the RAM down, add more resources and add more power to the FPGA
design and in many cases is not needed however if you do disable this,
you need to take extra care to ensure an undetected collision will not
give undesired results in your design. I too try to avoid
instantiation of BRAM however one advantage it does give you is it
will alert you to a memory collision as it is modeled in the UNISIM.
As mentioned before a timing simulation (no matter how the RAM was
entered) can also detect this. In system testing, can not detect
this. Reason being, collisions are as unpredictable as a timing error
and while a system may behave one way in one device in one
environmental condition (temperature or voltage) during a collision,
it may behave differently in another device or under a different
environmental condition) so I would not trust in-system testing to
this any more than I would a timing violation.

Hopefully this clears up some of the issues identified in this
thread. I often do infer RAMs in my designs however there are certain
circumstances (such as different port widths) that necessitate
instantiation so we are still not in a full RTL world when it comes to
RAMs. However more situations than most know can be inferred with
relative ease (i.e. dual-port, byte enables, read modes,
initialization from an external file, all can be inferred now).

Regards,

-- Brian Philofsky
-- Xilinx Applications
 
S

Sandro

Peter,
This time... (quite) no argument about the software too (see my
previous post).
XST (your software [xilinx]) infers the bram with two r/w ports both
with "READ FIRST" and with "WRITE FIRST" options...
Maybe the only software (vhdl) argument could be "how to infer dual
port BRAM with
different bus sizes for the two ports"
regards
Sandro

Thought I would chime in on some of the comments and observations from
this thread.  Starting with the most recent comment, if you need
different port widths in either the read vs. write of the same port or
different widths on the dual port, you do need to instantiate.
Neither XST, Synplify or Precision support RAMs with different port
widths.  I can comment from the XST side that we have investigated
this and plan to some day offer this however to date, have not been
able to include this capability.

As Sandro explains, you should be able to infer a common clock dual
port RAM (assuming same port widths) in any of the READ_FIRST,
WRITE_FIRST or NO_CHANGE modes.  It is fairly straightforward in
verilog to code this however for VHDL as explained, you do need to use
a shared variable to accomplish this.  I am more familiar with Verilog
than VHDL but my understanding is that the shared variable is
necessary for proper simulation when accessing the same array at the
same time.  In terms of coding examples for these RAMs, most of the
coding examples can be found in the Xilinx Language Templates which
are accessible from Xilinx Project Navigator.  Open the Templates and
look in VHDL or Verilog --> Synthesis Constructs --> Coding Examples --> RAM to see several examples.  In the Single-Port descriptions you

can see the differences between READ_FIRST, WRITE_FIRST and NO_CHANGE
mode however unfortunately for the dual port not all have been adapted
there but in theory should work.  I will see if in 11.2 we can get the
templates updated to include all of the dual port examples for these.
One other note, if you are inferring a BRAM in which you never plan to
read from the same port at the time you are writing, describe
NO_CHANGE mode.  It will save power but not many realize this.

In terms of memory collisions (writing to the same memory address on a
dual port RAM as either reading or writing on the other) this
described in the device User Guides and the Synthesis and Simulation
Design Guide so I hope that most understand what it is and what should
be done to avoid them however as for inferring dual-port BRAM, you do
need to heed more caution.  A behavioral RTL simulation will not alert
or model a collision so you can very well simulate a collision
behaviorally and get a seemingly valid result but the implementation
can give something different.  This is not covered by static timing
analysis as this is a dynamic situation.  It can be covered and
alerted by timing simulation however many choose not to do timing
simulations so in lieu of that some synthesis tools have decided to
arbitrate the access to the same memory locations with additional
logic around the BRAM.  Both Synplicity and Precision do this however
XST does not.  Most people who are aware of this, disable the addition
of the collision avoidance logic using a synthesis attribute as it can
slow the RAM down, add more resources and add more power to the FPGA
design and in many cases is not needed however if you do disable this,
you need to take extra care to ensure an undetected collision will not
give undesired results in your design.  I too try to avoid
instantiation of BRAM however one advantage it does give you is it
will alert you to a memory collision as it is modeled in the UNISIM.
As mentioned before a timing simulation (no matter how the RAM was
entered) can also detect this. In system testing, can not detect
this.  Reason being, collisions are as unpredictable as a timing error
and while a system may behave one way in one device in one
environmental condition (temperature or voltage) during a collision,
it may behave differently in another device or under a different
environmental condition) so I would not trust in-system testing to
this any more than I would a timing violation.

Hopefully this clears up some of the issues identified in this
thread.  I often do infer RAMs in my designs however there are certain
circumstances (such as different port widths) that necessitate
instantiation so we are still not in a full RTL world when it comes to
RAMs.  However more situations than most know can be inferred with
relative ease (i.e. dual-port, byte enables, read modes,
initialization from an external file, all can be inferred now).

Regards,

--  Brian Philofsky
--  Xilinx Applications

Brian,
thanks for your answer ... you avoided me to waste time
trying to figure out how the ram can be represented (in vhdl) as two
array with "different geometry" (read dual port with different
bus sizes).


Peter said:
...
What does the user community expect from us (Xilinx)?
...
(...winking to Peter) that is what the user
community expect from you (Xilinx) ;-)

regards
Sandro
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,814
Latest member
SpicetreeDigital

Latest Threads

Top