@@ -48,46 +48,34 @@ module ibex_register_file_ff #(
4848 localparam int unsigned NUM_WORDS = 2 ** ADDR_WIDTH ;
4949
5050 logic [DataWidth- 1 : 0 ] rf_reg [NUM_WORDS ];
51- logic [NUM_WORDS - 1 : 0 ] we_a_dec;
5251
52+ // Encode we_a/raddr_a/raddr_b into one-hot encoded signals
53+ logic [NUM_WORDS - 1 : 0 ] raddr_onehot_a, raddr_onehot_b, we_onehot_a;
54+
55+ // One-hot encoding error signals
5356 logic oh_raddr_a_err, oh_raddr_b_err, oh_we_err;
5457
55- always_comb begin : we_a_decoder
56- for (int unsigned i = 0 ; i < NUM_WORDS ; i++ ) begin
57- we_a_dec[i] = (waddr_a_i == 5 '(i)) ? we_a_i : 1'b0 ;
58- end
59- end
60-
61- // SEC_CM: DATA_REG_SW.GLITCH_DETECT
62- // This checks for spurious WE strobes on the regfile.
63- if (WrenCheck) begin : gen_wren_check
64- // Buffer the decoded write enable bits so that the checker
65- // is not optimized into the address decoding logic.
66- logic [NUM_WORDS - 1 : 0 ] we_a_dec_buf;
67- prim_buf # (
68- .Width (NUM_WORDS )
69- ) u_prim_buf (
70- .in_i (we_a_dec),
71- .out_o (we_a_dec_buf)
72- );
73-
74- prim_onehot_check # (
75- .AddrWidth (ADDR_WIDTH ),
76- .AddrCheck (1 ),
77- .EnableCheck (1 )
78- ) u_prim_onehot_check (
79- .clk_i,
80- .rst_ni,
81- .oh_i (we_a_dec_buf),
82- .addr_i (waddr_a_i),
83- .en_i (we_a_i),
84- .err_o (oh_we_err)
85- );
86- end else begin : gen_no_wren_check
87- logic unused_strobe;
88- assign unused_strobe = we_a_dec[0 ]; // this is never read from in this case
89- assign oh_we_err = 1'b0 ;
90- end
58+ // Common security functionality
59+ ibex_register_file_common # (
60+ .AddrWidth (ADDR_WIDTH ),
61+ .NumWords (NUM_WORDS ),
62+ .WrenCheck (WrenCheck),
63+ .RdataMuxCheck (RdataMuxCheck)
64+ ) security_module (
65+ .clk_i,
66+ .rst_ni,
67+ .raddr_a_i,
68+ .raddr_onehot_a,
69+ .oh_raddr_a_err,
70+ .raddr_b_i,
71+ .raddr_onehot_b,
72+ .oh_raddr_b_err,
73+ .waddr_a_i,
74+ .we_a_i,
75+ .we_onehot_a,
76+ .oh_we_err,
77+ .err_o
78+ );
9179
9280 // No flops for R0 as it's hard-wired to 0
9381 for (genvar i = 1 ; i < NUM_WORDS ; i++ ) begin : g_rf_flops
@@ -96,7 +84,7 @@ module ibex_register_file_ff #(
9684 always_ff @ (posedge clk_i or negedge rst_ni) begin
9785 if (! rst_ni) begin
9886 rf_reg_q <= WordZeroVal;
99- end else if (we_a_dec [i]) begin
87+ end else if (we_onehot_a [i]) begin
10088 rf_reg_q <= wdata_a_i;
10189 end
10290 end
@@ -134,75 +122,6 @@ module ibex_register_file_ff #(
134122 end
135123
136124 if (RdataMuxCheck) begin : gen_rdata_mux_check
137- // Encode raddr_a/b into one-hot encoded signals.
138- logic [NUM_WORDS - 1 : 0 ] raddr_onehot_a, raddr_onehot_b;
139- logic [NUM_WORDS - 1 : 0 ] raddr_onehot_a_buf, raddr_onehot_b_buf;
140- prim_onehot_enc # (
141- .OneHotWidth (NUM_WORDS )
142- ) u_prim_onehot_enc_raddr_a (
143- .in_i (raddr_a_i),
144- .en_i (1'b1 ),
145- .out_o (raddr_onehot_a)
146- );
147-
148- prim_onehot_enc # (
149- .OneHotWidth (NUM_WORDS )
150- ) u_prim_onehot_enc_raddr_b (
151- .in_i (raddr_b_i),
152- .en_i (1'b1 ),
153- .out_o (raddr_onehot_b)
154- );
155-
156- // Buffer the one-hot encoded signals so that the checkers
157- // are not optimized.
158- prim_buf # (
159- .Width (NUM_WORDS )
160- ) u_prim_buf_raddr_a (
161- .in_i (raddr_onehot_a),
162- .out_o (raddr_onehot_a_buf)
163- );
164-
165- prim_buf # (
166- .Width (NUM_WORDS )
167- ) u_prim_buf_raddr_b (
168- .in_i (raddr_onehot_b),
169- .out_o (raddr_onehot_b_buf)
170- );
171-
172- // SEC_CM: DATA_REG_SW.GLITCH_DETECT
173- // Check the one-hot encoded signals for glitches.
174- prim_onehot_check # (
175- .AddrWidth (ADDR_WIDTH ),
176- .OneHotWidth (NUM_WORDS ),
177- .AddrCheck (1 ),
178- // When AddrCheck=1 also EnableCheck needs to be 1.
179- .EnableCheck (1 )
180- ) u_prim_onehot_check_raddr_a (
181- .clk_i,
182- .rst_ni,
183- .oh_i (raddr_onehot_a_buf),
184- .addr_i (raddr_a_i),
185- // Set enable=1 as address is always valid.
186- .en_i (1'b1 ),
187- .err_o (oh_raddr_a_err)
188- );
189-
190- prim_onehot_check # (
191- .AddrWidth (ADDR_WIDTH ),
192- .OneHotWidth (NUM_WORDS ),
193- .AddrCheck (1 ),
194- // When AddrCheck=1 also EnableCheck needs to be 1.
195- .EnableCheck (1 )
196- ) u_prim_onehot_check_raddr_b (
197- .clk_i,
198- .rst_ni,
199- .oh_i (raddr_onehot_b_buf),
200- .addr_i (raddr_b_i),
201- // Set enable=1 as address is always valid.
202- .en_i (1'b1 ),
203- .err_o (oh_raddr_b_err)
204- );
205-
206125 // MUX register to rdata_a/b_o according to raddr_a/b_onehot.
207126 prim_onehot_mux # (
208127 .Width (DataWidth),
@@ -228,14 +147,21 @@ module ibex_register_file_ff #(
228147 end else begin : gen_no_rdata_mux_check
229148 assign rdata_a_o = rf_reg[raddr_a_i];
230149 assign rdata_b_o = rf_reg[raddr_b_i];
231- assign oh_raddr_a_err = 1'b0 ;
232- assign oh_raddr_b_err = 1'b0 ;
233- end
234150
235- assign err_o = oh_raddr_a_err || oh_raddr_b_err || oh_we_err;
151+ logic unused_raddr_onehot, unused_oh_raddr_err;
152+ assign unused_raddr_onehot = ^{ raddr_onehot_a, raddr_onehot_b} ;
153+ assign unused_oh_raddr_err = ^{ oh_raddr_a_err, oh_raddr_b_err} ;
154+ end
236155
237156 // Signal not used in FF register file
238157 logic unused_test_en;
239158 assign unused_test_en = test_en_i;
240159
160+ if (WrenCheck) begin : gen_wren_check
161+ end else begin : gen_no_wren_check
162+ logic unused_strobe, unused_oh_we_err;
163+ assign unused_strobe = we_onehot_a[0 ]; // this is never read from in this case
164+ assign unused_oh_we_err = oh_we_err; // this is never read from in this case
165+ end
166+
241167endmodule
0 commit comments