/
AWSteria_HW.bsv
230 lines (177 loc) · 7.17 KB
/
AWSteria_HW.bsv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// Copyright (c) 2021-2022 Bluespec, Inc. All Rights Reserved.
// Author: Rishiyur S. Nikhil
package AWSteria_HW;
// ================================================================
// This package contains a sample AWSteria_Infra app,
// i.e., a mkAWSteria_HW module with AWSteria_HW_IFC interface.
// This specific application contains
// - a 2xN AXI4 fabric, where N = 1,2,3,4 (64b addrs, 512b data):
// - an AXI4-Lite-to-AXI4 adapter
// The schematic is:
//
// +==AWSteria_HW================================================+
// | +=AXI4-Fabric=+ |
// AXI4_S----------------------------------------+ +-AXI4_M to DDR A
// | | | |
// | | +-AXI4_M to DDR B
// | | 2xN | |
// | | +-AXI4_M to DDR C
// | | | |
// | +-AXI4_S +-AXI4_M to DDR D
// | | +=============+ |
// | +=Adapter=+ | |
// AXI4L_S-----------------AXI4L_S AXI4_M-+ |
// | +=========+ |
// | |
// +=============================================================+
// ================================================================
// BSV library imports
import Vector :: *;
import FIFOF :: *;
import GetPut :: *;
import Connectable :: *;
import Clocks :: *;
// ----------------
// BSV additional libs
import Cur_Cycle :: *;
import Semi_FIFOF :: *;
import GetPut_Aux :: *;
// ================================================================
// Project imports
import AXI4_Types :: *;
import AXI4_Fabric :: *;
import AXI4_Lite_Types :: *;
import AXI4L_S_to_AXI4_M_Adapter :: *;
import AWSteria_HW_IFC :: *;
import AWSteria_HW_Platform :: *;
// ================================================================
export mkAWSteria_HW;
export AXI4_16_64_512_0_S_IFC;
export AXI4L_32_32_0_S_IFC;
export AXI4_16_64_512_0_M_IFC;
// ****************************************************************
// Module: synthesized instance of AXI4L_S to AXI4_M adapter
(* synthesize *)
module mkAXI4L_S_to_AXI4_M_Adapter_synth (AXI4L_S_to_AXI4_M_Adapter_IFC #(// AXI4L_S
32, // wd_addr
32, // wd_data
0, // wd_user
// AXI4L_M
16, // wd_id
64, // wd_addr
512, // wd_data
0)); // wd_user
let ifc <- mkAXI4L_S_to_AXI4_M_Adapter;
return ifc;
endmodule
// ****************************************************************
// Module: synthesized instance of AXI4 fabric connecting the host
// AXI4 and (via adapter) AXI4-Lite to the AXI4 DDRs
// ----------------
// Address-Decode function to route requests to appropriate DDR
function Tuple2 #(Bool, Bit #(TLog #(N_DDRs))) fn_addr_to_ddr_num (Bit #(64) addr);
if ((ddr_A_base <= addr) && (addr < ddr_A_lim))
return tuple2 (True, 0);
`ifdef INCLUDE_DDR_B
else if ((ddr_B_base <= addr) && (addr < ddr_B_lim))
return tuple2 (True, 1);
`endif
`ifdef INCLUDE_DDR_C
else if ((ddr_C_base <= addr) && (addr < ddr_C_lim))
return tuple2 (True, 2);
`endif
`ifdef INCLUDE_DDR_D
else if ((ddr_D_base <= addr) && (addr < ddr_D_lim))
return tuple2 (True, 3);
`endif
else
return tuple2 (False, 0);
endfunction
// ----------------
// The fabric
typedef AXI4_Fabric_IFC #(2, // num M ports
N_DDRs, // num S ports
16, // wd_id
64, // wd_addr
512, // wd_data
0)
AXI4_16_64_512_0_Fabric_2_N_IFC;
(* synthesize *)
module mkAXI4_16_64_512_0_Fabric_2_N (AXI4_16_64_512_0_Fabric_2_N_IFC);
let fabric <- mkAXI4_Fabric (fn_addr_to_ddr_num);
return fabric;
endmodule
// ****************************************************************
// TEMPORARY HACK. The Makefile for Verilator expects this module
// (because of a particular app, AWSteria_RISCV_Virtio
(* synthesize *)
module mkAWSteria_System (Empty);
endmodule
// ****************************************************************
// Module: synthesized instance of AWSteria HW-side top-level (the DUT)
// Here we do not use the extra clocks clk1, clk2, ...
// For host_AXI4_S interface (wd_id, wd_addr, wd_data, wd_user)
typedef AXI4_Slave_IFC #(16, 64, 512, 0) AXI4_16_64_512_0_S_IFC;
// For host_AXI4L_S interface (wd_addr, wd_data, wd_user)
typedef AXI4_Lite_Slave_IFC #(32, 32, 0) AXI4L_32_32_0_S_IFC;
// For each DDR connection
typedef AXI4_Master_IFC #(16, 64, 512, 0) AXI4_16_64_512_0_M_IFC;
(* synthesize *)
module mkAWSteria_HW #(Clock clk1, Clock clk2, Clock clk3, Clock clk4, Clock clk5)
(AWSteria_HW_IFC #(AXI4_Slave_IFC #(16, 64, 512, 0),
AXI4_Lite_Slave_IFC #(32, 32, 0),
AXI4_Master_IFC #(16, 64, 512, 0)));
// AXI4-Lite to AXI4 adapter
AXI4L_S_to_AXI4_M_Adapter_IFC #(32, // wd_addr_AXI4L_S
32, // wd_data_AXI4L_S
0, // wd_user_AXI4L_S
16, // wd_id_AXI4_M
64, // wd_addr_AXI4_M
512, // wd_data_AXI4_M
0) // wd_user_AXI4_M)
adapter_AXI4L_S_to_AXI4_M <- mkAXI4L_S_to_AXI4_M_Adapter_synth;
// AXI4 Fabric
AXI4_16_64_512_0_Fabric_2_N_IFC fabric <- mkAXI4_16_64_512_0_Fabric_2_N;
// Regs for control/status signals
Reg #(Bool) rg_env_ready <- mkReg (False);
Reg #(Bit #(64)) rg_glcount <- mkReg (0);
Reg #(Bool) rg_halted <- mkReg (False); // For simulation shutdown
// ================================================================
// BEHAVIOR
// Connect AXI4-Lite-to-AXI4-adapter to AXI4 fabric
mkConnection (adapter_AXI4L_S_to_AXI4_M.ifc_AXI4_M,
fabric.v_from_masters [1]);
// ================================================================
// INTERFACE
// Facing Host
interface AXI4_Slave_IFC host_AXI4_S = fabric.v_from_masters [0];
interface AXI4_Lite_Slave_IFC host_AXI4L_S = adapter_AXI4L_S_to_AXI4_M.ifc_AXI4L_S;
// Facing DDR
`ifdef INCLUDE_DDR_A
interface AXI4_Master_IFC ddr_A_M = fabric.v_to_slaves [0];
`endif
`ifdef INCLUDE_DDR_B
interface AXI4_Master_IFC ddr_B_M = fabric.v_to_slaves [1];
`endif
`ifdef INCLUDE_DDR_C
interface AXI4_Master_IFC ddr_C_M = fabric.v_to_slaves [2];
`endif
`ifdef INCLUDE_DDR_D
interface AXI4_Master_IFC ddr_D_M = fabric.v_to_slaves [3];
`endif
// ================
// Status signals
// The AWSteria environment asserts this to inform the DUT that it is ready
method Action m_env_ready (Bool env_ready);
rg_env_ready <= env_ready;
endmethod
// The DUT asserts this to inform the AWSteria environment that it has "halted"
method Bool m_halted = rg_halted;
// ================
// Real-time counter (in AWS and VCU118: 4ns period, irrespective of DUT clock)
method Action m_glcount (Bit #(64) glcount);
rg_glcount <= glcount;
endmethod
endmodule
// ================================================================
endpackage