2021-04-04 18:09:13 +00:00
|
|
|
|
|
|
|
module fctrl (
|
|
|
|
input logic [6:0] Funct7D,
|
|
|
|
input logic [6:0] OpD,
|
|
|
|
input logic [4:0] Rs2D,
|
2021-05-01 02:18:01 +00:00
|
|
|
input logic [2:0] Funct3D,
|
|
|
|
input logic [2:0] FRM_REGW,
|
|
|
|
output logic IllegalFPUInstrD,
|
2021-05-26 00:04:34 +00:00
|
|
|
output logic FWriteEnD,
|
|
|
|
output logic FDivStartD,
|
2021-05-01 02:18:01 +00:00
|
|
|
output logic [2:0] FResultSelD,
|
2021-05-26 00:04:34 +00:00
|
|
|
output logic [3:0] FOpCtrlD,
|
2021-04-04 18:09:13 +00:00
|
|
|
output logic FmtD,
|
2021-05-01 02:18:01 +00:00
|
|
|
output logic [2:0] FrmD,
|
2021-05-21 02:17:59 +00:00
|
|
|
output logic [1:0] FMemRWD,
|
2021-05-26 00:04:34 +00:00
|
|
|
output logic FOutputInput2D,
|
|
|
|
output logic FInput2UsedD, FInput3UsedD,
|
2021-05-21 02:17:59 +00:00
|
|
|
output logic FWriteIntD);
|
2021-04-04 18:09:13 +00:00
|
|
|
|
|
|
|
|
2021-05-21 02:17:59 +00:00
|
|
|
logic IllegalFPUInstr1D, IllegalFPUInstr2D;
|
2021-04-04 18:09:13 +00:00
|
|
|
//precision is taken directly from instruction
|
|
|
|
assign FmtD = Funct7D[0];
|
2021-05-01 02:18:01 +00:00
|
|
|
// *** fix rounding for dynamic rounding
|
|
|
|
assign FrmD = &Funct3D ? FRM_REGW : Funct3D;
|
2021-04-04 18:09:13 +00:00
|
|
|
|
|
|
|
//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
|
2021-05-01 02:18:01 +00:00
|
|
|
7'b1010011 : isFP = 1'b1;
|
|
|
|
7'b1000011 : isFP = 1'b1;
|
|
|
|
7'b1000111 : isFP = 1'b1;
|
|
|
|
7'b1001011 : isFP = 1'b1;
|
|
|
|
7'b1001111 : isFP = 1'b1;
|
|
|
|
7'b0100111 : isFP = 1'b1;
|
|
|
|
7'b0000111 : isFP = 1'b1;// KEP change 7'b1010011 to 7'b0000111
|
|
|
|
default : isFP = 1'b0;
|
2021-04-04 18:09:13 +00:00
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
2021-05-01 02:18:01 +00:00
|
|
|
|
2021-04-04 18:09:13 +00:00
|
|
|
|
|
|
|
//useful intermediary signals
|
|
|
|
//
|
|
|
|
//(mult only not supported in current datapath)
|
|
|
|
//set third FMA operand to zero in this case
|
|
|
|
//(or equivalent)
|
|
|
|
|
|
|
|
always_comb begin
|
2021-05-23 22:33:14 +00:00
|
|
|
//checks all but FMA/store/load
|
|
|
|
IllegalFPUInstr2D = 0;
|
|
|
|
if(OpD == 7'b1010011) begin
|
|
|
|
casez(Funct7D)
|
|
|
|
//compare
|
|
|
|
7'b10100?? : FResultSelD = 3'b001;
|
|
|
|
//div/sqrt
|
|
|
|
7'b0?011?? : FResultSelD = 3'b000;
|
|
|
|
//add/sub
|
|
|
|
7'b0000??? : FResultSelD = 3'b100;
|
|
|
|
//mult
|
|
|
|
7'b00010?? : FResultSelD = 3'b010;
|
|
|
|
//convert (not precision)
|
|
|
|
7'b110?0?? : FResultSelD = 3'b100;
|
|
|
|
//convert (precision)
|
|
|
|
7'b010000? : FResultSelD = 3'b100;
|
|
|
|
//Min/Max
|
|
|
|
7'b00101?? : FResultSelD = 3'b001;
|
|
|
|
//sign injection
|
|
|
|
7'b00100?? : FResultSelD = 3'b011;
|
|
|
|
//classify //only if funct3 = 001
|
|
|
|
7'b11100?? : if(Funct3D == 3'b001) FResultSelD = 3'b101;
|
|
|
|
//output ReadData1
|
|
|
|
else if (Funct7D[1] == 0) FResultSelD = 3'b111;
|
|
|
|
//output SrcW
|
|
|
|
7'b111100? : FResultSelD = 3'b110;
|
|
|
|
default : begin FResultSelD = 3'b0; IllegalFPUInstr2D = 1'b1; end
|
|
|
|
endcase
|
|
|
|
end
|
|
|
|
//FMA/store/load
|
|
|
|
else begin
|
|
|
|
case(OpD)
|
|
|
|
//4 FMA instructions
|
|
|
|
7'b1000011 : FResultSelD = 3'b010;
|
|
|
|
7'b1000111 : FResultSelD = 3'b010;
|
|
|
|
7'b1001011 : FResultSelD = 3'b010;
|
|
|
|
7'b1001111 : FResultSelD = 3'b010;
|
|
|
|
//store
|
|
|
|
7'b0100111 : FResultSelD = 3'b111;
|
|
|
|
//load
|
|
|
|
7'b0000111 : FResultSelD = 3'b111;
|
|
|
|
default : begin FResultSelD = 3'b0; IllegalFPUInstr2D = 1'b1; end
|
|
|
|
endcase
|
|
|
|
end
|
2021-04-04 18:09:13 +00:00
|
|
|
end
|
|
|
|
|
2021-05-26 00:04:34 +00:00
|
|
|
assign FOutputInput2D = OpD == 7'b0100111;
|
2021-05-01 02:18:01 +00:00
|
|
|
|
2021-05-26 00:04:34 +00:00
|
|
|
assign FMemRWD[0] = FOutputInput2D;
|
2021-05-21 02:17:59 +00:00
|
|
|
assign FMemRWD[1] = OpD == 7'b0000111;
|
2021-05-01 02:18:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-04 18:09:13 +00:00
|
|
|
//register is chosen based on operation performed
|
|
|
|
//----
|
|
|
|
//write selection is chosen in the same way as
|
|
|
|
//register selection
|
|
|
|
//
|
|
|
|
|
|
|
|
// reg/write sel logic and assignment
|
|
|
|
//
|
2021-05-01 02:18:01 +00:00
|
|
|
// 3'b000 = div/sqrt
|
|
|
|
// 3'b001 = cmp
|
|
|
|
// 3'b010 = fma/mult
|
|
|
|
// 3'b011 = sgn inj
|
|
|
|
// 3'b100 = add/sub/cnvt
|
|
|
|
// 3'b101 = classify
|
|
|
|
// 3'b110 = output SrcAW
|
|
|
|
// 3'b111 = output ReadData1
|
2021-04-04 18:09:13 +00:00
|
|
|
//
|
|
|
|
//reg select
|
|
|
|
|
|
|
|
//this value is used enough to be shorthand
|
|
|
|
|
|
|
|
//if op is div/sqrt - start div/sqrt
|
2021-05-26 00:04:34 +00:00
|
|
|
assign FDivStartD = ~|FResultSelD; // is FResultSelD == 000
|
2021-04-04 18:09:13 +00:00
|
|
|
|
|
|
|
//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
|
2021-05-26 00:04:34 +00:00
|
|
|
// assign FOpCtrlD[3] = 1'b0;
|
2021-04-04 18:09:13 +00:00
|
|
|
//
|
|
|
|
//
|
|
|
|
|
2021-05-01 02:18:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
always_comb begin
|
2021-05-21 02:17:59 +00:00
|
|
|
IllegalFPUInstr1D = 0;
|
2021-05-26 00:04:34 +00:00
|
|
|
FInput3UsedD = 0;
|
2021-05-01 02:18:01 +00:00
|
|
|
case (FResultSelD)
|
|
|
|
// div/sqrt
|
|
|
|
// fdiv = ???0
|
|
|
|
// fsqrt = ???1
|
2021-05-26 00:04:34 +00:00
|
|
|
3'b000 : begin FOpCtrlD = {3'b0, Funct7D[5]}; FInput2UsedD = ~Funct7D[5]; end
|
2021-05-01 02:18:01 +00:00
|
|
|
// cmp
|
|
|
|
// fmin = ?100
|
|
|
|
// fmax = ?101
|
|
|
|
// feq = ?010
|
|
|
|
// flt = ?001
|
|
|
|
// fle = ?011
|
|
|
|
// {?, is min or max, is eq or le, is lt or le}
|
2021-05-26 00:04:34 +00:00
|
|
|
3'b001 : begin FOpCtrlD = {1'b0, Funct7D[2], ~Funct3D[0], ~(|Funct3D[2:1])}; FInput2UsedD = 1'b1; end
|
2021-05-01 02:18:01 +00:00
|
|
|
//fma/mult
|
|
|
|
// fmadd = ?000
|
|
|
|
// fmsub = ?001
|
|
|
|
// fnmadd = ?010
|
|
|
|
// fnmsub = ?011
|
|
|
|
// fmul = ?100
|
|
|
|
// {?, is mul, is negitive, is sub}
|
2021-05-26 00:04:34 +00:00
|
|
|
3'b010 : begin FOpCtrlD = {1'b0, OpD[4:2]}; FInput2UsedD = 1'b1; FInput3UsedD = ~OpD[4]; end
|
2021-05-01 02:18:01 +00:00
|
|
|
// sgn inj
|
|
|
|
// fsgnj = ??00
|
|
|
|
// fsgnjn = ??01
|
|
|
|
// fsgnjx = ??10
|
2021-05-26 00:04:34 +00:00
|
|
|
3'b011 : begin FOpCtrlD = {2'b0, Funct3D[1:0]}; FInput2UsedD = 1'b1; end
|
2021-05-01 02:18:01 +00:00
|
|
|
// add/sub/cnvt
|
|
|
|
// fadd = 0000
|
|
|
|
// fsub = 0001
|
|
|
|
// fcvt.w.s = 0100
|
|
|
|
// fcvt.wu.s = 0101
|
|
|
|
// fcvt.s.w = 0110
|
|
|
|
// fcvt.s.wu = 0111
|
|
|
|
// fcvt.s.d = 0010
|
|
|
|
// fcvt.w.d = 1100
|
|
|
|
// fcvt.wu.d = 1101
|
|
|
|
// fcvt.d.w = 1110
|
|
|
|
// fcvt.d.wu = 1111
|
|
|
|
// fcvt.d.s = 1000
|
|
|
|
// { is double and not add/sub, is to/from int, is to int or float to double, is unsigned or sub
|
2021-05-26 16:33:33 +00:00
|
|
|
3'b100 : begin FOpCtrlD = {Funct7D[0]&Funct7D[5], Funct7D[6], Funct7D[3] | (~Funct7D[6]&Funct7D[5]&~Funct7D[0]), (Rs2D[0]&Funct7D[5])|(Funct7D[2]&~Funct7D[5])}; FInput2UsedD = ~Funct7D[5]; end
|
2021-05-01 02:18:01 +00:00
|
|
|
// classify {?, ?, ?, ?}
|
2021-05-26 00:04:34 +00:00
|
|
|
3'b101 : begin FOpCtrlD = 4'b0; FInput2UsedD = 1'b0; end
|
2021-05-01 02:18:01 +00:00
|
|
|
// output SrcAW
|
|
|
|
// fmv.w.x = ???0
|
|
|
|
// fmv.w.d = ???1
|
2021-05-26 00:04:34 +00:00
|
|
|
3'b110 : begin FOpCtrlD = {3'b0, Funct7D[0]}; FInput2UsedD = 1'b0; end
|
2021-05-21 02:17:59 +00:00
|
|
|
// output Input1
|
2021-05-01 02:18:01 +00:00
|
|
|
// flw = ?000
|
2021-05-21 02:17:59 +00:00
|
|
|
// fld = ?001
|
|
|
|
// fsw = ?010 // output Input2
|
|
|
|
// fsd = ?011 // output Input2
|
2021-05-01 02:18:01 +00:00
|
|
|
// fmv.x.w = ?100
|
2021-05-24 18:44:30 +00:00
|
|
|
// fmv.x.d = ?101
|
2021-05-26 00:04:34 +00:00
|
|
|
// {?, is mv, is store, is double or fmv}
|
|
|
|
3'b111 : begin FOpCtrlD = {1'b0, OpD[6:5], Funct3D[0] | (OpD[6]&Funct7D[0])}; FInput2UsedD = OpD[5]; end
|
|
|
|
default : begin FOpCtrlD = 4'b0; IllegalFPUInstr1D = 1'b1; FInput2UsedD = 1'b0; end
|
2021-05-01 02:18:01 +00:00
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
2021-05-21 02:17:59 +00:00
|
|
|
assign IllegalFPUInstrD = IllegalFPUInstr1D | IllegalFPUInstr2D;
|
2021-04-04 18:09:13 +00:00
|
|
|
//write to integer source if conv to int occurs
|
|
|
|
//AND of Funct7 for int results
|
2021-05-01 02:18:01 +00:00
|
|
|
// is add/cvt and is to int or is classify or is cmp and not max/min or is output ReadData1 and is mv
|
2021-05-21 02:17:59 +00:00
|
|
|
assign FWriteIntD = ((FResultSelD == 3'b100)&Funct7D[3]) | (FResultSelD == 3'b101) | ((FResultSelD == 3'b001)&~Funct7D[2]) | ((FResultSelD == 3'b111)&OpD[6]);
|
2021-05-01 02:18:01 +00:00
|
|
|
// if not writting to int reg and not a store function and not move
|
2021-05-26 00:04:34 +00:00
|
|
|
assign FWriteEnD = ~FWriteIntD & ~OpD[5] & ~((FResultSelD == 3'b111)&OpD[6]) & isFP;
|
2021-04-04 18:09:13 +00:00
|
|
|
endmodule
|