Parallel FSR's and F CTRL logic

This commit is contained in:
Brett Mathis 2021-02-04 02:25:55 -06:00
parent 088fbbcbf0
commit 11e2666bb2
5 changed files with 839 additions and 0 deletions

View file

@ -0,0 +1,89 @@
//////////////////////////////////////////
// wally-config.vh
//
// Written: David_Harris@hmc.edu 4 January 2021
// Modified: Brett Mathis
//
// Purpose: Specify which features are configured
// Macros to determine which modes are supported based on MISA
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
// RV32 or RV64: XLEN = 32 or 64
`define XLEN 64
//`define MISA (32'h00000104)
`define MISA (32'h00000104 | 1<<5 | 1<<18 | 1 << 20)
`define A_SUPPORTED ((`MISA >> 0) % 2 == 1)
`define C_SUPPORTED ((`MISA >> 2) % 2 == 1)
`define D_SUPPORTED ((`MISA >> 3) % 2 == 1)
`define F_SUPPORTED ((`MISA >> 5) % 2 == 1)
`define M_SUPPORTED ((`MISA >> 12) % 2 == 1)
`define S_SUPPORTED ((`MISA >> 18) % 2 == 1)
`define U_SUPPORTED ((`MISA >> 20) % 2 == 1)
`define ZCSR_SUPPORTED 1
`define ZCOUNTERS_SUPPORTED 1
// N-mode user-level interrupts are depricated per Andrew Waterman 1/13/21
//`define N_SUPPORTED ((MISA >> 13) % 2 == 1)
`define N_SUPPORTED 0
`define M_MODE (2'b11)
`define S_MODE (2'b01)
`define U_MODE (2'b00)
// Microarchitectural Features
`define UARCH_PIPELINED 1
`define UARCH_SUPERSCALR 0
`define UARCH_SINGLECYCLE 0
`define MEM_DCACHE 0
`define MEM_DTIM 1
`define MEM_ICACHE 0
`define MEM_VIRTMEM 0
// Address space
`define RESET_VECTOR 64'h0000000080000000
// Bus Interface width
`define AHBW 64
// Peripheral Addresses
// Peripheral memory space extends from BASE to BASE+RANGE
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
`define TIMBASE 32'h80000000
`define TIMRANGE 32'h0007FFFF
`define CLINTBASE 32'h02000000
`define CLINTRANGE 32'h0000FFFF
`define GPIOBASE 32'h10012000
`define GPIORANGE 32'h000000FF
`define UARTBASE 32'h10000000
`define UARTRANGE 32'h00000007
// Test modes
// Tie GPIO outputs back to inputs
`define GPIO_LOOPBACK_TEST 0
// Hardware configuration
`define UART_PRESCALE 1
/* verilator lint_off STMTDLY */
/* verilator lint_off WIDTH */
/* verilator lint_off ASSIGNDLY */
/* verilator lint_off PINCONNECTEMPTY */

View 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

View 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

View file

@ -0,0 +1,65 @@
`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
//write signal mux
//address signal mux
//parallel floating-point registers are
//used for modularity and future performance
//comparisons between operation sets
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
*/
endmodule

View 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