2021-04-04 18:09:13 +00:00
module fctrl (
2021-07-24 18:59:57 +00:00
input logic [ 6 : 0 ] Funct7D , // bits 31:25 of instruction - may contain percision
input logic [ 6 : 0 ] OpD , // bits 6:0 of instruction
input logic [ 4 : 0 ] Rs2D , // bits 24:20 of instruction
input logic [ 2 : 0 ] Funct3D , // bits 14:12 of instruction - may contain rounding mode
input logic [ 2 : 0 ] FRM_REGW , // rounding mode from CSR
output logic IllegalFPUInstrD , // Is the instruction an illegal fpu instruction
output logic FRegWriteD , // FP register write enable
output logic FDivStartD , // Start division or squareroot
output logic [ 2 : 0 ] FResultSelD , // select result to be written to fp register
output logic [ 3 : 0 ] FOpCtrlD , // chooses which opperation to do - specifics shown at bottom of module and in each unit
output logic [ 1 : 0 ] FResSelD , // select one of the results done in the memory stage
output logic [ 1 : 0 ] FIntResSelD , // select the result that will be written to the integer register
output logic FmtD , // precision - single-0 double-1
output logic [ 2 : 0 ] FrmD , // rounding mode 000 = rount to nearest, ties to even 001 = round twords zero 010 = round down 011 = round up 100 = round to nearest, ties to max magnitude
output logic FWriteIntD // is the result written to the integer register
) ;
2021-04-04 18:09:13 +00:00
2021-06-28 22:53:58 +00:00
`define FCTRLW 15
logic [ `FCTRLW - 1 : 0 ] ControlsD ;
// FPU Instruction Decoder
always_comb
case ( OpD )
2021-07-13 17:20:30 +00:00
// FRegWrite_FWriteInt_FResultSel_FOpCtrl_FResSel_FIntResSel_FDivStart_IllegalFPUInstr
2021-06-28 22:53:58 +00:00
7 'b0000111 : case ( Funct3D )
3 'b010 : ControlsD = `FCTRLW 'b1 _0_000_0000_00_00_0_0 ; // flw
3 'b011 : ControlsD = `FCTRLW 'b1 _0_000_0001_00_00_0_0 ; // fld
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
7 'b0100111 : case ( Funct3D )
3 'b010 : ControlsD = `FCTRLW 'b0 _0_000_0010_00_00_0_0 ; // fsw
3 'b011 : ControlsD = `FCTRLW 'b0 _0_000_0011_00_00_0_0 ; // fsd
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
7 'b1000011 : ControlsD = `FCTRLW 'b1 _0_001_0000_00_00_0_0 ; // fmadd
7 'b1000111 : ControlsD = `FCTRLW 'b1 _0_001_0001_00_00_0_0 ; // fmsub
7 'b1001011 : ControlsD = `FCTRLW 'b1 _0_001_0010_00_00_0_0 ; // fnmsub
7 'b1001111 : ControlsD = `FCTRLW 'b1 _0_001_0011_00_00_0_0 ; // fnmadd
7 'b1010011 : casez ( Funct7D )
7 'b00000 ? ? : ControlsD = `FCTRLW 'b1 _0_010_0000_00_00_0_0 ; // fadd
7 'b00001 ? ? : ControlsD = `FCTRLW 'b1 _0_010_0001_00_00_0_0 ; // fsub
7 'b00010 ? ? : ControlsD = `FCTRLW 'b1 _0_001_0100_00_00_0_0 ; // fmul
7 'b00011 ? ? : ControlsD = `FCTRLW 'b1 _0_011_0000_00_00_1_0 ; // fdiv
7 'b01011 ? ? : ControlsD = `FCTRLW 'b1 _0_011_0001_00_00_1_0 ; // fsqrt
7 'b00100 ? ? : case ( Funct3D )
3 'b000 : ControlsD = `FCTRLW 'b1 _0_100_0000_01_00_0_0 ; // fsgnj
3 'b001 : ControlsD = `FCTRLW 'b1 _0_100_0001_01_00_0_0 ; // fsgnjn
3 'b010 : ControlsD = `FCTRLW 'b1 _0_100_0010_01_00_0_0 ; // fsgnjx
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
7 'b00101 ? ? : case ( Funct3D )
3 'b000 : ControlsD = `FCTRLW 'b1 _0_100_0111_10_00_0_0 ; // fmin
3 'b001 : ControlsD = `FCTRLW 'b1 _0_100_0101_10_00_0_0 ; // fmax
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
7 'b10100 ? ? : case ( Funct3D )
3 'b010 : ControlsD = `FCTRLW 'b0 _1_100_0010_00_00_0_0 ; // feq
3 'b001 : ControlsD = `FCTRLW 'b0 _1_100_0001_00_00_0_0 ; // flt
3 'b000 : ControlsD = `FCTRLW 'b0 _1_100_0011_00_00_0_0 ; // fle
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
7 'b11100 ? ? : if ( Funct3D = = 3 'b001 )
ControlsD = `FCTRLW 'b0 _1_100_0000_00_10_0_0 ; // fclass
else if ( Funct3D [ 1 : 0 ] = = 2 'b00 ) ControlsD = `FCTRLW 'b0 _1_100_0100_00_01_0_0 ; // fmv.x.w
else if ( Funct3D [ 1 : 0 ] = = 2 'b01 ) ControlsD = `FCTRLW 'b0 _1_100_0101_00_01_0_0 ; // fmv.x.d
else ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
2021-07-11 22:06:33 +00:00
7 'b1101000 : case ( Rs2D [ 1 : 0 ] )
2 'b00 : ControlsD = `FCTRLW 'b1 _0_100_0001_11_00_0_0 ; // fcvt.s.w
2 'b01 : ControlsD = `FCTRLW 'b1 _0_100_0101_11_00_0_0 ; // fcvt.s.wu
2 'b10 : ControlsD = `FCTRLW 'b1 _0_100_1001_11_00_0_0 ; // fcvt.s.l
2 'b11 : ControlsD = `FCTRLW 'b1 _0_100_1101_11_00_0_0 ; // fcvt.s.lu
2021-06-28 22:53:58 +00:00
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
2021-07-11 22:06:33 +00:00
7 'b1100000 : case ( Rs2D [ 1 : 0 ] )
2 'b00 : ControlsD = `FCTRLW 'b0 _1_100_0010_11_11_0_0 ; // fcvt.w.s
2 'b01 : ControlsD = `FCTRLW 'b0 _1_100_0110_11_11_0_0 ; // fcvt.wu.s
2 'b10 : ControlsD = `FCTRLW 'b0 _1_100_1010_11_11_0_0 ; // fcvt.l.s
2 'b11 : ControlsD = `FCTRLW 'b0 _1_100_1110_11_11_0_0 ; // fcvt.lu.s
2021-06-28 22:53:58 +00:00
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
7 'b1111000 : ControlsD = `FCTRLW 'b1 _0_100_0000_00_00_0_0 ; // fmv.w.x
2021-07-11 22:06:33 +00:00
7 'b0100000 : ControlsD = `FCTRLW 'b1 _0_010_0111_00_00_0_0 ; // fcvt.s.d
7 'b1101001 : case ( Rs2D [ 1 : 0 ] )
2 'b00 : ControlsD = `FCTRLW 'b1 _0_100_0001_11_00_0_0 ; // fcvt.d.w
2 'b01 : ControlsD = `FCTRLW 'b1 _0_100_0101_11_00_0_0 ; // fcvt.d.wu
2 'b10 : ControlsD = `FCTRLW 'b1 _0_100_1001_11_00_0_0 ; // fcvt.d.l
2 'b11 : ControlsD = `FCTRLW 'b1 _0_100_1101_11_00_0_0 ; // fcvt.d.lu
2021-06-28 22:53:58 +00:00
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
2021-07-11 22:06:33 +00:00
7 'b1100001 : case ( Rs2D [ 1 : 0 ] )
2 'b00 : ControlsD = `FCTRLW 'b0 _1_100_0010_11_11_0_0 ; // fcvt.w.d
2 'b01 : ControlsD = `FCTRLW 'b0 _1_100_0110_11_11_0_0 ; // fcvt.wu.d
2 'b10 : ControlsD = `FCTRLW 'b0 _1_100_1010_11_11_0_0 ; // fcvt.l.d
2 'b11 : ControlsD = `FCTRLW 'b0 _1_100_1110_11_11_0_0 ; // fcvt.lu.d
2021-06-28 22:53:58 +00:00
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
7 'b1111001 : ControlsD = `FCTRLW 'b1 _0_100_0001_00_00_0_0 ; // fmv.d.x
2021-07-11 22:06:33 +00:00
7 'b0100001 : ControlsD = `FCTRLW 'b1 _0_010_0111_00_00_0_0 ; // fcvt.d.s
2021-06-28 22:53:58 +00:00
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
default : ControlsD = `FCTRLW 'b0 _0_000_0000_00_00_0_1 ; // non-implemented instruction
endcase
2021-07-24 18:59:57 +00:00
2021-06-28 22:53:58 +00:00
// unswizzle control bits
2021-07-13 17:20:30 +00:00
assign { FRegWriteD , FWriteIntD , FResultSelD , FOpCtrlD , FResSelD , FIntResSelD , FDivStartD , IllegalFPUInstrD } = ControlsD ;
2021-04-04 18:09:13 +00:00
2021-07-24 18:59:57 +00:00
// rounding modes:
// 000 - round to nearest, ties to even
// 001 - round twords 0 - round to min magnitude
// 010 - round down - round twords negitive infinity
// 011 - round up - round twords positive infinity
// 100 - round to nearest, ties to max magnitude - round to nearest, ties away from zero
// 111 - dynamic - choose FRM_REGW as rounding mode
2021-06-28 22:53:58 +00:00
assign FrmD = & Funct3D ? FRM_REGW : Funct3D ;
2021-05-01 02:18:01 +00:00
2021-06-28 22:53:58 +00:00
// Precision
2021-07-24 18:59:57 +00:00
// 0-single
// 1-double
2021-07-11 22:06:33 +00:00
assign FmtD = FResultSelD = = 3 'b000 ? Funct3D [ 0 ] : OpD [ 6 : 1 ] = = 6 'b010000 ? ~ Funct7D [ 0 ] : Funct7D [ 0 ] ;
2021-07-24 18:59:57 +00:00
// FResultSel:
// 000 - ReadRes - load
// 001 - FMARes - FMA and multiply
// 010 - FAddRes - add and fp to fp
// 011 - FDivRes - divide and squareroot
// 100 - FRes - anything that is written to the fp register and is ready in the memory stage
// FResSel:
// 00 - SrcA - move to fp register
// 01 - SgnRes - sign injection
// 10 - CmpRes - min/max
// 11 - CvtRes - convert to fp
// FIntResSel:
// 00 - CmpRes - less than, equal, or less than or equal
// 01 - FSrcX - move to int register
// 10 - ClassRes - classify
// 11 - CvtRes - convert to signed/unsigned int
// OpCtrl values:
2021-06-28 22:53:58 +00:00
// div/sqrt
2021-05-01 02:18:01 +00:00
// fdiv = ???0
// fsqrt = ???1
2021-06-28 22:53:58 +00:00
// cmp
2021-05-27 19:23:28 +00:00
// fmin = ?111
2021-05-01 02:18:01 +00:00
// fmax = ?101
// feq = ?010
// flt = ?001
// fle = ?011
2021-07-24 18:59:57 +00:00
// {?, is min or max, is eq or le, is lt or le}
2021-06-28 22:53:58 +00:00
//fma/mult
2021-05-01 02:18:01 +00:00
// fmadd = ?000
// fmsub = ?001
2021-06-04 18:00:11 +00:00
// fnmsub = ?010 -(a*b)+c
// fnmadd = ?011 -(a*b)-c
2021-05-01 02:18:01 +00:00
// fmul = ?100
2021-07-24 18:59:57 +00:00
// {?, is mul, negate product, negate addend}
2021-06-28 22:53:58 +00:00
// sgn inj
2021-05-01 02:18:01 +00:00
// fsgnj = ??00
// fsgnjn = ??01
// fsgnjx = ??10
2021-06-28 22:53:58 +00:00
// add/sub/cnvt
2021-05-01 02:18:01 +00:00
// fadd = 0000
// fsub = 0001
2021-07-24 18:59:57 +00:00
// fcvt.s.d = 0111
// fcvt.d.s = 0111
// Fmt controls the output for fp -> fp
// convert
2021-07-02 16:40:58 +00:00
// fcvt.w.s = 0010
// fcvt.wu.s = 0110
// fcvt.s.w = 0001
// fcvt.s.wu = 0101
// fcvt.l.s = 1010
// fcvt.lu.s = 1110
// fcvt.s.l = 1001
// fcvt.s.lu = 1101
2021-07-24 18:59:57 +00:00
// fcvt.w.d = 0010
2021-07-02 16:40:58 +00:00
// fcvt.wu.d = 0110
// fcvt.d.w = 0001
// fcvt.d.wu = 0101
// fcvt.l.d = 1010
// fcvt.lu.d = 1110
// fcvt.d.l = 1001
// fcvt.d.lu = 1101
2021-07-24 18:59:57 +00:00
// {long, unsigned, to int, from int}
2021-06-28 22:53:58 +00:00
2021-06-21 00:24:09 +00:00
2021-04-04 18:09:13 +00:00
endmodule