10-23-2012 08:53 PM
I am using a memory block which is replicated several times over.
I am targetting my design for V6 and V5 devices.
The business end of the RAM code is here:
-- Port A (with byte enable) porta_rdwr_proc : process (port_a_clk) begin if port_a_clk'event and port_a_clk = '1' then port_a_dout <= RAM(conv_integer(port_a_addr)); if port_a_we = '1' then for i in 0 to DATA_WIDTH/8-1 loop if port_a_be(i) = '1' then RAM(conv_integer(port_a_addr))(i*8+0) := port_a_din(i*8+0); RAM(conv_integer(port_a_addr))(i*8+1) := port_a_din(i*8+1); RAM(conv_integer(port_a_addr))(i*8+2) := port_a_din(i*8+2); RAM(conv_integer(port_a_addr))(i*8+3) := port_a_din(i*8+3); RAM(conv_integer(port_a_addr))(i*8+4) := port_a_din(i*8+4); RAM(conv_integer(port_a_addr))(i*8+5) := port_a_din(i*8+5); RAM(conv_integer(port_a_addr))(i*8+6) := port_a_din(i*8+6); RAM(conv_integer(port_a_addr))(i*8+7) := port_a_din(i*8+7); end if; end loop; -- i end if; end if; end process porta_rdwr_proc; -- Port B portb_rdwr_proc : process (port_b_clk) begin if port_b_clk'event and port_b_clk = '1' then port_b_dout <= RAM(conv_integer(port_b_addr)); if port_b_we = '1' then for j in 0 to DATA_WIDTH/8-1 loop if port_b_be(j) = '1' then RAM(conv_integer(port_b_addr))(j*8+0) := port_b_din(j*8+0); RAM(conv_integer(port_b_addr))(j*8+1) := port_b_din(j*8+1); RAM(conv_integer(port_b_addr))(j*8+2) := port_b_din(j*8+2); RAM(conv_integer(port_b_addr))(j*8+3) := port_b_din(j*8+3); RAM(conv_integer(port_b_addr))(j*8+4) := port_b_din(j*8+4); RAM(conv_integer(port_b_addr))(j*8+5) := port_b_din(j*8+5); RAM(conv_integer(port_b_addr))(j*8+6) := port_b_din(j*8+6); RAM(conv_integer(port_b_addr))(j*8+7) := port_b_din(j*8+7); end if; end loop; end if; end if; end process portb_rdwr_proc;
On Virtex-6 devices (tested on ML605) this was synthesized without problems.
On Virtex-5 devices (tested on ML510) this fails. I was able to pin down the problem as V5 using an old XST parser.
(VHDL source expression not yet supported: 'AscendingRange'.)
I then used the XST option "-use_new_parser yes" option. This passes synthesis but leaves a bunch of uncomfortable warnings.
I am not sure how to fix this problem ? I really want to infer the RAMs as portability is an important concern.
Does anyone know a workaround ?
RRS
10-23-2012 11:30 PM
Hi,
what warnings have you got? Please post them too.
V6 and V5 have different architectures.
So if your code is originally made for V6 devices some V5 specific detail may be different causing the warnings.
Have a nice synthesis
Eilert
10-24-2012 12:47 PM
What does the declaration of RAM look like? It sounds like the problem is with an
ascending range like ( 0 to 1023) instead of (1023 downto 0).
-- Gabor
10-24-2012 12:52 PM
The entire code looks like this:
library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; use ieee.std_logic_textio.all; library std; use std.textio.all; entity dual_port_ram_w_be is generic( DATA_WIDTH : natural := 32; ADDR_WIDTH : natural := 10; INITIALIZE_TO_ZERO : boolean := true; MEMTYPE_PAR_DIRECTIVE : string := "block" ); port( -- Port A port_a_clk : in std_logic; port_a_we : in std_logic; port_a_be : in std_logic_vector(DATA_WIDTH/8-1 downto 0); port_a_addr : in std_logic_vector(ADDR_WIDTH-1 downto 0); port_a_din : in std_logic_vector(DATA_WIDTH-1 downto 0); port_a_dout : out std_logic_vector(DATA_WIDTH-1 downto 0); -- Port B port_b_clk : in std_logic; port_b_we : in std_logic; port_b_be : in std_logic_vector(DATA_WIDTH/8-1 downto 0); port_b_addr : in std_logic_vector(ADDR_WIDTH-1 downto 0); port_b_din : in std_logic_vector(DATA_WIDTH-1 downto 0); port_b_dout : out std_logic_vector(DATA_WIDTH-1 downto 0) ); end dual_port_ram_w_be; architecture dual_port_ram_w_be_arch of dual_port_ram_w_be is -- Infer a memory constant MEM_DEPTH : natural := 2**ADDR_WIDTH; type ram_type is array (0 to MEM_DEPTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0); -- Memory initialization scheme impure function zero_initialize return ram_type is variable mem : ram_type; begin if INITIALIZE_TO_ZERO = true then for i in 0 to MEM_DEPTH-1 loop mem(i) := (others => '0'); end loop; -- i end if; return mem; end zero_initialize; -- RAM declaration shared variable RAM : ram_type := zero_initialize; -- Constrain memory to use block, auto or distributed attribute ram_style : string; attribute ram_style of RAM : variable is MEMTYPE_PAR_DIRECTIVE; begin porta_rdwr_proc : process (port_a_clk) begin if port_a_clk'event and port_a_clk = '1' then port_a_dout <= RAM(conv_integer(port_a_addr)); if port_a_we = '1' then for i in 0 to DATA_WIDTH/8-1 loop if port_a_be(i) = '1' then RAM(conv_integer(port_a_addr))(i*8+0) := port_a_din(i*8+0); RAM(conv_integer(port_a_addr))(i*8+1) := port_a_din(i*8+1); RAM(conv_integer(port_a_addr))(i*8+2) := port_a_din(i*8+2); RAM(conv_integer(port_a_addr))(i*8+3) := port_a_din(i*8+3); RAM(conv_integer(port_a_addr))(i*8+4) := port_a_din(i*8+4); RAM(conv_integer(port_a_addr))(i*8+5) := port_a_din(i*8+5); RAM(conv_integer(port_a_addr))(i*8+6) := port_a_din(i*8+6); RAM(conv_integer(port_a_addr))(i*8+7) := port_a_din(i*8+7); end if; end loop; -- i end if; end if; end process porta_rdwr_proc; -- Port B portb_rdwr_proc : process (port_b_clk) begin if port_b_clk'event and port_b_clk = '1' then port_b_dout <= RAM(conv_integer(port_b_addr)); if port_b_we = '1' then for j in 0 to DATA_WIDTH/8-1 loop if port_b_be(j) = '1' then RAM(conv_integer(port_b_addr))(j*8+0) := port_b_din(j*8+0); RAM(conv_integer(port_b_addr))(j*8+1) := port_b_din(j*8+1); RAM(conv_integer(port_b_addr))(j*8+2) := port_b_din(j*8+2); RAM(conv_integer(port_b_addr))(j*8+3) := port_b_din(j*8+3); RAM(conv_integer(port_b_addr))(j*8+4) := port_b_din(j*8+4); RAM(conv_integer(port_b_addr))(j*8+5) := port_b_din(j*8+5); RAM(conv_integer(port_b_addr))(j*8+6) := port_b_din(j*8+6); RAM(conv_integer(port_b_addr))(j*8+7) := port_b_din(j*8+7); end if; end loop; end if; end if; end process portb_rdwr_proc; end dual_port_ram_w_be_arch;