DPRAM in VHDL with different bus width

Guest
Hi to everybody!
I'm trying to make a VHDL DPRAM for a xilinx spartan II. It works great
for the same bus width on each side but I don't know how to make
different bus size. I need a 128x1 on one side and 16x8 on the other
side...
I tried this, but it generates an error.... anyone who can help?

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity latch_dpram is
generic (
WIDTH : integer := 16;
DEPTH : integer := 8
);
port (
w_clk : in std_logic;
w_en_in : in std_logic;
w_data_in : in std_logic_vector(WIDTH*(2**DEPTH)-1 downto 0);
r_clk : in std_logic;
r_addr_in : in std_logic_vector(DEPTH-1 downto 0);
r_data_out : out std_logic_vector(WIDTH-1 downto 0)
);
end entity;
----------------------------------------------------------------------------------------------------
architecture xilinx_latch_ram of latch_dpram is
type memory_type is array (natural range <>) of
std_logic_vector(WIDTH-1 downto 0);
signal memory : memory_type(2**DEPTH-1 downto 0);
signal r_addr_int: std_logic_vector(DEPTH-1 downto 0);
begin
write : process(w_clk)
begin
if w_clk'event and w_clk = '1' then
if w_en_in = '1' then
memory <= w_data_in;
end if;
end if;
end process;
read : process(r_clk)
begin
if r_clk'event and r_clk = '1' then
r_addr_int <= r_addr_in;
end if;
end process;
r_data_out <= memory(to_integer(unsigned(r_addr_int)));
end architecture;
 
reto.knaak@agie.ch wrote:
Hi to everybody!
I'm trying to make a VHDL DPRAM for a xilinx spartan II. It works great
for the same bus width on each side but I don't know how to make
different bus size. I need a 128x1 on one side and 16x8 on the other
side...
I tried this, but it generates an error.... anyone who can help?
What error did it generate?

-a
 
memory <= w_data_in;
r_data_out <= memory(to_integer(unsigned(r_addr_int)));
memory is array of SLV, w_data_in and r_data_out are not, which is
probably what's generating the error.
 
A couple of points:

AFAIK, inferring ram from arrays requires same read/write data widths.
If you want to use bram hardware to create different width IO, you have
to instantiate the bram. Otherwise, infer the ram with an array of the
widest data path (read or write) and use muxes (on read path) or
decoders and enables (on write path) to split up that wide path into
narrower chunks, based on lower address bits. Note that this extra
hardware will be in clbs, not part of bram.

It looks like you need w_data_in to be slv(width*depth-1 downto 0)

Andy
 
Thank you for all the comments! This night I came to the same
conslusions and following code compiles now (well, not using
blockrams..Synthesizing Unit <latch_dpram>....
Found 16-bit 8-to-1 multiplexer for signal <r_data_out>.
Found 128-bit register for signal <memory>.
Found 3-bit register for signal <r_addr_int>....
Unit <latch_dpram> synthesized.)

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity latch_dpram is
generic (
WIDTH : integer := 16;
DEPTH : integer := 3 --2^3=8
);
port (
w_clk : in std_logic;
w_en_in : in std_logic;
w_data_in : in std_logic_vector(WIDTH*(2**DEPTH)-1 downto 0);
r_clk : in std_logic;
r_addr_in : in std_logic_vector(DEPTH-1 downto 0);
r_data_out : out std_logic_vector(WIDTH-1 downto 0)
);
end entity;
architecture xilinx_latch_ram of latch_dpram is
type memory_type is array (natural range <>) of
std_logic_vector(WIDTH-1 downto 0);
signal memory : memory_type(2**DEPTH-1 downto 0);
signal r_addr_int: std_logic_vector(DEPTH-1 downto 0);
begin
write : process(w_clk)
begin
if w_clk'event and w_clk = '1' then
if w_en_in = '1' then
memory(0) <= w_data_in(15 downto 0); -- not so pretty but
working
memory(1) <= w_data_in(31 downto 16);
memory(2) <= w_data_in(47 downto 32);
memory(3) <= w_data_in(63 downto 48);
memory(4) <= w_data_in(79 downto 64);
memory(5) <= w_data_in(95 downto 80);
memory(6) <= w_data_in(111 downto 96);
memory(7) <= w_data_in(127 downto 112);
end if;
end if;
end process;
read : process(r_clk)
begin
if r_clk'event and r_clk = '1' then
r_addr_int <= r_addr_in;
end if;
end process;
r_data_out <= memory(to_integer(unsigned(r_addr_int)));
end architecture;
 

Welcome to EDABoard.com

Sponsor

Back
Top