1 ------------------------------------------------------------------------------- 2 -- File : AxiLiteRingBuffer.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2014-05-02 5 -- Last update: 2016-02-05 6 ------------------------------------------------------------------------------- 7 -- Description: Wrapper for simple BRAM based ring buffer with AXI-Lite interface 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_arith.
all;
21 use ieee.std_logic_unsigned.
all;
30 -- General Configurations 38 -- Data to store in ring buffer 45 -- AXI-Lite interface for readout 52 end AxiLiteRingBuffer;
56 ------------------------------ 57 -- Stream clock domain signals 58 ------------------------------ 59 type DataRegType is record 67 constant DATA_REG_INIT_C : DataRegType := ( 69 ramWrData => (others => '0'), 70 bufferLength => (others => '0'), 71 firstAddr => (others => '0'), 72 nextAddr => (others => '0'));
74 signal dataR : DataRegType := DATA_REG_INIT_C;
75 signal dataRin : DataRegType;
77 signal axilBufferEnable : sl;
-- Synchronized AXI register 78 signal axilBufferClear : sl;
-- Synchronized AXI register 80 -------------------------------- 81 -- AXI-Lite clock domain signals 82 -------------------------------- 85 type AxilRegType is record 89 axilRdEn : slv(2 downto 0);
94 constant AXIL_REG_INIT_C : AxilRegType := ( 97 ramRdAddr => (others => '0'), 102 signal axilR : AxilRegType := AXIL_REG_INIT_C;
103 signal axilRin : AxilRegType;
109 signal extBufferEnable : sl;
110 signal extBufferClear : sl;
114 ---------------------- 115 -- Instantiate the RAM 116 ---------------------- 128 wea => dataR.ramWrEn,
130 addra => dataR.nextAddr,
131 dina => dataR.ramWrData,
135 addrb => axilR.ramRdAddr,
136 doutb => axilRamRdData
);
138 ------------------------------- 139 -- Synchronize AXI registers to data clock dataClk 140 ------------------------------- 147 dataIn => axilR.bufferEnable,
156 dataIn => axilR.bufferClear,
159 -------------------------- 160 -- Main AXI-Stream process 161 -------------------------- 164 variable v : DataRegType;
165 variable enable : sl;
168 -- Latch the current value 174 -- Default assignment 176 enable := bufferEnable
or axilBufferEnable;
179 -- Increment the addresses on each valid if logging enabled 180 if (dataValid = '1') and (enable = '1') then 184 -- Increment the address 185 v.nextAddr := dataR.nextAddr + 1;
186 -- Check if the write pointer = read pointer 187 if (v.nextAddr = dataR.firstAddr) then 188 v.firstAddr := dataR.firstAddr + 1;
190 -- Calculate the length of the buffer 191 v.bufferLength := dataR.nextAddr - dataR.firstAddr;
195 if (dataRst = '1') or (clear = '1') then 196 v := DATA_REG_INIT_C;
199 -- Register the variable for next clock cycle 207 dataR <= dataRin after TPD_G;
211 ----------------------------------------------------- 212 -- Synchronize write address across to AXI-Lite clock 213 ----------------------------------------------------- 221 din => dataR.firstAddr,
223 dout => axilFirstAddr
);
232 din => dataR.bufferLength,
254 ------------------------ 255 -- Main AXI-Lite process 256 ------------------------ 259 variable v : AxilRegType;
261 variable axiWriteResp : slv(1 downto 0);
262 variable axiReadResp : slv(1 downto 0);
264 -- Latch the current value 270 -- Update Shift Register 271 v.axilRdEn(0) := '0';
272 v.axilRdEn(1) := axilR.axilRdEn(0);
273 v.axilRdEn(2) := axilR.axilRdEn(1);
275 -- Determine the transaction type 278 -- Check for write request 280 -- Check for an out of 32 bit aligned address 282 -- Check for first mapped address access (which is the control register) 287 -- Unmapped write register access 290 -- Set the Slave's response 294 -- Check for read request 296 -- Reset the read data bus 298 -- Check for an out of 32 bit aligned address 300 -- Control register mapped at address 0 310 -- All other AXI-Lite addresses are automatically offset by firstAddr. 311 -- Thus axil word-address 1 always pulls from firstAddr, etc. 314 -- Wait 3 cycles before placing the ram read data on the AXIL bus and responding. 315 -- This is enough time to cover every ram type 316 -- LUTRAM + !REG_EN_G = 1 Cycle 317 -- LUTRAM + REG_EN_G = 2 Cycles 318 -- BRAM + !REG_EN_G = 2 Cycles 319 -- BRAM + REG_EN_G = 3 Cycles 320 v.axilRdEn(0) := '1';
321 if (axilR.axilRdEn(2) = '1') then 322 -- Reset the shift register 324 -- Update the read data bus 326 -- Set the Slave's response 334 v := AXIL_REG_INIT_C;
337 -- Register the variable for next clock cycle 349 axilR <= axilRin after TPD_G;
out axilWriteSlaveAxiLiteWriteSlaveType
out axilReadSlaveAxiLiteReadSlaveType
in rstsl :=not RST_POLARITY_G
in dinslv( DATA_WIDTH_G- 1 downto 0)
out doutbslv( DATA_WIDTH_G- 1 downto 0)
DATA_WIDTH_Gpositive range 1 to 32:= 32
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 4
MODE_Gstring := "read-first"
out doutslv( DATA_WIDTH_G- 1 downto 0)
in rstsl :=not RST_POLARITY_G
in axilReadMasterAxiLiteReadMasterType
slv( 1 downto 0) := "11" AXI_RESP_DECERR_C
DOB_REG_Gboolean := false
RAM_ADDR_WIDTH_Gpositive range 1 to 19:= 10
out doutaslv( DATA_WIDTH_G- 1 downto 0)
in addrbslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
in dataValueslv( DATA_WIDTH_G- 1 downto 0)
AxiLiteReadSlaveType :=(arready => '0',rdata =>( others => '0'),rresp =>( others => '0'),rvalid => '0') AXI_LITE_READ_SLAVE_INIT_C
in rstasl :=not ( RST_POLARITY_G)
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')
in axilWriteMasterAxiLiteWriteMasterType
slv( 1 downto 0) := "00" AXI_RESP_OK_C
AXI_ERROR_RESP_Gslv( 1 downto 0) := AXI_RESP_DECERR_C
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
in rstbsl :=not ( RST_POLARITY_G)
AxiLiteWriteSlaveType :=(awready => '0',wready => '0',bresp =>( others => '0'),bvalid => '0') AXI_LITE_WRITE_SLAVE_INIT_C
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16