1 ------------------------------------------------------------------------------- 2 -- File : AxiStreamDmaRingWrite.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2015-09-29 5 -- Last update: 2017-02-20 6 ------------------------------------------------------------------------------- 7 -- Description: AXI Stream to DMA Ring Buffer Write Module 8 ------------------------------------------------------------------------------- 9 -- This file is part of 'SLAC Firmware Standard Library'. 10 -- It is subject to the license terms in the LICENSE.txt file found in the 11 -- top-level directory of this distribution and at: 12 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. 13 -- No part of 'SLAC Firmware Standard Library', including this file, 14 -- may be copied, modified, propagated, or distributed except according to 15 -- the terms contained in the LICENSE.txt file. 16 ------------------------------------------------------------------------------- 19 use ieee.std_logic_1164.
all;
20 use ieee.std_logic_unsigned.
all;
21 use ieee.std_logic_arith.
all;
38 ENABLE_UNALIGN_G : := false;
44 BYP_SHIFT_G : := true;
-- Bypass both because we do not want them to back-pressure 45 BYP_CACHE_G : := true);
-- Bypass both because we do not want them to back-pressure 47 -- AXI-Lite Interface for local registers 61 -- AXI (DDR) clock domain 64 -- Axi Stream data to be buffered 67 -- Low level buffer control 77 -- AXI4 Interface for RAM 81 end entity AxiStreamDmaRingWrite;
85 -- Ram contents represent AXI address shifted by 2 87 constant RAM_ADDR_WIDTH_C : := log2(BUFFERS_G);
89 constant AXIL_RAM_ADDR_WIDTH_C : := RAM_ADDR_WIDTH_C + log2((RAM_DATA_WIDTH_C-1)/4);
93 -- Create burst size constant for status 96 -- 15 = burst size 131072 97 constant BURST_SIZE_SLV_C : slv(3 downto 0) := toSlv(DMA_ADDR_LOW_C-2, 4);
99 function statusRamInit 101 variable ret : slv(31 downto 0) := (others => '0');
109 ret(FST_C) := (others => '0');
111 end function statusRamInit;
113 constant STATUS_RAM_INIT_C : slv(31 downto 0) := statusRamInit;
148 ssiAxiStreamConfig(1, TKEEP_FIXED_C, TUSER_FIRST_LAST_C, 4);
150 -- TSTRB_EN_C => false, 151 -- TDATA_BYTES_C => 1, 152 -- TDEST_BITS_C => 4, 154 -- TKEEP_MODE_C => TKEEP_FIXED_C, --ite(BSA_STREAM_BYTE_WIDTH_G = 4, TKEEP_FIXED_C, TKEEP_COMP_C), 155 -- TUSER_BITS_C => 2, 156 -- TUSER_MODE_C => TUSER_NONE_C); 158 type StateType is (WAIT_TVALID_S, ASSERT_ADDR_S, LATCH_POINTERS_S, WAIT_DMA_DONE_S);
160 type RegType is record 161 wrRamAddr : slv(RAM_ADDR_WIDTH_C-1 downto 0);
162 rdRamAddr : slv(RAM_ADDR_WIDTH_C-1 downto 0);
163 activeBuffer : slv(RAM_ADDR_WIDTH_C-1 downto 0);
166 nextAddr : slv(RAM_DATA_WIDTH_C-1 downto 0);
167 startAddr : slv(RAM_DATA_WIDTH_C-1 downto 0);
168 endAddr : slv(RAM_DATA_WIDTH_C-1 downto 0);
169 trigAddr : slv(RAM_DATA_WIDTH_C-1 downto 0);
170 mode : slv(31 downto 0);
171 status : slv(31 downto 0);
186 constant REG_INIT_C : RegType := ( 187 wrRamAddr => (others => '0'), 188 rdRamAddr => (others => '0'), 189 activeBuffer => (others => '0'), 192 nextAddr => (others => '0'), 193 startAddr => (others => '0'), 194 endAddr => (others => '0'), 195 trigAddr => (others => '0'), 196 mode => (others => '0'), 197 status => (others => '0'), 198 state => WAIT_TVALID_S, 205 softTrigger => (others => '0'), 215 signal r : RegType := REG_INIT_C;
216 signal rin : RegType;
219 signal startRamDout : slv(RAM_DATA_WIDTH_C-1 downto 0);
220 signal endRamDout : slv(RAM_DATA_WIDTH_C-1 downto 0);
221 signal nextRamDout : slv(RAM_DATA_WIDTH_C-1 downto 0);
222 signal trigRamDout : slv(RAM_DATA_WIDTH_C-1 downto 0);
223 signal modeRamDout : slv(31 downto 0);
224 signal statusRamDout : slv(31 downto 0);
226 signal modeWrValid : sl;
227 signal modeWrStrobe : slv(3 downto 0);
228 signal modeWrAddr : slv(RAM_ADDR_WIDTH_C-1 downto 0);
229 signal modeWrData : slv(31 downto 0);
232 -- Assert that stream config has enough tdest bits for the number of buffers being tracked 233 -- Assert that BURST_SIZE_BYTES_G is a power of 2 256 ------------------------------------------------------------------------------------------------- 257 -- AXI RAMs store buffer information 258 ------------------------------------------------------------------------------------------------- 259 -- Start Addresses. AXIL writeable 279 dout => startRamDout
);
281 -- End Addresses. AXIL writeable 304 -- Next Addresses. System writeable 326 dout => nextRamDout
);
349 dout => trigRamDout
);
387 INIT_G => STATUS_RAM_INIT_C
) 400 dout => statusRamDout
);
417 dmaReq => r.dmaReq,
-- [in] 418 dmaAck => dmaAck,
-- [out] 424 -- Pass status message through a small fifo to convert to statusClk 450 ------------------------------------------------------------------------------------------------- 452 ------------------------------------------------------------------------------------------------- 454 modeRamDout, modeWrAddr, modeWrData, modeWrStrobe, modeWrValid, nextRamDout, r,
455 startRamDout, statusRamDout, trigRamDout)
is 456 variable v : RegType;
461 -- These registers default to zero 463 v.initBufferEn := '0';
466 -- If last txn of frame, check for trigger condition and EOFE and latch them in registers. 476 -- Check for software trigger. 478 v.softTrigger := r.softTrigger or decode(modeWrAddr);
481 -- Override state machine if a buffer clear is being requested 482 -- This could occur through the ports (bufferClearEn+bufferClear) 483 -- Or through the mode registers 485 v.initBufferEn := '1';
487 v.state := ASSERT_ADDR_S;
488 elsif(modeWrValid = '1' and modeWrData(INIT_C) = '1' and modeWrStrobe(INIT_C/8) = '1') then 489 v.initBufferEn := '1';
490 v.rdRamAddr := modeWrAddr;
491 v.state := ASSERT_ADDR_S;
494 -- Set status and pointers back to init state and write the values to the local ram registers 495 if (r.initBufferEn = '1') then 501 v.status(FST_C) := (others => '0');
502 v.wrRamAddr := r.rdRamAddr;
503 v.nextAddr := startRamDout;
504 v.trigAddr := (others => '1');
510 when WAIT_TVALID_S => 511 -- Only final burst before readout can be short, so no need to worry about next 512 -- burst wrapping awkwardly. Whole thing will be reset after readout. 513 -- Don't do anything if in the middle of a buffer address clear 515 v.activeBuffer := axisDataMaster.tdest(RAM_ADDR_WIDTH_C-1 downto 0);
516 v.state := ASSERT_ADDR_S;
517 elsif (v.initBufferEn = '1') then 518 -- Stay in this state if bufferes need to be cleared 519 v.state := WAIT_TVALID_S;
522 when ASSERT_ADDR_S => 523 -- State holds here as long buffers are being initialized 524 if (v.initBufferEn = '0' and r.initBufferEn = '0') then 525 v.rdRamAddr := r.activeBuffer;
526 v.wrRamAddr := r.activeBuffer;
527 v.state := LATCH_POINTERS_S;
530 when LATCH_POINTERS_S => 532 -- Might go back to ASSERT_ADDR_S if bufferClearEn is high 533 -- But everything this state asserts is still valid 534 v.startAddr := startRamDout;
-- Address of start of buffer 535 v.endAddr := endRamDout;
-- Address of end of buffer 536 v.nextAddr := nextRamDout;
-- Address of next frame in buffer 537 v.trigAddr := trigRamDout;
-- Start address of frame where trigger was seen 538 v.mode := modeRamDout;
-- Number of frames since trigger seen 539 v.status := statusRamDout;
-- Number of frames to log after trigger seen 541 -- Assert a new request. 542 -- Direct that frame be dropped if buffer is done with trigger sequence 543 -- Writes always start on a BURST_SIZE_BYTES_G boundary, so can drive low dmaReq.address 544 -- bits to zero for optimization. 547 v.dmaReq.address(DMA_ADDR_LOW_C-1 downto 0) := (others => '0');
550 -- status(DONE_C) indicates a push, but maybe more than one 551 v.dmaReq.drop := '0';
554 v.state := WAIT_DMA_DONE_S;
556 when WAIT_DMA_DONE_S => 557 -- Wait until DMA transaction is done. 558 -- Must also check that buffer not being cleared so as not to step on the addresses 559 if (dmaAck.done = '1' and v.initBufferEn = '0') then 561 v.dmaReq.request := '0';
-- Deassert dma request 562 v.status(EMPTY_C) := '0';
-- Update empty status 563 v.ramWe := '1';
-- write new values into register ram 565 -- Increment address of last burst in buffer. 566 -- Wrap back to start when it hits the end of the buffer. 567 v.nextAddr := r.nextAddr + dmaAck.size;
--(BURST_SIZE_BYTES_G); -- 568 if (v.nextAddr = r.endAddr) then 573 v.nextAddr := r.startAddr;
576 -- Record trigger position if a trigger was seen on current frame 578 v.softTrigger(conv_integer(r.activeBuffer)) := '0';
579 if ((r.trigger = '1' or r.softTrigger(conv_integer(r.activeBuffer)) = '1') and r.status(TRIGGERED_C) = '0') then 580 v.trigAddr := r.nextAddr;
586 if (r.eofe = '1') then 592 -- Increment FramesSinceTrigger when necessary 601 -- Output status message when done 602 if (v.status(DONE_C) = '1' and r.dmaReq.drop = '0') then 610 v.state := WAIT_TVALID_S;
616 -- Assign status outputs 617 if (r.ramWe = '1') then 625 if(modeWrValid = '1' and modeWrStrobe(ENABLED_C/8) = '1') then 630 ---------------------------------------------------------------------------------------------- 631 -- Reset and output assignment 632 ---------------------------------------------------------------------------------------------- 649 if (rising_edge(axiClk)) then 650 r <= rin after TPD_G;
654 end architecture rtl;
BYP_SHIFT_Gboolean := false
in dmaReqAxiWriteDmaReqType
AXI_WRITE_CONFIG_GAxiConfigType := axiConfig( 32, 8, 1, 8)
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
out dmaAckAxiWriteDmaAckType
slv( 63 downto 0) address
in mAxiWriteSlavesAxiLiteWriteSlaveArray( NUM_MASTER_SLOTS_G- 1 downto 0)
slv( 15 downto 0) connectivity
out axiWrAddrslv( ADDR_WIDTH_G- 1 downto 0)
in addrslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
out axiWriteMasterAxiWriteMasterType
array(natural range <> ) of AxiLiteWriteSlaveType AxiLiteWriteSlaveArray
integer := 5 STATUS_AXIL_C
out axisDataSlaveAxiStreamSlaveType
in mAxiReadSlavesAxiLiteReadSlaveArray( NUM_MASTER_SLOTS_G- 1 downto 0)
PIPE_STAGES_Gnatural range 0 to 16:= 1
out axilReadSlaveAxiLiteReadSlaveType
NUM_SLAVE_SLOTS_Gnatural range 1 to 16:= 4
BYP_CACHE_Gboolean := true
out bufferEnabledslv( BUFFERS_G- 1 downto 0)
ACK_WAIT_BVALID_Gboolean := true
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
out doutslv( DATA_WIDTH_G- 1 downto 0)
integer range 31 downto 16 FST_C
DATA_AXIS_CONFIG_GAxiStreamConfigType := ssiAxiStreamConfig( 8)
BURST_SIZE_BYTES_Gnatural range 4 to 2** 17:= 4096
array(natural range <> ) of AxiLiteReadMasterType AxiLiteReadMasterArray
DATA_WIDTH_Ginteger := 32
SLAVE_READY_EN_Gboolean := true
FIFO_FIXED_THRESH_Gboolean := true
BUFFERS_Gnatural range 2 to 64:= 64
in axilWriteMasterAxiLiteWriteMasterType
out axiWriteMasterAxiWriteMasterType
slv( 31 downto 0) baseAddr
integer := 6 AXIL_MASTERS_C
GEN_SYNC_FIFO_Gboolean := false
in bufferClearslv( log2(BUFFERS_G )- 1 downto 0) :=( others => '0')
positive range 12 to 64 ADDR_WIDTH_C
array(natural range <> ) of AxiLiteCrossbarMasterConfigType AxiLiteCrossbarMasterConfigArray
integer := 1 DONE_WHEN_FULL_C
MASTERS_CONFIG_GAxiLiteCrossbarMasterConfigArray := AXIL_XBAR_CFG_DEFAULT_C
TRIGGER_USER_BIT_Gnatural range 0 to 7:= 2
DEC_ERROR_RESP_Gslv( 1 downto 0) := AXI_RESP_DECERR_C
out axiReadSlaveAxiLiteReadSlaveType
slv( 1 downto 0) := "11" AXI_RESP_DECERR_C
in axiWriteMasterAxiLiteWriteMasterType
COMMON_CLK_Gboolean := false
STATUS_AXIS_CONFIG_GAxiStreamConfigType := ssiAxiStreamConfig( 1)
BYP_CACHE_Gboolean := false
in axisStatusSlaveAxiStreamSlaveType := AXI_STREAM_SLAVE_FORCE_C
AXI_CACHE_Gslv( 3 downto 0) := "1111"
SYS_WR_EN_Gboolean := false
out bufferTriggeredslv( BUFFERS_G- 1 downto 0)
out mAxiReadMastersAxiLiteReadMasterArray( NUM_MASTER_SLOTS_G- 1 downto 0)
out axiWrDataslv( DATA_WIDTH_G- 1 downto 0)
out axilWriteSlaveAxiLiteWriteSlaveType
integer := 0 START_AXIL_C
in axiWriteSlaveAxiWriteSlaveType
AXI_BURST_Gslv( 1 downto 0) := "01"
NUM_MASTER_SLOTS_Gnatural range 1 to 64:= 4
out sAxisSlaveAxiStreamSlaveType
in axiWriteSlaveAxiWriteSlaveType
in axisMasterAxiStreamMasterType
out bufferEmptyslv( BUFFERS_G- 1 downto 0)
integer range 11 downto 8 BURST_SIZE_C
array(natural range <> ) of AxiLiteWriteMasterType AxiLiteWriteMasterArray
in axiReadMasterAxiLiteReadMasterType
out axisStatusMasterAxiStreamMasterType
slv( 31 downto 0) maxSize
in sAxisMasterAxiStreamMasterType
out axiWriteSlaveAxiLiteWriteSlaveType
in dinslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')
out mAxisMasterAxiStreamMasterType
out bufferFullslv( BUFFERS_G- 1 downto 0)
BRAM_EN_Gboolean := false
AxiStreamSlaveType :=(tReady => '1') AXI_STREAM_SLAVE_FORCE_C
out bufferErrorslv( BUFFERS_G- 1 downto 0)
integer := 3 SOFT_TRIGGER_C
integer range 31 downto 16 FAT_C
AXIS_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
array(natural range <> ) of AxiLiteReadSlaveType AxiLiteReadSlaveArray
AXIL_BASE_ADDR_Gslv( 31 downto 0) :=( others => '0')
ENABLE_UNALIGN_Gboolean := false
in mAxisSlaveAxiStreamSlaveType
out mAxiWriteMastersAxiLiteWriteMasterArray( NUM_MASTER_SLOTS_G- 1 downto 0)
USE_BUILT_IN_Gboolean := false
integer range 7 downto 4 STATUS_TDEST_C
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 5
FIFO_PAUSE_THRESH_Ginteger range 1 to ( 2** 24):= 1
VALID_THOLD_Ginteger range 0 to ( 2** 24):= 1
in axilReadMasterAxiLiteReadMasterType
in axisDataMasterAxiStreamMasterType
out axiWrStrobeslv( wordCount( DATA_WIDTH_G, 8)- 1 downto 0)
in bufferClearEnsl := '0'
AXI_CONFIG_GAxiConfigType := AXI_CONFIG_INIT_C
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
AXI_WR_EN_Gboolean := true
out axisSlaveAxiStreamSlaveType
AXI_READY_EN_Gboolean := false
out bufferDoneslv( BUFFERS_G- 1 downto 0)
BYP_SHIFT_Gboolean := true