1 ------------------------------------------------------------------------------- 2 -- File : FifoAsync.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2013-07-10 5 -- Last update: 2016-06-30 6 ------------------------------------------------------------------------------- 7 -- Description: ASYNC FIFO module 8 ------------------------------------------------------------------------------- 9 -- This file is part of 'SLAC Firmware Standard Library'. 10 -- It is subject to the license terms in the LICENSE.txt file found in the 11 -- top-level directory of this distribution and at: 12 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. 13 -- No part of 'SLAC Firmware Standard Library', including this file, 14 -- may be copied, modified, propagated, or distributed except according to 15 -- the terms contained in the LICENSE.txt file. 16 ------------------------------------------------------------------------------- 19 use ieee.std_logic_1164.
all;
20 use ieee.std_logic_arith.
all;
21 use ieee.std_logic_unsigned.
all;
26 --! @ingroup base_fifo 46 -- Write Ports (wr_clk domain) 57 -- Read Ports (rd_clk domain) 74 type RegType is record 85 constant READ_INIT_C : RegType := ( 86 waddr => (others => '0'), 87 raddr => (others => '0'), 89 cnt => (others => '0'), -- empty during reset 95 constant WRITE_INIT_C : RegType := ( 96 waddr => (others => '0'), 97 raddr => (others => '0'), 99 cnt => (others => '1'), -- full during reset 105 signal rdReg : RegType := READ_INIT_C;
106 signal wrReg : RegType := WRITE_INIT_C;
108 signal fullStatus : sl;
109 signal readEnable : sl;
112 signal writeRst : sl;
114 signal rdReg_ready : sl;
115 signal wrReg_ready : sl;
121 constant GRAY_INIT_C : slv(ADDR_WIDTH_G-1 downto 0) := (others => '0');
127 type RamPortType is record 136 signal portA, portB : RamPortType;
138 type ReadStatusType is 145 constant READ_STATUS_INIT_C : ReadStatusType := ( 146 count => (others => '0'), 150 signal fifoStatus, fwftStatus : ReadStatusType := READ_STATUS_INIT_C;
153 attribute use_dsp48 : ;
154 attribute use_dsp48 of rdReg : signal is USE_DSP48_G;
155 attribute use_dsp48 of wrReg : signal is USE_DSP48_G;
159 -- FULL_THRES_G upper range check 161 report "FULL_THRES_G must be <= ((2**ADDR_WIDTH_G)-1)" 163 -- EMPTY_THRES_G upper range check 165 report "EMPTY_THRES_G must be <= ((2**ADDR_WIDTH_G)-2)" 169 report "USE_DSP48_G must be either yes, no, auto, or automax" 171 -- INIT_G length check 173 "INIT_G must either be ""0"" or the same length as DATA_WIDTH_G" severity failure;
175 ------------------------------- 177 ------------------------------- 178 READ_RstSync :
entity work.
RstSync 190 fifoStatus.count <= rdReg.cnt;
193 fifoStatus.empty <= '1' when (rdReg.cnt = 0) else readRst;
195 FIFO_Gen : if (FWFT_EN_G = false) generate 205 FWFT_Gen : if (FWFT_EN_G = true) generate 227 readEnable <= (sRdEn or fwftStatus.empty) and not(fifoStatus.empty);
228 sValid <= not(fwftStatus.empty);
236 if rising_edge(rd_clk) then 237 if readRst = '1' then 238 fwftStatus <= READ_STATUS_INIT_C after TPD_G;
243 fwftStatus.count <= fifoStatus.count after TPD_G;
274 READ_SEQUENCE :
process (
rd_clk)
is 276 if rising_edge(rd_clk) then 277 if readRst = '1' then 278 rdReg <= READ_INIT_C after TPD_G;
279 rdReg_rdGray <= GRAY_INIT_C after TPD_G;
281 rdReg.done <= '1' after TPD_G;
282 rdReg.Ack <= '0' after TPD_G;
283 rdReg.error <= '0' after TPD_G;
284 if rdReg_ready = '1' then 286 -- Decode the Gray code pointer 287 rdReg.waddr <= grayDecode(rdReg_wrGray) after TPD_G;
289 -- Check for read operation 290 if readEnable = '1' then 291 if fifoStatus.empty = '0' then 292 -- Calculate the count 293 rdReg.cnt <= rdReg.waddr - rdReg.advance after TPD_G;
294 -- Increment the read address pointer 295 rdReg.raddr <= rdReg.raddr + 1 after TPD_G;
296 rdReg.advance <= rdReg.advance + 1 after TPD_G;
297 rdReg.Ack <= '1' after TPD_G;
299 -- Calculate the count 300 rdReg.cnt <= rdReg.waddr - rdReg.raddr after TPD_G;
301 rdReg.error <= '1' after TPD_G;
304 -- Calculate the count 305 rdReg.cnt <= rdReg.waddr - rdReg.raddr after TPD_G;
308 -- Encode the Gray code pointer 309 rdReg_rdGray <= grayEncode(rdReg.raddr) after TPD_G;
314 end process READ_SEQUENCE;
316 ------------------------------- 318 ------------------------------- 319 WRITE_RstSync :
entity work.
RstSync 337 if rising_edge(wr_clk) then 338 if writeRst = '1' then 341 fullStatus <= '1' after TPD_G;
350 if (wrReg.cnt = (RAM_DEPTH_C-1)) or (wrReg.cnt = (RAM_DEPTH_C-2)) or (wrReg.cnt = (RAM_DEPTH_C-3)) then 356 if (wrReg.cnt = (RAM_DEPTH_C-1)) or (wrReg.cnt = (RAM_DEPTH_C-2)) then 357 fullStatus <= '1' after TPD_G;
359 fullStatus <= '0' after TPD_G;
390 WRITE_SEQUENCE :
process (
wr_clk)
is 392 if rising_edge(wr_clk) then 393 if writeRst = '1' then 394 wrReg <= WRITE_INIT_C after TPD_G;
395 wrReg_wrGray <= GRAY_INIT_C after TPD_G;
397 wrReg.done <= '1' after TPD_G;
398 wrReg.Ack <= '0' after TPD_G;
399 wrReg.error <= '0' after TPD_G;
400 if wrReg_ready = '1' then 401 if wrReg.rdy = '0' then 403 wrReg.cnt <= (others => '0');
406 -- Decode the Gray code pointer 407 wrReg.raddr <= grayDecode(wrReg_rdGray) after TPD_G;
409 -- Check for write operation 411 if fullStatus = '0' then 412 -- Calculate the count 413 wrReg.cnt <= wrReg.advance - wrReg.raddr after TPD_G;
414 -- Increment the read address pointer 415 wrReg.waddr <= wrReg.waddr + 1 after TPD_G;
416 wrReg.advance <= wrReg.advance + 1 after TPD_G;
417 wrReg.Ack <= '1' after TPD_G;
419 wrReg.error <= '1' after TPD_G;
420 -- Calculate the count 421 wrReg.cnt <= wrReg.waddr - wrReg.raddr after TPD_G;
424 -- Calculate the count 425 wrReg.cnt <= wrReg.waddr - wrReg.raddr after TPD_G;
428 -- Encode the Gray code pointer 429 wrReg_wrGray <= grayEncode(wrReg.waddr) after TPD_G;
435 end process WRITE_SEQUENCE;
437 ------------------------------- 438 -- rd_clk and wr_clk domain 439 ------------------------------- 441 -- RAM Port A Mapping 444 portA.we <= wr_en and not(fullStatus);
445 portA.addr <= wrReg.waddr;
448 -- RAM Port B Mapping 450 portB.en <= readEnable and not(fifoStatus.empty);
451 portB.rst <= readRst;
453 portB.addr <= rdReg.raddr;
454 portB.din <= (others => '0');
475 rstb => '0',
-- Rely on rd/wr ptrs 477 doutb => portB.dout
);
479 end architecture rtl;
EMPTY_THRES_Ginteger range 1 to ( 2** 24):= 1
in addrbslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
in rstbsl :=not ( RST_POLARITY_G)
RST_ASYNC_Gboolean := false
ALTERA_RAM_Gstring := "M9K"
out doutbslv( DATA_WIDTH_G- 1 downto 0)
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
in rstsl :=not RST_POLARITY_G
PIPE_STAGES_Gnatural range 0 to 16:= 0
SYNC_STAGES_Ginteger range 3 to ( 2** 24):= 3
RST_ASYNC_Gboolean := false
in dataInslv( WIDTH_G- 1 downto 0)
out doutslv( DATA_WIDTH_G- 1 downto 0)
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
ALTERA_SYN_Gboolean := false
RELEASE_DELAY_Ginteger range 3 to positive'high:= 3
ALTERA_RAM_Gstring := "M9K"
ADDR_WIDTH_Ginteger range 2 to 48:= 4
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 4
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
out dataOutslv( WIDTH_G- 1 downto 0)
out rd_data_countslv( ADDR_WIDTH_G- 1 downto 0)
USE_DSP48_Gstring := "no"
in rstsl :=not RST_POLARITY_G
PIPE_STAGES_Gnatural range 0 to 16:= 1
ALTERA_SYN_Gboolean := false
FWFT_EN_Gboolean := false
FULL_THRES_Ginteger range 1 to ( 2** 24):= 1
in dinslv( DATA_WIDTH_G- 1 downto 0)
RST_ASYNC_Gboolean := false
out wr_data_countslv( ADDR_WIDTH_G- 1 downto 0)
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
in sDataslv( DATA_WIDTH_G- 1 downto 0)
in rstsl :=not RST_POLARITY_G
out mDataslv( DATA_WIDTH_G- 1 downto 0)
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')