From: Martin Schoeberl on
>>
>>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?
>>
> NO, but you can use GENERATE (assuming VHDL) to switch between different bram geometries
> Aurelian
>
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


From: Olaf Petzold on
Hi,

> I'll give up one this vendor independent block RAM project. For
> the 32-bit write data, 8-bit read data with registered address,

Don't give up ;-)

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

Regards,
Olaf


---8<---
library unisim;
use unisim.vcomponents.all;

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


entity ram_512x80 is

generic (
RESET_ACTIVE : std_logic := '1');

port (
clk : in std_logic;
reset : in std_logic;
en : in std_logic;
AB : in std_logic_vector(8 downto 0);
DB_I : in std_logic_vector(79 downto 0);
DB_O : out std_logic_vector(79 downto 0);
we : in std_logic);

end entity ram_512x80;

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

architecture banking of ram_512x80 is

constant NUM_BLOCKS : positive := 10; -- XC2S100

signal m_clk : std_logic;
signal m_reset : std_logic;

begin

-- reset conversation
m_reset <= '1' when (reset = RESET_ACTIVE) else '0';

-- xilinx specific
clk_buf : BUFG
port map (I => clk, O => 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
--
http://toolbox.xilinx.com/docsan/xilinx7/de/libs/lib/ramb4_sn.pdf
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))) <= DB_I;
DB_O <= DB_I;
else
DB_O <= blockram(to_integer(unsigned(AB)));
end if;
end if;
end if;
end process;

end architecture infering;
From: Martin Schoeberl on
Hi Olaf,

>> I'll give up one this vendor independent block RAM project. For
>> the 32-bit write data, 8-bit read data with registered address,
>
> Don't give up ;-)
>
> Maybe the code attached from my project will help you. Using configurations 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 <= ram_block(to_integer(unsigned(rda_reg(jpc_width-1 downto 2))));

process(clk)
begin

if rising_edge(clk) then
if wr_en='1' then
ram_block(to_integer(unsigned(wr_addr))) <= data;
end if;

rda_reg <= rd_addr;

end if;
end process;


process(rda_reg, d)
begin
case rda_reg(1 downto 0) is
when "11" =>
q <= d(31 downto 24);
when "10" =>
q <= d(23 downto 16);
when "01" =>
q <= d(15 downto 8);
when "00" =>
q <= d(7 downto 0);
when others =>
null;
end case;
end process;

end rtl;




From: John Adair on
Martin

One good place for information is the libraries guide. A version of it is
here http://toolbox.xilinx.com/docsan/xilinx7/books/docs/lib/lib.pdf . 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.
http://www.enterpoint.co.uk


"Martin Schoeberl" <mschoebe(a)mail.tuwien.ac.at> wrote in message
news:4385f45c$0$12126$3b214f66(a)tunews.univie.ac.at...
>> 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.
>
> 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).
>
>> 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.
>
> 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.
>
>
>> 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.
>
> 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
>
>
>>> >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.
>>>>
>>>
>>> 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
>>>
>>
>>
>
>


From: Martin Thompson on
"Martin Schoeberl" <mschoebe(a)mail.tuwien.ac.at> writes:

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

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(a)trw.com
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.trw.com/conekt

First  |  Prev  |  Next  |  Last
Pages: 1 2 3
Prev: Spartan-3E starter kit
Next: Slow FIFO using external SRAM