| `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 vdda1, // User area 1 3.3V supply |
| inout vdda2, // User area 2 3.3V supply |
| inout vssa1, // User area 1 analog ground |
| inout vssa2, // User area 2 analog ground |
| inout vccd1, // User area 1 1.8V supply |
| inout vccd2, // User area 2 1.8v supply |
| inout vssd1, // User area 1 digital ground |
| inout vssd2, // User area 2 digital ground |
| `endif |
| input clk_i, |
| input rst_i , |
| input [WORD_SIZE + ECCBITS - 1 : 0] data_to_register_i, |
| //input [((REGISTERS/ SEGMENTS) * (WORD_SIZE + ECCBITS)) - 1 : 0] data_to_register_i, // 156 interface |
| input [REGDIRSIZE - 1 : 0] register_i , |
| input [WHISBONE_ADR - 1 : 0] wbs_adr_i, |
| input [2 : 0] operation_type_i, |
| input wregister_i , |
| input rregister_i , |
| input valid_i, |
| input [3 : 0] wstrb_i, |
| input [WORD_SIZE -1 : 0] wdata_i, |
| input 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] 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 |
| assign nand_1 = rregister_i & operation_type_i == 2'b01 ? 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 == 2'b01 ? 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 == 2'b01 ? 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 == 2'b01 ? r[register_i[REGDIRSIZE - 1: 2]][31:0] ^ r[register_i[REGDIRSIZE - 1: 2]][70:39] : {WORD_SIZE + ECCBITS{1'b0}}; |
| assign xor_2 = rregister_i & operation_type_i == 2'b01 ? r[register_i[REGDIRSIZE - 1: 2]][70:39] ^ r[register_i[REGDIRSIZE - 1: 2]][109:78]: {WORD_SIZE + ECCBITS{1'b0}}; |
| assign xor_3 = rregister_i & operation_type_i == 2'b01 ? r[register_i[REGDIRSIZE - 1: 2]][31:0] ^ r[register_i[REGDIRSIZE - 1: 2]][109:78]: {WORD_SIZE + ECCBITS{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 |