forked from Github_Repos/cvw
149 lines
5.4 KiB
Systemverilog
149 lines
5.4 KiB
Systemverilog
|
|
||
|
module fctrl (
|
||
|
input logic [6:0] Funct7D,
|
||
|
input logic [6:0] OpD,
|
||
|
input logic [4:0] Rs2D,
|
||
|
input logic [4:0] Rs1D,
|
||
|
input logic [2:0] FrmW,
|
||
|
output logic WriteEnD,
|
||
|
output logic DivSqrtStartD,
|
||
|
//output logic [2:0] regSelD,
|
||
|
output logic [2:0] WriteSelD,
|
||
|
output logic [3:0] OpCtrlD,
|
||
|
output logic FmtD,
|
||
|
output logic WriteIntD);
|
||
|
|
||
|
|
||
|
|
||
|
//precision is taken directly from instruction
|
||
|
assign FmtD = Funct7D[0];
|
||
|
|
||
|
//all subsequent logic is based on the table present
|
||
|
//in Section 5 of Wally Architecture Specification
|
||
|
|
||
|
//write is enabled for all fp instruciton op codes
|
||
|
//sans fp load
|
||
|
logic isFP, isFPLD;
|
||
|
always_comb begin
|
||
|
//case statement is easier to modify
|
||
|
//in case of errors
|
||
|
case(OpD)
|
||
|
//fp instructions sans load
|
||
|
7'b1010011 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||
|
7'b1000011 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||
|
7'b1000111 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||
|
7'b1001011 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||
|
7'b1001111 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||
|
7'b0100111 : begin isFP = 1'b1; isFPLD = 1'b0; end
|
||
|
//fp load
|
||
|
7'b1010011 : begin isFP = 1'b1; isFPLD = 1'b1; end
|
||
|
default : begin isFP = 1'b0; isFPLD = 1'b0; end
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
assign WriteEnD = isFP & ~isFPLD;
|
||
|
|
||
|
//useful intermediary signals
|
||
|
//
|
||
|
//(mult only not supported in current datapath)
|
||
|
//set third FMA operand to zero in this case
|
||
|
//(or equivalent)
|
||
|
logic isAddSub, isFMA, isMult, isDivSqrt, isCvt, isCmp, isFPSTR;
|
||
|
|
||
|
always_comb begin
|
||
|
//checks all but FMA/store/load
|
||
|
if(OpD == 7'b1010011) begin
|
||
|
case(Funct7D)
|
||
|
//compare
|
||
|
7'b10100?? : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b1; isFPSTR = 1'b0; end
|
||
|
//div/sqrt
|
||
|
7'b0?011?? : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b1; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||
|
//add/sub
|
||
|
7'b0000??? : begin isAddSub = 1'b1; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||
|
//mult
|
||
|
7'b00010?? : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b1; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||
|
//convert (not precision)
|
||
|
7'b110?0?? : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b1; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||
|
//convert (precision)
|
||
|
7'b010000? : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b1; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||
|
endcase
|
||
|
end
|
||
|
//FMA/store/load
|
||
|
else begin
|
||
|
case(OpD)
|
||
|
//4 FMA instructions
|
||
|
7'b1000011 : begin isAddSub = 1'b0; isFMA = 1'b1; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||
|
7'b1000111 : begin isAddSub = 1'b0; isFMA = 1'b1; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||
|
7'b1001011 : begin isAddSub = 1'b0; isFMA = 1'b1; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||
|
7'b1001111 : begin isAddSub = 1'b0; isFMA = 1'b1; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b0; end
|
||
|
//store (load already found)
|
||
|
7'b0100111 : begin isAddSub = 1'b0; isFMA = 1'b0; isMult = 1'b0; isDivSqrt = 1'b0; isCvt = 1'b0; isCmp = 1'b0; isFPSTR = 1'b1; end
|
||
|
endcase
|
||
|
end
|
||
|
end
|
||
|
|
||
|
//register is chosen based on operation performed
|
||
|
//----
|
||
|
//write selection is chosen in the same way as
|
||
|
//register selection
|
||
|
//
|
||
|
|
||
|
// reg/write sel logic and assignment
|
||
|
//
|
||
|
// 3'b000 = add/sub/cvt
|
||
|
// 3'b001 = sign
|
||
|
// 3'b010 = fma
|
||
|
// 3'b011 = cmp
|
||
|
// 3'b100 = div/sqrt
|
||
|
//
|
||
|
//reg select
|
||
|
|
||
|
//this value is used enough to be shorthand
|
||
|
logic isSign;
|
||
|
assign isSign = ~Funct7D[6] & ~Funct7D[5] & Funct7D[4] & ~Funct7D[3] & ~Funct7D[2];
|
||
|
|
||
|
//write select
|
||
|
assign WriteSelD[2] = isDivSqrt & ~isFMA;
|
||
|
assign WriteSelD[1] = isFMA | isCmp;
|
||
|
//AND of Funct7 for sign
|
||
|
assign WriteSelD[0] = isCmp | isSign;
|
||
|
|
||
|
//if op is div/sqrt - start div/sqrt
|
||
|
assign DivSqrtStartD = isDivSqrt & ~isFMA;
|
||
|
|
||
|
//operation control for each fp operation
|
||
|
//has to be expanded over standard to account for
|
||
|
//integrated fpadd/cvt
|
||
|
//
|
||
|
//will integrate FMA opcodes into design later
|
||
|
//
|
||
|
//conversion instructions will
|
||
|
//also need to be added later as I find the opcode
|
||
|
//version I used for this repo
|
||
|
|
||
|
//let's do separate SOP for each type of operation
|
||
|
// assign OpCtrlD[3] = 1'b0;
|
||
|
//
|
||
|
//
|
||
|
|
||
|
//add/cvt chooses unsigned conversion here
|
||
|
assign OpCtrlD[3] = (isAddSub & Rs2D[0]) | (isFMA & 1'b0) | (isDivSqrt & 1'b0) | (isCmp & 1'b0) | (isSign & 1'b0);
|
||
|
//add/cvt chooses FP/int or int/FP conversion
|
||
|
assign OpCtrlD[2] = (isAddSub & (Funct7D[6] & Funct7D[5] & ~Funct7D[4])) | (isFMA & 1'b0) | (isDivSqrt & 1'b0) | (isCmp & 1'b0) | (isSign & 1'b0);
|
||
|
//compare chooses equals
|
||
|
//sign chooses sgnjx
|
||
|
//add/cvt can chooses between abs/neg functions, but they aren't used in the
|
||
|
//wally-spec
|
||
|
assign OpCtrlD[1] = (isAddSub & 1'b0) | (isFMA & 1'b0) | (isDivSqrt & 1'b0) | (isCmp & FrmW[2]) | (isSign & FrmW[1]);
|
||
|
//divide chooses between div/sqrt
|
||
|
//compare chooses between LT and LE
|
||
|
//sign chooses between sgnj and sgnjn
|
||
|
//add/cvt chooses between add/sub or single-precision conversion
|
||
|
assign OpCtrlD[0] = (isAddSub & (Funct7D[2] | Funct7D[0])) | (isFMA & 1'b0) | (isDivSqrt & Funct7D[5]) | (isCmp & FrmW[1]) | (isSign & FrmW[0]);
|
||
|
|
||
|
//write to integer source if conv to int occurs
|
||
|
//AND of Funct7 for int results
|
||
|
assign WriteIntD = isCvt & (Funct7D[6] & Funct7D[5] & ~Funct7D[4] & ~Funct7D[3] & ~Funct7D[2] & ~Funct7D[1]);
|
||
|
|
||
|
endmodule
|