1 ------------------------------------------------------------------------------- 2 -- File : AxiStreamDmaWrite.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2014-04-25 5 -- Last update: 2016-12-02 6 ------------------------------------------------------------------------------- 8 -- Block to transfer a single AXI Stream frame into 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;
49 -- DMA Control Interface 53 -- Streaming Interface 60 end AxiStreamDmaWrite;
87 type RegType is record 90 threshold : slv(FIFO_ADDR_WIDTH_C-1 downto 0);
91 shift : slv(3 downto 0);
95 reqCount : slv(31 downto 0);
96 ackCount : slv(31 downto 0);
97 stCount : slv(15 downto 0);
104 constant REG_INIT_C : RegType := ( 107 threshold => (others => '1'), 108 shift => (others => '0'), 112 reqCount => (others => '0'), 113 ackCount => (others => '0'), 114 stCount => (others => '0'), 115 awlen => (others => '0'), 120 signal r : RegType := REG_INIT_C;
121 signal rin : RegType;
132 -- attribute dont_touch : string; 133 -- attribute dont_touch of r : signal is "true"; 138 report "AXIS (" & 'image(LOC_AXIS_CONFIG_C.TDATA_BYTES_C) & ") and AXI (" 205 din =>
(others => '0'
),
212 intAxisMaster <= shiftMaster;
213 shiftSlave <= intAxisSlave;
222 variable v : RegType;
224 variable ibValid : sl;
226 -- Latch the current value 229 -- Set cache value if enabled in software 234 -- Reset strobing Signals 243 v.wMaster.wlast := '0';
246 -- Wait for memory bus response 248 -- Increment the counter 249 v.ackCount := r.ackCount + 1;
250 -- Check for error response 254 -- Latch the response value 259 -- Check for handshaking 265 -- Count number of bytes in return data 268 -- Check the AXI stream data cache 269 if (lastDet = '1') or (cache.pause = '1') then 275 ---------------------------------------------------------------------- 277 -- Update the variables 279 -- Reset the counters and threshold 280 v.reqCount := (others => '0');
281 v.ackCount := (others => '0');
282 v.shift := (others => '0');
283 v.stCount := (others => '0');
284 v.threshold := (others => '1');
285 -- Align shift and address to transfer size 288 v.shift(ADDR_LSB_C-1 downto 0) := dmaReq.address(ADDR_LSB_C-1 downto 0);
290 -- Check for DMA request 292 -- Reset the flags and counters 301 -- Check if we are dumping AXIS frames 310 ---------------------------------------------------------------------- 312 -- Check if ready to make memory request 313 if (v.wMaster.awvalid = '0') then 314 -- Set the memory address 316 -- Determine transfer size to align address to AXI_BURST_BYTES_G boundaries 317 -- This initial alignment will ensure that we never cross a 4k boundary 318 if (AWLEN_C > 0) then 319 -- Set the burst length 321 -- Limit write burst size 326 -- Latch AXI awlen value 328 -- Update the threshold 329 v.threshold := '0' & v.awlen;
330 v.threshold := v.threshold + 1;
331 -- DMA request has dropped. Abort. This is needed to disable engine while it 332 -- is still waiting for an inbound frame. 336 -- Check if enough room and data to move 337 elsif (pause = '0') and (ibValid = '1') then 340 -- Increment the counter 341 v.reqCount := r.reqCount + 1;
346 ---------------------------------------------------------------------- 348 -- Check if ready to make memory request 349 if (v.wMaster.awvalid = '0') then 350 -- Set the memory address 352 -- Bursts after the FIRST are garunteed to be aligned. 353 v.wMaster.awlen := AWLEN_C;
357 -- Latch AXI awlen value 359 -- Update the threshold 360 v.threshold := '0' & v.awlen;
361 v.threshold := v.threshold + 1;
362 -- DMA request has dropped. Abort. This is needed to disable engine while it 363 -- is still waiting for an inbound frame. 367 -- Check if enough room and data to move 368 elsif (pause = '0') and (ibValid = '1') then 371 -- Increment the counter 372 v.reqCount := r.reqCount + 1;
377 ---------------------------------------------------------------------- 379 -- Reset the threshold 380 v.threshold := (others => '1');
381 -- Check if ready to move data 382 if (v.wMaster.wvalid = '0') and ((intAxisMaster.tValid = '1') or (r.last = '1')) then 384 v.slave.tReady := not(r.last);
388 -- Address and size increment 391 -- Check if tLast not registered yet 392 if (r.last = '0') then 393 -- Increment the byte counter 396 -- -- Check for first AXIS word 397 if (r.first = '0') then 400 -- Latch the tDest/tId/tUser values 403 v.dmaAck.firstUser(LOC_AXIS_CONFIG_C.TUSER_BITS_C-1 downto 0) := axiStreamGetUserField(LOC_AXIS_CONFIG_C, intAxisMaster, conv_integer(r.shift));
405 -- -- Check for last AXIS word 406 if (intAxisMaster.tLast = '1') and (r.last = '0') then 409 -- Latch the tUser value 413 if (r.last = '1') then 414 -- Reset byte write strobes 415 v.wMaster.wstrb := (others => '0');
416 -- Check the read size 418 -- Set the error flag 420 -- Reset byte write strobes 421 v.wMaster.wstrb := (others => '0');
423 -- Decrement the counter 425 -- Set byte write strobes 428 -- Check for last AXI transfer 429 if (AWLEN_C = 0) or (r.awlen = 0) then 431 v.wMaster.wlast := '1';
432 -- Check if AXIS is completed 433 if (v.last = '1') then 436 -- Check the error flags 440 -- Continue to the next memory request transaction 446 -- Decrement the counter 450 ---------------------------------------------------------------------- 455 if (intAxisMaster.tValid = '1') then 456 -- Check for first AXIS word 457 if (r.first = '0') then 460 -- Latch the tDest/tId/tUser values 463 v.dmaAck.firstUser(LOC_AXIS_CONFIG_C.TUSER_BITS_C-1 downto 0) := axiStreamGetUserField(LOC_AXIS_CONFIG_C, intAxisMaster, conv_integer(r.shift));
465 -- Check for last AXIS word 466 if (intAxisMaster.tLast = '1') then 467 -- Latch the tUser value 473 ---------------------------------------------------------------------- 475 -- Check if ACK counter caught up with REQ counter 481 -- Check for ACK timeout 482 elsif (r.stCount = x"FFFF") then 489 -- Increment the counter 490 v.stCount := r.stCount + 1;
492 ---------------------------------------------------------------------- 494 -- Check for ACK completion 499 ---------------------------------------------------------------------- 502 -- Forward the state of the state machine 503 if (v.state = IDLE_S) then 516 -- Register the variable for next clock cycle 521 intAxisSlave <= v.slave;
528 if (rising_edge(axiClk)) then 529 r <= rin after TPD_G;
BYP_SHIFT_Gboolean := false
in dmaReqAxiWriteDmaReqType
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
out dmaAckAxiWriteDmaAckType
natural range 0 to 8 TDEST_BITS_C
slv( 63 downto 0) address
ADDR_WIDTH_Ginteger range 4 to 48:= 4
out sAxisCtrlAxiStreamCtrlType
out axiWriteMasterAxiWriteMasterType
PIPE_STAGES_Gnatural range 0 to 16:= 1
in rstsl :=not RST_POLARITY_G
slv( 7 downto 0) firstUser
out sAxisSlaveAxiStreamSlaveType
in axiWriteCtrlAxiCtrlType := AXI_CTRL_UNUSED_C
slv( 1023 downto 0) wdata
ACK_WAIT_BVALID_Gboolean := true
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
in sAxisMasterAxiStreamMasterType
SLAVE_READY_EN_Gboolean := true
FIFO_FIXED_THRESH_Gboolean := true
AxiCtrlType :=(pause => '0',overflow => '0') AXI_CTRL_UNUSED_C
natural range 1 to 16 TDATA_BYTES_C
in axiShiftCntslv( 3 downto 0)
GEN_SYNC_FIFO_Gboolean := false
TkeepModeType TKEEP_MODE_C
positive range 12 to 64 ADDR_WIDTH_C
slv( 7 downto 0) lastUser
natural range 0 to 8 TID_BITS_C
in dinslv( DATA_WIDTH_G- 1 downto 0)
out mAxisMasterAxiStreamMasterType
INT_PIPE_STAGES_Gnatural range 0 to 16:= 0
BYP_CACHE_Gboolean := false
AXI_CACHE_Gslv( 3 downto 0) := "1111"
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
BYP_SHIFT_Gboolean := false
SW_CACHE_EN_Gboolean := false
TUserModeType TUSER_MODE_C
in axiWriteSlaveAxiWriteSlaveType
natural range 0 to 8 TUSER_BITS_C
AxiWriteDmaAckType :=(idle => '1',done => '0',size =>( others => '0'),overflow => '0',writeError => '0',errorValue => "00",firstUser =>( others => '0'),lastUser =>( others => '0'),dest =>( others => '0'),id =>( others => '0')) AXI_WRITE_DMA_ACK_INIT_C
AXI_BURST_Gslv( 1 downto 0) := "01"
out sAxisSlaveAxiStreamSlaveType
in axisMasterAxiStreamMasterType
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
positive range 1 to 128 DATA_BYTES_C
slv( 1 downto 0) errorValue
slv( 31 downto 0) maxSize
in swCacheslv( 3 downto 0) := "0000"
in sAxisMasterAxiStreamMasterType
in mAxisSlaveAxiStreamSlaveType
FWFT_EN_Gboolean := false
out mAxisMasterAxiStreamMasterType
PIPE_STAGES_Gnatural := 1
AXIS_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
PIPE_STAGES_Ginteger range 0 to 16:= 0
in fifoPauseThreshslv( FIFO_ADDR_WIDTH_G- 1 downto 0) :=( others => '1')
AXIS_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
in mAxisSlaveAxiStreamSlaveType
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
VALID_THOLD_Ginteger range 0 to ( 2** 24):= 1
BYP_RAM_Gboolean := false
AxiConfigType :=axiConfig(ADDR_WIDTH_C => 32,DATA_BYTES_C => 4,ID_BITS_C => 12,LEN_BITS_C => 4) AXI_CONFIG_INIT_C
AXI_CONFIG_GAxiConfigType := AXI_CONFIG_INIT_C
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
out axisSlaveAxiStreamSlaveType
AXI_READY_EN_Gboolean := false
natural range 0 to 8 LEN_BITS_C
AxiWriteDmaReqType :=(request => '0',drop => '0',address =>( others => '0'),maxSize =>( others => '0')) AXI_WRITE_DMA_REQ_INIT_C