SPI_Test/rtl/qubitmcu/qbmcu_exu_dpath.v

366 lines
13 KiB
Verilog

//+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"