switchboard-hw 0.3.0__cp314-cp314-macosx_10_15_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. _switchboard.cpython-314-darwin.so +0 -0
  2. switchboard/__init__.py +24 -0
  3. switchboard/ams.py +668 -0
  4. switchboard/apb.py +278 -0
  5. switchboard/autowrap.py +1000 -0
  6. switchboard/axi.py +571 -0
  7. switchboard/axil.py +348 -0
  8. switchboard/bitvector.py +112 -0
  9. switchboard/cmdline.py +142 -0
  10. switchboard/cpp/Makefile +13 -0
  11. switchboard/cpp/bitutil.h +39 -0
  12. switchboard/cpp/pagemap.h +91 -0
  13. switchboard/cpp/pciedev.h +86 -0
  14. switchboard/cpp/router.cc +89 -0
  15. switchboard/cpp/spsc_queue.h +267 -0
  16. switchboard/cpp/switchboard.hpp +257 -0
  17. switchboard/cpp/switchboard_pcie.hpp +234 -0
  18. switchboard/cpp/switchboard_tlm.hpp +98 -0
  19. switchboard/cpp/umilib.h +144 -0
  20. switchboard/cpp/umilib.hpp +113 -0
  21. switchboard/cpp/umisb.hpp +364 -0
  22. switchboard/cpp/xyce.hpp +90 -0
  23. switchboard/deps/__init__.py +0 -0
  24. switchboard/deps/verilog_axi.py +23 -0
  25. switchboard/dpi/__init__.py +0 -0
  26. switchboard/dpi/switchboard_dpi.cc +119 -0
  27. switchboard/dpi/switchboard_dpi.py +13 -0
  28. switchboard/dpi/xyce_dpi.cc +43 -0
  29. switchboard/gpio.py +108 -0
  30. switchboard/icarus.py +85 -0
  31. switchboard/loopback.py +157 -0
  32. switchboard/network.py +714 -0
  33. switchboard/pytest_plugin.py +11 -0
  34. switchboard/sbdesign.py +55 -0
  35. switchboard/sbdut.py +744 -0
  36. switchboard/sbtcp.py +345 -0
  37. switchboard/sc/__init__.py +0 -0
  38. switchboard/sc/morty/__init__.py +0 -0
  39. switchboard/sc/morty/uniquify.py +67 -0
  40. switchboard/sc/sed/__init__.py +0 -0
  41. switchboard/sc/sed/sed_remove.py +47 -0
  42. switchboard/sc/standalone_netlist_flow.py +25 -0
  43. switchboard/switchboard.py +53 -0
  44. switchboard/test_util.py +46 -0
  45. switchboard/uart_xactor.py +66 -0
  46. switchboard/umi.py +793 -0
  47. switchboard/util.py +131 -0
  48. switchboard/verilator/__init__.py +0 -0
  49. switchboard/verilator/config.vlt +13 -0
  50. switchboard/verilator/testbench.cc +143 -0
  51. switchboard/verilator/verilator.py +13 -0
  52. switchboard/verilator_run.py +31 -0
  53. switchboard/verilog/__init__.py +0 -0
  54. switchboard/verilog/common/__init__.py +0 -0
  55. switchboard/verilog/common/common.py +26 -0
  56. switchboard/verilog/common/switchboard.vh +429 -0
  57. switchboard/verilog/common/uart_xactor.sv +247 -0
  58. switchboard/verilog/common/umi_gpio.v +236 -0
  59. switchboard/verilog/fpga/__init__.py +0 -0
  60. switchboard/verilog/fpga/axi_reader.sv +82 -0
  61. switchboard/verilog/fpga/axi_writer.sv +111 -0
  62. switchboard/verilog/fpga/config_registers.sv +249 -0
  63. switchboard/verilog/fpga/fpga.py +21 -0
  64. switchboard/verilog/fpga/include/sb_queue_regmap.vh +21 -0
  65. switchboard/verilog/fpga/include/spsc_queue.vh +7 -0
  66. switchboard/verilog/fpga/memory_fault.sv +40 -0
  67. switchboard/verilog/fpga/sb_fpga_queues.sv +416 -0
  68. switchboard/verilog/fpga/sb_rx_fpga.sv +303 -0
  69. switchboard/verilog/fpga/sb_tx_fpga.sv +294 -0
  70. switchboard/verilog/fpga/umi_fpga_queues.sv +146 -0
  71. switchboard/verilog/sim/__init__.py +0 -0
  72. switchboard/verilog/sim/auto_stop_sim.sv +25 -0
  73. switchboard/verilog/sim/perf_meas_sim.sv +97 -0
  74. switchboard/verilog/sim/queue_to_sb_sim.sv +176 -0
  75. switchboard/verilog/sim/queue_to_umi_sim.sv +66 -0
  76. switchboard/verilog/sim/sb_apb_m.sv +146 -0
  77. switchboard/verilog/sim/sb_axi_m.sv +199 -0
  78. switchboard/verilog/sim/sb_axil_m.sv +180 -0
  79. switchboard/verilog/sim/sb_axil_s.sv +180 -0
  80. switchboard/verilog/sim/sb_clk_gen.sv +89 -0
  81. switchboard/verilog/sim/sb_jtag_rbb_sim.sv +148 -0
  82. switchboard/verilog/sim/sb_rx_sim.sv +55 -0
  83. switchboard/verilog/sim/sb_to_queue_sim.sv +196 -0
  84. switchboard/verilog/sim/sb_tx_sim.sv +55 -0
  85. switchboard/verilog/sim/switchboard_sim.py +49 -0
  86. switchboard/verilog/sim/umi_rx_sim.sv +61 -0
  87. switchboard/verilog/sim/umi_to_queue_sim.sv +66 -0
  88. switchboard/verilog/sim/umi_tx_sim.sv +61 -0
  89. switchboard/verilog/sim/xyce_intf.sv +67 -0
  90. switchboard/vpi/switchboard_vpi.cc +431 -0
  91. switchboard/vpi/xyce_vpi.cc +200 -0
  92. switchboard/warn.py +14 -0
  93. switchboard/xyce.py +27 -0
  94. switchboard_hw-0.3.0.dist-info/METADATA +303 -0
  95. switchboard_hw-0.3.0.dist-info/RECORD +99 -0
  96. switchboard_hw-0.3.0.dist-info/WHEEL +6 -0
  97. switchboard_hw-0.3.0.dist-info/entry_points.txt +6 -0
  98. switchboard_hw-0.3.0.dist-info/licenses/LICENSE +190 -0
  99. switchboard_hw-0.3.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,416 @@
1
+ // Copyright (c) 2024 Zero ASIC Corporation
2
+ // This code is licensed under Apache License 2.0 (see LICENSE for details)
3
+
4
+ `default_nettype none
5
+
6
+ module sb_fpga_queues #(
7
+ parameter NUM_RX_QUEUES = 1,
8
+ parameter NUM_TX_QUEUES = 1,
9
+ parameter NUM_USER_REGS = 0,
10
+
11
+ parameter integer DW=416
12
+ ) (
13
+ input wire clk,
14
+ input wire nreset,
15
+
16
+ // Switchboard interfaces
17
+ output wire [NUM_RX_QUEUES*DW-1:0] rx_data,
18
+ output wire [NUM_RX_QUEUES*32-1:0] rx_dest,
19
+ output wire [NUM_RX_QUEUES-1:0] rx_last,
20
+ input wire [NUM_RX_QUEUES-1:0] rx_ready,
21
+ output wire [NUM_RX_QUEUES-1:0] rx_valid,
22
+
23
+ input wire [NUM_TX_QUEUES*DW-1:0] tx_data,
24
+ input wire [NUM_TX_QUEUES*32-1:0] tx_dest,
25
+ input wire [NUM_TX_QUEUES-1:0] tx_last,
26
+ output wire [NUM_TX_QUEUES-1:0] tx_ready,
27
+ input wire [NUM_TX_QUEUES-1:0] tx_valid,
28
+
29
+ output wire [(NUM_USER_REGS > 0 ? NUM_USER_REGS : 1)*32-1:0] cfg_user,
30
+
31
+ // AXI manager interface for memory access
32
+ output wire [15:0] m_axi_awid,
33
+ output wire [63:0] m_axi_awaddr,
34
+ output wire [7:0] m_axi_awlen,
35
+ output wire [2:0] m_axi_awsize,
36
+ output wire [18:0] m_axi_awuser,
37
+ output wire m_axi_awvalid,
38
+ input wire m_axi_awready,
39
+
40
+ output wire [511:0] m_axi_wdata,
41
+ output wire [63:0] m_axi_wstrb,
42
+ output wire m_axi_wlast,
43
+ output wire m_axi_wvalid,
44
+ input wire m_axi_wready,
45
+
46
+ input wire [15:0] m_axi_bid,
47
+ input wire [1:0] m_axi_bresp,
48
+ input wire m_axi_bvalid,
49
+ output wire m_axi_bready,
50
+
51
+ output wire [15:0] m_axi_arid,
52
+ output wire [63:0] m_axi_araddr,
53
+ output wire [7:0] m_axi_arlen,
54
+ output wire [2:0] m_axi_arsize,
55
+ output wire [18:0] m_axi_aruser,
56
+ output wire m_axi_arvalid,
57
+ input wire m_axi_arready,
58
+
59
+ input wire [15:0] m_axi_rid,
60
+ input wire [511:0] m_axi_rdata,
61
+ input wire [1:0] m_axi_rresp,
62
+ input wire m_axi_rlast,
63
+ input wire m_axi_rvalid,
64
+ output wire m_axi_rready,
65
+
66
+ // AXIL subordinate interface for config registers
67
+ input wire s_axil_awvalid,
68
+ input wire [31:0] s_axil_awaddr,
69
+ output wire s_axil_awready,
70
+
71
+ input wire s_axil_wvalid,
72
+ input wire [31:0] s_axil_wdata,
73
+ input wire [3:0] s_axil_wstrb,
74
+ output wire s_axil_wready,
75
+
76
+ output wire s_axil_bvalid,
77
+ output wire [1:0] s_axil_bresp,
78
+ input wire s_axil_bready,
79
+
80
+ input wire s_axil_arvalid,
81
+ input wire [31:0] s_axil_araddr,
82
+ output wire s_axil_arready,
83
+
84
+ output wire s_axil_rvalid,
85
+ output wire [31:0] s_axil_rdata,
86
+ output wire [1:0] s_axil_rresp,
87
+ input wire s_axil_rready
88
+ );
89
+
90
+ localparam NUM_QUEUES = NUM_RX_QUEUES + NUM_TX_QUEUES;
91
+ // We have a fixed number of ID bits out, and we need to reserve a few for
92
+ // response routing in the arbiter.
93
+ localparam ID_WIDTH = 16 - $clog2(NUM_QUEUES);
94
+
95
+ wire [NUM_QUEUES-1:0] cfg_enable;
96
+ wire [NUM_QUEUES-1:0] cfg_reset;
97
+ wire [NUM_QUEUES*64-1:0] cfg_base_addr;
98
+ wire [NUM_QUEUES*32-1:0] cfg_capacity;
99
+
100
+ wire [NUM_QUEUES-1:0] status_idle;
101
+
102
+ wire [NUM_QUEUES*ID_WIDTH-1:0] axi_awid;
103
+ wire [NUM_QUEUES*64-1:0] axi_awaddr;
104
+ wire [NUM_QUEUES*8-1:0] axi_awlen;
105
+ wire [NUM_QUEUES*3-1:0] axi_awsize;
106
+ wire [NUM_QUEUES-1:0] axi_awvalid;
107
+ wire [NUM_QUEUES-1:0] axi_awready;
108
+
109
+ wire [NUM_QUEUES*512-1:0] axi_wdata;
110
+ wire [NUM_QUEUES*64-1:0] axi_wstrb;
111
+ wire [NUM_QUEUES-1:0] axi_wlast;
112
+ wire [NUM_QUEUES-1:0] axi_wvalid;
113
+ wire [NUM_QUEUES-1:0] axi_wready;
114
+
115
+ wire [NUM_QUEUES*ID_WIDTH-1:0] axi_bid;
116
+ wire [NUM_QUEUES*2-1:0] axi_bresp;
117
+ wire [NUM_QUEUES-1:0] axi_bvalid;
118
+ wire [NUM_QUEUES-1:0] axi_bready;
119
+
120
+ wire [NUM_QUEUES*ID_WIDTH-1:0] axi_arid;
121
+ wire [NUM_QUEUES*64-1:0] axi_araddr;
122
+ wire [NUM_QUEUES*8-1:0] axi_arlen;
123
+ wire [NUM_QUEUES*3-1:0] axi_arsize;
124
+ wire [NUM_QUEUES-1:0] axi_arvalid;
125
+ wire [NUM_QUEUES-1:0] axi_arready;
126
+
127
+ wire [NUM_QUEUES*ID_WIDTH-1:0] axi_rid;
128
+ wire [NUM_QUEUES*512-1:0] axi_rdata;
129
+ wire [NUM_QUEUES*2-1:0] axi_rresp;
130
+ wire [NUM_QUEUES-1:0] axi_rlast;
131
+ wire [NUM_QUEUES-1:0] axi_rvalid;
132
+ wire [NUM_QUEUES-1:0] axi_rready;
133
+
134
+ genvar i;
135
+ generate
136
+ for (i = 0; i < NUM_RX_QUEUES; i = i + 1) begin
137
+ sb_rx_fpga #(
138
+ .ID_WIDTH(ID_WIDTH),
139
+ .DW(DW)
140
+ ) rx (
141
+ .clk(clk),
142
+ .en(cfg_enable[2*i]),
143
+ .reset(cfg_reset[2*i]),
144
+
145
+ .cfg_base_addr(cfg_base_addr[64*(2*i)+:64]),
146
+ .cfg_capacity(cfg_capacity[32*(2*i)+:32]),
147
+
148
+ .status_idle(status_idle[2*i]),
149
+
150
+ .data(rx_data[DW*i+:DW]),
151
+ .dest(rx_dest[32*i+:32]),
152
+ .last(rx_last[i]),
153
+ .ready(rx_ready[i]),
154
+ .valid(rx_valid[i]),
155
+
156
+ .m_axi_awid(axi_awid[ID_WIDTH*i+:ID_WIDTH]),
157
+ .m_axi_awaddr(axi_awaddr[64*i+:64]),
158
+ .m_axi_awlen(axi_awlen[8*i+:8]),
159
+ .m_axi_awsize(axi_awsize[3*i+:3]),
160
+ .m_axi_awvalid(axi_awvalid[i]),
161
+ .m_axi_awready(axi_awready[i]),
162
+
163
+ .m_axi_wdata(axi_wdata[512*i+:512]),
164
+ .m_axi_wstrb(axi_wstrb[64*i+:64]),
165
+ .m_axi_wlast(axi_wlast[i]),
166
+ .m_axi_wvalid(axi_wvalid[i]),
167
+ .m_axi_wready(axi_wready[i]),
168
+
169
+ .m_axi_bid(axi_bid[ID_WIDTH*i+:ID_WIDTH]),
170
+ .m_axi_bresp(axi_bresp[2*i+:2]),
171
+ .m_axi_bvalid(axi_bvalid[i]),
172
+ .m_axi_bready(axi_bready[i]),
173
+
174
+ .m_axi_arid(axi_arid[ID_WIDTH*i+:ID_WIDTH]),
175
+ .m_axi_araddr(axi_araddr[64*i+:64]),
176
+ .m_axi_arlen(axi_arlen[8*i+:8]),
177
+ .m_axi_arsize(axi_arsize[3*i+:3]),
178
+ .m_axi_arvalid(axi_arvalid[i]),
179
+ .m_axi_arready(axi_arready[i]),
180
+
181
+ .m_axi_rid(axi_rid[ID_WIDTH*i+:ID_WIDTH]),
182
+ .m_axi_rdata(axi_rdata[512*i+:512]),
183
+ .m_axi_rresp(axi_rresp[2*i+:2]),
184
+ .m_axi_rlast(axi_rlast[i]),
185
+ .m_axi_rvalid(axi_rvalid[i]),
186
+ .m_axi_rready(axi_rready[i])
187
+ );
188
+ end
189
+ endgenerate
190
+
191
+ generate
192
+ for (i = NUM_RX_QUEUES; i < NUM_QUEUES; i = i + 1) begin
193
+ sb_tx_fpga #(
194
+ .ID_WIDTH(ID_WIDTH),
195
+ .DW(DW)
196
+ ) tx (
197
+ .clk(clk),
198
+ .en(cfg_enable[2*(i-NUM_RX_QUEUES)+1]),
199
+ .reset(cfg_reset[2*(i-NUM_RX_QUEUES)+1]),
200
+
201
+ .cfg_base_addr(cfg_base_addr[64*(2*(i-NUM_RX_QUEUES)+1)+:64]),
202
+ .cfg_capacity(cfg_capacity[32*(2*(i-NUM_RX_QUEUES)+1)+:32]),
203
+
204
+ .status_idle(status_idle[2*(i-NUM_RX_QUEUES)+1]),
205
+
206
+ .data(tx_data[DW*(i-NUM_RX_QUEUES)+:DW]),
207
+ .dest(tx_dest[32*(i-NUM_RX_QUEUES)+:32]),
208
+ .last(tx_last[i-NUM_RX_QUEUES]),
209
+ .ready(tx_ready[i-NUM_RX_QUEUES]),
210
+ .valid(tx_valid[i-NUM_RX_QUEUES]),
211
+
212
+ .m_axi_awid(axi_awid[ID_WIDTH*i+:ID_WIDTH]),
213
+ .m_axi_awaddr(axi_awaddr[64*i+:64]),
214
+ .m_axi_awlen(axi_awlen[8*i+:8]),
215
+ .m_axi_awsize(axi_awsize[3*i+:3]),
216
+ .m_axi_awvalid(axi_awvalid[i]),
217
+ .m_axi_awready(axi_awready[i]),
218
+
219
+ .m_axi_wdata(axi_wdata[512*i+:512]),
220
+ .m_axi_wstrb(axi_wstrb[64*i+:64]),
221
+ .m_axi_wlast(axi_wlast[i]),
222
+ .m_axi_wvalid(axi_wvalid[i]),
223
+ .m_axi_wready(axi_wready[i]),
224
+
225
+ .m_axi_bid(axi_bid[ID_WIDTH*i+:ID_WIDTH]),
226
+ .m_axi_bresp(axi_bresp[2*i+:2]),
227
+ .m_axi_bvalid(axi_bvalid[i]),
228
+ .m_axi_bready(axi_bready[i]),
229
+
230
+ .m_axi_arid(axi_arid[ID_WIDTH*i+:ID_WIDTH]),
231
+ .m_axi_araddr(axi_araddr[64*i+:64]),
232
+ .m_axi_arlen(axi_arlen[8*i+:8]),
233
+ .m_axi_arsize(axi_arsize[3*i+:3]),
234
+ .m_axi_arvalid(axi_arvalid[i]),
235
+ .m_axi_arready(axi_arready[i]),
236
+
237
+ .m_axi_rid(axi_rid[ID_WIDTH*i+:ID_WIDTH]),
238
+ .m_axi_rdata(axi_rdata[512*i+:512]),
239
+ .m_axi_rresp(axi_rresp[2*i+:2]),
240
+ .m_axi_rlast(axi_rlast[i]),
241
+ .m_axi_rvalid(axi_rvalid[i]),
242
+ .m_axi_rready(axi_rready[i])
243
+ );
244
+ end
245
+ endgenerate
246
+
247
+ config_registers #(
248
+ .NUM_QUEUES(NUM_QUEUES),
249
+ .NUM_USER_REGS(NUM_USER_REGS)
250
+ ) config_regs (
251
+ .clk(clk),
252
+ .nreset(nreset),
253
+
254
+ .status_idle(status_idle),
255
+ .cfg_enable(cfg_enable),
256
+ .cfg_reset(cfg_reset),
257
+ .cfg_base_addr(cfg_base_addr),
258
+ .cfg_capacity(cfg_capacity),
259
+ .cfg_user(cfg_user),
260
+
261
+ .s_axil_awaddr(s_axil_awaddr),
262
+ .s_axil_awvalid(s_axil_awvalid),
263
+ .s_axil_awready(s_axil_awready),
264
+ .s_axil_wdata(s_axil_wdata),
265
+ .s_axil_wstrb(s_axil_wstrb),
266
+ .s_axil_wvalid(s_axil_wvalid),
267
+ .s_axil_wready(s_axil_wready),
268
+ .s_axil_bresp(s_axil_bresp),
269
+ .s_axil_bvalid(s_axil_bvalid),
270
+ .s_axil_bready(s_axil_bready),
271
+ .s_axil_araddr(s_axil_araddr),
272
+ .s_axil_arvalid(s_axil_arvalid),
273
+ .s_axil_arready(s_axil_arready),
274
+ .s_axil_rdata(s_axil_rdata),
275
+ .s_axil_rresp(s_axil_rresp),
276
+ .s_axil_rvalid(s_axil_rvalid),
277
+ .s_axil_rready(s_axil_rready)
278
+ );
279
+
280
+ // Handles arbitration between AXI interfaces on queues, as well as
281
+ // registering outputs.
282
+ axi_crossbar #(
283
+ .S_COUNT(NUM_QUEUES),
284
+ .M_COUNT(1),
285
+ .DATA_WIDTH(512),
286
+ .ADDR_WIDTH(64),
287
+ .S_ID_WIDTH(ID_WIDTH),
288
+ .M_ADDR_WIDTH(32'd64),
289
+ .S_AW_REG_TYPE({NUM_QUEUES{2'd0}}),
290
+ .S_W_REG_TYPE({NUM_QUEUES{2'd0}}),
291
+ .S_B_REG_TYPE({NUM_QUEUES{2'd0}}),
292
+ .S_AR_REG_TYPE({NUM_QUEUES{2'd0}}),
293
+ .S_R_REG_TYPE({NUM_QUEUES{2'd0}}),
294
+ .M_AW_REG_TYPE(2'd2),
295
+ .M_W_REG_TYPE(2'd2),
296
+ .M_B_REG_TYPE(2'd2),
297
+ .M_AR_REG_TYPE(2'd2),
298
+ .M_R_REG_TYPE(2'd2)
299
+ ) crossbar (
300
+ .clk(clk),
301
+ .rst(~nreset),
302
+
303
+ .s_axi_awid(axi_awid),
304
+ .s_axi_awaddr(axi_awaddr),
305
+ .s_axi_awlen(axi_awlen),
306
+ .s_axi_awsize(axi_awsize),
307
+ .s_axi_awburst(),
308
+ .s_axi_awlock(),
309
+ .s_axi_awcache(),
310
+ .s_axi_awprot(),
311
+ .s_axi_awqos(),
312
+ .s_axi_awuser(),
313
+ .s_axi_awvalid(axi_awvalid),
314
+ .s_axi_awready(axi_awready),
315
+ .s_axi_wdata(axi_wdata),
316
+ .s_axi_wstrb(axi_wstrb),
317
+ .s_axi_wlast(axi_wlast),
318
+ .s_axi_wuser(),
319
+ .s_axi_wvalid(axi_wvalid),
320
+ .s_axi_wready(axi_wready),
321
+ .s_axi_bid(axi_bid),
322
+ .s_axi_bresp(axi_bresp),
323
+ .s_axi_buser(),
324
+ .s_axi_bvalid(axi_bvalid),
325
+ .s_axi_bready(axi_bready),
326
+ .s_axi_arid(axi_arid),
327
+ .s_axi_araddr(axi_araddr),
328
+ .s_axi_arlen(axi_arlen),
329
+ .s_axi_arsize(axi_arsize),
330
+ .s_axi_arburst(),
331
+ .s_axi_arlock(),
332
+ .s_axi_arcache(),
333
+ .s_axi_arprot(),
334
+ .s_axi_arqos(),
335
+ .s_axi_aruser(),
336
+ .s_axi_arvalid(axi_arvalid),
337
+ .s_axi_arready(axi_arready),
338
+ .s_axi_rid(axi_rid),
339
+ .s_axi_rdata(axi_rdata),
340
+ .s_axi_rresp(axi_rresp),
341
+ .s_axi_rlast(axi_rlast),
342
+ .s_axi_ruser(),
343
+ .s_axi_rvalid(axi_rvalid),
344
+ .s_axi_rready(axi_rready),
345
+
346
+ .m_axi_awid (m_axi_awid),
347
+ .m_axi_awaddr (m_axi_awaddr),
348
+ .m_axi_awlen (m_axi_awlen),
349
+ .m_axi_awsize (m_axi_awsize),
350
+ .m_axi_awburst (),
351
+ .m_axi_awlock (),
352
+ .m_axi_awcache (),
353
+ .m_axi_awprot (),
354
+ .m_axi_awqos (),
355
+ .m_axi_awregion (),
356
+ .m_axi_awuser (),
357
+ .m_axi_awvalid (m_axi_awvalid),
358
+ .m_axi_awready (m_axi_awready),
359
+ .m_axi_wdata (m_axi_wdata),
360
+ .m_axi_wstrb (m_axi_wstrb),
361
+ .m_axi_wlast (m_axi_wlast),
362
+ .m_axi_wuser (),
363
+ .m_axi_wvalid (m_axi_wvalid),
364
+ .m_axi_wready (m_axi_wready),
365
+ .m_axi_bid (m_axi_bid),
366
+ .m_axi_bresp (m_axi_bresp),
367
+ .m_axi_buser (),
368
+ .m_axi_bvalid (m_axi_bvalid),
369
+ .m_axi_bready (m_axi_bready),
370
+ .m_axi_arid (m_axi_arid),
371
+ .m_axi_araddr (m_axi_araddr),
372
+ .m_axi_arlen (m_axi_arlen),
373
+ .m_axi_arsize (m_axi_arsize),
374
+ .m_axi_arburst (),
375
+ .m_axi_arlock (),
376
+ .m_axi_arcache (),
377
+ .m_axi_arprot (),
378
+ .m_axi_arqos (),
379
+ .m_axi_arregion (),
380
+ .m_axi_aruser (),
381
+ .m_axi_arvalid (m_axi_arvalid),
382
+ .m_axi_arready (m_axi_arready),
383
+ .m_axi_rid (m_axi_rid),
384
+ .m_axi_rdata (m_axi_rdata),
385
+ .m_axi_rresp (m_axi_rresp),
386
+ .m_axi_rlast (m_axi_rlast),
387
+ .m_axi_ruser (),
388
+ .m_axi_rvalid (m_axi_rvalid),
389
+ .m_axi_rready (m_axi_rready)
390
+ );
391
+
392
+ `ifdef DEBUG
393
+ ila_0 ILA_PCIM_RD (
394
+ .clk (clk),
395
+ .probe0 (m_axi_arvalid),
396
+ .probe1 (m_axi_araddr),
397
+ .probe2 (m_axi_arready),
398
+ .probe3 (m_axi_rvalid),
399
+ .probe4 (m_axi_rdata[63:0]),
400
+ .probe5 (m_axi_rready)
401
+ );
402
+
403
+ ila_0 ILA_PCIM_WR (
404
+ .clk (clk),
405
+ .probe0 (m_axi_awvalid),
406
+ .probe1 (m_axi_awaddr),
407
+ .probe2 (m_axi_awready),
408
+ .probe3 (m_axi_wvalid),
409
+ .probe4 (m_axi_wdata[63:0]),
410
+ .probe5 (m_axi_wready)
411
+ );
412
+ `endif
413
+
414
+ endmodule
415
+
416
+ `default_nettype wire
@@ -0,0 +1,303 @@
1
+ // Copyright (c) 2024 Zero ASIC Corporation
2
+ // This code is licensed under Apache License 2.0 (see LICENSE for details)
3
+
4
+ `default_nettype none
5
+
6
+ module sb_rx_fpga #(
7
+ parameter ID_WIDTH = 16,
8
+ // must be <= 448 (512-64)
9
+ parameter DW = 416
10
+ ) (
11
+ input wire clk,
12
+ input wire en,
13
+ input wire reset,
14
+
15
+ output reg [DW-1:0] data={DW{1'b0}},
16
+ output reg [31:0] dest=32'b0,
17
+ output reg last=1'b0,
18
+ input wire ready,
19
+ output reg valid=1'b0,
20
+
21
+ input wire [63:0] cfg_base_addr,
22
+ input wire [31:0] cfg_capacity,
23
+
24
+ output wire status_idle,
25
+
26
+ output wire [ID_WIDTH-1:0] m_axi_awid,
27
+ output wire [63:0] m_axi_awaddr,
28
+ output wire [7:0] m_axi_awlen,
29
+ output wire [2:0] m_axi_awsize,
30
+ output wire m_axi_awvalid,
31
+ input wire m_axi_awready,
32
+
33
+ output wire [511:0] m_axi_wdata,
34
+ output wire [63:0] m_axi_wstrb,
35
+ output wire m_axi_wlast,
36
+ output wire m_axi_wvalid,
37
+ input wire m_axi_wready,
38
+
39
+ input wire [ID_WIDTH-1:0] m_axi_bid,
40
+ input wire [1:0] m_axi_bresp,
41
+ input wire m_axi_bvalid,
42
+ output wire m_axi_bready,
43
+
44
+ output wire [ID_WIDTH-1:0] m_axi_arid,
45
+ output wire [63:0] m_axi_araddr,
46
+ output wire [7:0] m_axi_arlen,
47
+ output wire [2:0] m_axi_arsize,
48
+ output wire m_axi_arvalid,
49
+ input wire m_axi_arready,
50
+
51
+ input wire [ID_WIDTH-1:0] m_axi_rid,
52
+ input wire [511:0] m_axi_rdata,
53
+ input wire [1:0] m_axi_rresp,
54
+ input wire m_axi_rlast,
55
+ input wire m_axi_rvalid,
56
+ output wire m_axi_rready
57
+ );
58
+
59
+ `include "spsc_queue.vh"
60
+
61
+ /*
62
+ * Main state machine
63
+ */
64
+
65
+ localparam [2:0] STATE_IDLE = 3'd0;
66
+ localparam [2:0] STATE_RD_HEAD = 3'd1;
67
+ localparam [2:0] STATE_RD_PACKET = 3'd2;
68
+ localparam [2:0] STATE_WR_TAIL = 3'd3;
69
+ localparam [2:0] STATE_FAULT = 3'd4;
70
+
71
+ wire wvalid;
72
+ reg [63:0] waddr;
73
+ reg [63:0] wstrb;
74
+ reg [511:0] wdata;
75
+ wire wready;
76
+
77
+ wire rvalid;
78
+ reg [63:0] raddr;
79
+ wire rready;
80
+ wire [511:0] rdata;
81
+
82
+ wire empty;
83
+ wire fault;
84
+
85
+ reg [2:0] state = STATE_IDLE;
86
+ reg [2:0] state_next;
87
+
88
+ always @(*) begin
89
+ state_next = state;
90
+ case (state)
91
+ STATE_IDLE: begin
92
+ if (!valid && en) begin
93
+ if (!empty) begin
94
+ state_next = STATE_RD_PACKET;
95
+ end else begin
96
+ state_next = STATE_RD_HEAD;
97
+ end
98
+ end
99
+ end
100
+
101
+ STATE_RD_HEAD: begin
102
+ if (rready && !en) begin
103
+ state_next = STATE_IDLE;
104
+ end else if (!empty) begin
105
+ state_next = STATE_RD_PACKET;
106
+ end
107
+ end
108
+
109
+ STATE_RD_PACKET: begin
110
+ // This state doesn't force a transition to IDLE on !en, since
111
+ // we always need to write the tail after reading the packet.
112
+ if (rready) begin
113
+ state_next = STATE_WR_TAIL;
114
+ end
115
+ end
116
+
117
+ STATE_WR_TAIL: begin
118
+ if (wready) begin
119
+ state_next = STATE_IDLE;
120
+ end
121
+ end
122
+
123
+ STATE_FAULT: begin
124
+ state_next = STATE_FAULT;
125
+ end
126
+
127
+ // Shouldn't reach here
128
+ default: state_next = 3'bXXX;
129
+ endcase
130
+ end
131
+
132
+ always @(posedge clk) begin
133
+ if (reset) begin
134
+ state <= STATE_IDLE;
135
+ end else if (fault) begin
136
+ state <= STATE_FAULT;
137
+ end else begin
138
+ state <= state_next;
139
+ end
140
+ end
141
+
142
+ /*
143
+ * Queue state logic
144
+ */
145
+
146
+ reg [31:0] head = 32'd0;
147
+ reg [31:0] tail = 32'd0;
148
+ wire [31:0] head_next;
149
+ wire [31:0] tail_next;
150
+ wire [31:0] tail_incr;
151
+
152
+ assign head_next = (state == STATE_RD_HEAD && rready) ? rdata[31:0] : head;
153
+
154
+ assign tail_incr = (tail + 32'd1 == cfg_capacity) ? 32'd0 : (tail + 32'd1);
155
+ assign tail_next = (state == STATE_RD_PACKET && rready) ? tail_incr : tail;
156
+
157
+ always @(posedge clk) begin
158
+ if (reset) begin
159
+ head <= 32'd0;
160
+ tail <= 32'd0;
161
+ end else begin
162
+ head <= head_next;
163
+ tail <= tail_next;
164
+ end
165
+ end
166
+
167
+ // Use *_next signals here to speed up state machine transitions.
168
+ assign empty = (head_next == tail_next);
169
+
170
+ // Addresses within queue
171
+ wire [63:0] head_addr;
172
+ wire [63:0] tail_addr;
173
+ assign head_addr = cfg_base_addr + HEAD_OFFSET;
174
+ assign tail_addr = cfg_base_addr + TAIL_OFFSET;
175
+
176
+ /*
177
+ * Checker for out-of-bounds writes
178
+ */
179
+
180
+ wire wvalid_checked;
181
+ wire [63:0] fault_addr;
182
+ memory_fault write_checker(
183
+ .clk(clk),
184
+ .reset(reset),
185
+
186
+ .access_valid_in(wvalid),
187
+ .access_addr(waddr),
188
+ .access_valid_out(wvalid_checked),
189
+
190
+ .base_legal_addr(cfg_base_addr),
191
+ .legal_length(cfg_capacity * PACKET_SIZE + PACKET_OFFSET),
192
+
193
+ .fault(fault),
194
+ .fault_addr(fault_addr)
195
+ );
196
+
197
+ /*
198
+ * Simple W/R interface to AXI bus
199
+ */
200
+
201
+ axi_writer #(
202
+ .ID_WIDTH(ID_WIDTH)
203
+ ) writer (
204
+ .wvalid(wvalid_checked),
205
+ .*
206
+ );
207
+
208
+ axi_reader #(
209
+ .ID_WIDTH(ID_WIDTH)
210
+ ) reader (
211
+ .*
212
+ );
213
+
214
+ assign wvalid = (state == STATE_WR_TAIL);
215
+ always @(*) begin
216
+ waddr = 64'd0;
217
+ wstrb = 64'd0;
218
+ wdata = 512'd0;
219
+ if (state == STATE_WR_TAIL) begin
220
+ waddr = tail_addr;
221
+ wstrb = 64'hff;
222
+ wdata = {480'd0, tail};
223
+ end
224
+ end
225
+ assign rvalid = ((state == STATE_RD_HEAD) || (state == STATE_RD_PACKET));
226
+ always @(*) begin
227
+ raddr = 64'd0;
228
+ if (state == STATE_RD_HEAD) begin
229
+ raddr = head_addr;
230
+ end else if (state == STATE_RD_PACKET) begin
231
+ raddr = cfg_base_addr + PACKET_OFFSET + (tail * PACKET_SIZE);
232
+ end
233
+ end
234
+
235
+ /*
236
+ * SB handshaking
237
+ */
238
+
239
+ // This logic relies on maintaining invariant that valid != 1 when state ==
240
+ // STATE_RD_PACKET
241
+ always @(posedge clk) begin
242
+ if (reset) begin
243
+ valid <= 1'b0;
244
+ dest <= 32'd0;
245
+ last <= 1'b0;
246
+ data <= 'd0;
247
+ end else if (state == STATE_RD_PACKET && rready) begin
248
+ valid <= 1'b1;
249
+ dest <= rdata[31:0];
250
+ last <= rdata[32];
251
+ data <= rdata[DW+64-1:64];
252
+ end else if (valid && ready) begin
253
+ valid <= 1'b0;
254
+ end
255
+ end
256
+
257
+ assign status_idle = state == STATE_IDLE;
258
+
259
+ `ifdef DEBUG
260
+ ila_0 ILA_RD (
261
+ .clk (clk),
262
+ .probe0 (m_axi_arvalid),
263
+ .probe1 (m_axi_araddr),
264
+ .probe2 (m_axi_arready),
265
+ .probe3 (m_axi_rvalid),
266
+ .probe4 (m_axi_rdata[63:0]),
267
+ .probe5 (m_axi_rready)
268
+ );
269
+
270
+ ila_0 ILA_WR (
271
+ .clk (clk),
272
+ .probe0 (m_axi_awvalid),
273
+ .probe1 (m_axi_awaddr),
274
+ .probe2 (m_axi_awready),
275
+ .probe3 (m_axi_wvalid),
276
+ .probe4 (m_axi_wdata[63:0]),
277
+ .probe5 (m_axi_wready)
278
+ );
279
+
280
+ ila_0 ILA_STATE (
281
+ .clk (clk),
282
+ .probe0 (en),
283
+ .probe1 ({head, tail}),
284
+ .probe2 (valid),
285
+ .probe3 (ready),
286
+ .probe4 ({state, tail_incr}),
287
+ .probe5 (empty)
288
+ );
289
+
290
+ ila_0 ILA_FAULT (
291
+ .clk (clk),
292
+ .probe0 (fault),
293
+ .probe1 (fault_addr),
294
+ .probe2 (),
295
+ .probe3 (),
296
+ .probe4 (),
297
+ .probe5 ()
298
+ );
299
+ `endif
300
+
301
+ endmodule
302
+
303
+ `default_nettype wire