SURF  1.0
AxiStreamDepacketizer.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AxiStreamDepacketizer
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2015-09-29
5 -- Last update: 2016-07-13
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  INPUT_PIPE_STAGES_G : integer := 0;
37  OUTPUT_PIPE_STAGES_G : integer := 0);
38 
39  port (
40  -- AXI-Lite Interface for local registers
41  axisClk : in sl;
42  axisRst : in sl;
43 
44  restart : in sl := '0'; -- Reset the expected frame number back to 0
45 
48 
51 
52 end entity AxiStreamDepacketizer;
53 
54 architecture rtl of AxiStreamDepacketizer is
55 
56  constant AXIS_CONFIG_C : AxiStreamConfigType := (
57  TSTRB_EN_C => false,
58  TDATA_BYTES_C => 8,
59  TDEST_BITS_C => 8,
60  TID_BITS_C => 8,
61  TKEEP_MODE_C => TKEEP_NORMAL_C,
62  TUSER_BITS_C => 8,
63  TUSER_MODE_C => TUSER_FIRST_LAST_C);
64 
65 
66  constant VERSION_C : slv(3 downto 0) := "0000";
67 
68  type StateType is (HEADER_S, BLEED_S, MOVE_S, DONE_S);
69 
70  type RegType is record
71  state : StateType;
72  frameNumber : slv(11 downto 0);
73  packetNumber : slv(23 downto 0);
74  sof : sl;
75  startup : sl;
76  sideband : sl;
77  inputAxisSlave : AxiStreamSlaveType;
78  outputAxisMaster : AxiStreamMasterArray(1 downto 0);
79  end record RegType;
80 
81  constant REG_INIT_C : RegType := (
82  state => HEADER_S,
83  frameNumber => (others => '0'),
84  packetNumber => (others => '0'),
85  sof => '1',
86  startup => '1',
87  sideband => '0',
88  inputAxisSlave => AXI_STREAM_SLAVE_INIT_C,
89  outputAxisMaster => (others => axiStreamMasterInit(AXIS_CONFIG_C)));
90 
91  signal r : RegType := REG_INIT_C;
92  signal rin : RegType;
93 
94  signal inputAxisMaster : AxiStreamMasterType;
95  signal inputAxisSlave : AxiStreamSlaveType;
96  signal outputAxisMaster : AxiStreamMasterType;
97  signal outputAxisSlave : AxiStreamSlaveType;
98 
99 begin
100 
101  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
102  -- Input pipeline
103  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
104  U_AxiStreamPipeline_Input : entity work.AxiStreamPipeline
105  generic map (
106  TPD_G => TPD_G,
108  port map (
109  axisClk => axisClk, -- [in]
110  axisRst => axisRst, -- [in]
111  sAxisMaster => sAxisMaster, -- [in]
112  sAxisSlave => sAxisSlave, -- [out]
113  mAxisMaster => inputAxisMaster, -- [out]
114  mAxisSlave => inputAxisSlave); -- [in]
115 
116  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
117  -- Output pipeline
118  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
119  U_AxiStreamPipeline_Output : entity work.AxiStreamPipeline
120  generic map (
121  TPD_G => TPD_G,
123  port map (
124  axisClk => axisClk, -- [in]
125  axisRst => axisRst, -- [in]
126  sAxisMaster => outputAxisMaster, -- [in]
127  sAxisSlave => outputAxisSlave, -- [out]
128  mAxisMaster => mAxisMaster, -- [out]
129  mAxisSlave => mAxisSlave); -- [in]
130 
131  -------------------------------------------------------------------------------------------------
132  -- Accumulation sequencing, DMA ring buffer, and AXI-Lite logic
133  -------------------------------------------------------------------------------------------------
134  comb : process (axisRst, inputAxisMaster, outputAxisSlave, r, restart) is
135  variable v : RegType;
136 
137  begin
138  v := r;
139 
140  if (restart = '1') then
141  v.startup := '1';
142  v.sof := '1';
143  end if;
144 
145  v.inputAxisSlave.tready := '0';
146  if (outputAxisSlave.tReady = '1') then
147  v.outputAxisMaster(1).tValid := '0';
148  v.outputAxisMaster(0).tValid := '0';
149  end if;
150 
151  case r.state is
152  when HEADER_S =>
153  v.inputAxisSlave.tready := '1';
154  v.outputAxisMaster(1) := axiStreamMasterInit(AXIS_CONFIG_C);
155 
156  if (r.outputAxisMaster(1).tValid = '1' and v.outputAxisMaster(0).tValid = '0') then
157  v.outputAxisMaster(0) := r.outputAxisMaster(1);
158  end if;
159 
160  -- Process the header
161  if (inputAxisMaster.tValid = '1' and v.outputAxisMaster(1).tValid = '0') then
162  v.state := MOVE_S;
163 
164  -- Assign sideband fields
165  v.outputAxisMaster(1).tDest(7 downto 0) := inputAxisMaster.tData(47 downto 40);
166  v.outputAxisMaster(1).tId(7 downto 0) := inputAxisMaster.tData(55 downto 48);
167  v.outputAxisMaster(1).tUser(7 downto 0) := inputAxisMaster.tData(63 downto 56);
168 
169  -- Assert SOF if starting a new frame
170  axiStreamSetUserBit(AXIS_CONFIG_C, v.outputAxisMaster(1), SSI_SOF_C, r.sof, 0); -- SOF
171  v.sof := '0';
172 
173  -- Check frame and packet number
174  if (r.sof = '1') then
175  v.frameNumber := inputAxisMaster.tData(15 downto 4);
176  v.packetNumber := (others => '0');
177  if ((r.startup = '0' and inputAxisMaster.tData(15 downto 4) /= r.frameNumber+1) or
178  inputAxisMaster.tData(39 downto 16) /= 0) then
179  v.state := BLEED_S; -- Error - Missing frames
180  end if;
181  else
182  v.packetNumber := inputAxisMaster.tData(39 downto 16);
183  if (inputAxisMaster.tData(15 downto 4) /= r.frameNumber or
184  inputAxisMaster.tData(39 downto 16) /= r.packetNumber+1) then
185  v.outputAxisMaster(1).tvalid := '1';
186  v.outputAxisMaster(1).tlast := '1';
187  axiStreamSetUserBit(AXIS_CONFIG_C, v.outputAxisMaster(1), SSI_EOFE_C, '1', 0);
188  v.state := BLEED_S;
189  end if;
190  end if;
191  v.startup := '0';
192  v.sideband := '1';
193  end if;
194 
195  when BLEED_S =>
196  -- Blead an entire packet
197  -- Set startup and sof true when done
198  v.inputAxisSlave.tready := '1';
199  v.outputAxisMaster(1).tvalid := '0';
200  v.sof := '1';
201  v.startup := '1';
202  if (inputAxisMaster.tLast = '1') then
203  v.state := HEADER_S;
204  end if;
205 
206  when MOVE_S =>
207  -- Keep the caches copy
208  v.outputAxisMaster(1).tvalid := r.outputAxisMaster(1).tvalid;
209  -- Check if we can move data
210  if (inputAxisMaster.tValid = '1' and v.outputAxisMaster(0).tValid = '0') then
211  -- Accept the data
212  v.inputAxisSlave.tReady := '1';
213  -- Advance the pipeline
214  v.outputAxisMaster(1) := inputAxisMaster;
215  v.outputAxisMaster(0) := r.outputAxisMaster(1);
216  -- Keep sideband data from header
217  v.outputAxisMaster(1).tDest := r.outputAxisMaster(1).tDest;
218  v.outputAxisMaster(1).tId := r.outputAxisMaster(1).tId;
219  if (r.sideband = '1') then
220  -- But tUser only for first output txn
221  v.outputAxisMaster(1).tUser := r.outputAxisMaster(1).tUser;
222  v.sideband := '0';
223  end if;
224  -- End of frame
225  if (inputAxisMaster.tLast = '1') then
226  -- Check tkeep to find tail byte (and strip it out)
227  v.outputAxisMaster(1).tKeep := '0' & inputAxisMaster.tKeep(15 downto 1);
228  case (inputAxisMaster.tKeep(7 downto 0)) is
229  when X"01" =>
230  -- Single byte tail, append tUser to previous txn which has been held
231  v.outputAxisMaster(1).tValid := '0';
232  v.outputAxisMaster(0).tUser(63 downto 56) := '0' & inputAxisMaster.tData(6 downto 0);
233  v.outputAxisMaster(0).tLast := inputAxisMaster.tData(7);
234  v.sof := inputAxisMaster.tData(7);
235  when X"03" =>
236  v.outputAxisMaster(1).tUser(7 downto 0) := '0' & inputAxisMaster.tData(14 downto 8);
237  v.sof := inputAxisMaster.tData(15);
238  when X"07" =>
239  v.outputAxisMaster(1).tUser(15 downto 8) := '0' & inputAxisMaster.tData(22 downto 16);
240  v.sof := inputAxisMaster.tData(23);
241  when X"0F" =>
242  v.outputAxisMaster(1).tUser(23 downto 16) := '0' & inputAxisMaster.tData(30 downto 24);
243  v.sof := inputAxisMaster.tData(31);
244  when X"1F" =>
245  v.outputAxisMaster(1).tUser(31 downto 24) := '0' & inputAxisMaster.tData(38 downto 32);
246  v.sof := inputAxisMaster.tData(39);
247  when X"3F" =>
248  v.outputAxisMaster(1).tUser(39 downto 32) := '0' & inputAxisMaster.tData(46 downto 40);
249  v.sof := inputAxisMaster.tData(47);
250  when X"7F" =>
251  v.outputAxisMaster(1).tUser(47 downto 40) := '0' & inputAxisMaster.tData(54 downto 48);
252  v.sof := inputAxisMaster.tData(55);
253  when X"FF" =>
254  v.outputAxisMaster(1).tUser(55 downto 48) := '0' & inputAxisMaster.tData(62 downto 56);
255  v.sof := inputAxisMaster.tData(63);
256  when others =>
257  null;
258  end case;
259  v.outputAxisMaster(1).tLast := v.sof;
260  v.state := DONE_S;
261  end if;
262  end if;
263 
264 
265  when DONE_S =>
266  -- Keep the caches copy
267  v.outputAxisMaster(1).tvalid := r.outputAxisMaster(1).tvalid;
268  -- Check if we can move data
269  if (v.outputAxisMaster(0).tValid = '0') then
270  -- Advance the pipeline
271  v.outputAxisMaster(1).tValid := '0';
272  v.outputAxisMaster(0) := r.outputAxisMaster(1);
273  v.state := HEADER_S;
274  end if;
275 
276  end case;
277 
278  ----------------------------------------------------------------------------------------------
279  -- Reset and output assignment
280  ----------------------------------------------------------------------------------------------
281  if (axisRst = '1') then
282  v := REG_INIT_C;
283  end if;
284 
285  rin <= v;
286 
287  inputAxisSlave <= v.inputAxisSlave;
288 
289  -- Hold each out tvalid until next in tvalid arrives
290  outputAxisMaster <= r.outputAxisMaster(0);
291 
292  end process comb;
293 
294  seq : process (axisClk) is
295  begin
296  if (rising_edge(axisClk)) then
297  r <= rin after TPD_G;
298  end if;
299  end process seq;
300 
301 end architecture rtl;
302 
slv( 7 downto 0) tId
out mAxisMasterAxiStreamMasterType
PIPE_STAGES_Gnatural range 0 to 16:= 0
natural range 0 to 8 TDEST_BITS_C
sl sof
Definition: SsiPkg.vhd:72
std_logic sl
Definition: StdRtlPkg.vhd:28
integer := 1 SSI_SOF_C
Definition: SsiPkg.vhd:31
integer := 0 SSI_EOFE_C
Definition: SsiPkg.vhd:30
out sAxisSlaveAxiStreamSlaveType
slv( 15 downto 0) tKeep
natural range 1 to 16 TDATA_BYTES_C
in mAxisSlaveAxiStreamSlaveType
TkeepModeType TKEEP_MODE_C
natural range 0 to 8 TID_BITS_C
in sAxisMasterAxiStreamMasterType
slv( 127 downto 0) tData
out sAxisSlaveAxiStreamSlaveType
in sAxisMasterAxiStreamMasterType
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
boolean TSTRB_EN_C
TUserModeType TUSER_MODE_C
slv( 127 downto 0) tUser
in mAxisSlaveAxiStreamSlaveType
array(natural range <> ) of AxiStreamMasterType AxiStreamMasterArray
natural range 0 to 8 TUSER_BITS_C
out mAxisMasterAxiStreamMasterType
slv( 7 downto 0) tDest
_library_ ieeeieee
std_logic_vector slv
Definition: StdRtlPkg.vhd:29