forked from Github_Repos/cvw
FPU Assembly tests
This commit is contained in:
parent
6be5bb1f84
commit
ec82453ba1
29
wally-pipelined/src/fpu/fcsr.sv
Normal file
29
wally-pipelined/src/fpu/fcsr.sv
Normal file
@ -0,0 +1,29 @@
|
||||
`include "../../config/rv64icfd/wally-config.vh"
|
||||
|
||||
module fcsr(
|
||||
input logic [2:0] frm,
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic write,
|
||||
input logic [4:0] flags,
|
||||
output logic [31:0] readData);
|
||||
|
||||
//register I/O assignment
|
||||
logic [31:0] regInput;
|
||||
logic [31:0] regOutput;
|
||||
|
||||
//no L instruction support
|
||||
//only last 8 bits used for FCSR
|
||||
|
||||
//latching input to write signal
|
||||
//AND clk and write and remove latch
|
||||
//for clk-based write
|
||||
assign regInput = (write) ? {24'h0,frm,flags} : regInput;
|
||||
|
||||
floprc #(32) (.clk(clk), .reset(reset), .clear(clear), .d(regInput), .q(regOutput));
|
||||
|
||||
assign readData = regOutput;
|
||||
|
||||
|
||||
endmodule
|
143
wally-pipelined/src/fpu/fctrl.sv
Normal file
143
wally-pipelined/src/fpu/fctrl.sv
Normal file
@ -0,0 +1,143 @@
|
||||
`include "../../config/rv64icfd/wally-config.vh"
|
||||
|
||||
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];
|
||||
|
||||
|
||||
assign regSelD[2] = isDivSqrt & ~isFMA;
|
||||
assign regSelD[1] = isFMA | isCmp;
|
||||
//AND of Funct7 for sign
|
||||
assign regSelD[0] = isCmp | isSign;
|
||||
|
||||
//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
|
||||
|
||||
assign OpCtrlD[3] = 1'b0;
|
||||
//if is positive sign injection OR is precision convert
|
||||
assign OpCtrlD[2] = (isSign & ~FrmW[0]) | (~Funct7D[6] & Funct7D[5] & ~Funct7D[4] & ~Funct7D[3] & ~Funct7D[2] & ~Funct7D[1]);
|
||||
//if is precision convert OR is sign xor
|
||||
assign OpCtrlD[1] = (isSign & FrmW[1]) | (~Funct7D[6] & Funct7D[5] & ~Funct7D[4] & ~Funct7D[3] & ~Funct7D[2] & ~Funct7D[1]);
|
||||
//if is sqrt OR is sub OR is single-precision cmp OR negation
|
||||
assign OpCtrlD[0] = (isDivSqrt & ~isFMA & Funct7D[6]) | (isAddSub & ~isFMA & Funct7D[2]) | (isCmp & ~isFMA & Funct7D[0]) | (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
|
59
wally-pipelined/src/fpu/fputop.sv
Normal file
59
wally-pipelined/src/fpu/fputop.sv
Normal file
@ -0,0 +1,59 @@
|
||||
`include "../../config/rv64icfd/wally-config.vh"
|
||||
|
||||
module fputop (
|
||||
input logic [2:0] FrmW,
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic [31:0] InstrD,
|
||||
input logic [`XLEN-1:0] SrcAE,
|
||||
input logic [`XLEN-1:0] SrcAW,
|
||||
output logic [31:0] FSROutW,
|
||||
output logic DivSqrtDoneE,
|
||||
output logic FInvalInstrD,
|
||||
output logic [`XLEN-1:0] FPUResultW);
|
||||
|
||||
/*fctrl ();
|
||||
|
||||
//regfile instantiation and decode stage
|
||||
//freg1adr ();
|
||||
|
||||
//freg2adr ();
|
||||
|
||||
//freg2adr ();
|
||||
|
||||
//freg2adr ();
|
||||
|
||||
freg3adr ();
|
||||
|
||||
//can easily be merged into privledged core
|
||||
//if necessary
|
||||
//fcsr ();
|
||||
|
||||
//E pipe and execution stage
|
||||
|
||||
fpdivsqrt ();
|
||||
|
||||
fma1 ();
|
||||
|
||||
fpaddcvt1 ();
|
||||
|
||||
fpcmp1 ();
|
||||
|
||||
fpsign ();
|
||||
|
||||
//M pipe and memory stage
|
||||
|
||||
fma2 ();
|
||||
|
||||
fpaddcvt2 ();
|
||||
|
||||
fpcmp2 ();
|
||||
|
||||
//W pipe and writeback stage
|
||||
|
||||
//flag signal mux
|
||||
|
||||
//result mux
|
||||
*/
|
||||
endmodule
|
513
wally-pipelined/src/fpu/freg.sv
Normal file
513
wally-pipelined/src/fpu/freg.sv
Normal file
@ -0,0 +1,513 @@
|
||||
`include "../../config/rv64icfd/wally-config.vh"
|
||||
|
||||
module freg1adr (
|
||||
input logic [2:0] frm,
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic [4:0] rd,
|
||||
input logic write,
|
||||
input logic [4:0] adr1,
|
||||
input logic [`XLEN-1:0] writeData,
|
||||
output logic [`XLEN-1:0] readData);
|
||||
|
||||
//note - not word aligning based on precision of
|
||||
//operation (frm)
|
||||
|
||||
//reg number should remain static, but it doesn't hurt
|
||||
//to parameterize
|
||||
parameter numRegs = 32;
|
||||
|
||||
//intermediary signals - useful for debugging
|
||||
//and easy instatiation of generated modules
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regInput;
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regOutput;
|
||||
|
||||
//generate fp registers themselves
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < numRegs; i = i + 1) begin:register
|
||||
|
||||
floprc #(`XLEN) (.clk(clk), .reset(reset), .clear(clear), .d(regInput[i][`XLEN-1:0]), .q(regOutput[i][`XLEN-1:0]));
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
//this could be done with:
|
||||
//
|
||||
//assign readData = regOutput[adr1];
|
||||
//
|
||||
//but always_comb allows for finer control
|
||||
|
||||
|
||||
//address decoder
|
||||
//only 1 for this fp register set
|
||||
//used with fpsign
|
||||
//defaults to outputting zeroes
|
||||
always_comb begin
|
||||
case(adr1)
|
||||
5'b00000 : readData = regOutput[0];
|
||||
5'b00001 : readData = regOutput[1];
|
||||
5'b00010 : readData = regOutput[2];
|
||||
5'b00011 : readData = regOutput[3];
|
||||
5'b00100 : readData = regOutput[4];
|
||||
5'b00101 : readData = regOutput[5];
|
||||
5'b00110 : readData = regOutput[6];
|
||||
5'b00111 : readData = regOutput[7];
|
||||
5'b01000 : readData = regOutput[8];
|
||||
5'b01001 : readData = regOutput[9];
|
||||
5'b01010 : readData = regOutput[10];
|
||||
5'b01011 : readData = regOutput[11];
|
||||
5'b01100 : readData = regOutput[12];
|
||||
5'b01101 : readData = regOutput[13];
|
||||
5'b01110 : readData = regOutput[14];
|
||||
5'b01111 : readData = regOutput[15];
|
||||
5'b10000 : readData = regOutput[16];
|
||||
5'b10001 : readData = regOutput[17];
|
||||
5'b10010 : readData = regOutput[18];
|
||||
5'b10011 : readData = regOutput[19];
|
||||
5'b10100 : readData = regOutput[20];
|
||||
5'b10101 : readData = regOutput[21];
|
||||
5'b10110 : readData = regOutput[22];
|
||||
5'b10111 : readData = regOutput[23];
|
||||
5'b11000 : readData = regOutput[24];
|
||||
5'b11001 : readData = regOutput[25];
|
||||
5'b11010 : readData = regOutput[26];
|
||||
5'b11011 : readData = regOutput[27];
|
||||
5'b11100 : readData = regOutput[28];
|
||||
5'b11101 : readData = regOutput[29];
|
||||
5'b11110 : readData = regOutput[30];
|
||||
5'b11111 : readData = regOutput[31];
|
||||
default : readData = `XLEN'h0;
|
||||
endcase
|
||||
end
|
||||
|
||||
//destination register decoder
|
||||
//only change input values on write
|
||||
//defaults to undefined with invalid address
|
||||
//
|
||||
//note - this is an intermediary signal, so
|
||||
//this is not asynch assignment. FF in flopr
|
||||
//will not update data until clk pulse
|
||||
always_comb begin
|
||||
if(write) begin
|
||||
case(rd)
|
||||
5'b00000 : regInput[0] = writeData;
|
||||
5'b00001 : regInput[1] = writeData;
|
||||
5'b00010 : regInput[2] = writeData;
|
||||
5'b00011 : regInput[3] = writeData;
|
||||
5'b00100 : regInput[4] = writeData;
|
||||
5'b00101 : regInput[5] = writeData;
|
||||
5'b00110 : regInput[6] = writeData;
|
||||
5'b00111 : regInput[7] = writeData;
|
||||
5'b01000 : regInput[8] = writeData;
|
||||
5'b01000 : regInput[9] = writeData;
|
||||
5'b01001 : regInput[10] = writeData;
|
||||
5'b01010 : regInput[11] = writeData;
|
||||
5'b01111 : regInput[12] = writeData;
|
||||
5'b01101 : regInput[13] = writeData;
|
||||
5'b01110 : regInput[14] = writeData;
|
||||
5'b01111 : regInput[15] = writeData;
|
||||
5'b10000 : regInput[16] = writeData;
|
||||
5'b10001 : regInput[17] = writeData;
|
||||
5'b10010 : regInput[18] = writeData;
|
||||
5'b10011 : regInput[19] = writeData;
|
||||
5'b10100 : regInput[20] = writeData;
|
||||
5'b10101 : regInput[21] = writeData;
|
||||
5'b10110 : regInput[22] = writeData;
|
||||
5'b10111 : regInput[23] = writeData;
|
||||
5'b11000 : regInput[24] = writeData;
|
||||
5'b11000 : regInput[25] = writeData;
|
||||
5'b11001 : regInput[26] = writeData;
|
||||
5'b11010 : regInput[27] = writeData;
|
||||
5'b11111 : regInput[28] = writeData;
|
||||
5'b11101 : regInput[29] = writeData;
|
||||
5'b11110 : regInput[30] = writeData;
|
||||
5'b11111 : regInput[31] = writeData;
|
||||
default : regInput[0] = `XLEN'hx;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//********
|
||||
//formatting separation
|
||||
//********
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module freg2adr (
|
||||
input logic [2:0] frm,
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic [4:0] rd,
|
||||
input logic write,
|
||||
input logic [4:0] adr1,
|
||||
input logic [4:0] adr2,
|
||||
input logic [`XLEN-1:0] writeData,
|
||||
output logic [`XLEN-1:0] readData1,
|
||||
output logic [`XLEN-1:0] readData2);
|
||||
|
||||
//note - not word aligning based on precision of
|
||||
//operation (frm)
|
||||
|
||||
//reg number should remain static, but it doesn't hurt
|
||||
//to parameterize
|
||||
parameter numRegs = 32;
|
||||
|
||||
//intermediary signals - useful for debugging
|
||||
//and easy instatiation of generated modules
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regInput;
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regOutput;
|
||||
|
||||
//generate fp registers themselves
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < numRegs; i = i + 1) begin:register
|
||||
|
||||
floprc #(`XLEN) (.clk(clk), .reset(reset), .clear(clear), .d(regInput[i][`XLEN-1:0]), .q(regOutput[i][`XLEN-1:0]));
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
//address decoder
|
||||
//2 are used for this fp register set
|
||||
//used with fpadd/cvt, fpdiv/sqrt, and fpcmp
|
||||
//defaults to outputting zeroes
|
||||
always_comb begin
|
||||
|
||||
//adderss 1 decoder
|
||||
case(adr1)
|
||||
5'b00000 : readData1 = regOutput[0];
|
||||
5'b00001 : readData1 = regOutput[1];
|
||||
5'b00010 : readData1 = regOutput[2];
|
||||
5'b00011 : readData1 = regOutput[3];
|
||||
5'b00100 : readData1 = regOutput[4];
|
||||
5'b00101 : readData1 = regOutput[5];
|
||||
5'b00110 : readData1 = regOutput[6];
|
||||
5'b00111 : readData1 = regOutput[7];
|
||||
5'b01000 : readData1 = regOutput[8];
|
||||
5'b01001 : readData1 = regOutput[9];
|
||||
5'b01010 : readData1 = regOutput[10];
|
||||
5'b01011 : readData1 = regOutput[11];
|
||||
5'b01100 : readData1 = regOutput[12];
|
||||
5'b01101 : readData1 = regOutput[13];
|
||||
5'b01110 : readData1 = regOutput[14];
|
||||
5'b01111 : readData1 = regOutput[15];
|
||||
5'b10000 : readData1 = regOutput[16];
|
||||
5'b10001 : readData1 = regOutput[17];
|
||||
5'b10010 : readData1 = regOutput[18];
|
||||
5'b10011 : readData1 = regOutput[19];
|
||||
5'b10100 : readData1 = regOutput[20];
|
||||
5'b10101 : readData1 = regOutput[21];
|
||||
5'b10110 : readData1 = regOutput[22];
|
||||
5'b10111 : readData1 = regOutput[23];
|
||||
5'b11000 : readData1 = regOutput[24];
|
||||
5'b11001 : readData1 = regOutput[25];
|
||||
5'b11010 : readData1 = regOutput[26];
|
||||
5'b11011 : readData1 = regOutput[27];
|
||||
5'b11100 : readData1 = regOutput[28];
|
||||
5'b11101 : readData1 = regOutput[29];
|
||||
5'b11110 : readData1 = regOutput[30];
|
||||
5'b11111 : readData1 = regOutput[31];
|
||||
default : readData1 = `XLEN'h0;
|
||||
endcase
|
||||
|
||||
//address 2 decoder
|
||||
case(adr2)
|
||||
5'b00000 : readData2 = regOutput[0];
|
||||
5'b00001 : readData2 = regOutput[1];
|
||||
5'b00010 : readData2 = regOutput[2];
|
||||
5'b00011 : readData2 = regOutput[3];
|
||||
5'b00100 : readData2 = regOutput[4];
|
||||
5'b00101 : readData2 = regOutput[5];
|
||||
5'b00110 : readData2 = regOutput[6];
|
||||
5'b00111 : readData2 = regOutput[7];
|
||||
5'b01000 : readData2 = regOutput[8];
|
||||
5'b01001 : readData2 = regOutput[9];
|
||||
5'b01010 : readData2 = regOutput[10];
|
||||
5'b01011 : readData2 = regOutput[11];
|
||||
5'b01100 : readData2 = regOutput[12];
|
||||
5'b01101 : readData2 = regOutput[13];
|
||||
5'b01110 : readData2 = regOutput[14];
|
||||
5'b01111 : readData2 = regOutput[15];
|
||||
5'b10000 : readData2 = regOutput[16];
|
||||
5'b10001 : readData2 = regOutput[17];
|
||||
5'b10010 : readData2 = regOutput[18];
|
||||
5'b10011 : readData2 = regOutput[19];
|
||||
5'b10100 : readData2 = regOutput[20];
|
||||
5'b10101 : readData2 = regOutput[21];
|
||||
5'b10110 : readData2 = regOutput[22];
|
||||
5'b10111 : readData2 = regOutput[23];
|
||||
5'b11000 : readData2 = regOutput[24];
|
||||
5'b11001 : readData2 = regOutput[25];
|
||||
5'b11010 : readData2 = regOutput[26];
|
||||
5'b11011 : readData2 = regOutput[27];
|
||||
5'b11100 : readData2 = regOutput[28];
|
||||
5'b11101 : readData2 = regOutput[29];
|
||||
5'b11110 : readData2 = regOutput[30];
|
||||
5'b11111 : readData2 = regOutput[31];
|
||||
default : readData2 = `XLEN'h0;
|
||||
endcase
|
||||
end
|
||||
|
||||
//destination register decoder
|
||||
//only change input values on write
|
||||
//defaults to undefined with invalid address
|
||||
//
|
||||
//note - this is an intermediary signal, so
|
||||
//this is not asynch assignment. FF in flopr
|
||||
//will not update data until clk pulse
|
||||
always_comb begin
|
||||
if(write) begin
|
||||
case(rd)
|
||||
5'b00000 : regInput[0] = writeData;
|
||||
5'b00001 : regInput[1] = writeData;
|
||||
5'b00010 : regInput[2] = writeData;
|
||||
5'b00011 : regInput[3] = writeData;
|
||||
5'b00100 : regInput[4] = writeData;
|
||||
5'b00101 : regInput[5] = writeData;
|
||||
5'b00110 : regInput[6] = writeData;
|
||||
5'b00111 : regInput[7] = writeData;
|
||||
5'b01000 : regInput[8] = writeData;
|
||||
5'b01000 : regInput[9] = writeData;
|
||||
5'b01001 : regInput[10] = writeData;
|
||||
5'b01010 : regInput[11] = writeData;
|
||||
5'b01111 : regInput[12] = writeData;
|
||||
5'b01101 : regInput[13] = writeData;
|
||||
5'b01110 : regInput[14] = writeData;
|
||||
5'b01111 : regInput[15] = writeData;
|
||||
5'b10000 : regInput[16] = writeData;
|
||||
5'b10001 : regInput[17] = writeData;
|
||||
5'b10010 : regInput[18] = writeData;
|
||||
5'b10011 : regInput[19] = writeData;
|
||||
5'b10100 : regInput[20] = writeData;
|
||||
5'b10101 : regInput[21] = writeData;
|
||||
5'b10110 : regInput[22] = writeData;
|
||||
5'b10111 : regInput[23] = writeData;
|
||||
5'b11000 : regInput[24] = writeData;
|
||||
5'b11000 : regInput[25] = writeData;
|
||||
5'b11001 : regInput[26] = writeData;
|
||||
5'b11010 : regInput[27] = writeData;
|
||||
5'b11111 : regInput[28] = writeData;
|
||||
5'b11101 : regInput[29] = writeData;
|
||||
5'b11110 : regInput[30] = writeData;
|
||||
5'b11111 : regInput[31] = writeData;
|
||||
default : regInput[0] = `XLEN'hx;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//********
|
||||
//formatting separation
|
||||
//********
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module freg3adr (
|
||||
input logic [2:0] frm,
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic [4:0] rd,
|
||||
input logic write,
|
||||
input logic [4:0] adr1,
|
||||
input logic [4:0] adr2,
|
||||
input logic [4:0] adr3,
|
||||
input logic [`XLEN-1:0] writeData,
|
||||
output logic [`XLEN-1:0] readData1,
|
||||
output logic [`XLEN-1:0] readData2,
|
||||
output logic [`XLEN-1:0] readData3);
|
||||
|
||||
//note - not word aligning based on precision of
|
||||
//operation (frm)
|
||||
|
||||
//reg number should remain static, but it doesn't hurt
|
||||
//to parameterize
|
||||
parameter numRegs = 32;
|
||||
|
||||
//intermediary signals - useful for debugging
|
||||
//and easy instatiation of generated modules
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regInput;
|
||||
logic [`XLEN-1:0] [numRegs-1:0] regOutput;
|
||||
|
||||
//generate fp registers themselves
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < numRegs; i = i + 1) begin:register
|
||||
|
||||
floprc #(`XLEN) (.clk(clk), .reset(reset), .clear(clear), .d(regInput[i][`XLEN-1:0]), .q(regOutput[i][`XLEN-1:0]));
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
//address decoder
|
||||
//3 are used for this fp register set
|
||||
//used exclusively for fma
|
||||
//defaults to outputting zeroes
|
||||
always_comb begin
|
||||
|
||||
//adderss 1 decoder
|
||||
case(adr1)
|
||||
5'b00000 : readData1 = regOutput[0];
|
||||
5'b00001 : readData1 = regOutput[1];
|
||||
5'b00010 : readData1 = regOutput[2];
|
||||
5'b00011 : readData1 = regOutput[3];
|
||||
5'b00100 : readData1 = regOutput[4];
|
||||
5'b00101 : readData1 = regOutput[5];
|
||||
5'b00110 : readData1 = regOutput[6];
|
||||
5'b00111 : readData1 = regOutput[7];
|
||||
5'b01000 : readData1 = regOutput[8];
|
||||
5'b01001 : readData1 = regOutput[9];
|
||||
5'b01010 : readData1 = regOutput[10];
|
||||
5'b01011 : readData1 = regOutput[11];
|
||||
5'b01100 : readData1 = regOutput[12];
|
||||
5'b01101 : readData1 = regOutput[13];
|
||||
5'b01110 : readData1 = regOutput[14];
|
||||
5'b01111 : readData1 = regOutput[15];
|
||||
5'b10000 : readData1 = regOutput[16];
|
||||
5'b10001 : readData1 = regOutput[17];
|
||||
5'b10010 : readData1 = regOutput[18];
|
||||
5'b10011 : readData1 = regOutput[19];
|
||||
5'b10100 : readData1 = regOutput[20];
|
||||
5'b10101 : readData1 = regOutput[21];
|
||||
5'b10110 : readData1 = regOutput[22];
|
||||
5'b10111 : readData1 = regOutput[23];
|
||||
5'b11000 : readData1 = regOutput[24];
|
||||
5'b11001 : readData1 = regOutput[25];
|
||||
5'b11010 : readData1 = regOutput[26];
|
||||
5'b11011 : readData1 = regOutput[27];
|
||||
5'b11100 : readData1 = regOutput[28];
|
||||
5'b11101 : readData1 = regOutput[29];
|
||||
5'b11110 : readData1 = regOutput[30];
|
||||
5'b11111 : readData1 = regOutput[31];
|
||||
default : readData1 = `XLEN'h0;
|
||||
endcase
|
||||
|
||||
//address 2 decoder
|
||||
case(adr2)
|
||||
5'b00000 : readData2 = regOutput[0];
|
||||
5'b00001 : readData2 = regOutput[1];
|
||||
5'b00010 : readData2 = regOutput[2];
|
||||
5'b00011 : readData2 = regOutput[3];
|
||||
5'b00100 : readData2 = regOutput[4];
|
||||
5'b00101 : readData2 = regOutput[5];
|
||||
5'b00110 : readData2 = regOutput[6];
|
||||
5'b00111 : readData2 = regOutput[7];
|
||||
5'b01000 : readData2 = regOutput[8];
|
||||
5'b01001 : readData2 = regOutput[9];
|
||||
5'b01010 : readData2 = regOutput[10];
|
||||
5'b01011 : readData2 = regOutput[11];
|
||||
5'b01100 : readData2 = regOutput[12];
|
||||
5'b01101 : readData2 = regOutput[13];
|
||||
5'b01110 : readData2 = regOutput[14];
|
||||
5'b01111 : readData2 = regOutput[15];
|
||||
5'b10000 : readData2 = regOutput[16];
|
||||
5'b10001 : readData2 = regOutput[17];
|
||||
5'b10010 : readData2 = regOutput[18];
|
||||
5'b10011 : readData2 = regOutput[19];
|
||||
5'b10100 : readData2 = regOutput[20];
|
||||
5'b10101 : readData2 = regOutput[21];
|
||||
5'b10110 : readData2 = regOutput[22];
|
||||
5'b10111 : readData2 = regOutput[23];
|
||||
5'b11000 : readData2 = regOutput[24];
|
||||
5'b11001 : readData2 = regOutput[25];
|
||||
5'b11010 : readData2 = regOutput[26];
|
||||
5'b11011 : readData2 = regOutput[27];
|
||||
5'b11100 : readData2 = regOutput[28];
|
||||
5'b11101 : readData2 = regOutput[29];
|
||||
5'b11110 : readData2 = regOutput[30];
|
||||
5'b11111 : readData2 = regOutput[31];
|
||||
default : readData2 = `XLEN'h0;
|
||||
endcase
|
||||
|
||||
//address 3 decoder
|
||||
case(adr3)
|
||||
5'b00000 : readData3 = regOutput[0];
|
||||
5'b00001 : readData3 = regOutput[1];
|
||||
5'b00010 : readData3 = regOutput[2];
|
||||
5'b00011 : readData3 = regOutput[3];
|
||||
5'b00100 : readData3 = regOutput[4];
|
||||
5'b00101 : readData3 = regOutput[5];
|
||||
5'b00110 : readData3 = regOutput[6];
|
||||
5'b00111 : readData3 = regOutput[7];
|
||||
5'b01000 : readData3 = regOutput[8];
|
||||
5'b01001 : readData3 = regOutput[9];
|
||||
5'b01010 : readData3 = regOutput[10];
|
||||
5'b01011 : readData3 = regOutput[11];
|
||||
5'b01100 : readData3 = regOutput[12];
|
||||
5'b01101 : readData3 = regOutput[13];
|
||||
5'b01110 : readData3 = regOutput[14];
|
||||
5'b01111 : readData3 = regOutput[15];
|
||||
5'b10000 : readData3 = regOutput[16];
|
||||
5'b10001 : readData3 = regOutput[17];
|
||||
5'b10010 : readData3 = regOutput[18];
|
||||
5'b10011 : readData3 = regOutput[19];
|
||||
5'b10100 : readData3 = regOutput[20];
|
||||
5'b10101 : readData3 = regOutput[21];
|
||||
5'b10110 : readData3 = regOutput[22];
|
||||
5'b10111 : readData3 = regOutput[23];
|
||||
5'b11000 : readData3 = regOutput[24];
|
||||
5'b11001 : readData3 = regOutput[25];
|
||||
5'b11010 : readData3 = regOutput[26];
|
||||
5'b11011 : readData3 = regOutput[27];
|
||||
5'b11100 : readData3 = regOutput[28];
|
||||
5'b11101 : readData3 = regOutput[29];
|
||||
5'b11110 : readData3 = regOutput[30];
|
||||
5'b11111 : readData3 = regOutput[31];
|
||||
default : readData3 = `XLEN'h0;
|
||||
endcase
|
||||
end
|
||||
|
||||
//destination register decoder
|
||||
//only change input values on write
|
||||
//defaults to undefined with invalid address
|
||||
//
|
||||
//note - this is an intermediary signal, so
|
||||
//this is not asynch assignment. FF in flopr
|
||||
//will not update data until clk pulse
|
||||
always_comb begin
|
||||
if(write) begin
|
||||
case(rd)
|
||||
5'b00000 : regInput[0] = writeData;
|
||||
5'b00001 : regInput[1] = writeData;
|
||||
5'b00010 : regInput[2] = writeData;
|
||||
5'b00011 : regInput[3] = writeData;
|
||||
5'b00100 : regInput[4] = writeData;
|
||||
5'b00101 : regInput[5] = writeData;
|
||||
5'b00110 : regInput[6] = writeData;
|
||||
5'b00111 : regInput[7] = writeData;
|
||||
5'b01000 : regInput[8] = writeData;
|
||||
5'b01000 : regInput[9] = writeData;
|
||||
5'b01001 : regInput[10] = writeData;
|
||||
5'b01010 : regInput[11] = writeData;
|
||||
5'b01111 : regInput[12] = writeData;
|
||||
5'b01101 : regInput[13] = writeData;
|
||||
5'b01110 : regInput[14] = writeData;
|
||||
5'b01111 : regInput[15] = writeData;
|
||||
5'b10000 : regInput[16] = writeData;
|
||||
5'b10001 : regInput[17] = writeData;
|
||||
5'b10010 : regInput[18] = writeData;
|
||||
5'b10011 : regInput[19] = writeData;
|
||||
5'b10100 : regInput[20] = writeData;
|
||||
5'b10101 : regInput[21] = writeData;
|
||||
5'b10110 : regInput[22] = writeData;
|
||||
5'b10111 : regInput[23] = writeData;
|
||||
5'b11000 : regInput[24] = writeData;
|
||||
5'b11000 : regInput[25] = writeData;
|
||||
5'b11001 : regInput[26] = writeData;
|
||||
5'b11010 : regInput[27] = writeData;
|
||||
5'b11111 : regInput[28] = writeData;
|
||||
5'b11101 : regInput[29] = writeData;
|
||||
5'b11110 : regInput[30] = writeData;
|
||||
5'b11111 : regInput[31] = writeData;
|
||||
default : regInput[0] = `XLEN'hx;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user