cvw/wally-pipelined/src/fpu/fctrl.sv

223 lines
6.9 KiB
Systemverilog
Raw Normal View History

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 = ?111
2021-05-01 02:18:01 +00:00
// 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