Tengo un proyecto con varios bloques de RAM de doble puerto inferidos. El código para esta memoria RAM de doble puerto es el siguiente:
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 := 12;
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
-- Memory formation : Byte enabled RAM is formed by laying byte RAM arrays
-- side-by-side. Read and write processes are realized by for loops iterating
-- across the byte array RAMs
-- Calculate array length, number of byte arrays
constant MEM_DEPTH : natural := 2**ADDR_WIDTH;
constant NUM_BYTE_ARRAY : natural := DATA_WIDTH/8;
-- Infer memory
type byte_array is array (0 to MEM_DEPTH-1) of std_logic_vector(7 downto 0);
type ram_type is array (NUM_BYTE_ARRAY-1 downto 0) of byte_array;
-- Zero initialize function
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
for byte_index in 0 to NUM_BYTE_ARRAY-1 loop
mem(byte_index)(i) := (others => '0');
end loop; -- byte_index
end loop; -- i
end if;
return mem;
end zero_initialize;
-- Constrain RAM memory to use "block", warn if not possible
shared variable RAM : ram_type := zero_initialize;
attribute ram_style : string;
attribute ram_style of RAM : variable is MEMTYPE_PAR_DIRECTIVE;
-- Temp signals
signal port_a_dout_reg : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
signal port_b_dout_reg : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
begin
-----------------------------------------------------------------------------
-- Port A block
-----------------------------------------------------------------------------
port_a_dout <= port_a_dout_reg;
porta_rdwr_blkgen : for i in 0 to NUM_BYTE_ARRAY-1 generate
porta_proc : process (port_a_clk)
begin -- process portb_proc
if port_a_clk'event and port_a_clk = '1' then
port_a_dout_reg((i+1)*8-1 downto i*8) <= RAM(i)(conv_integer(port_a_addr));
if port_a_we = '1' then
if port_a_be(i) = '1' then
RAM(i)(conv_integer(port_a_addr)) := port_a_din((i+1)*8-1 downto i*8);
end if;
end if;
end if;
end process porta_proc;
end generate porta_rdwr_blkgen;
-------------------------------------------------------------------------------
---- Port B
-------------------------------------------------------------------------------
port_b_dout <= port_b_dout_reg;
portb_rdwr_blkgen : for i in 0 to NUM_BYTE_ARRAY-1 generate
portb_proc : process (port_b_clk)
begin -- process portb_proc
if port_b_clk'event and port_b_clk = '1' then
port_b_dout_reg((i+1)*8-1 downto i*8) <= RAM(i)(conv_integer(port_b_addr));
if port_b_we = '1' then
if port_b_be(i) = '1' then
RAM(i)(conv_integer(port_b_addr)) := port_b_din((i+1)*8-1 downto i*8);
end if;
end if;
end if;
end process portb_proc;
end generate portb_rdwr_blkgen;
end dual_port_ram_w_be_arch;
El código anterior está sintetizado en XST y Synplify Pro. Este compila correctamente y funciona perfectamente en FPGA sin problemas cuando se sintetiza y se PARea con XST.
En Synplify Pro, aparece un error para la línea:
port_a_dout_reg((i+1)*8-1 downto i*8) <= RAM(i)(conv_integer(port_a_addr));
El error que me sale es:Logic for ram_0_0_4(7 downto 0) does not match a standard flip-flop
Parece que XST es indulgente con las pautas de codificación, mientras que Synplify es más estricto. ¿Puedes explicar por qué está ocurriendo el error? Cómo puedo resolverlo ?
Necesito usar Synplify porque necesito transferir mi código a un dispositivo más antiguo.
Muy bien... Puede que haya descubierto la solución. La solución es reducir el número de condiciones anidadas. De esa forma, el sintetizador no piensa que el flip-flop tenga múltiples niveles de señales de control.
-- Write process
porta_write_blkgen : for i in 0 to NUM_BYTE_ARRAY-1 generate
porta_wrproc : process (port_a_be, port_a_clk, port_a_we)
begin -- process portb_proc
if port_a_clk'event and port_a_clk = '1' and port_a_we = '1' and port_a_be(i) = '1' then
RAM(i)(conv_integer(port_a_addr)) := port_a_din((i+1)*8-1 downto i*8);
end if;
end process porta_wrproc;
end generate porta_write_blkgen;
Synplify parece ser más pedante en estos asuntos en comparación con las herramientas de Xilinx.
Probé la solución en FPGA y parece estar bien.
PVP