diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index de6deed..37a4ccb 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -3,65 +3,26 @@ module serv_decode #(parameter [0:0] PRE_REGISTER = 1, parameter [0:0] MDU = 0) ( - input wire clk, + input wire clk, //Input input wire [31:2] i_wb_rdt, - input wire i_wb_en, + input wire i_wb_en, //To state - 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_shift_op, - output reg o_slt_or_branch, - output reg o_rd_op, - output reg o_two_stage_op, - output reg o_dbus_en, - //MDU - output reg o_mdu_op, - //Extension - output reg [2:0] o_ext_funct3, - //To bufreg - output reg o_bufreg_rs1_en, - output reg o_bufreg_imm_en, - output reg o_bufreg_clr_lsb, - output reg o_bufreg_sh_signed, + output reg o_e_op,//xx + output reg o_ebreak,//xx //To ctrl - 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 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 reg o_mem_signed, - output reg o_mem_word, - output reg o_mem_half, - output reg o_mem_cmd, + output reg o_ctrl_mret,//xx //To CSR - 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, - output reg o_mtval_pc, - //To top - output reg [3:0] o_immdec_ctrl, - output reg [3:0] o_immdec_en, - output reg o_op_b_source, + output reg o_csr_en,//xx + output reg [1:0] o_csr_addr,//xx + output reg o_csr_mstatus_en,//xx + output reg o_csr_mie_en,//xx + output reg o_csr_mcause_en,//xx + output reg [1:0] o_csr_source,//xx + output reg o_csr_d_sel,//xx + output reg o_csr_imm_en,//xx //To RF IF - output reg o_rd_mem_en, - output reg o_rd_csr_en, - output reg o_rd_alu_en); + output reg o_rd_csr_en);//xx reg [4:0] opcode; reg [2:0] funct3; @@ -73,91 +34,14 @@ module serv_decode reg imm25; reg imm30; - wire co_mdu_op = MDU & (opcode == 5'b01100) & imm25; - - wire co_two_stage_op = - ~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0] & ~opcode[4]) | - (funct3[1] & ~funct3[2] & ~opcode[0] & ~opcode[4]) | co_mdu_op; - wire co_shift_op = (opcode[2] & ~funct3[1]) & !co_mdu_op; - wire co_slt_or_branch = (opcode[4] | (funct3[1] & opcode[2]) | (imm30 & opcode[2] & opcode[3] & ~funct3[2])) & !co_mdu_op; - wire co_branch_op = opcode[4]; - wire co_dbus_en = ~opcode[2] & ~opcode[4]; - wire co_mtval_pc = opcode[4]; - wire co_mem_word = funct3[1]; - wire co_rd_alu_en = !opcode[0] & opcode[2] & !opcode[4] & !co_mdu_op; - wire co_rd_mem_en = (!opcode[2] & !opcode[0]) | co_mdu_op; - wire [2:0] co_ext_funct3 = funct3; - - //jal,branch = imm - //jalr = rs1+imm - //mem = rs1+imm - //shift = rs1 - 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? - 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 - wire co_cond_branch = !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 - 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 - wire co_rd_op = (opcode[2] | - (!opcode[2] & opcode[4] & opcode[0]) | - (!opcode[2] & !opcode[3] & !opcode[0])); - - // - //funct3 - // - - wire co_sh_right = funct3[2]; - wire co_bne_or_bge = funct3[0]; - - //Matches system ops except eceall/ebreak/mret - wire csr_op = opcode[4] & opcode[2] & (|funct3); - - //op20 wire co_ebreak = op20; - - //opcode & funct3 & op21 - - wire co_ctrl_mret = opcode[4] & opcode[2] & op21 & !(|funct3); - //Matches system opcodes except CSR accesses (funct3 == 0) - //and mret (!op21) - wire co_e_op = opcode[4] & opcode[2] & !op21 & !(|funct3); - - //opcode & funct3 & imm30 - - wire co_bufreg_sh_signed = imm30; - - /* - True for sub, b*, slt* - False for add* - op opcode f3 i30 - b* 11000 xxx x t - addi 00100 000 x f - slt* 0x100 01x x t - add 01100 000 0 f - sub 01100 000 1 t - */ - wire co_alu_sub = funct3[1] | funct3[0] | (opcode[3] & imm30) | opcode[4]; + //csr_op matches system ops except eceall/ebreak/mret + //e_op matches system opcodes except CSR accesses (funct3 == 0) and mret (!op21) + wire co_rd_csr_en = opcode[4] & opcode[2] & (|funct3); + wire co_ctrl_mret = opcode[4] & opcode[2] & !(|funct3) & op21; + wire co_e_op = opcode[4] & opcode[2] & !(|funct3) & !op21; /* Bits 26, 22, 21 and 20 are enough to uniquely identify the eight supported CSR regs @@ -182,55 +66,17 @@ module serv_decode //true for mtvec,mscratch,mepc and mtval //false for mstatus, mie, mcause - wire csr_valid = op20 | (op26 & !op21); + wire co_csr_en = op20 | (op26 & !op21); - wire co_rd_csr_en = csr_op; - - 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; + wire co_csr_mstatus_en = !op26 & !op22; + wire co_csr_mie_en = !op26 & op22 & !op20; + wire co_csr_mcause_en = op21 & !op20; 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}; - wire co_alu_cmp_eq = funct3[2:1] == 2'b00; - - wire co_alu_cmp_sig = ~((funct3[0] & funct3[1]) | (funct3[1] & funct3[2])); - - wire co_mem_cmd = opcode[3]; - wire co_mem_signed = ~funct3[2]; - wire co_mem_half = funct3[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 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 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]; - - 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 - - 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 - wire co_op_b_source = opcode[3]; - generate if (PRE_REGISTER) begin @@ -248,37 +94,9 @@ module serv_decode end always @(*) begin - o_sh_right = co_sh_right; - o_bne_or_bge = co_bne_or_bge; - o_cond_branch = co_cond_branch; - o_dbus_en = co_dbus_en; - o_mtval_pc = co_mtval_pc; - o_two_stage_op = co_two_stage_op; o_e_op = co_e_op; o_ebreak = co_ebreak; - o_branch_op = co_branch_op; - o_shift_op = co_shift_op; - o_slt_or_branch = co_slt_or_branch; - o_rd_op = co_rd_op; - o_mdu_op = co_mdu_op; - o_ext_funct3 = co_ext_funct3; - 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; @@ -287,12 +105,7 @@ module serv_decode 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; - o_rd_mem_en = co_rd_mem_en; end end else begin @@ -310,37 +123,9 @@ module serv_decode 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_two_stage_op <= co_two_stage_op; - o_dbus_en <= co_dbus_en; - o_mtval_pc <= co_mtval_pc; - o_branch_op <= co_branch_op; - o_shift_op <= co_shift_op; - o_slt_or_branch <= co_slt_or_branch; - o_rd_op <= co_rd_op; - o_mdu_op <= co_mdu_op; - o_ext_funct3 <= co_ext_funct3; - 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; @@ -349,12 +134,7 @@ module serv_decode 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; - o_rd_mem_en <= co_rd_mem_en; end end diff --git a/rtl/serv_mem_decode.v b/rtl/serv_mem_decode.v new file mode 100644 index 0000000..1c56531 --- /dev/null +++ b/rtl/serv_mem_decode.v @@ -0,0 +1,658 @@ +module serv_auto_decode + #(parameter [0:0] MDU = 1'b0, + parameter [0:0] CSR = 1'b0) + ( + input wire i_clk, + //Input + input wire i_en, + input wire i_imm30, + input wire [2:0] i_funct3, + input wire [4:0] i_opcode, + //MDU/Ext/CSR + input wire i_imm25, + output reg [2:0] o_ext_funct3, + output reg o_mdu_op, + input wire i_op20, + input wire i_op21, + input wire i_op22, + input wire i_op26, + output reg o_e_op, + output reg o_ebreak, + output reg o_ctrl_mret, + output reg o_csr_en, + output reg o_csr_addr1, + output reg o_csr_addr0, + output reg o_csr_mstatus_en, + output reg o_csr_mie_en, + output reg o_csr_mcause_en, + output reg o_csr_source1, + output reg o_csr_source0, + output reg o_csr_d_sel, + output reg o_csr_imm_en, + output reg o_rd_csr_en, + //Output + output wire o_branch_op, + output wire o_ctrl_jal_or_jalr, + output wire o_slt_or_branch, + output wire o_alu_sub, + output wire o_alu_bool_op1, + output wire o_op_b_source, + output wire o_mem_cmd, + output wire o_immdec_ctrl0, + output wire o_immdec_en0, + output wire o_immdec_ctrl1, + output wire o_bufreg_rs1_en, + output wire o_immdec_ctrl2, + output wire o_cond_branch, + output wire o_immdec_ctrl3, + output wire o_two_stage_op, + output wire o_immdec_en1, + output wire o_immdec_en2, + output wire o_immdec_en3, + output wire o_bne_or_bge, + output wire o_rd_alu_en, + output wire o_sh_right, + output wire o_alu_cmp_sig, + output wire o_mem_signed, + output wire o_shift_op, + output wire o_alu_bool_op0, + output wire o_rd_mem_en, + output wire o_dbus_en, + output wire o_bufreg_imm_en, + output wire o_alu_rd_sel0, + output wire o_bufreg_clr_lsb, + output wire o_ctrl_pc_rel, + output wire o_alu_rd_sel1, + output wire o_bufreg_sh_signed, + output wire o_alu_cmp_eq, + output wire o_mem_half, + output wire o_ctrl_utype, + output wire o_rd_op, + output wire o_alu_rd_sel2, + output wire o_mem_word); + + (* ram_style = "block" *) reg [19:0] mem [0:511]; + reg [19:0] d; + + initial begin + mem[0] = 20'h46b50; + mem[1] = 20'h00000; + mem[2] = 20'h00000; + mem[3] = 20'h00000; + mem[4] = 20'h44710; + mem[5] = 20'h68380; + mem[6] = 20'h00000; + mem[7] = 20'h00000; + mem[8] = 20'h0625c; + mem[9] = 20'h00000; + mem[10] = 20'h00000; + mem[11] = 20'h00000; + mem[12] = 20'h44404; + mem[13] = 20'h60380; + mem[14] = 20'h00000; + mem[15] = 20'h00000; + mem[16] = 20'h00000; + mem[17] = 20'h00000; + mem[18] = 20'h00000; + mem[19] = 20'h00000; + mem[20] = 20'h00000; + mem[21] = 20'h00000; + mem[22] = 20'h00000; + mem[23] = 20'h00000; + mem[24] = 20'h1c26f; + mem[25] = 20'h44157; + mem[26] = 20'h00000; + mem[27] = 20'h4c3c7; + mem[28] = 20'h00000; + mem[29] = 20'h00000; + mem[30] = 20'h00000; + mem[31] = 20'h00000; + mem[32] = 20'h56b50; + mem[33] = 20'h00000; + mem[34] = 20'h00000; + mem[35] = 20'h00000; + mem[36] = 20'h41750; + mem[37] = 20'h68380; + mem[38] = 20'h00000; + mem[39] = 20'h00000; + mem[40] = 20'h1625c; + mem[41] = 20'h00000; + mem[42] = 20'h00000; + mem[43] = 20'h00000; + mem[44] = 20'h41454; + mem[45] = 20'h60380; + mem[46] = 20'h00000; + mem[47] = 20'h00000; + mem[48] = 20'h00000; + mem[49] = 20'h00000; + mem[50] = 20'h00000; + mem[51] = 20'h00000; + mem[52] = 20'h00000; + mem[53] = 20'h00000; + mem[54] = 20'h00000; + mem[55] = 20'h00000; + mem[56] = 20'h1c66f; + mem[57] = 20'h44157; + mem[58] = 20'h00000; + mem[59] = 20'h4c3c7; + mem[60] = 20'h00000; + mem[61] = 20'h00000; + mem[62] = 20'h00000; + mem[63] = 20'h00000; + mem[64] = 20'hc6350; + mem[65] = 20'h00000; + mem[66] = 20'h00000; + mem[67] = 20'h00000; + mem[68] = 20'h48f52; + mem[69] = 20'h68380; + mem[70] = 20'h00000; + mem[71] = 20'h00000; + mem[72] = 20'h8625c; + mem[73] = 20'h00000; + mem[74] = 20'h00000; + mem[75] = 20'h00000; + mem[76] = 20'h48c46; + mem[77] = 20'h60380; + mem[78] = 20'h00000; + mem[79] = 20'h00000; + mem[80] = 20'h00000; + mem[81] = 20'h00000; + mem[82] = 20'h00000; + mem[83] = 20'h00000; + mem[84] = 20'h00000; + mem[85] = 20'h00000; + mem[86] = 20'h00000; + mem[87] = 20'h00000; + mem[88] = 20'h00000; + mem[89] = 20'h44157; + mem[90] = 20'h00000; + mem[91] = 20'h4c3c7; + mem[92] = 20'h00000; + mem[93] = 20'h00000; + mem[94] = 20'h00000; + mem[95] = 20'h00000; + mem[96] = 20'h00000; + mem[97] = 20'h00000; + mem[98] = 20'h00000; + mem[99] = 20'h00000; + mem[100] = 20'h48752; + mem[101] = 20'h68380; + mem[102] = 20'h00000; + mem[103] = 20'h00000; + mem[104] = 20'h00000; + mem[105] = 20'h00000; + mem[106] = 20'h00000; + mem[107] = 20'h00000; + mem[108] = 20'h48446; + mem[109] = 20'h60380; + mem[110] = 20'h00000; + mem[111] = 20'h00000; + mem[112] = 20'h00000; + mem[113] = 20'h00000; + mem[114] = 20'h00000; + mem[115] = 20'h00000; + mem[116] = 20'h00000; + mem[117] = 20'h00000; + mem[118] = 20'h00000; + mem[119] = 20'h00000; + mem[120] = 20'h00000; + mem[121] = 20'h44157; + mem[122] = 20'h00000; + mem[123] = 20'h4c3c7; + mem[124] = 20'h00000; + mem[125] = 20'h00000; + mem[126] = 20'h00000; + mem[127] = 20'h00000; + mem[128] = 20'h46350; + mem[129] = 20'h00000; + mem[130] = 20'h00000; + mem[131] = 20'h00000; + mem[132] = 20'hc0710; + mem[133] = 20'h68380; + mem[134] = 20'h00000; + mem[135] = 20'h00000; + mem[136] = 20'h00000; + mem[137] = 20'h00000; + mem[138] = 20'h00000; + mem[139] = 20'h00000; + mem[140] = 20'hc0404; + mem[141] = 20'h60380; + mem[142] = 20'h00000; + mem[143] = 20'h00000; + mem[144] = 20'h00000; + mem[145] = 20'h00000; + mem[146] = 20'h00000; + mem[147] = 20'h00000; + mem[148] = 20'h00000; + mem[149] = 20'h00000; + mem[150] = 20'h00000; + mem[151] = 20'h00000; + mem[152] = 20'h0ca6f; + mem[153] = 20'h44157; + mem[154] = 20'h00000; + mem[155] = 20'h4c3c7; + mem[156] = 20'h00000; + mem[157] = 20'h00000; + mem[158] = 20'h00000; + mem[159] = 20'h00000; + mem[160] = 20'h56350; + mem[161] = 20'h00000; + mem[162] = 20'h00000; + mem[163] = 20'h00000; + mem[164] = 20'h41f50; + mem[165] = 20'h68380; + mem[166] = 20'h00000; + mem[167] = 20'h00000; + mem[168] = 20'h00000; + mem[169] = 20'h00000; + mem[170] = 20'h00000; + mem[171] = 20'h00000; + mem[172] = 20'h41c54; + mem[173] = 20'h60380; + mem[174] = 20'h00000; + mem[175] = 20'h00000; + mem[176] = 20'h00000; + mem[177] = 20'h00000; + mem[178] = 20'h00000; + mem[179] = 20'h00000; + mem[180] = 20'h00000; + mem[181] = 20'h00000; + mem[182] = 20'h00000; + mem[183] = 20'h00000; + mem[184] = 20'h0ce6f; + mem[185] = 20'h44157; + mem[186] = 20'h00000; + mem[187] = 20'h4c3c7; + mem[188] = 20'h00000; + mem[189] = 20'h00000; + mem[190] = 20'h00000; + mem[191] = 20'h00000; + mem[192] = 20'h00000; + mem[193] = 20'h00000; + mem[194] = 20'h00000; + mem[195] = 20'h00000; + mem[196] = 20'hc0712; + mem[197] = 20'h68380; + mem[198] = 20'h00000; + mem[199] = 20'h00000; + mem[200] = 20'h00000; + mem[201] = 20'h00000; + mem[202] = 20'h00000; + mem[203] = 20'h00000; + mem[204] = 20'hc0406; + mem[205] = 20'h60380; + mem[206] = 20'h00000; + mem[207] = 20'h00000; + mem[208] = 20'h00000; + mem[209] = 20'h00000; + mem[210] = 20'h00000; + mem[211] = 20'h00000; + mem[212] = 20'h00000; + mem[213] = 20'h00000; + mem[214] = 20'h00000; + mem[215] = 20'h00000; + mem[216] = 20'h0c26f; + mem[217] = 20'h44157; + mem[218] = 20'h00000; + mem[219] = 20'h4c3c7; + mem[220] = 20'h00000; + mem[221] = 20'h00000; + mem[222] = 20'h00000; + mem[223] = 20'h00000; + mem[224] = 20'h00000; + mem[225] = 20'h00000; + mem[226] = 20'h00000; + mem[227] = 20'h00000; + mem[228] = 20'hc1712; + mem[229] = 20'h68380; + mem[230] = 20'h00000; + mem[231] = 20'h00000; + mem[232] = 20'h00000; + mem[233] = 20'h00000; + mem[234] = 20'h00000; + mem[235] = 20'h00000; + mem[236] = 20'hc1406; + mem[237] = 20'h60380; + mem[238] = 20'h00000; + mem[239] = 20'h00000; + mem[240] = 20'h00000; + mem[241] = 20'h00000; + mem[242] = 20'h00000; + mem[243] = 20'h00000; + mem[244] = 20'h00000; + mem[245] = 20'h00000; + mem[246] = 20'h00000; + mem[247] = 20'h00000; + mem[248] = 20'h0c66f; + mem[249] = 20'h44157; + mem[250] = 20'h00000; + mem[251] = 20'h4c3c7; + mem[252] = 20'h00000; + mem[253] = 20'h00000; + mem[254] = 20'h00000; + mem[255] = 20'h00000; + mem[256] = 20'h46b50; + mem[257] = 20'h00000; + mem[258] = 20'h00000; + mem[259] = 20'h00000; + mem[260] = 20'h44710; + mem[261] = 20'h68380; + mem[262] = 20'h00000; + mem[263] = 20'h00000; + mem[264] = 20'h0625c; + mem[265] = 20'h00000; + mem[266] = 20'h00000; + mem[267] = 20'h00000; + mem[268] = 20'h44406; + mem[269] = 20'h60380; + mem[270] = 20'h00000; + mem[271] = 20'h00000; + mem[272] = 20'h00000; + mem[273] = 20'h00000; + mem[274] = 20'h00000; + mem[275] = 20'h00000; + mem[276] = 20'h00000; + mem[277] = 20'h00000; + mem[278] = 20'h00000; + mem[279] = 20'h00000; + mem[280] = 20'h1c26f; + mem[281] = 20'h44157; + mem[282] = 20'h00000; + mem[283] = 20'h4c3c7; + mem[284] = 20'h00000; + mem[285] = 20'h00000; + mem[286] = 20'h00000; + mem[287] = 20'h00000; + mem[288] = 20'h56b50; + mem[289] = 20'h00000; + mem[290] = 20'h00000; + mem[291] = 20'h00000; + mem[292] = 20'h00000; + mem[293] = 20'h68380; + mem[294] = 20'h00000; + mem[295] = 20'h00000; + mem[296] = 20'h1625c; + mem[297] = 20'h00000; + mem[298] = 20'h00000; + mem[299] = 20'h00000; + mem[300] = 20'h00000; + mem[301] = 20'h60380; + mem[302] = 20'h00000; + mem[303] = 20'h00000; + mem[304] = 20'h00000; + mem[305] = 20'h00000; + mem[306] = 20'h00000; + mem[307] = 20'h00000; + mem[308] = 20'h00000; + mem[309] = 20'h00000; + mem[310] = 20'h00000; + mem[311] = 20'h00000; + mem[312] = 20'h1c66f; + mem[313] = 20'h44157; + mem[314] = 20'h00000; + mem[315] = 20'h4c3c7; + mem[316] = 20'h00000; + mem[317] = 20'h00000; + mem[318] = 20'h00000; + mem[319] = 20'h00000; + mem[320] = 20'hc6350; + mem[321] = 20'h00000; + mem[322] = 20'h00000; + mem[323] = 20'h00000; + mem[324] = 20'h48f52; + mem[325] = 20'h68380; + mem[326] = 20'h00000; + mem[327] = 20'h00000; + mem[328] = 20'h8625c; + mem[329] = 20'h00000; + mem[330] = 20'h00000; + mem[331] = 20'h00000; + mem[332] = 20'h00000; + mem[333] = 20'h60380; + mem[334] = 20'h00000; + mem[335] = 20'h00000; + mem[336] = 20'h00000; + mem[337] = 20'h00000; + mem[338] = 20'h00000; + mem[339] = 20'h00000; + mem[340] = 20'h00000; + mem[341] = 20'h00000; + mem[342] = 20'h00000; + mem[343] = 20'h00000; + mem[344] = 20'h00000; + mem[345] = 20'h44157; + mem[346] = 20'h00000; + mem[347] = 20'h4c3c7; + mem[348] = 20'h00000; + mem[349] = 20'h00000; + mem[350] = 20'h00000; + mem[351] = 20'h00000; + mem[352] = 20'h00000; + mem[353] = 20'h00000; + mem[354] = 20'h00000; + mem[355] = 20'h00000; + mem[356] = 20'h48752; + mem[357] = 20'h68380; + mem[358] = 20'h00000; + mem[359] = 20'h00000; + mem[360] = 20'h00000; + mem[361] = 20'h00000; + mem[362] = 20'h00000; + mem[363] = 20'h00000; + mem[364] = 20'h00000; + mem[365] = 20'h60380; + mem[366] = 20'h00000; + mem[367] = 20'h00000; + mem[368] = 20'h00000; + mem[369] = 20'h00000; + mem[370] = 20'h00000; + mem[371] = 20'h00000; + mem[372] = 20'h00000; + mem[373] = 20'h00000; + mem[374] = 20'h00000; + mem[375] = 20'h00000; + mem[376] = 20'h00000; + mem[377] = 20'h44157; + mem[378] = 20'h00000; + mem[379] = 20'h4c3c7; + mem[380] = 20'h00000; + mem[381] = 20'h00000; + mem[382] = 20'h00000; + mem[383] = 20'h00000; + mem[384] = 20'h46350; + mem[385] = 20'h00000; + mem[386] = 20'h00000; + mem[387] = 20'h00000; + mem[388] = 20'hc0710; + mem[389] = 20'h68380; + mem[390] = 20'h00000; + mem[391] = 20'h00000; + mem[392] = 20'h00000; + mem[393] = 20'h00000; + mem[394] = 20'h00000; + mem[395] = 20'h00000; + mem[396] = 20'h00000; + mem[397] = 20'h60380; + mem[398] = 20'h00000; + mem[399] = 20'h00000; + mem[400] = 20'h00000; + mem[401] = 20'h00000; + mem[402] = 20'h00000; + mem[403] = 20'h00000; + mem[404] = 20'h00000; + mem[405] = 20'h00000; + mem[406] = 20'h00000; + mem[407] = 20'h00000; + mem[408] = 20'h0ca6f; + mem[409] = 20'h44157; + mem[410] = 20'h00000; + mem[411] = 20'h4c3c7; + mem[412] = 20'h00000; + mem[413] = 20'h00000; + mem[414] = 20'h00000; + mem[415] = 20'h00000; + mem[416] = 20'h56350; + mem[417] = 20'h00000; + mem[418] = 20'h00000; + mem[419] = 20'h00000; + mem[420] = 20'h51f50; + mem[421] = 20'h68380; + mem[422] = 20'h00000; + mem[423] = 20'h00000; + mem[424] = 20'h00000; + mem[425] = 20'h00000; + mem[426] = 20'h00000; + mem[427] = 20'h00000; + mem[428] = 20'h51c54; + mem[429] = 20'h60380; + mem[430] = 20'h00000; + mem[431] = 20'h00000; + mem[432] = 20'h00000; + mem[433] = 20'h00000; + mem[434] = 20'h00000; + mem[435] = 20'h00000; + mem[436] = 20'h00000; + mem[437] = 20'h00000; + mem[438] = 20'h00000; + mem[439] = 20'h00000; + mem[440] = 20'h0ce6f; + mem[441] = 20'h44157; + mem[442] = 20'h00000; + mem[443] = 20'h4c3c7; + mem[444] = 20'h00000; + mem[445] = 20'h00000; + mem[446] = 20'h00000; + mem[447] = 20'h00000; + mem[448] = 20'h00000; + mem[449] = 20'h00000; + mem[450] = 20'h00000; + mem[451] = 20'h00000; + mem[452] = 20'hc0712; + mem[453] = 20'h68380; + mem[454] = 20'h00000; + mem[455] = 20'h00000; + mem[456] = 20'h00000; + mem[457] = 20'h00000; + mem[458] = 20'h00000; + mem[459] = 20'h00000; + mem[460] = 20'h00000; + mem[461] = 20'h60380; + mem[462] = 20'h00000; + mem[463] = 20'h00000; + mem[464] = 20'h00000; + mem[465] = 20'h00000; + mem[466] = 20'h00000; + mem[467] = 20'h00000; + mem[468] = 20'h00000; + mem[469] = 20'h00000; + mem[470] = 20'h00000; + mem[471] = 20'h00000; + mem[472] = 20'h0c26f; + mem[473] = 20'h44157; + mem[474] = 20'h00000; + mem[475] = 20'h4c3c7; + mem[476] = 20'h00000; + mem[477] = 20'h00000; + mem[478] = 20'h00000; + mem[479] = 20'h00000; + mem[480] = 20'h00000; + mem[481] = 20'h00000; + mem[482] = 20'h00000; + mem[483] = 20'h00000; + mem[484] = 20'hc1712; + mem[485] = 20'h68380; + mem[486] = 20'h00000; + mem[487] = 20'h00000; + mem[488] = 20'h00000; + mem[489] = 20'h00000; + mem[490] = 20'h00000; + mem[491] = 20'h00000; + mem[492] = 20'h00000; + mem[493] = 20'h60380; + mem[494] = 20'h00000; + mem[495] = 20'h00000; + mem[496] = 20'h00000; + mem[497] = 20'h00000; + mem[498] = 20'h00000; + mem[499] = 20'h00000; + mem[500] = 20'h00000; + mem[501] = 20'h00000; + mem[502] = 20'h00000; + mem[503] = 20'h00000; + mem[504] = 20'h0c66f; + mem[505] = 20'h44157; + mem[506] = 20'h00000; + mem[507] = 20'h4c3c7; + mem[508] = 20'h00000; + mem[509] = 20'h00000; + mem[510] = 20'h00000; + mem[511] = 20'h00000; + end + +always @(posedge i_clk) + if (i_en) + d <= mem[{i_imm30,i_funct3,i_opcode}]; + + assign o_branch_op = d[0]; + assign o_ctrl_jal_or_jalr = o_branch_op; + assign o_slt_or_branch = d[1]; + assign o_alu_sub = o_slt_or_branch; + assign o_alu_bool_op1 = o_slt_or_branch; + assign o_op_b_source = d[2]; + assign o_mem_cmd = o_op_b_source; + assign o_immdec_ctrl0 = d[3]; + assign o_immdec_en0 = o_immdec_ctrl0; + assign o_immdec_ctrl1 = d[4]; + assign o_bufreg_rs1_en = o_immdec_ctrl1; + assign o_immdec_ctrl2 = d[5]; + assign o_cond_branch = o_immdec_ctrl2; + assign o_immdec_ctrl3 = d[6]; + assign o_two_stage_op = o_immdec_ctrl3; + assign o_immdec_en1 = d[7]; + assign o_immdec_en2 = d[8]; + assign o_immdec_en3 = d[9]; + assign o_bne_or_bge = d[10]; + assign o_rd_alu_en = o_bne_or_bge; + assign o_sh_right = d[11]; + assign o_alu_cmp_sig = o_sh_right; + assign o_mem_signed = o_sh_right; + assign o_shift_op = d[12]; + assign o_alu_bool_op0 = o_shift_op; + assign o_rd_mem_en = d[13]; + assign o_dbus_en = o_rd_mem_en; + assign o_bufreg_imm_en = d[14]; + assign o_alu_rd_sel0 = o_bufreg_imm_en; + assign o_bufreg_clr_lsb = d[15]; + assign o_ctrl_pc_rel = o_bufreg_clr_lsb; + assign o_alu_rd_sel1 = o_bufreg_clr_lsb; + assign o_bufreg_sh_signed = d[16]; + assign o_alu_cmp_eq = o_bufreg_sh_signed; + assign o_mem_half = o_bufreg_sh_signed; + assign o_ctrl_utype = d[17]; + assign o_rd_op = d[18]; + assign o_alu_rd_sel2 = d[19]; + assign o_mem_word = o_alu_rd_sel2; + +always @(posedge i_clk) begin +if (i_en) begin + //MDU/CSR/Ext + o_mdu_op <= MDU & (i_opcode == 5'b01100) & i_imm25; + o_ext_funct3 <= MDU ? i_funct3 : 3'b000; + o_ebreak <= CSR & (i_op20); + o_rd_csr_en <= CSR & (i_opcode[4] & i_opcode[2] & (|i_funct3)); + o_ctrl_mret <= CSR & (i_opcode[4] & i_opcode[2] & !(|i_funct3) & i_op21); + o_e_op <= CSR & (i_opcode[4] & i_opcode[2] & !(|i_funct3) & !i_op21); + o_csr_en <= CSR & (i_op20 | (i_op26 & !i_op21)); + o_csr_mstatus_en <= CSR & (!i_op26 & !i_op22); + o_csr_mie_en <= CSR & (!i_op26 & i_op22 & !i_op20); + o_csr_mcause_en <= CSR & ( i_op21 & !i_op20); + o_csr_source1 <= CSR & (i_funct3[1]); + o_csr_source0 <= CSR & (i_funct3[0]); + o_csr_d_sel <= CSR & (i_funct3[2]); + o_csr_imm_en <= CSR & (i_opcode[4] & i_opcode[2] & i_funct3[2]); + o_csr_addr1 <= CSR & (i_op26 & i_op20); + o_csr_addr0 <= CSR & (!i_op26 | i_op21); +end +end + +endmodule diff --git a/rtl/serv_post_reg_decode.v b/rtl/serv_post_reg_decode.v new file mode 100644 index 0000000..6720d9d --- /dev/null +++ b/rtl/serv_post_reg_decode.v @@ -0,0 +1,177 @@ +module serv_auto_decode + #(parameter [0:0] MDU = 1'b0) + ( + input wire i_clk, + //Input + input wire i_en, + input wire i_imm30, + input wire [2:0] i_funct3, + input wire [4:0] i_opcode, + //MDU/Ext/CSR + input wire i_imm25, + output reg [2:0] o_ext_funct3, + output reg o_mdu_op, + input wire i_op20, + input wire i_op21, + input wire i_op22, + input wire i_op26, + output reg o_e_op, + output reg o_ebreak, + output reg o_ctrl_mret, + output reg o_csr_en, + output reg o_csr_addr1, + output reg o_csr_addr0, + output reg o_csr_mstatus_en, + output reg o_csr_mie_en, + output reg o_csr_mcause_en, + output reg o_csr_source1, + output reg o_csr_source0, + output reg o_csr_d_sel, + output reg o_csr_imm_en, + output reg o_rd_csr_en, + //Output + output reg o_branch_op, + output wire o_ctrl_jal_or_jalr, + output reg o_slt_or_branch, + output wire o_alu_rd_sel1, + output reg o_op_b_source, + output wire o_immdec_ctrl3, + output reg o_immdec_ctrl0, + output wire o_immdec_en0, + output reg o_immdec_ctrl1, + output wire o_bufreg_rs1_en, + output reg o_immdec_ctrl2, + output wire o_cond_branch, + output reg o_immdec_en1, + output reg o_immdec_en2, + output reg o_immdec_en3, + output reg o_bne_or_bge, + output wire o_rd_alu_en, + output reg o_sh_right, + output wire o_alu_cmp_sig, + output wire o_mem_signed, + output reg o_shift_op, + output wire o_alu_bool_op0, + output reg o_two_stage_op, + output reg o_rd_mem_en, + output wire o_dbus_en, + output reg o_bufreg_imm_en, + output wire o_alu_rd_sel0, + output reg o_bufreg_clr_lsb, + output wire o_ctrl_pc_rel, + output wire o_alu_sub, + output wire o_alu_bool_op1, + output reg o_bufreg_sh_signed, + output wire o_alu_cmp_eq, + output wire o_mem_word, + output reg o_ctrl_utype, + output wire o_mem_cmd, + output reg o_rd_op, + output reg o_alu_rd_sel2, + output wire o_mem_half); + +// lajjbbbbbblllllsssassxoasssassssxssoa +// uuaaenlglgbhwbhbhwdllornlrrdulllorrrn +// iillqetete uu dttridlladblttrla d +// p r uu iiii iiii u +// c u +//branch_op |0011111111000000000000000000000000000| +//slt_or_branch | 11111111000000000110000000001100000| +//op_b_source |0011111111000001110000000001111111111| +//immdec_ctrl0 |0000111111000001110000000000000000000| +//immdec_ctrl1 |000100000011111111111111111 1 11 | +//immdec_ctrl2 |000011111100000000000000000 | +//immdec_en1 |1110000000000000000000000000000000000| +//immdec_en2 |1111000000111110001111111110000000000| +//immdec_en3 |1110111111111111111111111110000000000| +//bne_or_bge |000001010100000 1111111111111111111| +//sh_right | 110011 00 10 011 010 11 | +//shift_op | 0000000000000000 00001111 10001101| +//two_stage_op |0011111111111111110110001110011101100| +//rd_mem_en |0000000000111111110000000000000000000| +//bufreg_imm_en | 11111111111111111000000001100000000| +//bufreg_clr_lsb |0110111111000000000110110000101100011| +//bufreg_sh_signed | 11000000100001 00 01 00 01 | +//ctrl_utype |1100000000000001110000000000000000000| +//rd_op |1111000000111110001111111111111111111| +//alu_rd_sel2 | 010010100001110000000010011| +//20 signals +// +always @(posedge i_clk) + if (i_en) begin + o_branch_op <= i_opcode[4]; + o_slt_or_branch <= i_opcode[4] | (i_funct3[1] & i_opcode[2] & ~i_funct3[2]); + o_op_b_source <= i_opcode[4] | (i_opcode[3] & ~i_opcode[0]); + o_immdec_ctrl0 <= i_opcode[3] & ~i_opcode[0] & ~i_opcode[2]; + o_immdec_ctrl1 <= (~i_opcode[0] & ~i_opcode[4]) | (i_opcode[0] & ~i_opcode[1] & ~i_opcode[2]); + o_immdec_ctrl2 <= i_opcode[4] & ~i_opcode[0]; + o_immdec_en1 <= i_opcode[1] | (i_opcode[0] & ~i_opcode[4]); + o_immdec_en2 <= i_opcode[0] | ~i_opcode[3]; + o_immdec_en3 <= i_opcode[1] | ~i_opcode[3] | (i_opcode[0] & ~i_opcode[4]) | (~i_opcode[0] & ~i_opcode[2]); + o_bne_or_bge <= (i_opcode[2] & ~i_opcode[0]) | (i_funct3[0] & i_opcode[3] & ~i_opcode[0]); + o_sh_right <= (i_funct3[2] & i_opcode[2]) | (i_opcode[4] & ~i_funct3[1]) | (~i_funct3[0] & ~i_funct3[2]) | (~i_funct3[2] & ~i_opcode[2]); + o_shift_op <= (i_funct3[0] & i_funct3[2] & i_opcode[2]) | (i_funct3[0] & i_opcode[2] & ~i_funct3[1]); + o_two_stage_op <= ~i_opcode[2] | (i_funct3[0] & ~i_funct3[1] & ~i_opcode[0]) | (i_funct3[1] & ~i_funct3[2] & ~i_opcode[0]); + o_rd_mem_en <= ~i_opcode[2] & ~i_opcode[4]; + o_bufreg_imm_en <= ~i_opcode[2] | (~i_funct3[0] & ~i_funct3[1] & ~i_funct3[2]); + o_bufreg_clr_lsb <= i_opcode[1] | (i_opcode[0] & ~i_opcode[3]) | (i_opcode[4] & ~i_opcode[0]) | (i_funct3[1] & i_opcode[2] & ~i_opcode[0]) | (i_imm30 & i_opcode[2] & i_opcode[3] & ~i_funct3[2] & ~i_opcode[0]); + o_bufreg_sh_signed <= (i_opcode[4] & ~i_funct3[2]) | (i_imm30 & i_opcode[2] & ~i_funct3[1]) | (i_funct3[1] & ~i_funct3[2] & ~i_opcode[2]); + o_ctrl_utype <= (i_opcode[0] & ~i_opcode[4]) | (i_opcode[3] & ~i_opcode[2] & ~i_opcode[4]); + o_rd_op <= i_opcode[0] | i_opcode[2] | ~i_opcode[3]; + o_alu_rd_sel2 <= (i_funct3[1] & i_funct3[2]) | (i_funct3[0] & ~i_opcode[2]) | (i_funct3[2] & i_opcode[2] & ~i_funct3[0]); + //MDU/CSR/Ext + o_mdu_op <= MDU & (i_opcode == 5'b01100) & i_imm25; +// o_ext_funct3 <= i_funct3; + o_ebreak <= i_op20; + o_ctrl_mret <= i_opcode[4] & i_opcode[2] & !(|i_funct3) & i_op21; + o_e_op <= i_opcode[4] & i_opcode[2] & !(|i_funct3) & !i_op21; +/* + o_rd_csr_en <= i_opcode[4] & i_opcode[2] & (|i_funct3); + o_csr_en <= i_op20 | (i_op26 & !i_op21); + o_csr_mstatus_en <= !i_op26 & !i_op22; + o_csr_mie_en <= !i_op26 & i_op22 & !i_op20; + o_csr_mcause_en <= i_op21 & !i_op20; + o_csr_source1 <= i_funct3[1]; + o_csr_source0 <= i_funct3[0]; + o_csr_d_sel <= i_funct3[2]; + o_csr_imm_en <= i_opcode[4] & i_opcode[2] & i_funct3[2]; + o_csr_addr1 <= i_op26 & i_op20; + o_csr_addr0 <= !i_op26 | i_op21; + */end + always @(*) begin + o_ext_funct3 <= 3'd0; + o_rd_csr_en <= 1'b0; + o_csr_en <= 1'b0; + o_csr_mstatus_en <= 1'b0; + o_csr_mie_en <= 1'b0; + o_csr_mcause_en <= 1'b0; + o_csr_source1 <= 1'b0; + o_csr_source0 <= 1'b0; + o_csr_d_sel <= 1'b0; + o_csr_imm_en <= 1'b0; + o_csr_addr1 <= 1'b0; + o_csr_addr0 <= 1'b0; + end + + assign o_ctrl_jal_or_jalr = o_branch_op; + assign o_alu_rd_sel1 = o_slt_or_branch; + assign o_immdec_ctrl3 = o_op_b_source; + assign o_immdec_en0 = o_immdec_ctrl0; + assign o_bufreg_rs1_en = o_immdec_ctrl1; + assign o_cond_branch = o_immdec_ctrl2; + assign o_rd_alu_en = o_bne_or_bge; + assign o_alu_cmp_sig = o_sh_right; + assign o_mem_signed = o_sh_right; + assign o_alu_bool_op0 = o_shift_op; + assign o_dbus_en = o_rd_mem_en; + assign o_alu_rd_sel0 = o_bufreg_imm_en; + assign o_ctrl_pc_rel = o_bufreg_clr_lsb; + assign o_alu_sub = o_bufreg_clr_lsb; + assign o_alu_bool_op1 = o_bufreg_clr_lsb; + assign o_alu_cmp_eq = o_bufreg_sh_signed; + assign o_mem_word = o_bufreg_sh_signed; + assign o_mem_cmd = o_ctrl_utype; + assign o_mem_half = o_alu_rd_sel2; + + +endmodule diff --git a/rtl/serv_pre_reg_decode.v b/rtl/serv_pre_reg_decode.v new file mode 100644 index 0000000..0c09f88 --- /dev/null +++ b/rtl/serv_pre_reg_decode.v @@ -0,0 +1,152 @@ +module serv_auto_decode + #(parameter [0:0] MDU = 1'b0) + ( + input wire i_clk, + //Input + input wire i_en, + input wire i_imm30, + input wire [2:0] i_funct3, + input wire [4:0] i_opcode, + //MDU/Ext/CSR + input wire i_imm25, + output reg [2:0] o_ext_funct3, + output reg o_mdu_op, + input wire i_op20, + input wire i_op21, + input wire i_op22, + input wire i_op26, + output reg o_e_op, + output reg o_ebreak, + output reg o_ctrl_mret, + output reg o_csr_en, + output reg o_csr_addr1, + output reg o_csr_addr0, + output reg o_csr_mstatus_en, + output reg o_csr_mie_en, + output reg o_csr_mcause_en, + output reg o_csr_source1, + output reg o_csr_source0, + output reg o_csr_d_sel, + output reg o_csr_imm_en, + output reg o_rd_csr_en, + //Output + output wire o_branch_op, + output wire o_ctrl_jal_or_jalr, + output wire o_slt_or_branch, + output wire o_alu_rd_sel1, + output wire o_op_b_source, + output wire o_immdec_ctrl3, + output wire o_immdec_ctrl0, + output wire o_immdec_en0, + output wire o_immdec_ctrl1, + output wire o_bufreg_rs1_en, + output wire o_immdec_ctrl2, + output wire o_cond_branch, + output wire o_immdec_en1, + output wire o_immdec_en2, + output wire o_immdec_en3, + output wire o_bne_or_bge, + output wire o_rd_alu_en, + output wire o_sh_right, + output wire o_alu_cmp_sig, + output wire o_mem_signed, + output wire o_shift_op, + output wire o_alu_bool_op0, + output wire o_two_stage_op, + output wire o_rd_mem_en, + output wire o_dbus_en, + output wire o_bufreg_imm_en, + output wire o_alu_rd_sel0, + output wire o_bufreg_clr_lsb, + output wire o_ctrl_pc_rel, + output wire o_alu_sub, + output wire o_alu_bool_op1, + output wire o_bufreg_sh_signed, + output wire o_alu_cmp_eq, + output wire o_mem_word, + output wire o_ctrl_utype, + output wire o_mem_cmd, + output wire o_rd_op, + output wire o_alu_rd_sel2, + output wire o_mem_half); + + reg imm30; + reg [2:0] funct3; + reg [4:0] opcode; + +always @(posedge i_clk) + if (i_en) begin + imm30 <= i_imm30; + funct3 <= i_funct3; + opcode <= i_opcode; + end + assign o_branch_op = opcode[4]; + assign o_ctrl_jal_or_jalr = o_branch_op; assign o_slt_or_branch = opcode[4] | (funct3[1] & opcode[2] & ~funct3[2]); + assign o_alu_rd_sel1 = o_slt_or_branch; assign o_op_b_source = opcode[4] | (opcode[3] & ~opcode[0]); + assign o_immdec_ctrl3 = o_op_b_source; assign o_immdec_ctrl0 = opcode[3] & ~opcode[0] & ~opcode[2]; + assign o_immdec_en0 = o_immdec_ctrl0; assign o_immdec_ctrl1 = (~opcode[0] & ~opcode[4]) | (opcode[0] & ~opcode[1] & ~opcode[2]); + assign o_bufreg_rs1_en = o_immdec_ctrl1; assign o_immdec_ctrl2 = opcode[4] & ~opcode[0]; + assign o_cond_branch = o_immdec_ctrl2; assign o_immdec_en1 = opcode[1] | (opcode[0] & ~opcode[4]); + assign o_immdec_en2 = opcode[0] | ~opcode[3]; + assign o_immdec_en3 = opcode[1] | ~opcode[3] | (opcode[0] & ~opcode[4]) | (~opcode[0] & ~opcode[2]); + assign o_bne_or_bge = (opcode[2] & ~opcode[0]) | (funct3[0] & opcode[3] & ~opcode[0]); + assign o_rd_alu_en = o_bne_or_bge; assign o_sh_right = (funct3[2] & opcode[2]) | (opcode[4] & ~funct3[1]) | (~funct3[0] & ~funct3[2]) | (~funct3[2] & ~opcode[2]); + assign o_alu_cmp_sig = o_sh_right; assign o_mem_signed = o_sh_right; assign o_shift_op = (funct3[0] & funct3[2] & opcode[2]) | (funct3[0] & opcode[2] & ~funct3[1]); + assign o_alu_bool_op0 = o_shift_op; assign o_two_stage_op = ~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0]) | (funct3[1] & ~funct3[2] & ~opcode[0]); + assign o_rd_mem_en = ~opcode[2] & ~opcode[4]; + assign o_dbus_en = o_rd_mem_en; assign o_bufreg_imm_en = ~opcode[2] | (~funct3[0] & ~funct3[1] & ~funct3[2]); + assign o_alu_rd_sel0 = o_bufreg_imm_en; assign o_bufreg_clr_lsb = opcode[1] | (opcode[0] & ~opcode[3]) | (opcode[4] & ~opcode[0]) | (funct3[1] & opcode[2] & ~opcode[0]) | (imm30 & opcode[2] & opcode[3] & ~funct3[2] & ~opcode[0]); + assign o_ctrl_pc_rel = o_bufreg_clr_lsb; assign o_alu_sub = o_bufreg_clr_lsb; assign o_alu_bool_op1 = o_bufreg_clr_lsb; assign o_bufreg_sh_signed = (opcode[4] & ~funct3[2]) | (imm30 & opcode[2] & ~funct3[1]) | (funct3[1] & ~funct3[2] & ~opcode[2]); + assign o_alu_cmp_eq = o_bufreg_sh_signed; assign o_mem_word = o_bufreg_sh_signed; assign o_ctrl_utype = (opcode[0] & ~opcode[4]) | (opcode[3] & ~opcode[2] & ~opcode[4]); + assign o_mem_cmd = o_ctrl_utype; assign o_rd_op = opcode[0] | opcode[2] | ~opcode[3]; + assign o_alu_rd_sel2 = (funct3[1] & funct3[2]) | (funct3[0] & ~opcode[2]) | (funct3[2] & opcode[2] & ~funct3[0]); + assign o_mem_half = o_alu_rd_sel2; + //MDU/CSR/Ext + reg imm25; + reg op20; + reg op21; + reg op22; + reg op26; + +always @(posedge i_clk) + if (i_en) begin + imm25 <= i_imm25; + funct3 <= i_funct3; + opcode <= i_opcode; + op20 <= i_op20; + op21 <= i_op21; + op22 <= i_op22; + op26 <= i_op26; + end + + assign o_mdu_op = MDU & (opcode == 5'b01100) & imm25; + assign o_ext_funct3 = funct3; + assign o_ebreak = op20; + assign o_ctrl_mret = opcode[4] & opcode[2] & !(|funct3) & op21; + assign o_e_op = opcode[4] & opcode[2] & !(|funct3) & !op21; +/* assign o_rd_csr_en = opcode[4] & opcode[2] & (|funct3); + assign o_csr_en = op20 | (op26 & !op21); + assign o_csr_mstatus_en = !op26 & !op22; + assign o_csr_mie_en = !op26 & op22 & !op20; + assign o_csr_mcause_en = op21 & !op20; + assign o_csr_source1 = funct3[1]; + assign o_csr_source0 = funct3[0]; + assign o_csr_d_sel = funct3[2]; + assign o_csr_imm_en = opcode[4] & opcode[2] & funct3[2]; + assign o_csr_addr1 = op26 & op20; + assign o_csr_addr0 = !op26 | op21; +*/ + assign o_rd_csr_en = 1'b0; + assign o_csr_en = 1'b0; + assign o_csr_mstatus_en = 1'b0; + assign o_csr_mie_en = 1'b0; + assign o_csr_mcause_en = 1'b0; + assign o_csr_source1 = 1'b0; + assign o_csr_source0 = 1'b0; + assign o_csr_d_sel = 1'b0; + assign o_csr_imm_en = 1'b0; + assign o_csr_addr1 = 1'b0; + assign o_csr_addr0 = 1'b0; + + +endmodule diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 05ebc95..fc26d69 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -94,7 +94,6 @@ module serv_top wire alu_rd; wire mem_rd; wire csr_rd; - wire mtval_pc; wire ctrl_pc_en; wire jump; @@ -229,71 +228,110 @@ module serv_top .i_rf_ready (i_rf_ready), .o_rf_rd_en (rd_en)); - serv_decode - #(.PRE_REGISTER (PRE_REGISTER), - .MDU(MDU)) - decode + wire pshift_op; + wire pslt_or_branch; + wire prd_op; + wire ptwo_stage_op; + wire pbufreg_rs1_en; + wire pbufreg_imm_en; + wire pdbus_en; + wire pimmdec_en1; + wire prd_alu_en; + wire pjal_or_jalr; + wire prd_mem_en; + wire timmdec_ctrl3; + + + assign shift_op = pshift_op & !mdu_op; + assign slt_or_branch = pslt_or_branch & !mdu_op; + assign rd_op = prd_op | rd_csr_en; + assign two_stage_op = ptwo_stage_op & !rd_csr_en | mdu_op; + assign bufreg_rs1_en = pbufreg_rs1_en | mdu_op; + assign bufreg_imm_en = pbufreg_imm_en & !mdu_op; + assign dbus_en = pdbus_en & !mdu_op; + assign immdec_en[1] = pimmdec_en1 | csr_imm_en; + assign rd_alu_en = prd_alu_en & !rd_csr_en & !mdu_op; + assign jal_or_jalr = pjal_or_jalr & !rd_csr_en; + assign rd_mem_en = prd_mem_en /*& !rd_csr_en*/ | mdu_op; + assign immdec_ctrl[3] = timmdec_ctrl3 | rd_csr_en; + + serv_auto_decode #(.MDU (MDU)) autodec ( - .clk (clk), + .i_clk (clk), //Input - .i_wb_rdt (i_ibus_rdt[31:2]), - .i_wb_en (i_ibus_ack), - //To state - .o_bne_or_bge (bne_or_bge), - .o_cond_branch (cond_branch), - .o_dbus_en (dbus_en), + .i_imm30 (i_ibus_rdt[30]), + .i_funct3 (i_ibus_rdt[14:12]), + .i_opcode (i_ibus_rdt[6:2]), + .i_en (i_ibus_ack), + //CSR/MDU + .i_imm25 (i_ibus_rdt[25]), + .o_ext_funct3 (o_ext_funct3), + .o_mdu_op (mdu_op), + + .i_op20 (i_ibus_rdt[20]), + .i_op21 (i_ibus_rdt[21]), + .i_op22 (i_ibus_rdt[22]), + .i_op26 (i_ibus_rdt[26]), .o_e_op (e_op), .o_ebreak (ebreak), - .o_branch_op (branch_op), - .o_shift_op (shift_op), - .o_slt_or_branch (slt_or_branch), - .o_rd_op (rd_op), - .o_sh_right (sh_right), - .o_mdu_op (mdu_op), - .o_two_stage_op (two_stage_op), - //Extension - .o_ext_funct3 (o_ext_funct3), - - //To bufreg - .o_bufreg_rs1_en (bufreg_rs1_en), - .o_bufreg_imm_en (bufreg_imm_en), - .o_bufreg_clr_lsb (bufreg_clr_lsb), - .o_bufreg_sh_signed (bufreg_sh_signed), - //To bufreg2 - .o_op_b_source (op_b_sel), //To ctrl - .o_ctrl_jal_or_jalr (jal_or_jalr), - .o_ctrl_utype (utype), - .o_ctrl_pc_rel (pc_rel), .o_ctrl_mret (mret), - //To alu - .o_alu_sub (alu_sub), - .o_alu_bool_op (alu_bool_op), - .o_alu_cmp_eq (alu_cmp_eq), - .o_alu_cmp_sig (alu_cmp_sig), - .o_alu_rd_sel (alu_rd_sel), - //To mem IF - .o_mem_cmd (o_dbus_we), - .o_mem_signed (mem_signed), - .o_mem_word (mem_word), - .o_mem_half (mem_half), //To CSR - .o_csr_en (csr_en), - .o_csr_addr (csr_addr), + .o_csr_en (csr_en ), + .o_csr_addr1 (csr_addr[1] ), + .o_csr_addr0 (csr_addr[0] ), .o_csr_mstatus_en (csr_mstatus_en), - .o_csr_mie_en (csr_mie_en), - .o_csr_mcause_en (csr_mcause_en), - .o_csr_source (csr_source), - .o_csr_d_sel (csr_d_sel), - .o_csr_imm_en (csr_imm_en), - .o_mtval_pc (mtval_pc ), - //To top - .o_immdec_ctrl (immdec_ctrl), - .o_immdec_en (immdec_en), + .o_csr_mie_en (csr_mie_en ), + .o_csr_mcause_en (csr_mcause_en ), + .o_csr_source1 (csr_source[1] ), + .o_csr_source0 (csr_source[0] ), + .o_csr_d_sel (csr_d_sel ), + .o_csr_imm_en (csr_imm_en ), //To RF IF - .o_rd_mem_en (rd_mem_en), .o_rd_csr_en (rd_csr_en), - .o_rd_alu_en (rd_alu_en)); + +// .o_mtval_pc (), + //To alu + .o_op_b_source (op_b_sel), + .o_sh_right (sh_right ), + .o_bne_or_bge (bne_or_bge ), + .o_cond_branch (cond_branch ), + .o_branch_op (branch_op ), + .o_shift_op (pshift_op ), + .o_slt_or_branch (pslt_or_branch), + .o_rd_op (prd_op ), + .o_two_stage_op (ptwo_stage_op ), + .o_dbus_en (pdbus_en ), + .o_bufreg_rs1_en (pbufreg_rs1_en ), + .o_bufreg_imm_en (pbufreg_imm_en ), + .o_bufreg_clr_lsb (bufreg_clr_lsb ), + .o_bufreg_sh_signed (bufreg_sh_signed), + .o_ctrl_jal_or_jalr (pjal_or_jalr ), + .o_ctrl_utype (utype ), + .o_ctrl_pc_rel (pc_rel ), + .o_alu_sub (alu_sub ), + .o_alu_bool_op1 (alu_bool_op[1]), + .o_alu_bool_op0 (alu_bool_op[0]), + .o_alu_cmp_eq (alu_cmp_eq ), + .o_alu_cmp_sig (alu_cmp_sig ), + .o_alu_rd_sel2 (alu_rd_sel[2] ), + .o_alu_rd_sel1 (alu_rd_sel[1] ), + .o_alu_rd_sel0 (alu_rd_sel[0] ), + .o_mem_signed (mem_signed ), + .o_mem_word (mem_word ), + .o_mem_half (mem_half ), + .o_mem_cmd (o_dbus_we ), + .o_immdec_ctrl0 (immdec_ctrl[0]), + .o_immdec_ctrl1 (immdec_ctrl[1]), + .o_immdec_ctrl2 (immdec_ctrl[2]), + .o_immdec_ctrl3 (timmdec_ctrl3), + .o_immdec_en0 (immdec_en[0] ), + .o_immdec_en1 (pimmdec_en1 ), + .o_immdec_en2 (immdec_en[2] ), + .o_immdec_en3 (immdec_en[3] ), + .o_rd_mem_en (prd_mem_en), + .o_rd_alu_en (prd_alu_en )); + serv_immdec immdec ( @@ -431,12 +469,12 @@ module serv_top .i_trap (trap), .i_mret (mret), .i_mepc (o_ibus_adr[0]), - .i_mtval_pc (mtval_pc), + .i_mtval_pc (branch_op), .i_bufreg_q (bufreg_q), .i_bad_pc (bad_pc), .o_csr_pc (csr_pc), //CSR write port - .i_csr_en (csr_en), + .i_csr_en (csr_en & rd_csr_en), .i_csr_addr (csr_addr), .i_csr (csr_in), //RD write port @@ -496,7 +534,7 @@ module serv_top .i_cnt3 (cnt3), .i_cnt7 (cnt7), .i_cnt_done (cnt_done), - .i_mem_op (!mtval_pc), + .i_mem_op (dbus_en), .i_mtip (i_timer_irq), .i_trap (trap), .o_new_irq (new_irq), @@ -504,9 +542,9 @@ module serv_top .i_e_op (e_op), .i_ebreak (ebreak), .i_mem_cmd (o_dbus_we), - .i_mstatus_en (csr_mstatus_en), - .i_mie_en (csr_mie_en ), - .i_mcause_en (csr_mcause_en ), + .i_mstatus_en (rd_csr_en & csr_mstatus_en), + .i_mie_en (rd_csr_en & csr_mie_en ), + .i_mcause_en (rd_csr_en & csr_mcause_en ), .i_csr_source (csr_source), .i_mret (mret), .i_csr_d_sel (csr_d_sel), diff --git a/serv.core b/serv.core index a9b6ec7..4d71cb6 100644 --- a/serv.core +++ b/serv.core @@ -11,6 +11,7 @@ filesets: - rtl/serv_alu.v - rtl/serv_csr.v - rtl/serv_ctrl.v + - rtl/serv_mem_decode.v - rtl/serv_decode.v - rtl/serv_immdec.v - rtl/serv_mem_if.v diff --git a/sw/decodegen.py b/sw/decodegen.py new file mode 100644 index 0000000..5ca9ba6 --- /dev/null +++ b/sw/decodegen.py @@ -0,0 +1,494 @@ +from sympy.logic import SOPform +from sympy import symbols +from functools import partial, reduce +from itertools import product, combinations +import networkx as nx +import z3 + +HEADER = """module serv_auto_decode + #(parameter [0:0] MDU = 1'b0, + parameter [0:0] CSR = 1'b0) + ( + input wire i_clk, + //Input + input wire i_en, + input wire i_imm30, + input wire [2:0] i_funct3, + input wire [4:0] i_opcode, + //MDU/Ext/CSR + input wire i_imm25, + output reg [2:0] o_ext_funct3, + output reg o_mdu_op, + input wire i_op20, + input wire i_op21, + input wire i_op22, + input wire i_op26, + output reg o_e_op, + output reg o_ebreak, + output reg o_ctrl_mret, + output reg o_csr_en, + output reg o_csr_addr1, + output reg o_csr_addr0, + output reg o_csr_mstatus_en, + output reg o_csr_mie_en, + output reg o_csr_mcause_en, + output reg o_csr_source1, + output reg o_csr_source0, + output reg o_csr_d_sel, + output reg o_csr_imm_en, + output reg o_rd_csr_en, + //Output + {ports}); + +{body} +endmodule +""" + +def printmap(ctrlmap): + s = "" + l = max([len(x) for x in ctrlmap]) + s+=' '*(l+2)+"lajjbbbbbblllllsssassxoasssassssxssoa\n" + s+=' '*(l+2)+"uuaaenlglgbhwbhbhwdllornlrrdulllorrrn\n" + s+=' '*(l+2)+"iillqetete uu dttridlladblttrla d\n" + s+=' '*(l+2)+" p r uu iiii iiii u \n" + s+=' '*(l+2)+" c u \n" + + for k,v in ctrlmap.items(): + s += f"{k:<{l}} |{v}|\n" + s += f"{len(ctrlmap)} signals\n" + return s + +def merge(d, dst, src): + l = list(d[dst]) + for i in range(len(l)): + if l[i] == ' ': + l[i] = d[src][i] + elif l[i] == '1' and d[src][i] == '0': + raise Exception + elif l[i] == '0' and d[src][i] == '1': + raise Exception + d[dst] = ''.join(l) + d.pop(src) + +def merge_signals(ctrlmap): + #Merge control signals and keep track of which signals that have been combined + + # We build a graph of signals as nodes and merge conflicts as edges. We use z3 to find + # an optimal coloring of the graph. All nodes of the same color will have no conflicts + # and can be merged + + solver = z3.Optimize() + + node_colors = {} + + g = nx.Graph() + + color_count = z3.Int('color_count') + + # Create a node for every signal + for sig in ctrlmap: + g.add_node(sig) + node_colors[sig] = node_color = z3.Int('color_' + sig) + + solver.add(node_color >= 0, node_color < color_count) + + # Conflicting signals may not get the same color + for sig_i, sig_j in combinations(ctrlmap, 2): + collide = any( + i != j and ' ' not in (i, j) + for i, j in zip(ctrlmap[sig_i], ctrlmap[sig_j]) + ) + if collide: + g.add_edge(sig_i, sig_j) + solver.add(node_colors[sig_i] != node_colors[sig_j]) + + # We use networkx to find the largest clique. All nodes in that clique will have to get + # distinct colors. Since the numbering of colors is arbitrary, we can without loss of + # generality decide a fixed numbering of the colors of that clique. This kind of + # symmetry breaking is essential for performance here. + for i, sig in enumerate(max(nx.find_cliques(g), key=len)): + solver.add(node_colors[sig] == i) + + solver.minimize(color_count) + + if solver.check() != z3.sat: + raise Exception("optmization failed") # Shouldn't happen + + model = solver.model() + + print(f"Found coloring using {model[color_count]} colors") + + merged_signals = {} + merge_by_color = {} + + for signal in list(ctrlmap): + color = model[node_colors[signal]] + if color in merge_by_color: + other_signal = merge_by_color[color] + merge(ctrlmap, other_signal, signal) + merged_signals.setdefault(other_signal, []).append(signal) + else: + merge_by_color[color] = signal + + if merged_signals: + for k,v in merged_signals.items(): + print(f"Merged {', '.join(v)} into {k}") + return (ctrlmap, merged_signals) + +def map2signals(ctrlmap): + for k,v in ctrlmap.items(): + ctrl_signals = {} + t = [] + f = [] + for i,op in enumerate(ops): + #Only rv32i for now + if i > 36: + continue + + if v[i] == '1': + t.append(op) + elif v[i] == '0': + f.append(op) + ctrl_signals[k] = (t,f) + return ctrl_signals + +def minterms(s): + return list(map(partial(reduce, lambda x, y: 2*x + y), product(*([0, 1] if z == 'x' else [int(z)] for z in s)))) + +def map2minterms(bitmap): + m = [] + falsies = [] + for i,op in enumerate(ops): + #Only rv32i for now + if i > 36: + continue + + if bitmap[i] == '1': + m += minterms(ops[op]) + elif bitmap[i] == '0': + falsies += minterms(ops[op]) + return (m, falsies) + +def write_post_reg_logic_decoder(ctrlmap, merged_signals): + signames = [ + 'i_imm30', + 'i_funct3[2]', + 'i_funct3[1]', + 'i_funct3[0]', + 'i_opcode[4]', + 'i_opcode[3]', + 'i_opcode[2]', + 'i_opcode[1]', + 'i_opcode[0]', + ] + syms = [*symbols(' '.join(signames))] + ports = [] + body = '\n'.join('//'+x for x in printmap(ctrlmap).split('\n')) + body += "\nalways @(posedge i_clk)\n" + body += " if (i_en) begin\n" + body2 =" end\n\n" + for sig, bitmap in ctrlmap.items(): + #Find all conditions signals must be true and false + (t, f) = map2minterms(bitmap) + + #Use Quine-McCluskey to minimize the logic expressions needed for each + #control signal. Don't cares are the ones that are neither listed as + #true or false + dc = set(range(2**9))-set(t)-set(f) + s = SOPform(syms, t, dc) + + ports.append(f"output reg o_{sig}") + + #Output final control signal expression + body += f" o_{sig} <= {s};\n" + if sig in merged_signals: + for alias in merged_signals[sig]: + ports.append(f"output wire o_{alias}") + body2 += f" assign o_{alias} = o_{sig};\n" + + #Some extra signals + body += " //MDU/CSR/Ext\n" + body += " o_mdu_op <= MDU & (i_opcode == 5'b01100) & i_imm25;\n" + body += " o_ext_funct3 <= i_funct3;\n" + body += " o_ebreak <= i_op20;\n" + body += " o_rd_csr_en <= i_opcode[4] & i_opcode[2] & (|i_funct3);\n" + body += " o_ctrl_mret <= i_opcode[4] & i_opcode[2] & !(|i_funct3) & i_op21;\n" + body += " o_e_op <= i_opcode[4] & i_opcode[2] & !(|i_funct3) & !i_op21;\n" + body += " o_csr_en <= i_op20 | (i_op26 & !i_op21);\n" + body += " o_csr_mstatus_en <= !i_op26 & !i_op22;\n" + body += " o_csr_mie_en <= !i_op26 & i_op22 & !i_op20;\n" + body += " o_csr_mcause_en <= i_op21 & !i_op20;\n" + body += " o_csr_source1 <= i_funct3[1];\n" + body += " o_csr_source0 <= i_funct3[0];\n" + body += " o_csr_d_sel <= i_funct3[2];\n" + body += " o_csr_imm_en <= i_opcode[4] & i_opcode[2] & i_funct3[2];\n" + body += " o_csr_addr1 <= i_op26 & i_op20;\n" + body += " o_csr_addr0 <= !i_op26 | i_op21;\n" + + with open('serv_post_reg_decode.v', 'w') as f: + f.write(HEADER.format(ports=',\n '.join(ports), body=body+body2+'\n')) + +def write_pre_reg_logic_decoder(ctrlmap, merged_signals): + signames = [ + 'imm30', + 'funct3[2]', + 'funct3[1]', + 'funct3[0]', + 'opcode[4]', + 'opcode[3]', + 'opcode[2]', + 'opcode[1]', + 'opcode[0]', + ] + syms = [*symbols(' '.join(signames))] + ports = [] + body = """ reg imm30; + reg [2:0] funct3; + reg [4:0] opcode; + +always @(posedge i_clk) + if (i_en) begin + imm30 <= i_imm30; + funct3 <= i_funct3; + opcode <= i_opcode; + end +""" + + for sig, bitmap in ctrlmap.items(): + #Find all conditions signals must be true and false + (t, f) = map2minterms(bitmap) + + #Use Quine-McCluskey to minimize the logic expressions needed for each + #control signal. Don't cares are the ones that are neither listed as + #true or false + dc = set(range(2**9))-set(t)-set(f) + s = SOPform(syms, t, dc) + + ports.append(f"output wire o_{sig}") + + #Output final control signal expression + body += f" assign o_{sig} = {s};\n" + if sig in merged_signals: + for alias in merged_signals[sig]: + ports.append(f"output wire o_{alias}") + body += f" assign o_{alias} = o_{sig};" + + #Some extra signals + body += "\n" + body += " //MDU/CSR/Ext\n" + body += "always @(posedge i_clk)\n" + body += " if (i_en) begin\n" + body += " imm25 <= i_imm25;\n" + body += " funct3 <= i_funct3;\n" + body += " opcode <= i_opcode;\n" + body += " op20 <= i_op20;\n" + body += " op21 <= i_op21;\n" + body += " op22 <= i_op22;\n" + body += " op26 <= i_op26;\n" + body += " end\n" + body += " assign o_mdu_op = MDU & (opcode == 5'b01100) & imm25;\n" + body += " assign o_ext_funct3 = funct3;\n" + body += " assign o_ebreak = op20;\n" + body += " assign o_rd_csr_en = opcode[4] & opcode[2] & (|funct3);\n" + body += " assign o_ctrl_mret = opcode[4] & opcode[2] & !(|funct3) & op21;\n" + body += " assign o_e_op = opcode[4] & opcode[2] & !(|funct3) & !op21;\n" + body += " assign o_csr_en = op20 | (op26 & !op21);\n" + body += " assign o_csr_mstatus_en = !op26 & !op22;\n" + body += " assign o_csr_mie_en = !op26 & op22 & !op20;\n" + body += " assign o_csr_mcause_en = op21 & !op20;\n" + body += " assign o_csr_source1 = funct3[1];\n" + body += " assign o_csr_source0 = funct3[0];\n" + body += " assign o_csr_d_sel = funct3[2];\n" + body += " assign o_csr_imm_en = opcode[4] & opcode[2] & funct3[2];\n" + body += " assign o_csr_addr1 = op26 & op20;\n" + body += " assign o_csr_addr0 = !op26 | op21;\n" + + with open('serv_pre_reg_decode.v', 'w') as f: + f.write(HEADER.format(ports=',\n '.join(ports), body=body)) + +def write_mem_decoder(ctrlmap, merged_signals): + ports = [] + mem = [0]*512 + + width = len(ctrlmap) + body = """ (* ram_style = "block" *) reg [{msb}:0] mem [0:511]; + reg [{msb}:0] d; + + initial begin +{mem} end + +always @(posedge i_clk) + if (i_en) + d <= mem[{{i_imm30,i_funct3,i_opcode}}]; + +""" + + s = "" + for i, (sig, bitmap) in enumerate(ctrlmap.items()): + #Find all conditions signals must be true + #Rest can be zero + (t, _) = map2minterms(bitmap) + for x in t: + mem[x] += 2**i + body += f" assign o_{sig} = d[{i}];\n" + + ports.append(f"output wire o_{sig}") + + if sig in merged_signals: + for alias in merged_signals[sig]: + ports.append(f"output wire o_{alias}") + body += f" assign o_{alias} = o_{sig};\n" + + for i, m in enumerate(mem): + s += f" mem[{i}] = {width}'h{m:0{(width+3)//4}x};\n" + + body += "\nalways @(posedge i_clk) begin\n" + body += "if (i_en) begin\n" + body += " //MDU/CSR/Ext\n" + body += " o_mdu_op <= MDU & (i_opcode == 5'b01100) & i_imm25;\n" + body += " o_ext_funct3 <= MDU ? i_funct3 : 3'b000;\n" + body += " o_ebreak <= CSR & (i_op20);\n" + body += " o_rd_csr_en <= CSR & (i_opcode[4] & i_opcode[2] & (|i_funct3));\n" + body += " o_ctrl_mret <= CSR & (i_opcode[4] & i_opcode[2] & !(|i_funct3) & i_op21);\n" + body += " o_e_op <= CSR & (i_opcode[4] & i_opcode[2] & !(|i_funct3) & !i_op21);\n" + body += " o_csr_en <= CSR & (i_op20 | (i_op26 & !i_op21));\n" + body += " o_csr_mstatus_en <= CSR & (!i_op26 & !i_op22);\n" + body += " o_csr_mie_en <= CSR & (!i_op26 & i_op22 & !i_op20);\n" + body += " o_csr_mcause_en <= CSR & ( i_op21 & !i_op20);\n" + body += " o_csr_source1 <= CSR & (i_funct3[1]);\n" + body += " o_csr_source0 <= CSR & (i_funct3[0]);\n" + body += " o_csr_d_sel <= CSR & (i_funct3[2]);\n" + body += " o_csr_imm_en <= CSR & (i_opcode[4] & i_opcode[2] & i_funct3[2]);\n" + body += " o_csr_addr1 <= CSR & (i_op26 & i_op20);\n" + body += " o_csr_addr0 <= CSR & (!i_op26 | i_op21);\n" + body += "end\n" + body += "end\n" + + with open('serv_mem_decode.v', 'w') as f: + f.write(HEADER.format(ports=',\n '.join(ports), body=body.format(msb=width-1, mem=s))) + + +#imm30, funct3, opcode +ops = { + 'lui' : 'x' + 'xxx' + '01101', + 'auipc' : 'x' + 'xxx' + '00101', + 'jal' : 'x' + 'xxx' + '11011', + 'jalr' : 'x' + 'xxx' + '11001',#funct3 = 000? + 'beq' : 'x' + '000' + '11000', + 'bne' : 'x' + '001' + '11000', + 'blt' : 'x' + '100' + '11000', + 'bge' : 'x' + '101' + '11000', + 'bltu' : 'x' + '110' + '11000', + 'bgeu' : 'x' + '111' + '11000', + 'lb' : 'x' + '000' + '00000', + 'lh' : 'x' + '001' + '00000', + 'lw' : 'x' + '010' + '00000', + 'lbu' : 'x' + '100' + '00000', + 'lhu' : 'x' + '101' + '00000', + 'sb' : 'x' + '000' + '01000', + 'sh' : 'x' + '001' + '01000', + 'sw' : 'x' + '010' + '01000', + 'addi' : 'x' + '000' + '00100', + 'slti' : 'x' + '010' + '00100', + 'sltiu' : 'x' + '011' + '00100', + 'xori' : 'x' + '100' + '00100', + 'ori' : 'x' + '110' + '00100', + 'andi' : 'x' + '111' + '00100', + 'slli' : '0' + '001' + '00100', + 'srli' : '0' + '101' + '00100', + 'srai' : '1' + '101' + '00100', + 'add' : '0' + '000' + '01100', + 'sub' : '1' + '000' + '01100', + 'sll' : '0' + '001' + '01100', + 'slt' : '0' + '010' + '01100', + 'sltu' : '0' + '011' + '01100', + 'xor' : '0' + '100' + '01100', + 'srl' : '0' + '101' + '01100', + 'sra' : '1' + '101' + '01100', + 'or' : '0' + '110' + '01100', + 'and' : '0' + '111' + '01100', + 'fence' : 'x' + 'xxx' + '00011',#funct3=000? + 'ecall' : 'x' + '000' + '11100',#ebreak same but op20=1 + 'csrrw' : 'x' + '001' + '11100', + 'csrrs' : 'x' + '010' + '11100', + 'csrrc' : 'x' + '011' + '11100', + 'csrrwi': 'x' + '101' + '11100', + 'csrrsi': 'x' + '110' + '11100', + 'csrrci': 'x' + '111' + '11100', +} + +################################### +################################### +################################### + + +#Map of all required true/false conditions for each op. +#This should ideally be created automatically from riscv-formal runs +#TODO: Extend with optional ISA extensions (M, Zicsr, Zifencei..) + +#ebreak = ecall with op20=1 +ctrlmap = \ +{ + #UUJRBBBBBBIIIIISSSIIIIIIIIIRRRRRRRRRR + #lajjbbbbbblllllsssassxoasssassssxssoa + #uuaaenlglgbhwbhbhwdllornlrrdulllorrrn + #iillqetete uu dttridlladblttrla d + # p r uu iiii iiii u + # c u + 'branch_op' : ' 1111111100000000 00 000 000 00 ', + 'slt_or_branch' : ' 1111111100000000 11 000 011 00 ', + 'op_b_source' : ' 11111111000001110000000001111111111', + 'immdec_ctrl0' : ' 0 11111100000111000000000 ', + 'immdec_ctrl1' : '000 11111111111111111 ', + 'immdec_ctrl2' : '000 11111100000000000000000 ', + 'immdec_ctrl3' : '001 ', + 'immdec_en0' : '0000111111000001110000000000000000000', + 'immdec_en1' : '1110000000000000000000000000000000000', + 'immdec_en2' : '1111000000111110001111111110000000000', + 'immdec_en3' : '1110111111111111111111111110000000000', + 'bne_or_bge' : ' 010101 ', + 'sh_right' : ' 011 0 11 ', + 'cond_branch' : ' 00111111 ', + 'shift_op' : ' 0000000000000000 00 111 100 11 ', + 'two_stage_op' : '0011111111111111110110001110011101100', + 'rd_alu_en' : '0000 00000 1111111111111111111', + 'rd_mem_en' : '0000 11111 0000000000000000000', + 'dbus_en' : ' 0000000011111111 00 000 000 00 ', + 'bufreg_rs1_en' : ' 0100000011111111 111 1 11 ', + 'bufreg_imm_en' : ' 1111111111111111 000 0 00 ', + 'bufreg_clr_lsb' : ' 1011111100000000 000 0 00 ', + 'bufreg_sh_signed': ' 01 01 ', + 'ctrl_jal_or_jalr': '0011 00000 0000000000000000000', + 'ctrl_utype' : '110000000000000 0000000000000000000', + 'ctrl_pc_rel' : '0110111111 ', + 'rd_op' : '1111000000111110001111111111111111111', + 'alu_sub' : ' 111111 011 01 11 ', + 'alu_bool_op1' : ' 011000 0 00011', + 'alu_bool_op0' : ' 001111 1 01101', + 'alu_cmp_eq' : ' 110000 00 00 ', + 'alu_cmp_sig' : ' 1100 10 10 ', + 'alu_rd_sel0' : ' 1000000001100000000', + 'alu_rd_sel1' : ' 0110000000001100000', + 'alu_rd_sel2' : ' 0001110000000010011', + 'mem_signed' : ' 11 00 ', + 'mem_word' : ' 00100001 ', + 'mem_half' : ' 01001010 ', + 'mem_cmd' : ' 00000111 ', +# 'mtval_pc' : ' 1111111100000000 ', +} + +print(printmap(ctrlmap)) + +print("\nMerging control signals") +(ctrlmap, merged_signals) = merge_signals(ctrlmap) +print(printmap(ctrlmap)) + +#Create the various decoders +print("Creating mem decoder") +write_mem_decoder(ctrlmap, merged_signals) + +#print("Writing post-registered logic decoder") +#write_post_reg_logic_decoder(ctrlmap, merged_signals) +# +#print("Writing pre-registered logic decoder") +#write_pre_reg_logic_decoder(ctrlmap, merged_signals)