Warum gibt Synplify einen Fehler aus, während Xilinx XST ohne Probleme durchgeht?

Ich habe ein Projekt mit mehreren abgeleiteten Dual-Port-RAM-Blöcken. Der Code für dieses Dual-Port-RAM lautet wie folgt:

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;

Der obige Code wird in XST und Synplify Pro synthetisiert. Dies wird korrekt kompiliert und funktioniert perfekt auf FPGA ohne Probleme, wenn es mit XST synthetisiert und PARed wird.

In Synplify Pro erhalte ich einen Fehler für die Zeile:

port_a_dout_reg((i+1)*8-1 downto i*8) <= RAM(i)(conv_integer(port_a_addr));

Der Fehler, den ich bekomme, ist:Logic for ram_0_0_4(7 downto 0) does not match a standard flip-flop

Es sieht so aus, als ob XST mit Codierungsrichtlinien nachsichtig ist, während Synplify strenger ist. Können Sie erklären, warum der Fehler auftritt? Wie kann ich es lösen?

Ich muss Synplify verwenden, weil ich meinen Code auf ein älteres Gerät zurückportieren muss.

Antworten (1)

In Ordnung ... Ich habe vielleicht die Lösung herausgefunden. Die Lösung besteht darin, die Anzahl der verschachtelten Bedingungen zu reduzieren. Auf diese Weise denkt der Synthesizer nicht daran, dass das Flip-Flop mehrere Ebenen von Steuersignalen hat.

-- 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 scheint in diesen Dingen umständlicher zu sein als die Xilinx-Tools.

Ich habe die Lösung auf FPGA getestet und es scheint in Ordnung zu sein.

RRS