blob: 61f7d8a1bba2904f954ca17e83aa401499731354 [file] [log] [blame]
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
`default_nettype none
//-----------------------------------------------------
// Project Name : Register File
// Function : Rergiter bank data
// Description : This is the main processor
// Coder : Ivan Rodriguez Ferrandez AND Alvaro Jover-Alvarez
//***Headers***
//***Module***
module register_data #(
parameter integer WORD_SIZE = 32,
parameter integer REGISTERS = 32,
parameter integer SEGMENTS = 8 ,
parameter integer REGDIRSIZE = 5,
parameter integer ECCBITS = 7,
parameter integer WHISBONE_ADR = 32,
parameter [19:0] ADDRBASE = 20'h3010_0
)
(
`ifdef USE_POWER_PINS
inout wire vdda1, // User area 1 3.3V supply
inout wire vdda2, // User area 2 3.3V supply
inout wire vssa1, // User area 1 analog ground
inout wire vssa2, // User area 2 analog ground
inout wire vccd1, // User area 1 1.8V supply
inout wire vccd2, // User area 2 1.8v supply
inout wire vssd1, // User area 1 digital ground
inout wire vssd2, // User area 2 digital ground
`endif
input wire clk_i,
input wire rst_i ,
input wire [WORD_SIZE + ECCBITS - 1 : 0] data_to_register_i,
//input [((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)) - 1 : 0] data_to_register_i, // 156 interface
input wire [REGDIRSIZE - 1 : 0] register_i ,
input wire [WHISBONE_ADR - 1 : 0] wbs_adr_i,
input wire [2 : 0] operation_type_i,
input wire wregister_i ,
input wire rregister_i ,
input wire valid_i,
input wire [3 : 0] wstrb_i,
input wire [WORD_SIZE -1 : 0] wdata_i,
input wire wbs_we_i,
output reg [WORD_SIZE + ECCBITS -1: 0] store_data_o ,
output reg operational_o ,
output reg ready_o,
output reg [WORD_SIZE - 1 : 0] rdata_o,
output reg [1:0] redundat_validation_o
);
//***Internal logic generated by compiler***
//***Dumped Internal logic***
// wires
//wire [WORD_SIZE - 1 : 0] majority_output;
//wire [WORD_SIZE - 1 : 0] majority_output_filter;
wire [WORD_SIZE - 1 : 0] nand_1;
wire [WORD_SIZE - 1 : 0] nand_2;
wire [WORD_SIZE - 1 : 0] nand_3;
wire [WORD_SIZE - 1 : 0] xor_1;
wire [WORD_SIZE - 1 : 0] xor_2;
wire [WORD_SIZE - 1 : 0] xor_3;
wire xor_reduce_1;
wire xor_reduce_2;
wire xor_reduce_3;
wire correted_triple;
wire uncorreted_triple;
// register bank
reg [((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)) - 1 : 0 ] r[0:SEGMENTS-1];
//triple_redunancy calculation
/*majority_gate_32 #(
.WORD_SIZE (WORD_SIZE)
)
inst_majority(
`ifdef USE_POWER_PINS
.vdda1(vdda1), // User area 1 3.3V power
.vdda2(vdda2), // User area 2 3.3V power
.vssa1(vssa1), // User area 1 analog ground
.vssa2(vssa2), // User area 2 analog ground
.vccd1(vccd1), // User area 1 1.8V power
.vccd2(vccd2), // User area 2 1.8V power
.vssd1(vssd1), // User area 1 digital ground
.vssd2(vssd2), // User area 2 digital ground
`endif
.value_1_i (r[register_i[REGDIRSIZE - 1: 2]][31:0] ),
.value_2_i (r[register_i[REGDIRSIZE - 1: 2]][70:39] ),
.value_3_i (r[register_i[REGDIRSIZE - 1: 2]][109:78]),
.result_o (majority_output)
);
assign majority_output_filter = rregister_i & operation_type_i == 3'b001 ? majority_output : {WORD_SIZE{1'b0}};*/
assign nand_1 = rregister_i & operation_type_i == 3'b001 ? r[register_i[REGDIRSIZE - 1: 2]][31:0] ~& r[register_i[REGDIRSIZE - 1: 2]][70:39]: {WORD_SIZE + ECCBITS{1'b0}};
assign nand_2 = rregister_i & operation_type_i == 3'b001 ? r[register_i[REGDIRSIZE - 1: 2]][70:39] ~& r[register_i[REGDIRSIZE - 1: 2]][109:78]: {WORD_SIZE + ECCBITS{1'b0}};
assign nand_3 = rregister_i & operation_type_i == 3'b001 ? r[register_i[REGDIRSIZE - 1: 2]][31:0] ~& r[register_i[REGDIRSIZE - 1: 2]][109:78]: {WORD_SIZE + ECCBITS{1'b0}};
//triple_redunancy status
assign xor_1 = rregister_i & operation_type_i == 3'b001 ? r[register_i[REGDIRSIZE - 1: 2]][31:0] ^ r[register_i[REGDIRSIZE - 1: 2]][70:39] : {WORD_SIZE{1'b0}};
assign xor_2 = rregister_i & operation_type_i == 3'b001 ? r[register_i[REGDIRSIZE - 1: 2]][70:39] ^ r[register_i[REGDIRSIZE - 1: 2]][109:78]: {WORD_SIZE{1'b0}};
assign xor_3 = rregister_i & operation_type_i == 3'b001 ? r[register_i[REGDIRSIZE - 1: 2]][31:0] ^ r[register_i[REGDIRSIZE - 1: 2]][109:78]: {WORD_SIZE{1'b0}};
assign xor_reduce_1 = |xor_1;
assign xor_reduce_2 = |xor_2;
assign xor_reduce_3 = |xor_3;
always @(posedge clk_i) begin
// calculate last parity bit
if (rst_i) begin
r[0] = {((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)){1'b0}};
r[1] = {((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)){1'b0}};
r[2] = {((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)){1'b0}};
r[3] = {((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)){1'b0}};
r[4] = {((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)){1'b0}};
r[5] = {((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)){1'b0}};
r[6] = {((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)){1'b0}};
r[7] = {((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)){1'b0}};
ready_o <= 1'b0;
store_data_o <= {WORD_SIZE + ECCBITS{1'b0}};
redundat_validation_o <= 2'b00;
operational_o <= 1'b1;
end
// Read operation
else if (rregister_i) begin
// takes care of reading 000 ECC and 100 No proteccion
if (operation_type_i[1:0] == 2'b00) begin
case (register_i[1:0])
2'b00: begin
store_data_o <= r[register_i[REGDIRSIZE - 1: 2]][38:0];
end
2'b01: begin
store_data_o <= r[register_i[REGDIRSIZE - 1: 2]][77:39];
end
2'b10: begin
store_data_o <= r[register_i[REGDIRSIZE - 1: 2]][116:78];
end
2'b11: begin
store_data_o <= r[register_i[REGDIRSIZE - 1: 2]][155:117];
end
endcase
operational_o <= 1'b1;
redundat_validation_o <= 2'b00;
end
else if (operation_type_i == 3'b001) begin
redundat_validation_o[0] <= (xor_reduce_1 ^ xor_reduce_2) | (xor_reduce_2 ^ xor_reduce_3);
redundat_validation_o[1] <= xor_reduce_1 & xor_reduce_2 & xor_reduce_3 ;
store_data_o <= {7'b0000000,~(nand_1 & nand_2 & nand_3)};
operational_o <= 1'b1;
end
else if (operation_type_i[1] == 1'b1) begin
// use standart shadow_register
case (register_i[1:0])
2'b00: begin
if (operation_type_i[0] == 1'b1) begin
// use standart shadow_register
store_data_o <= {7'b0000000,r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][31:0]};
redundat_validation_o[0] <= 1'b0;
redundat_validation_o[1] <= |( r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][31:0] ^ r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][31:0] );
end
else begin
// use ECC shadow_register
store_data_o <= r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][38:0];
redundat_validation_o[0] <= 1'b0;
redundat_validation_o[1] <= |(r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][38:0] ^ r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][38:0]);
end
end
2'b01: begin
if (operation_type_i[0] == 1'b1) begin
// use standart shadow_register
store_data_o <= {7'b0000000,r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][70:39]};
redundat_validation_o[0] <= 1'b0;
redundat_validation_o[1] <= |(r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][70:39] ^ r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][70:39]);
end
else begin
// use ECC shadow_register
store_data_o <= r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][77:39];
redundat_validation_o[0] <= 1'b0;
redundat_validation_o[1] <= |(r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][77:39] ^ r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][77:39]);
end
end
2'b10: begin
if (operation_type_i[0] == 1'b1) begin
// use standart shadow_register
store_data_o <= {7'b0000000,r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][109:78]};
redundat_validation_o[0] <= 1'b0;
redundat_validation_o[1] <= |(r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][109:78] ^ r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][109:78]);
end
else begin
// use ECC shadow_register
store_data_o <= r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][116:78];
redundat_validation_o[0] <= 1'b0;
redundat_validation_o[1] <= |(r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][116:78] ^ r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][116:78]);
end
end
2'b11: begin
if (operation_type_i[0] == 1'b1) begin
// use standart shadow_register
store_data_o <= {7'b0000000,r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][148:117]};
redundat_validation_o[0] <= 1'b0;
redundat_validation_o[1] <= |(r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][148:117] ^ r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][148:117]);
end
else begin
// use ECC shadow_register
store_data_o <= r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][155:117];
redundat_validation_o[0] <= 1'b0;
redundat_validation_o[1] <= |(r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][155:117] ^ r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][155:117]);
end
end
endcase
operational_o <= 1'b1;
end
end
else if (wregister_i) begin
// ECC value and no proteccion
if (operation_type_i[1:0] == 2'b00) begin
case (register_i[1:0])
2'b00: begin
r[register_i[REGDIRSIZE - 1: 2]][38:0] <= data_to_register_i;
end
2'b01: begin
r[register_i[REGDIRSIZE - 1: 2]][77:39] <= data_to_register_i;
end
2'b10: begin
r[register_i[REGDIRSIZE - 1: 2]][116:78] <= data_to_register_i;
end
2'b11: begin
r[register_i[REGDIRSIZE - 1: 2]][155:117] <= data_to_register_i;
end
endcase
store_data_o <= {WORD_SIZE + ECCBITS{1'b0}};
redundat_validation_o <= 2'b00;
operational_o <= 1'b1;
end
// triple redundaccy value
else if (operation_type_i == 3'b001) begin
r[register_i[REGDIRSIZE - 1: 2]][116:0] <= {data_to_register_i,data_to_register_i,data_to_register_i};
store_data_o <= {WORD_SIZE + ECCBITS{1'b0}};
redundat_validation_o <= 2'b00;
operational_o <= 1'b1;
end
else if (operation_type_i[1] == 1'b1) begin
case (register_i[1:0])
2'b00: begin
if (operation_type_i[0] == 1'b1) begin
// use standart shadow_register
r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][31:0] <= data_to_register_i[31:0];
r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][31:0] <= data_to_register_i[31:0];
end
else begin
// use ECC shadow_register
r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][38:0] <= data_to_register_i;
r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][38:0] <= data_to_register_i;
end
end
2'b01: begin
if (operation_type_i[0] == 1'b1) begin
// use standart shadow_register
r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][70:39] <= data_to_register_i[31:0];
r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][70:39] <= data_to_register_i[31:0];
end
else begin
// use ECC shadow_register
r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][77:39] <= data_to_register_i;
r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][77:39] <= data_to_register_i;
end
end
2'b10: begin
if (operation_type_i[0] == 1'b1) begin
// use standart shadow_register
r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][109:78] <= data_to_register_i[31:0];
r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][109:78] <= data_to_register_i[31:0];
end
else begin
// use ECC shadow_register
r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][116:78] <= data_to_register_i;
r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][116:78] <= data_to_register_i;
end
end
2'b11: begin
if (operation_type_i[0] == 1'b1) begin
// use standart shadow_register
r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][148:117] <= data_to_register_i[31:0];
r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][148:117] <= data_to_register_i[31:0];
end
else begin
// use ECC shadow_register
r[{1'b0,register_i[REGDIRSIZE - 2: 2]}][155:117] <= data_to_register_i;
r[{1'b1,register_i[REGDIRSIZE - 2: 2]}][155:117] <= data_to_register_i;
end
end
endcase
store_data_o <= {WORD_SIZE + ECCBITS{1'b0}};
redundat_validation_o <= 2'b00;
operational_o <= 1'b1;
end
end
if (valid_i && wbs_adr_i[31:12] == ADDRBASE) begin
// big 32 register switch case for the whisbone acces to the registers
case (wbs_adr_i[3:0])
4'h0: begin
ready_o <= 1'b1;
if (wbs_we_i) begin
if (wstrb_i[0]) r[wbs_adr_i[8:4]][7:0] <= wdata_i[7:0];
if (wstrb_i[1]) r[wbs_adr_i[8:4]][15:8] <= wdata_i[15:8];
if (wstrb_i[2]) r[wbs_adr_i[8:4]][23:16] <= wdata_i[23:16];
if (wstrb_i[3]) r[wbs_adr_i[8:4]][31:24] <= wdata_i[31:24];
end
else begin
rdata_o <= {r[wbs_adr_i[8:4]][31:0]};
end
end
4'h4: begin
ready_o <= 1'b1;
if (wbs_we_i) begin
if (wstrb_i[0]) r[wbs_adr_i[8:4]][46:39] <= wdata_i[7:0];
if (wstrb_i[1]) r[wbs_adr_i[8:4]][54:47] <= wdata_i[15:8];
if (wstrb_i[2]) r[wbs_adr_i[8:4]][62:55] <= wdata_i[23:16];
if (wstrb_i[3]) r[wbs_adr_i[8:4]][70:63] <= wdata_i[31:24];
end
else begin
rdata_o <= {r[wbs_adr_i[8:4]][70:39]};
end
end
4'h8: begin
ready_o <= 1'b1;
if (wbs_we_i) begin
if (wstrb_i[0]) r[wbs_adr_i[8:4]][85:78] <= wdata_i[7:0];
if (wstrb_i[1]) r[wbs_adr_i[8:4]][93:86] <= wdata_i[15:8];
if (wstrb_i[2]) r[wbs_adr_i[8:4]][101:94] <= wdata_i[23:16];
if (wstrb_i[3]) r[wbs_adr_i[8:4]][109:102] <= wdata_i[31:24];
end
else begin
rdata_o <= {r[wbs_adr_i[8:4]][109:78]};
end
end
4'hC: begin
ready_o <= 1'b1;
if (wbs_we_i) begin
if (wstrb_i[0]) r[wbs_adr_i[8:4]][124:117] <= wdata_i[7:0];
if (wstrb_i[1]) r[wbs_adr_i[8:4]][135:125] <= wdata_i[15:8];
if (wstrb_i[2]) r[wbs_adr_i[8:4]][140:136] <= wdata_i[23:16];
if (wstrb_i[3]) r[wbs_adr_i[8:4]][148:141] <= wdata_i[31:24];
end
else begin
rdata_o <= {r[wbs_adr_i[8:4]][148:117]};
end
end
default: ready_o <= 1'b1; // if is not one put 1 to continue the wisbone execution
endcase
operational_o <= 1'b0;
end
else if (valid_i && wbs_adr_i[31:28] == ADDRBASE[19:16]) begin
// case for the error state that the address is not correct.
//Also if the adrres is valid for the PMU will create a on signal but will be filter out that with or gat in the top
ready_o <= 1'b1;
end
else begin
ready_o <= 1'b0;
end
end
endmodule