Skip to content

Commit 36e220a

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

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

rtl/ibex_register_file_common.sv

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

0 commit comments

Comments
 (0)