My only hope is in the wisdom of this list... I have a problem I can't
solve, maybe some of you have a solution. I'm trying to implement a
parametrizable (i.e. generic) memory entity for Xilinx SpartanII. I want it
to be synthetizable also with ISE Web edition. I want it to be placed by the
compiler to block-RAMs. I also want to support all of the block-RAMs
facilities, i.e. full dual-port access with both ports having read-write
access. I've almost succeeded with that. The code below compiles fine if I
comment out the line marked with (1). That's the second port's write access.
However with that, XST does not recognizes this any more and gives a
compiler error. Please don't suggest to use primitives as they are not
generics or the coregen as that's not included in the web-pack.
Thanks,
Andras Tantos
-- A true dual-port memory implementation.
library IEEE;
use IEEE.std_logic_1164.all;
entity dpmem is
generic (
adr_width : integer := 8;
dat_width : integer := 8
);
port (
-- Signals for the port A
a_clk_i : in std_logic; -- Read
clock
a_stb_i : in std_logic; -- Read port
select
a_we_i : in std_logic; -- Read port
Write enable
a_adr_i : in std_logic_vector(adr_width -1 downto 0); -- Read
Address
a_dat_i : in std_logic_vector(dat_width -1 downto 0); -- Input
data
a_dat_o : out std_logic_vector(dat_width -1 downto 0); -- Output
data
a_ack_o : out std_logic; -- Read
ready output
-- Signals for the port B
b_clk_i : in std_logic; -- Write
clock
b_stb_i : in std_logic; -- Write
port select
b_we_i : in std_logic; -- Write
Enable
b_adr_i : in std_logic_vector(adr_width -1 downto 0); -- Write
Address
b_dat_i : in std_logic_vector(dat_width -1 downto 0); -- Input
data
b_dat_o : out std_logic_vector(dat_width -1 downto 0); -- Output
data
b_ack_o : out std_logic -- Write
ready output
);
end dpmem;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
architecture xilinx of dpmem is
type ram_type is array (2**adr_width-1 downto 0) of std_logic_vector
(dat_width-1 downto 0);
signal RAM : ram_type;
signal l_a_adr : std_logic_vector(adr_width-1 downto 0);
signal l_b_adr : std_logic_vector(adr_width-1 downto 0);
signal l_a_ack : std_logic;
signal l_b_ack : std_logic;
begin
process (a_clk_i, b_clk_i)
begin
-- port A
if (a_clk_i'event and a_clk_i = '1') then
l_a_adr <= a_adr_i;
if a_stb_i = '1' then
if a_we_i = '0' then
-- read operation (read operation is allways performed
-- the only question is the hand-shake)
l_a_ack <= not l_a_ack;
else
-- write opration
RAM(conv_integer(a_adr_i)) <= a_dat_i;
l_a_ack <= '1';
end if;
else
l_a_ack <= '0';
end if;
end if;
-- port B
if (b_clk_i'event and b_clk_i = '1') then
l_b_adr <= b_adr_i;
if b_stb_i = '1' then
if b_we_i = '0' then
-- read operation (read operation is allways
performed
-- the only question is the hand-shake)
l_b_ack <= not l_b_ack;
else
-- write opration
RAM(conv_integer(b_adr_i)) <= b_dat_i; -- (1) Problem
here!!
l_b_ack <= '1';
end if;
else
l_b_ack <= '0';
end if;
end if;
end process;
a_dat_o <= RAM(conv_integer(l_a_adr));
a_ack_o <= l_a_ack;
b_dat_o <= RAM(conv_integer(l_b_adr));
b_ack_o <= l_b_ack;
end xilinx;
"Tantos Andras" <andras...@yahoo.com> wrote in message
news:fgJs8.21696$Sa2....@nwrddc01.gnilink.net...
Andras Tantos
"Paul Baxter" <pauljnos...@hotnospammail.com> wrote in message
news:3cb408bd$0$8510$cc9e...@news.dial.pipex.com...
I don't have the tool here with me, so I can't cite it word by word but XST
compains about having a non-synthetizable process because of it's dual
clocks. Sure it has, but without the incriminated line it just works fine.
My conclusion was that XST no longer recognizes the structure as a memory,
trying to synthetize it from normal logic and than fails. If I remove the
second clock signal, making the memory a single-clock, dual ported memory,
it tries to synthetize it from flip-flops and address decoders. Still fails
to recognize the possibility to put the whole thing into block-RAMs. I've
also tried to have two processes for the two ports. That also works if the
second port has a read-only access and also fails if I turn the second
ports' write access back on. In that case XST complains about having
multiple drivers for the signal: RAM. Again: it's very true but what can I
do about it? In a dual-port memory there *are* multiple drivers for the RAM
cells aren't there?
I will try your suggestions.
Thanks,
Andras Tantos
"Benjamin Todd" <Benjam...@cern.ch> wrote in message
news:a918f6$j10$1...@sunnews.cern.ch...
* Initialization of BlockRAMs not supported
* BlockRAMs which use the functionality of the RST and EN pins
ENA/ENB pins currently inaccessible - always tied to "1"
RSTA/RSTB pins currently inaccessible
* Dual-port RAMs that have different address widths
* Dual-port RAMs that read and write from both A and B ports
The port sizes of a distributed RAM are always equal. The current supported V2
primitives for the dual port memory are:
RAMB16_S1_S1
RAMB16_S2_S2
RAMB16_S9_S9
RAMB16_S36_S36
I'm not familiar with VHDL, but here's some code in Verilog
This example shows how to create a 512x1 (512 words 1 bits per word)
synchronous,
dual-port RAM within XST
module ram512x1d_inf (spo, dpo, we, d, raddr, waddr, clk);
parameter D_WIDTH = 1, ADDR_WIDTH = 9;
output [D_WIDTH - 1:0] spo, dpo;
input we, clk;
input [D_WIDTH - 1:0] d;
input [ADDR_WIDTH - 1:0] raddr, waddr;
reg [D_WIDTH - 1:0] mem [(1 << ADDR_WIDTH) - 1:0];
reg [ADDR_WIDTH - 1:0] raddr_reg, waddr_reg;
always @(posedge clk)
begin
waddr_reg = waddr;
raddr_reg = raddr;
end
always @(posedge clk)
if (we)
mem[waddr] = d;
assign spo = mem[waddr_reg];
assign dpo = mem[raddr_reg];
endmodule
--
/ 7\'7 Paulo Dutra (pa...@xilinx.com)
\ \ ` Xilinx hot...@xilinx.com
/ / 2100 Logic Drive http://www.xilinx.com
\_\/.\ San Jose, California 95124-3450 USA