Skip to content
Closed
Changes from all commits
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
145 changes: 89 additions & 56 deletions rtl/ecc_wrap/ecc_scrubber.sv
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@
// - iteratively steps through memory bank
// - corrects *only* correctable errors

module ecc_scrubber #(
module ecc_scrubber
import ariane_pkg::*;
#(
parameter int unsigned BankSize = 256,
parameter bit UseExternalECC = 0,
parameter int unsigned DataWidth = 39,
parameter int unsigned ProtWidth = 7
parameter int unsigned ProtWidth = 7,
parameter int unsigned AddrWidth = 8,
parameter int unsigned DCACHE_SET_ASSOC = 2
) (
input logic clk_i,
input logic rst_ni,
Expand All @@ -26,41 +30,46 @@ module ecc_scrubber #(
output logic uncorrectable_o,

// Input signals from others accessing memory bank
input logic intc_req_i,
input logic [DCACHE_SET_ASSOC-1:0] intc_req_i,
input logic intc_we_i,
input logic [$clog2(BankSize)-1:0] intc_add_i,
input logic [ DataWidth-1:0] intc_wdata_i,
output logic [ DataWidth-1:0] intc_rdata_o,
input logic [AddrWidth-1:0] intc_add_i,
input std_cache_pkg::cl_be_SRAM_t intc_be_i,
input std_cache_pkg::cache_line_SRAM_t intc_wdata_i,
output std_cache_pkg::cache_line_SRAM_t [DCACHE_SET_ASSOC-1:0]intc_rdata_o,

// Output directly to bank
output logic bank_req_o,
output logic [DCACHE_SET_ASSOC-1:0] bank_req_o,
output logic bank_we_o,
output logic [$clog2(BankSize)-1:0] bank_add_o,
output logic [ DataWidth-1:0] bank_wdata_o,
input logic [ DataWidth-1:0] bank_rdata_i,

// If using external ECC
output logic [ DataWidth-1:0] ecc_out_o,
input logic [ DataWidth-1:0] ecc_in_i,
input logic [ 2:0] ecc_err_i
output logic [AddrWidth-1:0] bank_add_o,
output std_cache_pkg::cache_line_SRAM_t bank_wdata_o,
input std_cache_pkg::cache_line_SRAM_t [DCACHE_SET_ASSOC-1:0] bank_rdata_i,
output std_cache_pkg::cl_be_SRAM_t bank_be_o


);
// TODO vldrty add per cache
// Note TODO, currently is this module deactivted


logic [ 1:0] ecc_err;
logic [SECDEC_DIVISIONS_DATA-1:0][ 1:0] ecc_err_s;

logic scrub_req;
logic [ 1:0] ecc_err_t;
logic [1:0] ecc_err;

logic[DCACHE_SET_ASSOC-1:0] scrub_req, scrub_req_d, scrub_req_q;
logic scrub_we;
logic [$clog2(BankSize)-1:0] scrub_add;
logic [ DataWidth-1:0] scrub_wdata;
logic [ DataWidth-1:0] scrub_rdata;
logic [AddrWidth-1:0] scrub_add;
std_cache_pkg::cache_line_SRAM_t scrub_wdata;
std_cache_pkg::cache_line_SRAM_t [DCACHE_SET_ASSOC-1:0] scrub_rdata;

typedef enum logic [2:0] {Idle, Read, Write} scrub_state_e;

scrub_state_e state_d, state_q;
scrub_state_e state_s_d, state_s_q;

logic [$clog2(BankSize)-1:0] working_add_d, working_add_q;
logic [AddrWidth-1:0] working_add_d, working_add_q;
assign scrub_add = working_add_q;

assign bank_req_o = intc_req_i || scrub_req;
assign bank_req_o = (scrub_trigger_i && (state_s_q == Read || state_s_q == Write) && (|intc_req_i) == 1'b0) ? 2**scrub_req : intc_req_i;
assign intc_rdata_o = bank_rdata_i;
assign scrub_rdata = bank_rdata_i;

Expand All @@ -69,72 +78,94 @@ module ecc_scrubber #(
bank_we_o = intc_we_i;
bank_add_o = intc_add_i;
bank_wdata_o = intc_wdata_i;
bank_be_o = intc_be_i;

// If scrubber active and outside is not, do scrub
if ( (state_q == Read || state_q == Write) && intc_req_i == 1'b0) begin
if (scrub_trigger_i && (state_s_q == Read || state_s_q == Write) && (|intc_req_i) == 1'b0) begin

bank_we_o = scrub_we;
bank_add_o = scrub_add;
bank_wdata_o = scrub_wdata;
bank_be_o = '1;
end
end

if (UseExternalECC) begin : gen_external_ecc
assign ecc_err = ecc_err_i;
assign ecc_out_o = scrub_rdata;
assign scrub_wdata = ecc_in_i;
end else begin : gen_internal_ecc
assign ecc_out_o = '0;
hsiao_ecc_cor #(
.DataWidth (DataWidth-ProtWidth),
.ProtWidth (ProtWidth)
) ecc_corrector (
.in ( scrub_rdata ),
.out ( scrub_wdata ),
for (genvar j = 0; j<SECDEC_DIVISIONS_DATA;j++) begin
hsiao_ecc_cor #(
.DataWidth (SECDEC_BLOCK_SIZE)
) ecc_corrector (
.in ( scrub_rdata[scrub_req_q].data[j*SECDEC_BLOCK_SIZE_ECC+:SECDEC_BLOCK_SIZE_ECC] ),
.out ( scrub_wdata.data[j*SECDEC_BLOCK_SIZE_ECC+:SECDEC_BLOCK_SIZE_ECC] ),
.syndrome_o(),
.err_o ( ecc_err )
);
.err_o ( ecc_err_s[j] )
);
end

hsiao_ecc_cor #(
.DataWidth (DCACHE_TAG_WIDTH)
) ecc_corrector (
.in ( scrub_rdata[scrub_req_q].tag),
.out ( scrub_wdata.tag),
.syndrome_o(),
.err_o ( ecc_err_t )
);


assign scrub_wdata.dirty =scrub_rdata[scrub_req_q].dirty;
assign scrub_wdata.valid =scrub_rdata[scrub_req_q].valid;




assign ecc_err = (|ecc_err_s) | ecc_err_t;

always_comb begin : proc_FSM_logic
state_d = state_q;
scrub_req = 1'b0;
state_s_d = state_s_q;
scrub_req = scrub_req_q;
scrub_we = 1'b0;
working_add_d = working_add_q;
scrub_req_d = scrub_req_q;
bit_corrected_o = 1'b0;
uncorrectable_o = 1'b0;

if (state_q == Idle) begin
if (state_s_q == Idle) begin
// Switch to read state if triggered to scrub
if (scrub_trigger_i) begin
state_d = Read;
if (scrub_trigger_i) begin // TODO maybe add time delay
state_s_d = Read;
end

end else if (state_q == Read) begin
end else if (state_s_q == Read) begin
// Request read to scrub
scrub_req = 1'b1;
scrub_req = scrub_req_q;
// Request only active if outside is inactive
if (intc_req_i == 1'b0) begin
state_d = Write;
state_s_d = Write;
end

end else if (state_q == Write) begin
if (ecc_err[0] == 1'b0) begin // No correctable Error
end else if (state_s_q == Write) begin
if (ecc_err[0] == 1'b0) begin // No correctable Error TODO make a loop and not do |ecc_err
// Return to idle state
state_d = Idle;
working_add_d = (working_add_q + 1) % BankSize; // increment address
state_s_d = Idle;
scrub_req_d = (scrub_req_q ) % DCACHE_SET_ASSOC;
if (scrub_req_q== DCACHE_SET_ASSOC-1) begin //count of the req and then afterwards count up the address
working_add_d = (working_add_q + 1) % BankSize; // increment address
end
uncorrectable_o = ecc_err[1];

end else begin // Correctable Error
// Write corrected version
scrub_req = 1'b1;
scrub_req = scrub_req_q;
scrub_we = 1'b1;

// INTC interference - retry read and write
if (intc_req_i == 1'b1) begin
state_d = Read;
state_s_d = Read;
end else begin // Error corrected
state_d = Idle;
working_add_d = (working_add_q + 1) % BankSize; // increment address
state_s_d = Idle;
scrub_req_d = (scrub_req_q + 1) % DCACHE_SET_ASSOC;
if (scrub_req_q== DCACHE_SET_ASSOC-1) begin //count of the req and then afterwards count up the address
working_add_d = (working_add_q + 1) % BankSize; // increment address
end
bit_corrected_o = 1'b1;
end
end
Expand All @@ -144,16 +175,18 @@ module ecc_scrubber #(
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_bank_add
if(!rst_ni) begin
working_add_q <= '0;
scrub_req_q <= '0;
end else begin
working_add_q <= working_add_d;
scrub_req_q <= scrub_req_d;
end
end

always_ff @(posedge clk_i or negedge rst_ni) begin : proc_FSM
if(!rst_ni) begin
state_q <= Idle;
state_s_q <= Idle;
end else begin
state_q <= state_d;
state_s_q <= state_s_d;
end
end

Expand Down