UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor dak_zach
Visitor
10,705 Views
Registered: ‎06-21-2013

Simple Dual Port Blockram

Need a little help.  I'm using ISE 14.7 and a Virtex6 and I'm trying to make a simple dual port (SDP) blockram module (1 write-only port, 1 read-only port) both running on different clocks.  Space is an issue in my design, so I designed the widths and depths to fit into one RAMB18E1.  Synthesis report is correctly inferring the right values:

 

 

INFO:Xst:3226 - The RAM <ram_gen1[0].fir/Mram_styp_AxWary_ram> will be implemented as a BLOCK RAM, absorbing the following register(s): <ram_gen1[0].fir/s2x18_rd_data[0]_s2x18_rd_data[1]> <ram_gen1[0].fir/o2x18_rd_data[0]_o2x18_rd_data[1]>
    -----------------------------------------------------------------------
    | ram_type           | Block                               |          |
    -----------------------------------------------------------------------
    | Port A                                                              |
    |     aspect ratio   | 1024-word x 18-bit                  |          |
    |     mode           | write-first                         |          |
    |     clkA           | connected to signal <i_pcie_clk>    | rise     |
    |     weA            | connected to signal <ram_gen1[0].fir/i_wr_en_0> | high     |
    |     addrA          | connected to signal <(sbus_pcienet_dma_dpram_e10_byte_addr> |          |
    |     diA            | connected to signal <(sbus_pcienet_dma_dpram_e18_data> |          |
    -----------------------------------------------------------------------
    | optimization       | speed                               |          |
    -----------------------------------------------------------------------
    | Port B                                                              |
    |     aspect ratio   | 512-word x 36-bit                   |          |
    |     mode           | write-first                         |          |
    |     clkB           | connected to signal <i_safe_clk>    | rise     |
    |     enB            | connected to signal <s_safenet_port_en> | high     |
    |     addrB          | connected to signal <s9_safenet_addr_dly> |          |
    |     doB            | connected to signal <s36_safenet_data> |          |
    -----------------------------------------------------------------------
    | optimization       | speed                               |          |
    -----------------------------------------------------------------------

 (notice no doA or diB, so it should be SDP)

 

 

This should fit into a RAMB18E1 if it were implemented as a SDP, but when I look at the finished design, it has implemented a true dual port (TDP) RAMB36E1 block.  I think the problem is that since it though TDP, it had to put it into a RAMB36E1 (rather than the smaller RAMB18E1), since my maximum bit width is 36 (pg. 21 of ug363).

 

 

Anyone experience this problem before or know how to force the tools to implement SDP other than use the ipcore generator or the primitives?

 

0 Kudos
11 Replies
Scholar austin
Scholar
10,698 Views
Registered: ‎02-27-2008

Re: Simple Dual Port Blockram

d,

 

Depending on what family you are using, the hardware block that is used for the element you decsribe is the RAM36 (function requested vs. the hardware that i used).

 

That is the smallest possible physical block.  It will place two RAM18 into one RAM36 is possible , but you cannot get any smaller than using at least one RAM36, regardless of the actual number of bytes you need.

 

 

Austin Lesea
Principal Engineer
Xilinx San Jose
Visitor dak_zach
Visitor
10,671 Views
Registered: ‎06-21-2013

Re: Simple Dual Port Blockram

Ahhh, I found the note that references what you're talking about. There's a note in the xst user guide that talks about inferring asymmetric ram and bit width:

 

Note Asymmetric RAM inference for data buses larger than 18-bit will require the

RAMB36E1 block.

 

 

That explains why it is using a RAM36 and not a RAM18, but why is it setting the block up as TDP?  Wouldn't it be simpler to make it a SDP?

0 Kudos
Historian
Historian
10,662 Views
Registered: ‎02-25-2008

Re: Simple Dual Port Blockram


@dak_zach wrote:

 

That explains why it is using a RAM36 and not a RAM18, but why is it setting the block up as TDP?  Wouldn't it be simpler to make it a SDP?


The BRAM is just one "thing." It's always a true dual-port memory. When a design uses it as a simple dual-port, like yours, the synthesis infers the correct logic, but when the mapper and fitter tools go to work, the only thing they can use is the TDP, with various signals tied off.

 

So the tools will use the true dual port and on the read side, the write enable/address/data are all tied off. 

----------------------------Yes, I do this for a living.
0 Kudos
Instructor
Instructor
10,647 Views
Registered: ‎08-14-2007

Re: Simple Dual Port Blockram


@dak_zach wrote:

Ahhh, I found the note that references what you're talking about. There's a note in the xst user guide that talks about inferring asymmetric ram and bit width:

 

Note Asymmetric RAM inference for data buses larger than 18-bit will require the

RAMB36E1 block.

 

 

That explains why it is using a RAM36 and not a RAM18, but why is it setting the block up as TDP?  Wouldn't it be simpler to make it a SDP?


Seems odd that the asymmetry should play in the decision to use 36K instead of 18K.  Usually it's just a limit in the largest port size.  If you can get a symmetric 36-wide RAM in the 18K block, then you could add some logic to make your write data the full 36 bits and save some BRAM.  How easy this is depends on whether you need to write 18 bits of a word when you will not also immediately write the other 18 bits (requires "byte" enables or read/mod/write).

-- Gabor
0 Kudos
Highlighted
Visitor dak_zach
Visitor
10,585 Views
Registered: ‎06-21-2013

Re: Simple Dual Port Blockram

Couple thoughts/notes on my application and what everyones contributed to the discussion.

 

1.  I realize that there are really only RAM36 blocks.  I am going to have several of these blocks in the design, so in order to reduce bram utilization, I wanted each block to be placed in half of a RAM36 (equal to 1 RAM18) and the other half used for a second instantiation of the same type.  I can't combine them into one instance because they will be used independent of each other for reading.

 

2.  Each RAM36 block is identical, meaning they are all really TDP, but can be used as SDP by tying certain signals either high or low.  Why does the primitive have a generic for RAM_MODE then?  The way I've been checking to see how this block is implemented is by opening up the completed design in FGPA Editor, and each bram instance has so far shown the RAM_MODE as being implemented as TDP.  I have done other (simpler) inferred ram where the RAM_MODE was set to SDP.

 

3.  I think what I'm going to end up implementing is instantiating a ram18e1 primitive to give me the asymetrical bram that I need.  I could add extra logic to store every other 18 bits to write with the next incoming data, but that doesn't work out very well with how I'm reading the data.  I also could implement byte enables.  I actually thought of that before I tried asymmetrical ports.  I was running into the same problem of the bram getting placed into a RAM36 rather than a RAM18 that I had wanted.

 

 

Thanks for all the help guys, I appreciate it.

 

0 Kudos
Instructor
Instructor
10,580 Views
Registered: ‎08-14-2007

Re: Simple Dual Port Blockram

I don't think you can work around this by instantiating the primitive.  Using CoreGen I see that I still can't get a 18b/36b asymmetric RAM into one 18K RAMB.  So I don't think that the restriction is really just for RAM inference.  However it is possible to get 36b/36b into one 18K RAMB even if you use the byte write enables ("byte" = 9b using coregen).

-- Gabor
0 Kudos
Visitor dak_zach
Visitor
10,570 Views
Registered: ‎06-21-2013

Re: Simple Dual Port Blockram

I also cannot get the ipcore generator to place a 18b/36b blockram in a RAM18, even when I half the amount of memory (make the 36b port only 256 words deep).

 

Could that be a limitation of the ipcore generator?  In UG363, the memory resources user guide (v1.8), Table 1-9 lists available port widths for a RAM18 in SDP mode.  The note at the bottom says either the write or read port must be 32 or 36 bits wide.  I'm assuming the other port can be any other width listed in the table.  My read port is 36 bits wide, and 18 is listed in the table, so it technically should work.

 

I'll try implementing the byte enable untill we find out.

0 Kudos
Contributor
Contributor
10,558 Views
Registered: ‎08-12-2008

Re: Simple Dual Port Blockram

It can be done - see attached. 

 

As to "packing" two of these together, don't forget that they have to have the same control set for that to happen.

0 Kudos
Contributor
Contributor
9,835 Views
Registered: ‎08-12-2008

Re: Simple Dual Port Blockram

>Note Asymmetric RAM inference for data buses larger than 18-bit will require the RAMB36E1 block.

 

Where is this note located?  Why should that restriction exist?  I've already proven (to myself at least) that 32x16 and 16x32 asymetric rams can be implemented in a RAM18E1 by direct instantiation. 

 

I think it's a bug (Vivado at least, not sure about ISE).  

dpram_32x16.jpg
0 Kudos
Visitor dak_zach
Visitor
5,671 Views
Registered: ‎06-21-2013

Re: Simple Dual Port Blockram

The note is in UG687(version 14.5)  pg. 215.

 

To add to your results, I've used the RAM18E primitive for a 18x36 with no problems.  Generally, what I've found is that I can infer almost any kind of memory that I need, as long as I don't have a specific way I'd like it implemented.

0 Kudos
Contributor
Contributor
5,669 Views
Registered: ‎08-12-2008

Re: Simple Dual Port Blockram

> The note is in UG687(version 14.5)  pg. 215.

 

I see.  That is for XST.  A similar note doesn't exist in the Vivado synthesis guide.

 

>To add to your results, I've used the RAM18E primitive for a 18x36 with no problems.  Generally, what I've found is that I >can infer almost any kind of memory that I need, as long as I don't have a specific way I'd like it implemented.

 

Which would be fine except you often can't afford to have your memory usage expand by a factor of 2.  I'd like to see someone from Xilinx reply on this.  Maybe I need to start a web case.  I did do one last year on this and if I remember correctly, it was supposed to be fixed by 2014.3 or 2014.4 (or was it 2014.2).  I'd like to get an explanation as to why this is so hard to get correct when they have it _mostly_ working.

 

 

0 Kudos