[secded] Switch to inverted ECC codes

Signed-off-by: Michael Schaffner <msf@google.com>
This commit is contained in:
Michael Schaffner 2021-12-01 18:19:15 -08:00
parent 4df2221dee
commit 169785d071
10 changed files with 54 additions and 37 deletions

View file

@ -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.

View file

@ -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);

View file

@ -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,

View file

@ -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(),

View file

@ -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)
);
@ -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])
);
@ -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 (),
@ -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 (),

View file

@ -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 (),
@ -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})
);

View file

@ -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,
@ -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
@ -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];

View file

@ -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,
@ -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;

View file

@ -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,
@ -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;
@ -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

View file

@ -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),
@ -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),
@ -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),