1 ------------------------------------------------------------------------------- 2 -- File : AxiStreamDmaV2Write.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2017-02-02 5 -- Last update: 2017-02-02 6 ------------------------------------------------------------------------------- 8 -- Block to transfer a single AXI Stream frame into memory using an AXI 9 -- interface. Version 2 supports interleaved frames. 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;
44 -- DMA write descriptor request, ack and return 52 -- Streaming Interface 59 end AxiStreamDmaV2Write;
78 type RegType is record 83 reqCount : slv(31 downto 0);
84 ackCount : slv(31 downto 0);
85 stCount : slv(15 downto 0);
95 constant REG_INIT_C : RegType := ( 100 reqCount => (others => '0'), 101 ackCount => (others => '0'), 102 stCount => (others => '0'), 103 awlen => (others => '0'), 104 wMaster => axiWriteMasterInit(AXI_CONFIG_G, '1', "01", "0000"), 111 signal r : RegType := REG_INIT_C;
112 signal rin : RegType;
120 attribute dont_touch : ;
121 attribute dont_touch of r : signal is "true";
129 -- Placeholder for potential FIFO 133 -- Pause when enabled 139 variable v : RegType;
142 -- Latch the current value 145 -- Clear stream slave 157 v.wMaster.wlast := '0';
160 -- Wait for memory bus response 162 -- Increment the counter 163 v.ackCount := r.ackCount + 1;
164 -- Check for error response 166 -- Latch the response value 171 -- Descriptor handshaking 179 -- Count number of bytes in return data 184 ---------------------------------------------------------------------- 187 if r.stCount = 100 then 190 v.stCount := r.stCount + 1;
192 ---------------------------------------------------------------------- 194 v.dmaWrTrack.dest := r.dmaWrTrack.dest + 1;
195 if r.dmaWrTrack.dest = 255 then 198 ---------------------------------------------------------------------- 200 if intAxisMaster.tValid = '1' then 201 -- Current destination matches incoming frame 202 if r.dmaWrTrack.dest = intAxisMaster.tDest and r.dmaWrTrack.inUse = '1' then 203 if r.dmaWrTrack.dropEn = '1' then 209 -- Wait for mem selection to match incoming frame 210 elsif trackData.dest = intAxisMaster.tDest then 211 -- Set tracking data and setup request 212 v.dmaWrTrack := trackData;
215 -- Is entry valid or do we need a new buffer 216 if trackData.inUse = '1' then 217 if trackData.dropEn = '1' then 228 ---------------------------------------------------------------------- 230 -- Wait for response and latch fields 232 v.dmaWrTrack.inUse := '1';
235 v.dmaWrTrack.size := (others=>'0');
242 -- Descriptor return calls for dumping frame? 249 ---------------------------------------------------------------------- 251 -- Reset counter, continue and last user 252 v.stCount := (others=>'0');
255 -- Address can be sent 256 if (v.wMaster.awvalid = '0') then 257 -- Set the memory address 260 -- Determine transfer size aligned to 4k boundaries 262 -- Latch AXI awlen value 264 -- Check if enough room 268 -- Increment the counter 269 v.reqCount := r.reqCount + 1;
274 ---------------------------------------------------------------------- 276 -- Incoming valid data 277 if intAxisMaster.tValid = '1' then 278 v.stCount := (others=>'0');
279 -- Destination has changed, complete current write 283 elsif bytes > r.dmaWrTrack.maxSize then 284 -- Multi-descriptor DMA is supported 285 if r.dmaWrTrack.contEn = '1' then 287 v.dmaWrTrack.inUse := '0';
290 v.dmaWrTrack.dropEn := '1';
292 -- Pad current write, dump of incoming frame will occur 293 -- after state machine returns to idle due to dropEn being set. 294 -- Return will follow pad with inUse = '0' 296 -- We are able to push more data 297 elsif v.wMaster.wvalid = '0' then 303 -- Set byte write strobes 305 -- Address and size increment 307 v.dmaWrTrack.address(ADDR_LSB_C-1 downto 0) := (others => '0');
308 -- Increment the byte counter 309 v.dmaWrTrack.size := r.dmaWrTrack.size + bytes;
312 if r.dmaWrTrack.size = 0 then 313 -- Latch the tDest/tId/tUser values 314 v.dmaWrTrack.id := intAxisMaster.tId;
318 -- -- Check for last AXIS word 319 if intAxisMaster.tLast = '1' then 320 -- Latch the tUser value 323 v.dmaWrTrack.inUse := '0';
324 -- Pad write if transaction is not done, return will following PAD because inUse = 0 331 -- Check for last AXI transfer 334 v.wMaster.wlast := '1';
335 -- If next state has not already been updated go to idle 336 if v.state = MOVE_S then 340 -- Decrement the transaction counter 344 -- Timeout on stalled writes to avoid locking AXI crossbar 345 elsif r.stCount = 100 then 348 v.stCount := r.stCount + 1;
350 ---------------------------------------------------------------------- 352 v.stCount := (others=>'0');
353 -- We are able to push more data 354 if v.wMaster.wvalid = '0' then 356 v.wMaster.wstrb := (others=>'0');
357 -- Check for last AXI transfer 360 v.wMaster.wlast := '1';
361 -- Frame is done. Go to return. Otherwise go to idle. 362 if r.dmaWrTrack.inUse = '0' then 368 -- Decrement the counter 372 ---------------------------------------------------------------------- 374 -- Previous return was acked 376 -- Setup return record 387 v.dmaWrTrack.inUse := '0';
388 -- Wait for all transactions to complete before returning descriptor 392 -- Check for ACK timeout 393 elsif (r.stCount = x"FFFF") then 397 v.reqCount := (others => '0');
398 v.ackCount := (others => '0');
401 -- Increment the counter 402 v.stCount := r.stCount + 1;
405 v.stCount := (others=>'0');
407 ---------------------------------------------------------------------- 409 -- Incoming valid data 410 if intAxisMaster.tValid = '1' then 411 -- Destination has changed, complete current write 417 -- -- Check for last AXIS word 418 if intAxisMaster.tLast = '1' then 419 v.dmaWrTrack.inUse := '0';
424 ---------------------------------------------------------------------- 429 -- Forward the state of the state machine 430 if (v.state = IDLE_S) then 441 -- Register the variable for next clock cycle 445 intAxisSlave <= v.slave;
455 if (rising_edge(axiClk)) then 456 r <= rin after TPD_G;
460 -------------------------- 462 -------------------------- 472 addra => r.dmaWrTrack.dest,
476 addrb => intAxisMaster.tDest,
479 trackDin <= toSlv(r.dmaWrTrack);
480 trackData <= toAxiWriteDmaTrack(trackDout);
integer := 172 AXI_WRITE_DMA_TRACK_SIZE_C
in axiWriteCtrlAxiCtrlType := AXI_CTRL_UNUSED_C
slv( 63 downto 0) address
slv( 7 downto 0) firstUser
in axisMasterAxiStreamMasterType
out doutbslv( DATA_WIDTH_G- 1 downto 0)
slv( 1023 downto 0) wdata
out dmaWrDescRetAxiWriteDmaDescRetType
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 4
ACK_WAIT_BVALID_Gboolean := true
in axiWriteSlaveAxiWriteSlaveType
AxiCtrlType :=(pause => '0',overflow => '0') AXI_CTRL_UNUSED_C
natural range 1 to 16 TDATA_BYTES_C
BURST_BYTES_Ginteger range 1 to 4096:= 4096
AXI_CONFIG_GAxiConfigType := AXI_CONFIG_INIT_C
AxiWriteDmaDescReqType :=(valid => '0',dest =>( others => '0')) AXI_WRITE_DMA_DESC_REQ_INIT_C
positive range 12 to 64 ADDR_WIDTH_C
AXIS_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
slv( 7 downto 0) lastUser
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
AXI_READY_EN_Gboolean := false
out axiWriteMasterAxiWriteMasterType
out dmaWrDescReqAxiWriteDmaDescReqType
in addrbslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
in dmaWrDescAckAxiWriteDmaDescAckType
out axisSlaveAxiStreamSlaveType
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
in rstasl :=not ( RST_POLARITY_G)
AxiWriteDmaTrackType :=(dest =>( others => '0'),inUse => '0',address =>( others => '0'),maxSize =>( others => '0'),size =>( others => '0'),firstUser =>( others => '0'),contEn => '0',dropEn => '0',id =>( others => '0'),buffId =>( others => '0'),overflow => '0') AXI_WRITE_DMA_TRACK_INIT_C
in axiCacheslv( 3 downto 0)
natural range 0 to 8 TUSER_BITS_C
AxiWriteDmaDescRetType :=(valid => '0',buffId =>( others => '0'),firstUser =>( others => '0'),lastUser =>( others => '0'),size =>( others => '0'),continue => '0',result =>( others => '0'),dest =>( others => '0'),id =>( others => '0')) AXI_WRITE_DMA_DESC_RET_INIT_C
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')
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( 31 downto 0) maxSize
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
AxiConfigType :=axiConfig(ADDR_WIDTH_C => 32,DATA_BYTES_C => 4,ID_BITS_C => 12,LEN_BITS_C => 4) AXI_CONFIG_INIT_C
in rstbsl :=not ( RST_POLARITY_G)
natural range 0 to 8 LEN_BITS_C