Skip to content

Commit 5974980

Browse files
br_apb_demux Implementation (xlsynth#1238)
# Summary Adds an APB demux with shared address decoding, one-hot routing, optional retiming, and focused simulation coverage; refactors the CSR demux to reuse the address decoder.
1 parent 3446968 commit 5974980

9 files changed

Lines changed: 975 additions & 69 deletions

File tree

amba/rtl/BUILD.bazel

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,30 @@ verilog_library(
119119
],
120120
)
121121

122+
verilog_library(
123+
name = "br_apb_demux_select_onehot",
124+
srcs = ["br_apb_demux_select_onehot.sv"],
125+
deps = [
126+
":br_amba_apb_timing_slice",
127+
":br_amba_pkg",
128+
"//macros:br_asserts_internal",
129+
"//macros:br_unused",
130+
"//mux/rtl:br_mux_onehot",
131+
],
132+
)
133+
134+
verilog_library(
135+
name = "br_apb_demux",
136+
srcs = ["br_apb_demux.sv"],
137+
deps = [
138+
":br_amba_pkg",
139+
":br_apb_demux_select_onehot",
140+
"//demux/rtl:br_demux_addr_decode",
141+
"//macros:br_asserts_internal",
142+
"//macros:br_unused",
143+
],
144+
)
145+
122146
br_verilog_elab_and_lint_test_suite(
123147
name = "br_amba_axil2apb_test_suite",
124148
params = {
@@ -341,6 +365,113 @@ br_verilog_elab_and_lint_test_suite(
341365
deps = [":br_amba_apb_timing_slice"],
342366
)
343367

368+
br_verilog_elab_and_lint_test_suite(
369+
name = "br_apb_demux_select_onehot_test_suite",
370+
params = {
371+
"AddrWidth": [
372+
"12",
373+
"32",
374+
],
375+
"EnableDecodeError": [
376+
"0",
377+
"1",
378+
],
379+
"NumDownstreams": [
380+
"2",
381+
"3",
382+
],
383+
},
384+
deps = [":br_apb_demux_select_onehot"],
385+
)
386+
387+
br_verilog_elab_and_lint_test_suite(
388+
name = "br_apb_demux_select_onehot_test_suite_single_downstream",
389+
params = {
390+
"AddrWidth": [
391+
"12",
392+
"32",
393+
],
394+
"EnableDecodeError": [
395+
"0",
396+
"1",
397+
],
398+
"NumDownstreams": ["1"],
399+
},
400+
deps = [":br_apb_demux_select_onehot"],
401+
)
402+
403+
br_verilog_synth_suite(
404+
name = "br_apb_demux_select_onehot_baseline_ppa",
405+
params = {
406+
"AddrWidth": ["16"],
407+
"EnableDecodeError": ["1"],
408+
"NumDownstreams": ["4"],
409+
},
410+
deps = [":br_apb_demux_select_onehot"],
411+
)
412+
413+
br_verilog_synth_suite(
414+
name = "br_apb_demux_select_onehot_scaled_ppa",
415+
params = {
416+
"AddrWidth": ["32"],
417+
"EnableDecodeError": ["0"],
418+
"NumDownstreams": ["16"],
419+
},
420+
deps = [":br_apb_demux_select_onehot"],
421+
)
422+
423+
br_verilog_elab_and_lint_test_suite(
424+
name = "br_apb_demux_test_suite",
425+
params = {
426+
"AddrWidth": [
427+
"12",
428+
"32",
429+
],
430+
"HasDefaultDownstream": [
431+
"0",
432+
"1",
433+
],
434+
"NumDownstreams": [
435+
"2",
436+
"3",
437+
],
438+
},
439+
deps = [":br_apb_demux"],
440+
)
441+
442+
br_verilog_elab_and_lint_test_suite(
443+
name = "br_apb_demux_test_suite_single_downstream",
444+
params = {
445+
"AddrWidth": [
446+
"12",
447+
"32",
448+
],
449+
"HasDefaultDownstream": ["0"],
450+
"NumDownstreams": ["1"],
451+
},
452+
deps = [":br_apb_demux"],
453+
)
454+
455+
br_verilog_synth_suite(
456+
name = "br_apb_demux_baseline_ppa",
457+
params = {
458+
"AddrWidth": ["16"],
459+
"HasDefaultDownstream": ["0"],
460+
"NumDownstreams": ["4"],
461+
},
462+
deps = [":br_apb_demux"],
463+
)
464+
465+
br_verilog_synth_suite(
466+
name = "br_apb_demux_scaled_ppa",
467+
params = {
468+
"AddrWidth": ["32"],
469+
"HasDefaultDownstream": ["1"],
470+
"NumDownstreams": ["16"],
471+
},
472+
deps = [":br_apb_demux"],
473+
)
474+
344475
verilog_library(
345476
name = "br_amba_axi_isolate_sub",
346477
srcs = ["br_amba_axi_isolate_sub.sv"],

amba/rtl/br_apb_demux.sv

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
//
3+
// Bedrock-RTL Address-Decoding APB Demux
4+
//
5+
// Routes APB transfers to the correct downstream interface based on PADDR.
6+
// Address ranges, optional masking, normalization, and default routing use the
7+
// protocol-neutral br_demux_addr_decode helper. APB fanout, timing, and
8+
// response handling use br_apb_demux_select_onehot.
9+
10+
`include "br_asserts_internal.svh"
11+
`include "br_unused.svh"
12+
13+
module br_apb_demux #(
14+
parameter int AddrWidth = 12, // Must be at least 12
15+
parameter int NumDownstreams = 1, // Must be at least 1
16+
// ri lint_check_waive ARRAY_LENGTH_ONE
17+
parameter int NumRetimeStages[NumDownstreams] = '{default: 0},
18+
// When set, the final downstream receives every address that misses the
19+
// explicit ranges. Otherwise, misses complete with PSLVERR.
20+
parameter bit HasDefaultDownstream = 0,
21+
localparam int NumAddressRanges = HasDefaultDownstream ? NumDownstreams - 1 : NumDownstreams,
22+
// Require enabled ranges to be power-of-two sized and naturally aligned.
23+
// ri lint_check_waive ARRAY_LENGTH_ONE
24+
parameter bit RequirePowerOfTwoAlignedRanges[NumAddressRanges] = '{default: 1},
25+
// Rebase each explicit downstream address before applying its output mask.
26+
// ri lint_check_waive ARRAY_LENGTH_ONE
27+
parameter bit NormalizeDownstreamAddress[NumAddressRanges] = '{default: 0},
28+
// Mask used only for address decode; forwarded addresses remain unmasked.
29+
parameter logic [AddrWidth-1:0] UpstreamAddrMask = '1,
30+
// Mask applied to each forwarded address after optional normalization.
31+
parameter logic [NumDownstreams-1:0][AddrWidth-1:0] DownstreamAddrMask = '1
32+
) (
33+
input logic clk,
34+
input logic rst,
35+
36+
input logic [AddrWidth-1:0] upstream_paddr,
37+
input logic upstream_psel,
38+
input logic upstream_penable,
39+
input logic [br_amba::ApbProtWidth-1:0] upstream_pprot,
40+
input logic [3:0] upstream_pstrb,
41+
input logic upstream_pwrite,
42+
// TODO(twabbott): Parameterize APB data/strobe widths once br_amba_apb_timing_slice supports it.
43+
input logic [31:0] upstream_pwdata,
44+
output logic [31:0] upstream_prdata,
45+
output logic upstream_pready,
46+
output logic upstream_pslverr,
47+
48+
// Configurable ranges must remain stable while an APB transfer is pending.
49+
input logic [NumAddressRanges-1:0][AddrWidth-1:0] downstream_addr_base,
50+
input logic [NumAddressRanges-1:0][AddrWidth-1:0] downstream_addr_size,
51+
52+
output logic [NumDownstreams-1:0][AddrWidth-1:0] downstream_paddr,
53+
output logic [NumDownstreams-1:0] downstream_psel,
54+
output logic [NumDownstreams-1:0] downstream_penable,
55+
output logic [NumDownstreams-1:0][br_amba::ApbProtWidth-1:0] downstream_pprot,
56+
output logic [NumDownstreams-1:0][3:0] downstream_pstrb,
57+
output logic [NumDownstreams-1:0] downstream_pwrite,
58+
output logic [NumDownstreams-1:0][31:0] downstream_pwdata,
59+
input logic [NumDownstreams-1:0][31:0] downstream_prdata,
60+
input logic [NumDownstreams-1:0] downstream_pready,
61+
input logic [NumDownstreams-1:0] downstream_pslverr
62+
);
63+
// Integration Checks
64+
65+
logic upstream_request_pending;
66+
67+
assign upstream_request_pending = upstream_psel && (!upstream_penable || !upstream_pready);
68+
69+
`BR_ASSERT_STATIC(legal_num_downstreams_a, NumDownstreams >= 1 + HasDefaultDownstream)
70+
`BR_ASSERT_STATIC(legal_addr_width_a, AddrWidth >= 12)
71+
`BR_ASSERT_INTG(addr_map_stable_while_pending_a, upstream_request_pending |=> $stable
72+
({downstream_addr_base, downstream_addr_size}))
73+
`BR_UNUSED(upstream_request_pending)
74+
75+
// Implementation
76+
77+
logic [NumDownstreams-1:0] select_onehot;
78+
logic [NumDownstreams-1:0][AddrWidth-1:0] downstream_paddr_unmasked;
79+
80+
br_demux_addr_decode #(
81+
.AddrWidth(AddrWidth),
82+
.NumDownstreams(NumDownstreams),
83+
.HasDefaultDownstream(HasDefaultDownstream),
84+
.RequirePowerOfTwoAlignedRanges(RequirePowerOfTwoAlignedRanges),
85+
.NormalizeDownstreamAddress(NormalizeDownstreamAddress),
86+
.UpstreamAddrMask(UpstreamAddrMask),
87+
.DownstreamAddrMask(DownstreamAddrMask)
88+
) br_demux_addr_decode (
89+
.clk,
90+
.rst,
91+
.addr_valid(upstream_psel),
92+
.upstream_addr(upstream_paddr),
93+
.downstream_addr_base,
94+
.downstream_addr_size,
95+
.downstream_addr_in(downstream_paddr_unmasked),
96+
.select_onehot,
97+
.downstream_addr_out(downstream_paddr)
98+
);
99+
100+
br_apb_demux_select_onehot #(
101+
.AddrWidth(AddrWidth),
102+
.NumDownstreams(NumDownstreams),
103+
.EnableDecodeError(!HasDefaultDownstream),
104+
.NumRetimeStages(NumRetimeStages)
105+
) br_apb_demux_select_onehot (
106+
.clk,
107+
.rst,
108+
.select_onehot,
109+
.upstream_paddr,
110+
.upstream_psel,
111+
.upstream_penable,
112+
.upstream_pprot,
113+
.upstream_pstrb,
114+
.upstream_pwrite,
115+
.upstream_pwdata,
116+
.upstream_prdata,
117+
.upstream_pready,
118+
.upstream_pslverr,
119+
.downstream_paddr(downstream_paddr_unmasked),
120+
.downstream_psel,
121+
.downstream_penable,
122+
.downstream_pprot,
123+
.downstream_pstrb,
124+
.downstream_pwrite,
125+
.downstream_pwdata,
126+
.downstream_prdata,
127+
.downstream_pready,
128+
.downstream_pslverr
129+
);
130+
131+
endmodule : br_apb_demux

0 commit comments

Comments
 (0)