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