Skip to content

Commit 3bbd28c

Browse files
committed
[rtl] Add common security features of regfiles to separate module
1 parent 0369438 commit 3bbd28c

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

rtl/ibex_register_file_common.sv

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
// Copyright lowRISC contributors.
2+
// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
3+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
/**
7+
* RISC-V register file
8+
*
9+
* Register file common security functionality across multiple implementations
10+
*/
11+
12+
module ibex_register_file_common #(
13+
parameter bit FPGA = 0,
14+
parameter int unsigned AddrWidth = 5,
15+
parameter int unsigned NumWords = 2 ** AddrWidth,
16+
parameter bit WrenCheck = 0,
17+
parameter bit RdataMuxCheck = 0
18+
) (
19+
/* verilator lint_off UNUSED */
20+
// Clock and Reset
21+
input logic clk_i,
22+
input logic rst_ni,
23+
/* verilator lint_on UNUSED */
24+
25+
//Read port R1
26+
input logic [4:0] raddr_a_i,
27+
output logic [NumWords-1:0] raddr_onehot_a,
28+
output logic oh_raddr_a_err,
29+
30+
//Read port R2
31+
input logic [4:0] raddr_b_i,
32+
output logic [NumWords-1:0] raddr_onehot_b,
33+
output logic oh_raddr_b_err,
34+
35+
// Write port W1
36+
input logic [4:0] waddr_a_i,
37+
input logic we_a_i,
38+
output logic [NumWords-1:0] we_onehot_a,
39+
output logic oh_we_err,
40+
41+
// This indicates whether spurious WE or non-one-hot encoded raddr are detected.
42+
output logic err_o
43+
);
44+
45+
if (FPGA) begin : gen_fpga_oh_we_a_o_decoder
46+
always_comb begin : oh_we_a_o_decoder
47+
for (int unsigned i = 0; i < NumWords; i++) begin
48+
we_onehot_a[i] = (i == 0) ? we_a_i : 1'b0;
49+
end
50+
end
51+
end else begin : gen_other_oh_we_a_o_decoder
52+
always_comb begin : oh_we_a_o_decoder
53+
for (int unsigned i = 0; i < NumWords; i++) begin
54+
we_onehot_a[i] = (waddr_a_i == 5'(i)) ? we_a_i : 1'b0;
55+
end
56+
end
57+
end
58+
59+
// SEC_CM: DATA_REG_SW.GLITCH_DETECT
60+
// This checks for spurious WE strobes on the regfile.
61+
if (WrenCheck) begin : gen_wren_check
62+
// Buffer the decoded write enable bits so that the checker
63+
// is not optimized into the address decoding logic.
64+
logic [NumWords-1:0] we_onehot_a_buf;
65+
prim_buf #(
66+
.Width(NumWords)
67+
) u_prim_buf (
68+
.in_i (we_onehot_a),
69+
.out_o(we_onehot_a_buf)
70+
);
71+
72+
prim_onehot_check #(
73+
.AddrWidth (AddrWidth),
74+
.OneHotWidth(NumWords),
75+
.AddrCheck (FPGA ? 0 : 1), // disable in case of FPGA impl, as we use [0] only
76+
.EnableCheck(1),
77+
) u_prim_onehot_check (
78+
.clk_i,
79+
.rst_ni,
80+
.oh_i (we_onehot_a_buf),
81+
.addr_i(waddr_a_i),
82+
.en_i (we_a_i),
83+
.err_o (oh_we_err)
84+
);
85+
end else begin : gen_no_wren_check
86+
if (FPGA) begin : gen_unused_wren_check
87+
logic unused_waddr_a;
88+
assign unused_waddr_a = ^waddr_a_i;
89+
end
90+
assign oh_we_err = 1'b0;
91+
end
92+
93+
if (RdataMuxCheck) begin : gen_rdata_mux_check
94+
// Encode raddr_a/b into one-hot encoded signals.
95+
logic [NumWords-1:0] raddr_onehot_a_buf, raddr_onehot_b_buf;
96+
prim_onehot_enc #(
97+
.OneHotWidth(NumWords)
98+
) u_prim_onehot_enc_raddr_a (
99+
.in_i (raddr_a_i),
100+
.en_i (1'b1),
101+
.out_o(raddr_onehot_a)
102+
);
103+
104+
prim_onehot_enc #(
105+
.OneHotWidth(NumWords)
106+
) u_prim_onehot_enc_raddr_b (
107+
.in_i (raddr_b_i),
108+
.en_i (1'b1),
109+
.out_o(raddr_onehot_b)
110+
);
111+
112+
// Buffer the one-hot encoded signals so that the checkers
113+
// are not optimized.
114+
prim_buf #(
115+
.Width(NumWords)
116+
) u_prim_buf_raddr_a (
117+
.in_i (raddr_onehot_a),
118+
.out_o(raddr_onehot_a_buf)
119+
);
120+
121+
prim_buf #(
122+
.Width(NumWords)
123+
) u_prim_buf_raddr_b (
124+
.in_i (raddr_onehot_b),
125+
.out_o(raddr_onehot_b_buf)
126+
);
127+
128+
// SEC_CM: DATA_REG_SW.GLITCH_DETECT
129+
// Check the one-hot encoded signals for glitches.
130+
prim_onehot_check #(
131+
.AddrWidth (AddrWidth),
132+
.OneHotWidth(NumWords),
133+
.AddrCheck (1),
134+
// When AddrCheck=1 also EnableCheck needs to be 1.
135+
.EnableCheck(1)
136+
) u_prim_onehot_check_raddr_a (
137+
.clk_i,
138+
.rst_ni,
139+
.oh_i (raddr_onehot_a_buf),
140+
.addr_i(raddr_a_i),
141+
// Set enable=1 as address is always valid.
142+
.en_i (1'b1),
143+
.err_o (oh_raddr_a_err)
144+
);
145+
146+
prim_onehot_check #(
147+
.AddrWidth (AddrWidth),
148+
.OneHotWidth(NumWords),
149+
.AddrCheck (1),
150+
// When AddrCheck=1 also EnableCheck needs to be 1.
151+
.EnableCheck(1)
152+
) u_prim_onehot_check_raddr_b (
153+
.clk_i,
154+
.rst_ni,
155+
.oh_i (raddr_onehot_b_buf),
156+
.addr_i(raddr_b_i),
157+
// Set enable=1 as address is always valid.
158+
.en_i (1'b1),
159+
.err_o (oh_raddr_b_err)
160+
);
161+
end else begin : gen_no_rdata_mux_check
162+
assign oh_raddr_a_err = 1'b0;
163+
assign oh_raddr_b_err = 1'b0;
164+
assign raddr_onehot_a = '0;
165+
assign raddr_onehot_b = '0;
166+
167+
logic unused_raddr;
168+
assign unused_raddr = ^{raddr_a_i, raddr_b_i};
169+
end
170+
171+
assign err_o = oh_raddr_a_err || oh_raddr_b_err || oh_we_err;
172+
173+
endmodule

0 commit comments

Comments
 (0)