SURF  1.0
AxiStreamPacketizer.vhd
Go to the documentation of this file.
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 -------------------------------------------------------------------------------
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 use work.SsiPkg.all;
29 
30 --! @see entity
31  --! @ingroup axi
33 
34  generic (
35  TPD_G : time := 1 ns;
36  MAX_PACKET_BYTES_G : integer := 1440; -- Must be a multiple of 8
37  MIN_TKEEP_G : slv(15 downto 0) := X"0001";
38  OUTPUT_SSI_G : boolean := true; -- SSI compliant output (SOF on tuser)
39  INPUT_PIPE_STAGES_G : integer := 0;
40  OUTPUT_PIPE_STAGES_G : integer := 0);
41 
42  port (
43  -- AXI-Lite Interface for local registers
44  axisClk : in sl;
45  axisRst : in sl;
46 
49 
52 
53 end entity AxiStreamPacketizer;
54 
55 architecture rtl of AxiStreamPacketizer is
56 
57  constant MAX_WORD_COUNT_C : integer := (MAX_PACKET_BYTES_G / 8) - 3;
58 
59  constant AXIS_CONFIG_C : AxiStreamConfigType := (
60  TSTRB_EN_C => false,
61  TDATA_BYTES_C => 8,
62  TDEST_BITS_C => 0,
63  TID_BITS_C => 0,
64  TKEEP_MODE_C => TKEEP_NORMAL_C,
65  TUSER_BITS_C => ite(OUTPUT_SSI_G, 2, 0),
66  TUSER_MODE_C => TUSER_FIRST_LAST_C);
67 
68 
69  constant VERSION_C : slv(3 downto 0) := "0000";
70 
71  type StateType is (IDLE_S, MOVE_S, TAIL_S);
72 
73  type RegType is record
74  state : StateType;
75  frameNumber : slv(11 downto 0);
76  packetNumber : slv(23 downto 0);
77  wordCount : slv(bitSize(MAX_WORD_COUNT_C)-1 downto 0);
78  eof : sl;
79  tUserLast : slv(7 downto 0);
80  inputAxisSlave : AxiStreamSlaveType;
81  outputAxisMaster : AxiStreamMasterType;
82  end record RegType;
83 
84  constant REG_INIT_C : RegType := (
85  state => IDLE_S,
86  frameNumber => (others => '0'),
87  packetNumber => (others => '0'),
88  wordCount => (others => '0'),
89  eof => '0',
90  tUserLast => (others => '0'),
91  inputAxisSlave => AXI_STREAM_SLAVE_INIT_C,
92  outputAxisMaster => axiStreamMasterInit(AXIS_CONFIG_C));
93 
94  signal r : RegType := REG_INIT_C;
95  signal rin : RegType;
96 
97  signal inputAxisMaster : AxiStreamMasterType;
98  signal inputAxisSlave : AxiStreamSlaveType;
99  signal outputAxisMaster : AxiStreamMasterType;
100  signal outputAxisSlave : AxiStreamSlaveType;
101 
102 begin
103 
104  assert ((MAX_PACKET_BYTES_G rem 8) = 0)
105  report "MAX_PACKET_BYTES_G must be a multiple of 8" severity error;
106 
107  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
108  -- Input pipeline
109  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
110  U_AxiStreamPipeline_Input : entity work.AxiStreamPipeline
111  generic map (
112  TPD_G => TPD_G,
114  port map (
115  axisClk => axisClk, -- [in]
116  axisRst => axisRst, -- [in]
117  sAxisMaster => sAxisMaster, -- [in]
118  sAxisSlave => sAxisSlave, -- [out]
119  mAxisMaster => inputAxisMaster, -- [out]
120  mAxisSlave => inputAxisSlave); -- [in]
121 
122  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
123  -- Output pipeline
124  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
125  U_AxiStreamPipeline_Output : entity work.AxiStreamPipeline
126  generic map (
127  TPD_G => TPD_G,
129  port map (
130  axisClk => axisClk, -- [in]
131  axisRst => axisRst, -- [in]
132  sAxisMaster => outputAxisMaster, -- [in]
133  sAxisSlave => outputAxisSlave, -- [out]
134  mAxisMaster => mAxisMaster, -- [out]
135  mAxisSlave => mAxisSlave); -- [in]
136 
137  -------------------------------------------------------------------------------------------------
138  -- Accumulation sequencing, DMA ring buffer, and AXI-Lite logic
139  -------------------------------------------------------------------------------------------------
140  comb : process (axisRst, inputAxisMaster, outputAxisSlave, r) is
141  variable v : RegType;
142 
143  begin
144  v := r;
145 
146  if (outputAxisSlave.tReady = '1') then
147  v.outputAxisMaster.tValid := '0';
148  end if;
149 
150  case r.state is
151  when IDLE_S =>
152  v.wordCount := (others => '0');
153 
154  -- Will need to insert header, so hold off tReady
155  v.inputAxisSlave.tReady := '0';
156 
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);
160  v.outputAxisMaster.tValid := inputAxisMaster.tValid;
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);
167  if (OUTPUT_SSI_G) then
168  axiStreamSetUserBit(AXIS_CONFIG_C, v.outputAxisMaster, SSI_SOF_C, '1', 0); -- SOF
169  end if;
170  v.state := MOVE_S;
171  v.packetNumber := r.packetNumber + 1;
172  end if;
173 
174  when MOVE_S =>
175  v.inputAxisSlave.tReady := '0'; --outputAxisSlave.tReady;
176 
177  if (inputAxisMaster.tValid = '1' and v.outputAxisMaster.tValid = '0') then
178  -- Send data through
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');
184 
185  -- Increment word count with each txn
186  v.wordCount := r.wordCount + 1;
187 
188  -- Reach max packet size. Append tail.
189  if (r.wordCount = MAX_WORD_COUNT_C) then
190  v.state := TAIL_S;
191  end if;
192 
193  -- End of frame
194  if (inputAxisMaster.tLast = '1') then
195  -- Increment frame number, clear packetNumber
196  v.frameNumber := r.frameNumber + 1;
197  v.packetNumber := (others => '0');
198  v.state := IDLE_S;
199 
200  -- Need to either append tail to current txn or put tail on next txn (TAIL_S)
201  -- depending on tKeep
202  v.outputAxisMaster.tKeep := MIN_TKEEP_G or (inputAxisMaster.tKeep(14 downto 0) & '1');
203 
204  case (inputAxisMaster.tKeep) is
205  when X"0000" =>
206  v.outputAxisMaster.tData(7 downto 0) := '1' & inputAxisMaster.tUser(6 downto 0);
207  when X"0001" =>
208  v.outputAxisMaster.tData(15 downto 8) := '1' & inputAxisMaster.tUser(14 downto 8);
209  when X"0003" =>
210  v.outputAxisMaster.tData(23 downto 16) := '1' & inputAxisMaster.tUser(22 downto 16);
211  when X"0007" =>
212  v.outputAxisMaster.tData(31 downto 24) := '1' & inputAxisMaster.tUser(30 downto 24);
213  when X"000F" =>
214  v.outputAxisMaster.tData(39 downto 32) := '1' & inputAxisMaster.tUser(38 downto 32);
215  when X"001F" =>
216  v.outputAxisMaster.tData(47 downto 40) := '1' & inputAxisMaster.tUser(46 downto 40);
217  when X"003F" =>
218  v.outputAxisMaster.tData(55 downto 48) := '1' & inputAxisMaster.tUser(54 downto 48);
219  when X"007F" =>
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;
224  v.state := TAIL_S;
225  v.tUserLast := inputAxisMaster.tUser(7 downto 0);
226  v.eof := '1';
227  v.outputAxisMaster.tLast := '0';
228  end case;
229 
230  end if;
231  end if;
232 
233  when TAIL_S =>
234  -- Hold off slave side while inserting tail
235  v.inputAxisSlave.tReady := '0';
236 
237  -- Insert tail when master side is ready for it
238  if (v.outputAxisMaster.tValid = '0') then
239  v.outputAxisMaster.tValid := '1';
240  v.outputAxisMaster.tKeep := MIN_TKEEP_G; --X"0001";
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
249  end if;
250 
251  end case;
252 
253  v.outputAxisMaster.tStrb := v.outputAxisMaster.tKeep;
254 
255  ----------------------------------------------------------------------------------------------
256  -- Reset and output assignment
257  ----------------------------------------------------------------------------------------------
258  if (axisRst = '1') then
259  v := REG_INIT_C;
260  end if;
261 
262  rin <= v;
263 
264  inputAxisSlave <= v.inputAxisSlave;
265  outputAxisMaster <= r.outputAxisMaster;
266 
267  end process comb;
268 
269  seq : process (axisClk) is
270  begin
271  if (rising_edge(axisClk)) then
272  r <= rin after TPD_G;
273  end if;
274  end process seq;
275 
276 end architecture rtl;
277 
slv( 7 downto 0) tId
PIPE_STAGES_Gnatural range 0 to 16:= 0
natural range 0 to 8 TDEST_BITS_C
_library_ ieeeieee
MIN_TKEEP_Gslv( 15 downto 0) := X"0001"
out sAxisSlaveAxiStreamSlaveType
std_logic sl
Definition: StdRtlPkg.vhd:28
integer := 1 SSI_SOF_C
Definition: SsiPkg.vhd:31
MAX_PACKET_BYTES_Ginteger := 1440
OUTPUT_SSI_Gboolean := true
out sAxisSlaveAxiStreamSlaveType
slv( 15 downto 0) tStrb
slv( 15 downto 0) tKeep
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
slv( 127 downto 0) tData
in mAxisSlaveAxiStreamSlaveType
in sAxisMasterAxiStreamMasterType
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
boolean TSTRB_EN_C
TUserModeType TUSER_MODE_C
slv( 127 downto 0) tUser
natural range 0 to 8 TUSER_BITS_C
out mAxisMasterAxiStreamMasterType
OUTPUT_PIPE_STAGES_Ginteger := 0
slv( 7 downto 0) tDest
sl eof
Definition: SsiPkg.vhd:73
std_logic_vector slv
Definition: StdRtlPkg.vhd:29