Skip to content

Commit 0fd2ba3

Browse files
committed
multiaddr_decode: Add default port logic
1 parent 10dac0f commit 0fd2ba3

File tree

1 file changed

+71
-11
lines changed

1 file changed

+71
-11
lines changed

src/multiaddr_decode.sv

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@
2727
/// is set.
2828
/// For each rule, it also returns the subset of addresses in {`addr_i`, `mask_i`} which
2929
/// match the rule {`addr_o[i]`, `mask_o[i]`}.
30+
///
31+
/// There is the possibility to add a default mapping:
32+
/// `en_default_idx_i`: Driving this port to `1'b1` maps all input addresses
33+
/// for which no rule in `addr_map_i` exists to the default index specified by
34+
/// `default_idx_i`. In this case, `dec_error_o` is always `1'b0`.
35+
/// Note: `default_idx_i` must carry the rule representing the union of all other
36+
/// rules' address sets, in order to determine if any address in the input address
37+
/// doesn't fall in the address set of any rule.
3038
module multiaddr_decode #(
3139
/// Highest index which can happen in a rule.
3240
parameter int unsigned NoIndices = 32'd0,
@@ -60,7 +68,16 @@ module multiaddr_decode #(
6068
/// to the {addr, mask} representation (and viceversa) using the following equations:
6169
/// - mask = {'0, {log2(end - start){1'b1}}}
6270
/// - addr = start
63-
parameter type rule_t = logic
71+
parameter type rule_t = logic,
72+
/// Dependent parameter, do **not** overwite!
73+
///
74+
/// Width of the `default_idx_i` input port.
75+
parameter int unsigned IdxWidth = cf_math_pkg::idx_width(NoIndices),
76+
/// Dependent parameter, do **not** overwite!
77+
///
78+
/// Type of the `default_idx_i` input port.
79+
parameter type idx_t = logic [IdxWidth-1:0]
80+
6481
) (
6582
/// Multi-address to decode.
6683
input addr_t addr_i,
@@ -75,19 +92,35 @@ module multiaddr_decode #(
7592
/// Decode is valid.
7693
output logic dec_valid_o,
7794
/// Decode is not valid, no matching rule found.
78-
output logic dec_error_o
95+
output logic dec_error_o,
96+
/// Enable default port mapping.
97+
///
98+
/// When not used, tie to `0`.
99+
input logic en_default_idx_i,
100+
/// Default port rule.
101+
///
102+
/// When `en_default_idx_i` is `1`, this containes the index when the input doesn't
103+
/// fully match the other rules. To easily determine if this is the case, this signal
104+
/// carries the rule representing the union of all other rules. This is not the default
105+
/// slave's rule but actually its complement.
106+
///
107+
/// When not used, tie to `0`.
108+
input rule_t default_idx_i
79109
);
80110

81111
logic [NoRules-1:0] matched_rules; // purely for address map debugging
82112

83113
always_comb begin
84114
// default assignments
85-
matched_rules = '0;
86-
dec_valid_o = 1'b0;
87-
dec_error_o = 1'b1;
88-
select_o = '0;
89-
addr_o = '0;
90-
mask_o = '0;
115+
matched_rules = '0;
116+
dec_valid_o = 1'b0;
117+
dec_error_o = en_default_idx_i ? 1'b0 : 1'b1;
118+
select_o = '0;
119+
// input address and mask are propagated unchanged to the default slave
120+
addr_o = '0;
121+
mask_o = '0;
122+
addr_o[default_idx_i.idx] = en_default_idx_i ? addr_i : '0;
123+
mask_o[default_idx_i.idx] = en_default_idx_i ? mask_i : '0;
91124

92125
// Match the rules
93126
for (int unsigned i = 0; i < NoRules; i++) begin
@@ -117,6 +150,14 @@ module multiaddr_decode #(
117150
addr_o[idx] = (~mask_i & addr_i) | (mask_i & addr_map_i[i].addr);
118151
end
119152
end
153+
// Match the default slave rule
154+
// An input address set is fully contained in a rule's address set if there is a
155+
// match (dec_valid_o) and there are no masked bits in the input address set which
156+
// are not masked also in the rule's address set.
157+
// If the input address set is not fully contained in the union of all rules'
158+
// address sets, forward to default slave.
159+
if (en_default_idx_i)
160+
select_o[default_idx_i.idx] = (!dec_valid_o || |(mask_i & ~default_idx_i.mask));
120161
end
121162

122163
// Assumptions and assertions
@@ -132,18 +173,37 @@ module multiaddr_decode #(
132173
end
133174

134175
// These following assumptions check the validity of the address map.
135-
// check_idx: Enforces a valid index in the rule.
136-
always @(addr_map_i) #0 begin : proc_check_addr_map
176+
// check_default_idx: Enforces a valid default idx.
177+
// check_rule_idx: Enforces a valid index in the rule.
178+
// check_rule_idx_default: Checks that no rule contains the default index.
179+
always @(addr_map_i, en_default_idx_i, default_idx_i) #0 begin : proc_check_addr_map
137180
if (!$isunknown(addr_map_i)) begin
181+
if (en_default_idx_i) begin
182+
check_default_idx : assume (default_idx_i.idx < NoIndices) else
183+
$fatal(1, $sformatf("Default index value is not allowed!!!\n\
184+
IDX: %h\n\
185+
MAX_IDX: %h\n\
186+
#####################################################",
187+
default_idx_i.idx, (NoIndices-1)));
188+
end
138189
for (int unsigned i = 0; i < NoRules; i++) begin
139190
// check the SLV ids
140-
check_idx : assume (addr_map_i[i].idx < NoIndices) else
191+
check_rule_idx : assume (addr_map_i[i].idx < NoIndices) else
141192
$fatal(1, $sformatf("This rule has a IDX that is not allowed!!!\n\
142193
Violating rule %d.\n\
143194
Rule> IDX: %h\n\
144195
Rule> MAX_IDX: %h\n\
145196
#####################################################",
146197
i, addr_map_i[i].idx, (NoIndices-1)));
198+
if (en_default_idx_i) begin
199+
check_rule_idx_default : assume (addr_map_i[i].idx != default_idx_i.idx) else
200+
$fatal(1, $sformatf("This rule has a IDX that is not allowed!!!\n\
201+
Violating rule %d.\n\
202+
Index: %h\n\
203+
Default index> : %h\n\
204+
#####################################################",
205+
i, addr_map_i[i].idx, default_idx_i.idx));
206+
end
147207
end
148208
end
149209
end

0 commit comments

Comments
 (0)