1 ------------------------------------------------------------------------------- 2 -- File : AxiStreamUnpacker.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2013-09-26 5 -- Last update: 2017-05-24 6 ------------------------------------------------------------------------------- 7 -- Description: Takes 8 80-bit (5x16) ADC frames and reformats them into 8 -- 7 80 bit (5x14) frames. 9 ------------------------------------------------------------------------------- 10 -- This file is part of 'SLAC Firmware Standard Library'. 11 -- It is subject to the license terms in the LICENSE.txt file found in the 12 -- top-level directory of this distribution and at: 13 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. 14 -- No part of 'SLAC Firmware Standard Library', including this file, 15 -- may be copied, modified, propagated, or distributed except according to 16 -- the terms contained in the LICENSE.txt file. 17 ------------------------------------------------------------------------------- 20 use ieee.std_logic_1164.
all;
21 use ieee.std_logic_arith.
all;
22 use ieee.std_logic_unsigned.
all;
37 -- PACK_SIZE_G : integer); 52 end entity AxiStreamUnpacker;
58 constant SIZE_DIFFERENCE_C : := STREAM_WIDTH_C-PACK_SIZE_C;
59 constant ZERO_C : slv(SIZE_DIFFERENCE_C-1 downto 0) := slvZero(SIZE_DIFFERENCE_C);
61 type RegType is record 64 data : slv(STREAM_WIDTH_C*2-1 downto 0);
65 splitIndex : slv(log2(STREAM_WIDTH_C)-1 downto 0);
71 constant REG_INIT_C : RegType := ( 74 data => (others => '0'), 75 splitIndex => (others => '0'), 80 signal r : RegType := REG_INIT_C;
92 -- Convert AXI-Stream signals to SSI 96 comb :
process (
axisRst, packedSsiMaster, r)
is 98 variable splitIndexInt : ;
99 variable shiftIndexInt : ;
100 variable wrData : slv(STREAM_WIDTH_C+SIZE_DIFFERENCE_C-1 downto 0);
104 v.rawSsiMaster.sof := '0';
105 v.rawSsiMaster.eof := '0';
106 v.rawSsiMaster.eofe := '0';
107 v.rawSsiMaster.valid := '0';
109 v.packedSsiSlave.ready := '1';
110 v.packedSsiSlave.pause := '0';
114 if (packedSsiMaster.valid = '1' and r.packedSsiSlave.ready = '1') then 115 -- Shift leftover data from last txn down to the right for output 116 v.data(STREAM_WIDTH_C-1 downto 0) := r.data(STREAM_WIDTH_C*2-1 downto STREAM_WIDTH_C);
119 if (packedSsiMaster.sof = '1') then 120 -- SOF txns are not packed. Just send the input data straight out. 121 v.data := (others => '0');
122 v.data(STREAM_WIDTH_C-1 downto 0) := packedSsiMaster.data(STREAM_WIDTH_C-1 downto 0);
123 v.rawSsiMaster.valid := '1';
124 v.rawSsiMaster.sof := '1';
125 v.splitIndex := (others => '0');
126 v.splitIndex := v.splitIndex-SIZE_DIFFERENCE_C;
129 -- Each incomming txn contains part of the data from two outgoing txns. 130 -- First we find the split index. 131 -- On the first txn the split index is at STREAM_WIDTH_C-SIZE_DIFFERENCE_C. 132 -- It then decrements by SIZE_DIFFERENCE_C on each subsequent txn. 133 -- splitIndexInt := STREAM_WIDTH_C - (conv_integer(r.seqNum)+1)*SIZE_DIFFERENCE_C; 134 splitIndexInt := conv_integer(r.splitIndex);
135 v.splitIndex := r.splitIndex - SIZE_DIFFERENCE_C;
137 -- Insert SIZE_DIFFERENCE_C zeros at the split index. Store in temporary variable. 138 -- This is how it should look: 139 -- wrData := packedSsiMaster.data(STREAM_WIDTH_C-1 downto zeroIndex) & 140 -- ZERO_C & packedSsiMaster.data(splitIndexInt downto 0); 141 -- But Vivado can't synthesize it that way, so we do this hack: 142 wrData := (others => '0');
143 wrData(STREAM_WIDTH_C+SIZE_DIFFERENCE_C-1 downto SIZE_DIFFERENCE_C) := 144 packedSsiMaster.data(STREAM_WIDTH_C-1 downto 0);
145 wrData(splitIndexInt+SIZE_DIFFERENCE_C-1 downto splitIndexInt) := 147 wrData(splitIndexInt-1 downto 0) := 148 packedSsiMaster.data(splitIndexInt-1 downto 0);
151 -- Leftover bits from the previous txn have already by shifted to the far right of v.data. 152 -- We don't want to overwrite these, so we assign our zero filled value to v.data with the proper 153 -- offset to avoid doing so. 154 shiftIndexInt := PACK_SIZE_C-splitIndexInt;
156 v.data(shiftIndexInt + STREAM_WIDTH_C+SIZE_DIFFERENCE_C - 1 downto shiftIndexInt) := wrData;
158 -- Now shift the output segment by RANGE_LOW_G to recover LSB zeros 161 -- Assert valid and pass any eof through 162 v.rawSsiMaster.valid := '1';
163 v.rawSsiMaster.eof := packedSsiMaster.eof;
164 v.rawSsiMaster.eofe := packedSsiMaster.eofe;
166 if (r.splitIndex = SIZE_DIFFERENCE_C) then 167 -- This is the last txn of a group. 168 -- Don't output eof yet, as we want it to go out with the 'extra' output txn. 169 v.packedSsiSlave.ready := '0';
170 v.rawSsiMaster.eof := '0';
171 v.rawSsiMaster.eofe := '0';
172 v.eof := packedSsiMaster.eof;
179 if (r.splitIndex = 0 and r.doLast = '1') then 180 -- When split index reaches zero, we have received all txns in a group 181 -- We now have an extra txn that must be shifted out. 183 v.rawSsiMaster.valid := '1';
184 v.rawSsiMaster.eof := r.eof;
189 v.splitIndex := r.splitIndex - SIZE_DIFFERENCE_C;
192 -- Assign v.data to rawSsiMaster 193 -- Synthesis will merge the r.data registers with r.rawSsiMaster.data 194 v.rawSsiMaster.data(STREAM_WIDTH_C -1 downto 0) := v.data(STREAM_WIDTH_C-1 downto 0);
197 ---------------------------------------------------------------------------------------------- 199 ---------------------------------------------------------------------------------------------- 206 ---------------------------------------------------------------------------------------------- 208 ---------------------------------------------------------------------------------------------- 209 locRawAxisMaster <= ssi2AxisMaster(AXI_STREAM_CONFIG_G, r.rawSsiMaster);
218 r <= rin after TPD_G;
223 locRawAxisSlave <= rawAxisSlave;
224 locRawAxisCtrl <= rawAxisCtrl;
226 -- Could probably get rid of this 227 -- AxiStreamFifo_1 : entity work.AxiStreamFifoV2 230 -- BRAM_EN_G => false, 231 -- GEN_SYNC_FIFO_G => true, 232 -- FIFO_ADDR_WIDTH_G => 4, 233 -- FIFO_FIXED_THRESH_G => true, 234 -- FIFO_PAUSE_THRESH_G => 15, 235 -- SLAVE_AXI_CONFIG_G => AXI_STREAM_CONFIG_G, 236 -- MASTER_AXI_CONFIG_G => AXI_STREAM_CONFIG_G) 238 -- sAxisClk => axisClk, 239 -- sAxisRst => axisRst, 240 -- sAxisMaster => locRawAxisMaster, 241 -- sAxisSlave => locRawAxisSlave, 242 -- sAxisCtrl => locRawAxisCtrl, 243 -- mAxisClk => axisClk, 244 -- mAxisRst => axisRst, 245 -- mAxisMaster => rawAxisMaster, 246 -- mAxisSlave => rawAxisSlave); 248 end architecture rtl;
RANGE_HIGH_Ginteger := 119
natural range 1 to 16 TDATA_BYTES_C
out packedAxisCtrlAxiStreamCtrlType
in rawAxisCtrlAxiStreamCtrlType
in packedAxisMasterAxiStreamMasterType
out packedAxisSlaveAxiStreamSlaveType
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
AXI_STREAM_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
out rawAxisMasterAxiStreamMasterType
in rawAxisSlaveAxiStreamSlaveType