Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Assoc option to ecc_scrubber.sv #24

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
81 changes: 49 additions & 32 deletions rtl/ecc_wrap/ecc_scrubber.sv
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ module ecc_scrubber #(
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 Assoc = 1,
parameter type line_t = logic [DataWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
Expand All @@ -26,32 +28,33 @@ module ecc_scrubber #(
output logic uncorrectable_o,

// Input signals from others accessing memory bank
input logic intc_req_i,
input logic [ 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 line_t intc_wdata_i,
output line_t [ Assoc-1:0] intc_rdata_o,

// Output directly to bank
output logic bank_req_o,
output logic [ 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,
output line_t bank_wdata_o,
input line_t [ Assoc-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 line_t [ Assoc-1:0] ecc_out_o,
input line_t [ Assoc-1:0] ecc_in_i,
input logic [ Assoc-1:0][1:0] ecc_err_i
);

logic [ 1:0] ecc_err;

logic scrub_req;
logic [ Assoc-1:0][1:0] ecc_err;
int assoc_c = 0;
logic [ Assoc-1:0] scrub_req;
logic scrub_we;
logic [$clog2(BankSize)-1:0] scrub_add;
logic [ DataWidth-1:0] scrub_wdata;
logic [ DataWidth-1:0] scrub_rdata;
line_t scrub_wdata;
line_t [ Assoc-1:0] temp_scrub_wdata;
line_t [ Assoc-1:0] scrub_rdata;

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

Expand All @@ -60,7 +63,6 @@ module ecc_scrubber #(
logic [$clog2(BankSize)-1:0] working_add_d, working_add_q;
assign scrub_add = working_add_q;

assign bank_req_o = intc_req_i || scrub_req;
assign intc_rdata_o = bank_rdata_i;
assign scrub_rdata = bank_rdata_i;

Expand All @@ -69,30 +71,45 @@ module ecc_scrubber #(
bank_we_o = intc_we_i;
bank_add_o = intc_add_i;
bank_wdata_o = intc_wdata_i;
bank_req_o = intc_req_i;

// If scrubber active and outside is not, do scrub
if ( (state_q == Read || state_q == Write) && intc_req_i == 1'b0) begin
if ( (state_q == Read || state_q == Write) && |intc_req_i === 1'b0) begin
bank_we_o = scrub_we;
bank_add_o = scrub_add;
bank_wdata_o = scrub_wdata;
bank_req_o = scrub_req;
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;
assign temp_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 ),
.syndrome_o(),
.err_o ( ecc_err )
);

for (genvar assoc = 0; assoc<Assoc; ++assoc)begin : gen_error_correct_assoc
hsiao_ecc_cor #(
.DataWidth (DataWidth-ProtWidth),
.ProtWidth (ProtWidth)
) ecc_corrector (
.in ( scrub_rdata[assoc] ),
.out ( temp_scrub_wdata[assoc] ),
.syndrome_o(),
.err_o ( ecc_err[assoc] )
);
end
end

always_comb begin
for (int assoc=0; assoc<Assoc; ++assoc)begin
if ((|ecc_err[assoc])===1'b1 )begin
scrub_wdata = temp_scrub_wdata[assoc];
assoc_c = assoc;
break;
end
end
end

always_comb begin : proc_FSM_logic
Expand All @@ -111,26 +128,26 @@ module ecc_scrubber #(

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

end else if (state_q == Write) begin
if (ecc_err[0] == 1'b0) begin // No correctable Error
if (ecc_err[assoc_c][0] !== 1'b1) begin // No correctable Error
// Return to idle state
state_d = Idle;
working_add_d = (working_add_q + 1) % BankSize; // increment address
uncorrectable_o = ecc_err[1];
uncorrectable_o = ecc_err[assoc_c][1];

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

// INTC interference - retry read and write
if (intc_req_i == 1'b1) begin
if (|intc_req_i === 1'b1) begin
state_d = Read;
end else begin // Error corrected
state_d = Idle;
Expand Down
Loading