1 ------------------------------------------------------------------------------- 2 -- File : AxiLiteCrossbar.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2013-09-24 5 -- Last update: 2017-05-09 6 ------------------------------------------------------------------------------- 7 -- Description: Wrapper around Xilinx generated Main AXI Crossbar for HPS Front End 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;
42 -- Slave Slots (Connect to AxiLite Masters 48 -- Master Slots (Connect to AXI Slaves) 56 end entity AxiLiteCrossbar;
60 type SlaveStateType is (S_WAIT_AXI_TXN_S, S_DEC_ERR_S, S_ACK_S, S_TXN_S);
65 type SlaveType is record 66 wrState : SlaveStateType;
68 wrReqNum : slv(REQ_NUM_SIZE_C-1 downto 0);
69 rdState : SlaveStateType;
71 rdReqNum : slv(REQ_NUM_SIZE_C-1 downto 0);
74 type SlaveArray is array ( range <>) of SlaveType;
76 type MasterStateType is (M_WAIT_REQ_S, M_WAIT_READYS_S, M_WAIT_REQ_FALL_S);
78 type MasterType is record 79 wrState : MasterStateType;
81 wrAckNum : slv(ACK_NUM_SIZE_C-1 downto 0);
83 rdState : MasterStateType;
85 rdAckNum : slv(ACK_NUM_SIZE_C-1 downto 0);
87 end record MasterType;
89 type MasterArray is array ( range <>) of MasterType;
91 type RegType is record 100 constant REG_INIT_C : RegType := ( 103 wrState => S_WAIT_AXI_TXN_S, 104 wrReqs => (others => '0'), 105 wrReqNum => (others => '0'), 106 rdState => S_WAIT_AXI_TXN_S, 107 rdReqs => (others => '0'), 108 rdReqNum => (others => '0'))), 111 wrState => M_WAIT_REQ_S, 112 wrAcks => (others => '0'), 113 wrAckNum => (others => '0'), 115 rdState => M_WAIT_REQ_S, 116 rdAcks => (others => '0'), 117 rdAckNum => (others => '0'), 124 signal r : RegType := REG_INIT_C;
125 signal rin : RegType;
131 print(DEBUG_G, "AXI_LITE_CROSSBAR: " & LF & 135 "MASTERS_CONFIG_G:");
142 end generate printCfg;
145 variable v : RegType;
152 -- Control slave side outputs 164 -- Reset rvalid upon rready 169 -- Write state machine 170 case (r.slave(s).wrState) is 171 when S_WAIT_AXI_TXN_S => 177 -- Check for address match 181 v.slave(s).wrReqs(m) := '1';
182 v.slave(s).wrReqNum := conv_std_logic_vector(m, REQ_NUM_SIZE_C);
183 -- print("AxiLiteCrossbar: Slave " & str(s) & " reqd Master " & str(m) & " Write addr " & hstr(sAxiWriteMasters(s).awaddr)); 187 -- Respond with error if decode fails 188 if (uOr(v.slave(s).wrReqs) = '0') then 191 v.slave(s).wrState := S_DEC_ERR_S;
193 v.slave(s).wrState := S_ACK_S;
202 v.slave(s).wrState := S_WAIT_AXI_TXN_S;
205 -- Transaction is acked 208 if (r.slave(s).wrReqNum = m and r.slave(s).wrReqs(m) = '1' and r.master(m).wrAcks(s) = '1') then 211 v.slave(s).wrState := S_TXN_S;
215 -- Transaction in progress 218 if (r.slave(s).wrReqNum = m and r.slave(s).wrReqs(m) = '1' and r.master(m).wrAcks(s) = '1') then 220 -- Forward write response 224 -- bvalid or rvalid indicates txn concluding 227 v.slave(s).wrReqs := (others => '0');
228 v.slave(s).wrState := S_WAIT_AXI_TXN_S;
234 -- Read state machine 235 case (r.slave(s).rdState) is 236 when S_WAIT_AXI_TXN_S => 241 -- Check for address match 245 v.slave(s).rdReqs(m) := '1';
246 v.slave(s).rdReqNum := conv_std_logic_vector(m, REQ_NUM_SIZE_C);
250 -- Respond with error if decode fails 251 if (uOr(v.slave(s).rdReqs) = '0') then 253 v.slave(s).rdState := S_DEC_ERR_S;
255 v.slave(s).rdState := S_ACK_S;
265 v.slave(s).rdState := S_WAIT_AXI_TXN_S;
268 -- Transaction is acked 271 if (r.slave(s).rdReqNum = m and r.slave(s).rdReqs(m) = '1' and r.master(m).rdAcks(s) = '1') then 273 v.slave(s).rdState := S_TXN_S;
277 -- Transaction in progress 280 if (r.slave(s).rdReqNum = m and r.slave(s).rdReqs(m) = '1' and r.master(m).rdAcks(s) = '1') then 282 -- Forward read response 287 -- rvalid indicates txn concluding 290 v.slave(s).rdReqs := (others => '0');
291 v.slave(s).rdState := S_WAIT_AXI_TXN_S;
--S_WAIT_DONE_S; 299 -- Control master side outputs 302 -- Group reqs by master 303 mWrReqs := (others => '0');
304 mRdReqs := (others => '0');
305 for i in mWrReqs'range loop 306 mWrReqs(i) := r.slave(i).wrReqs(m);
307 mRdReqs(i) := r.slave(i).rdReqs(m);
310 -- Write path processing 311 case (r.master(m).wrState) is 314 -- Keep these in reset state while waiting for requests 315 v.master(m).wrAcks := (others => '0');
318 -- Wait for a request, arbitrate between simultaneous requests 319 if (r.master(m).wrValid = '0') then 320 arbitrate(mWrReqs, r.master(m).wrAckNum, v.master(m).wrAckNum, v.master(m).wrValid, v.master(m).wrAcks);
323 -- Upon valid request (set 1 cycle previous by arbitrate()), connect slave side 324 -- busses to this master's outputs. 325 if (r.master(m).wrValid = '1') then 326 v.master(m).wrAcks := r.master(m).wrAcks;
328 v.master(m).wrState := M_WAIT_READYS_S;
331 when M_WAIT_READYS_S => 333 -- Wait for attached slave to respond 334 -- Clear *valid signals upon *ready responses 342 -- When all *valid signals cleared, wait for slave side to clear request 344 v.master(m).wrState := M_WAIT_REQ_FALL_S;
347 when M_WAIT_REQ_FALL_S => 348 -- When slave side deasserts request, clear ack and valid and start waiting for next 350 if (mWrReqs(conv_integer(r.master(m).wrAckNum)) = '0') then 351 v.master(m).wrState := M_WAIT_REQ_S;
352 v.master(m).wrAcks := (others => '0');
353 v.master(m).wrValid := '0';
358 -- Don't allow baseAddr bits to be overwritten 359 -- They can't be anyway based on the logic above, but Vivado can't figure that out. 360 -- This helps optimization happen properly 366 -- Read path processing 367 case (r.master(m).rdState) is 370 -- Keep these in reset state while waiting for requests 371 v.master(m).rdAcks := (others => '0');
374 -- Wait for a request, arbitrate between simultaneous requests 375 if (r.master(m).rdValid = '0') then 376 arbitrate(mRdReqs, r.master(m).rdAckNum, v.master(m).rdAckNum, v.master(m).rdValid, v.master(m).rdAcks);
379 -- Upon valid request (set 1 cycle previous by arbitrate()), connect slave side 380 -- busses to this master's outputs. 381 if (r.master(m).rdValid = '1') then 382 v.master(m).rdAcks := r.master(m).rdAcks;
384 v.master(m).rdState := M_WAIT_READYS_S;
387 when M_WAIT_READYS_S => 389 -- Wait for attached slave to respond 390 -- Clear *valid signals upon *ready responses 395 -- When all *valid signals cleared, wait for slave side to clear request 397 v.master(m).rdState := M_WAIT_REQ_FALL_S;
400 when M_WAIT_REQ_FALL_S => 401 -- When slave side deasserts request, clear ack and valid and start waiting for next 403 if (mRdReqs(conv_integer(r.master(m).rdAckNum)) = '0') then 404 v.master(m).rdState := M_WAIT_REQ_S;
405 v.master(m).rdAcks := (others => '0');
406 v.master(m).rdValid := '0';
411 -- Don't allow baseAddr bits to be overwritten 412 -- They can't be anyway based on the logic above, but Vivado can't figure that out. 413 -- This helps optimization happen properly 434 if (rising_edge(axiClk)) then 435 r <= rin after TPD_G;
439 end architecture rtl;
in mAxiWriteSlavesAxiLiteWriteSlaveArray( NUM_MASTER_SLOTS_G- 1 downto 0)
AxiLiteCrossbarMasterConfigArray( 0 to 3) :=( 0=>(baseAddr => X"00000000",addrBits => 16,connectivity => X"FFFF"), 1=>(baseAddr => X"00010000",addrBits => 16,connectivity => X"FFFF"), 2=>(baseAddr => X"00020000",addrBits => 16,connectivity => X"FFFF"), 3=>(baseAddr => X"00030000",addrBits => 16,connectivity => X"FFFF")) AXIL_XBAR_CFG_DEFAULT_C
slv( 15 downto 0) connectivity
array(natural range <> ) of AxiLiteWriteSlaveType AxiLiteWriteSlaveArray
in mAxiReadSlavesAxiLiteReadSlaveArray( NUM_MASTER_SLOTS_G- 1 downto 0)
NUM_SLAVE_SLOTS_Gnatural range 1 to 16:= 4
in sAxiWriteMastersAxiLiteWriteMasterArray( NUM_SLAVE_SLOTS_G- 1 downto 0)
array(natural range <> ) of AxiLiteReadMasterType AxiLiteReadMasterArray
slv( 31 downto 0) baseAddr
in sAxiReadMastersAxiLiteReadMasterArray( NUM_SLAVE_SLOTS_G- 1 downto 0)
array(natural range <> ) of AxiLiteCrossbarMasterConfigType AxiLiteCrossbarMasterConfigArray
MASTERS_CONFIG_GAxiLiteCrossbarMasterConfigArray := AXIL_XBAR_CFG_DEFAULT_C
DEC_ERROR_RESP_Gslv( 1 downto 0) := AXI_RESP_DECERR_C
slv( 1 downto 0) := "11" AXI_RESP_DECERR_C
out mAxiReadMastersAxiLiteReadMasterArray( NUM_MASTER_SLOTS_G- 1 downto 0)
AxiLiteReadSlaveType :=(arready => '0',rdata =>( others => '0'),rresp =>( others => '0'),rvalid => '0') AXI_LITE_READ_SLAVE_INIT_C
NUM_MASTER_SLOTS_Gnatural range 1 to 64:= 4
array(natural range <> ) of AxiLiteWriteMasterType AxiLiteWriteMasterArray
out sAxiReadSlavesAxiLiteReadSlaveArray( NUM_SLAVE_SLOTS_G- 1 downto 0)
array(natural range <> ) of AxiLiteReadSlaveType AxiLiteReadSlaveArray
out mAxiWriteMastersAxiLiteWriteMasterArray( NUM_MASTER_SLOTS_G- 1 downto 0)
AxiLiteWriteSlaveType :=(awready => '0',wready => '0',bresp =>( others => '0'),bvalid => '0') AXI_LITE_WRITE_SLAVE_INIT_C
out sAxiWriteSlavesAxiLiteWriteSlaveArray( NUM_SLAVE_SLOTS_G- 1 downto 0)