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) 2017 Bluespec, Inc. All Rights Reserved
16 package AXI4_Lite_Types;
18 // ================================================================
19 // Facilities for ARM AXI4-Lite, consisting of 5 independent channels:
20 // Write Address, Write Data, Write Response, Read Address and Read Data
23 // AMBA AXI and ACE Protocol Specification
24 // AXI3, AXI4, and AXI4-Lite
26 // ARM IHI 0022E (ID022613)
27 // Issue E, 22 Feb 2013
29 // See export list below
31 // ================================================================
36 // RTL-level interfaces (signals/buses)
37 AXI4_Lite_Master_IFC (..),
38 AXI4_Lite_Slave_IFC (..),
40 // Dummy slave that accepts no requests and generates no response
41 // Used for tying-off unused slave interfaces on fabrics.
42 dummy_AXI4_Lite_Slave_ifc,
44 // Higher-level enums and structs for the 5 AXI4 channel payloads
47 AXI4_Lite_Wr_Addr (..),
48 AXI4_Lite_Wr_Data (..),
49 AXI4_Lite_Wr_Resp (..),
50 AXI4_Lite_Rd_Addr (..),
51 AXI4_Lite_Rd_Data (..),
53 // Higher-level FIFO-like interfaces for the 5 AXI4 channels,
54 AXI4_Lite_Master_Xactor_IFC (..),
55 AXI4_Lite_Slave_Xactor_IFC (..),
57 // Transactors from RTL-level interfacecs to FIFO-like interfaces.
58 mkAXI4_Lite_Master_Xactor,
59 mkAXI4_Lite_Slave_Xactor;
61 // ================================================================
62 // BSV library imports
65 import Connectable :: *;
68 // BSV additional libs
70 import Semi_FIFOF :: *;
72 // ****************************************************************
73 // ****************************************************************
74 // Section: RTL-level interfaces
75 // ****************************************************************
76 // ****************************************************************
78 // ================================================================
79 // These are the signal-level interfaces for an AXI4-Lite master.
80 // The (*..*) attributes ensure that when bsc compiles this to Verilog,
81 // we get exactly the signals specified in the ARM spec.
83 interface AXI4_Lite_Master_IFC #(numeric type wd_addr,
85 numeric type wd_user);
87 (* always_ready, result="awvalid" *) method Bool m_awvalid; // out
88 (* always_ready, result="awaddr" *) method Bit #(wd_addr) m_awaddr; // out
89 (* always_ready, result="awuser" *) method Bit #(wd_user) m_awuser; // out
90 (* always_ready, result="awsize" *) method Bit #(3) m_awsize; // out
91 (* always_ready, always_enabled *) method Action m_awready ((* port="awready" *) Bool awready); // in
94 (* always_ready, result="wvalid" *) method Bool m_wvalid; // out
95 (* always_ready, result="wdata" *) method Bit #(wd_data) m_wdata; // out
96 (* always_ready, result="wstrb" *) method Bit #(TDiv #(wd_data, 8)) m_wstrb; // out
97 (* always_ready, always_enabled *) method Action m_wready ((* port="wready" *) Bool wready); // in
99 // Wr Response channel
100 (* always_ready, always_enabled *)
101 method Action m_bvalid ((* port="bvalid" *) Bool bvalid, // in
102 (* port="bresp" *) Bit #(2) bresp, // in
103 (* port="buser" *) Bit #(wd_user) buser); // in
104 (* always_ready, result="bready" *)
105 method Bool m_bready; // out
108 (* always_ready, result="arvalid" *) method Bool m_arvalid; // out
109 (* always_ready, result="araddr" *) method Bit #(wd_addr) m_araddr; // out
110 (* always_ready, result="aruser" *) method Bit #(wd_user) m_aruser; // out
111 (* always_ready, result="arsize" *) method Bit #(3) m_arsize; // out
112 (* always_ready, always_enabled *) method Action m_arready ((* port="arready" *) Bool arready); // in
115 (* always_ready, always_enabled *)
116 method Action m_rvalid ((* port="rvalid" *) Bool rvalid, // in
117 (* port="rresp" *) Bit #(2) rresp, // in
118 (* port="rdata" *) Bit #(wd_data) rdata, // in
119 (* port="ruser" *) Bit #(wd_user) ruser); // in
120 (* always_ready, result="rready" *)
121 method Bool m_rready; // out
122 endinterface: AXI4_Lite_Master_IFC
124 // ================================================================
125 // These are the signal-level interfaces for an AXI4-Lite slave.
126 // The (*..*) attributes ensure that when bsc compiles this to Verilog,
127 // we get exactly the signals specified in the ARM spec.
129 interface AXI4_Lite_Slave_IFC #(numeric type wd_addr,
130 numeric type wd_data,
131 numeric type wd_user);
133 (* always_ready, always_enabled *)
134 method Action m_awvalid ((* port="awvalid" *) Bool awvalid, // in
135 (* port="awaddr" *) Bit #(wd_addr) awaddr, // in
136 (* port="awsize" *) Bit #(3) awsize, // in
137 (* port="awuser" *) Bit #(wd_user) awuser); // in
138 (* always_ready, result="awready" *)
139 method Bool m_awready; // out
142 (* always_ready, always_enabled *)
143 method Action m_wvalid ((* port="wvalid" *) Bool wvalid, // in
144 (* port="wdata" *) Bit #(wd_data) wdata, // in
145 (* port="wstrb" *) Bit #(TDiv #(wd_data,8)) wstrb); // in
146 (* always_ready, result="wready" *)
147 method Bool m_wready; // out
149 // Wr Response channel
150 (* always_ready, result="bvalid" *) method Bool m_bvalid; // out
151 (* always_ready, result="bresp" *) method Bit #(2) m_bresp; // out
152 (* always_ready, result="buser" *) method Bit #(wd_user) m_buser; // out
153 (* always_ready, always_enabled *) method Action m_bready ((* port="bready" *) Bool bready); // in
156 (* always_ready, always_enabled *)
157 method Action m_arvalid ((* port="arvalid" *) Bool arvalid, // in
158 (* port="araddr" *) Bit #(wd_addr) araddr, // in
159 (* port="arsize" *) Bit #(3) arsize, // in
160 (* port="aruser" *) Bit #(wd_user) aruser); // in
161 (* always_ready, result="arready" *)
162 method Bool m_arready; // out
165 (* always_ready, result="rvalid" *) method Bool m_rvalid; // out
166 (* always_ready, result="rresp" *) method Bit #(2) m_rresp; // out
167 (* always_ready, result="rdata" *) method Bit #(wd_data) m_rdata; // out
168 (* always_ready, result="ruser" *) method Bit #(wd_user) m_ruser; // out
169 (* always_ready, always_enabled *) method Action m_rready ((* port="rready" *) Bool rready); // in
170 endinterface: AXI4_Lite_Slave_IFC
172 // ================================================================
173 // Connecting signal-level interfaces
175 instance Connectable #(AXI4_Lite_Master_IFC #(wd_addr, wd_data, wd_user),
176 AXI4_Lite_Slave_IFC #(wd_addr, wd_data, wd_user));
178 module mkConnection #(AXI4_Lite_Master_IFC #(wd_addr, wd_data, wd_user) axim,
179 AXI4_Lite_Slave_IFC #(wd_addr, wd_data, wd_user) axis)
182 (* fire_when_enabled, no_implicit_conditions *)
183 rule rl_wr_addr_channel;
184 axis.m_awvalid (axim.m_awvalid, axim.m_awaddr, axim.m_awsize, axim.m_awuser);
185 axim.m_awready (axis.m_awready);
188 (* fire_when_enabled, no_implicit_conditions *)
189 rule rl_wr_data_channel;
190 axis.m_wvalid (axim.m_wvalid, axim.m_wdata, axim.m_wstrb);
191 axim.m_wready (axis.m_wready);
194 (* fire_when_enabled, no_implicit_conditions *)
195 rule rl_wr_response_channel;
196 axim.m_bvalid (axis.m_bvalid, axis.m_bresp, axis.m_buser);
197 axis.m_bready (axim.m_bready);
200 (* fire_when_enabled, no_implicit_conditions *)
201 rule rl_rd_addr_channel;
202 axis.m_arvalid (axim.m_arvalid, axim.m_araddr, axim.m_arsize, axim.m_aruser);
203 axim.m_arready (axis.m_arready);
206 (* fire_when_enabled, no_implicit_conditions *)
207 rule rl_rd_data_channel;
208 axim.m_rvalid (axis.m_rvalid, axis.m_rresp, axis.m_rdata, axis.m_ruser);
209 axis.m_rready (axim.m_rready);
214 // ================================================================
215 // AXI4-Lite dummy slave: never accepts requests, never produces responses
217 AXI4_Lite_Slave_IFC #(wd_addr, wd_data, wd_user)
218 dummy_AXI4_Lite_Slave_ifc = interface AXI4_Lite_Slave_IFC
220 method Action m_awvalid (Bool awvalid,
221 Bit #(wd_addr) awaddr,
223 Bit #(wd_user) awuser);
227 method Bool m_awready;
232 method Action m_wvalid (Bool wvalid,
233 Bit #(wd_data) wdata,
234 Bit #(TDiv #(wd_data,8)) wstrb);
238 method Bool m_wready;
242 // Wr Response channel
243 method Bool m_bvalid;
247 method Bit #(2) m_bresp;
251 method Bit #(wd_user) m_buser;
255 method Action m_bready (Bool bready);
260 method Action m_arvalid (Bool arvalid,
261 Bit #(wd_addr) araddr,
263 Bit #(wd_user) aruser);
267 method Bool m_arready;
272 method Bool m_rvalid;
276 method Bit #(2) m_rresp;
280 method Bit #(wd_data) m_rdata;
284 method Bit #(wd_user) m_ruser;
288 method Action m_rready (Bool rready);
293 // ****************************************************************
294 // ****************************************************************
295 // Section: Higher-level FIFO-like interfaces and transactors
296 // ****************************************************************
297 // ****************************************************************
299 // ================================================================
300 // Higher-level types for payloads (rather than just bits)
302 typedef enum { AXI4_LITE_OKAY, AXI4_LITE_EXOKAY, AXI4_LITE_SLVERR, AXI4_LITE_DECERR } AXI4_Lite_Resp
303 deriving (Bits, Eq, FShow);
305 // Write Address channel
308 Bit #(wd_addr) awaddr;
309 Bit #(wd_user) awuser;
311 } AXI4_Lite_Wr_Addr #(numeric type wd_addr, numeric type wd_user)
312 deriving (Bits, FShow);
314 // Write Data channel
317 Bit #(wd_data) wdata;
318 Bit #(TDiv #(wd_data, 8)) wstrb;
319 } AXI4_Lite_Wr_Data #(numeric type wd_data)
320 deriving (Bits, FShow);
322 // Write Response channel
325 AXI4_Lite_Resp bresp;
326 Bit #(wd_user) buser;
327 } AXI4_Lite_Wr_Resp #(numeric type wd_user)
328 deriving (Bits, FShow);
330 // Read Address channel
333 Bit #(wd_addr) araddr;
334 Bit #(wd_user) aruser;
336 } AXI4_Lite_Rd_Addr #(numeric type wd_addr, numeric type wd_user)
337 deriving (Bits, FShow);
342 AXI4_Lite_Resp rresp;
343 Bit #(wd_data) rdata;
344 Bit #(wd_user) ruser;
345 } AXI4_Lite_Rd_Data #(numeric type wd_data, numeric type wd_user)
346 deriving (Bits, FShow);
348 // ================================================================
349 // Master transactor interface
351 interface AXI4_Lite_Master_Xactor_IFC #(numeric type wd_addr,
352 numeric type wd_data,
353 numeric type wd_user);
357 interface AXI4_Lite_Master_IFC #(wd_addr, wd_data, wd_user) axi_side;
360 interface FIFOF_I #(AXI4_Lite_Wr_Addr #(wd_addr, wd_user)) i_wr_addr;
361 interface FIFOF_I #(AXI4_Lite_Wr_Data #(wd_data)) i_wr_data;
362 interface FIFOF_O #(AXI4_Lite_Wr_Resp #(wd_user)) o_wr_resp;
364 interface FIFOF_I #(AXI4_Lite_Rd_Addr #(wd_addr, wd_user)) i_rd_addr;
365 interface FIFOF_O #(AXI4_Lite_Rd_Data #(wd_data, wd_user)) o_rd_data;
366 endinterface: AXI4_Lite_Master_Xactor_IFC
368 // ----------------------------------------------------------------
371 module mkAXI4_Lite_Master_Xactor (AXI4_Lite_Master_Xactor_IFC #(wd_addr, wd_data, wd_user));
373 Bool unguarded = True;
374 Bool guarded = False;
376 // These FIFOs are guarded on BSV side, unguarded on AXI side
377 FIFOF #(AXI4_Lite_Wr_Addr #(wd_addr, wd_user)) f_wr_addr <- mkGFIFOF (guarded, unguarded);
378 FIFOF #(AXI4_Lite_Wr_Data #(wd_data)) f_wr_data <- mkGFIFOF (guarded, unguarded);
379 FIFOF #(AXI4_Lite_Wr_Resp #(wd_user)) f_wr_resp <- mkGFIFOF (unguarded, guarded);
381 FIFOF #(AXI4_Lite_Rd_Addr #(wd_addr, wd_user)) f_rd_addr <- mkGFIFOF (guarded, unguarded);
382 FIFOF #(AXI4_Lite_Rd_Data #(wd_data, wd_user)) f_rd_data <- mkGFIFOF (unguarded, guarded);
384 // ----------------------------------------------------------------
396 interface axi_side = interface AXI4_Lite_Master_IFC;
398 method Bool m_awvalid = f_wr_addr.notEmpty;
399 method Bit #(wd_addr) m_awaddr = f_wr_addr.first.awaddr;
400 method Bit #(wd_user) m_awuser = f_wr_addr.first.awuser;
401 method Bit #(3) m_awsize = f_wr_addr.first.awsize;
402 method Action m_awready (Bool awready);
403 if (f_wr_addr.notEmpty && awready) f_wr_addr.deq;
407 method Bool m_wvalid = f_wr_data.notEmpty;
408 method Bit #(wd_data) m_wdata = f_wr_data.first.wdata;
409 method Bit #(TDiv #(wd_data, 8)) m_wstrb = f_wr_data.first.wstrb;
410 method Action m_wready (Bool wready);
411 if (f_wr_data.notEmpty && wready) f_wr_data.deq;
414 // Wr Response channel
415 method Action m_bvalid (Bool bvalid, Bit #(2) bresp, Bit #(wd_user) buser);
416 if (bvalid && f_wr_resp.notFull)
417 f_wr_resp.enq (AXI4_Lite_Wr_Resp {bresp: unpack (bresp), buser: buser});
420 method Bool m_bready;
421 return f_wr_resp.notFull;
425 method Bool m_arvalid = f_rd_addr.notEmpty;
426 method Bit #(wd_addr) m_araddr = f_rd_addr.first.araddr;
427 method Bit #(wd_user) m_aruser = f_rd_addr.first.aruser;
428 method Bit #(3) m_arsize = f_rd_addr.first.arsize;
429 method Action m_arready (Bool arready);
430 if (f_rd_addr.notEmpty && arready) f_rd_addr.deq;
434 method Action m_rvalid (Bool rvalid,
436 Bit #(wd_data) rdata,
437 Bit #(wd_user) ruser);
438 if (rvalid && f_rd_data.notFull)
439 f_rd_data.enq (AXI4_Lite_Rd_Data {rresp: unpack (rresp),
444 method Bool m_rready;
445 return f_rd_data.notFull;
451 interface i_wr_addr = to_FIFOF_I (f_wr_addr);
452 interface i_wr_data = to_FIFOF_I (f_wr_data);
453 interface o_wr_resp = to_FIFOF_O (f_wr_resp);
455 interface i_rd_addr = to_FIFOF_I (f_rd_addr);
456 interface o_rd_data = to_FIFOF_O (f_rd_data);
457 endmodule: mkAXI4_Lite_Master_Xactor
459 // ================================================================
460 // Slave transactor interface
462 interface AXI4_Lite_Slave_Xactor_IFC #(numeric type wd_addr,
463 numeric type wd_data,
464 numeric type wd_user);
468 interface AXI4_Lite_Slave_IFC #(wd_addr, wd_data, wd_user) axi_side;
471 interface FIFOF_O #(AXI4_Lite_Wr_Addr #(wd_addr, wd_user)) o_wr_addr;
472 interface FIFOF_O #(AXI4_Lite_Wr_Data #(wd_data)) o_wr_data;
473 interface FIFOF_I #(AXI4_Lite_Wr_Resp #(wd_user)) i_wr_resp;
475 interface FIFOF_O #(AXI4_Lite_Rd_Addr #(wd_addr, wd_user)) o_rd_addr;
476 interface FIFOF_I #(AXI4_Lite_Rd_Data #(wd_data, wd_user)) i_rd_data;
477 endinterface: AXI4_Lite_Slave_Xactor_IFC
479 // ----------------------------------------------------------------
482 module mkAXI4_Lite_Slave_Xactor (AXI4_Lite_Slave_Xactor_IFC #(wd_addr, wd_data, wd_user));
484 Bool unguarded = True;
485 Bool guarded = False;
487 // These FIFOs are guarded on BSV side, unguarded on AXI side
488 FIFOF #(AXI4_Lite_Wr_Addr #(wd_addr, wd_user)) f_wr_addr <- mkGFIFOF (unguarded, guarded);
489 FIFOF #(AXI4_Lite_Wr_Data #(wd_data)) f_wr_data <- mkGFIFOF (unguarded, guarded);
490 FIFOF #(AXI4_Lite_Wr_Resp #(wd_user)) f_wr_resp <- mkGFIFOF (guarded, unguarded);
492 FIFOF #(AXI4_Lite_Rd_Addr #(wd_addr, wd_user)) f_rd_addr <- mkGFIFOF (unguarded, guarded);
493 FIFOF #(AXI4_Lite_Rd_Data #(wd_data, wd_user)) f_rd_data <- mkGFIFOF (guarded, unguarded);
495 // ----------------------------------------------------------------
507 interface axi_side = interface AXI4_Lite_Slave_IFC;
509 method Action m_awvalid (Bool awvalid,
510 Bit #(wd_addr) awaddr,
512 Bit #(wd_user) awuser);
513 if (awvalid && f_wr_addr.notFull)
514 f_wr_addr.enq (AXI4_Lite_Wr_Addr {awaddr: awaddr,
519 method Bool m_awready;
520 return f_wr_addr.notFull;
524 method Action m_wvalid (Bool wvalid,
525 Bit #(wd_data) wdata,
526 Bit #(TDiv #(wd_data, 8)) wstrb);
527 if (wvalid && f_wr_data.notFull)
528 f_wr_data.enq (AXI4_Lite_Wr_Data {wdata: wdata, wstrb: wstrb});
531 method Bool m_wready;
532 return f_wr_data.notFull;
535 // Wr Response channel
536 method Bool m_bvalid = f_wr_resp.notEmpty;
537 method Bit #(2) m_bresp = pack (f_wr_resp.first.bresp);
538 method Bit #(wd_user) m_buser = f_wr_resp.first.buser;
539 method Action m_bready (Bool bready);
540 if (bready && f_wr_resp.notEmpty)
545 method Action m_arvalid (Bool arvalid,
546 Bit #(wd_addr) araddr,
548 Bit #(wd_user) aruser);
549 if (arvalid && f_rd_addr.notFull)
550 f_rd_addr.enq (AXI4_Lite_Rd_Addr {araddr: araddr,
555 method Bool m_arready;
556 return f_rd_addr.notFull;
560 method Bool m_rvalid = f_rd_data.notEmpty;
561 method Bit #(2) m_rresp = pack (f_rd_data.first.rresp);
562 method Bit #(wd_data) m_rdata = f_rd_data.first.rdata;
563 method Bit #(wd_user) m_ruser = f_rd_data.first.ruser;
564 method Action m_rready (Bool rready);
565 if (rready && f_rd_data.notEmpty)
571 interface o_wr_addr = to_FIFOF_O (f_wr_addr);
572 interface o_wr_data = to_FIFOF_O (f_wr_data);
573 interface i_wr_resp = to_FIFOF_I (f_wr_resp);
575 interface o_rd_addr = to_FIFOF_O (f_rd_addr);
576 interface i_rd_data = to_FIFOF_I (f_rd_data);
577 endmodule: mkAXI4_Lite_Slave_Xactor
579 // ================================================================