1 ------------------------------------------------------------------------------- 2 -- File : AxiStreamPacketizer 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2015-09-29 5 -- Last update: 2016-08-30 6 ------------------------------------------------------------------------------- 7 -- Description: AXI stream DePacketerizer Module (non-interleave only) 8 -- Formats an AXI-Stream for a transport link. 9 -- Sideband fields are placed into the data stream in a header. 10 -- Long frames are broken into smaller packets. 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 ------------------------------------------------------------------------------- 22 use ieee.std_logic_1164.
all;
23 use ieee.std_logic_unsigned.
all;
24 use ieee.std_logic_arith.
all;
43 -- AXI-Lite Interface for local registers 53 end entity AxiStreamPacketizer;
69 constant VERSION_C : slv(3 downto 0) := "0000";
71 type StateType is (IDLE_S, MOVE_S, TAIL_S);
73 type RegType is record 75 frameNumber : slv(11 downto 0);
76 packetNumber : slv(23 downto 0);
77 wordCount : slv(bitSize(MAX_WORD_COUNT_C)-1 downto 0);
79 tUserLast : slv(7 downto 0);
84 constant REG_INIT_C : RegType := ( 86 frameNumber => (others => '0'), 87 packetNumber => (others => '0'), 88 wordCount => (others => '0'), 90 tUserLast => (others => '0'), 92 outputAxisMaster => axiStreamMasterInit(AXIS_CONFIG_C));
94 signal r : RegType := REG_INIT_C;
105 report "MAX_PACKET_BYTES_G must be a multiple of 8" severity error;
107 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 109 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 122 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 124 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 137 ------------------------------------------------------------------------------------------------- 138 -- Accumulation sequencing, DMA ring buffer, and AXI-Lite logic 139 ------------------------------------------------------------------------------------------------- 140 comb :
process (
axisRst, inputAxisMaster, outputAxisSlave, r)
is 141 variable v : RegType;
146 if (outputAxisSlave.tReady = '1') then 147 v.outputAxisMaster.tValid := '0';
152 v.wordCount := (others => '0');
154 -- Will need to insert header, so hold off tReady 155 v.inputAxisSlave.tReady := '0';
157 -- Place header on output when new data arrived and previous output clear 158 if (inputAxisMaster.tValid = '1' and v.outputAxisMaster.tValid = '0') then 159 v.outputAxisMaster := axiStreamMasterInit(AXIS_CONFIG_C);
161 v.outputAxisMaster.tData(3 downto 0) := VERSION_C;
162 v.outputAxisMaster.tData(15 downto 4) := r.frameNumber;
163 v.outputAxisMaster.tData(39 downto 16) := r.packetNumber;
164 v.outputAxisMaster.tData(47 downto 40) := inputAxisMaster.tDest(7 downto 0);
165 v.outputAxisMaster.tData(55 downto 48) := inputAxisMaster.tId(7 downto 0);
166 v.outputAxisMaster.tData(63 downto 56) := inputAxisMaster.tUser(7 downto 0);
168 axiStreamSetUserBit(AXIS_CONFIG_C, v.outputAxisMaster, SSI_SOF_C, '1', 0);
-- SOF 171 v.packetNumber := r.packetNumber + 1;
175 v.inputAxisSlave.tReady := '0';
--outputAxisSlave.tReady; 177 if (inputAxisMaster.tValid = '1' and v.outputAxisMaster.tValid = '0') then 179 v.inputAxisSlave.tReady := '1';
180 v.outputAxisMaster := inputAxisMaster;
181 v.outputAxisMaster.tUser := (others => '0');
182 v.outputAxisMaster.tDest := (others => '0');
183 v.outputAxisMaster.tId := (others => '0');
185 -- Increment word count with each txn 186 v.wordCount := r.wordCount + 1;
188 -- Reach max packet size. Append tail. 189 if (r.wordCount = MAX_WORD_COUNT_C) then 194 if (inputAxisMaster.tLast = '1') then 195 -- Increment frame number, clear packetNumber 196 v.frameNumber := r.frameNumber + 1;
197 v.packetNumber := (others => '0');
200 -- Need to either append tail to current txn or put tail on next txn (TAIL_S) 201 -- depending on tKeep 204 case (inputAxisMaster.tKeep) is 206 v.outputAxisMaster.tData(7 downto 0) := '1' & inputAxisMaster.tUser(6 downto 0);
208 v.outputAxisMaster.tData(15 downto 8) := '1' & inputAxisMaster.tUser(14 downto 8);
210 v.outputAxisMaster.tData(23 downto 16) := '1' & inputAxisMaster.tUser(22 downto 16);
212 v.outputAxisMaster.tData(31 downto 24) := '1' & inputAxisMaster.tUser(30 downto 24);
214 v.outputAxisMaster.tData(39 downto 32) := '1' & inputAxisMaster.tUser(38 downto 32);
216 v.outputAxisMaster.tData(47 downto 40) := '1' & inputAxisMaster.tUser(46 downto 40);
218 v.outputAxisMaster.tData(55 downto 48) := '1' & inputAxisMaster.tUser(54 downto 48);
220 v.outputAxisMaster.tData(63 downto 56) := '1' & inputAxisMaster.tUser(62 downto 56);
221 when others => --X"0FFF" or anything else 222 -- Full tkeep. Add new word for tail 223 v.outputAxisMaster.tKeep := inputAxisMaster.tKeep;
225 v.tUserLast := inputAxisMaster.tUser(7 downto 0);
227 v.outputAxisMaster.tLast := '0';
234 -- Hold off slave side while inserting tail 235 v.inputAxisSlave.tReady := '0';
237 -- Insert tail when master side is ready for it 238 if (v.outputAxisMaster.tValid = '0') then 239 v.outputAxisMaster.tValid := '1';
241 v.outputAxisMaster.tData := (others => '0');
242 v.outputAxisMaster.tData(7) := r.eof;
243 v.outputAxisMaster.tData(6 downto 0) := r.tUserLast(6 downto 0);
244 v.outputAxisMaster.tUser := (others => '0');
245 v.outputAxisMaster.tLast := '1';
246 v.eof := '0';
-- Clear EOF for next frame 247 v.tUserLast := (others => '0');
248 v.state := IDLE_S;
-- Go to idle and wait for new data 253 v.outputAxisMaster.tStrb := v.outputAxisMaster.tKeep;
255 ---------------------------------------------------------------------------------------------- 256 -- Reset and output assignment 257 ---------------------------------------------------------------------------------------------- 264 inputAxisSlave <= v.inputAxisSlave;
265 outputAxisMaster <= r.outputAxisMaster;
272 r <= rin after TPD_G;
276 end architecture rtl;
PIPE_STAGES_Gnatural range 0 to 16:= 0
natural range 0 to 8 TDEST_BITS_C
MIN_TKEEP_Gslv( 15 downto 0) := X"0001"
out sAxisSlaveAxiStreamSlaveType
MAX_PACKET_BYTES_Ginteger := 1440
OUTPUT_SSI_Gboolean := true
out sAxisSlaveAxiStreamSlaveType
natural range 1 to 16 TDATA_BYTES_C
in mAxisSlaveAxiStreamSlaveType
in sAxisMasterAxiStreamMasterType
TkeepModeType TKEEP_MODE_C
out mAxisMasterAxiStreamMasterType
natural range 0 to 8 TID_BITS_C
in mAxisSlaveAxiStreamSlaveType
in sAxisMasterAxiStreamMasterType
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
TUserModeType TUSER_MODE_C
natural range 0 to 8 TUSER_BITS_C
out mAxisMasterAxiStreamMasterType
OUTPUT_PIPE_STAGES_Ginteger := 0
INPUT_PIPE_STAGES_Ginteger := 0