diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index f735b1a..271b601 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -1,138 +1,139 @@ `default_nettype none -module serv_decode - ( - input wire clk, +module serv_decode #( + parameter integer PRE_REGISTER = 1 +)( + input wire clk, //Input input wire [31:2] i_wb_rdt, - input wire i_wb_en, + input wire i_wb_en, //To state - output wire o_sh_right, - output wire o_bne_or_bge, - output wire o_cond_branch, - output wire o_e_op, - output wire o_ebreak, - output wire o_branch_op, - output wire o_mem_op, - output wire o_shift_op, - output wire o_slt_op, - output wire o_rd_op, + output reg o_sh_right, + output reg o_bne_or_bge, + output reg o_cond_branch, + output reg o_e_op, + output reg o_ebreak, + output reg o_branch_op, + output reg o_mem_op, + output reg o_shift_op, + output reg o_slt_op, + output reg o_rd_op, //To bufreg - output wire o_bufreg_rs1_en, - output wire o_bufreg_imm_en, - output wire o_bufreg_clr_lsb, - output wire o_bufreg_sh_signed, + output reg o_bufreg_rs1_en, + output reg o_bufreg_imm_en, + output reg o_bufreg_clr_lsb, + output reg o_bufreg_sh_signed, //To ctrl - output wire o_ctrl_jal_or_jalr, - output wire o_ctrl_utype, - output wire o_ctrl_pc_rel, - output wire o_ctrl_mret, + output reg o_ctrl_jal_or_jalr, + output reg o_ctrl_utype, + output reg o_ctrl_pc_rel, + output reg o_ctrl_mret, //To alu - output wire o_alu_sub, - output wire [1:0] o_alu_bool_op, - output wire o_alu_cmp_eq, - output wire o_alu_cmp_sig, - output wire [2:0] o_alu_rd_sel, + output reg o_alu_sub, + output reg [1:0] o_alu_bool_op, + output reg o_alu_cmp_eq, + output reg o_alu_cmp_sig, + output reg [2:0] o_alu_rd_sel, //To mem IF - output wire o_mem_signed, - output wire o_mem_word, - output wire o_mem_half, - output wire o_mem_cmd, + output reg o_mem_signed, + output reg o_mem_word, + output reg o_mem_half, + output reg o_mem_cmd, //To CSR - output wire o_csr_en, - output wire [1:0] o_csr_addr, - output wire o_csr_mstatus_en, - output wire o_csr_mie_en, - output wire o_csr_mcause_en, - output wire [1:0] o_csr_source, - output wire o_csr_d_sel, - output wire o_csr_imm_en, + output reg o_csr_en, + output reg [1:0] o_csr_addr, + output reg o_csr_mstatus_en, + output reg o_csr_mie_en, + output reg o_csr_mcause_en, + output reg [1:0] o_csr_source, + output reg o_csr_d_sel, + output reg o_csr_imm_en, //To top - output wire [3:0] o_immdec_ctrl, - output wire [3:0] o_immdec_en, - output wire o_op_b_source, - output wire o_rd_csr_en, - output wire o_rd_alu_en); + output reg [3:0] o_immdec_ctrl, + output reg [3:0] o_immdec_en, + output reg o_op_b_source, + output reg o_rd_csr_en, + output reg o_rd_alu_en); reg [4:0] opcode; reg [2:0] funct3; - reg op20; - reg op21; - reg op22; - reg op26; + reg op20; + reg op21; + reg op22; + reg op26; reg imm30; //opcode - wire op_or_opimm = (!opcode[4] & opcode[2] & !opcode[0]); + wire op_or_opimm = (!opcode[4] & opcode[2] & !opcode[0]); - assign o_mem_op = !opcode[4] & !opcode[2] & !opcode[0]; - assign o_branch_op = opcode[4] & !opcode[2]; + wire co_mem_op = !opcode[4] & !opcode[2] & !opcode[0]; + wire co_branch_op = opcode[4] & !opcode[2]; //jal,branch = imm //jalr = rs1+imm //mem = rs1+imm //shift = rs1 - assign o_bufreg_rs1_en = !opcode[4] | (!opcode[1] & opcode[0]); - assign o_bufreg_imm_en = !opcode[2]; + wire co_bufreg_rs1_en = !opcode[4] | (!opcode[1] & opcode[0]); + wire co_bufreg_imm_en = !opcode[2]; //Clear LSB of immediate for BRANCH and JAL ops //True for BRANCH and JAL //False for JALR/LOAD/STORE/OP/OPIMM? - assign o_bufreg_clr_lsb = opcode[4] & ((opcode[1:0] == 2'b00) | (opcode[1:0] == 2'b11)); + wire co_bufreg_clr_lsb = opcode[4] & ((opcode[1:0] == 2'b00) | (opcode[1:0] == 2'b11)); //Conditional branch //True for BRANCH //False for JAL/JALR - assign o_cond_branch = !opcode[0]; + wire co_cond_branch = !opcode[0]; - assign o_ctrl_utype = !opcode[4] & opcode[2] & opcode[0]; - assign o_ctrl_jal_or_jalr = opcode[4] & opcode[0]; + wire co_ctrl_utype = !opcode[4] & opcode[2] & opcode[0]; + wire co_ctrl_jal_or_jalr = opcode[4] & opcode[0]; //PC-relative operations //True for jal, b* auipc //False for jalr, lui - assign o_ctrl_pc_rel = (opcode[2:0] == 3'b000) | - (opcode[1:0] == 2'b11) | - (opcode[4:3] == 2'b00); + wire co_ctrl_pc_rel = (opcode[2:0] == 3'b000) | + (opcode[1:0] == 2'b11) | + (opcode[4:3] == 2'b00); //Write to RD //True for OP-IMM, AUIPC, OP, LUI, SYSTEM, JALR, JAL, LOAD //False for STORE, BRANCH, MISC-MEM - assign o_rd_op = (opcode[2] | - (!opcode[2] & opcode[4] & opcode[0]) | - (!opcode[2] & !opcode[3] & !opcode[0])); + wire co_rd_op = (opcode[2] | + (!opcode[2] & opcode[4] & opcode[0]) | + (!opcode[2] & !opcode[3] & !opcode[0])); // //funct3 // - assign o_sh_right = funct3[2]; - assign o_bne_or_bge = funct3[0]; - + wire co_sh_right = funct3[2]; + wire co_bne_or_bge = funct3[0]; + // // opcode & funct3 // - assign o_shift_op = op_or_opimm & (funct3[1:0] == 2'b01); - assign o_slt_op = op_or_opimm & (funct3[2:1] == 2'b01); + wire co_shift_op = op_or_opimm & (funct3[1:0] == 2'b01); + wire co_slt_op = op_or_opimm & (funct3[2:1] == 2'b01); //Matches system ops except eceall/ebreak/mret wire csr_op = opcode[4] & opcode[2] & (|funct3); //op20 - assign o_ebreak = op20; + wire co_ebreak = op20; //opcode & funct3 & op21 - assign o_ctrl_mret = opcode[4] & opcode[2] & op21 & !(|funct3); + wire co_ctrl_mret = opcode[4] & opcode[2] & op21 & !(|funct3); //Matches system opcodes except CSR accesses (funct3 == 0) //and mret (!op21) - assign o_e_op = opcode[4] & opcode[2] & !op21 & !(|funct3); + wire co_e_op = opcode[4] & opcode[2] & !op21 & !(|funct3); //opcode & funct3 & imm30 - assign o_bufreg_sh_signed = imm30; + wire co_bufreg_sh_signed = imm30; /* True for sub, b*, slt* @@ -144,16 +145,16 @@ module serv_decode add 01100 000 0 f sub 01100 000 1 t */ - assign o_alu_sub = funct3[1] | funct3[0] | (opcode[3] & imm30) | opcode[4]; + wire co_alu_sub = funct3[1] | funct3[0] | (opcode[3] & imm30) | opcode[4]; /* Bits 26, 22, 21 and 20 are enough to uniquely identify the eight supported CSR regs mtvec, mscratch, mepc and mtval are stored externally (normally in the RF) and are treated differently from mstatus, mie and mcause which are stored in serv_csr. - + The former get a 2-bit address as seen below while the latter get a one-hot enable signal each. - + Hex|2 222|Reg |csr adr|6 210|name |addr ---|-----|--------|---- @@ -164,70 +165,179 @@ module serv_decode 341|1_001|mepc | 10 342|1_010|mcause | xx 343|1_011|mtval | 11 - + */ //true for mtvec,mscratch,mepc and mtval //false for mstatus, mie, mcause wire csr_valid = op20 | (op26 & !op21); - assign o_rd_csr_en = csr_op; + wire co_rd_csr_en = csr_op; - assign o_csr_en = csr_op & csr_valid; - assign o_csr_mstatus_en = csr_op & !op26 & !op22; - assign o_csr_mie_en = csr_op & !op26 & op22 & !op20; - assign o_csr_mcause_en = csr_op & op21 & !op20; + wire co_csr_en = csr_op & csr_valid; + wire co_csr_mstatus_en = csr_op & !op26 & !op22; + wire co_csr_mie_en = csr_op & !op26 & op22 & !op20; + wire co_csr_mcause_en = csr_op & op21 & !op20; - assign o_csr_source = funct3[1:0]; - assign o_csr_d_sel = funct3[2]; - assign o_csr_imm_en = opcode[4] & opcode[2] & funct3[2]; - assign o_csr_addr = {op26 & op20, !op26 | op21}; + wire [1:0] co_csr_source = funct3[1:0]; + wire co_csr_d_sel = funct3[2]; + wire co_csr_imm_en = opcode[4] & opcode[2] & funct3[2]; + wire [1:0] co_csr_addr = {op26 & op20, !op26 | op21}; - assign o_alu_cmp_eq = funct3[2:1] == 2'b00; + wire co_alu_cmp_eq = funct3[2:1] == 2'b00; - assign o_alu_cmp_sig = ~((funct3[0] & funct3[1]) | (funct3[1] & funct3[2])); + wire co_alu_cmp_sig = ~((funct3[0] & funct3[1]) | (funct3[1] & funct3[2])); - assign o_mem_cmd = opcode[3]; - assign o_mem_signed = ~funct3[2]; - assign o_mem_word = funct3[1]; - assign o_mem_half = funct3[0]; + wire co_mem_cmd = opcode[3]; + wire co_mem_signed = ~funct3[2]; + wire co_mem_word = funct3[1]; + wire co_mem_half = funct3[0]; - assign o_alu_bool_op = funct3[1:0]; + wire [1:0] co_alu_bool_op = funct3[1:0]; + wire [3:0] co_immdec_ctrl; //True for S (STORE) or B (BRANCH) type instructions //False for J type instructions - assign o_immdec_ctrl[0] = opcode[3:0] == 4'b1000; + assign co_immdec_ctrl[0] = opcode[3:0] == 4'b1000; //True for OP-IMM, LOAD, STORE, JALR (I S) - //False for LUI, AUIPC, JAL (U J) - assign o_immdec_ctrl[1] = (opcode[1:0] == 2'b00) | (opcode[2:1] == 2'b00); - assign o_immdec_ctrl[2] = opcode[4] & !opcode[0]; - assign o_immdec_ctrl[3] = opcode[4]; + //False for LUI, AUIPC, JAL (U J) + assign co_immdec_ctrl[1] = (opcode[1:0] == 2'b00) | (opcode[2:1] == 2'b00); + assign co_immdec_ctrl[2] = opcode[4] & !opcode[0]; + assign co_immdec_ctrl[3] = opcode[4]; - assign o_immdec_en[3] = opcode[4] | opcode[3] | opcode[2] | !opcode[0]; //B I J S U - assign o_immdec_en[2] = (opcode[4] & opcode[2]) | !opcode[3] | opcode[0]; // I J U - assign o_immdec_en[1] = (opcode[2:1] == 2'b01) | (opcode[2] & opcode[0]) | o_csr_imm_en;// J U - assign o_immdec_en[0] = ~o_rd_op; //B S + wire [3:0] co_immdec_en; + assign co_immdec_en[3] = opcode[4] | opcode[3] | opcode[2] | !opcode[0]; //B I J S U + assign co_immdec_en[2] = (opcode[4] & opcode[2]) | !opcode[3] | opcode[0]; // I J U + assign co_immdec_en[1] = (opcode[2:1] == 2'b01) | (opcode[2] & opcode[0]) | co_csr_imm_en;// J U + assign co_immdec_en[0] = ~co_rd_op; //B S - assign o_alu_rd_sel[0] = (funct3 == 3'b000); // Add/sub - assign o_alu_rd_sel[1] = (funct3[2:1] == 2'b01); //SLT* - assign o_alu_rd_sel[2] = funct3[2]; //Bool - always @(posedge clk) begin - if (i_wb_en) begin - funct3 <= i_wb_rdt[14:12]; - imm30 <= i_wb_rdt[30]; - opcode <= i_wb_rdt[6:2]; - op20 <= i_wb_rdt[20]; - op21 <= i_wb_rdt[21]; - op22 <= i_wb_rdt[22]; - op26 <= i_wb_rdt[26]; - end - end + wire [2:0] co_alu_rd_sel; + assign co_alu_rd_sel[0] = (funct3 == 3'b000); // Add/sub + assign co_alu_rd_sel[1] = (funct3[2:1] == 2'b01); //SLT* + assign co_alu_rd_sel[2] = funct3[2]; //Bool //0 (OP_B_SOURCE_IMM) when OPIMM //1 (OP_B_SOURCE_RS2) when BRANCH or OP - assign o_op_b_source = opcode[3]; + wire co_op_b_source = opcode[3]; - assign o_rd_alu_en = !opcode[0] & opcode[2] & !opcode[4]; + wire co_rd_alu_en = !opcode[0] & opcode[2] & !opcode[4]; + generate + if (PRE_REGISTER) begin + + always @(posedge clk) begin + if (i_wb_en) begin + funct3 <= i_wb_rdt[14:12]; + imm30 <= i_wb_rdt[30]; + opcode <= i_wb_rdt[6:2]; + op20 <= i_wb_rdt[20]; + op21 <= i_wb_rdt[21]; + op22 <= i_wb_rdt[22]; + op26 <= i_wb_rdt[26]; + end + end + + always @(*) begin + o_sh_right = co_sh_right; + o_bne_or_bge = co_bne_or_bge; + o_cond_branch = co_cond_branch; + o_e_op = co_e_op; + o_ebreak = co_ebreak; + o_branch_op = co_branch_op; + o_mem_op = co_mem_op; + o_shift_op = co_shift_op; + o_slt_op = co_slt_op; + o_rd_op = co_rd_op; + o_bufreg_rs1_en = co_bufreg_rs1_en; + o_bufreg_imm_en = co_bufreg_imm_en; + o_bufreg_clr_lsb = co_bufreg_clr_lsb; + o_bufreg_sh_signed = co_bufreg_sh_signed; + o_ctrl_jal_or_jalr = co_ctrl_jal_or_jalr; + o_ctrl_utype = co_ctrl_utype; + o_ctrl_pc_rel = co_ctrl_pc_rel; + o_ctrl_mret = co_ctrl_mret; + o_alu_sub = co_alu_sub; + o_alu_bool_op = co_alu_bool_op; + o_alu_cmp_eq = co_alu_cmp_eq; + o_alu_cmp_sig = co_alu_cmp_sig; + o_alu_rd_sel = co_alu_rd_sel; + o_mem_signed = co_mem_signed; + o_mem_word = co_mem_word; + o_mem_half = co_mem_half; + o_mem_cmd = co_mem_cmd; + o_csr_en = co_csr_en; + o_csr_addr = co_csr_addr; + o_csr_mstatus_en = co_csr_mstatus_en; + o_csr_mie_en = co_csr_mie_en; + o_csr_mcause_en = co_csr_mcause_en; + o_csr_source = co_csr_source; + o_csr_d_sel = co_csr_d_sel; + o_csr_imm_en = co_csr_imm_en; + o_immdec_ctrl = co_immdec_ctrl; + o_immdec_en = co_immdec_en; + o_op_b_source = co_op_b_source; + o_rd_csr_en = co_rd_csr_en; + o_rd_alu_en = co_rd_alu_en; + end + + end else begin + + always @(*) begin + funct3 = i_wb_rdt[14:12]; + imm30 = i_wb_rdt[30]; + opcode = i_wb_rdt[6:2]; + op20 = i_wb_rdt[20]; + op21 = i_wb_rdt[21]; + op22 = i_wb_rdt[22]; + op26 = i_wb_rdt[26]; + end + + always @(posedge clk) begin + if (i_wb_en) begin + o_sh_right <= co_sh_right; + o_bne_or_bge <= co_bne_or_bge; + o_cond_branch <= co_cond_branch; + o_e_op <= co_e_op; + o_ebreak <= co_ebreak; + o_branch_op <= co_branch_op; + o_mem_op <= co_mem_op; + o_shift_op <= co_shift_op; + o_slt_op <= co_slt_op; + o_rd_op <= co_rd_op; + o_bufreg_rs1_en <= co_bufreg_rs1_en; + o_bufreg_imm_en <= co_bufreg_imm_en; + o_bufreg_clr_lsb <= co_bufreg_clr_lsb; + o_bufreg_sh_signed <= co_bufreg_sh_signed; + o_ctrl_jal_or_jalr <= co_ctrl_jal_or_jalr; + o_ctrl_utype <= co_ctrl_utype; + o_ctrl_pc_rel <= co_ctrl_pc_rel; + o_ctrl_mret <= co_ctrl_mret; + o_alu_sub <= co_alu_sub; + o_alu_bool_op <= co_alu_bool_op; + o_alu_cmp_eq <= co_alu_cmp_eq; + o_alu_cmp_sig <= co_alu_cmp_sig; + o_alu_rd_sel <= co_alu_rd_sel; + o_mem_signed <= co_mem_signed; + o_mem_word <= co_mem_word; + o_mem_half <= co_mem_half; + o_mem_cmd <= co_mem_cmd; + o_csr_en <= co_csr_en; + o_csr_addr <= co_csr_addr; + o_csr_mstatus_en <= co_csr_mstatus_en; + o_csr_mie_en <= co_csr_mie_en; + o_csr_mcause_en <= co_csr_mcause_en; + o_csr_source <= co_csr_source; + o_csr_d_sel <= co_csr_d_sel; + o_csr_imm_en <= co_csr_imm_en; + o_immdec_ctrl <= co_immdec_ctrl; + o_immdec_en <= co_immdec_en; + o_op_b_source <= co_op_b_source; + o_rd_csr_en <= co_rd_csr_en; + o_rd_alu_en <= co_rd_alu_en; + end + end + + end + endgenerate endmodule