SURF  1.0
AxiLiteCrossbar.vhd
Go to the documentation of this file.
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 -------------------------------------------------------------------------------
17 
18 library ieee;
19 use ieee.std_logic_1164.all;
20 use ieee.std_logic_arith.all;
21 use ieee.std_logic_unsigned.all;
22 use work.StdRtlPkg.all;
23 use work.AxiLitePkg.all;
24 use work.ArbiterPkg.all;
25 use work.TextUtilPkg.all;
26 
27 --! @see entity
28  --! @ingroup axi
29 entity AxiLiteCrossbar is
30 
31  generic (
32  TPD_G : time := 1 ns;
33  NUM_SLAVE_SLOTS_G : natural range 1 to 16 := 4;
34  NUM_MASTER_SLOTS_G : natural range 1 to 64 := 4;
37  DEBUG_G : boolean := false);
38  port (
39  axiClk : in sl;
40  axiClkRst : in sl;
41 
42  -- Slave Slots (Connect to AxiLite Masters
47 
48  -- Master Slots (Connect to AXI Slaves)
53 
54  );
55 
56 end entity AxiLiteCrossbar;
57 
58 architecture rtl of AxiLiteCrossbar is
59 
60  type SlaveStateType is (S_WAIT_AXI_TXN_S, S_DEC_ERR_S, S_ACK_S, S_TXN_S);
61 
62  constant REQ_NUM_SIZE_C : integer := bitSize(NUM_MASTER_SLOTS_G-1);
63  constant ACK_NUM_SIZE_C : integer := bitSize(NUM_SLAVE_SLOTS_G-1);
64 
65  type SlaveType is record
66  wrState : SlaveStateType;
67  wrReqs : slv(NUM_MASTER_SLOTS_G-1 downto 0);
68  wrReqNum : slv(REQ_NUM_SIZE_C-1 downto 0);
69  rdState : SlaveStateType;
70  rdReqs : slv(NUM_MASTER_SLOTS_G-1 downto 0);
71  rdReqNum : slv(REQ_NUM_SIZE_C-1 downto 0);
72  end record SlaveType;
73 
74  type SlaveArray is array (natural range <>) of SlaveType;
75 
76  type MasterStateType is (M_WAIT_REQ_S, M_WAIT_READYS_S, M_WAIT_REQ_FALL_S);
77 
78  type MasterType is record
79  wrState : MasterStateType;
80  wrAcks : slv(NUM_SLAVE_SLOTS_G-1 downto 0);
81  wrAckNum : slv(ACK_NUM_SIZE_C-1 downto 0);
82  wrValid : sl;
83  rdState : MasterStateType;
84  rdAcks : slv(NUM_SLAVE_SLOTS_G-1 downto 0);
85  rdAckNum : slv(ACK_NUM_SIZE_C-1 downto 0);
86  rdValid : sl;
87  end record MasterType;
88 
89  type MasterArray is array (natural range <>) of MasterType;
90 
91  type RegType is record
92  slave : SlaveArray(NUM_SLAVE_SLOTS_G-1 downto 0);
93  master : MasterArray(NUM_MASTER_SLOTS_G-1 downto 0);
98  end record RegType;
99 
100  constant REG_INIT_C : RegType := (
101  slave => (
102  others => (
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'))),
109  master => (
110  others => (
111  wrState => M_WAIT_REQ_S,
112  wrAcks => (others => '0'),
113  wrAckNum => (others => '0'),
114  wrValid => '0',
115  rdState => M_WAIT_REQ_S,
116  rdAcks => (others => '0'),
117  rdAckNum => (others => '0'),
118  rdValid => '0')),
121  mAxiWriteMasters => axiWriteMasterInit(MASTERS_CONFIG_G),
122  mAxiReadMasters => axiReadMasterInit(MASTERS_CONFIG_G));
123 
124  signal r : RegType := REG_INIT_C;
125  signal rin : RegType;
126 
127  type AxiStatusArray is array (natural range <>) of AxiLiteStatusType;
128 
129 begin
130 
131  print(DEBUG_G, "AXI_LITE_CROSSBAR: " & LF &
132  "NUM_SLAVE_SLOTS_G: " & integer'image(NUM_SLAVE_SLOTS_G) & LF &
133  "NUM_MASTER_SLOTS_G: " & integer'image(NUM_MASTER_SLOTS_G) & LF &
134  "DEC_ERROR_RESP_G: " & str(DEC_ERROR_RESP_G) & LF &
135  "MASTERS_CONFIG_G:");
136 
137  printCfg : for i in MASTERS_CONFIG_G'range generate
138  print(DEBUG_G,
139  " baseAddr: " & hstr(MASTERS_CONFIG_G(i).baseAddr) & LF &
140  " addrBits: " & str(MASTERS_CONFIG_G(i).addrBits) & LF &
141  " connectivity: " & hstr(MASTERS_CONFIG_G(i).connectivity));
142  end generate printCfg;
143 
145  variable v : RegType;
146  variable sAxiStatuses : AxiStatusArray(NUM_SLAVE_SLOTS_G-1 downto 0);
147  variable mRdReqs : slv(NUM_SLAVE_SLOTS_G-1 downto 0);
148  variable mWrReqs : slv(NUM_SLAVE_SLOTS_G-1 downto 0);
149  begin
150  v := r;
151 
152  -- Control slave side outputs
153  for s in NUM_SLAVE_SLOTS_G-1 downto 0 loop
154 
155  v.sAxiWriteSlaves(s).awready := '0';
156  v.sAxiWriteSlaves(s).wready := '0';
157  v.sAxiReadSlaves(s).arready := '0';
158 
159  -- Reset resp valid
160  if (sAxiWriteMasters(s).bready = '1') then
161  v.sAxiWriteSlaves(s).bvalid := '0';
162  end if;
163 
164  -- Reset rvalid upon rready
165  if (sAxiReadMasters(s).rready = '1') then
166  v.sAxiReadSlaves(s).rvalid := '0';
167  end if;
168 
169  -- Write state machine
170  case (r.slave(s).wrState) is
171  when S_WAIT_AXI_TXN_S =>
172 
173  -- Incomming write
174  if (sAxiWriteMasters(s).awvalid = '1' and sAxiWriteMasters(s).wvalid = '1') then
175 
176  for m in MASTERS_CONFIG_G'range loop
177  -- Check for address match
178  if (sAxiWriteMasters(s).awaddr(31 downto MASTERS_CONFIG_G(m).addrBits) =
180  MASTERS_CONFIG_G(m).connectivity(s) = '1') then
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));
184  end if;
185  end loop;
186 
187  -- Respond with error if decode fails
188  if (uOr(v.slave(s).wrReqs) = '0') then
189  v.sAxiWriteSlaves(s).awready := '1';
190  v.sAxiWriteSlaves(s).wready := '1';
191  v.slave(s).wrState := S_DEC_ERR_S;
192  else
193  v.slave(s).wrState := S_ACK_S;
194  end if;
195  end if;
196 
197  -- Send error
198  when S_DEC_ERR_S =>
199  if (sAxiWriteMasters(s).bready = '1') then
201  v.sAxiWriteSlaves(s).bvalid := '1';
202  v.slave(s).wrState := S_WAIT_AXI_TXN_S;
203  end if;
204 
205  -- Transaction is acked
206  when S_ACK_S =>
207  for m in NUM_MASTER_SLOTS_G-1 downto 0 loop
208  if (r.slave(s).wrReqNum = m and r.slave(s).wrReqs(m) = '1' and r.master(m).wrAcks(s) = '1') then
209  v.sAxiWriteSlaves(s).awready := '1';
210  v.sAxiWriteSlaves(s).wready := '1';
211  v.slave(s).wrState := S_TXN_S;
212  end if;
213  end loop;
214 
215  -- Transaction in progress
216  when S_TXN_S =>
217  for m in NUM_MASTER_SLOTS_G-1 downto 0 loop
218  if (r.slave(s).wrReqNum = m and r.slave(s).wrReqs(m) = '1' and r.master(m).wrAcks(s) = '1') then
219 
220  -- Forward write response
223 
224  -- bvalid or rvalid indicates txn concluding
225  if (r.sAxiWriteSlaves(s).bvalid = '1' and sAxiWriteMasters(s).bready = '1') then
227  v.slave(s).wrReqs := (others => '0');
228  v.slave(s).wrState := S_WAIT_AXI_TXN_S;
229  end if;
230  end if;
231  end loop;
232  end case;
233 
234  -- Read state machine
235  case (r.slave(s).rdState) is
236  when S_WAIT_AXI_TXN_S =>
237 
238  -- Incomming read
239  if (sAxiReadMasters(s).arvalid = '1') then
240  for m in MASTERS_CONFIG_G'range loop
241  -- Check for address match
242  if (sAxiReadMasters(s).araddr(31 downto MASTERS_CONFIG_G(m).addrBits) =
244  MASTERS_CONFIG_G(m).connectivity(s) = '1') then
245  v.slave(s).rdReqs(m) := '1';
246  v.slave(s).rdReqNum := conv_std_logic_vector(m, REQ_NUM_SIZE_C);
247  end if;
248  end loop;
249 
250  -- Respond with error if decode fails
251  if (uOr(v.slave(s).rdReqs) = '0') then
252  v.sAxiReadSlaves(s).arready := '1';
253  v.slave(s).rdState := S_DEC_ERR_S;
254  else
255  v.slave(s).rdState := S_ACK_S;
256  end if;
257  end if;
258 
259  -- Error
260  when S_DEC_ERR_S =>
261  if (sAxiReadMasters(s).rready = '1') then
263  v.sAxiReadSlaves(s).rdata := (others => '0');
264  v.sAxiReadSlaves(s).rvalid := '1';
265  v.slave(s).rdState := S_WAIT_AXI_TXN_S;
266  end if;
267 
268  -- Transaction is acked
269  when S_ACK_S =>
270  for m in NUM_MASTER_SLOTS_G-1 downto 0 loop
271  if (r.slave(s).rdReqNum = m and r.slave(s).rdReqs(m) = '1' and r.master(m).rdAcks(s) = '1') then
272  v.sAxiReadSlaves(s).arready := '1';
273  v.slave(s).rdState := S_TXN_S;
274  end if;
275  end loop;
276 
277  -- Transaction in progress
278  when S_TXN_S =>
279  for m in NUM_MASTER_SLOTS_G-1 downto 0 loop
280  if (r.slave(s).rdReqNum = m and r.slave(s).rdReqs(m) = '1' and r.master(m).rdAcks(s) = '1') then
281 
282  -- Forward read response
286 
287  -- rvalid indicates txn concluding
288  if (r.sAxiReadSlaves(s).rvalid = '1' and sAxiReadMasters(s).rready = '1') then
290  v.slave(s).rdReqs := (others => '0');
291  v.slave(s).rdState := S_WAIT_AXI_TXN_S; --S_WAIT_DONE_S;
292  end if;
293  end if;
294  end loop;
295  end case;
296  end loop;
297 
298 
299  -- Control master side outputs
300  for m in NUM_MASTER_SLOTS_G-1 downto 0 loop
301 
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);
308  end loop;
309 
310  -- Write path processing
311  case (r.master(m).wrState) is
312  when M_WAIT_REQ_S =>
313 
314  -- Keep these in reset state while waiting for requests
315  v.master(m).wrAcks := (others => '0');
316  v.mAxiWriteMasters(m) := axiWriteMasterInit(MASTERS_CONFIG_G(m));
317 
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);
321  end if;
322 
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;
327  v.mAxiWriteMasters(m) := sAxiWriteMasters(conv_integer(r.master(m).wrAckNum));
328  v.master(m).wrState := M_WAIT_READYS_S;
329  end if;
330 
331  when M_WAIT_READYS_S =>
332 
333  -- Wait for attached slave to respond
334  -- Clear *valid signals upon *ready responses
335  if (mAxiWriteSlaves(m).awready = '1') then
336  v.mAxiWriteMasters(m).awvalid := '0';
337  end if;
338  if (mAxiWriteSlaves(m).wready = '1') then
339  v.mAxiWriteMasters(m).wvalid := '0';
340  end if;
341 
342  -- When all *valid signals cleared, wait for slave side to clear request
343  if (v.mAxiWriteMasters(m).awvalid = '0' and v.mAxiWriteMasters(m).wvalid = '0') then
344  v.master(m).wrState := M_WAIT_REQ_FALL_S;
345  end if;
346 
347  when M_WAIT_REQ_FALL_S =>
348  -- When slave side deasserts request, clear ack and valid and start waiting for next
349  -- request
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';
354  end if;
355 
356  end case;
357 
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
361  v.mAxiWriteMasters(m).awaddr(31 downto MASTERS_CONFIG_G(m).addrBits) :=
363 
364 
365 
366  -- Read path processing
367  case (r.master(m).rdState) is
368  when M_WAIT_REQ_S =>
369 
370  -- Keep these in reset state while waiting for requests
371  v.master(m).rdAcks := (others => '0');
372  v.mAxiReadMasters(m) := axiReadMasterInit(MASTERS_CONFIG_G(m));
373 
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);
377  end if;
378 
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;
383  v.mAxiReadMasters(m) := sAxiReadMasters(conv_integer(r.master(m).rdAckNum));
384  v.master(m).rdState := M_WAIT_READYS_S;
385  end if;
386 
387  when M_WAIT_READYS_S =>
388 
389  -- Wait for attached slave to respond
390  -- Clear *valid signals upon *ready responses
391  if (mAxiReadSlaves(m).arready = '1') then
392  v.mAxiReadMasters(m).arvalid := '0';
393  end if;
394 
395  -- When all *valid signals cleared, wait for slave side to clear request
396  if (v.mAxiReadMasters(m).arvalid = '0') then
397  v.master(m).rdState := M_WAIT_REQ_FALL_S;
398  end if;
399 
400  when M_WAIT_REQ_FALL_S =>
401  -- When slave side deasserts request, clear ack and valid and start waiting for next
402  -- request
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';
407  end if;
408 
409  end case;
410 
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
414  v.mAxiReadMasters(m).araddr(31 downto MASTERS_CONFIG_G(m).addrBits) :=
416 
417  end loop;
418 
419  if (axiClkRst = '1') then
420  v := REG_INIT_C;
421  end if;
422 
423  rin <= v;
424 
429 
430  end process comb;
431 
432  seq : process (axiClk) is
433  begin
434  if (rising_edge(axiClk)) then
435  r <= rin after TPD_G;
436  end if;
437  end process seq;
438 
439 end architecture rtl;
440 
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
Definition: AxiLitePkg.vhd:204
slv( 15 downto 0) connectivity
Definition: AxiLitePkg.vhd:199
slv( 1 downto 0) rresp
Definition: AxiLitePkg.vhd:90
array(natural range <> ) of AxiLiteWriteSlaveType AxiLiteWriteSlaveArray
Definition: AxiLitePkg.vhd:164
in mAxiReadSlavesAxiLiteReadSlaveArray( NUM_MASTER_SLOTS_G- 1 downto 0)
TPD_Gtime := 1 ns
std_logic sl
Definition: StdRtlPkg.vhd:28
NUM_SLAVE_SLOTS_Gnatural range 1 to 16:= 4
slv( 31 downto 0) rdata
Definition: AxiLitePkg.vhd:89
in sAxiWriteMastersAxiLiteWriteMasterArray( NUM_SLAVE_SLOTS_G- 1 downto 0)
_library_ ieeeieee
array(natural range <> ) of AxiLiteReadMasterType AxiLiteReadMasterArray
Definition: AxiLitePkg.vhd:77
DEBUG_Gboolean := false
slv( 31 downto 0) baseAddr
Definition: AxiLitePkg.vhd:197
in sAxiReadMastersAxiLiteReadMasterArray( NUM_SLAVE_SLOTS_G- 1 downto 0)
array(natural range <> ) of AxiLiteCrossbarMasterConfigType AxiLiteCrossbarMasterConfigArray
Definition: AxiLitePkg.vhd:202
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
Definition: AxiLitePkg.vhd:49
natural addrBits
Definition: AxiLitePkg.vhd:198
slv( 31 downto 0) awaddr
Definition: AxiLitePkg.vhd:113
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
Definition: AxiLitePkg.vhd:95
slv( 1 downto 0) bresp
Definition: AxiLitePkg.vhd:150
NUM_MASTER_SLOTS_Gnatural range 1 to 64:= 4
array(natural range <> ) of AxiLiteWriteMasterType AxiLiteWriteMasterArray
Definition: AxiLitePkg.vhd:136
out sAxiReadSlavesAxiLiteReadSlaveArray( NUM_SLAVE_SLOTS_G- 1 downto 0)
slv( 31 downto 0) araddr
Definition: AxiLitePkg.vhd:61
array(natural range <> ) of AxiLiteReadSlaveType AxiLiteReadSlaveArray
Definition: AxiLitePkg.vhd:103
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
Definition: AxiLitePkg.vhd:156
out sAxiWriteSlavesAxiLiteWriteSlaveArray( NUM_SLAVE_SLOTS_G- 1 downto 0)
std_logic_vector slv
Definition: StdRtlPkg.vhd:29