2 Copyright (c) 2013, IIT Madras
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
14 // Copyright (c) 2013-2017 Bluespec, Inc. All Rights Reserved
16 package AXI4_Lite_Fabric;
18 // ================================================================
19 // This package defines a fabric connecting CPUs, Memories and DMAs
20 // and other IP blocks.
22 // ================================================================
23 // Bluespec library imports
27 import ConfigReg :: *;
30 // BSV additional libs
32 import Cur_Cycle :: *;
34 // ================================================================
37 import Semi_FIFOF :: *;
38 import AXI4_Lite_Types :: *;
40 // ================================================================
41 // The interface for the fabric module
43 interface AXI4_Lite_Fabric_IFC #(numeric type num_masters,
44 numeric type num_slaves,
47 numeric type wd_user);
49 method Action set_verbosity (Bit #(4) verbosity);
52 interface Vector #(num_masters, AXI4_Lite_Slave_IFC #(wd_addr, wd_data, wd_user)) v_from_masters;
55 interface Vector #(num_slaves, AXI4_Lite_Master_IFC #(wd_addr, wd_data, wd_user)) v_to_slaves;
58 // ================================================================
60 // The function parameter is an address-decode function, which returns
61 // returns (True, slave-port-num) if address is mapped to slave-port-num
62 // (False, ?) if address is unmapped to any port
64 module mkAXI4_Lite_Fabric #(function Tuple2 #(Bool, Bit #(TLog #(num_slaves)))
65 fn_addr_to_slave_num (Bit #(wd_addr) addr))
66 (AXI4_Lite_Fabric_IFC #(num_masters, num_slaves, wd_addr, wd_data, wd_user))
68 provisos (Log #(num_masters, log_nm),
69 Log #(num_slaves, log_ns),
70 Log #(TAdd #(num_masters, 1), log_nm_plus_1),
71 Log #(TAdd #(num_slaves, 1), log_ns_plus_1),
72 Add #(_dummy, TLog #(num_slaves), log_ns_plus_1));
74 Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (0);
76 // Transactors facing masters
77 Vector #(num_masters, AXI4_Lite_Slave_Xactor_IFC #(wd_addr, wd_data, wd_user))
78 xactors_from_masters <- replicateM (mkAXI4_Lite_Slave_Xactor);
80 // Transactors facing slaves
81 Vector #(num_slaves, AXI4_Lite_Master_Xactor_IFC #(wd_addr, wd_data, wd_user))
82 xactors_to_slaves <- replicateM (mkAXI4_Lite_Master_Xactor);
84 // FIFOs to keep track of which master originated a transaction, in
85 // order to route corresponding responses back to that master.
86 // Legal masters are 0..(num_masters-1)
87 // The value of 'num_masters' is used for decode errors (no such slave)
89 Vector #(num_masters, FIFOF #(Bit #(log_ns_plus_1))) v_f_wr_sjs <- replicateM (mkFIFOF);
90 Vector #(num_masters, FIFOF #(Bit #(wd_user))) v_f_wr_err_user <- replicateM (mkFIFOF);
91 Vector #(num_slaves, FIFOF #(Bit #(log_nm_plus_1))) v_f_wr_mis <- replicateM (mkFIFOF);
93 Vector #(num_masters, FIFOF #(Bit #(log_ns_plus_1))) v_f_rd_sjs <- replicateM (mkFIFOF);
94 Vector #(num_masters, FIFOF #(Bit #(wd_user))) v_f_rd_err_user <- replicateM (mkFIFOF);
95 Vector #(num_slaves, FIFOF #(Bit #(log_nm_plus_1))) v_f_rd_mis <- replicateM (mkFIFOF);
97 // ----------------------------------------------------------------
100 function Bool wr_move_from_mi_to_sj (Integer mi, Integer sj);
101 let addr = xactors_from_masters [mi].o_wr_addr.first.awaddr;
102 match { .legal, .slave_num } = fn_addr_to_slave_num (addr);
103 return (legal && (slave_num == fromInteger (sj)));
106 function Bool wr_illegal_sj (Integer mi);
107 let addr = xactors_from_masters [mi].o_wr_addr.first.awaddr;
108 match { .legal, ._ } = fn_addr_to_slave_num (addr);
112 function Bool rd_move_from_mi_to_sj (Integer mi, Integer sj);
113 let addr = xactors_from_masters [mi].o_rd_addr.first.araddr;
114 match { .legal, .slave_num } = fn_addr_to_slave_num (addr);
115 return (legal && (slave_num == fromInteger (sj)));
118 function Bool rd_illegal_sj (Integer mi);
119 let addr = xactors_from_masters [mi].o_rd_addr.first.araddr;
120 match { .legal, ._ } = fn_addr_to_slave_num (addr);
125 // Wr requests from masters to slaves
127 // Legal destination slaves
128 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
129 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
131 rule rl_wr_xaction_master_to_slave (wr_move_from_mi_to_sj (mi, sj));
132 AXI4_Lite_Wr_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_wr_addr);
133 AXI4_Lite_Wr_Data #(wd_data) d <- pop_o (xactors_from_masters [mi].o_wr_data);
135 xactors_to_slaves [sj].i_wr_addr.enq (a);
136 xactors_to_slaves [sj].i_wr_data.enq (d);
138 v_f_wr_mis [sj].enq (fromInteger (mi));
139 v_f_wr_sjs [mi].enq (fromInteger (sj));
141 if (cfg_verbosity > 1) begin
142 $display ("%0d: AXI4_Lite_Fabric: wr master [%0d] -> slave [%0d]", cur_cycle, mi, sj);
143 $display (" ", fshow (a));
144 $display (" ", fshow (d));
148 // Non-existent destination slaves
149 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
150 rule rl_wr_xaction_no_such_slave (wr_illegal_sj (mi));
151 AXI4_Lite_Wr_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_wr_addr);
152 AXI4_Lite_Wr_Data #(wd_data) d <- pop_o (xactors_from_masters [mi].o_wr_data);
154 v_f_wr_sjs [mi].enq (fromInteger (valueOf (num_slaves)));
155 v_f_wr_err_user [mi].enq (a.awuser);
157 if (cfg_verbosity > 1) begin
158 $display ("%0d: AXI4_Lite_Fabric: wr master [%0d] -> illegal addr", cur_cycle, mi);
159 $display (" ", fshow (a));
164 // Rd requests from masters to slaves
166 // Legal destination slaves
167 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
168 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
170 rule rl_rd_xaction_master_to_slave (rd_move_from_mi_to_sj (mi, sj));
171 AXI4_Lite_Rd_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_rd_addr);
173 xactors_to_slaves [sj].i_rd_addr.enq (a);
175 v_f_rd_mis [sj].enq (fromInteger (mi));
176 v_f_rd_sjs [mi].enq (fromInteger (sj));
178 if (cfg_verbosity > 1) begin
179 $display ("%0d: AXI4_Lite_Fabric: rd master [%0d] -> slave [%0d]", cur_cycle, mi, sj);
180 $display (" ", fshow (a));
184 // Non-existent destination slaves
185 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
186 rule rl_rd_xaction_no_such_slave (rd_illegal_sj (mi));
187 AXI4_Lite_Rd_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_rd_addr);
189 v_f_rd_sjs [mi].enq (fromInteger (valueOf (num_slaves)));
190 v_f_rd_err_user [mi].enq (a.aruser);
192 if (cfg_verbosity > 1) begin
193 $display ("%0d: AXI4_Lite_Fabric: rd master [%0d] -> illegal addr", cur_cycle, mi);
194 $display (" ", fshow (a));
199 // Wr responses from slaves to masters
201 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
202 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
204 rule rl_wr_resp_slave_to_master ( (v_f_wr_mis [sj].first == fromInteger (mi))
205 && (v_f_wr_sjs [mi].first == fromInteger (sj)));
208 AXI4_Lite_Wr_Resp #(wd_user) b <- pop_o (xactors_to_slaves [sj].o_wr_resp);
210 xactors_from_masters [mi].i_wr_resp.enq (b);
212 if (cfg_verbosity > 1) begin
213 $display ("%0d: AXI4_Lite_Fabric: wr master [%0d] <- slave [%0d]", cur_cycle, mi, sj);
214 $display (" ", fshow (b));
219 // Wr error responses to masters
220 // v_f_wr_sjs [mi].first has value num_slaves (illegal value)
221 // v_f_wr_err_user [mi].first contains the request's 'user' data
223 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
225 rule rl_wr_resp_err_to_master (v_f_wr_sjs [mi].first == fromInteger (valueOf (num_slaves)));
227 v_f_wr_err_user [mi].deq;
229 let b = AXI4_Lite_Wr_Resp {bresp: AXI4_LITE_DECERR, buser: v_f_wr_err_user [mi].first};
231 xactors_from_masters [mi].i_wr_resp.enq (b);
233 if (cfg_verbosity > 1) begin
234 $display ("%0d: AXI4_Lite_Fabric: wr master [%0d] <- error", cur_cycle, mi);
235 $display (" ", fshow (b));
240 // Rd responses from slaves to masters
242 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
243 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
245 rule rl_rd_resp_slave_to_master ( (v_f_rd_mis [sj].first == fromInteger (mi))
246 && (v_f_rd_sjs [mi].first == fromInteger (sj)));
249 AXI4_Lite_Rd_Data #(wd_data, wd_user) r <- pop_o (xactors_to_slaves [sj].o_rd_data);
251 xactors_from_masters [mi].i_rd_data.enq (r);
253 if (cfg_verbosity > 1) begin
254 $display ("%0d: AXI4_Lite_Fabric: rd master [%0d] <- slave [%0d]", cur_cycle, mi, sj);
255 $display (" ", fshow (r));
260 // Rd error responses to masters
261 // v_f_rd_sjs [mi].first has value num_slaves (illegal value)
262 // v_f_rd_err_user [mi].first contains the request's 'user' data
264 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
266 rule rl_rd_resp_err_to_master (v_f_rd_sjs [mi].first == fromInteger (valueOf (num_slaves)));
268 v_f_rd_err_user [mi].deq;
270 Bit #(wd_data) data = 0;
271 let r = AXI4_Lite_Rd_Data {rresp: AXI4_LITE_DECERR, ruser: v_f_rd_err_user [mi].first, rdata: data};
273 xactors_from_masters [mi].i_rd_data.enq (r);
275 if (cfg_verbosity > 1) begin
276 $display ("%0d: AXI4_Lite_Fabric: rd master [%0d] <- error", cur_cycle, mi);
277 $display (" ", fshow (r));
281 // ----------------------------------------------------------------
284 function AXI4_Lite_Slave_IFC #(wd_addr, wd_data, wd_user) f1 (Integer j) = xactors_from_masters [j].axi_side;
285 function AXI4_Lite_Master_IFC #(wd_addr, wd_data, wd_user) f2 (Integer j) = xactors_to_slaves [j].axi_side;
288 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1) begin
289 xactors_from_masters [mi].reset;
291 v_f_wr_sjs [mi].clear;
292 v_f_wr_err_user [mi].clear;
294 v_f_rd_sjs [mi].clear;
295 v_f_rd_err_user [mi].clear;
298 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1) begin
299 xactors_to_slaves [sj].reset;
300 v_f_wr_mis [sj].clear;
301 v_f_rd_mis [sj].clear;
305 method Action set_verbosity (Bit #(4) verbosity);
306 cfg_verbosity <= verbosity;
309 interface v_from_masters = genWith (f1);
310 interface v_to_slaves = genWith (f2);
313 // ================================================================
315 endpackage: AXI4_Lite_Fabric