1 ------------------------------------------------------------------------------- 2 -- File : AxiStreamDmaV2Desc.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2017-02-02 5 -- Last update: 2017-02-02 6 ------------------------------------------------------------------------------- 8 -- Descriptor manager for AXI DMA read and write engines. 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;
56 -- DMA write descriptor request, ack and return 61 -- DMA read descriptor request, ack and return 72 end AxiStreamDmaV2Desc;
76 constant CROSSBAR_CONN_C : slv(15 downto 0) := x"FFFF";
78 constant CB_COUNT_C : := 2;
80 constant LOC_INDEX_C : := 0;
82 constant LOC_NUM_BITS_C : := 14;
84 constant ADDR_INDEX_C : := 1;
86 constant ADDR_NUM_BITS_C : := 14;
103 type DescStateType is ( IDLE_S, WRITE_S, READ_S, WAIT_S );
107 constant DESC_SIZE_C : := bitSize(DESC_COUNT_C-1);
109 type RegType is record 111 -- Write descriptor interface 115 -- Read descriptor interface 127 buffBaseAddr : slv(63 downto 32);
-- For buffer entries 128 wrBaseAddr : slv(63 downto 0);
-- For wr ring buffer 129 rdBaseAddr : slv(63 downto 0);
-- For rd ring buffer 139 intAckCount : slv(15 downto 0);
140 descCache : slv(3 downto 0);
141 buffCache : slv(3 downto 0);
144 fifoDin : slv(31 downto 0);
146 rdFifoWr : slv(1 downto 0);
149 wrFifoValidDly : slv(1 downto 0);
150 wrAddr : slv(31 downto 0);
153 rdFifoValidDly : slv(1 downto 0);
154 rdAddr : slv(31 downto 0);
157 -- Write Desc Request 159 wrReqNum : slv(CHAN_SIZE_C-1 downto 0);
161 wrReqMissed : slv(31 downto 0);
164 descRetList : slv(DESC_COUNT_C-1 downto 0);
165 descState : DescStateType;
166 descRetNum : slv(DESC_SIZE_C-1 downto 0);
167 descRetAcks : slv(DESC_COUNT_C-1 downto 0);
169 wrMemAddr : slv(63 downto 0);
171 rdMemAddr : slv(63 downto 0);
173 intReqCount : slv(31 downto 0);
178 constant REG_INIT_C : RegType := ( 186 buffBaseAddr => (others => '0'), 187 wrBaseAddr => (others => '0'), 188 rdBaseAddr => (others => '0'), 198 intAckCount => (others=>'0'), 199 descCache => (others=>'0'), 200 buffCache => (others=>'0'), 201 fifoDin => (others=>'0'), 203 rdFifoWr => (others=>'0'), 206 wrFifoValidDly => (others=>'0'), 207 wrAddr => (others=>'0'), 210 rdFifoValidDly => (others=>'0'), 211 rdAddr => (others=>'0'), 214 wrReqNum => (others=>'0'), 215 wrReqAcks => (others=>'0'), 216 wrReqMissed => (others=>'0'), 217 descRetList => (others=>'0'), 219 descRetNum => (others=>'0'), 220 descRetAcks => (others=>'0'), 221 wrIndex => (others=>'0'), 222 wrMemAddr => (others=>'0'), 223 rdIndex => (others=>'0'), 224 rdMemAddr => (others=>'0'), 226 intReqCount => (others=>'0'), 230 signal r : RegType := REG_INIT_C;
231 signal rin : RegType;
233 signal rdFifoValid : slv(1 downto 0);
234 signal rdFifoDout : slv(63 downto 0);
235 signal wrFifoValid : sl;
236 signal wrFifoDout : slv(15 downto 0);
237 signal addrRamDout : slv(31 downto 0);
240 attribute dont_touch : ;
241 attribute dont_touch of r : signal is "true";
243 procedure axiWrDetect (
248 -- Need to remap addr range to be (length-1 downto 0) 249 constant ADDR_LEN_C : := addr'length;
250 constant ADDR_C : slv(ADDR_LEN_C-1 downto 0) := addr;
253 if std_match(ep.axiWriteMaster.awaddr(ADDR_LEN_C-1 downto 2), ADDR_C(ADDR_LEN_C-1 downto 2)) then 262 ----------------------------------------- 264 ----------------------------------------- 284 ----------------------------------------- 285 -- Write Free List FIFO 286 ----------------------------------------- 287 U_DescFifo:
entity work.
Fifo 298 din => r.fifoDin
(15 downto 0),
302 valid => wrFifoValid
);
304 ----------------------------------------- 305 -- Read Transaction FIFOs 306 ----------------------------------------- 307 U_RdLowFifo:
entity work.
Fifo 317 wr_en => r.rdFifoWr
(0),
321 dout => rdFifoDout
(31 downto 0),
322 valid => rdFifoValid
(0));
324 U_RdHighFifo:
entity work.
Fifo 334 wr_en => r.rdFifoWr
(1),
338 dout => rdFifoDout
(63 downto 32),
339 valid => rdFifoValid
(1));
341 ----------------------------------------- 343 ----------------------------------------- 362 dout => addrRamDout
);
364 addrRamAddr <= wrFifoDout(DESC_AWIDTH_G-1 downto 0) when r.addrFifoSel = '0' else 367 ----------------------------------------- 369 ----------------------------------------- 371 -- Choose pause source 376 wrFifoDout, wrFifoValid, rdFifoDout, rdFifoValid, addrRamDout,
pause, r)
is 378 variable v : RegType;
380 --variable descRetList : slv(DESC_COUNT_C-1 downto 0); 381 variable descRetValid : sl;
382 variable descIndex : ;
385 variable regCon : AxiLiteEndPointType;
388 -- Latch the current value 391 -- Clear one shot signals 398 ----------------------------- 400 ----------------------------- 402 -- Start transaction block 405 axiSlaveRegister(regCon, x"000", 0, v.enable);
406 axiSlaveRegisterR(regCon, x"000", 24, toSlv(2,8));
-- Version 2 = 2, Version1 = 0 408 axiSlaveRegister(regCon, x"004", 0, v.intEnable);
409 axiSlaveRegister(regCon, x"008", 0, v.contEn);
410 axiSlaveRegister(regCon, x"00C", 0, v.dropEn);
411 axiSlaveRegister(regCon, x"010", 0, v.wrBaseAddr(31 downto 0));
412 axiSlaveRegister(regCon, x"014", 0, v.wrBaseAddr(63 downto 32));
413 axiSlaveRegister(regCon, x"018", 0, v.rdBaseAddr(31 downto 0));
414 axiSlaveRegister(regCon, x"01C", 0, v.rdBaseAddr(63 downto 32));
415 axiSlaveRegister(regCon, x"020", 0, v.fifoReset);
416 axiSlaveRegister(regCon, x"024", 0, v.buffBaseAddr(63 downto 32));
417 axiSlaveRegister(regCon, x"028", 0, v.maxSize);
418 axiSlaveRegister(regCon, x"02C", 0, v.online);
419 axiSlaveRegister(regCon, x"030", 0, v.acknowledge);
421 axiSlaveRegisterR(regCon, x"034", 0, toSlv(CHAN_COUNT_G,8));
422 axiSlaveRegisterR(regCon, x"038", 0, toSlv(DESC_AWIDTH_G,8));
423 axiSlaveRegister(regCon, x"03C", 0, v.descCache);
424 axiSlaveRegister(regCon, x"03C", 8, v.buffCache);
426 axiSlaveRegister(regCon, x"040", 0, v.fifoDin);
427 axiWrDetect(regCon, x"040", v.rdFifoWr(0));
429 axiSlaveRegister(regCon, x"044", 0, v.fifoDin);
430 axiWrDetect(regCon, x"044", v.rdFifoWr(1));
432 axiSlaveRegister(regCon, x"048", 0, v.fifoDin);
433 axiWrDetect(regCon, x"048", v.wrFifoWr);
435 axiSlaveRegister(regCon, x"04C", 0, v.intAckCount);
436 axiSlaveRegister(regCon, x"04C", 17, v.intEnable);
437 axiWrDetect(regCon, x"04C", v.intAckEn);
439 axiSlaveRegisterR(regCon, x"050", 0, r.intReqCount);
440 axiSlaveRegisterR(regCon, x"054", 0, r.wrIndex);
441 axiSlaveRegisterR(regCon, x"058", 0, r.rdIndex);
443 axiSlaveRegisterR(regCon, x"05C", 0, r.wrReqMissed);
445 -- End transaction block 448 -------------------------------------- 449 -- Address FIFO Control 450 -------------------------------------- 451 -- Alternate between read and write FIFOs to common address pool 452 v.addrFifoSel := not v.addrFifoSel;
455 if r.wrFifoRd = '1' then 456 v.wrFifoValidDly := (others=>'0');
457 v.wrAddr := (others=>'1');
458 v.wrAddrValid := '0';
460 v.wrFifoValidDly := (wrFifoValid and (not r.addrFifoSel)) & r.wrFifoValidDly(1);
461 if r.wrFifoValidDly(0) = '1' then 462 v.wrAddr := addrRamDout;
463 v.wrAddrValid := '1';
468 if r.rdFifoRd = '1' then 469 v.rdFifoValidDly := (others=>'0');
470 v.rdAddr := (others=>'1');
471 v.rdAddrValid := '0';
473 v.rdFifoValidDly := (rdFifoValid(0) and rdFifoValid(1) and r.addrFifoSel) & r.rdFifoValidDly(1);
474 if r.rdFifoValidDly(0) = '1' then 475 v.rdAddr := addrRamDout;
476 v.rdAddrValid := '1';
480 -------------------------------------- 481 -- Write Descriptor Requests 482 -------------------------------------- 490 if r.wrReqValid = '0' then 493 wrReqList := (others=>'0');
498 -- Aribrate between requesters 499 if r.enable = '1' and r.wrFifoRd = '0' and r.wrAddrValid = '1' then 500 arbitrate(wrReqList, r.wrReqNum, v.wrReqNum, v.wrReqValid, v.wrReqAcks);
503 if r.enable = '0' then 504 v.wrReqMissed := (others=>'0');
505 elsif wrReqList /= 0 and wrFifoValid = '0' then 506 v.wrReqMissed := r.wrReqMissed + 1;
509 -- Valid arbitration result 526 -------------------------------------- 527 -- Read/Write Descriptor Returns 528 -------------------------------------- 537 -- Reset strobing Signals 546 -- Generate descriptor ring addresses 547 v.wrMemAddr := v.wrBaseAddr + (v.wrIndex & "000");
548 v.rdMemAddr := v.rdBaseAddr + (v.rdIndex & "000");
552 ---------------------------------------------------------------------- 556 v.descRetList := (others=>'0');
562 -- Aribrate between requesters 563 if r.enable = '1' and pause = '0' then 564 arbitrate(v.descRetList, r.descRetNum, v.descRetNum, descRetValid, v.descRetAcks);
567 if descRetValid = '1' then 568 if v.descRetNum(0) = '1' then 569 v.descState := READ_S;
571 v.descState := WRITE_S;
576 ---------------------------------------------------------------------- 579 descIndex := conv_integer(r.descRetNum(DESC_SIZE_C-1 downto 1));
584 -- Write address channel 588 -- Write data channel 601 -- Encoded channel into upper destination bits 608 v.wrIndex := r.wrIndex + 1;
609 v.descState := WAIT_S;
613 ---------------------------------------------------------------------- 616 descIndex := conv_integer(r.descRetNum(DESC_SIZE_C-1 downto 1));
621 -- Write address channel 625 -- Write data channel 638 v.rdIndex := r.rdIndex + 1;
639 v.descState := WAIT_S;
643 ---------------------------------------------------------------------- 648 v.descState := IDLE_S;
652 v.descState := IDLE_S;
657 if r.intReqCount /= 0 then 664 if r.intAckEn = '1' then 669 if r.intAckCount > r.intReqCount then 670 v.intReqCount := (others=>'0');
672 v.intReqCount := r.intReqCount - r.intAckCount;
675 -- Firmware posted an entry 676 elsif r.intReqEn = '1' then 677 v.intReqCount := r.intReqCount + 1;
682 if r.enable = '0' then 685 v.intReqCount := (others=>'0');
689 -------------------------------------- 690 -- Read Descriptor Requests 691 -------------------------------------- 702 dmaRdReq.valid := r.rdAddrValid;
703 dmaRdReq.address := r.buffBaseAddr & r.rdAddr;
704 dmaRdReq.dest := rdFifoDout(63 downto 56);
705 dmaRdReq.size(23 downto 0) := rdFifoDout(55 downto 32);
706 dmaRdReq.firstUser := rdFifoDout(31 downto 24);
707 dmaRdReq.lastUser := rdFifoDout(23 downto 16);
708 dmaRdReq.buffId(11 downto 0) := rdFifoDout(15 downto 4);
711 -- Upper dest bits select channel 713 rdIndex := conv_integer(dmaRdReq.dest(7 downto 8-CHAN_SIZE_C));
714 dmaRdReq.dest(7 downto 8-CHAN_SIZE_C) := (others=>'0');
719 -- Pull next entry if we are not waiting for ack on given channel 725 -------------------------------------- 726 if r.enable = '0' then 727 v.wrIndex := (others=>'0');
728 v.rdIndex := (others=>'0');
736 -- Register the variable for next clock cycle 757 if (rising_edge(axiClk)) then 758 r <= rin after TPD_G;
in dinslv( DATA_WIDTH_G- 1 downto 0)
slv( 63 downto 0) address
in mAxiWriteSlavesAxiLiteWriteSlaveArray( NUM_MASTER_SLOTS_G- 1 downto 0)
out dmaRdDescReqAxiReadDmaDescReqArray( CHAN_COUNT_G- 1 downto 0)
out dmaRdDescRetAckslv( CHAN_COUNT_G- 1 downto 0)
slv( 15 downto 0) connectivity
AXI_CONFIG_GAxiConfigType := AXI_CONFIG_INIT_C
in addrslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
out dmaWrDescRetAckslv( CHAN_COUNT_G- 1 downto 0)
array(natural range <> ) of AxiWriteDmaDescReqType AxiWriteDmaDescReqArray
array(natural range <> ) of AxiLiteWriteSlaveType AxiLiteWriteSlaveArray
array(natural range <> ) of AxiReadDmaDescRetType AxiReadDmaDescRetArray
in mAxiReadSlavesAxiLiteReadSlaveArray( NUM_MASTER_SLOTS_G- 1 downto 0)
slv( 7 downto 0) firstUser
array(natural range <> ) of AxiReadDmaDescReqType AxiReadDmaDescReqArray
NUM_SLAVE_SLOTS_Gnatural range 1 to 16:= 4
array(natural range <> ) of AxiWriteDmaDescAckType AxiWriteDmaDescAckArray
FWFT_EN_Gboolean := false
slv( 1023 downto 0) wdata
in axilWriteMasterAxiLiteWriteMasterType
out dmaWrDescAckAxiWriteDmaDescAckArray( CHAN_COUNT_G- 1 downto 0)
out doutslv( DATA_WIDTH_G- 1 downto 0)
in axiWriteSlaveAxiWriteSlaveType
CHAN_COUNT_Ginteger range 1 to 16:= 1
array(natural range <> ) of AxiLiteReadMasterType AxiLiteReadMasterArray
DATA_WIDTH_Ginteger := 32
out acknowledgeslv( CHAN_COUNT_G- 1 downto 0)
AxiCtrlType :=(pause => '0',overflow => '0') AXI_CTRL_UNUSED_C
slv( 31 downto 0) baseAddr
in dmaWrDescRetAxiWriteDmaDescRetArray( CHAN_COUNT_G- 1 downto 0)
in dmaRdDescRetAxiReadDmaDescRetArray( CHAN_COUNT_G- 1 downto 0)
array(natural range <> ) of AxiWriteDmaDescRetType AxiWriteDmaDescRetArray
AxiLiteStatusType axiStatus
slv( 7 downto 0) lastUser
array(natural range <> ) of AxiLiteCrossbarMasterConfigType AxiLiteCrossbarMasterConfigArray
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
MASTERS_CONFIG_GAxiLiteCrossbarMasterConfigArray := AXIL_XBAR_CFG_DEFAULT_C
DEC_ERROR_RESP_Gslv( 1 downto 0) := AXI_RESP_DECERR_C
out axiReadSlaveAxiLiteReadSlaveType
in axiWriteMasterAxiLiteWriteMasterType
COMMON_CLK_Gboolean := false
AxiReadDmaDescReqType :=(valid => '0',address =>( others => '0'),buffId =>( others => '0'),firstUser =>( others => '0'),lastUser =>( others => '0'),size =>( others => '0'),continue => '0',id =>( others => '0'),dest =>( others => '0')) AXI_READ_DMA_DESC_REQ_INIT_C
in axilReadMasterAxiLiteReadMasterType
out axilReadSlaveAxiLiteReadSlaveType
out mAxiReadMastersAxiLiteReadMasterArray( NUM_MASTER_SLOTS_G- 1 downto 0)
DESC_AWIDTH_Ginteger range 4 to 12:= 12
AxiLiteReadSlaveType :=(arready => '0',rdata =>( others => '0'),rresp =>( others => '0'),rvalid => '0') AXI_LITE_READ_SLAVE_INIT_C
in dmaRdDescAckslv( CHAN_COUNT_G- 1 downto 0)
GEN_SYNC_FIFO_Gboolean := false
NUM_MASTER_SLOTS_Gnatural range 1 to 64:= 4
out axiCacheslv( 3 downto 0)
in dmaWrDescReqAxiWriteDmaDescReqArray( CHAN_COUNT_G- 1 downto 0)
out axilWriteSlaveAxiLiteWriteSlaveType
AxiWriteDmaDescAckType :=(valid => '0',address =>( others => '0'),dropEn => '0',maxSize =>( others => '0'),contEn => '0',buffId =>( others => '0')) AXI_WRITE_DMA_DESC_ACK_INIT_C
out doutslv( DATA_WIDTH_G- 1 downto 0)
in rstsl :=not RST_POLARITY_G
array(natural range <> ) of AxiLiteWriteMasterType AxiLiteWriteMasterArray
in axiWriteCtrlAxiCtrlType := AXI_CTRL_UNUSED_C
AXIL_BASE_ADDR_Gslv( 31 downto 0) := x"00000000"
in axiReadMasterAxiLiteReadMasterType
slv( 31 downto 0) maxSize
out axiWriteSlaveAxiLiteWriteSlaveType
ADDR_WIDTH_Ginteger range 4 to 48:= 4
slv( 1 downto 0) := "00" AXI_RESP_OK_C
AXI_READY_EN_Gboolean := false
BRAM_EN_Gboolean := false
array(natural range <> ) of AxiLiteReadSlaveType AxiLiteReadSlaveArray
out mAxiWriteMastersAxiLiteWriteMasterArray( NUM_MASTER_SLOTS_G- 1 downto 0)
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 5
AXI_ERROR_RESP_Gslv( 1 downto 0) := AXI_RESP_OK_C
AxiConfigType :=axiConfig(ADDR_WIDTH_C => 32,DATA_BYTES_C => 4,ID_BITS_C => 12,LEN_BITS_C => 4) AXI_CONFIG_INIT_C
AxiLiteWriteSlaveType :=(awready => '0',wready => '0',bresp =>( others => '0'),bvalid => '0') AXI_LITE_WRITE_SLAVE_INIT_C
ACK_WAIT_BVALID_Gboolean := true
out onlineslv( CHAN_COUNT_G- 1 downto 0)
out axiWriteMasterAxiWriteMasterType