Skip to content

Commit 265b4cf

Browse files
committed
multiaddr_decode: Add default port logic
1 parent 47b020a commit 265b4cf

File tree

1 file changed

+79
-14
lines changed

1 file changed

+79
-14
lines changed

src/multiaddr_decode.sv

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

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

85115
always_comb begin
86116
// default assignments
87-
matched_rules = '0;
88-
dec_valid_o = 1'b0;
89-
dec_error_o = 1'b1;
90-
select_o = '0;
91-
addr_o = '0;
92-
mask_o = '0;
117+
matched_rules = '0;
118+
dec_valid_o = 1'b0;
119+
dec_error_o = en_default_idx_i ? 1'b0 : 1'b1;
120+
select_o = '0;
121+
// input address and mask are propagated unchanged to the default slave
122+
addr_o = '0;
123+
mask_o = '0;
124+
addr_o[default_idx_i.idx] = en_default_idx_i ? addr_i : '0;
125+
mask_o[default_idx_i.idx] = en_default_idx_i ? mask_i : '0;
93126

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

124165
// Assumptions and assertions
@@ -131,19 +172,43 @@ module multiaddr_decode #(
131172
end
132173

133174
// These following assumptions check the validity of the address map.
134-
// check_idx: Enforces a valid index in the rule.
175+
// check_default_idx: Enforces a valid default idx.
176+
// check_rule_idx: Enforces a valid index in the rule.
177+
// check_rule_idx_default: Checks that no rule contains the default index.
135178
`ifndef SYNTHESIS
136179
always_comb begin : proc_check_addr_map
137180
if (!$isunknown(addr_map_i)) begin
181+
182+
// check the default slave index
183+
if (en_default_idx_i) begin
184+
`ASSUME_I(check_default_idx, default_idx_i.idx < NoIndices,
185+
$sformatf("Default index value is not allowed!!!\n\
186+
IDX: %h\n\
187+
MAX_IDX: %h\n\
188+
#####################################################",
189+
default_idx_i.idx, NoIndices - 1));
190+
end
191+
138192
for (int unsigned i = 0; i < NoRules; i++) begin
139-
// check the SLV ids
140-
`ASSUME_I(check_idx, addr_map_i[i].idx < NoIndices,
193+
// check the slave indices
194+
`ASSUME_I(check_rule_idx, addr_map_i[i].idx < NoIndices,
195+
$sformatf("This rule has a IDX that is not allowed!!!\n\
196+
Violating rule %d.\n\
197+
Rule> IDX: %h\n\
198+
Rule> MAX_IDX: %h\n\
199+
#####################################################",
200+
i, addr_map_i[i].idx, NoIndices - 1));
201+
202+
// check the default rule
203+
if (en_default_idx_i) begin
204+
`ASSUME_I(check_rule_idx_default, addr_map_i[i].idx != default_idx_i.idx,
141205
$sformatf("This rule has a IDX that is not allowed!!!\n\
142206
Violating rule %d.\n\
143-
Rule> IDX: %h\n\
144-
Rule> MAX_IDX: %h\n\
207+
Index: %h\n\
208+
Default index> : %h\n\
145209
#####################################################",
146-
i, addr_map_i[i].idx, (NoIndices-1)))
210+
i, addr_map_i[i].idx, default_idx_i.idx));
211+
end
147212
end
148213
end
149214
end

0 commit comments

Comments
 (0)