Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dv/uvm/core_ibex/ibex_dv.f
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
${PRJ_DIR}/rtl/ibex_multdiv_fast.sv
${PRJ_DIR}/rtl/ibex_prefetch_buffer.sv
${PRJ_DIR}/rtl/ibex_fetch_fifo.sv
${PRJ_DIR}/rtl/ibex_register_file_common.sv
${PRJ_DIR}/rtl/ibex_register_file_ff.sv
${PRJ_DIR}/rtl/ibex_register_file_fpga.sv
${PRJ_DIR}/rtl/ibex_register_file_latch.sv
Expand Down
1 change: 1 addition & 0 deletions ibex_top.core
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ filesets:
- lowrisc:prim:onehot_check
- lowrisc:prim:onehot
files:
- rtl/ibex_register_file_common.sv
- rtl/ibex_register_file_ff.sv # generic FF-based
- rtl/ibex_register_file_fpga.sv # FPGA
- rtl/ibex_register_file_latch.sv # ASIC
Expand Down
1 change: 1 addition & 0 deletions rtl/ibex_core.f
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
ibex_multdiv_fast.sv
ibex_prefetch_buffer.sv
ibex_fetch_fifo.sv
ibex_register_file_common.sv
ibex_register_file_ff.sv
ibex_core.sv
148 changes: 37 additions & 111 deletions rtl/ibex_register_file_ff.sv
Original file line number Diff line number Diff line change
Expand Up @@ -48,46 +48,34 @@ module ibex_register_file_ff #(
localparam int unsigned NUM_WORDS = 2**ADDR_WIDTH;

logic [DataWidth-1:0] rf_reg [NUM_WORDS];
logic [NUM_WORDS-1:0] we_a_dec;

// Encode we_a/raddr_a/raddr_b into one-hot encoded signals
logic [NUM_WORDS-1:0] raddr_onehot_a, raddr_onehot_b, we_onehot_a;

// One-hot encoding error signals
logic oh_raddr_a_err, oh_raddr_b_err, oh_we_err;

always_comb begin : we_a_decoder
for (int unsigned i = 0; i < NUM_WORDS; i++) begin
we_a_dec[i] = (waddr_a_i == 5'(i)) ? we_a_i : 1'b0;
end
end

// SEC_CM: DATA_REG_SW.GLITCH_DETECT
// This checks for spurious WE strobes on the regfile.
if (WrenCheck) begin : gen_wren_check
// Buffer the decoded write enable bits so that the checker
// is not optimized into the address decoding logic.
logic [NUM_WORDS-1:0] we_a_dec_buf;
prim_buf #(
.Width(NUM_WORDS)
) u_prim_buf (
.in_i(we_a_dec),
.out_o(we_a_dec_buf)
);

prim_onehot_check #(
.AddrWidth(ADDR_WIDTH),
.AddrCheck(1),
.EnableCheck(1)
) u_prim_onehot_check (
.clk_i,
.rst_ni,
.oh_i(we_a_dec_buf),
.addr_i(waddr_a_i),
.en_i(we_a_i),
.err_o(oh_we_err)
);
end else begin : gen_no_wren_check
logic unused_strobe;
assign unused_strobe = we_a_dec[0]; // this is never read from in this case
assign oh_we_err = 1'b0;
end
// Common security functionality
ibex_register_file_common #(
.AddrWidth(ADDR_WIDTH),
.NumWords(NUM_WORDS),
.WrenCheck(WrenCheck),
.RdataMuxCheck(RdataMuxCheck)
) security_module (
.clk_i,
.rst_ni,
.raddr_a_i,
.raddr_onehot_a,
.oh_raddr_a_err,
.raddr_b_i,
.raddr_onehot_b,
.oh_raddr_b_err,
.waddr_a_i,
.we_a_i,
.we_onehot_a,
.oh_we_err,
.err_o
);

// No flops for R0 as it's hard-wired to 0
for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_flops
Expand All @@ -96,7 +84,7 @@ module ibex_register_file_ff #(
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rf_reg_q <= WordZeroVal;
end else if (we_a_dec[i]) begin
end else if (we_onehot_a[i]) begin
rf_reg_q <= wdata_a_i;
end
end
Expand Down Expand Up @@ -134,75 +122,6 @@ module ibex_register_file_ff #(
end

if (RdataMuxCheck) begin : gen_rdata_mux_check
// Encode raddr_a/b into one-hot encoded signals.
logic [NUM_WORDS-1:0] raddr_onehot_a, raddr_onehot_b;
logic [NUM_WORDS-1:0] raddr_onehot_a_buf, raddr_onehot_b_buf;
prim_onehot_enc #(
.OneHotWidth(NUM_WORDS)
) u_prim_onehot_enc_raddr_a (
.in_i (raddr_a_i),
.en_i (1'b1),
.out_o (raddr_onehot_a)
);

prim_onehot_enc #(
.OneHotWidth(NUM_WORDS)
) u_prim_onehot_enc_raddr_b (
.in_i (raddr_b_i),
.en_i (1'b1),
.out_o (raddr_onehot_b)
);

// Buffer the one-hot encoded signals so that the checkers
// are not optimized.
prim_buf #(
.Width(NUM_WORDS)
) u_prim_buf_raddr_a (
.in_i (raddr_onehot_a),
.out_o(raddr_onehot_a_buf)
);

prim_buf #(
.Width(NUM_WORDS)
) u_prim_buf_raddr_b (
.in_i (raddr_onehot_b),
.out_o(raddr_onehot_b_buf)
);

// SEC_CM: DATA_REG_SW.GLITCH_DETECT
// Check the one-hot encoded signals for glitches.
prim_onehot_check #(
.AddrWidth(ADDR_WIDTH),
.OneHotWidth(NUM_WORDS),
.AddrCheck(1),
// When AddrCheck=1 also EnableCheck needs to be 1.
.EnableCheck(1)
) u_prim_onehot_check_raddr_a (
.clk_i,
.rst_ni,
.oh_i (raddr_onehot_a_buf),
.addr_i (raddr_a_i),
// Set enable=1 as address is always valid.
.en_i (1'b1),
.err_o (oh_raddr_a_err)
);

prim_onehot_check #(
.AddrWidth(ADDR_WIDTH),
.OneHotWidth(NUM_WORDS),
.AddrCheck(1),
// When AddrCheck=1 also EnableCheck needs to be 1.
.EnableCheck(1)
) u_prim_onehot_check_raddr_b (
.clk_i,
.rst_ni,
.oh_i (raddr_onehot_b_buf),
.addr_i (raddr_b_i),
// Set enable=1 as address is always valid.
.en_i (1'b1),
.err_o (oh_raddr_b_err)
);

// MUX register to rdata_a/b_o according to raddr_a/b_onehot.
prim_onehot_mux #(
.Width(DataWidth),
Expand All @@ -228,14 +147,21 @@ module ibex_register_file_ff #(
end else begin : gen_no_rdata_mux_check
assign rdata_a_o = rf_reg[raddr_a_i];
assign rdata_b_o = rf_reg[raddr_b_i];
assign oh_raddr_a_err = 1'b0;
assign oh_raddr_b_err = 1'b0;
end

assign err_o = oh_raddr_a_err || oh_raddr_b_err || oh_we_err;
logic unused_raddr_onehot, unused_oh_raddr_err;
assign unused_raddr_onehot = ^{raddr_onehot_a, raddr_onehot_b};
assign unused_oh_raddr_err = ^{oh_raddr_a_err, oh_raddr_b_err};
end

// Signal not used in FF register file
logic unused_test_en;
assign unused_test_en = test_en_i;

if (WrenCheck) begin : gen_wren_check
end else begin : gen_no_wren_check
logic unused_strobe, unused_oh_we_err;
assign unused_strobe = we_onehot_a[0]; // this is never read from in this case
assign unused_oh_we_err = oh_we_err; // this is never read from in this case
end

endmodule
118 changes: 36 additions & 82 deletions rtl/ibex_register_file_fpga.sv
Original file line number Diff line number Diff line change
Expand Up @@ -48,82 +48,38 @@ module ibex_register_file_fpga #(
logic [DataWidth-1:0] mem[NUM_WORDS];
logic we; // write enable if writing to any register other than R0

logic [DataWidth-1:0] mem_o_a, mem_o_b;
// Encode we_a/raddr_a/raddr_b into one-hot encoded signals
logic [NUM_WORDS-1:0] raddr_onehot_a, raddr_onehot_b, we_onehot_a;

// WE strobe and one-hot encoded raddr alert.
logic oh_raddr_a_err, oh_raddr_b_err, oh_we_err;
assign err_o = oh_raddr_a_err || oh_raddr_b_err || oh_we_err;

if (RdataMuxCheck) begin : gen_rdata_mux_check
// Encode raddr_a/b into one-hot encoded signals.
logic [NUM_WORDS-1:0] raddr_onehot_a, raddr_onehot_b;
logic [NUM_WORDS-1:0] raddr_onehot_a_buf, raddr_onehot_b_buf;
prim_onehot_enc #(
.OneHotWidth(NUM_WORDS)
) u_prim_onehot_enc_raddr_a (
.in_i (raddr_a_i),
.en_i (1'b1),
.out_o (raddr_onehot_a)
);

prim_onehot_enc #(
.OneHotWidth(NUM_WORDS)
) u_prim_onehot_enc_raddr_b (
.in_i (raddr_b_i),
.en_i (1'b1),
.out_o (raddr_onehot_b)
);

// Buffer the one-hot encoded signals so that the checkers
// are not optimized.
prim_buf #(
.Width(NUM_WORDS)
) u_prim_buf_raddr_a (
.in_i (raddr_onehot_a),
.out_o(raddr_onehot_a_buf)
);

prim_buf #(
.Width(NUM_WORDS)
) u_prim_buf_raddr_b (
.in_i (raddr_onehot_b),
.out_o(raddr_onehot_b_buf)
);

// SEC_CM: DATA_REG_SW.GLITCH_DETECT
// Check the one-hot encoded signals for glitches.
prim_onehot_check #(
.AddrWidth(ADDR_WIDTH),
.OneHotWidth(NUM_WORDS),
.AddrCheck(1),
// When AddrCheck=1 also EnableCheck needs to be 1.
.EnableCheck(1)
) u_prim_onehot_check_raddr_a (
.clk_i,
.rst_ni,
.oh_i (raddr_onehot_a_buf),
.addr_i (raddr_a_i),
// Set enable=1 as address is always valid.
.en_i (1'b1),
.err_o (oh_raddr_a_err)
);
logic [DataWidth-1:0] mem_o_a, mem_o_b;

prim_onehot_check #(
.AddrWidth(ADDR_WIDTH),
.OneHotWidth(NUM_WORDS),
.AddrCheck(1),
// When AddrCheck=1 also EnableCheck needs to be 1.
.EnableCheck(1)
) u_prim_onehot_check_raddr_b (
.clk_i,
.rst_ni,
.oh_i (raddr_onehot_b_buf),
.addr_i (raddr_b_i),
// Set enable=1 as address is always valid.
.en_i (1'b1),
.err_o (oh_raddr_b_err)
);
// Common security functionality
ibex_register_file_common #(
.FPGA(1),
.AddrWidth(ADDR_WIDTH),
.NumWords(NUM_WORDS),
.WrenCheck(WrenCheck),
.RdataMuxCheck(RdataMuxCheck)
) security_module (
.clk_i,
.rst_ni,
.raddr_a_i,
.raddr_onehot_a,
.oh_raddr_a_err,
.raddr_b_i,
.raddr_onehot_b,
.oh_raddr_b_err,
.waddr_a_i,
.we_a_i,
.we_onehot_a,
.oh_we_err,
.err_o
);

if (RdataMuxCheck) begin : gen_rdata_mux_check
// MUX register to rdata_a/b_o according to raddr_a/b_onehot.
prim_onehot_mux #(
.Width(DataWidth),
Expand Down Expand Up @@ -153,21 +109,13 @@ module ibex_register_file_fpga #(
assign rdata_a_o = (raddr_a_i == '0) ? WordZeroVal : mem[raddr_a_i];
assign rdata_b_o = (raddr_b_i == '0) ? WordZeroVal : mem[raddr_b_i];

assign oh_raddr_a_err = 1'b0;
assign oh_raddr_b_err = 1'b0;
logic unused_raddr_onehot, unused_oh_raddr_err;
assign unused_raddr_onehot = ^{raddr_onehot_a, raddr_onehot_b};
assign unused_oh_raddr_err = ^{oh_raddr_a_err, oh_raddr_b_err};
end

// we select
assign we = (waddr_a_i == '0) ? 1'b0 : we_a_i;

// SEC_CM: DATA_REG_SW.GLITCH_DETECT
// This checks for spurious WE strobes on the regfile.
if (WrenCheck) begin : gen_wren_check
// Since the FPGA uses a memory macro, there is only one write-enable strobe to check.
assign oh_we_err = we && !we_a_i;
end else begin : gen_no_wren_check
assign oh_we_err = 1'b0;
end
assign we = (waddr_a_i == '0) ? 1'b0 : we_onehot_a[0];

// Note that the SystemVerilog LRM requires variables on the LHS of assignments within
// "always_ff" to not be written to by any other process. However, to enable the initialization
Expand Down Expand Up @@ -198,4 +146,10 @@ module ibex_register_file_fpga #(
logic unused_test_en;
assign unused_test_en = test_en_i;

if (WrenCheck) begin : gen_wren_check
end else begin : gen_no_wren_check
logic unused_oh_we_err;
assign unused_oh_we_err = oh_we_err; // this is never read from in this case
end
Comment on lines +149 to +153
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe change this to if (!WrenCheck) begin: gen_no_wren_check? Same with the above examples.


endmodule
Loading