//+FHDR-------------------------------------------------------------------------------------------------------- // Company: //----------------------------------------------------------------------------------------------------------------- // File Name : qbmcu_decode.v // Department : // Author : PWY // Author's Tel : //----------------------------------------------------------------------------------------------------------------- // Relese History // Version Date Author Description // 0.1 2024-03-13 PWY The decode module to decode the instruction details //----------------------------------------------------------------------------------------------------------------- // Keywords : // //----------------------------------------------------------------------------------------------------------------- // Parameter // //----------------------------------------------------------------------------------------------------------------- // Purpose : // //----------------------------------------------------------------------------------------------------------------- // Target Device: // Tool versions: //----------------------------------------------------------------------------------------------------------------- // Reuse Issues // Reset Strategy: // Clock Domains: // Critical Timing: // Asynchronous I/F: // Synthesizable (y/n): // Other: //-FHDR-------------------------------------------------------------------------------------------------------- `include "qbmcu_defines.v" module qbmcu_decode( input clk // System Clock ,input rst_n // System reset,active low ,input dec_i_active // DEC module Active from MCU FSM ////////////////////////////////////////////////////////////// // The IR stage to Decoder ,input [`QBMCU_INSTR_SIZE-1 :0] dec_i_instr ,input [`QBMCU_PC_SIZE-1 :0] dec_i_pc ////////////////////////////////////////////////////////////// // The Decoded Info-Bus //,output dec_o_rs1en //,output dec_o_rs2en ,output dec_o_rdwen ,output [`QBMCU_RFIDX_WIDTH-1 :0] dec_o_rs1idx ,output [`QBMCU_RFIDX_WIDTH-1 :0] dec_o_rs2idx ,output [`QBMCU_RFIDX_WIDTH-1 :0] dec_o_rdidx ,output [`QBMCU_DECINFO_WIDTH-1:0] dec_o_info ,output [`QBMCU_XLEN-1 :0] dec_o_imm ,output [`QBMCU_PC_SIZE-1 :0] dec_o_pc ,output dec_o_ilegl ); wire dec_i_active_r; wire [`QBMCU_DECINFO_WIDTH-1:0] dec_info_w; //dec_i_active_r //sirv_gnrl_dffr #(1) dec_i_active_r_dffr (dec_i_active, dec_i_active_r, clk, rst_n); assign dec_i_active_r = dec_i_active; /////////////////////////////////////////////////////////////// //Instruction decoding /////////////////////////////////////////////////////////////// wire [32-1:0] rv32_instr = dec_i_instr; wire [6:0] opcode = rv32_instr[6:0]; //wire opcode_1_0_00 = (opcode[1:0] == 2'b00); //wire opcode_1_0_01 = (opcode[1:0] == 2'b01); //wire opcode_1_0_10 = (opcode[1:0] == 2'b10); wire opcode_1_0_11 = (opcode[1:0] == 2'b11); wire rv32 = (~(dec_i_instr[4:2] == 3'b111)) & opcode_1_0_11; wire [4:0] rv32_rd = rv32_instr[11:7]; wire [2:0] rv32_func3 = rv32_instr[14:12]; wire [4:0] rv32_rs1 = rv32_instr[19:15]; wire [4:0] rv32_rs2 = rv32_instr[24:20]; wire [6:0] rv32_func7 = rv32_instr[31:25]; // We generate the signals and reused them as much as possible to save gatecounts wire opcode_4_2_000 = (opcode[4:2] == 3'b000); wire opcode_4_2_001 = (opcode[4:2] == 3'b001); wire opcode_4_2_010 = (opcode[4:2] == 3'b010); wire opcode_4_2_011 = (opcode[4:2] == 3'b011); wire opcode_4_2_100 = (opcode[4:2] == 3'b100); wire opcode_4_2_101 = (opcode[4:2] == 3'b101); //wire opcode_4_2_110 = (opcode[4:2] == 3'b110); wire opcode_4_2_111 = (opcode[4:2] == 3'b111); wire opcode_6_5_00 = (opcode[6:5] == 2'b00); wire opcode_6_5_01 = (opcode[6:5] == 2'b01); //wire opcode_6_5_10 = (opcode[6:5] == 2'b10); wire opcode_6_5_11 = (opcode[6:5] == 2'b11); wire rv32_func3_000 = (rv32_func3 == 3'b000); wire rv32_func3_001 = (rv32_func3 == 3'b001); wire rv32_func3_010 = (rv32_func3 == 3'b010); wire rv32_func3_011 = (rv32_func3 == 3'b011); wire rv32_func3_100 = (rv32_func3 == 3'b100); wire rv32_func3_101 = (rv32_func3 == 3'b101); wire rv32_func3_110 = (rv32_func3 == 3'b110); wire rv32_func3_111 = (rv32_func3 == 3'b111); wire rv32_func7_0000000 = (rv32_func7 == 7'b0000000); wire rv32_func7_0100000 = (rv32_func7 == 7'b0100000); wire rv32_func7_1111111 = (rv32_func7 == 7'b1111111); wire rv32_rs1_x0 = (rv32_rs1 == 5'b00000); wire rv32_rs2_x0 = (rv32_rs2 == 5'b00000); //wire rv32_rs2_x1 = (rv32_rs2 == 5'b00001); wire rv32_rd_x0 = (rv32_rd == 5'b00000); //wire rv32_rd_x2 = (rv32_rd == 5'b00010); wire rv32_rs1_x31 = (rv32_rs1 == 5'b11111); wire rv32_rs2_x31 = (rv32_rs2 == 5'b11111); wire rv32_rd_x31 = (rv32_rd == 5'b11111); wire rv32_load = opcode_6_5_00 & opcode_4_2_000 & opcode_1_0_11; //LB wire rv32_store = opcode_6_5_01 & opcode_4_2_000 & opcode_1_0_11; //SB wire rv32_branch = opcode_6_5_11 & opcode_4_2_000 & opcode_1_0_11; //B wire rv32_jalr = opcode_6_5_11 & opcode_4_2_001 & opcode_1_0_11; //JALR wire rv32_custom0 = opcode_6_5_00 & opcode_4_2_010 & opcode_1_0_11; //WAIT SENDC SEND wire rv32_custom1 = opcode_6_5_01 & opcode_4_2_010 & opcode_1_0_11; //EXIT EXIT_IRQ wire rv32_jal = opcode_6_5_11 & opcode_4_2_011 & opcode_1_0_11; //JAL wire rv32_op_imm = opcode_6_5_00 & opcode_4_2_100 & opcode_1_0_11; //ADDI wire rv32_op = opcode_6_5_01 & opcode_4_2_100 & opcode_1_0_11; //ADD wire rv32_auipc = opcode_6_5_00 & opcode_4_2_101 & opcode_1_0_11; //AUIPC wire rv32_lui = opcode_6_5_01 & opcode_4_2_101 & opcode_1_0_11; //LUI // =========================================================================== // Branch Instructions wire rv32_beq = rv32_branch & rv32_func3_000; //B beq wire rv32_bne = rv32_branch & rv32_func3_001; //B bne wire rv32_blt = rv32_branch & rv32_func3_100; //B blt wire rv32_bgt = rv32_branch & rv32_func3_101; //B bge wire rv32_bltu = rv32_branch & rv32_func3_110; //B bltu wire rv32_bgtu = rv32_branch & rv32_func3_111; //B bgeu // =========================================================================== // The Branch and system group of instructions will be handled by BJP wire dec_jal = rv32_jal ; wire dec_jalr = rv32_jalr; wire dec_bxx = rv32_branch; wire dec_bjp = dec_jal | dec_jalr | dec_bxx; wire bjp_op = dec_bjp ; wire [`QBMCU_DECINFO_BJP_WIDTH-1:0] bjp_info_bus; assign bjp_info_bus[`QBMCU_DECINFO_GRP ] = `QBMCU_DECINFO_GRP_BJP; assign bjp_info_bus[`QBMCU_DECINFO_RV32 ] = rv32; assign bjp_info_bus[`QBMCU_DECINFO_BJP_JUMP ] = dec_jal | dec_jalr; assign bjp_info_bus[`QBMCU_DECINFO_BJP_JALR ] = dec_jalr; assign bjp_info_bus[`QBMCU_DECINFO_BJP_BEQ ] = rv32_beq ; assign bjp_info_bus[`QBMCU_DECINFO_BJP_BNE ] = rv32_bne ; assign bjp_info_bus[`QBMCU_DECINFO_BJP_BLT ] = rv32_blt; assign bjp_info_bus[`QBMCU_DECINFO_BJP_BGT ] = rv32_bgt ; assign bjp_info_bus[`QBMCU_DECINFO_BJP_BLTU ] = rv32_bltu; assign bjp_info_bus[`QBMCU_DECINFO_BJP_BGTU ] = rv32_bgtu; assign bjp_info_bus[`QBMCU_DECINFO_BJP_BXX ] = dec_bxx; // =========================================================================== // ALU Instructions wire rv32_addi = rv32_op_imm & rv32_func3_000; // I addi wire rv32_slti = rv32_op_imm & rv32_func3_010; // I slti wire rv32_sltiu = rv32_op_imm & rv32_func3_011; // I sltiu wire rv32_xori = rv32_op_imm & rv32_func3_100; // I xori wire rv32_ori = rv32_op_imm & rv32_func3_110; // I ori wire rv32_andi = rv32_op_imm & rv32_func3_111; // I andi wire rv32_slli = rv32_op_imm & rv32_func3_001 & (rv32_instr[31:26] == 6'b000000); // I slli wire rv32_srli = rv32_op_imm & rv32_func3_101 & (rv32_instr[31:26] == 6'b000000); // I srli wire rv32_srai = rv32_op_imm & rv32_func3_101 & (rv32_instr[31:26] == 6'b010000); // I srai wire rv32_sxxi_shamt_legl = (rv32_instr[25] == 1'b0); //shamt[5] must be zero for RV32I wire rv32_sxxi_shamt_ilgl = (rv32_slli | rv32_srli | rv32_srai) & (~rv32_sxxi_shamt_legl); wire rv32_add = rv32_op & rv32_func3_000 & rv32_func7_0000000; // R add wire rv32_sub = rv32_op & rv32_func3_000 & rv32_func7_0100000; // R sub wire rv32_sll = rv32_op & rv32_func3_001 & rv32_func7_0000000; // R sll wire rv32_slt = rv32_op & rv32_func3_010 & rv32_func7_0000000; // R slt wire rv32_sltu = rv32_op & rv32_func3_011 & rv32_func7_0000000; // R sltu wire rv32_xor = rv32_op & rv32_func3_100 & rv32_func7_0000000; // R xor wire rv32_srl = rv32_op & rv32_func3_101 & rv32_func7_0000000; // R srl wire rv32_sra = rv32_op & rv32_func3_101 & rv32_func7_0100000; // R sra wire rv32_or = rv32_op & rv32_func3_110 & rv32_func7_0000000; // R or wire rv32_and = rv32_op & rv32_func3_111 & rv32_func7_0000000; // R and wire rv32_nop = rv32_addi & rv32_rs1_x0 & rv32_rd_x0 & (~(|rv32_instr[31:20])); wire alu_op = (~rv32_sxxi_shamt_ilgl) & ( rv32_op_imm | rv32_op | rv32_auipc | rv32_lui | rv32_nop) ; wire need_imm; wire [`QBMCU_DECINFO_ALU_WIDTH-1:0] alu_info_bus; assign alu_info_bus[`QBMCU_DECINFO_GRP ] = `QBMCU_DECINFO_GRP_ALU; assign alu_info_bus[`QBMCU_DECINFO_RV32 ] = rv32; assign alu_info_bus[`QBMCU_DECINFO_ALU_ADD ] = rv32_add | rv32_addi | rv32_auipc ; assign alu_info_bus[`QBMCU_DECINFO_ALU_SUB ] = rv32_sub ; assign alu_info_bus[`QBMCU_DECINFO_ALU_SLT ] = rv32_slt | rv32_slti; assign alu_info_bus[`QBMCU_DECINFO_ALU_SLTU ] = rv32_sltu | rv32_sltiu; assign alu_info_bus[`QBMCU_DECINFO_ALU_XOR ] = rv32_xor | rv32_xori ; assign alu_info_bus[`QBMCU_DECINFO_ALU_SLL ] = rv32_sll | rv32_slli ; assign alu_info_bus[`QBMCU_DECINFO_ALU_SRL ] = rv32_srl | rv32_srli ; assign alu_info_bus[`QBMCU_DECINFO_ALU_SRA ] = rv32_sra | rv32_srai ; assign alu_info_bus[`QBMCU_DECINFO_ALU_OR ] = rv32_or | rv32_ori ; assign alu_info_bus[`QBMCU_DECINFO_ALU_AND ] = rv32_and | rv32_andi ; assign alu_info_bus[`QBMCU_DECINFO_ALU_LUI ] = rv32_lui ; assign alu_info_bus[`QBMCU_DECINFO_ALU_OP2IMM] = need_imm; assign alu_info_bus[`QBMCU_DECINFO_ALU_OP1PC ] = rv32_auipc; assign alu_info_bus[`QBMCU_DECINFO_ALU_NOP ] = rv32_nop; // =========================================================================== // Load/Store Instructions //wire rv32_lb = rv32_load & rv32_func3_000; // I lb //wire rv32_lh = rv32_load & rv32_func3_001; // I lh //wire rv32_lw = rv32_load & rv32_func3_010; // I lw //wire rv32_lbu = rv32_load & rv32_func3_100; // I lbu //wire rv32_lhu = rv32_load & rv32_func3_101; // I lhu //wire rv32_sb = rv32_store & rv32_func3_000; // S sb //wire rv32_sh = rv32_store & rv32_func3_001; // S sh //wire rv32_sw = rv32_store & rv32_func3_010; // S sw // Load/Store Data Size wire [1:0] lsu_info_size = rv32_func3[1:0] ; // Load/Store Data Sign wire lsu_info_usign = rv32_func3[2]; wire ldst_op = rv32_load | rv32_store; wire [`QBMCU_DECINFO_AGU_WIDTH-1:0] agu_info_bus; assign agu_info_bus[`QBMCU_DECINFO_GRP ] = `QBMCU_DECINFO_GRP_AGU; assign agu_info_bus[`QBMCU_DECINFO_RV32 ] = rv32; assign agu_info_bus[`QBMCU_DECINFO_AGU_LOAD ] = rv32_load ; assign agu_info_bus[`QBMCU_DECINFO_AGU_STORE ] = rv32_store ; assign agu_info_bus[`QBMCU_DECINFO_AGU_SIZE ] = lsu_info_size; assign agu_info_bus[`QBMCU_DECINFO_AGU_USIGN ] = lsu_info_usign; assign agu_info_bus[`QBMCU_DECINFO_AGU_OP2IMM ] = need_imm; // =========================================================================== // Expand instructions : WAIT SEND SENC EXIT EiXT_IRQ wire rv32_wait = rv32_custom0 & rv32_func3_000; //WAIT wire rv32_send = rv32_custom0 & rv32_func3_010; //SEND wire rv32_sendc = rv32_custom0 & rv32_func3_011; //WAIT wire rv32_exit = rv32_custom1 & rv32_func3_000; //EXIT wire rv32_exiti = rv32_custom1 & rv32_func3_001; //EXIT_IRQ wire ext_op = (~rv32_sxxi_shamt_ilgl) & ( rv32_wait | rv32_send | rv32_sendc | rv32_exit | rv32_exiti) ; wire [`QBMCU_DECINFO_EXT_WIDTH-1:0] ext_info_bus; assign ext_info_bus[`QBMCU_DECINFO_GRP ] = `QBMCU_DECINFO_GRP_EXT; assign ext_info_bus[`QBMCU_DECINFO_RV32 ] = rv32; assign ext_info_bus[`QBMCU_DECINFO_EXT_WAIT ] = rv32_wait; assign ext_info_bus[`QBMCU_DECINFO_EXT_SEND ] = rv32_send; assign ext_info_bus[`QBMCU_DECINFO_EXT_SENDC ] = rv32_sendc; assign ext_info_bus[`QBMCU_DECINFO_EXT_EXIT ] = rv32_exit; assign ext_info_bus[`QBMCU_DECINFO_EXT_EXITI ] = rv32_exiti ; assign ext_info_bus[`QBMCU_DECINFO_EXT_OP2IMM] = need_imm; // Reuse the common signals as much as possible to save gatecounts wire rv32_all0s_ilgl = rv32_func7_0000000 & rv32_rs2_x0 & rv32_rs1_x0 & rv32_func3_000 & rv32_rd_x0 & opcode_6_5_00 & opcode_4_2_000 & (opcode[1:0] == 2'b00); wire rv32_all1s_ilgl = rv32_func7_1111111 & rv32_rs2_x31 & rv32_rs1_x31 & rv32_func3_111 & rv32_rd_x31 & opcode_6_5_11 & opcode_4_2_111 & (opcode[1:0] == 2'b11); wire rv_all0s1s_ilgl = (rv32_all0s_ilgl | rv32_all1s_ilgl); // // All the RV32I need RD register except the // * Branch, Store, wire rv32_need_rd = (~rv32_rd_x0 ) & (~rv32_branch ) & (~rv32_store ) & (~rv32_custom1); // All the RV32I need RS1 register except the // * lui // * auipc // * jal //wire rv32_need_rs1 = (~rv32_rs1_x0) // & (~rv32_lui ) // & (~rv32_auipc ) // & (~rv32_jal ); // Following RV32IMA instructions need RS2 register // * branch // * store // * rv32_op //wire rv32_need_rs2 = (~rv32_rs2_x0) // & ((rv32_branch) // | (rv32_store ) // | (rv32_op )); wire [31:0] rv32_i_imm = { {20{rv32_instr[31]}} , rv32_instr[31:20] }; wire [31:0] rv32_s_imm = { {20{rv32_instr[31]}} , rv32_instr[31:25] , rv32_instr[11:7] }; wire [31:0] rv32_b_imm = { {19{rv32_instr[31]}} , rv32_instr[31] , rv32_instr[7] , rv32_instr[30:25] , rv32_instr[11:8] , 1'b0 }; wire [31:0] rv32_u_imm = {rv32_instr[31:12],12'b0}; wire [31:0] rv32_j_imm = { {11{rv32_instr[31]}} , rv32_instr[31] , rv32_instr[19:12] , rv32_instr[20] , rv32_instr[30:21] , 1'b0 }; //expand immediate operands wire [31:0] rv32_e_imm = rv32_i_imm; // It will select i-type immediate when // * rv32_op_imm // * rv32_jalr // * rv32_load wire rv32_imm_sel_i = rv32_op_imm | rv32_jalr | rv32_load; //wire rv32_imm_sel_jalr = rv32_jalr; //wire [31:0] rv32_jalr_imm = rv32_i_imm; // It will select u-type immediate when // * rv32_lui, rv32_auipc wire rv32_imm_sel_u = rv32_lui | rv32_auipc; // It will select j-type immediate when // * rv32_jal wire rv32_imm_sel_j = rv32_jal; //wire rv32_imm_sel_jal = rv32_jal; //wire [31:0] rv32_jal_imm = rv32_j_imm; // It will select b-type immediate when // * rv32_branch wire rv32_imm_sel_b = rv32_branch; //wire rv32_imm_sel_bxx = rv32_branch; //wire [31:0] rv32_bxx_imm = rv32_b_imm; // It will select s-type immediate when // * rv32_store wire rv32_imm_sel_s = rv32_store; // It will select e-type immediate when // * rv32_custom0 // * rv32_custom1 wire rv32_imm_sel_e = rv32_custom0 | rv32_custom1; wire [31:0] rv32_imm = ({32{rv32_imm_sel_i}} & rv32_i_imm) | ({32{rv32_imm_sel_s}} & rv32_s_imm) | ({32{rv32_imm_sel_b}} & rv32_b_imm) | ({32{rv32_imm_sel_u}} & rv32_u_imm) | ({32{rv32_imm_sel_j}} & rv32_j_imm) | ({32{rv32_imm_sel_e}} & rv32_e_imm) ; wire rv32_need_imm = rv32_imm_sel_i | rv32_imm_sel_s | rv32_imm_sel_b | rv32_imm_sel_u | rv32_imm_sel_j | rv32_imm_sel_e ; assign need_imm = rv32_need_imm ; //dec_o_imm sirv_gnrl_dfflr #(`QBMCU_XLEN) dec_o_imm_dfflr (dec_i_active_r, rv32_imm, dec_o_imm, clk, rst_n); //dec_o_pc sirv_gnrl_dfflr #(`QBMCU_PC_SIZE) dec_o_pc_dfflr (dec_i_active_r, dec_i_pc, dec_o_pc, clk, rst_n); assign dec_info_w = ({`QBMCU_DECINFO_WIDTH{alu_op}} & {{`QBMCU_DECINFO_WIDTH-`QBMCU_DECINFO_ALU_WIDTH{1'b0}},alu_info_bus}) | ({`QBMCU_DECINFO_WIDTH{ldst_op}} & {{`QBMCU_DECINFO_WIDTH-`QBMCU_DECINFO_AGU_WIDTH{1'b0}},agu_info_bus}) | ({`QBMCU_DECINFO_WIDTH{bjp_op}} & {{`QBMCU_DECINFO_WIDTH-`QBMCU_DECINFO_BJP_WIDTH{1'b0}},bjp_info_bus}) | ({`QBMCU_DECINFO_WIDTH{ext_op}} & {{`QBMCU_DECINFO_WIDTH-`QBMCU_DECINFO_EXT_WIDTH{1'b0}},ext_info_bus}) ; //dec_o_info sirv_gnrl_dfflr #(`QBMCU_DECINFO_WIDTH) dec_o_info_dfflr (dec_i_active_r, dec_info_w, dec_o_info, clk, rst_n); //dec_o_rs1idx sirv_gnrl_dfflr #(`QBMCU_RFIDX_WIDTH) dec_o_rs1idx_dfflr (dec_i_active_r, rv32_rs1[`QBMCU_RFIDX_WIDTH-1:0], dec_o_rs1idx, clk, rst_n); //dec_o_rs2idx sirv_gnrl_dfflr #(`QBMCU_RFIDX_WIDTH) dec_o_rs2idx_dfflr (dec_i_active_r, rv32_rs2[`QBMCU_RFIDX_WIDTH-1:0], dec_o_rs2idx, clk, rst_n); //dec_o_rdidx sirv_gnrl_dfflr #(`QBMCU_RFIDX_WIDTH) dec_o_rdidx_dfflr (dec_i_active_r, rv32_rd[`QBMCU_RFIDX_WIDTH-1:0], dec_o_rdidx, clk, rst_n); //dec_o_rs1en //sirv_gnrl_dfflr #(1) dec_o_rs1en_dfflr (dec_i_active_r, rv32_need_rs1, dec_o_rs1en, clk, rst_n); //dec_o_rs2en //sirv_gnrl_dfflr #(1) dec_o_rs2en_dfflr (dec_i_active_r, rv32_need_rs2, dec_o_rs2en, clk, rst_n); //dec_o_rdwen sirv_gnrl_dfflr #(1) dec_o_rdwen_dfflr (dec_i_active_r, rv32_need_rd, dec_o_rdwen, clk, rst_n); wire legl_ops = alu_op | ldst_op | bjp_op | ext_op ; wire rv_index_ilgl = 1'b0; wire dec_ilegl_w = (rv_all0s1s_ilgl) | (rv_index_ilgl) | (rv32_sxxi_shamt_ilgl) | (~legl_ops); //dec_o_ilegl sirv_gnrl_dfflr #(1) dec_o_ilegl_dfflr (dec_i_active_r, dec_ilegl_w, dec_o_ilegl, clk, rst_n); endmodule `include "qbmcu_undefines.v"