FPGARelated.com
Forums

Dual Port RAM

Started by maxascent October 30, 2006
Martin Thompson wrote:

> when I use a FIFO, all I > want is a simple FIFO with a consistent interface. Do others have a > different view? > Perhaps we should all get together and write the wrappers and docs for > this between us for the benefit of future generations ( :-)?)
I think you've hit the nail on the head. There is no money to be made by solving this problem, and spending time on it won't speed up the hot project of the day. There would have to be some other motivation. -- Mike Treseler
John_H <newsgroup@johnhandwork.com> writes:

> Martin Thompson wrote: > > Maybe I'll regret jumping in here, but here's my take :-) > > We designers want standard interfaces to FPGA bits and bobs. > > <snip> > > It's nice to hear another opinion, but.... I have a software guy that > wants us FPGA designers to standardize on 16550 UARTs for our embedded > designs. WTF?! This device is from a quarter century ago and made to > work with serial links that are quite a bit worse than the embedded > applications I have today. > > WHY is a standard interface desired when much of what "was" there can > become completely superfluous? >
Well, to make life easier for *some* people. But read on...
> Personally - and this is opinion as it is with the other posts - I > want to get the best performance/cost/size balance I can strike. Why > should I burden my design with bloated code to pacify others who want > to blow my performance, increase my cost, or bloat the size? >
I agree - you shouldn't.
> If you want a standard interface, make one. PLEASE don't force me to > use silicon with hard-coded features that are much less than what they > could be all for the sake of conformance. >
I (and I think KJ) don't want the silicon defined by the interface. If you need all the hairy features of the V-5 FIFO, then it's there for you to use. But for those of use that just need a simple FIFO with a write and a read and some flags, then I shouldn't need to instance a different block for each bit of silicon I target. The interface *to my VHDL (or verilog)* is what is constant. The silicon can do what it wants. And if in future if ends up not able to meet my simple interface (which I doubt for a memory or FIFO type thing) then I'll accept I need to change things. All this applies in spades to RAM blocks, most of the time, all I want is an address bus (or two), a write enable and a data bus (or two). The Xiinx way forces me to instantiate specific sizes of blocks, which change from generation to generation, when all I want to do is say I need a 2Kx8 RAM.
> The only time I would care to see a standard interface pursued is if > there is ZERO impact to my engineering tradeoffs. >
And that is what I would want to see also. Easy for those who can gain from standardisation. "Power" available for those who need it. Cheers, Martin -- martin.j.thompson@trw.com TRW Conekt - Consultancy in Engineering, Knowledge and Technology http://www.conekt.net/electronics.html
Martin Thompson wrote:


> All this applies in spades to RAM blocks, most of the time, all I want > is an address bus (or two), a write enable and a data bus (or two). > The Xiinx way forces me to instantiate specific sizes of blocks, which > change from generation to generation, when all I want to do is say I > need a 2Kx8 RAM.
Martin, starting with Virtex4, the same RAMB16 primitive is used for all variants of the block RAM. It is parameterized with generics, which makes it a lot easier to instantiate a RAM that is sized according to the need. I find it still needs a wrapper, but at least that wrapper doesn't have to contain primitives with every combination of port sizes. I use a wrapper that automatically generates a RAM array with the appropriately sized ports on individual BRAMs based on the widths of the data ports and address ports. It also hides the parity bit/data bit distinction, plus it gives an easy method to porting to a different family (replace the wrapper).
Ray Andraka <ray@andraka.com> writes:

> Martin Thompson wrote: > > > > All this applies in spades to RAM blocks, most of the time, all I want > > is an address bus (or two), a write enable and a data bus (or two). > > The Xiinx way forces me to instantiate specific sizes of blocks, which > > change from generation to generation, when all I want to do is say I > > need a 2Kx8 RAM. > > Martin, starting with Virtex4, the same RAMB16 primitive is used for > all variants of the block RAM. It is parameterized with generics, > which makes it a lot easier to instantiate a RAM that is sized > according to the need.
Thanks Ray, that's good to know - I haven't V-4ed in anger yet...
> I find it still needs a wrapper, but at least that wrapper doesn't > have to contain primitives with every combination of port sizes. I > use a wrapper that automatically generates a RAM array with the > appropriately sized ports on individual BRAMs based on the widths of > the data ports and address ports. It also hides the parity bit/data > bit distinction, plus it gives an easy method to porting to a > different family (replace the wrapper). >
I still maintain that Xilinx should provide us with a useful wrapper though, rather than us all having to do our own :-) Cheers, Martin -- martin.j.thompson@trw.com TRW Conekt - Consultancy in Engineering, Knowledge and Technology http://www.conekt.net/electronics.html
Martin Thompson wrote:
> Ray Andraka <ray@andraka.com> writes:
> > I still maintain that Xilinx should provide us with a useful wrapper > though, rather than us all having to do our own :-) > >
I agree, however with the caveat that it may still not fit all users. Mine, for example accepts an unconstrained integer array generic for initialization values. It puts the contents of that N element array into the first N locations of the RAM and zero fills the rest. Since the width can be greater than the 32 bits represented by VHDL integers, I have a second integer array generic for separately initializing the top half of an upto 63 bit wide composite memory. The wrapper instantiates RAMB16s with the depths determined by the number of address bits on each port, and then puts in as many RAMB16s as are required to accommodate the widths of the data ports. The entity for my V4 wrapper is: entity dual_port_ram is generic( SIM_COLLISION_CHECK : STRING := "NONE"; DO_reg: integer:=0; allow_pbits: integer:=1; reset_data: integer:= 0; --not usable with do_reg=1 RAM_data: int_array:=(0,0); --initial data RAM_data_hi: int_array:=(0,0)); --initial data port( CLKA: in std_logic; CLKB: in std_logic; SSRA: in std_logic; SSRB: in std_logic; WEA : in std_logic; WEB : in std_logic; DIA : in std_logic_vector; DIB : in std_logic_vector; DOA : out std_logic_vector; DOB : out std_logic_vector; ADDRA : in std_logic_vector; ADDRB : in std_logic_vector ); end dual_port_ram;
Ray Andraka <ray@andraka.com> writes:

> Martin Thompson wrote: > > Ray Andraka <ray@andraka.com> writes: > > > I still maintain that Xilinx should provide us with a useful wrapper > > though, rather than us all having to do our own :-) > > > > I agree, however with the caveat that it may still not fit all > users.
This is always true :-)
> Mine, for example accepts an unconstrained integer array > generic for initialization values. It puts the contents of that N > element array into the first N locations of the RAM and zero fills the > rest. Since the width can be greater than the 32 bits represented by > VHDL integers, I have a second integer array generic for separately > initializing the top half of an upto 63 bit wide composite memory.
That's useful!
> The wrapper instantiates RAMB16s with the depths determined by the > number of address bits on each port, and then puts in as many RAMB16s > as are required to accommodate the widths of the data ports. The > entity for my V4 wrapper is: > > entity dual_port_ram is > generic( > SIM_COLLISION_CHECK : STRING := "NONE"; > DO_reg: integer:=0; > allow_pbits: integer:=1; > reset_data: integer:= 0; --not usable with do_reg=1 > RAM_data: int_array:=(0,0); --initial data > RAM_data_hi: int_array:=(0,0)); --initial data > > port( > CLKA: in std_logic; > CLKB: in std_logic; > SSRA: in std_logic; > SSRB: in std_logic; > WEA : in std_logic; > WEB : in std_logic; > DIA : in std_logic_vector; > DIB : in std_logic_vector; > DOA : out std_logic_vector; > DOB : out std_logic_vector; > ADDRA : in std_logic_vector; > ADDRB : in std_logic_vector ); > > end dual_port_ram;
And presumably that works with more than just V-4, and also on other brands? I like the idea of using unconstraing vectors on the ports - I got in a habit of generic-ising those sorts of things early in my VHDL life and then constraining port widths based on that. I'm slowly revisiting older code to your sort of style! The upshot of all this seems to be we all have our own wrappers for the standard blocks, which probably only differ very slightly (if at all!)... oh well - I guess that's the way the world has worked out, even if it seems inefficient in term sof engineering effort! Thanks for your contributions (as always - they're full of useful nuggets!) Cheers, Martin -- martin.j.thompson@trw.com TRW Conekt - Consultancy in Engineering, Knowledge and Technology http://www.conekt.net/electronics.html