//+FHDR-------------------------------------------------------------------------------------------------------- // Company: //----------------------------------------------------------------------------------------------------------------- // File Name : qbmcu_exu_dpath.v // Department : // Author : PWY // Author's Tel : //----------------------------------------------------------------------------------------------------------------- // Relese History // Version Date Author Description // 0.1 2024-03-13 PWY This module to implement the datapath of ALU //----------------------------------------------------------------------------------------------------------------- // 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_exu_dpath( ////////////////////////////////////////////////////// // ALU request the datapath input alu_req_alu ,input alu_req_alu_add ,input alu_req_alu_sub ,input alu_req_alu_xor ,input alu_req_alu_sll ,input alu_req_alu_srl ,input alu_req_alu_sra ,input alu_req_alu_or ,input alu_req_alu_and ,input alu_req_alu_slt ,input alu_req_alu_sltu ,input alu_req_alu_lui ,input [`QBMCU_XLEN-1:0] alu_req_alu_op1 ,input [`QBMCU_XLEN-1:0] alu_req_alu_op2 ,output [`QBMCU_XLEN-1:0] alu_req_alu_res ////////////////////////////////////////////////////// // BJP request the datapath ,input bjp_req_alu ,input [`QBMCU_XLEN-1:0] bjp_req_alu_op1 ,input [`QBMCU_XLEN-1:0] bjp_req_alu_op2 ,input bjp_req_alu_cmp_eq ,input bjp_req_alu_cmp_ne ,input bjp_req_alu_cmp_lt ,input bjp_req_alu_cmp_gt ,input bjp_req_alu_cmp_ltu ,input bjp_req_alu_cmp_gtu ,input bjp_req_alu_add ,output bjp_req_alu_cmp_res ,output [`QBMCU_XLEN-1:0] bjp_req_alu_add_res ); wire [`QBMCU_XLEN-1:0] mux_op1; wire [`QBMCU_XLEN-1:0] mux_op2; wire [`QBMCU_XLEN-1:0] misc_op1 = mux_op1[`QBMCU_XLEN-1:0]; wire [`QBMCU_XLEN-1:0] misc_op2 = mux_op2[`QBMCU_XLEN-1:0]; // Only the regular ALU use shifter wire [`QBMCU_XLEN-1:0] shifter_op1 = alu_req_alu_op1[`QBMCU_XLEN-1:0]; wire [`QBMCU_XLEN-1:0] shifter_op2 = alu_req_alu_op2[`QBMCU_XLEN-1:0]; wire op_add; wire op_sub; wire op_addsub = op_add | op_sub; wire op_or; wire op_xor; wire op_and; wire op_sll; wire op_srl; wire op_sra; wire op_slt; wire op_sltu; wire op_mvop2; wire op_cmp_eq ; wire op_cmp_ne ; wire op_cmp_lt ; wire op_cmp_gt ; wire op_cmp_ltu; wire op_cmp_gtu; wire cmp_res; ////////////////////////////////////////////////////////////// // Impelment the Left-Shifter // // The Left-Shifter will be used to handle the shift op wire [`QBMCU_XLEN-1:0] shifter_in1; wire [5-1:0] shifter_in2; wire [`QBMCU_XLEN-1:0] shifter_res; wire op_shift = op_sra | op_sll | op_srl; // Make sure to use logic-gating to gateoff the assign shifter_in1 = {`QBMCU_XLEN{op_shift}} & // In order to save area and just use one left-shifter, we // convert the right-shift op into left-shift operation ( (op_sra | op_srl) ? { shifter_op1[00],shifter_op1[01],shifter_op1[02],shifter_op1[03], shifter_op1[04],shifter_op1[05],shifter_op1[06],shifter_op1[07], shifter_op1[08],shifter_op1[09],shifter_op1[10],shifter_op1[11], shifter_op1[12],shifter_op1[13],shifter_op1[14],shifter_op1[15], shifter_op1[16],shifter_op1[17],shifter_op1[18],shifter_op1[19], shifter_op1[20],shifter_op1[21],shifter_op1[22],shifter_op1[23], shifter_op1[24],shifter_op1[25],shifter_op1[26],shifter_op1[27], shifter_op1[28],shifter_op1[29],shifter_op1[30],shifter_op1[31] } : shifter_op1 ); assign shifter_in2 = {5{op_shift}} & shifter_op2[4:0]; assign shifter_res = (shifter_in1 << shifter_in2); wire [`QBMCU_XLEN-1:0] sll_res = shifter_res; wire [`QBMCU_XLEN-1:0] srl_res = { shifter_res[00],shifter_res[01],shifter_res[02],shifter_res[03], shifter_res[04],shifter_res[05],shifter_res[06],shifter_res[07], shifter_res[08],shifter_res[09],shifter_res[10],shifter_res[11], shifter_res[12],shifter_res[13],shifter_res[14],shifter_res[15], shifter_res[16],shifter_res[17],shifter_res[18],shifter_res[19], shifter_res[20],shifter_res[21],shifter_res[22],shifter_res[23], shifter_res[24],shifter_res[25],shifter_res[26],shifter_res[27], shifter_res[28],shifter_res[29],shifter_res[30],shifter_res[31] }; wire [`QBMCU_XLEN-1:0] eff_mask = (~(`QBMCU_XLEN'b0)) >> shifter_in2; wire [`QBMCU_XLEN-1:0] sra_res = (srl_res & eff_mask) | ({32{shifter_op1[31]}} & (~eff_mask)); ////////////////////////////////////////////////////////////// // Impelment the Adder // // The Adder will be reused to handle the add/sub/compare op // all other unit request ALU-adder with 32bits opereand without sign extended wire op_unsigned = op_sltu | op_cmp_ltu | op_cmp_gtu; wire [`QBMCU_ALU_ADDER_WIDTH-1:0] misc_adder_op1 = {{`QBMCU_ALU_ADDER_WIDTH-`QBMCU_XLEN{(~op_unsigned) & misc_op1[`QBMCU_XLEN-1]}},misc_op1}; wire [`QBMCU_ALU_ADDER_WIDTH-1:0] misc_adder_op2 = {{`QBMCU_ALU_ADDER_WIDTH-`QBMCU_XLEN{(~op_unsigned) & misc_op2[`QBMCU_XLEN-1]}},misc_op2}; wire [`QBMCU_ALU_ADDER_WIDTH-1:0] adder_op1 = misc_adder_op1; wire [`QBMCU_ALU_ADDER_WIDTH-1:0] adder_op2 = misc_adder_op2; wire adder_cin; wire [`QBMCU_ALU_ADDER_WIDTH-1:0] adder_in1; wire [`QBMCU_ALU_ADDER_WIDTH-1:0] adder_in2; wire [`QBMCU_ALU_ADDER_WIDTH-1:0] adder_res; wire adder_add; wire adder_sub; assign adder_add = op_add; assign adder_sub = ( // The original sub instruction (op_sub) // The compare lt or gt instruction | (op_cmp_lt | op_cmp_gt | op_cmp_ltu | op_cmp_gtu | op_slt | op_sltu )); wire adder_addsub = adder_add | adder_sub; // Make sure to use logic-gating to gateoff the assign adder_in1 = {`QBMCU_ALU_ADDER_WIDTH{adder_addsub}} & (adder_op1); assign adder_in2 = {`QBMCU_ALU_ADDER_WIDTH{adder_addsub}} & (adder_sub ? (~adder_op2) : adder_op2); assign adder_cin = adder_addsub & adder_sub; assign adder_res = adder_in1 + adder_in2 + adder_cin; ////////////////////////////////////////////////////////////// // Impelment the XOR-er // // The XOR-er will be reused to handle the XOR and compare op wire [`QBMCU_XLEN-1:0] xorer_in1; wire [`QBMCU_XLEN-1:0] xorer_in2; wire xorer_op = op_xor // The compare eq or ne instruction | (op_cmp_eq | op_cmp_ne); // Make sure to use logic-gating to gateoff the assign xorer_in1 = {`QBMCU_XLEN{xorer_op}} & misc_op1; assign xorer_in2 = {`QBMCU_XLEN{xorer_op}} & misc_op2; wire [`QBMCU_XLEN-1:0] xorer_res = xorer_in1 ^ xorer_in2; // The OR and AND is too light-weight, so no need to gate off wire [`QBMCU_XLEN-1:0] orer_res = misc_op1 | misc_op2; wire [`QBMCU_XLEN-1:0] ander_res = misc_op1 & misc_op2; ////////////////////////////////////////////////////////////// // Generate the CMP operation result // It is Non-Equal if the XOR result have any bit non-zero wire neq = (|xorer_res); wire cmp_res_ne = (op_cmp_ne & neq); // It is Equal if it is not Non-Equal wire cmp_res_eq = op_cmp_eq & (~neq); // It is Less-Than if the adder result is negative wire cmp_res_lt = op_cmp_lt & adder_res[`QBMCU_XLEN]; wire cmp_res_ltu = op_cmp_ltu & adder_res[`QBMCU_XLEN]; // It is Greater-Than if the adder result is postive wire op1_gt_op2 = (~adder_res[`QBMCU_XLEN]); wire cmp_res_gt = op_cmp_gt & op1_gt_op2; wire cmp_res_gtu = op_cmp_gtu & op1_gt_op2; assign cmp_res = cmp_res_eq | cmp_res_ne | cmp_res_lt | cmp_res_gt | cmp_res_ltu | cmp_res_gtu; ////////////////////////////////////////////////////////////// // Generate the mvop2 result // Just directly use op2 since the op2 will be the immediate wire [`QBMCU_XLEN-1:0] mvop2_res = misc_op2; ////////////////////////////////////////////////////////////// // Generate the SLT and SLTU result // Just directly use op2 since the op2 will be the immediate wire op_slttu = (op_slt | op_sltu); // The SLT and SLTU is reusing the adder to do the comparasion // It is Less-Than if the adder result is negative wire slttu_cmp_lt = op_slttu & adder_res[`QBMCU_XLEN]; wire [`QBMCU_XLEN-1:0] slttu_res = slttu_cmp_lt ? `QBMCU_XLEN'b1 : `QBMCU_XLEN'b0; ////////////////////////////////////////////////////////////// // Generate the final result wire [`QBMCU_XLEN-1:0] alu_dpath_res = ({`QBMCU_XLEN{op_or }} & orer_res ) | ({`QBMCU_XLEN{op_and }} & ander_res) | ({`QBMCU_XLEN{op_xor }} & xorer_res) | ({`QBMCU_XLEN{op_addsub }} & adder_res[`QBMCU_XLEN-1:0]) | ({`QBMCU_XLEN{op_srl }} & srl_res) | ({`QBMCU_XLEN{op_sll }} & sll_res) | ({`QBMCU_XLEN{op_sra }} & sra_res) | ({`QBMCU_XLEN{op_mvop2 }} & mvop2_res) | ({`QBMCU_XLEN{op_slttu }} & slttu_res) ; ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // The ALU-Datapath Mux for the requestors localparam DPATH_MUX_WIDTH = ((`QBMCU_XLEN*2)+17); assign { mux_op1 ,mux_op2 ,op_add ,op_sub ,op_or ,op_xor ,op_and ,op_sll ,op_srl ,op_sra ,op_slt ,op_sltu ,op_mvop2 ,op_cmp_eq ,op_cmp_ne ,op_cmp_lt ,op_cmp_gt ,op_cmp_ltu ,op_cmp_gtu } = ({DPATH_MUX_WIDTH{alu_req_alu}} & { alu_req_alu_op1 ,alu_req_alu_op2 ,alu_req_alu_add ,alu_req_alu_sub ,alu_req_alu_or ,alu_req_alu_xor ,alu_req_alu_and ,alu_req_alu_sll ,alu_req_alu_srl ,alu_req_alu_sra ,alu_req_alu_slt ,alu_req_alu_sltu ,alu_req_alu_lui// LUI just move-Op2 operation ,1'b0 ,1'b0 ,1'b0 ,1'b0 ,1'b0 ,1'b0 }) | ({DPATH_MUX_WIDTH{bjp_req_alu}} & { bjp_req_alu_op1 ,bjp_req_alu_op2 ,bjp_req_alu_add ,1'b0 ,1'b0 ,1'b0 ,1'b0 ,1'b0 ,1'b0 ,1'b0 ,1'b0 ,1'b0 ,1'b0 ,bjp_req_alu_cmp_eq ,bjp_req_alu_cmp_ne ,bjp_req_alu_cmp_lt ,bjp_req_alu_cmp_gt ,bjp_req_alu_cmp_ltu ,bjp_req_alu_cmp_gtu }) ; assign alu_req_alu_res = alu_dpath_res[`QBMCU_XLEN-1:0]; assign bjp_req_alu_add_res = alu_dpath_res[`QBMCU_XLEN-1:0]; assign bjp_req_alu_cmp_res = cmp_res; endmodule `include "qbmcu_undefines.v"