KJ said:
Meaning that lpm_fifo_dc will (or could) misfunction in what way? Ignore a
write? Something else?
Depends on constraints. It's an asynch race:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.LPM_COMPONENTS.all;
entity LPM_FIFO_DC is
generic (LPM_WIDTH : positive ;
LPM_WIDTHU : positive := 1;
LPM_NUMWORDS : positive;
LPM_SHOWAHEAD : string := "OFF";
LPM_TYPE : string := "LPM_FIFO_DC";
LPM_HINT : string := "UNUSED");
port (DATA : in std_logic_vector(LPM_WIDTH-1 downto 0);
WRCLOCK : in std_logic;
RDCLOCK : in std_logic;
WRREQ : in std_logic;
RDREQ : in std_logic;
ACLR : in std_logic := '0';
Q : out std_logic_vector(LPM_WIDTH-1 downto 0);
WRUSEDW : out std_logic_vector(LPM_WIDTHU-1 downto 0);
RDUSEDW : out std_logic_vector(LPM_WIDTHU-1 downto 0);
WRFULL : out std_logic;
RDFULL : out std_logic;
WREMPTY : out std_logic;
RDEMPTY : out std_logic);
end LPM_FIFO_DC;
architecture LPM_SYN of lpm_fifo_dc is
type lpm_memory is array (lpm_numwords-1 downto 0) of
std_logic_vector(lpm_width-1 downto 0);
signal i_q : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
signal i_read_and_write : std_logic := '0';
signal i_rdptr, i_wrptr : integer := 0;
signal i_rdempty, i_wrempty : std_logic := '1';
signal i_rdfull, i_wrfull : std_logic := '0';
signal i_rdusedw, i_wrusedw : integer := 0;
constant ZEROS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS =>
'0');
constant RDPTR_DP : integer := 5;
constant WRPTR_DP : integer := 5;
constant RDUSEDW_DP : integer := 1;
constant WRUSEDW_DP : integer := 1;
constant FULL_RISEEARLY : integer := 2;
type t_rdptrpipe is array (0 to RDPTR_DP) of integer;
type t_wrptrpipe is array (0 to WRPTR_DP) of integer;
type t_rdusedwpipe is array (0 to RDUSEDW_DP) of integer;
type t_wrusedwpipe is array (0 to WRUSEDW_DP) of integer;
begin
process (rdclock, wrclock, aclr, i_read_and_write)
variable mem_data : lpm_memory := (OTHERS => ZEROS);
variable pipe_wrptr : t_rdptrpipe := (OTHERS => 0);
variable pipe_rdptr : t_wrptrpipe := (OTHERS => 0);
variable pipe_rdusedw : t_rdusedwpipe := (OTHERS => 0);
variable pipe_wrusedw : t_wrusedwpipe := (OTHERS => 0);
begin
if (ACLR = '1') then
----- CLEAR ALL VARIABLES -----
i_q <= ZEROS;
i_read_and_write <= '0';
i_rdptr <= 0;
i_wrptr <= 0;
i_rdempty <= '1';
i_wrempty <= '1';
i_rdfull <= '0';
i_wrfull <= '0';
-- i_rdusedw and i_wrusedw are cleard in the pipelines.
if (lpm_showahead = "ON") then
i_q <= mem_data(0);
end if;
elsif (wrclock'event and wrclock = '1') then
----- SET FLAGS -----
if (i_wrusedw >= lpm_numwords-1-FULL_RISEEARLY) then
i_wrfull <= '1';
else
i_wrfull <= '0';
end if;
if (i_wrusedw <= 0 and i_rdptr = i_wrptr) then
i_wrempty <= '1';
end if;
if (wrreq = '1' and i_wrfull = '0' and not wrreq'event) then
----- WRITE DATA -----
mem_data(i_wrptr) := data;
----- SET FLAGS -----
i_wrempty <= '0';
----- INC WRPTR -----
if (i_wrptr >= lpm_numwords-1) then
i_wrptr <= 0;
else
i_wrptr <= i_wrptr + 1;
end if;
end if;
if (rdclock'event and rdclock = '1') then
i_read_and_write <= '1';
end if;
elsif ((rdclock'event and rdclock = '1') or
i_read_and_write = '1') then
i_read_and_write <= '0';
----- SET FLAGS -----
if (i_rdusedw >= lpm_numwords-1-FULL_RISEEARLY) then
i_rdfull <= '1';
else
i_rdfull <= '0';
end if;
if (i_rdptr = i_wrptr) then
i_rdempty <= '1';
elsif (i_rdempty = '1' and i_rdusedw > 0) then
i_rdempty <= '0';
end if;
----- Q SHOWAHEAD -----
if (lpm_showahead = "ON" and i_rdptr /= i_wrptr) then
i_q <= mem_data(i_rdptr);
end if;
if (rdreq = '1' and i_rdempty = '0' and not rdreq'event) then
----- READ DATA -----
i_q <= mem_data(i_rdptr);
if (lpm_showahead = "ON") then
if (i_rdptr = i_wrptr) then
i_q <= ZEROS;
else
if (i_rdptr >= lpm_numwords-1) then
i_q <= mem_data(0);
else
i_q <= mem_data(i_rdptr+1);
end if;
end if;
end if;
----- SET FLAGS -----
if ((i_rdptr = lpm_numwords-1 and i_wrptr = 0) or
i_rdptr+1 = i_wrptr) then
i_rdempty <= '1';
end if;
----- INC RDPTR -----
if (i_rdptr >= lpm_numwords-1) then
i_rdptr <= 0;
else
i_rdptr <= i_rdptr + 1;
end if;
end if;
end if;
----- DELAY WRPTR FOR RDUSEDW -----
pipe_wrptr(RDPTR_DP) := i_wrptr;
if (RDPTR_DP > 0) then
if (ACLR = '1') then
for i in 0 to RDPTR_DP loop
pipe_wrptr(i) := 0;
end loop;
elsif (rdclock'event and rdclock = '1') then
pipe_wrptr(0 to RDPTR_DP-1) := pipe_wrptr(1 to RDPTR_DP);
end if;
end if;
if (pipe_wrptr(0) >= i_rdptr) then
pipe_rdusedw(RDUSEDW_DP) := pipe_wrptr(0) - i_rdptr;
else
pipe_rdusedw(RDUSEDW_DP) :=
lpm_numwords + pipe_wrptr(0) - i_rdptr;
end if;
----- DELAY RDPTR FOR WRUSEDW -----
pipe_rdptr(WRPTR_DP) := i_rdptr;
if (WRPTR_DP > 0) then
if (ACLR = '1') then
for i in 0 to WRPTR_DP loop
pipe_rdptr(i) := 0;
end loop;
elsif (wrclock'event and wrclock = '1') then
pipe_rdptr(0 to WRPTR_DP-1) := pipe_rdptr(1 to WRPTR_DP);
end if;
end if;
if (i_wrptr >= pipe_rdptr(0)) then
pipe_wrusedw(WRUSEDW_DP) := i_wrptr - pipe_rdptr(0);
else
pipe_wrusedw(WRUSEDW_DP) := lpm_numwords + i_wrptr - pipe_rdptr(0);
end if;
----- DELAY RDUSEDW -----
if (RDUSEDW_DP > 0) then
if (ACLR = '1') then
for i in 0 to RDUSEDW_DP loop
pipe_rdusedw(i) := 0;
end loop;
elsif (rdclock'event and rdclock = '1') then
pipe_rdusedw(0 to RDUSEDW_DP-1) :=
pipe_rdusedw(1 to RDUSEDW_DP);
end if;
end if;
i_rdusedw <= pipe_rdusedw(0);
----- DELAY WRUSEDW -----
if (WRUSEDW_DP > 0) then
if (ACLR = '1') then
for i in 0 to WRUSEDW_DP loop
pipe_wrusedw(i) := 0;
end loop;
elsif (wrclock'event and wrclock = '1') then
pipe_wrusedw(0 to WRUSEDW_DP-1) :=
pipe_wrusedw(1 to WRUSEDW_DP);
end if;
end if;
i_wrusedw <= pipe_wrusedw(0);
end process;
----- SET OUTPUTS ------
q <= i_q;
rdempty <= i_rdempty;
wrempty <= i_wrempty;
rdfull <= i_rdfull;
wrfull <= i_wrfull;
rdusedw <= conv_std_logic_vector(i_rdusedw, lpm_widthu);
wrusedw <= conv_std_logic_vector(i_wrusedw, lpm_widthu);
end LPM_SYN;