From 88b5e1d9ab384778c9e29319f146de220b73f3cc Mon Sep 17 00:00:00 2001 From: Florian Zaruba Date: Sat, 15 Apr 2017 13:26:33 +0200 Subject: [PATCH] Added initial decoder implementation --- Makefile | 2 +- decoder.sv | 168 ++++++++++++++++++++++++++++++++++++++ include/ariane_pkg.svh | 179 ++++++++++++++++++++++++++++------------- issue_read_operands.sv | 61 ++++++++------ regfile_ff.sv | 100 +++++++++++++++++++++++ scoreboard.sv | 65 +++++---------- 6 files changed, 448 insertions(+), 127 deletions(-) create mode 100644 decoder.sv create mode 100755 regfile_ff.sv diff --git a/Makefile b/Makefile index b82207fd0..cd0b3e5e3 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ agents = tb/agents/fu_if/fu_if.sv tb/agents/fu_if/fu_if_agent_pkg.sv \ # this list contains the standalone components src = alu.sv tb/sequences/alu_sequence_pkg.sv tb/env/alu_env_pkg.sv tb/test/alu_lib_pkg.sv tb/alu_tb.sv \ - issue_read_operands.sv + issue_read_operands.sv decoder.sv # Search here for include files (e.g.: non-standalone components) incdir = ./includes diff --git a/decoder.sv b/decoder.sv new file mode 100644 index 000000000..735a0d06a --- /dev/null +++ b/decoder.sv @@ -0,0 +1,168 @@ +import ariane_pkg::*; + +module decoder ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic [63:0] pc_i, // PC from IF + input logic [31:0] instruction_i, // instruction from IF + input exception ex_i, // if an exception occured in if + output scoreboard_entry instruction_o, // scoreboard entry to scoreboard + output logic illegal_instr_o +); + instruction instr; + assign instr = instruction'(instruction_i); + imm_sel_t imm_select; + + logic [63:0] imm_i_type; + logic [63:0] imm_iz_type; + logic [63:0] imm_s_type; + logic [63:0] imm_sb_type; + logic [63:0] imm_u_type; + logic [63:0] imm_uj_type; + logic [63:0] imm_z_type; + logic [63:0] imm_s2_type; + logic [63:0] imm_bi_type; + logic [63:0] imm_s3_type; + logic [63:0] imm_vs_type; + logic [63:0] imm_vu_type; + + always_comb begin : decoder + + imm_select = NOIMM; + illegal_instr_o = 1'b0; + instruction_o.valid = 1'b0; + instruction_o.ex = ex_i; + instruction_o.fu = NONE; + instruction_o.op = ADD; + instruction_o.rs1 = 5'b0; + instruction_o.rs2 = 5'b0; + instruction_o.rd = 5'b0; + instruction_o.pc = pc_i; + + if (~ex_i.valid) begin + case (instr.rtype.opcode) + OPCODE_SYSTEM: begin + // TODO: Implement + end + + OPCODE_FENCE: begin + // TODO: Implement + end + + OPCODE_OP: begin + instruction_o.fu = ALU; + instruction_o.rs1 = instr.rtype.rs1; + instruction_o.rs2 = instr.rtype.rs2; + instruction_o.rd = instr.rtype.rd; + + unique case ({instr.rtype.funct7, instr.rtype.funct3}) + {6'b00_0000, 3'b000}: instruction_o.op = ADD; // Add + {6'b10_0000, 3'b000}: instruction_o.op = SUB; // Sub + {6'b00_0000, 3'b010}: instruction_o.op = SLTS; // Set Lower Than + {6'b00_0000, 3'b011}: instruction_o.op = SLTU; // Set Lower Than Unsigned + {6'b00_0000, 3'b100}: instruction_o.op = XORL; // Xor + {6'b00_0000, 3'b110}: instruction_o.op = ORL; // Or + {6'b00_0000, 3'b111}: instruction_o.op = ANDL; // And + {6'b00_0000, 3'b001}: instruction_o.op = SLL; // Shift Left Logical + {6'b00_0000, 3'b101}: instruction_o.op = SRL; // Shift Right Logical + {6'b10_0000, 3'b101}: instruction_o.op = SRA; // Shift Right Arithmetic + default: begin + illegal_instr_o = 1'b1; + end + endcase + end + + OPCODE_OP32: begin + + end + + OPCODE_OPIMM: begin + imm_select = IIMM; + end + + OPCODE_OPIMM32: begin + imm_select = IIMM; + end + + OPCODE_STORE: begin + imm_select = SIMM; + end + + OPCODE_LOAD: begin + imm_select = IIMM; + end + + OPCODE_BRANCH: begin + imm_select = BIMM; + end + + OPCODE_JALR: begin + imm_select = UIMM; + end + + OPCODE_JAL: begin + imm_select = JIMM; + end + + OPCODE_AUIPC: begin + imm_select = UIMM; + end + + OPCODE_LUI: begin + imm_select = UIMM; + end + + default: illegal_instr_o = 1'b1; + endcase + end + end + + always_comb begin : sign_extend + imm_i_type = { {52 {instruction_i[31]}}, instruction_i[31:20] }; + imm_iz_type = { 52'b0, instruction_i[31:20] }; + imm_s_type = { {52 {instruction_i[31]}}, instruction_i[31:25], instruction_i[11:7] }; + imm_sb_type = { {51 {instruction_i[31]}}, instruction_i[31], instruction_i[7], instruction_i[30:25], instruction_i[11:8], 1'b0 }; + imm_u_type = { {32 {instruction_i[31]}}, instruction_i[31:12], 12'b0 }; // JAL, AUIPC, sign extended to 64 bit + imm_uj_type = { {44 {instruction_i[31]}}, instruction_i[19:12], instruction_i[20], instruction_i[30:21], 1'b0 }; + // imm_z_type = { 59'b0, instruction_i[`REG_S1] }; + imm_s2_type = { 59'b0, instruction_i[24:20] }; + imm_bi_type = { {59{instruction_i[24]}}, instruction_i[24:20] }; + imm_s3_type = { 59'b0, instruction_i[29:25] }; + imm_vs_type = { {58 {instruction_i[24]}}, instruction_i[24:20], instruction_i[25] }; + imm_vu_type = { 58'b0, instruction_i[24:20], instruction_i[25] }; + + // NOIMM, PCIMM, IIMM, SIMM, BIMM, BIMM, UIMM, JIMM + // select immediate + case (imm_select) + PCIMM: begin + instruction_o.imm = pc_i; + instruction_o.use_imm = 1'b1; + end + IIMM: begin + instruction_o.imm = imm_i_type; + instruction_o.use_imm = 1'b1; + end + SIMM: begin + instruction_o.imm = imm_s_type; + instruction_o.use_imm = 1'b1; + end + BIMM: begin + instruction_o.imm = imm_bi_type; + instruction_o.use_imm = 1'b1; + end + UIMM: begin + instruction_o.imm = imm_u_type; + instruction_o.use_imm = 1'b1; + end + JIMM: begin + instruction_o.imm = imm_uj_type; + instruction_o.use_imm = 1'b1; + end + default: begin + instruction_o.imm = 64'b0; + instruction_o.use_imm = 1'b0; + end + endcase + end + +endmodule \ No newline at end of file diff --git a/include/ariane_pkg.svh b/include/ariane_pkg.svh index a64a8c5e6..a94bf2d3e 100644 --- a/include/ariane_pkg.svh +++ b/include/ariane_pkg.svh @@ -10,70 +10,137 @@ */ package ariane_pkg; -// --------------- -// Fetch Stage -// --------------- + // --------------- + // Fetch Stage + // --------------- -// Only use struct when signals have same direction -typedef struct packed { - logic [63:0] pc; - logic [63:0] branch_target_address; - logic valid; -} btb; + // Only use struct when signals have same direction + typedef struct packed { + logic [63:0] pc; + logic [63:0] branch_target_address; + logic valid; + } btb; -// input to the fetch stage -typedef struct packed { - logic [63:0] ra; // return address - logic is_call; // is call - pop from stack - logic is_return; // is return - push on stack -} ras; + // input to the fetch stage + typedef struct packed { + logic [63:0] ra; // return address + logic is_call; // is call - pop from stack + logic is_return; // is return - push on stack + } ras; -// exception -typedef struct packed { - logic [63:0] epc; - logic [63:0] cause; - logic valid; -} exception; + // exception + typedef struct packed { + logic [63:0] epc; + logic [63:0] cause; + logic valid; + } exception; -// miss-predict -typedef struct packed { - logic [63:0] pc; - logic valid; // is miss-predict -} misspredict; + // miss-predict + typedef struct packed { + logic [63:0] pc; + logic valid; // is miss-predict + } misspredict; -typedef enum logic[3:0] { - NONE, ALU, MULT, LSU, CSR -} fu_t; + typedef enum logic[3:0] { + NONE, ALU, MULT, LSU, CSR + } fu_t; -// --------------- -// EX Stage -// --------------- + // --------------- + // EX Stage + // --------------- -typedef enum logic [7:0] { ADD, SUB, ADDW, SUBW, // basic ALU op - XORL, ORL, ANDL, // logic operations - SRA, SRL, SLL, SRLW, SLLW, SRAW, // shifts - LTS, LTU, LES, LEU, GTS, GTU, GES, GEU, EQ, NE, // comparisons - SLTS, SLTU, SLETS, SLETU, // set lower than operations - MRET, SRET, URET, ECALL, WRITE, READ, SET, CLEAR, // CSR functions - LD, SD, LW, SW, LH, SH, LB, SB, LBU, SBU // LSU functions - } alu_op; + typedef enum logic [7:0] { ADD, SUB, ADDW, SUBW, // basic ALU op + XORL, ORL, ANDL, // logic operations + SRA, SRL, SLL, SRLW, SLLW, SRAW, // shifts + LTS, LTU, LES, LEU, GTS, GTU, GES, GEU, EQ, NE, // comparisons + SLTS, SLTU, SLETS, SLETU, // set lower than operations + MRET, SRET, URET, ECALL, WRITE, READ, SET, CLEAR, // CSR functions + LD, SD, LW, SW, LH, SH, LB, SB, LBU, SBU // LSU functions + } alu_op; + // --------------- + // ID/EX/WB Stage + // --------------- + typedef struct packed { + logic [63:0] pc; + fu_t fu; + alu_op op; + logic [4:0] rs1; + logic [4:0] rs2; + logic [4:0] rd; + logic [63:0] result; + logic valid; + logic use_imm; + logic [63:0] imm; // maybe we can get this into the results field + exception ex; // the PC is redundant here + } scoreboard_entry; + + // -------------------- + // Instruction Types + // -------------------- + typedef struct packed { + logic [6:0] opcode; + logic [11:7] rd; + logic [14:12] funct3; + logic [19:15] rs1; + logic [24:20] rs2; + logic [31:25] funct7; + } rtype; + + typedef struct packed { + logic [6:0] opcode; + logic [11:7] rd; + logic [14:12] funct3; + logic [19:15] rs1; + logic [31:20] imm; + } itype; + + typedef struct packed { + logic [6:0] opcode; + logic [11:7] imm0; + logic [14:12] funct3; + logic [19:15] rs1; + logic [24:20] rs2; + logic [31:25] imm1; + } stype; + + typedef struct packed { + logic [6:0] opcode; + logic [11:7] rd; + logic [31:12] funct3; + } utype; + + typedef union packed { + logic [31:0] instr; + rtype rtype; + itype itype; + stype stype; + utype utype; + } instruction; + + // -------------------- + // Opcodes + // -------------------- + localparam OPCODE_SYSTEM = 7'h73; + localparam OPCODE_FENCE = 7'h0f; + localparam OPCODE_OP = 7'h33; + localparam OPCODE_OP32 = 7'h3B; + localparam OPCODE_OPIMM = 7'h13; + localparam OPCODE_OPIMM32 = 7'h1B; + localparam OPCODE_STORE = 7'h23; + localparam OPCODE_LOAD = 7'h03; + localparam OPCODE_BRANCH = 7'h63; + localparam OPCODE_JALR = 7'h67; + localparam OPCODE_JAL = 7'h6f; + localparam OPCODE_AUIPC = 7'h17; + localparam OPCODE_LUI = 7'h37; + + // -------------------- + // Immediate select + // -------------------- + typedef enum logic[3:0] { + NOIMM, PCIMM, IIMM, SIMM, BIMM, UIMM, JIMM + } imm_sel_t; -// --------------- -// ID/EX/WB Stage -// --------------- -typedef struct packed { - logic [63:0] pc; - fu_t fu; - alu_op op; - logic [4:0] rs1; - logic [4:0] rs2; - logic [4:0] rd; - logic [63:0] result; - logic valid; - logic use_imm; - logic [63:0] imm; // maybe we can get this into the results field - exception ex; // the PC is redundant here -} scoreboard_entry; endpackage diff --git a/issue_read_operands.sv b/issue_read_operands.sv index 87655b9d7..803989d0c 100755 --- a/issue_read_operands.sv +++ b/issue_read_operands.sv @@ -51,10 +51,20 @@ module issue_read_operands ( ); logic stall; // stall signal, we do not want to fetch any more entries logic fu_busy; // functional unit is busy - scoreboard_entry sbe_n, sbe_q; // instruction register (ID <-> EX) - logic [63:0] operand_a_regfile_n, operand_a_regfile_q, operand_b_regfile_n, operand_b_regfile_q; // operands coming from regfile + logic [63:0] operand_a_regfile, operand_b_regfile; // operands coming from regfile + + // output flipflop (ID <-> EX) + logic [63:0] operand_a_n, operand_a_q, operand_b_n, operand_b_q; + logic alu_valid_n, alu_valid_q; + alu_op operator_n, operator_q; + + // forwarding signals logic forward_rs1, forward_rs2; + assign operand_a_o = operand_a_q; + assign operand_b_o = operand_b_q; + assign operator_o = operator_q; + assign alu_valid_o = alu_valid_q; // --------------- // Issue Stage // --------------- @@ -63,7 +73,6 @@ module issue_read_operands ( // We also need to check if there is an unresolved branch in the scoreboard. always_comb begin : issue // default assignment - sbe_n = sbe_q; issue_ack_o = 1'b0; // check that we didn't stall, that the instruction we got is valid // and that the functional unit we need is not busy @@ -71,7 +80,6 @@ module issue_read_operands ( // check that the corresponding functional unit is not busy // no other instruction has the same destination register -> fetch the instruction if (rd_clobber_i[issue_instr_i.rd] == NONE) begin - sbe_n = issue_instr_i; issue_ack_o = 1'b1; end end @@ -98,7 +106,6 @@ module issue_read_operands ( // --------------- // Register stage // --------------- - assign operator_o = sbe_q.op; // check that all operands are available, otherwise stall // forward corresponding register always_comb begin : operands_available @@ -106,12 +113,12 @@ module issue_read_operands ( // operand forwarding signals forward_rs1 = 1'b0; forward_rs2 = 1'b0; - // address needs to be applied one cycle earlier + // poll the scoreboard for those values rs1_o = issue_instr_i.rs1; rs2_o = issue_instr_i.rs2; // 1. check if the source registers are clobberd // 2. poll the scoreboard - if (rd_clobber_i[sbe_q.rs1] != NONE) begin + if (rd_clobber_i[issue_instr_i.rs1] != NONE) begin // the operand is available, forward it if (rs1_valid_i) forward_rs1 = 1'b1; @@ -120,7 +127,7 @@ module issue_read_operands ( end - if (rd_clobber_i[sbe_q.rs2] != NONE) begin + if (rd_clobber_i[issue_instr_i.rs2] != NONE) begin // the operand is available, forward it if (rs2_valid_i) forward_rs2 = 1'b1; @@ -133,35 +140,35 @@ module issue_read_operands ( // Forwarding/Output MUX always_comb begin : forwarding // default is regfile - operand_a_o = operand_a_regfile_q; - operand_b_o = operand_b_regfile_q; + operand_a_n = operand_a_regfile; + operand_b_n = operand_b_regfile; // or should we forward if (forward_rs1) begin - operand_a_o = rs1_i; + operand_a_n = rs1_i; end if (forward_rs2) begin - operand_b_o = rs2_i; + operand_b_n = rs2_i; end // or is it an immediate (including PC) - if (sbe_q.use_imm) begin - operand_b_o = sbe_q.imm; + if (issue_instr_i.use_imm) begin + operand_b_n = issue_instr_i.imm; end end // FU select always_comb begin : unit_valid - alu_valid_o = 1'b0; + alu_valid_n = alu_valid_q; lsu_valid_o = 1'b0; mult_valid_o = 1'b0; // Exception pass through // if an exception has occurred simply pass it through - if (~sbe_q.ex.valid) begin - case (sbe_q.fu) + if (~issue_instr_i.ex.valid) begin + case (issue_instr_i.fu) ALU: - alu_valid_o = 1'b1; + alu_valid_n = 1'b1; MULT: mult_valid_o = 1'b1; LSU: @@ -183,10 +190,10 @@ module issue_read_operands ( .test_en_i ( test_en_i ), .raddr_a_i ( issue_instr_i.rs1 ), - .rdata_a_o ( operand_a_regfile_n ), + .rdata_a_o ( operand_a_regfile ), .raddr_b_i ( issue_instr_i.rs2 ), - .rdata_b_o ( operand_b_regfile_n ), + .rdata_b_o ( operand_b_regfile ), .waddr_a_i ( waddr_a_i ), .wdata_a_i ( wdata_a_i ), @@ -196,13 +203,15 @@ module issue_read_operands ( // Registers always_ff @(posedge clk_i or negedge rst_ni) begin if(~rst_ni) begin - sbe_q <= '{default: 0}; - operand_a_regfile_q <= '{default: 0}; - operand_b_regfile_q <= '{default: 0}; + operand_a_q <= '{default: 0}; + operand_b_q <= '{default: 0}; + alu_valid_q <= 1'b0; + operator_q <= ADD; end else begin - sbe_q <= sbe_n; - operand_a_regfile_q <= operand_a_regfile_n; - operand_b_regfile_q <= operand_b_regfile_n; + operand_a_q <= operand_a_n; + operand_b_q <= operand_b_n; + alu_valid_q <= alu_valid_n; + operator_q <= operator_n; end end endmodule diff --git a/regfile_ff.sv b/regfile_ff.sv new file mode 100755 index 000000000..fb8e44418 --- /dev/null +++ b/regfile_ff.sv @@ -0,0 +1,100 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 ETH Zurich, University of Bologna // +// All rights reserved. // +// // +// This code is under development and not yet released to the public. // +// Until it is released, the code is under the copyright of ETH Zurich // +// and the University of Bologna, and may contain unpublished work. // +// Any reuse/redistribution should only be under explicit permission. // +// // +// Bug fixes and contributions will eventually be released under the // +// SolderPad open hardware license and under the copyright of ETH Zurich // +// and the University of Bologna. // +// // +// Engineer: Francesco Conti - f.conti@unibo.it // +// // +// Additional contributions by: // +// Markus Wegmann - markus.wegmann@technokrat.ch // +// // +// Design Name: RISC-V register file // +// Project Name: zero-riscy // +// Language: SystemVerilog // +// // +// Description: Register file with 31 or 15x 32 bit wide registers. // +// Register 0 is fixed to 0. This register file is based on // +// flip flops. // +// // +//////////////////////////////////////////////////////////////////////////////// + +module regfile +#( + parameter DATA_WIDTH = 32 +) +( + // Clock and Reset + input logic clk, + input logic rst_n, + + input logic test_en_i, + + //Read port R1 + input logic [4:0] raddr_a_i, + output logic [DATA_WIDTH-1:0] rdata_a_o, + + //Read port R2 + input logic [4:0] raddr_b_i, + output logic [DATA_WIDTH-1:0] rdata_b_o, + + + // Write port W1 + input logic [4:0] waddr_a_i, + input logic [DATA_WIDTH-1:0] wdata_a_i, + input logic we_a_i + +); + + localparam ADDR_WIDTH = 5; + localparam NUM_WORDS = 2**ADDR_WIDTH; + + logic [NUM_WORDS-1:0][DATA_WIDTH-1:0] rf_reg; + logic [NUM_WORDS-1:0] we_a_dec; + + always_comb + begin : we_a_decoder + for (int i = 0; i < NUM_WORDS; i++) begin + if (waddr_a_i == i) + we_a_dec[i] = we_a_i; + else + we_a_dec[i] = 1'b0; + end + end + + + genvar i; + generate + + // loop from 1 to NUM_WORDS-1 as R0 is nil + for (i = 1; i < NUM_WORDS; i++) + begin : rf_gen + + always_ff @(posedge clk, negedge rst_n) + begin : register_write_behavioral + if (rst_n==1'b0) begin + rf_reg[i] <= 'b0; + end else begin + if (we_a_dec[i]) + rf_reg[i] <= wdata_a_i; + end + end + + end + + // R0 is nil + assign rf_reg[0] = '0; + + endgenerate + + assign rdata_a_o = rf_reg[raddr_a_i]; + assign rdata_b_o = rf_reg[raddr_b_i]; + +endmodule \ No newline at end of file diff --git a/scoreboard.sv b/scoreboard.sv index 17c60934d..1cb18a819 100644 --- a/scoreboard.sv +++ b/scoreboard.sv @@ -54,11 +54,7 @@ dtype [NR_ENTRIES-1:0] mem_q, mem_n; logic [BITS_ENTRIES-1:0] issue_pointer_n, issue_pointer_q, // points to the instruction currently in issue commit_pointer_n, commit_pointer_q, // points to the instruction currently in commit top_pointer_n, top_pointer_q, top_pointer_qq; // points to the top of the scoreboard, an empty slot, top pointer two cycles ago -// rd clobber register -logic [31:0][$bits(fu_t)-1:0] rd_clobber_n, rd_clobber_q; -// register read stage -logic [63:0] rs1_n, rs1_q, rs2_n, rs2_q; -logic rs1_valid_n, rs1_valid_q, rs2_valid_n, rs2_valid_q; + logic pointer_overflow; logic empty; logic reset_condition; @@ -69,11 +65,7 @@ assign reset_condition = top_pointer_q == top_pointer_qq; assign pointer_overflow = (top_pointer_q <= commit_pointer_q && ~reset_condition) ? 1'b1 : 1'b0; assign full_o = (reset_condition) ? 1'b0 : (commit_pointer_q == top_pointer_q); assign empty = (pointer_overflow) ? 1'b0 : (commit_pointer_q == top_pointer_q); -assign rd_clobber_o = rd_clobber_q; -assign rs1_o = rs1_q; -assign rs2_o = rs2_q; -assign rs1_valid_o = rs1_valid_q; -assign rs2_valid_o = rs2_valid_q; + // rd_clobber output: output currently clobbered destination registers // but only between commit and issue pointer // normal case: overflow case: @@ -85,31 +77,31 @@ assign rs2_valid_o = rs2_valid_q; // |_________________________|<- top pointer |_________________________| // always_comb begin : clobber_output - rd_clobber_n = rd_clobber_q; + rd_clobber_o = '{default: 0}; // excluding issue, the issue pointer points to the instruction which is currently not issued // but might be issued as soon as the issue unit acknowledges if (commit_pointer_q < issue_pointer_q) begin for (int unsigned i = 0; i < NR_ENTRIES; i++) begin // non overflowed case, depicted on the left if (i[BITS_ENTRIES-1:0] >= commit_pointer_q && i[BITS_ENTRIES-1:0] < issue_pointer_q) - rd_clobber_n[mem_q[i].rd] = mem_q[i].fu; + rd_clobber_o[mem_q[i].rd] = mem_q[i].fu; end end else begin // the issue pointer has overflowed, invert logic, depicted on the right for (int unsigned i = 0; i < NR_ENTRIES; i++) begin if (i[BITS_ENTRIES-1:0] >= commit_pointer_q || i[BITS_ENTRIES-1:0] < issue_pointer_q) - rd_clobber_n[mem_q[i].rd] = mem_q[i].fu; + rd_clobber_o[mem_q[i].rd] = mem_q[i].fu; end end - // // the zero register is always free - rd_clobber_n[0] = NONE; + // the zero register is always free + rd_clobber_o[0] = NONE; end // read operand interface: same logic as register file, including a valid file always_comb begin : read_operands - rs1_n = rs1_q; - rs2_n = rs2_q; - rs1_valid_n = rs1_valid_q; - rs2_valid_n = rs2_valid_q; + rs1_o = 64'b0; + rs2_o = 64'b0; + rs1_valid_o = 1'b0; + rs2_valid_o = 1'b0; if (commit_pointer_q < issue_pointer_q) begin for (int unsigned i = 0; i < NR_ENTRIES; i++) begin @@ -117,12 +109,12 @@ always_comb begin : read_operands // look at the appropriate fields and look whether there was an // instruction that wrote the rd field before, first for RS1 and then for RS2 if (mem_q[i[BITS_ENTRIES-1:0]].rd == rs1_i) begin - rs1_n = mem_q[i].result; - rs1_valid_n = mem_q[i].valid; + rs1_o = mem_q[i].result; + rs1_valid_o = mem_q[i].valid; // do the same for rs2 end else if (mem_q[i].rd == rs2_i) begin - rs2_n = mem_q[i].result; - rs2_valid_n = mem_q[i].valid; + rs2_o = mem_q[i].result; + rs2_valid_o = mem_q[i].valid; end end end @@ -131,21 +123,21 @@ always_comb begin : read_operands if (i[BITS_ENTRIES-1:0] >= commit_pointer_q || i[BITS_ENTRIES-1:0] < issue_pointer_q) begin // same as above but for the overflowed pointer case if (mem_q[i[BITS_ENTRIES-1:0]].rd == rs1_i) begin - rs1_n = mem_q[i].result; - rs1_valid_n = mem_q[i].valid; + rs1_o = mem_q[i].result; + rs1_valid_o = mem_q[i].valid; // do the same for rs2 end else if (mem_q[i[BITS_ENTRIES-1:0]].rd == rs2_i) begin - rs2_n = mem_q[i].result; - rs2_valid_n = mem_q[i].valid; + rs2_o = mem_q[i].result; + rs2_valid_o = mem_q[i].valid; end end end end // make sure we didn't read the zero register if (rs1_i == '0) - rs1_valid_n = 1'b0; + rs1_valid_o = 1'b0; if (rs2_i == '0) - rs2_valid_n = 1'b0; + rs2_valid_o = 1'b0; end // push new decoded instruction: if still empty space push the instruction to the scoreboard // write-back instruction: update value of RD register in scoreboard @@ -230,33 +222,18 @@ end // sequential process always_ff @(posedge clk_i or negedge rst_ni) begin : sequential if(~rst_ni) begin - rd_clobber_q <= '{default: 0}; - rs1_q <= 64'b0; - rs2_q <= 64'b0; - rs1_valid_q <= 1'b0; - rs2_valid_q <= 1'b0; issue_pointer_q <= '{default: 0}; commit_pointer_q <= '{default: 0}; top_pointer_q <= '{default: 0}; top_pointer_qq <= '{default: 0}; mem_q <= '{default: 0}; end else if (flush_i) begin // reset pointers on flush - rd_clobber_q <= '{default: 0}; - rs1_q <= 64'b0; - rs2_q <= 64'b0; - rs1_valid_q <= 1'b0; - rs2_valid_q <= 1'b0; issue_pointer_q <= '{default: 0}; commit_pointer_q <= '{default: 0}; top_pointer_q <= '{default: 0}; top_pointer_qq <= '{default: 0}; mem_q <= '{default: 0}; end else begin - rs1_q <= rs1_n; - rs2_q <= rs2_n; - rs1_valid_q <= rs1_valid_n; - rs2_valid_q <= rs2_valid_n; - rd_clobber_q <= rd_clobber_n; issue_pointer_q <= issue_pointer_n; commit_pointer_q <= commit_pointer_n; top_pointer_q <= top_pointer_n;