1 ------------------------------------------------------------------------------- 2 -- File : AxiStreamDmaRead.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2014-04-25 5 -- Last update: 2016-10-27 6 ------------------------------------------------------------------------------- 8 -- Block to transfer a single AXI Stream frame from memory using an AXI 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_arith.
all;
23 use ieee.std_logic_unsigned.
all;
48 -- DMA Control Interface 52 -- Streaming Interface 67 type ReqStateType is ( 79 type RegType is record 80 pendBytes : slv(31 downto 0);
82 reqSize : slv(31 downto 0);
83 reqCnt : slv(31 downto 0);
84 ackCnt : slv(31 downto 0);
87 shift : slv(3 downto 0);
93 reqState : ReqStateType;
97 constant REG_INIT_C : RegType := ( 98 pendBytes => (others => '0'), 99 size => (others => '0'), 100 reqSize => (others => '0'), 101 reqCnt => (others => '0'), 102 ackCnt => (others => '0'), 105 shift => (others => '0'), 114 signal r : RegType := REG_INIT_C;
115 signal rin : RegType;
123 -- attribute dont_touch : string; 124 -- attribute dont_touch of r : signal is "TRUE"; 135 variable v : RegType;
136 variable readSize : ;
140 -- Latch the current value 143 -- Set cache value if enabled in software 148 -- Reset strobing Signals 154 if (sSlave.tReady = '1') then 156 v.sMaster.tLast := '0';
157 v.sMaster.tUser := (others => '0');
158 v.sMaster.tKeep := (others => '1');
159 v.sMaster.tStrb := (others => '1');
162 -- Calculate the pending bytes 163 v.pendBytes := r.reqCnt - r.ackCnt;
168 -- Check for the threshold = zero case 170 if (r.pendBytes = 0) then 186 -- Check for handshaking 192 -- Memory Request State machine 194 ---------------------------------------------------------------------- 196 -- Update the variables 198 -- Reset the counters 199 v.shift := (others => '0');
200 v.reqCnt := (others => '0');
201 v.ackCnt := (others => '0');
202 -- Align shift and address to transfer size 205 v.shift(ADDR_LSB_C-1 downto 0) := dmaReq.address(ADDR_LSB_C-1 downto 0);
207 -- Check for DMA request 209 -- Reset the flags and counters 219 v.sMaster.tId := dmareq.id;
221 v.reqState := FIRST_S;
223 ---------------------------------------------------------------------- 225 -- Check if ready to make memory request 226 if (r.rMaster.arvalid = '0') then 227 -- Set the memory address 229 -- Determine transfer size to align address to 16-transfer boundaries 230 -- This initial alignment will ensure that we never cross a 4k boundary 231 if (ARLEN_C > 0) then 232 -- Set the burst length 234 -- Limit read burst size 235 if (r.reqSize(31 downto ADDR_LSB_C) < v.rMaster.arlen) then 239 -- There is enough room in the FIFO for a burst 240 if (pause = '0') then 243 -- Update the request size 245 v.reqCnt := toSlv(reqLen, 32) - conv_integer(r.shift);
246 v.reqSize := r.reqSize - reqLen;
247 -- Update next address 251 v.reqState := NEXT_S;
255 ---------------------------------------------------------------------- 257 -- Check if ready to make memory request 258 if (r.rMaster.arvalid = '0') then 259 -- Set the memory address 261 -- Bursts after the FIRST are guaranteed to be aligned 262 v.rMaster.arlen := ARLEN_C;
263 -- Limit read burst size 264 if (r.reqSize(31 downto ADDR_LSB_C) < v.rMaster.arlen) then 267 -- Check for the following: 268 -- 1) There is enough room in the FIFO for a burst 270 -- 3) Last transaction already completed 271 if (pause = '0') and (pending = false) and (r.reqCnt < r.dmaReq.size) then 274 -- Update the request size 276 v.reqCnt := r.reqCnt + reqLen;
277 v.reqSize := r.reqSize - reqLen;
278 -- Update next address 283 ---------------------------------------------------------------------- 286 -- Data Collection State machine 288 ---------------------------------------------------------------------- 290 -- Blowoff any out-of-phase data (should never happen) 292 ---------------------------------------------------------------------- 294 -- Check if ready to move data 302 if r.first = '1' then 305 -- Set the tUser for the first byte transferred 306 axiStreamSetUserField( 311 conv_integer(r.shift));
313 -- Calculate the read size 314 readSize := DATA_BYTES_C - ite(r.first = '1', conv_integer(r.shift), 0);
315 -- Check the read size 316 if (readSize > r.size) then 318 v.size := (others => '0');
319 -- Top out at dma.size 322 -- Decrement the counter 324 -- Increment the counter 325 v.ackCnt := r.ackCnt + readSize;
327 -- Check for completion 329 -- Terminate the frame 330 v.sMaster.tLast := '1';
331 v.sMaster.tKeep := genTKeep(conv_integer(r.size(4 downto 0)));
332 v.sMaster.tStrb := genTKeep(conv_integer(r.size(4 downto 0)));
333 -- Check for first transfer 334 if (r.first = '1') then 335 -- Compensate the tKeep and tStrb via shift module 336 v.sMaster.tKeep := shl(v.sMaster.tKeep, r.shift);
337 v.sMaster.tStrb := shl(v.sMaster.tStrb, r.shift);
346 ---------------------------------------------------------------------- 348 -- Hold until last transfer (required for Remap_mAxisMaster process) 349 if (mMaster.tValid = '1') and (mMaster.tLast = '1') and (mSlave.tReady = '1') then 353 ---------------------------------------------------------------------- 355 -- Check for ACK completion 359 -- Check if no leftover memory request data 360 if r.leftovers = '0' then 362 v.reqState := IDLE_S;
366 v.state := BLOWOFF_S;
369 ---------------------------------------------------------------------- 373 -- Check for last transfer 376 v.reqState := IDLE_S;
379 ---------------------------------------------------------------------- 382 -- Forward the state of the state machine 383 if v.state = IDLE_S then 396 -- Register the variable for next clock cycle 408 if (rising_edge(axiClk)) then 409 r <= rin after TPD_G;
442 Remap_mAxisMaster :
process (mMaster, r)
is 445 -- Latch the current value 448 if mMaster.tLast = '1' then 450 -- Note: This is done here (instead of "comb" process) to prevent a crazy long logic chain 451 -- Note: For the "1 byte" case, lastUser will overwrite the firstUser value.
PIPE_STAGES_Gnatural range 0 to 16:= 0
slv( 63 downto 0) address
slv( 1023 downto 0) rdata
AXIS_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
AXI_CACHE_Gslv( 3 downto 0) := "1111"
slv( 7 downto 0) firstUser
out sAxisSlaveAxiStreamSlaveType
in dmaReqAxiReadDmaReqType
in sAxisMasterAxiStreamMasterType
out sAxisSlaveAxiStreamSlaveType
PIPE_STAGES_Gnatural := 1
natural range 1 to 16 TDATA_BYTES_C
in mAxisSlaveAxiStreamSlaveType
in axiShiftCntslv( 3 downto 0)
in swCacheslv( 3 downto 0) := "0000"
out axiReadMasterAxiReadMasterType
positive range 12 to 64 ADDR_WIDTH_C
AXI_CONFIG_GAxiConfigType := AXI_CONFIG_INIT_C
in axiReadSlaveAxiReadSlaveType
SW_CACHE_EN_Gboolean := false
slv( 7 downto 0) lastUser
AXI_BURST_Gslv( 1 downto 0) := "01"
out dmaAckAxiReadDmaAckType
in axisCtrlAxiStreamCtrlType
out mAxisMasterAxiStreamMasterType
BYP_SHIFT_Gboolean := false
in sAxisMasterAxiStreamMasterType
BYP_SHIFT_Gboolean := false
PEND_THRESH_Gnatural := 0
AxiReadDmaReqType :=(request => '0',address =>( others => '0'),size =>( others => '0'),firstUser =>( others => '0'),lastUser =>( others => '0'),dest =>( others => '0'),id =>( others => '0')) AXI_READ_DMA_REQ_INIT_C
AXIS_READY_EN_Gboolean := false
natural range 0 to 8 TUSER_BITS_C
out mAxisMasterAxiStreamMasterType
in axisSlaveAxiStreamSlaveType
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
AxiReadDmaAckType :=(idle => '1',done => '0',readError => '0',errorValue => "00") AXI_READ_DMA_ACK_INIT_C
positive range 1 to 128 DATA_BYTES_C
slv( 1 downto 0) errorValue
in mAxisSlaveAxiStreamSlaveType
AxiStreamSlaveType :=(tReady => '1') AXI_STREAM_SLAVE_FORCE_C
AXIS_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
PIPE_STAGES_Ginteger range 0 to 16:= 0
AxiConfigType :=axiConfig(ADDR_WIDTH_C => 32,DATA_BYTES_C => 4,ID_BITS_C => 12,LEN_BITS_C => 4) AXI_CONFIG_INIT_C
natural range 0 to 8 LEN_BITS_C
out axisMasterAxiStreamMasterType