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