SURF  1.0
AxiStreamFifoV2.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AxiStreamFifoV2.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2016-09-02
5 -- Last update: 2016-11-30
6 -------------------------------------------------------------------------------
7 -- Description:
8 -- Block to serve as an async FIFO for AXI Streams. This block also allows the
9 -- bus to be compress/expanded, allowing different standard sizes on each side
10 -- of the FIFO. Re-sizing is always little endian.
11 -------------------------------------------------------------------------------
12 -- This file is part of 'SLAC Firmware Standard Library'.
13 -- It is subject to the license terms in the LICENSE.txt file found in the
14 -- top-level directory of this distribution and at:
15 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
16 -- No part of 'SLAC Firmware Standard Library', including this file,
17 -- may be copied, modified, propagated, or distributed except according to
18 -- the terms contained in the LICENSE.txt file.
19 -------------------------------------------------------------------------------
20 
21 library ieee;
22 use ieee.std_logic_1164.all;
23 use ieee.std_logic_unsigned.all;
24 use ieee.std_logic_arith.all;
25 
26 use work.StdRtlPkg.all;
27 use work.AxiStreamPkg.all;
28 
29 --! @see entity
30  --! @ingroup axi
31 entity AxiStreamFifoV2 is
32  generic (
33 
34  -- General Configurations
35  TPD_G : time := 1 ns;
36  INT_PIPE_STAGES_G : natural range 0 to 16 := 0; -- Internal FIFO setting
37  PIPE_STAGES_G : natural range 0 to 16 := 1;
38  SLAVE_READY_EN_G : boolean := true;
39 
40  -- Valid threshold should always be 1 when using interleaved tdest
41  VALID_THOLD_G : integer range 0 to (2**24) := 1; -- =1 = normal operation
42  -- =0 = only when frame ready
43  -- >1 = only when frame ready or # entries
44  VALID_BURST_MODE_G : boolean := false; -- only used in VALID_THOLD_G>1
45  -- FIFO configurations
46  BRAM_EN_G : boolean := true;
47  XIL_DEVICE_G : string := "7SERIES";
48  USE_BUILT_IN_G : boolean := false;
49  GEN_SYNC_FIFO_G : boolean := false;
50  ALTERA_SYN_G : boolean := false;
51  ALTERA_RAM_G : string := "M9K";
52  CASCADE_SIZE_G : integer range 1 to (2**24) := 1;
53  FIFO_ADDR_WIDTH_G : integer range 4 to 48 := 9;
54  FIFO_FIXED_THRESH_G : boolean := true;
55  FIFO_PAUSE_THRESH_G : integer range 1 to (2**24) := 1;
56 
57  -- Internal FIFO width select, "WIDE", "NARROW" or "CUSTOM"
58  -- WIDE uses wider of slave / master. NARROW uses narrower.
59  -- CUSOTM uses passed FIFO_DATA_WIDTH_G
60  INT_WIDTH_SELECT_G : string := "WIDE";
61  INT_DATA_WIDTH_G : natural range 1 to 16 := 16;
62 
63  -- If VALID_THOLD_G /=1, FIFO that stores on tLast txns can be smaller.
64  -- Set to 0 for same size as primary fifo (default)
65  -- Set >4 for custom size.
66  -- Use at own risk. Overflow of tLast fifo is not checked
67  LAST_FIFO_ADDR_WIDTH_G : integer range 0 to 48 := 0;
68 
69  -- Index = 0 is output, index = n is input
70  CASCADE_PAUSE_SEL_G : integer range 0 to (2**24) := 0;
71 
72  -- AXI Stream Port Configurations
75  );
76  port (
77 
78  -- Slave Port
79  sAxisClk : in sl;
80  sAxisRst : in sl;
84 
85  -- FIFO status & config , synchronous to sAxisClk, be carefull when using with
86  -- output pipeline stages
87  fifoPauseThresh : in slv(FIFO_ADDR_WIDTH_G-1 downto 0) := (others => '1');
88 
89  -- Master Port
90  mAxisClk : in sl;
91  mAxisRst : in sl;
94  mTLastTUser : out slv(7 downto 0)); -- when VALID_THOLD_G /= 1, used to look ahead at tLast's tUser
95 end AxiStreamFifoV2;
96 
97 architecture rtl of AxiStreamFifoV2 is
98 
99  constant LAST_FIFO_ADDR_WIDTH_C : integer range 4 to 48 :=
101 
102  -- Generate configuration for FIFO
103  constant FIFO_CONFIG_C : AxiStreamConfigType := (
104 
105  -- Enable strobe only if used on both sides
107 
108  -- Determine FIFO data bytes
110  ite(INT_WIDTH_SELECT_G = "WIDE",
111 
112  -- Using wider of the two
115 
116  -- Use narrower of the two
119 
120  -- Use the lesser of the two DEST widths
123 
124  -- Use the lesser of the two ID widths
127 
128  -- Use the lesser of the two USER widths
131 
132  -- Use slave settings for tkeep and tuser mode
135 
136  constant FIFO_BITS_C : integer := getSlvSize(FIFO_CONFIG_C);
137 
138  constant FIFO_USER_BITS_C : integer := FIFO_CONFIG_C.TUSER_BITS_C;
139 
140  ----------------
141  -- FIFO Signals
142  ----------------
143 
144  signal fifoWriteMaster : AxiStreamMasterType;
145  signal fifoWriteSlave : AxiStreamSlaveType;
146  signal fifoReadMaster : AxiStreamMasterType;
147  signal fifoReadSlave : AxiStreamSlaveType;
148  signal fifoDin : slv(FIFO_BITS_C-1 downto 0);
149  signal fifoWrite : sl;
150  signal fifoWriteLast : sl;
151  signal fifoWriteUser : slv(maximum(FIFO_USER_BITS_C-1, 0) downto 0);
152  signal fifoWrCount : slv(FIFO_ADDR_WIDTH_G-1 downto 0);
153  signal fifoRdCount : slv(FIFO_ADDR_WIDTH_G-1 downto 0);
154  signal fifoAFull : sl;
155  signal fifoReady : sl;
156  signal fifoPFull : sl;
157  signal fifoPFullVec : slv(CASCADE_SIZE_G-1 downto 0);
158  signal fifoDout : slv(FIFO_BITS_C-1 downto 0);
159  signal fifoRead : sl;
160  signal fifoReadLast : sl;
161  signal fifoReadUser : slv(maximum(FIFO_USER_BITS_C-1, 0) downto 0);
162  signal fifoValidInt : sl;
163  signal fifoValid : sl;
164  signal fifoValidLast : sl;
165  signal fifoInFrame : sl;
166 
167  signal burstEn : sl;
168  signal burstLast : sl;
169  signal burstCnt : natural range 0 to VALID_THOLD_G := 0;
170 
171  ---------------
172  -- Sync Signals
173  ---------------
174  signal axisMaster : AxiStreamMasterType;
175  signal axisSlave : AxiStreamSlaveType;
176 
177 begin
178 
179  -- Cant use tkeep_fixed on master side when resizing or if not on slave side
180  assert (not (MASTER_AXI_CONFIG_G.TKEEP_MODE_C = TKEEP_FIXED_C and
181  SLAVE_AXI_CONFIG_G.TKEEP_MODE_C /= TKEEP_FIXED_C))
182  report "AxiStreamFifoV2: Can't have TKEEP_MODE = TKEEP_FIXED on master side if not on slave side"
183  severity error;
184 
185  -------------------------
186  -- Slave Resize
187  -------------------------
188  U_SlaveResize : entity work.AxiStreamResize
189  generic map (
190  TPD_G => TPD_G,
193  MASTER_AXI_CONFIG_G => FIFO_CONFIG_C)
194  port map (
195  axisClk => sAxisClk,
196  axisRst => sAxisRst,
199  mAxisMaster => fifoWriteMaster,
200  mAxisSlave => fifoWriteSlave);
201 
202  -------------------------
203  -- FIFO
204  -------------------------
205 
206  -- Pause generation
207  process (fifoPFullVec, sAxisClk) is
208  begin
209  if FIFO_FIXED_THRESH_G then
210  sAxisCtrl.pause <= fifoPFullVec(CASCADE_PAUSE_SEL_G) after TPD_G;
211  elsif (rising_edge(sAxisClk)) then
212  if sAxisRst = '1' or fifoWrCount >= fifoPauseThresh then
213  sAxisCtrl.pause <= '1' after TPD_G;
214  else
215  sAxisCtrl.pause <= '0' after TPD_G;
216  end if;
217  end if;
218  end process;
219 
220  -- Is ready enabled?
221  fifoReady <= (not fifoAFull) when SLAVE_READY_EN_G else '1';
222 
223  -- Map bits
224  fifoDin <= toSlv(fifoWriteMaster, FIFO_CONFIG_C);
225  fifoWrite <= fifoWriteMaster.tValid and fifoReady;
226  fifoWriteLast <= fifoWriteMaster.tValid and fifoReady and fifoWriteMaster.tLast;
227  fifoWriteUser <= ite(FIFO_USER_BITS_C > 0,
228  resize(axiStreamGetUserField(FIFO_CONFIG_C, fifoWriteMaster, -1), FIFO_USER_BITS_C),
229  "0");
230 
231  fifoWriteSlave.tReady <= fifoReady;
232 
233  U_Fifo : entity work.FifoCascade
234  generic map (
235  TPD_G => TPD_G,
237  LAST_STAGE_ASYNC_G => true,
239  RST_POLARITY_G => '1',
240  RST_ASYNC_G => false,
242  BRAM_EN_G => BRAM_EN_G,
243  FWFT_EN_G => true,
244  USE_DSP48_G => "no",
249  SYNC_STAGES_G => 3,
250  DATA_WIDTH_G => FIFO_BITS_C,
252  INIT_G => "0",
254  EMPTY_THRES_G => 1)
255  port map (
256  rst => sAxisRst,
257  wr_clk => sAxisClk,
258  wr_en => fifoWrite,
259  din => fifoDin,
260  wr_data_count => fifoWrCount,
261  overflow => sAxisCtrl.overflow,
262  prog_full => fifoPFull,
263  progFullVec => fifoPFullVec,
264  almost_full => fifoAFull,
265  rd_clk => mAxisClk,
266  rd_en => fifoRead,
267  dout => fifoDout,
268  rd_data_count => fifoRdCount,
269  valid => fifoValidInt);
270 
271  U_LastFifoEnGen : if VALID_THOLD_G /= 1 generate
272 
273  U_LastFifo : entity work.FifoCascade
274  generic map (
275  TPD_G => TPD_G,
277  LAST_STAGE_ASYNC_G => true,
279  RST_POLARITY_G => '1',
280  RST_ASYNC_G => false,
282  BRAM_EN_G => false,
283  FWFT_EN_G => true,
284  USE_DSP48_G => "no",
287  USE_BUILT_IN_G => false,
289  SYNC_STAGES_G => 3,
290  DATA_WIDTH_G => maximum(FIFO_USER_BITS_C, 1),
291  ADDR_WIDTH_G => LAST_FIFO_ADDR_WIDTH_C,
292  INIT_G => "0",
293  FULL_THRES_G => 1,
294  EMPTY_THRES_G => 1)
295  port map (
296  rst => sAxisRst,
297  wr_clk => sAxisClk,
298  wr_en => fifoWriteLast,
299  din => fifoWriteUser,
300  rd_clk => mAxisClk,
301  rd_en => fifoReadLast,
302  dout => fifoReadUser,
303  valid => fifoValidLast);
304 
305  U_PreFillMode : if ((VALID_BURST_MODE_G = false) or (VALID_THOLD_G = 0)) generate
306 
307  process (mAxisClk) is
308  begin
309  if (rising_edge(mAxisClk)) then
310 
311  -- Stop output if fifo valid goes away, wait until another block is ready
312  if mAxisRst = '1' or fifoReadLast = '1' or fifoValidInt = '0' then
313  fifoInFrame <= '0' after TPD_G;
314 
315  -- Start output when a block or end of frame is available
316  elsif fifoValidLast = '1' or (VALID_THOLD_G /= 0 and fifoRdCount >= VALID_THOLD_G) then
317  fifoInFrame <= '1' after TPD_G;
318  end if;
319  end if;
320  end process;
321 
322  end generate;
323 
324  U_BurstMode : if ((VALID_BURST_MODE_G = true) and (VALID_THOLD_G /= 0)) generate
325 
326  process (mAxisClk) is
327  begin
328  if (rising_edge(mAxisClk)) then
329  if (mAxisRst = '1') or (fifoReadLast = '1') then
330  -- Reset the flags
331  fifoInFrame <= '0' after TPD_G;
332  burstEn <= '0' after TPD_G;
333  burstLast <= '0' after TPD_G;
334  else
335  -- Check if for burst mode
336  if (burstEn = '1') and (burstLast = '0') and (fifoRead = '1') then
337  -- Increment the counter
338  burstCnt <= burstCnt + 1 after TPD_G;
339  -- Check the counter
340  if burstCnt = (VALID_THOLD_G-1) then
341  -- Reset the flags
342  fifoInFrame <= '0' after TPD_G;
343  burstEn <= '0' after TPD_G;
344  end if;
345  end if;
346  if (fifoValidLast = '1') or ((fifoRdCount >= VALID_THOLD_G) and (burstEn = '0')) then
347  -- Set the flags
348  burstEn <= '1' after TPD_G;
349  burstLast <= fifoValidLast after TPD_G;
350  fifoInFrame <= '1' after TPD_G;
351  -- Reset the counter
352  burstCnt <= 0 after TPD_G;
353  end if;
354  end if;
355  end if;
356  end process;
357 
358  end generate;
359 
360  fifoValid <= fifoValidInt and fifoInFrame;
361 
362  end generate;
363 
364  U_LastFifoDisGen : if VALID_THOLD_G = 1 generate
365  fifoValidLast <= '0';
366  fifoInFrame <= '0';
367  fifoReadUser <= (others => '0');
368  fifoValid <= fifoValidInt;
369  end generate;
370 
371  mTLastTUser <= resize(fifoReadUser, 8);
372 
373  -- Map output Signals
374  fifoReadMaster <= toAxiStreamMaster (fifoDout, fifoValid, FIFO_CONFIG_C);
375 
376  fifoRead <= fifoReadSlave.tReady and fifoValid;
377  fifoReadLast <= fifoReadSlave.tReady and fifoValid and fifoReadMaster.tLast;
378 
379  -------------------------
380  -- Master Resize
381  -------------------------
382  U_MasterResize : entity work.AxiStreamResize
383  generic map (
384  TPD_G => TPD_G,
385  READY_EN_G => true,
386  SLAVE_AXI_CONFIG_G => FIFO_CONFIG_C,
388  port map (
389  axisClk => mAxisClk,
390  axisRst => mAxisRst,
391  sAxisMaster => fifoReadMaster,
392  sAxisSlave => fifoReadSlave,
393  mAxisMaster => axisMaster,
394  mAxisSlave => axisSlave);
395 
396  -------------------------
397  -- Idle Generation
398  -------------------------
399  -- Synchronize master side tvalid back to slave side ctrl.idle
400  -- This is a total hack
401  Synchronizer_1 : entity work.Synchronizer
402  generic map (
403  TPD_G => TPD_G,
404  OUT_POLARITY_G => '0') -- invert
405  port map (
406  clk => sAxisClk,
407  rst => sAxisRst,
408  dataIn => axisMaster.tValid,
409  dataOut => sAxisCtrl.idle);
410 
411  -------------------------
412  -- Pipeline Logic
413  -------------------------
414 
415  U_Pipe : entity work.AxiStreamPipeline
416  generic map (
417  TPD_G => TPD_G,
419  port map (
420  -- Clock and Reset
421  axisClk => mAxisClk,
422  axisRst => mAxisRst,
423  -- Slave Port
424  sAxisMaster => axisMaster,
425  sAxisSlave => axisSlave,
426  -- Master Port
429 
430 end rtl;
431 
out almost_fullsl
Definition: FifoCascade.vhd:59
ALTERA_RAM_Gstring := "M9K"
Definition: FifoCascade.vhd:38
out validsl
Definition: FifoCascade.vhd:68
out progFullVecslv( CASCADE_SIZE_G- 1 downto 0)
Definition: FifoCascade.vhd:62
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
PIPE_STAGES_Gnatural range 0 to 16:= 0
natural range 0 to 8 TDEST_BITS_C
out doutslv( DATA_WIDTH_G- 1 downto 0)
Definition: FifoCascade.vhd:66
out sAxisCtrlAxiStreamCtrlType
ALTERA_RAM_Gstring := "M9K"
XIL_DEVICE_Gstring := "7SERIES"
Definition: FifoCascade.vhd:40
RST_ASYNC_Gboolean := false
Definition: FifoCascade.vhd:32
PIPE_STAGES_Gnatural range 0 to 16:= 1
INIT_Gslv := "0"
Definition: FifoCascade.vhd:45
std_logic sl
Definition: StdRtlPkg.vhd:28
in rstsl :=not RST_POLARITY_G
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
BRAM_EN_Gboolean := true
Definition: FifoCascade.vhd:34
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
in dinslv( DATA_WIDTH_G- 1 downto 0)
Definition: FifoCascade.vhd:54
out sAxisSlaveAxiStreamSlaveType
SLAVE_READY_EN_Gboolean := true
FIFO_FIXED_THRESH_Gboolean := true
natural range 1 to 16 TDATA_BYTES_C
in mAxisSlaveAxiStreamSlaveType
in rd_clksl
Definition: FifoCascade.vhd:64
out prog_fullsl
Definition: FifoCascade.vhd:58
INT_DATA_WIDTH_Gnatural range 1 to 16:= 16
PIPE_STAGES_Gnatural range 0 to 16:= 0
Definition: FifoCascade.vhd:42
EMPTY_THRES_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoCascade.vhd:47
GEN_SYNC_FIFO_Gboolean := false
ALTERA_SYN_Gboolean := false
Definition: FifoCascade.vhd:37
TkeepModeType TKEEP_MODE_C
XIL_DEVICE_Gstring := "7SERIES"
out dataOutsl
in rd_ensl := '0'
Definition: FifoCascade.vhd:65
natural range 0 to 8 TID_BITS_C
in rstsl := '0'
Definition: FifoCascade.vhd:50
INT_WIDTH_SELECT_Gstring := "WIDE"
in wr_clksl
Definition: FifoCascade.vhd:52
out overflowsl
Definition: FifoCascade.vhd:57
out mAxisMasterAxiStreamMasterType
FULL_THRES_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoCascade.vhd:46
INT_PIPE_STAGES_Gnatural range 0 to 16:= 0
in sAxisMasterAxiStreamMasterType
SYNC_STAGES_Ginteger range 3 to ( 2** 24):= 3
Definition: FifoCascade.vhd:41
BRAM_EN_Gboolean := true
in mAxisSlaveAxiStreamSlaveType
boolean TSTRB_EN_C
in sAxisMasterAxiStreamMasterType
TPD_Gtime := 1 ns
TUserModeType TUSER_MODE_C
in wr_ensl := '0'
Definition: FifoCascade.vhd:53
TPD_Gtime := 1 ns
TPD_Gtime := 1 ns
OUT_POLARITY_Gsl := '1'
natural range 0 to 8 TUSER_BITS_C
out mAxisMasterAxiStreamMasterType
out sAxisSlaveAxiStreamSlaveType
ALTERA_SYN_Gboolean := false
GEN_SYNC_FIFO_Gboolean := false
Definition: FifoCascade.vhd:33
READY_EN_Gboolean := true
VALID_BURST_MODE_Gboolean := false
_library_ ieeeieee
AxiStreamConfigType :=(TSTRB_EN_C => false,TDATA_BYTES_C => 16,TDEST_BITS_C => 4,TID_BITS_C => 0,TKEEP_MODE_C => TKEEP_NORMAL_C,TUSER_BITS_C => 4,TUSER_MODE_C => TUSER_NORMAL_C) AXI_STREAM_CONFIG_INIT_C
TPD_Gtime := 1 ns
Definition: FifoCascade.vhd:28
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
LAST_FIFO_ADDR_WIDTH_Ginteger range 0 to 48:= 0
out mTLastTUserslv( 7 downto 0)
in sAxisMasterAxiStreamMasterType
USE_DSP48_Gstring := "no"
Definition: FifoCascade.vhd:36
LAST_STAGE_ASYNC_Gboolean := true
Definition: FifoCascade.vhd:30
out mAxisMasterAxiStreamMasterType
ADDR_WIDTH_Ginteger range 4 to 48:= 4
Definition: FifoCascade.vhd:44
USE_BUILT_IN_Gboolean := false
Definition: FifoCascade.vhd:39
FWFT_EN_Gboolean := false
Definition: FifoCascade.vhd:35
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
Definition: FifoCascade.vhd:43
in fifoPauseThreshslv( FIFO_ADDR_WIDTH_G- 1 downto 0) :=( others => '1')
in mAxisSlaveAxiStreamSlaveType
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
USE_BUILT_IN_Gboolean := false
FIFO_PAUSE_THRESH_Ginteger range 1 to ( 2** 24):= 1
VALID_THOLD_Ginteger range 0 to ( 2** 24):= 1
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoCascade.vhd:29
out sAxisSlaveAxiStreamSlaveType
out wr_data_countslv( ADDR_WIDTH_G- 1 downto 0)
Definition: FifoCascade.vhd:55
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
CASCADE_PAUSE_SEL_Ginteger range 0 to ( 2** 24):= 0
RST_POLARITY_Gsl := '1'
Definition: FifoCascade.vhd:31
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
out rd_data_countslv( ADDR_WIDTH_G- 1 downto 0)
Definition: FifoCascade.vhd:67