1 ------------------------------------------------------------------------------- 2 -- File : AxiStreamPacketizer 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2015-09-29 5 -- Last update: 2016-04-30 6 ------------------------------------------------------------------------------- 7 -- Description: Formats an AXI-Stream for a transport link. 8 -- Sideband fields are placed into the data stream in a header. 9 -- Long frames are broken into smaller packets. (non-interleave only) 10 ------------------------------------------------------------------------------- 11 -- This file is part of 'SLAC Firmware Standard Library'. 12 -- It is subject to the license terms in the LICENSE.txt file found in the 13 -- top-level directory of this distribution and at: 14 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. 15 -- No part of 'SLAC Firmware Standard Library', including this file, 16 -- may be copied, modified, propagated, or distributed except according to 17 -- the terms contained in the LICENSE.txt file. 18 ------------------------------------------------------------------------------- 21 use ieee.std_logic_1164.
all;
22 use ieee.std_logic_unsigned.
all;
23 use ieee.std_logic_arith.
all;
43 KEEP_TDEST_G : := true);
47 -- AXI-Lite Interface for local registers 53 disableSel :
in slv(NUM_SLAVES_G-1
downto 0) := (
others => '0');
58 end entity AxiStreamPacketizerMux;
62 -- Packetizer constants 65 constant VERSION_C : slv(3 downto 0) := "0000";
67 -- Mux arbiter constants 69 constant ARB_BITS_C : := 2**DEST_SIZE_C;
71 type StateType is (ARBITRATE_S, HEADER_S, MOVE_S, TAIL_S);
73 type RegType is record 75 frameNumber : slv(11 downto 0);
76 packetNumber : slv(23 downto 0);
78 wordCount : slv(bitSize(MAX_WORD_COUNT_C)-1 downto 0);
80 tUserLast : slv(7 downto 0);
81 acks : slv(ARB_BITS_C-1 downto 0);
82 ackNum : slv(DEST_SIZE_C-1 downto 0);
84 selDest : slv(7 downto 0);
89 constant REG_INIT_C : RegType := ( 91 frameNumber => (others => '0'), 92 packetNumber => (others => '0'), 93 packetNumberWe => '0', 94 wordCount => (others => '0'), 96 tUserLast => (others => '0'), 97 acks => (others => '0'), 98 ackNum => (others => '1'), 100 selDest => (others => '0'), 102 outputAxisMaster => axiStreamMasterInit(AXIS_CONFIG_C));
104 signal r : RegType := REG_INIT_C;
105 signal rin : RegType;
107 signal packetNumberOut : slv(23 downto 0);
117 report "MAX_PACKET_BYTES_G must be a multiple of 8" severity error;
119 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 121 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 122 INPUT_PIPELINES : for i in NUM_SLAVES_G-1 downto 0 generate 136 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 138 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 151 ------------------------------------------------------------------------------------------------- 153 -- track current packet count for each tDest 154 ------------------------------------------------------------------------------------------------- 164 wea => r.packetNumberWe,
-- [in] 166 addra => r.selDest,
-- [in] 167 dina => r.packetNumber,
-- [in] 168 douta => packetNumberOut
);
-- [out] 170 ------------------------------------------------------------------------------------------------- 171 -- Accumulation sequencing, DMA ring buffer, and AXI-Lite logic 172 ------------------------------------------------------------------------------------------------- 174 variable v : RegType;
175 variable requests : slv(ARB_BITS_C-1 downto 0);
180 if (outputAxisSlave.tReady = '1') then 181 v.outputAxisMaster.tValid := '0';
184 -- input tReadys 0 by default 186 v.inputAxisSlaves(i).tReady := '0';
199 requests := (others => '0');
204 -- Don't write new packet number by default 205 v.packetNumberWe := '0';
209 -- Arbitrate between requesters 210 if r.valid = '0' then 211 arbitrate(requests, r.ackNum, v.ackNum, v.valid, v.acks);
213 -- Reset the Arbitration flag 214 -- Register the selected tDest 215 -- Go to header state 217 v.selDest := selData.tDest;
222 v.wordCount := (others => '0');
224 -- Place header on output when new data arrived and previous output clear 225 if (selData.tValid = '1' and v.outputAxisMaster.tValid = '0') then 226 v.outputAxisMaster := axiStreamMasterInit(AXIS_CONFIG_C);
228 v.outputAxisMaster.tData(3 downto 0) := VERSION_C;
229 v.outputAxisMaster.tData(15 downto 4) := r.frameNumber;
230 v.outputAxisMaster.tData(39 downto 16) := packetNumberOut;
231 v.outputAxisMaster.tData(47 downto 40) := selData.tDest(7 downto 0);
232 v.outputAxisMaster.tData(55 downto 48) := selData.tId(7 downto 0);
233 v.outputAxisMaster.tData(63 downto 56) := selData.tUser(7 downto 0);
234 axiStreamSetUserBit(AXIS_CONFIG_C, v.outputAxisMaster, SSI_SOF_C, '1', 0);
-- SOF 236 v.packetNumber := packetNumberOut + 1;
241 -- Check if clear to move data 242 if (v.outputAxisMaster.tValid = '0') then 245 v.inputAxisSlaves(conv_integer(r.ackNum)).tReady := '1';
248 v.outputAxisMaster := selData;
249 v.outputAxisMaster.tUser := (others => '0');
250 v.outputAxisMaster.tDest := (others => '0');
251 v.outputAxisMaster.tId := (others => '0');
253 -- Increment word count with each txn 254 v.wordCount := r.wordCount + 1;
256 -- Reach max packet size. Append tail. 257 if (r.wordCount = MAX_WORD_COUNT_C) then 262 if (selData.tLast = '1') then 263 -- Increment frame number, clear packetNumber 264 v.frameNumber := r.frameNumber + 1;
265 v.packetNumber := (others => '0');
266 v.state := ARBITRATE_S;
268 -- Need to either append tail to current txn or put tail on next txn (TAIL_S) 269 -- depending on tKeep 272 case (selData.tKeep) is 274 v.outputAxisMaster.tData(7 downto 0) := '1' & selData.tUser(6 downto 0);
276 v.outputAxisMaster.tData(15 downto 8) := '1' & selData.tUser(14 downto 8);
278 v.outputAxisMaster.tData(23 downto 16) := '1' & selData.tUser(22 downto 16);
280 v.outputAxisMaster.tData(31 downto 24) := '1' & selData.tUser(30 downto 24);
282 v.outputAxisMaster.tData(39 downto 32) := '1' & selData.tUser(38 downto 32);
284 v.outputAxisMaster.tData(47 downto 40) := '1' & selData.tUser(46 downto 40);
286 v.outputAxisMaster.tData(55 downto 48) := '1' & selData.tUser(54 downto 48);
288 v.outputAxisMaster.tData(63 downto 56) := '1' & selData.tUser(62 downto 56);
289 when others => --X"0FFF" or anything else 290 -- Full tkeep. Add new word for tail 293 v.tUserLast := selData.tUser(7 downto 0);
295 v.outputAxisMaster.tLast := '0';
302 -- Hold off slave side while inserting tail 303 v.inputAxisSlaves(conv_integer(r.ackNum)).tReady := '0';
305 -- Insert tail when master side is ready for it 306 if (v.outputAxisMaster.tValid = '0') then 307 v.outputAxisMaster.tValid := '1';
309 v.outputAxisMaster.tData := (others => '0');
310 v.outputAxisMaster.tData(7) := r.eof;
311 v.outputAxisMaster.tData(6 downto 0) := r.tUserLast(6 downto 0);
312 v.outputAxisMaster.tUser := (others => '0');
313 v.outputAxisMaster.tLast := '1';
314 v.eof := '0';
-- Clear EOF for next frame 315 v.tUserLast := (others => '0');
316 v.packetNumberWe := '1';
317 v.state := ARBITRATE_S;
-- Go to idle and wait for new data 322 ---------------------------------------------------------------------------------------------- 323 -- Reset and output assignment 324 ---------------------------------------------------------------------------------------------- 331 inputAxisSlaves <= v.inputAxisSlaves;
332 outputAxisMaster <= r.outputAxisMaster;
339 r <= rin after TPD_G;
343 end architecture rtl;
out mAxisMasterAxiStreamMasterType
PIPE_STAGES_Gnatural range 0 to 16:= 0
array(natural range <> ) of AxiStreamSlaveType AxiStreamSlaveArray
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')
MAX_PACKET_BYTES_Ginteger := 1440
INPUT_PIPE_STAGES_Ginteger := 0
BYTE_WR_EN_Gboolean := false
out sAxisSlavesAxiStreamSlaveArray( NUM_SLAVES_G- 1 downto 0)
TDEST_HIGH_Ginteger range 0 to 7:= 7
out sAxisSlaveAxiStreamSlaveType
in mAxisSlaveAxiStreamSlaveType
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 4
in sAxisMastersAxiStreamMasterArray( NUM_SLAVES_G- 1 downto 0)
OUTPUT_PIPE_STAGES_Ginteger := 0
KEEP_TDEST_Gboolean := true
out doutaslv( DATA_WIDTH_G- 1 downto 0)
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
in sAxisMasterAxiStreamMasterType
in disableSelslv( NUM_SLAVES_G- 1 downto 0) :=( others => '0')
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
NUM_SLAVES_Ginteger range 1 to 32:= 4
in mAxisSlaveAxiStreamSlaveType
array(natural range <> ) of AxiStreamMasterType AxiStreamMasterArray
out mAxisMasterAxiStreamMasterType
TDEST_LOW_Ginteger range 0 to 7:= 0
in rstasl :=not ( RST_POLARITY_G)
MIN_TKEEP_Gslv( 15 downto 0) := X"0001"
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16