Memory in VHDL

I would like to code the on-chip memory in vendor neutral VHDL. I got it running for a dual-port memory with single clock and same port sizes for the read and write port.

However, I need a memory with a 32-bit write port and an 8-bit read port. So far I was not able to code it in VHDL in a way that the Synthesizer inferres the correct block ram without an extra read MUX.

BTW: I do my test at the moment with Quartus. Will see how Xilinx XSE will support this.

Martin

Reply to
Martin Schoeberl
Loading thread data ...

I'll give up one this vendor independent block RAM project. For the 32-bit write data, 8-bit read data with registered address, in data and unregistered out data RAM coded in VHDL I got:

On the Altera Cyclone: generates a 32-bit dual port RAM with an external 4:1 MUX. This MUX hurts fmax (from 94MHz down to 84MHz)!

On the Xlinix Spartan-3: The RAM gets implemented as distributed RAM! Uses a lot of LCs and the fmax goes from 65MHz down to

50MHz

So I will bite the bullet and use two vendor specific VHDL files. However, there is one open issue: I want the memory size be configurable via a generic. This is possible with Alteras altsyncram.

For Xilinx I only know those RAMB16_S9_S36 components where the memory size is part of the component name. Is there a a Xilinx block RAM component where I can specify the size?

Thanks, Martin

Reply to
Martin Schoeberl

The RAMB16 elements are the raw RAM macros. The Sx part of the name indicates the port width. You can build up bigger memories in Coregen which is a bit like the Altera Megawizard tool or build them up yourself using generic statements using the raw macros.

If you looking at switching between vendors one trick is to hide a RAM inside a wrapper file. If you use the wrapper level as the RAM component for instantiation then you will only have to change the technology based memory element in one place i.e. the the wrapper file.

Some synthesisers are capable of inferring RAM usually using an indexed array of something like VHDL's "std_logic_vector". I can't tell you much about the results as it isn't my own preferred method but a non-vendor synthesiser may do better than one offered by the silicon vendors.

John Adair Enterpoint Ltd. - Home of FPGA PCI Development Boards.

formatting link

Reply to
John Adair

NO, but you can use GENERATE (assuming VHDL) to switch between different bram geometries Aurelian

--
 __
/ /\/\ Aurelian Lazarut
\ \  / System Verification Engineer
/ /  \ Xilinx Ireland
\_\/\/
 
phone:	353 01 4032639
fax:	353 01 4640324
Reply to
Aurelian Lazarut

the port width. You can build up bigger memories in

yourself using generic statements using the raw macros.

Can you describe this a little bit more specific, please? Are the other components available to describe Xilinx block RAMs?

BTW: With the web edition I don't have Coregen and I also don't use the Megawizzard in Quartus. Ideal setup is a single generic parameter with the memory size (in lenght of the address).

a wrapper file. If you use the wrapper level as the

technology based memory element in one place i.e. the the

That's the way I do it. I switch between technologies with different files in the project. I also use this different VHDL files in projects for other customization - primitiv, but efficient.

of something like VHDL's "std_logic_vector". I can't

non-vendor synthesiser may do better than one offered by

The Xilinx tool interffered distributed RAM from the VHDL description. A thing I definitely don't want. Quartus had problems with the different port sizes, but single port sizes work very well.

Martin

Reply to
Martin Schoeberl

geometries

Really, that's it? Not very comfortable - a plus for Quartus.

Perhaps one in this group has already done this coding effort and can provide the VHDL file?

Martin

Reply to
Martin Schoeberl

Hi,

Don't give up ;-)

Maybe the code attached from my project will help you. Using configurations you can choose the architecture.

Regards, Olaf

---8 m_clk);

-- instance block ram bram : for n in NUM_BLOCKS-1 downto 0 generate

function lsb (i : integer) return integer is begin return i*8; end;

function msb (i : integer) return integer is begin return lsb(i) + 7; end;

begin -- D(79:72) D(71:64) D(63:56) D(55:48) D(47:40) D(39:32) D(31:24) D(23:16) D(15:8) D(7:0) ram_i : RAMB4_S8 -- RAMB4_S8: Virtex/E, Spartan-II/IIE 512 x 8 Single-Port RAM --

formatting link
generic map ( INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000", INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000") port map ( CLK => m_clk, -- Clock input RST => m_reset, -- Synchronous reset input EN => en, -- RAM enable input ADDR => AB, -- 9-bit address input DO => DB_O(msb(n) downto lsb(n)), -- 8-bit data output DI => DB_I(msb(n) downto lsb(n)), -- 8-bit data input WE => we); -- RAM write enable input

end generate;

end architecture banking;

-------------------------------------------------------------------------------

architecture infering of ram_512x80 is

constant BIT_DEPTH : positive := 512; constant BIT_WIDTH : positive := 80;

type ram_t is array(BIT_DEPTH-1 downto 0) of std_logic_vector(BIT_WIDTH-1 downto 0);

-- infer RAM signal blockram : ram_t;

begin

-- Note, Spartan-II doesn't have "No Change Mode"; -- Using Block RAM Single Port "Write First Mode" process (clk) begin if rising_edge(clk) then if (en = '1') then if (we = '1') then blockram(to_integer(unsigned(AB)))

Reply to
Olaf Petzold

Hi Olaf,

you can choose the architecture.

Not so bad! The infering architecture generates a block ram for the Spartan-3. However, with Quartus it generates registers. A little step forward ;-)

The next step is to generate a memory with different port sizes. The attached code instances a block ram with a MUX in Quartus and distributed memory with the Xilinx tool.

--

-- gen_mem.vhd

--

-- VHDL memory experiments

--

-- address, data in are registered

-- data out is unregistered

--

--

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;

entity jbc is generic (jpc_width : integer := 10); port ( clk : in std_logic; data : in std_logic_vector(31 downto 0); rd_addr : in std_logic_vector(jpc_width-1 downto 0); wr_addr : in std_logic_vector(jpc_width-3 downto 0); wr_en : in std_logic; q : out std_logic_vector(7 downto 0) ); end jbc;

--

-- registered wraddress, wren

-- registered din

-- registered rdaddress

-- unregistered dout

-- architecture rtl of jbc is

constant nwords : integer := 2**(jpc_width-2); type mem is array(0 to nwords-1) of std_logic_vector(31 downto 0); signal ram_block: mem;

signal d: std_logic_vector(31 downto 0);

signal rda_reg : std_logic_vector(jpc_width-1 downto 0);

begin

d
Reply to
Martin Schoeberl

Martin

One good place for information is the libraries guide. A version of it is here

formatting link
. The RAMB16 macros are basically the size of a single block ram - 16Kbit (18Kbit with parity). There is also help on ram component instantiation in ISE (I believe this is in Webpack). If you click on the lightbulb icon in the ISE tool you should get to some templates.

I don't think you will find any other size as ready built macro for Xilinx RAM. You will have build that up yourself if you don't have Coregen.

John Adair Enterpoint Ltd. - Home of Broaddown2. The Ultimate Spartan3 Development Board.

formatting link

Reply to
John Adair

Nope. I've been beating them up on this for years now - they just can't seem to grasp why I wouldn;t want to use Coregen for all my RAM needs!

Grrr!

(Another) Martin

--
martin.j.thompson@trw.com 
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.trw.com/conekt
Reply to
Martin Thompson

I have done some, although I haven't covered all the various options - unfortunately within work time, so I can't post them :-(

I based it on the ideas in David Kessner's Free-IP RAM library if that helps... I can't seem to find it out there on the web anymore.

The wayback machine has it though...

formatting link
formatting link

Sorry to be no more help! Martin

--
martin.j.thompson@trw.com 
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.trw.com/conekt
Reply to
Martin Thompson

That's fine, not everything can be open-source ;-) And this work should be done by Xilinx (as you wrote in the other post).

But the .zip files are not archieved :-(

Martin

Reply to
Martin Schoeberl

There is for Virtex4: the Ramb16 component sets the aspect ratio with generics/attributes. It, however, is not backwards compatible with the earlier families.

You can write a single file that uses generate to select the appropriate BRAM size based on input widths or generics. Once written, it can be used in many projects, so hopefully you can ammortize the coding effort over many projects. Once done, the generates are transparent to the end user unless he decides he has to look under the hood to see what the generic RAM you created has under the hood.

Reply to
Ray Andraka

Can you provide me more information on this matter

snipped-for-privacy@operamail.co

snipped-for-privacy@hotmail.co

Reply to
ralfsmith

The Virtex 4 "RAMB16" component lets you set the aspect ratio with generics/attributes. But it still only generates a single BlockRAM. If you want a RAM which is larger than 18kbits, then you need to instantiate the RAMB16 component multiple times.

-- Fergus J. Henderson "I have always known that the pursuit Galois Connections, Inc. of excellence is a lethal habit" Phone: +1 503 626 6616 -- the last words of T. S. Garp.

Reply to
fjh-mailbox-38

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.