mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-04-23 13:27:16 -04:00
Parallel FSR's and F CTRL logic
This commit is contained in:
parent
088fbbcbf0
commit
11e2666bb2
5 changed files with 839 additions and 0 deletions
89
wally-pipelined/config/rv64icfd/wally-config.vh
Normal file
89
wally-pipelined/config/rv64icfd/wally-config.vh
Normal 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 */
|
29
wally-pipelined/src/fpu/build_temp/fcsr.sv
Normal file
29
wally-pipelined/src/fpu/build_temp/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/build_temp/fctrl.sv
Normal file
143
wally-pipelined/src/fpu/build_temp/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
|
65
wally-pipelined/src/fpu/build_temp/fputop.sv
Normal file
65
wally-pipelined/src/fpu/build_temp/fputop.sv
Normal 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
|
513
wally-pipelined/src/fpu/build_temp/freg.sv
Normal file
513
wally-pipelined/src/fpu/build_temp/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…
Add table
Add a link
Reference in a new issue