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.
3240module 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