¿Por qué Synplify out out mientras que Xilinx XST pasa sin problemas?

5

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 se sintetiza en XST y Synplify Pro. Esto compila correctamente y funciona perfectamente en FPGA sin problemas cuando se sintetiza y PARed con XST.

En Synplify Pro, recibo 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 obtengo es: Logic for ram_0_0_4(7 downto 0) does not match a standard flip-flop

Parece que XST es indulgente con las directrices de codificación, mientras que Synplify es más estricto. ¿Puedes explicar por qué está ocurriendo el error? ¿Cómo puedo solucionarlo?

Necesito usar Synplify porque necesito hacer una copia de mi código a un dispositivo más antiguo.

    
pregunta boffin

1 respuesta

5

Está bien ... es posible que haya descubierto la solución. La solución es reducir el número de condiciones anidadas. De esa manera, 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.

RRS

    
respondido por el boffin

Lea otras preguntas en las etiquetas