Skip to content

Commit

Permalink
[secded] Switch to inverted ECC codes
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Schaffner <[email protected]>
  • Loading branch information
msfschaffner committed Dec 2, 2021
1 parent 4df2221 commit 169785d
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 37 deletions.
2 changes: 1 addition & 1 deletion doc/03_reference/load_store_unit.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Bus Integrity Checking
----------------------

The core can optionally generate and verify check bits sent alongside the data for memory accesses.
Checkbits are generated and checked using a 39/32 Hsaio code (see :file:`vendor/lowrisc_ip/ip/prim/rtl/prim_secded_39_32_enc.sv`).
Checkbits are generated and checked using an inverted 39/32 Hsaio code (see :file:`vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_enc.sv`).
When this feature is used, any mismatch in checkbits will generate a major alert.

This feature is only used if the core is configured with the SecureIbex parameter set.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class ibex_mem_intf_response_seq extends uvm_sequence #(ibex_mem_intf_seq_item);
end
end
// Add correct integrity bits
{req.intg, req.data} = prim_secded_pkg::prim_secded_39_32_enc(req.data);
{req.intg, req.data} = prim_secded_pkg::prim_secded_inv_39_32_enc(req.data);
`uvm_info(get_full_name(), $sformatf("Response transfer:\n%0s", req.sprint()), UVM_HIGH)
start_item(req);
finish_item(req);
Expand Down
12 changes: 6 additions & 6 deletions dv/uvm/core_ibex/ibex_dv.f
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_assert.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_cipher_pkg.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_lfsr.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_28_22_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_28_22_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_39_32_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_39_32_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_72_64_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_72_64_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_28_22_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_28_22_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_72_64_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_72_64_dec.sv

// Until this list is generated by FuseSoC, we have to use manually generated
// wrappers around the prim_* modules to instantiate the prim_generic_* ones,
Expand Down
6 changes: 3 additions & 3 deletions rtl/ibex_core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -779,19 +779,19 @@ module ibex_core import ibex_pkg::*; #(
logic rf_ecc_err_a_id, rf_ecc_err_b_id;

// ECC checkbit generation for regiter file wdata
prim_secded_39_32_enc regfile_ecc_enc (
prim_secded_inv_39_32_enc regfile_ecc_enc (
.data_i(rf_wdata_wb),
.data_o(rf_wdata_wb_ecc_o)
);

// ECC checking on register file rdata
prim_secded_39_32_dec regfile_ecc_dec_a (
prim_secded_inv_39_32_dec regfile_ecc_dec_a (
.data_i (rf_rdata_a_ecc_i),
.data_o (),
.syndrome_o(),
.err_o (rf_ecc_err_a)
);
prim_secded_39_32_dec regfile_ecc_dec_b (
prim_secded_inv_39_32_dec regfile_ecc_dec_b (
.data_i (rf_rdata_b_ecc_i),
.data_o (),
.syndrome_o(),
Expand Down
8 changes: 4 additions & 4 deletions rtl/ibex_icache.sv
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ module ibex_icache import ibex_pkg::*; #(
assign tag_ecc_input_padded = {{22-IC_TAG_SIZE{1'b0}},fill_tag_ic0};
assign tag_ecc_output_unused = tag_ecc_output_padded[21:IC_TAG_SIZE-1];

prim_secded_28_22_enc tag_ecc_enc (
prim_secded_inv_28_22_enc tag_ecc_enc (
.data_i (tag_ecc_input_padded),
.data_o (tag_ecc_output_padded)
);
Expand All @@ -299,7 +299,7 @@ module ibex_icache import ibex_pkg::*; #(

// Dataram ECC
for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
prim_secded_39_32_enc data_ecc_enc (
prim_secded_inv_39_32_enc data_ecc_enc (
.data_i (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]),
.data_o (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC])
);
Expand Down Expand Up @@ -421,7 +421,7 @@ module ibex_icache import ibex_pkg::*; #(
{22-IC_TAG_SIZE{1'b0}},
tag_rdata_ic1[way][IC_TAG_SIZE-1:0]};

prim_secded_28_22_dec data_ecc_dec (
prim_secded_inv_28_22_dec data_ecc_dec (
.data_i (tag_rdata_padded_ic1),
.data_o (),
.syndrome_o (),
Expand All @@ -433,7 +433,7 @@ module ibex_icache import ibex_pkg::*; #(
// Data ECC checking
// Note - could generate for all ways and mux after
for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
prim_secded_39_32_dec data_ecc_dec (
prim_secded_inv_39_32_dec data_ecc_dec (
.data_i (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]),
.data_o (),
.syndrome_o (),
Expand Down
6 changes: 3 additions & 3 deletions rtl/ibex_lockstep.sv
Original file line number Diff line number Diff line change
Expand Up @@ -216,14 +216,14 @@ module ibex_lockstep import ibex_pkg::*; #(
logic [31:0] unused_wdata;

// Checks on incoming data
prim_secded_39_32_dec u_instr_intg_dec (
prim_secded_inv_39_32_dec u_instr_intg_dec (
.data_i ({instr_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].instr_rdata}),
.data_o (),
.syndrome_o (),
.err_o (instr_intg_err)
);

prim_secded_39_32_dec u_data_intg_dec (
prim_secded_inv_39_32_dec u_data_intg_dec (
.data_i ({data_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].data_rdata}),
.data_o (),
.syndrome_o (),
Expand All @@ -234,7 +234,7 @@ module ibex_lockstep import ibex_pkg::*; #(
(shadow_inputs_q[LockstepOffset-1].data_rvalid & |data_intg_err);

// Generate integrity bits
prim_secded_39_32_enc u_data_gen (
prim_secded_inv_39_32_enc u_data_gen (
.data_i (data_wdata_i),
.data_o ({data_wdata_intg_o, unused_wdata})
);
Expand Down
15 changes: 8 additions & 7 deletions rtl/ibex_register_file_ff.sv
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
* targeting FPGA synthesis or Verilator simulation.
*/
module ibex_register_file_ff #(
parameter bit RV32E = 0,
parameter int unsigned DataWidth = 32,
parameter bit DummyInstructions = 0
parameter bit RV32E = 0,
parameter int unsigned DataWidth = 32,
parameter bit DummyInstructions = 0,
parameter logic [DataWidth-1:0] WordZeroVal = '0
) (
// Clock and Reset
input logic clk_i,
Expand Down Expand Up @@ -55,7 +56,7 @@ module ibex_register_file_ff #(
for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_flops
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rf_reg_q[i] <= '0;
rf_reg_q[i] <= WordZeroVal;
end else if (we_a_dec[i]) begin
rf_reg_q[i] <= wdata_a_i;
end
Expand All @@ -73,21 +74,21 @@ module ibex_register_file_ff #(

always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rf_r0_q <= '0;
rf_r0_q <= WordZeroVal;
end else if (we_r0_dummy) begin
rf_r0_q <= wdata_a_i;
end
end

// Output the dummy data for dummy instructions, otherwise R0 reads as zero
assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : '0;
assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : WordZeroVal;

end else begin : g_normal_r0
logic unused_dummy_instr_id;
assign unused_dummy_instr_id = dummy_instr_id_i;

// R0 is nil
assign rf_reg[0] = '0;
assign rf_reg[0] = WordZeroVal;
end

assign rf_reg[NUM_WORDS-1:1] = rf_reg_q[NUM_WORDS-1:1];
Expand Down
14 changes: 11 additions & 3 deletions rtl/ibex_register_file_fpga.sv
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
* FPGA architectures, it will produce RAM32M primitives. Other vendors have not yet been tested.
*/
module ibex_register_file_fpga #(
parameter bit RV32E = 0,
parameter int unsigned DataWidth = 32,
parameter bit DummyInstructions = 0
parameter bit RV32E = 0,
parameter int unsigned DataWidth = 32,
parameter bit DummyInstructions = 0,
parameter logic [DataWidth-1:0] WordZeroVal = '0
) (
// Clock and Reset
input logic clk_i,
Expand Down Expand Up @@ -56,6 +57,13 @@ module ibex_register_file_fpga #(
end
end : sync_write

// Make sure we initialize the BRAM with the correct register reset value.
initial begin
for (int k = 0; k < NUM_WORDS; k++) begin
mem[k] = WordZeroVal;
end
end

// Reset not used in this register file version
logic unused_rst_ni;
assign unused_rst_ni = rst_ni;
Expand Down
13 changes: 7 additions & 6 deletions rtl/ibex_register_file_latch.sv
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
* register file when targeting ASIC synthesis or event-based simulators.
*/
module ibex_register_file_latch #(
parameter bit RV32E = 0,
parameter int unsigned DataWidth = 32,
parameter bit DummyInstructions = 0
parameter bit RV32E = 0,
parameter int unsigned DataWidth = 32,
parameter bit DummyInstructions = 0,
parameter logic [DataWidth-1:0] WordZeroVal = '0
) (
// Clock and Reset
input logic clk_i,
Expand Down Expand Up @@ -78,7 +79,7 @@ module ibex_register_file_latch #(
// Use clk_int here, since otherwise we don't want to write anything anyway.
always_ff @(posedge clk_int or negedge rst_ni) begin : sample_wdata
if (!rst_ni) begin
wdata_a_q <= '0;
wdata_a_q <= WordZeroVal;
end else begin
if (we_a_i) begin
wdata_a_q <= wdata_a_i;
Expand Down Expand Up @@ -143,13 +144,13 @@ module ibex_register_file_latch #(
end

// Output the dummy data for dummy instructions, otherwise R0 reads as zero
assign mem[0] = dummy_instr_id_i ? mem_r0 : '0;
assign mem[0] = dummy_instr_id_i ? mem_r0 : WordZeroVal;

end else begin : g_normal_r0
logic unused_dummy_instr_id;
assign unused_dummy_instr_id = dummy_instr_id_i;

assign mem[0] = '0;
assign mem[0] = WordZeroVal;
end

`ifdef VERILATOR
Expand Down
13 changes: 10 additions & 3 deletions rtl/ibex_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,16 @@ module ibex_top import ibex_pkg::*; #(
// Register file Instantiation //
/////////////////////////////////

// We're using an inverted Hsiao code, hence we need to reset
// the regfile ECC bits to 1.
localparam logic [RegFileDataWidth-1:0] WordZeroVal = RegFileDataWidth'({7'h7f, 32'h0});

if (RegFile == RegFileFF) begin : gen_regfile_ff
ibex_register_file_ff #(
.RV32E (RV32E),
.DataWidth (RegFileDataWidth),
.DummyInstructions(DummyInstructions)
.DummyInstructions(DummyInstructions),
.WordZeroVal (WordZeroVal)
) register_file_i (
.clk_i (clk),
.rst_ni(rst_ni),
Expand All @@ -332,7 +337,8 @@ module ibex_top import ibex_pkg::*; #(
ibex_register_file_fpga #(
.RV32E (RV32E),
.DataWidth (RegFileDataWidth),
.DummyInstructions(DummyInstructions)
.DummyInstructions(DummyInstructions),
.WordZeroVal (WordZeroVal)
) register_file_i (
.clk_i (clk),
.rst_ni(rst_ni),
Expand All @@ -352,7 +358,8 @@ module ibex_top import ibex_pkg::*; #(
ibex_register_file_latch #(
.RV32E (RV32E),
.DataWidth (RegFileDataWidth),
.DummyInstructions(DummyInstructions)
.DummyInstructions(DummyInstructions),
.WordZeroVal (WordZeroVal)
) register_file_i (
.clk_i (clk),
.rst_ni(rst_ni),
Expand Down

0 comments on commit 169785d

Please sign in to comment.