On May 10, 6:00=A0am, Brian <scubabr...@gmail.com> wrote:> On May 9, 4:31=A0pm, Sandro <sdro...@netscape.net> wrote: > > > > > 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. =A0Starting 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. =A0I 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. =A0It is fairly straightforward in > verilog to code this however for VHDL as explained, you do need to use > a shared variable to accomplish this. =A0I 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. =A0In 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. =A0Open the Templates and > look in VHDL or Verilog --> Synthesis Constructs --> Coding Examples --> =RAM to see several examples. =A0In 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. =A0I 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. =A0It 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. =A0A 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. =A0This is not covered by static timing > analysis as this is a dynamic situation. =A0It 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. =A0Both Synplicity and Precision do this however > XST does not. =A0Most 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. =A0I 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. =A0Reason 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. =A0I 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. =A0However 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, > > -- =A0Brian Philofsky > -- =A0Xilinx ApplicationsBrian, 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 Alfke wrote:> ... > What does the user community expect from us (Xilinx)? > ...(...winking to Peter) that is what the user community expect from you (Xilinx) ;-) regards Sandro
Re: Dual Port RAM Inference
Started by ●May 9, 2009
Reply by ●May 10, 20092009-05-10
Reply by ●May 11, 20092009-05-11
My code is virtually this same thing. The tool tells me I am trying to infer two ports using distributed memory which it can't do. Rick On May 9, 5:26=A0pm, Sandro <sdro...@netscape.net> wrote:> 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 > =A0 generic ( > =A0 =A0 g_data_w : natural :=3D 9; > =A0 =A0 g_addr_w : natural :=3D 11 > =A0 =A0 ); > =A0 port ( > =A0 =A0 i_clkA =A0: in =A0std_logic; > =A0 =A0 --i_clkB =A0: in =A0std_logic; > =A0 =A0 i_enA =A0 : =A0 =A0 std_logic; > =A0 =A0 i_weA =A0 : =A0 =A0 std_logic; > =A0 =A0 i_addrA : in =A0std_logic_vector (g_addr_w - 1 downto 0); > =A0 =A0 i_dataA : in =A0std_logic_vector (g_data_w - 1 downto 0); > =A0 =A0 o_dataA : out std_logic_vector (g_data_w - 1 downto 0); > > =A0 =A0 i_enB =A0 : =A0 =A0 std_logic; > =A0 =A0 i_weB =A0 : =A0 =A0 std_logic; > =A0 =A0 i_addrB : in =A0std_logic_vector (g_addr_w - 1 downto 0); > =A0 =A0 i_dataB : in =A0std_logic_vector (g_data_w - 1 downto 0); > =A0 =A0 o_dataB : out std_logic_vector (g_data_w - 1 downto 0) > =A0 =A0 ); > end ramInference; > > architecture Behavioral of ramInference is > > =A0 constant c_ram_sz : natural :=3D 2**(g_addr_w); > > =A0 type t_ram is array (c_ram_sz - 1 downto 0) of > =A0 =A0 std_logic_vector (g_data_w - 1 downto 0); > > =A0 shared variable v_ram : t_ram :=3D ( > =A0 =A0 1 =A0 =A0 =A0=3D> X"05", > =A0 =A0 2 =A0 =A0 =A0=3D> X"08", > =A0 =A0 3 =A0 =A0 =A0=3D> X"1A", > =A0 =A0 -- ... > =A0 =A0 others =3D> X"00" > =A0 =A0 ); > > begin > > =A0 p_portA : process (i_clkA) > =A0 begin > =A0 =A0 if rising_edge(i_clkA) then > =A0 =A0 =A0 if (i_enA =3D '1') then > =A0 =A0 =A0 =A0 -- READ FIRST > =A0 =A0 =A0 =A0 o_dataA(g_data_w - 1 downto 0) <=3D v_ram(conv_integer > (i_addrA)); > =A0 =A0 =A0 =A0 -- WRITE AFTER > =A0 =A0 =A0 =A0 if (i_weA =3D '1') then > =A0 =A0 =A0 =A0 =A0 v_ram(conv_integer(i_addrA)) :=3D i_dataA(g_data_w - =1 downto> 0); > =A0 =A0 =A0 =A0 end if; > =A0 =A0 =A0 end if; > =A0 =A0 end if; > =A0 end process; > > =A0 p_portB : process (i_clkA) > =A0 begin > =A0 =A0 if rising_edge(i_clkA) then > =A0 =A0 =A0 if (i_enB =3D '1') then > =A0 =A0 =A0 =A0 -- WRITE FIRST > =A0 =A0 =A0 =A0 if (i_weB =3D '1') then > =A0 =A0 =A0 =A0 =A0 v_ram(conv_integer(i_addrB)) :=3D i_dataB(g_data_w - =1 downto> 0); > =A0 =A0 =A0 =A0 end if; > =A0 =A0 =A0 =A0 -- READ AFTER > =A0 =A0 =A0 =A0 o_dataB(g_data_w - 1 downto 0) <=3D v_ram(conv_integer > (i_addrB)); > =A0 =A0 =A0 end if; > =A0 =A0 end if; > =A0 end process; > > end Behavioral;
Reply by ●May 11, 20092009-05-11
On May 11, 7:46=A0pm, rickman <gnu...@gmail.com> wrote:> My code is virtually this same thing. =A0The tool tells me I am trying > to infer two ports using distributed memory which it can't do.Rick, I don't know! It works fine to me (webpack ISE 10.1.03 - linux). Did you try to use shared variable ? In your previous example I saw only "<=3D" instead of ":=3D" to "assign" a shared variable... Sandro





