merged with main to integrate with AHB

This commit is contained in:
kaveh pezeshki 2021-02-26 05:37:10 -08:00
commit e8b306bcba
69 changed files with 13098 additions and 327 deletions

6
.gitmodules vendored
View File

@ -1,9 +1,3 @@
[submodule "sky130/sky130_osu_sc_t12"] [submodule "sky130/sky130_osu_sc_t12"]
path = sky130/sky130_osu_sc_t12 path = sky130/sky130_osu_sc_t12
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t12/ url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t12/
[submodule "sky130/sky130_osu_sc_t15"]
path = sky130/sky130_osu_sc_t15
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t15/
[submodule "sky130/sky130_osu_sc_t18"]
path = sky130/sky130_osu_sc_t18
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t18/

@ -1 +1 @@
Subproject commit 87ca77795004bea5525b25badd7ec36cbc8222e1 Subproject commit f60f2d0395053c4df362a97d7e2099721b6face6

@ -1 +0,0 @@
Subproject commit dae3c2282e10d72f57af61d1dd73a1b0aead63f9

@ -1 +0,0 @@
Subproject commit 6c20402bf853e6bf3985fce49fe88ca25502cc63

View File

@ -0,0 +1,90 @@
//////////////////////////////////////////
// wally-config.vh
//
// Written: David_Harris@hmc.edu 4 January 2021
// Modified:
//
// 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 | 1 << 12)
`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
`define RESET_VECTOR 64'h0000000000000000
// 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'h00000000
`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

@ -61,7 +61,7 @@
// Bus Interface width // Bus Interface width
`define AHBW 64 `define AHBW 64
// Peripheral Addresses // Peripheral Physiccal Addresses
// Peripheral memory space extends from BASE to BASE+RANGE // 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 // Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits

102
wally-pipelined/ppa/ppa.sv Normal file
View File

@ -0,0 +1,102 @@
// ppa.sv
// Teo Ene & David_Harris@hmc.edu 25 Feb 2021
// Measure PPA of various building blocks
// replace this with the tools setting a library path to a config/skl130 directory containing config.vh
`define LIB SKL130
module top(
input logic a1,
input logic [7:0] a8, b8,
input logic [15:0] a16, b16,
input logic [31:0] a32, b32,
input logic [63:0] a64, b64,
output logic yinv,
output logic [63:0] y1, y2, y3, y4
);
// fo4 inverter
myinv myinv(a1, yinv);)
// adders
add #(8) add8(a8, b8, yadd8);
add #(16) add16(a16, b16, yadd16);
add #(32) add32(a32, b32, yadd32);
add #(64) add64(a64, b64, yadd64);
// mux2, mux3, mux4 of 1, 8, 16, 32, 64
endmodule
module myinv(input a, output y);
driver #(1) drive(a, in1);
assign out = ~in;
load #(1) load(out, y);
endmodule
module add #(parameter WIDTH=8) (
input logic [7:0] a, b,
output logic [7:0] y
);
logic [WIDTH-1:0] in1, in2, out;
driver #(WIDTH) drive1(a, in1);
driver #(WIDTH) drive2(b, in2);
assign out = in1 + in2;
load #(WIDTH) load(out, y);
endmodule
module INVX2(input logic a, output logic y);
generate
if (LIB == SKL130)
sky130_osu_sc_12T_ms__inv_2 inv(a, y);
else if (LIB == SKL90)
scc9gena_inv_2 inv(a, y)
else if (LIB == GF14)
INV_X2N_A10P5PP84TSL_C14(a, y)
endgenerate
endmodule
module driver #(parameter WDITH=1) (
input [WIDTH-1:0] logic a,
output [WIDTH-1:0] logic y
);
logic [WIDTH-1:0] ab;
INVX2 i1[WIDTH-1:0](a, ab);
INVX2 i2[WIDTH-1:0](ab, y);
endmodule
module inv4(input logic a, output logic y);
logic [3:0] b
INVX2 i0(a, b[0]);
INVX2 i1(a, b[1]);
INVX2 i2(a, b[2]);
INVX2 i3(a, b[3]);
INVX2 i00(b[0], y;
INVX2 i01(b[0], y);
INVX2 i02(b[0], y);
INVX2 i03(b[0], y);
INVX2 i10(b[1], y;
INVX2 i11(b[1], y);
INVX2 i12(b[1], y);
INVX2 i13(b[1], y);
INVX2 i20(b[2], y;
INVX2 i21(b[2], y);
INVX2 i22(b[2], y);
INVX2 i23(b[2], y);
INVX2 i30(b[3], y;
INVX2 i31(b[3], y);
INVX2 i32(b[3], y);
INVX2 i33(b[3], y);
endmodule
module load #(parameter WDITH=1) (
input [WIDTH-1:0] logic a,
output [WIDTH-1:0] logic y
);
logic [WIDTH-1:0] ab;
inv4 load[WIDTH-1:0](a, y);
endmodule

View File

@ -7,11 +7,11 @@
# #
# Takes 1:10 to run RV64IC tests using gui # Takes 1:10 to run RV64IC tests using gui
# Use this wally-pipelined.do file to run this example. # Use this wally-coremark.do file to run this example.
# Either bring up ModelSim and type the following at the "ModelSim>" prompt: # Either bring up ModelSim and type the following at the "ModelSim>" prompt:
# do wally-pipelined.do # do wally-coremark.do
# or, to run from a shell, type the following at the shell prompt: # or, to run from a shell, type the following at the shell prompt:
# vsim -do wally-pipelined.do -c # vsim -do wally-coremark.do -c
# (omit the "-c" to see the GUI while running from the shell) # (omit the "-c" to see the GUI while running from the shell)
onbreak {resume} onbreak {resume}
@ -27,12 +27,9 @@ vlib work
# "Extra checking for conflicts with always_comb done at vopt time" # "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt # because vsim will run vopt
# default to config/rv64ic, but allow this to be overridden at the command line. For example: # default to config/coremark, but allow this to be overridden at the command line. For example:
# do wally-pipelined.do ../config/rv32ic vlog +incdir+../config/coremark ../testbench/testbench-coremark.sv ../src/*/*.sv -suppress 2583
switch $argc {
0 {vlog +incdir+../config/rv64ic ../testbench/testbench-coremark.sv ../src/*/*.sv -suppress 2583}
1 {vlog +incdir+$1 ../testbench/testbench-coremark.sv ../src/*/*.sv -suppress 2583}
}
# start and run simulation # start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals # remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt +acc work.testbench -o workopt vopt +acc work.testbench -o workopt
@ -45,7 +42,7 @@ view wave
add wave /testbench/clk add wave /testbench/clk
add wave /testbench/reset add wave /testbench/reset
add wave -divider add wave -divider
add wave /testbench/dut/hart/ebu/IReadF #add wave /testbench/dut/hart/ebu/IReadF
add wave /testbench/dut/hart/DataStall add wave /testbench/dut/hart/DataStall
add wave /testbench/dut/hart/InstrStall add wave /testbench/dut/hart/InstrStall
add wave /testbench/dut/hart/StallF add wave /testbench/dut/hart/StallF
@ -58,11 +55,14 @@ add wave /testbench/dut/hart/FlushW
add wave -divider add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCF add wave -hex /testbench/dut/hart/ifu/PCF
add wave -hex /testbench/dut/hart/ifu/InstrF add wave -hex /testbench/dut/hart/ifu/InstrF
add wave /testbench/InstrFName
#add wave -hex /testbench/dut/hart/ifu/PCD #add wave -hex /testbench/dut/hart/ifu/PCD
add wave -hex /testbench/dut/hart/ifu/InstrD add wave -hex /testbench/dut/hart/ifu/InstrD
add wave /testbench/InstrDName
add wave -divider add wave -divider
#add wave -hex /testbench/dut/hart/ifu/PCE #add wave -hex /testbench/dut/hart/ifu/PCE
#add wave -hex /testbench/dut/hart/ifu/InstrE #add wave -hex /testbench/dut/hart/ifu/InstrE
add wave /testbench/InstrEName
add wave -hex /testbench/dut/hart/ieu/dp/SrcAE add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
@ -70,11 +70,13 @@ add wave /testbench/dut/hart/ieu/dp/PCSrcE
add wave -divider add wave -divider
#add wave -hex /testbench/dut/hart/ifu/PCM #add wave -hex /testbench/dut/hart/ifu/PCM
#add wave -hex /testbench/dut/hart/ifu/InstrM #add wave -hex /testbench/dut/hart/ifu/InstrM
add wave /testbench/InstrMName
add wave /testbench/dut/uncore/dtim/memwrite add wave /testbench/dut/uncore/dtim/memwrite
add wave -hex /testbench/dut/uncore/HADDR add wave -hex /testbench/dut/uncore/HADDR
add wave -hex /testbench/dut/uncore/HWDATA add wave -hex /testbench/dut/uncore/HWDATA
add wave -divider add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCW add wave -hex /testbench/dut/hart/ifu/PCW
add wave /testbench/InstrWName
add wave /testbench/dut/hart/ieu/dp/RegWriteW add wave /testbench/dut/hart/ieu/dp/RegWriteW
add wave -hex /testbench/dut/hart/ieu/dp/ResultW add wave -hex /testbench/dut/hart/ieu/dp/ResultW
add wave -hex /testbench/dut/hart/ieu/dp/RdW add wave -hex /testbench/dut/hart/ieu/dp/RdW

View File

@ -45,11 +45,14 @@ view wave
add wave /testbench/clk add wave /testbench/clk
add wave /testbench/reset add wave /testbench/reset
add wave -divider add wave -divider
add wave /testbench/dut/hart/ebu/IReadF #add wave /testbench/dut/hart/ebu/IReadF
add wave /testbench/dut/hart/DataStall add wave /testbench/dut/hart/DataStall
add wave /testbench/dut/hart/InstrStall add wave /testbench/dut/hart/InstrStall
add wave /testbench/dut/hart/StallF add wave /testbench/dut/hart/StallF
add wave /testbench/dut/hart/StallD add wave /testbench/dut/hart/StallD
add wave /testbench/dut/hart/StallE
add wave /testbench/dut/hart/StallM
add wave /testbench/dut/hart/StallW
add wave /testbench/dut/hart/FlushD add wave /testbench/dut/hart/FlushD
add wave /testbench/dut/hart/FlushE add wave /testbench/dut/hart/FlushE
add wave /testbench/dut/hart/FlushM add wave /testbench/dut/hart/FlushM
@ -59,26 +62,27 @@ add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCF add wave -hex /testbench/dut/hart/ifu/PCF
add wave -hex /testbench/dut/hart/ifu/InstrF add wave -hex /testbench/dut/hart/ifu/InstrF
add wave /testbench/InstrFName add wave /testbench/InstrFName
#add wave -hex /testbench/dut/hart/ifu/PCD add wave -hex /testbench/dut/hart/ifu/PCD
add wave -hex /testbench/dut/hart/ifu/InstrD add wave -hex /testbench/dut/hart/ifu/InstrD
add wave /testbench/InstrDName add wave /testbench/InstrDName
add wave -divider add wave -divider
#add wave -hex /testbench/dut/hart/ifu/PCE add wave -hex /testbench/dut/hart/ifu/PCE
#add wave -hex /testbench/dut/hart/ifu/InstrE add wave -hex /testbench/dut/hart/ifu/InstrE
add wave /testbench/InstrEName add wave /testbench/InstrEName
add wave -hex /testbench/dut/hart/ieu/dp/SrcAE add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
add wave /testbench/dut/hart/ieu/dp/PCSrcE add wave /testbench/dut/hart/ieu/dp/PCSrcE
add wave -divider add wave -divider
#add wave -hex /testbench/dut/hart/ifu/PCM add wave -hex /testbench/dut/hart/ifu/PCM
#add wave -hex /testbench/dut/hart/ifu/InstrM add wave -hex /testbench/dut/hart/ifu/InstrM
add wave /testbench/InstrMName add wave /testbench/InstrMName
add wave /testbench/dut/uncore/dtim/memwrite add wave /testbench/dut/uncore/dtim/memwrite
add wave -hex /testbench/dut/uncore/HADDR add wave -hex /testbench/dut/uncore/HADDR
add wave -hex /testbench/dut/uncore/HWDATA add wave -hex /testbench/dut/uncore/HWDATA
add wave -divider add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCW add wave -hex /testbench/dut/hart/ifu/PCW
add wave -hex /testbench/dut/hart/ifu/InstrW
add wave /testbench/InstrWName add wave /testbench/InstrWName
add wave /testbench/dut/hart/ieu/dp/RegWriteW add wave /testbench/dut/hart/ieu/dp/RegWriteW
add wave -hex /testbench/dut/hart/ieu/dp/ResultW add wave -hex /testbench/dut/hart/ieu/dp/ResultW
@ -101,6 +105,6 @@ configure wave -childrowmargin 2
set DefaultRadix hexadecimal set DefaultRadix hexadecimal
-- Run the Simulation -- Run the Simulation
#run 1000 #run 2000
run -all run -all
#quit #quit

View File

@ -30,19 +30,19 @@
module dmem ( module dmem (
input logic clk, reset, input logic clk, reset,
input logic FlushW, input logic FlushW,
output logic DataStall, //output logic DataStall,
// Memory Stage // Memory Stage
input logic [1:0] MemRWM, input logic [1:0] MemRWM,
input logic [`XLEN-1:0] MemAdrM, input logic [`XLEN-1:0] MemAdrM,
input logic [2:0] Funct3M, input logic [2:0] Funct3M,
input logic [`XLEN-1:0] ReadDataM, //input logic [`XLEN-1:0] ReadDataW,
input logic [`XLEN-1:0] WriteDataM, input logic [`XLEN-1:0] WriteDataM,
output logic [`XLEN-1:0] MemPAdrM, output logic [`XLEN-1:0] MemPAdrM,
output logic [1:0] MemRWAlignedM, output logic MemReadM, MemWriteM,
output logic DataMisalignedM, output logic DataMisalignedM,
// Writeback Stage // Writeback Stage
input logic MemAckW, input logic MemAckW,
output logic [`XLEN-1:0] ReadDataW, input logic [`XLEN-1:0] ReadDataW,
// faults // faults
input logic DataAccessFaultM, input logic DataAccessFaultM,
output logic LoadMisalignedFaultM, LoadAccessFaultM, output logic LoadMisalignedFaultM, LoadAccessFaultM,
@ -52,9 +52,6 @@ module dmem (
// Initially no MMU // Initially no MMU
assign MemPAdrM = MemAdrM; assign MemPAdrM = MemAdrM;
// Pipeline register *** AHB data will eventually come back in W anyway
floprc #(`XLEN) ReadDataWReg(clk, reset, FlushW, ReadDataM, ReadDataW);
// Determine if an Unaligned access is taking place // Determine if an Unaligned access is taking place
always_comb always_comb
case(Funct3M[1:0]) case(Funct3M[1:0])
@ -66,7 +63,8 @@ module dmem (
// Squash unaligned data accesses // Squash unaligned data accesses
// *** this is also the place to squash if the cache is hit // *** this is also the place to squash if the cache is hit
assign MemRWAlignedM = MemRWM & {2{~DataMisalignedM}}; assign MemReadM = MemRWM[1] & ~DataMisalignedM;
assign MemWriteM = MemRWM[0] & ~DataMisalignedM;
// Determine if address is valid // Determine if address is valid
assign LoadMisalignedFaultM = DataMisalignedM & MemRWM[1]; assign LoadMisalignedFaultM = DataMisalignedM & MemRWM[1];
@ -75,7 +73,7 @@ module dmem (
assign StoreAccessFaultM = DataAccessFaultM & MemRWM[0]; assign StoreAccessFaultM = DataAccessFaultM & MemRWM[0];
// Data stall // Data stall
assign DataStall = 0; //assign DataStall = 0;
endmodule endmodule

View File

@ -32,21 +32,20 @@
module ahblite ( module ahblite (
input logic clk, reset, input logic clk, reset,
input logic StallW, FlushW,
// Load control // Load control
input logic UnsignedLoadM, input logic UnsignedLoadM,
// Signals from Instruction Cache // Signals from Instruction Cache
input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram
input logic IReadF, input logic InstrReadF,
output logic [`XLEN-1:0] IRData, output logic [`XLEN-1:0] InstrRData,
// output logic IReady,
// Signals from Data Cache // Signals from Data Cache
input logic [`XLEN-1:0] MemPAdrM, input logic [`XLEN-1:0] MemPAdrM,
input logic DReadM, DWriteM, input logic MemReadM, MemWriteM,
input logic [`XLEN-1:0] WriteDataM, input logic [`XLEN-1:0] WriteDataM,
input logic [1:0] DSizeM, input logic [1:0] MemSizeM,
// Return from bus // Return from bus
output logic [`XLEN-1:0] DRData, output logic [`XLEN-1:0] ReadDataW,
// output logic DReady,
// AHB-Lite external signals // AHB-Lite external signals
input logic [`AHBW-1:0] HRDATA, input logic [`AHBW-1:0] HRDATA,
input logic HREADY, HRESP, input logic HREADY, HRESP,
@ -59,57 +58,91 @@ module ahblite (
output logic [3:0] HPROT, output logic [3:0] HPROT,
output logic [1:0] HTRANS, output logic [1:0] HTRANS,
output logic HMASTLOCK, output logic HMASTLOCK,
// Acknowledge // Delayed signals for writes
output logic InstrAckD, MemAckW output logic [2:0] HADDRD,
output logic [3:0] HSIZED,
output logic HWRITED,
// Stalls // Stalls
// output logic InstrStall, DataStall output logic InstrStall,/*InstrUpdate, */DataStall
); );
logic GrantData; logic GrantData;
logic [2:0] ISize; logic [2:0] ISize;
logic [`AHBW-1:0] HRDATAMasked; logic [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataPreW;
logic IReady, DReady; logic IReady, DReady;
logic CaptureDataM;
assign HCLK = clk; assign HCLK = clk;
assign HRESETn = ~reset; assign HRESETn = ~reset;
// Arbitrate requests by giving data priority over instructions
assign GrantData = DReadM | DWriteM;
// *** initially support HABW = XLEN // *** initially support HABW = XLEN
// Choose ISize based on XLen // track bus state
generate // Data accesses have priority over instructions. However, if a data access comes
if (`AHBW == 32) assign ISize = 3'b010; // 32-bit transfers // while an instruction read is occuring, the instruction read finishes before
else assign ISize = 3'b011; // 64-bit transfers // the data access can take place.
endgenerate typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADMEMPENDING} statetype;
statetype BusState, NextBusState;
// drive bus outputs always_ff @(posedge HCLK, negedge HRESETn)
assign HADDR = GrantData ? MemPAdrM[31:0] : InstrPAdrF[31:0]; if (~HRESETn) BusState <= #1 IDLE;
assign HWDATA = WriteDataM; else BusState <= #1 NextBusState;
//flop #(`XLEN) wdreg(HCLK, DWDataM, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
assign HWRITE = DWriteM; always_comb
assign HSIZE = GrantData ? {1'b0, DSizeM} : ISize; case (BusState)
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfHPROT IDLE: if (MemReadM) NextBusState = MEMREAD; // Memory has pirority over instructions
else if (MemWriteM) NextBusState = MEMWRITE;
else if (InstrReadF) NextBusState = INSTRREAD;
else NextBusState = IDLE;
MEMREAD: if (~HREADY) NextBusState = MEMREAD;
else if (InstrReadF) NextBusState = INSTRREAD;
else NextBusState = IDLE;
MEMWRITE: if (~HREADY) NextBusState = MEMWRITE;
else if (InstrReadF) NextBusState = INSTRREAD;
else NextBusState = IDLE;
INSTRREAD: //if (~HREADY & (MemReadM | MemWriteM)) NextBusState = INSTRREADMEMPENDING; // *** shouldn't happen, delete
if (~HREADY) NextBusState = INSTRREAD;
else NextBusState = IDLE;
INSTRREADMEMPENDING: if (~HREADY) NextBusState = INSTRREADMEMPENDING; // *** shouldn't happen, delete
else if (MemReadM) NextBusState = MEMREAD;
else NextBusState = MEMWRITE; // must be write if not a read. Don't return to idle.
endcase
// stall signals
assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || (NextBusState == INSTRREADMEMPENDING);
assign #1 InstrStall = (NextBusState == INSTRREAD);
// DH 2/20/22: A cyclic path presently exists
// HREADY->NextBusState->GrantData->HSIZE->HSELUART->HREADY
// This is because the peripherals assert HREADY on the same cycle
// When memory is working, also fix the peripherals to respond on the subsequent cycle
// and this path should be fixed.
// bus outputs
assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE);
assign #1 HADDR = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0];
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway
assign #1 HSIZE = GrantData ? {1'b0, MemSizeM} : ISize;
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH
assign HPROT = 4'b0011; // not used; see Section 3.7 assign HPROT = 4'b0011; // not used; see Section 3.7
assign HTRANS = IReadF | DReadM | DWriteM ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise assign HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
assign HMASTLOCK = 0; // no locking supported assign HMASTLOCK = 0; // no locking supported
assign HWRITE = (NextBusState == MEMWRITE);
// Route signals to Instruction and Data Caches // delay write data by one cycle for
flop #(`XLEN) wdreg(HCLK, WriteDataM, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
// delay signals for subword writes
flop #(3) adrreg(HCLK, HADDR[2:0], HADDRD);
flop #(4) sizereg(HCLK, {UnsignedLoadM, HSIZE}, HSIZED);
flop #(1) writereg(HCLK, HWRITE, HWRITED);
// Route signals to Instruction and Data Caches
// *** assumes AHBW = XLEN // *** assumes AHBW = XLEN
assign IRData = HRDATAMasked;
assign IReady = HREADY & IReadF & ~GrantData; // maybe unused?***
assign DRData = HRDATAMasked;
assign DReady = HREADY & GrantData; // ***unused?
// stalls assign InstrRData = HRDATA;
// Stall MEM stage if data is being accessed and bus isn't yet ready assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021
//assign DataStall = GrantData & ~HREADY; assign CaptureDataM = (BusState == MEMREAD) && (NextBusState != MEMREAD);
// Stall Fetch stage if instruction should be read but reading data or bus isn't ready flopenr #(`XLEN) ReadDataPreWReg(clk, reset, CaptureDataM, ReadDataM, ReadDataPreW); // *** this may break when there is no instruction read after data read
//assign InstrStall = IReadF & (GrantData | ~HREADY); flopenr #(`XLEN) ReadDataWReg(clk, reset, ~StallW, ReadDataPreW, ReadDataW);
// *** consider adding memory access faults based on HRESP being high
// InstrAccessFaultF, DataAccessFaultM,
subwordread swr(.*); subwordread swr(.*);

View File

@ -28,9 +28,9 @@
module subwordread ( module subwordread (
// from AHB Interface // from AHB Interface
input logic [`XLEN-1:0] HRDATA, input logic [`XLEN-1:0] HRDATA,
input logic [31:0] HADDR, input logic [2:0] HADDRD,
input logic UnsignedLoadM, //input logic UnsignedLoadM,
input logic [2:0] HSIZE, input logic [3:0] HSIZED,
// to ifu/dmems // to ifu/dmems
output logic [`XLEN-1:0] HRDATAMasked output logic [`XLEN-1:0] HRDATAMasked
); );
@ -42,7 +42,7 @@ module subwordread (
if (`XLEN == 64) begin if (`XLEN == 64) begin
// ByteMe mux // ByteMe mux
always_comb always_comb
case(HADDR[2:0]) case(HADDRD[2:0])
3'b000: ByteM = HRDATA[7:0]; 3'b000: ByteM = HRDATA[7:0];
3'b001: ByteM = HRDATA[15:8]; 3'b001: ByteM = HRDATA[15:8];
3'b010: ByteM = HRDATA[23:16]; 3'b010: ByteM = HRDATA[23:16];
@ -55,7 +55,7 @@ module subwordread (
// halfword mux // halfword mux
always_comb always_comb
case(HADDR[2:1]) case(HADDRD[2:1])
2'b00: HalfwordM = HRDATA[15:0]; 2'b00: HalfwordM = HRDATA[15:0];
2'b01: HalfwordM = HRDATA[31:16]; 2'b01: HalfwordM = HRDATA[31:16];
2'b10: HalfwordM = HRDATA[47:32]; 2'b10: HalfwordM = HRDATA[47:32];
@ -65,14 +65,14 @@ module subwordread (
logic [31:0] WordM; logic [31:0] WordM;
always_comb always_comb
case(HADDR[2]) case(HADDRD[2])
1'b0: WordM = HRDATA[31:0]; 1'b0: WordM = HRDATA[31:0];
1'b1: WordM = HRDATA[63:32]; 1'b1: WordM = HRDATA[63:32];
endcase endcase
// sign extension // sign extension
always_comb always_comb
case({UnsignedLoadM, HSIZE[1:0]}) case({HSIZED[3], HSIZED[1:0]}) // HSIZED[3] indicates unsigned load
3'b000: HRDATAMasked = {{56{ByteM[7]}}, ByteM}; // lb 3'b000: HRDATAMasked = {{56{ByteM[7]}}, ByteM}; // lb
3'b001: HRDATAMasked = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh 3'b001: HRDATAMasked = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: HRDATAMasked = {{32{WordM[31]}}, WordM[31:0]}; // lw 3'b010: HRDATAMasked = {{32{WordM[31]}}, WordM[31:0]}; // lw
@ -85,7 +85,7 @@ module subwordread (
end else begin // 32-bit end else begin // 32-bit
// byte mux // byte mux
always_comb always_comb
case(HADDR[1:0]) case(HADDRD[1:0])
2'b00: ByteM = HRDATA[7:0]; 2'b00: ByteM = HRDATA[7:0];
2'b01: ByteM = HRDATA[15:8]; 2'b01: ByteM = HRDATA[15:8];
2'b10: ByteM = HRDATA[23:16]; 2'b10: ByteM = HRDATA[23:16];
@ -94,14 +94,14 @@ module subwordread (
// halfword mux // halfword mux
always_comb always_comb
case(HADDR[1]) case(HADDRD[1])
1'b0: HalfwordM = HRDATA[15:0]; 1'b0: HalfwordM = HRDATA[15:0];
1'b1: HalfwordM = HRDATA[31:16]; 1'b1: HalfwordM = HRDATA[31:16];
endcase endcase
// sign extension // sign extension
always_comb always_comb
case({UnsignedLoadM, HSIZE[1:0]}) case({HSIZED[3], HSIZED[1:0]})
3'b000: HRDATAMasked = {{24{ByteM[7]}}, ByteM}; // lb 3'b000: HRDATAMasked = {{24{ByteM[7]}}, ByteM}; // lb
3'b001: HRDATAMasked = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh 3'b001: HRDATAMasked = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: HRDATAMasked = HRDATA; // lw 3'b010: HRDATAMasked = HRDATA; // lw

View File

@ -0,0 +1,61 @@
////////////////////////////////////////////////////////////////////////////////
//
// Block Name: add.v
// Author: David Harris
// Date: 11/12/1995
//
// Block Description:
// This block performs the addition of the product and addend. It also
// contains logic necessary to adjust the signs for effective subtracts
// and negative results.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
module add(r[105:0], s[105:0], t[157:0], sum[157:0],
negsum, invz, selsum1, killprod, negsum0, negsum1, proddenorm);
////////////////////////////////////////////////////////////////////////////////
input [105:0] r; // partial product 1
input [105:0] s; // partial product 2
input [157:0] t; // aligned addend
input invz; // invert addend
input selsum1; // select +1 mode of compound adder
input killprod; // z >> product
input negsum; // Negate sum
input proddenorm;
output [157:0] sum; // sum
output negsum0; // sum was negative in +0 mode
output negsum1; // sum was negative in +1 mode
// Internal nodes
wire [105:0] r2; // partial product possibly zeroed out
wire [105:0] s2; // partial product possibly zeroed out
wire [157:0] t2; // addend after inversion if necessary
wire [157:0] sum0; // sum of compound adder +0 mode
wire [157:0] sum1; // sum of compound adder +1 mode
// Invert addend if necessary
assign t2 = invz ? -t : t;
// Zero out product if Z >> product or product really should be zero
assign r2 = ~proddenorm & killprod ? 106'b0 : r;
assign s2 = ~proddenorm & killprod ? 106'b0 : s;
// Compound adder
// Consists of 3:2 CSA followed by long compound CPA
assign sum0 = {52'b0, r2} + {52'b0, s2} + t2 + 158'b0;
assign sum1 = {52'b0, r2} + {52'b0, s2} + t2 + 158'b1;
// Check sign bits in +0/1 modes
assign negsum0 = sum0[157];
assign negsum1 = sum1[157];
// Mux proper result (+Oil mode and inversion) using 4:1 mux
assign sum = selsum1 ? (negsum ? ~sum1 : sum1) : (negsum ? ~sum0 : sum0);
endmodule

View File

@ -0,0 +1,99 @@
///////////////////////////////////////////////////////////////////////////////
// Block Name: align.v
// Author: David Harris
// Date: 11/2/1995
//
// Block Description:
// This block implements the alignment shifter. It is responsible for
// adjusting the fraction portion of the addend relative to the fraction
// produced in the multiplier array.
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module align(z[51:0], ae[12:0], aligncnt, xzero, yzero, zzero, zdenorm, proddenorm, t[157:0], bs, ps,
killprod, bypsel[1], bypplus1, byppostnorm);
/////////////////////////////////////////////////////////////////////////////
input [51:0] z; // Fraction of addend z;
input [12:0] ae; // sign of exponent of addend z;
input [11:0] aligncnt; // amount to shift
input xzero; // Input X = 0
input yzero; // Input Y = 0
input zzero; // Input Z = 0
input zdenorm; // Input Z = denorm
input proddenorm;
input [1:1] bypsel; // Select bypass to X or Z
input bypplus1; // Add one to bypassed result
input byppostnorm; // Postnormalize bypassed result
output [157:0] t; // aligned addend (54 bits left of bpt)
output bs; // sticky bit of addend
output ps; // sticky bit of product
output killprod; // Z >> product
// Internal nodes
reg [157:0] t; // aligned addend from shifter
reg killprod; // Z >> product
reg bs; // sticky bit of addend
reg ps; // sticky bit of product
reg [7:0] i; // temp storage for finding sticky bit
wire [52:0] z1; // Z plus 1
wire [51:0] z2; // Z selected after handling rounds
wire [11:0] align104; // alignment count + 104
// Increment fraction of Z by one if necessary for prerounded bypass
// This incrementor delay is masked by the alignment count computation
assign z1 = z + 1;
assign z2 = bypsel[1] && bypplus1 ? (byppostnorm ? z1[52:1] : z1[51:0]): z;
// Compute sign of aligncnt + 104 to check for shifting too far right
assign align104 = aligncnt+104;
// Shift addend by alignment count. Generate sticky bits from
// addend on right shifts. Handle special cases of shifting
// by too much.
always @(z2 or aligncnt or align104 or zzero or xzero or yzero or zdenorm)
begin
// Default to clearing sticky bits
bs = 0;
ps = 0;
// And to using product as primary operand in adder I exponent gen
killprod = 0;
if(zzero) begin
t = 158'b0;
if (xzero || yzero) killprod = 1;
end else if ((aligncnt > 53 && ~aligncnt[11]) || xzero || yzero) begin
// Left shift by huge amount
// or product = 0
t = {53'b0, ~zzero, z2, 52'b0};
killprod = 1;
ps = ~xzero && ~yzero;
end else if ((ae[12] && align104[11])) begin //***fix the if statement
// KEP if the multiplier's exponent overflows
t = {53'b0, ~zzero, z2, 52'b0};
killprod = 1;
ps = ~xzero && ~yzero;
end else if(align104[11]) begin // Right shift by huge amount
bs = ~zzero;
t = 0;
end else if (~aligncnt[11]) begin // Left shift by reasonable amount
t = {53'b0, ~zzero, z2, 52'b0} << aligncnt;
end else begin // Otherwise right shift
t = {53'b0, ~zzero, z2, 52'b0} >> -aligncnt;
// use some behavioral code to find sticky bit. This is really
// done by hardware in the shifter.
if (aligncnt < 0)
for (i=0; i<-aligncnt-52; i = i+1)
bs = bs || z2[i];
end
end
endmodule

View File

@ -0,0 +1,114 @@
module array(x, y, xdenorm, ydenorm, r, s, bypsel, bypplus1);
/////////////////////////////////////////////////////////////////////////////
input [51:0] x; // Fraction of multiplicand x
input [51:0] y; // Fraction of multiplicand y
input xdenorm; // is x denormalized
input ydenorm; // is y denormalized
input bypsel; // Bypass X
input bypplus1; // Add 1 to X to handle rounding
output [105:0] r; // partial product 1
output [105:0] s; // partial product 2
wire [51:0] xnorm;
wire [51:0] ynorm;
wire [54:0] yExt; //y with appended 0 and assumed 1
wire [53:0] xExt; //y with assumed 1
wire [26:0][1:0] add1;
wire [26:0][54:0] pp;
wire [26:0] e;
logic [17:0][105:0] lv1add;
logic [11:0][105:0] lv2add;
logic [7:0][105:0] lv3add;
logic [3:0][105:0] lv4add;
logic [21:0][106:0] carryTmp;
wire [26:0][105:0] acc;
// wire [105:0] acc
genvar i;
assign xnorm = xdenorm ? {x[50:0], 1'b0} : x; // normalization of denormalized numbers
assign ynorm = ydenorm ? {y[50:0], 1'b0} : y;
assign yExt = {2'b01,ynorm,1'b0}; // y extended and added assumed 1
assign xExt = {2'b01,xnorm}; // x with added assumed 1
//booth encoding
generate
for(i=0; i<27; i=i+1) begin
booth booth(.xExt(xExt), .choose(yExt[(i*2)+2:i*2]), .add1(add1[i]), .e(e[i]), .pp(pp[i]));
end
endgenerate
assign acc[0] = {49'b0,~e[0],e[0],e[0],pp[0]};
assign acc[1] = {50'b01,~e[1],pp[1],add1[0]};
assign acc[2] = {48'b01,~e[2],pp[2],add1[1], 2'b0};
assign acc[3] = {46'b01,~e[3],pp[3],add1[2], 4'b0};
assign acc[4] = {44'b01,~e[4],pp[4],add1[3], 6'b0};
assign acc[5] = {42'b01,~e[5],pp[5],add1[4], 8'b0};
assign acc[6] = {40'b01,~e[6],pp[6],add1[5], 10'b0};
assign acc[7] = {38'b01,~e[7],pp[7],add1[6], 12'b0};
assign acc[8] = {36'b01,~e[8],pp[8],add1[7], 14'b0};
assign acc[9] = {34'b01,~e[9],pp[9],add1[8], 16'b0};
assign acc[10] = {32'b01,~e[10],pp[10],add1[9], 18'b0};
assign acc[11] = {30'b01,~e[11],pp[11],add1[10], 20'b0};
assign acc[12] = {28'b01,~e[12],pp[12],add1[11], 22'b0};
assign acc[13] = {26'b01,~e[13],pp[13],add1[12], 24'b0};
assign acc[14] = {24'b01,~e[14],pp[14],add1[13], 26'b0};
assign acc[15] = {22'b01,~e[15],pp[15],add1[14], 28'b0};
assign acc[16] = {20'b01,~e[16],pp[16],add1[15], 30'b0};
assign acc[17] = {18'b01,~e[17],pp[17],add1[16], 32'b0};
assign acc[18] = {16'b01,~e[18],pp[18],add1[17], 34'b0};
assign acc[19] = {14'b01,~e[19],pp[19],add1[18], 36'b0};
assign acc[20] = {12'b01,~e[20],pp[20],add1[19], 38'b0};
assign acc[21] = {10'b01,~e[21],pp[21],add1[20], 40'b0};
assign acc[22] = {8'b01,~e[22],pp[22],add1[21], 42'b0};
assign acc[23] = {6'b01,~e[23],pp[23],add1[22], 44'b0};
assign acc[24] = {4'b01,~e[24],pp[24],add1[23], 46'b0};
assign acc[25] = {~e[25],pp[25],add1[24], 48'b0};
assign acc[26] = {pp[26],add1[25], 50'b0};
//*** resize adders
generate
for(i=0; i<9; i=i+1) begin
add3comp2 #(.BITS(106)) add1(.a(acc[i*3]), .b(acc[i*3+1]), .c(acc[i*3+2]),
.carry(carryTmp[i][105:0]), .sum(lv1add[i*2+1]));
assign lv1add[i*2] = {carryTmp[i][104:0], 1'b0};
end
endgenerate
generate
for(i=0; i<6; i=i+1) begin
add3comp2 #(.BITS(106)) add2(.a(lv1add[i*3]), .b(lv1add[i*3+1]), .c(lv1add[i*3+2]),
.carry(carryTmp[i+9][105:0]), .sum(lv2add[i*2+1]));
assign lv2add[i*2] = {carryTmp[i+9][104:0], 1'b0};
end
endgenerate
generate
for(i=0; i<4; i=i+1) begin
add3comp2 #(.BITS(106)) add3(.a(lv2add[i*3]), .b(lv2add[i*3+1]), .c(lv2add[i*3+2]),
.carry(carryTmp[i+15][105:0]), .sum(lv3add[i*2+1]));
assign lv3add[i*2] = {carryTmp[i+15][104:0], 1'b0};
end
endgenerate
generate
for(i=0; i<2; i=i+1) begin
add4comp2 #(.BITS(106)) add4(.a(lv3add[i*4]), .b(lv3add[i*4+1]), .c(lv3add[i*4+2]), .d(lv3add[i*4+3]),
.carry(carryTmp[i+19]), .sum(lv4add[i*2+1]));
assign lv4add[i*2] = {carryTmp[i+19][104:0], 1'b0};
end
endgenerate
add4comp2 #(.BITS(106)) add5(.a(lv4add[0]), .b(lv4add[1]), .c(lv4add[2]), .d(lv4add[3]) ,
.carry(carryTmp[21]), .sum(s));
assign r = {carryTmp[21][104:0], 1'b0};
// assign r = 106'b0;
// assign s = ({54'b1,xnorm} + (bypsel && bypplus1)) * {54'b1,ynorm};
endmodule

View File

@ -0,0 +1,55 @@
module booth(xExt, choose, add1, e, pp);
/////////////////////////////////////////////////////////////////////////////
input [53:0] xExt; // multiplicand xExt
input [2:0] choose; // bits needed to choose which encoding
output [1:0] add1; // do you add 1
output e;
output [54:0] pp; // the resultant encoding
logic [54:0] pp, temp;
logic e;
logic [1:0] add1;
logic [53:0] negx;
//logic temp;
assign negx = ~xExt;
always @(choose, xExt, negx)
case (choose)
3'b000 : pp = 55'b0; // 0
3'b001 : pp = {xExt[53], xExt}; // 1
3'b010 : pp = {xExt[53], xExt}; // 1
3'b011 : pp = {xExt, 1'b0}; // 2
3'b100 : pp = {negx, 1'b0}; // -2
3'b101 : pp = {negx[53], negx}; // -1
3'b110 : pp = {negx[53], negx}; // -1
3'b111 : pp = 55'hfffffffffffffff; // -0
endcase
always @(choose, xExt, negx)
case (choose)
3'b000 : e = 0; // 0
3'b001 : e = xExt[53]; // 1
3'b010 : e = xExt[53]; // 1
3'b011 : e = xExt[53]; // 2
3'b100 : e = negx[53]; // -2
3'b101 : e = negx[53]; // -1
3'b110 : e = negx[53]; // -1
3'b111 : e = 1; // -0
endcase
// assign add1 = (choose[2] == 1'b1) ? ((choose[1:0] == 2'b11) ? 1'b0 : 1'b1) : 1'b0;
// assign add1 = choose[2];
always @(choose)
case (choose)
3'b000 : add1 = 2'b0; // 0
3'b001 : add1 = 2'b0; // 1
3'b010 : add1 = 2'b0; // 1
3'b011 : add1 = 2'b0; // 2
3'b100 : add1 = 2'b10; // -2
3'b101 : add1 = 2'b1; // -1
3'b110 : add1 = 2'b1; // -1
3'b111 : add1 = 2'b1; // -0
endcase
endmodule

View File

@ -0,0 +1,30 @@
/////////////////////////////////////////////////////////////////////////////
//
// Block Name: bypass.v
// Author: David Harris
// Date: 11/2/1995
//
// Block Description:
// This block contains the bypass muxes which allow fast prerounded
// bypass to the X and Z inputs of the FMAC
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module bypass(xrf[63:0], zrf[63:0], wbypass[63:0], bypsel[1:0],
x[63:0], z[63:0]);
/////////////////////////////////////////////////////////////////////////////
input [63:0] xrf; // X from register file
input [63:0] zrf; // Z from register file
input [63:0] wbypass; // Prerounded result for bypass
input [1:0] bypsel; // Select bypass to X or Z
output [63:0] x; // Source X
output [63:0] z; // Source Z
// If bypass select is asserted, bypass source, else take reg file value
assign x = bypsel[0] ? wbypass : xrf;
assign z = bypsel[1] ? wbypass : zrf;
endmodule

View File

@ -0,0 +1,90 @@
module add3comp2(a, b, c, carry, sum);
/////////////////////////////////////////////////////////////////////////////
//look into diffrent implementations of the compressors?
parameter BITS = 4;
input [BITS-1:0] a;
input [BITS-1:0] b;
input [BITS-1:0] c;
output [BITS-1:0] carry;
output [BITS-1:0] sum;
genvar i;
generate
for(i= 0; i<BITS; i=i+1) begin
sng3comp2 add0(a[i], b[i], c[i], carry[i], sum[i]);
end
endgenerate
endmodule
module add4comp2(a, b, c, d, carry, sum);
/////////////////////////////////////////////////////////////////////////////
parameter BITS = 4;
input [BITS-1:0] a;
input [BITS-1:0] b;
input [BITS-1:0] c;
input [BITS-1:0] d;
output [BITS:0] carry;
output [BITS-1:0] sum;
logic [BITS-1:0] cout;
logic carryTmp;
genvar i;
sng4comp2 add0(a[0], b[0], c[0], d[0], 1'b0, cout[0], carry[0], sum[0]);
generate
for(i= 1; i<BITS-1; i=i+1) begin
sng4comp2 add1(a[i], b[i], c[i], d[i], cout[i-1], cout[i], carry[i], sum[i]);
end
endgenerate
sng4comp2 add2(a[BITS-1], b[BITS-1], c[BITS-1], d[BITS-1], cout[BITS-2], cout[BITS-1], carryTmp, sum[BITS-1]);
assign carry[BITS-1] = carryTmp & cout[BITS-1];
assign carry[BITS] = carryTmp ^ cout[BITS-1];
endmodule
module sng3comp2(a, b, c, carry, sum);
/////////////////////////////////////////////////////////////////////////////
//look into diffrent implementations of the compressors?
input a;
input b;
input c;
output carry;
output sum;
logic axorb;
assign axorb = a ^ b;
assign sum = axorb ^ c;
assign carry = axorb ? c : a;
endmodule
module sng4comp2(a, b, c, d, cin, cout, carry, sum);
/////////////////////////////////////////////////////////////////////////////
//look into pass gate 4:2 counters?
input a;
input b;
input c;
input d;
input cin;
output cout;
output carry;
output sum;
logic TmpSum;
sng3comp2 add1(.carry(cout), .sum(TmpSum),.*);
sng3comp2 add2(.a(TmpSum), .b(d), .c(cin), .*);
endmodule

View File

@ -0,0 +1,135 @@
///////////////////////////////////////////////////////////////////////////////
// Block Name: expgen.v
// Author: David Harris
// Date: 11/2/1995
//
// Block Description:
// This block implements the exponent path of the FMAC. It performs the
// following operations:
//
// 1) Compute exponent of multiply.
// 2) Compare multiply and add exponents to generate alignment shift count
// 3) Adjust exponent based on normalization
// 4) Increment exponent based on postrounding renormalization
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module expgen(x[62:52], y[62:52], z[62:52],
earlyres[62:52], earlyressel, bypsel[1], byppostnorm,
killprod, sumzero, postnormalize, normcnt, infinity,
invalid, overflow, underflow, inf,
nan, xnan, ynan, znan, zdenorm, specialsel,
aligncnt, w[62:52], wbypass[62:52],
prodof, sumof, sumuf, denorm0, ae[12:0]);
/////////////////////////////////////////////////////////////////////////////
input [62:52] x; // Exponent of multiplicand x
input [62:52] y; // Exponent of multiplicand y
input [62:52] z; // Exponent of addend z
input [62:52] earlyres; // Result from other FPU block
input earlyressel; // Select result from other block
input [1:1] bypsel; // Bypass X or Z
input byppostnorm; // Postnormalize bypassed result
input killprod; // Z >> product
input sumzero; // sum exactly equals zero
input postnormalize; // postnormalize rounded result
input [8:0] normcnt; // normalization shift count
input infinity; // generate infinity on overflow
input invalid; // Result invalid
input overflow; // Result overflowed
input underflow; // Result underflowed
input inf; // Some input is infinity
input nan; // Some input is NaN
input xnan; // X is NaN
input ynan; // Y is NaN
input znan; // Z is NaN
input zdenorm; // Z is denorm
input specialsel; // Select special result
output [11:0] aligncnt; // shift count for alignment shifter
output [62:52] w; // Exponent of result
output [62:52] wbypass; // Prerounded exponent for bypass
output prodof; // X*Y exponent out of bounds
output sumof; // X*Y+Z exponent out of bounds
output sumuf; // X*Y+Z exponent underflows
output denorm0; // exponent = 0 for denorm
output [12:0] ae; //exponent of multiply
// Internal nodes
wire [12:0] aetmp; // Exponent of Multiply
wire [12:0] aligncnt0; // Shift count for alignment
wire [12:0] aligncnt1; // Shift count for alignment
wire [12:0] be; // Exponent of multiply
wire [12:0] de0; // Normalized exponent
wire [12:0] de1; // Normalized exponent
wire [12:0] de; // Normalized exponent
wire [10:0] infinityres; // Infinity or max number
wire [10:0] nanres; // Nan propagated or generated
wire [10:0] specialres; // Exceptional case result
// Compute exponent of multiply
// Note that the exponent does not have to be incremented on a postrounding
// normalization of X because the mantissa was already increased. Report
// if exponent is out of bounds
assign ae = x + y - 1023;
assign prodof = (ae > 2046 && ~ae[12] && ~killprod);
// Compute alignment shift count
// Adjust for postrounding normalization of Z.
// This should not increas the critical path because the time to
// check if a round overflows is shorter than the actual round and
// is masked by the bypass mux and two 10 bit adder delays.
assign aligncnt0 = z - ae[10:0] + 13'b0;
assign aligncnt1 = z - ae[10:0] + 13'b1;
assign aligncnt = bypsel[1] && byppostnorm ? aligncnt1 : aligncnt0;
// Select exponent (usually from product except in case of huge addend)
assign be = killprod ? z : ae;
// Adjust exponent based on normalization
// A compound adder takes care of the case of post-rounding normalization
// requiring an extra increment
assign de0 = sumzero ? 13'b0 : be + 53 - normcnt;
assign de1 = sumzero ? 13'b0 : be + 53 - normcnt + 13'b1;
// If the exponent becomes exactly zero (denormalized)
// signal such to adjust R bit before rounding
assign denorm0 = (de0 == 0);
// check for exponent out of bounds after add
assign de = postnormalize ? de1 : de0;
assign sumof = de > 2046 && ~de[12];
assign sumuf = (de == 0 || de[12]) && ~sumzero && ~zdenorm;//KEP ~zdenorm to prevent underflow flag
// bypass occurs before rounding or taking early results
assign wbypass = de0[10:0];
// In a non-critical special mux, we combine the early result from other
// FPU blocks with the results of exceptional conditions. Overflow
// produces either infinity or the largest finite number, depending on the
// rounding mode. NaNs are propagated or generated.
assign specialres = earlyressel ? earlyres :
invalid ? nanres :
overflow ? infinityres :
inf ? 11'b11111111111 :
underflow ? 11'b0 : 11'bx;
assign infinityres = infinity ? 11'b11111111111 : 11'b11111111110;
assign nanres = xnan ? x : (ynan ? y : (znan? z : 11'b11111111111));
// A mux selects the early result from other FPU blocks or the
// normalized FMAC result. Special cases are also detected.
assign w = specialsel ? specialres[10:0] : de;
endmodule

View File

@ -0,0 +1,85 @@
///////////////////////////////////////////////////////////////////////////////
// Block Name: flag.v
// Author: David Harris
// Date: 12/6/1995
//
// Block Description:
// This block generates the flags: invalid, overflow, underflow, inexact.
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module flag(xnan, ynan, znan, xinf, yinf, zinf, prodof, sumof, sumuf,
psign, zsign, xzero, yzero, v[1:0],
inf, nan, invalid, overflow, underflow, inexact);
/////////////////////////////////////////////////////////////////////////////
input xnan; // X is NaN
input ynan; // Y is NaN
input znan; // Z is NaN
input xinf; // X is Inf
input yinf; // Y is Inf
input zinf; // Z is Inf
input prodof; // X*Y overflows exponent
input sumof; // X*Y + z underflows exponent
input sumuf; // X*Y + z underflows exponent
input psign; // Sign of product
input zsign; // Sign of z
input xzero; // x = 0
input yzero; // y = 0
input [1:0] v; // R and S bits of result
output inf; // Some source is Inf
output nan; // Some source is NaN
output invalid; // Result is invalid
output overflow; // Result overflowed
output underflow; // Result underflowed
output inexact; // Result is not an exact number
// Internal nodes
wire prodinf; // X*Y larger than max possible
wire suminf; // X*Y+Z larger than max possible
// If any input is NaN, propagate the NaN
assign nan = xnan || ynan || znan;
// Same with infinity (inf - inf and O * inf don't propagate inf
// but it's ok becaue illegal op takes higher precidence)
assign inf= xinf || yinf || zinf;
// Generate infinity checks
assign prodinf = prodof && ~xnan && ~ynan;
assign suminf = sumof && ~xnan && ~ynan && ~znan;
// Set invalid flag for following cases:
// 1) Inf - Inf
// 2) 0 * Inf
// 3) Output = NaN (this is not part of the IEEE spec, only 486 proj)
assign invalid = (xinf || yinf || prodinf) && zinf && (psign ^ zsign) ||
xzero && yinf || yzero && xinf ||
nan;
// Set the overflow flag for the following cases:
// 1) Rounded multiply result would be out of bounds
// 2) Rounded add result would be out of bounds
assign overflow = suminf && ~inf;
// Set the underflow flag for the following cases:
// 1) Any input is denormalized
// 2) Output would be denormalized or smaller
assign underflow = (sumuf && ~inf && ~prodinf && ~nan);
// Set the inexact flag for the following cases:
// 1) Multiplication inexact
// 2) Addition inexact
// One of these cases occurred if the R or S bit is set
assign inexact = (v[0] || v[1] || suminf) && ~(inf || nan);
endmodule

View File

@ -0,0 +1,130 @@
////////////////////////////////////////////////////////////////////////////////
// Block Name: fmac.v
// Author: David Harris
// Date: 11/2/1995
//
// Block Description:
// This is the top level block of a floating-point multiply/accumulate
// unit(FMAC). It instantiates the following sub-blocks:
//
// array Booth encoding, partial product generation, product summation
// expgen Exponent summation, compare, and adjust
// align Alignment shifter
// add Carry-save adder for accumulate, carry propagate adder
// lza Leading zero anticipator to control normalization shifter
// normalize Normalization shifter
// round Rounding of result
// exception Handles exceptional cases
// bypass Handles bypass of result to X or Z inputs
// sign One bit sign handling block
// special Catch special cases (inputs = 0 / infinity / etc.)
//
// The FMAC computes W=X*Y+Z, rounded with the mode specified by
// RN, RZ, RM, or RP. The result is optionally bypassed back to
// the X or Z inputs for use on the next cycle. In addition, four signals
// are produced: trap, overflow, underflow, and inexact. Trap indicates
// an infinity, NaN, or denormalized number to be handled in software;
// the other three signals are IEEE flags.
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module fmac(xrf, y, zrf, rn, rz, rp, rm,
earlyres, earlyressel, bypsel, bypplus1, byppostnorm,
w, wbypass, invalid, overflow, underflow, inexact);
/////////////////////////////////////////////////////////////////////////////
input [63:0] xrf; // input X from reg file
input [63:0] y; // input Y
input [63:0] zrf; // input Z from reg file
input rn; // Round to Nearest
input rz; // Round toward zero
input rm; // Round toward minus infinity
input rp; // Round toward plus infinity
input [63:0] earlyres; // Early result from other FP logic
input earlyressel; // Select early result, not W
input [1:0] bypsel; // Select W bypass to X, or z
input bypplus1; // Add one in bypass
input byppostnorm; // postnormalize in bypass
output [63:0] w; // output W=X*Y+Z
output [63:0] wbypass; // prerounded output W=X*Y+Z for bypass
output invalid; // Result is invalid
output overflow; // Result overflowed
output underflow; // Result underflowed
output inexact; // Result is not an exact number
// Internal nodes
wire [63:0] x; // input X after bypass mux
wire [63:0] z; // input Z after bypass mux
wire [105:0] r; // one result of partial product sum
wire [105:0] s; // other result of partial products
wire [157:0] t; // output of alignment shifter
wire [157:0] sum; // output of carry prop adder
wire [53:0] v; // normalized sum, R, S bits
wire [11:0] aligncnt; // shift count for alignment
wire [8:0] normcnt; // shift count for normalizer
wire [12:0] ae; // multiplier expoent
wire bs; // sticky bit of addend
wire ps; // sticky bit of product
wire killprod; // Z >> product
wire negsum; // negate sum
wire invz; // invert addend
wire selsum1; // select +1 mode of sum
wire negsum0; // sum +0 < 0
wire negsum1; // sum +1 < 0
wire sumzero; // sum = 0
wire infinity; // generate infinity on overflow
wire prodof; // X*Y out of range
wire sumof; // result out of range
// Instantiate fraction datapath
array array(x[51:0], y[51:0], xdenorm, ydenorm, r[105:0], s[105:0],
bypsel[0], bypplus1);
align align(z[51:0], ae, aligncnt, xzero, yzero, zzero, zdenorm, proddenorm,
t[157:0], bs, ps, killprod,
bypsel[1], bypplus1, byppostnorm);
add add(r[105:0], s[105:0], t[157:0], sum[157:0],
negsum, invz, selsum1, killprod, negsum0, negsum1, proddenorm);
lop lop(sum, normcnt, sumzero);
normalize normalize(sum[157:0], normcnt, sumzero, bs, ps, denorm0, zdenorm,
v[53:0]);
round round(v[53:0], earlyres[51:0], earlyressel, rz, rn, rp, rm, w[63],
invalid, overflow, underflow, inf, nan, xnan, ynan, znan,
x[51:0], y[51:0], z[51:0],
w[51:0], postnorrnalize, infinity, specialsel);
bypass bypass(xrf[63:0], zrf[63:0], wbypass[63:0], bypsel[1:0],
x[63:0], z[63:0]);
// Instantiate exponent datapath
expgen expgen(x[62:52], y[62:52], z[62:52],
earlyres[62:52], earlyressel, bypsel[1], byppostnorm,
killprod, sumzero, postnorrnalize, normcnt,
infinity, invalid, overflow, underflow,
inf, nan, xnan, ynan, znan, zdenorm, specialsel,
aligncnt, w[62:52], wbypass[62:52],
prodof, sumof, sumuf, denorm0, ae);
// Instantiate special case detection across datapath & exponent path
special special(x[63:0], y[63:0], z[63:0], ae, xzero, yzero, zzero,
xnan, ynan, znan, xdenorm, ydenorm, zdenorm, proddenorm,
xinf, yinf, zinf);
// Produce W for bypass
assign wbypass[51:0] = v[53:2];
assign wbypass[63] = w[63];
// Instantiate control logic
sign sign(x[63], y[63], z[63], negsum0, negsum1, bs, ps,
killprod, rm, sumzero, nan, invalid, xinf, yinf, inf,
w[63], invz, negsum, selsum1, psign);
flag flag(xnan, ynan, znan, xinf, yinf, zinf, prodof, sumof, sumuf,
psign, z[63], xzero, yzero, v[1:0],
inf, nan, invalid, overflow, underflow, inexact);
endmodule

View File

@ -0,0 +1,41 @@
///////////////////////////////////////////////////////////////////////////////
// Block Name: lop.v
// Author: David Harris
// Date: 11/2/1995
//
// Block Description:
// This block implements a Leading One Predictor used to determine
// the normalization shift count.
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module lop(sum, normcnt, sumzero);
/////////////////////////////////////////////////////////////////////////////
input [157:0] sum; // sum
output [8:0] normcnt; // normalization shift count
output sumzero; // sum = 0
// Internal nodes
reg [8:0] i; // loop index
reg [8:0] normcnt; // normalization shift count
// A real LOP uses a fast carry chain to find only the first 0.
// It is an example of a parallel prefix algorithm. For the sake
// of simplicity, this model is behavioral instead.
// A real LOP would also operate on the sources of the adder, not
// the result!
always @ ( sum)
begin
i = 0;
while (~sum[157-i] && i < 157) i = i+1; // search for leading one
normcnt = i; // compute shift count
end
// Also check if sum is zero
assign sumzero = ~(|sum);
endmodule

View File

@ -0,0 +1,63 @@
///////////////////////////////////////////////////////////////////////////////
// Block Name: normalize.v
// Author: David Harris
// Date: 11/2/1995
//
// Block Description:
// This block performs the normalization shift. It also
// generates the Rands bits for rounding. Finally, it
// handles the special case of a zero sum.
//
// v[53:2] is the fraction component of the prerounded result.
// It can be bypassed back to the X or Z inputs of the FMAC
// for back-to-back operations.
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module normalize(sum[157:0], normcnt, sumzero, bs, ps, denorm0, zdenorm, v[53:0]);
/////////////////////////////////////////////////////////////////////////////
input [157:0] sum; // sum
input [8:0] normcnt; // normalization shift count
input sumzero; // sum is zero
input bs; // sticky bit for addend
input ps; // sticky bit for product
input denorm0; // exponent = -1023
input zdenorm; // Input Z is denormalized
output [53:0] v; // normalized sum, R, S bits
// Internal nodes
reg [53:0] v; // normalized sum, R, S bits
wire [157:0] sumshifted; // shifted sum
// When the sum is zero, normalization does not apply and only the
// sticky bit must be computed. Otherwise, the sum is right-shifted
// and the Rand S bits (v[1] and v[O], respectively) are assigned.
// The R bit is also set on denormalized numbers where the exponent
// was computed to be exactly -1023 and the L bit was set. This
// is required for correct rounding up of multiplication results.
// The sticky bit calculation is actually built into the shifter and
// does not require a true subtraction shown in the model.
always @(sum or normcnt or sumzero or bs or ps or sumshifted or denorm0)
begin
if (sumzero) begin // special case
v[53:1] = 0;
v[0] = ps || bs ;
end else begin // extract normalized bits
v[53:3] = sumshifted[156:106];
// KEP prevent plus1 in round.v when z is denormalized.
v[2] = sumshifted[105] || sumshifted[106] && denorm0 && ~zdenorm;
v[1] = sumshifted[104] || sumshifted[105] && denorm0 && ~zdenorm;
v[0] = |(sumshifted[103:0]) || ps || bs;
end
end
// shift sum left by normcnt, filling the right with zeros
assign sumshifted = sum << normcnt;
endmodule

View File

@ -0,0 +1,106 @@
/////////////////////////////////////////////////////////////////////////////
// Block Name: round.v
// Author: David Harris
// Date: 11/2/1995
//
// Block Description:
// This block is responsible for rounding the normalized result of // the FMAC. Because prenormalized results may be bypassed back to // the FMAC X and z inputs, rounding does not appear in the critical // path of most floating point code. This is good because rounding // requires an entire 52 bit carry-propagate half-adder delay.
//
// The results from other FPU blocks (e.g. FCVT, FDIV, etc) are also
// muxed in to form the actual result for register file writeback. This
// saves a mux from the writeback path.
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module round(v[53:0], earlyres[51:0], earlyressel, rz, rn, rp, rm, wsign,
invalid, overflow, underflow, inf, nan, xnan, ynan, znan,
x[51:0], y[51:0], z[51:0],
w[51:0], postnormalize, infinity, specialsel);
/////////////////////////////////////////////////////////////////////////////
input [53:0] v; // normalized sum, R, S bits
input [51:0] earlyres; // result from other FPU blocks
input earlyressel; // use result from other FPU blocks
input rz; // Round toward zero
input rn; // Round toward nearest
input rp; // Round toward plus infinity
input rm; // Round toward minus infinity
input wsign; // Sign of result
input invalid; // Trap on infinity, NaN, denorm
input overflow; // Result overflowed
input underflow; // Result underflowed
input inf; // Some input is infinity
input nan; // Some input is NaN
input xnan; // X is NaN
input ynan; // Y is NaN
input znan; // Z is NaN
input [51:0] x; // Input X
input [51:0] y; // Input Y
input [51:0] z; // Input Z
output [51:0] w; // rounded result of FMAC
output postnormalize; // Right shift 1 for post-rounding norm
output infinity; // Generate infinity on overflow
output specialsel; // Select special result
// Internal nodes
wire plus1; // Round by adding one
wire [52:0] v1; // Result + 1 (for rounding)
wire [51:0] specialres; // Result of exceptional case
wire [51:0] infinityres; // Infinity or largest real number
wire [51:0] nanres; // Propagated or generated NaN
// Compute if round should occur. This equation is derived from
// the rounding tables.
assign plus1 = rn && ((v[1] && v[0]) || (v[2] && (v[1]))) ||
rp && ~wsign && (v[1] || v[0]) ||
rm && wsign && (v[1] || v[0]);
// Compute rounded result
assign v1 = v[53:2] + 1;
// Determine if postnormalization is necessary
// Predicted by all bits =1 before round +1
assign postnormalize = &(v[53:2]) && plus1;
// Determine special result in event of of selection of a result from
// another FPU functional unit, infinity, NAN, or underflow
// The special result mux is a 4:1 mux that should not appear in the
// critical path of the machine. It is not priority encoded, despite
// the code below suggesting otherwise. Also, several of the identical data
// inputs to the wide muxes can be combined at the expense of more
// complicated non-critical control in the circuit implementation.
assign specialsel = earlyressel || overflow || underflow || invalid ||
nan || inf;
assign specialres = earlyressel ? earlyres :
invalid ? nanres :
overflow ? infinityres :
inf ? 52'b0 :
underflow ? 52'b0 : 52'bx; // default to undefined
// Overflow is handled differently for different rounding modes
// Round is to either infinity or to maximum finite number
assign infinity = rn || (rp && ~wsign) || (rm && wsign);
assign infinityres = infinity ? 52'b0 : {52{1'b1}};
// Invalid operations produce a quiet NaN. The result should
// propagate an input if the input is NaN. Since we assume all
// NaN inputs are already quiet, we don't have to force them quiet.
// assign nanres = xnan ? x: (ynan ? y : (znan ? z : {1'b1, 51'b0})); // original
assign nanres = xnan ? {1'b1, x[50:0]}: (ynan ? {1'b1, y[50:0]} : (znan ? {1'b1, z[50:0]} : {1'b1, 51'b0}));// KEP 210112 add the 1 to make NaNs quiet
// Select result with 4:1 mux
// If the sum is zero and we round up, there is a special case in
// which we produce a massive loss of significance and trap to software.
// It is handled in the exception unit.
assign w = specialsel ? specialres : (plus1 ? v1[51:0] : v[53:2]);
endmodule

View File

@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////////
// Block Name: sign.v
// Author: David Harris
// Date: 12/1/1995
//
// Block Description:
// This block manages the signs of the numbers.
// 1 = negative
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module sign(xsign, ysign, zsign, negsum0, negsum1, bs, ps, killprod, rm,
sumzero, nan, invalid, xinf, yinf, inf, wsign, invz, negsum, selsum1, psign);
////////////////////////////////////////////////////////////////////////////I
input xsign; // Sign of X
input ysign; // Sign of Y
input zsign; // Sign of Z
input negsum0; // Sum in +O mode is negative
input negsum1; // Sum in +1 mode is negative
input bs; // sticky bit from addend
input ps; // sticky bit from product
input killprod; // Product forced to zero
input rm; // Round toward minus infinity
input sumzero; // Sum = O
input nan; // Some input is NaN
input invalid; // Result invalid
input xinf; // X = Inf
input yinf; // Y = Inf
input inf; // Some input = Inf
output wsign; // Sign of W
output invz; // Invert addend into adder
output negsum; // Negate result of adder
output selsum1; // Select +1 mode from compound adder
output psign; // sign of product X * Y
// Internal nodes
wire zerosign; // sign if result= 0
wire infsign; // sign if result= Inf
reg negsum; // negate result of adder
reg selsum1; // select +1 mode from compound adder
// Compute sign of product
assign psign = xsign ^ ysign;
// Invert addend if sign of Z is different from sign of product assign invz = zsign ^ psign;
assign invz = zsign ^ psign;
// Select +l mode for adder and compute if result must be negated
// This is done according to cases based on the sticky bit.
always @(invz or negsum0 or negsum1 or bs or ps)
begin
if (~invz) begin // both inputs have same sign
negsum = 0;
selsum1 = 0;
end else if (bs) begin // sticky bit set on addend
selsum1 = 0;
negsum = negsum0;
end else if (ps) begin // sticky bit set on product
selsum1 = 1;
negsum = negsum1;
end else begin // both sticky bits clear
selsum1 = negsum1; // KEP 210113-10:44 Selsum1 was adding 1 to values that were multiplied by 0
// selsum1 = ~negsum1; //original
negsum = negsum1;
end
end
// Compute sign of result
// This involves a special case when the sum is zero:
// x+x retains the same sign as x even when x = +/- 0.
// otherwise, x-x = +O unless in the RM mode when x-x = -0
// There is also a special case for NaNs and invalid results;
// the sign of the NaN produced is forced to be 0.
// Sign calculation is not in the critical path so the cases
// can be tolerated.
// IEEE 754-2008 section 6.3 states
// "When ether an input or result is NaN, this standard does not interpret the sign of a NaN."
// also pertaining to negZero it states:
// "When the sum/difference of two operands with opposite signs is exactly zero, the sign of that sum/difference
// shall be +0 in all rounding attributes EXCEPT roundTowardNegative. Under that attribute, the sign of an exact zero
// sum/difference shall be -0. However, x+x = x-(-X) retains the same sign as x even when x is zero."
assign zerosign = (~invz && killprod) ? zsign : rm;
assign infsign = psign; //KEP 210112 keep the correct sign when result is infinity
// assign infsign = xinf ? (yinf ? psign : xsign) : yinf ? ysign : zsign;//original
assign wsign =invalid? 0 : (inf ? infsign:
(sumzero ? zerosign : psign ^ negsum));
endmodule

View File

@ -0,0 +1,70 @@
///////////////////////////////////////////////////////////////////////////////
// Block Name: special.v
// Author: David Harris
// Date: 12/2/1995
//
// Block Description:
// This block implements special case handling for unusual operands (e.g.
// 0, NaN, denormalize, infinity). The block consists of zero/one detectors.
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module special(x[63:0], y[63:0], z[63:0], ae, xzero, yzero, zzero,
xnan, ynan, znan, xdenorm, ydenorm, zdenorm, proddenorm, xinf, yinf, zinf);
/////////////////////////////////////////////////////////////////////////////
input [63:0] x; // Input x
input [63:0] y; // Input Y
input [63:0] z; // Input z
input [12:0] ae; // exponent of product
output xzero; // Input x = 0
output yzero; // Input y = 0
output zzero; // Input z = 0
output xnan; // x is NaN
output ynan; // y is NaN
output znan; // z is NaN
output xdenorm; // x is denormalized
output ydenorm; // y is denormalized
output zdenorm; // z is denormalized
output proddenorm; // product is denormalized
output xinf; // x is infinity
output yinf; // y is infinity
output zinf; // z is infinity
// In the actual circuit design, the gates looking at bits
// 51:0 and at bits 62:52 should be shared among the various detectors.
// Check if input is NaN
assign xnan = &x[62:52] && |x[51:0];
assign ynan = &y[62:52] && |y[51:0];
assign znan = &z[62:52] && |z[51:0];
// Check if input is denormalized
assign xdenorm = ~(|x[62:52]) && |x[51:0];
assign ydenorm = ~(|y[62:52]) && |y[51:0];
assign zdenorm = ~(|z[62:52]) && |z[51:0];
assign proddenorm = &ae & ~xzero & ~yzero; //KEP is the product denormalized
// Check if input is infinity
assign xinf = &x[62:52] && ~(|x[51:0]);
assign yinf = &y[62:52] && ~(|y[51:0]);
assign zinf = &z[62:52] && ~(|z[51:0]);
// Check if inputs are all zero
// Also forces denormalized inputs to zero.
// In the circuit implementation, this can be optimized
// to just check if the exponent is zero.
// KATHERINE - commented following (21/01/11)
// assign xzero = ~(|x[62:0]) || xdenorm;
// assign yzero = ~(|y[62:0]) || ydenorm;
// assign zzero = ~(|z[62:0]) || zdenorm;
// KATHERINE - removed denorm to prevent outputing zero when computing with a denormalized number
assign xzero = ~(|x[62:0]);
assign yzero = ~(|y[62:0]);
assign zzero = ~(|z[62:0]);
endmodule

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,199 @@
c22000007fffffff 24700000ffffffef a6a00001800007ed
bfc00000000011fe 3fdfffffffffff03 bfb000000000117f
a83100000007fffe 41e0000effffffff aa21000ff0080004
0000000000000000 001ffffffffffffe 0000000000000000
400327ca64d70ec7 3ca0000000000001 3cb327ca64d70ec9
0000000000000000 43e207ffffffffff 0000000000000000
0000000000000000 3fd0000000000000 0000000000000000
0000000000000000 3fdfffffffffffff 0000000000000000
0000000000000000 3fe0000000000000 0000000000000000
c870200000010000 3fefffffffffffff c87020000000ffff
c00aaa4fd557ef13 c3b8917384eb32d0 43d478efdc9216d8
0000000000000000 7ffc000000000000 7ff8000000000000
0000000000000000 c18aca47203438e2 0000000000000000
0000000000000000 4000000000000001 0000000000000000
47efff0008000000 b1dcb0523546117f b9dcaf6cb9e07bdb
43f000ffffff7fff 22300000001fffdf 26300100001f81de
402ff000001fffff 40759558e27de226 40b58a8e3622388e
0000000000000000 40efdeffffffffff 0000000000000000
0000000000000000 434fffffffffffff 0000000000000000
7ffc000000000000 7fe0000000000000 7ff8000000000000
b35e061abc769f3a c078000003fffffe 33e684941119bac2
403a793cfb1e2471 bff0000100007fff c03a793ea2b2c7eb
3d1ffffbfe000000 216898822a24af3f 1e98987f158ae1d8
bfb00000001bffff 7ffc000000000000 7ff8000000000000
37f0000000efffff c3d00007fffffeff bbd0000800efff75
0000000000000000 ffefff8000080000 0000000000000000
3fb00200000000ff c0000000011fffff bfc00200012024fd
41c0000007ffffff 49103fffefffffff 4ae03ffff81ffff6
407effbfffffffff 3e00000040001fff 3e8effc07bff3dfd
c1f00013fffffffe 7ffc000000000000 7ff8000000000000
c3f00004000001ff c3d00bfffffffffe 47d00c04030001ff
403b5ab30b28be12 bfdfffffffffffff c02b5ab30b28be11
0000000000000000 c1cfffffff87ffff 0000000000000000
0000000000000000 bfe0000000000001 0000000000000000
801ffc000007ffff bfeffffffffffffe 001ffc000007fffe
0000000000000000 ffe0000005fffffe 0000000000000000
0000000000000000 bfffffffffffffff 0000000000000000
0000000000000000 c000000000000000 0000000000000000
c3d09308769f3f51 c00fffffffffffff 43f09308769f3f51
0000000000000000 402ffffdfefffffe 0000000000000000
0000000000000000 c010000000000001 0000000000000000
c01fffffffc00fff c01ffffffffffffe 404fffffffc00ffe
c025e14360f49046 412fff0000000003 c165e09456d988a3
0000000000000000 43ee59a2f1155c8b 0000000000000000
3fe0000000008fff 802ffffff7fffff6 801ffffff8011ff3
0000000000000000 ffefffffffffffff 0000000000000000
40401007fffffffe fff0000000000000 80401007fffffffe
0000000000000000 c0045abb4860cbf3 0000000000000000
0000000000000000 7ffc000000000000 7ff8000000000000
bffffffec0000000 c000000000003eff 400ffffec0007dfe
48000000004001ff 41f331de979ac49e 4a0331de97e78e7e
3d0fffffbff7ffff 7ffc000000000000 7ff8000000000000
43d3ffffff000000 3caffffffffffffe 4093fffffeffffff
7ffc000000000000 43dfff8004000000 7ff8000000000000
bcaffe0000000008 3fd00008000000ff bc8ffe0fff000205
404ffbfffffffffc c34ffff8003fffff c3affbf8013ff7fb
43e0000000000082 3db000003ffffeff 41a000003fffff82
c1d004000ffffffe 4000000000000000 c1e004000ffffffe
c00fffffc000007e c02ffffdfffffbff 404ffffdc000007e
409dfffbffffffff 4010000000000001 40bdfffc00000001
c120000003ffffe0 c06000fffbffffff 4190010000003fde
3fd1f7ffffffffff c01000001dffffff bff1f80021b0fffd
2e0fefdfffffffff 4030000020000040 2e4fefe03fdfc07f
43c0000803ffffff 3fcfffffffffffff 43a0000803ffffff
c0afffffbffffdfe 3fc07ffdffffffff c0807ffddf0002f5
c0fffffffeffffee 55139bb9349e058c d6239bb9340127b7
41ffdbaf18ce06bd 8010000000000000 821fdbaf18ce06bd
c0e1000000080000 801ffffffffffffe 011100000007ffff
3fbffffff0000007 c807dfffffffffff c7d7dffff4100004
c357b53537b96da5 bfd0000000000000 4337b53537b96da5
401fffffffffffff ffebff8000000000 801bff7fffffffff
c7eff77bf2b59c3c bfe0000000000001 47dff77bf2b59c3e
380c3f72cc3dec98 c3fffffffbffffff bc1c3f72c8b5fe3d
b8e0000003fbffff c503f4d44f4bf888 3df3f4d454443066
3f3ffffc001fffff c000000000000001 bf4ffffc00200000
c340002000004000 c0db3367e0423019 442b339e47125d6b
4f60000801ffffff 41c07fe000000000 51307fe841fffbff
c1ffffffbfefffff c340000000000001 454fffffbff00001
404fff7fffffff7f 48ab7e2aad4ec686 490b7dbcb4a410dd
7ffc000000000000 ffefffffffffffff 7ff8000000000000
41e189ea1a6fff97 7ffc000000000000 7ff8000000000000
3ff0ee9046c9330f 8479e1e79766e02b 847b63d14ff91acb
d2f805130a8c11df 43effffdfdfffffe d6f8051188ba9004
4f1fffbfffe00000 bcd02000000007ff cc001fdfbfefe7fe
be70000077ffffff c1efffffffffffff 4070000077ffffff
41e1ffffbffffffe 3caffffffffffffe 3ea1ffffbffffffd
3bbd976272fb1d2a c06ffff80007fffe bc3d975b0d29e641
434fff01ffffffff 403dfeffffffffff 439dfe11e7efffff
be6fff7fffffffff 3feffffffffffffe be6fff7ffffffffd
41d007ff80000000 41f0fffffffc0000 43d1087f77fbfe01
ffeef7a206029708 bdcfa4109a3a5b22 7dce9eaa2542875b
3b6ffffffeffffc0 3c7ffffe003ffffe 37fffffdff3fffce
c1d1ffffffbfffff bfcffffefffff800 41b1ffff6fbffb82
2030000000000090 c05e2e90015c47a1 a09e2e90015c48b0
bbf000000007efff 001fe0000007fffe fc1fe0000017d01c
41cae866712069f4 c02fffffffffffff c20ae866712069f3
bfce1e32ccf56348 3ca1f66d4c8eeef3 bc80e7fa025544da
ffedfffff0000000 ffeffff000000800 3fedfff0f0000f80
37effffc3ffffffe bca0fffffffffffd b4a0fffe01fffffb
bc950a021bf9dee1 3db0001fffdffffe ba550a2c2fd402cd
fd4fffffdfffffef 41cffffdffffffef ff2ffffde00001de
bfc00000004007ff bcafffffffffffff 3c800000004007ff
c009130b80fe8274 b811571307061a38 382b2cb1993b60f3
c0600000ffffffdf 7feda1b8c591f9c6 805da1ba9fad85e2
c1e4af3f8d45e031 3ca0020002000000 be94b1d577cd70de
3800008100000000 b810000020000080 b020008120010280
372ff00000003fff 7fe000fdfffffffe 771ff1fb02003fff
47d00021fffffffe c00fffffffffffff c7f00021fffffffd
bfbc9ea0c2b4884b 43f4a552574073d5 c3c277000b21a4e7
bf1fe0000000ffff c01ffffffffffffe 3f4fe0000000fffe
41ffffffff7ffffb 0027ffffffffeffe 0237ffffff9feffb
c7e040000fffffff ffe0000000000000 07d040000fffffff
7ffc000000000000 3fe0000ffffff7ff 7ff8000000000000
c1effc1fffffffff 7ffc000000000000 7ff8000000000000
c0d000000001ffbf c03ba46e644e4e9c 411ba46e6451c2ba
c4500000005fffff c03a20ab4de47fc9 449a20ab4e8143cc
400e00000000007e 001fffffffffffff 003e00000000007e
45a01fffff7fffff c3c0020200000000 c9702206037fefee
3e8ff800000000ff 3caffffffffffffe 3b4ff800000000fe
be004000000007fe 3fdffff7ff7fffff bdf03ffbefbf07fd
b11000007ffffe00 3fe0000000000000 b10000007ffffe00
b80cef50bd17db40 c05fffc00000000e 387cef16de76611d
3d4000ffffffffff 3d47f68d8eb6b9a4 3a97f80cf78fa50f
ffe3fffffffffffb c03dc3321aaa5380 003299ff50aa742c
3ca3fffffffffeff bf02ffafb4e9241d bbb7bf9ba2236bf3
53598c812c3c39dd 3f20000100fffffe 52898c82c69d14b1
c3dffffff8000001 3fe0020000003ffe c3d001fffbffbffe
7ba00800003fffff 3ff9a9a129c791b3 7ba9b675fac31bff
c3d0000fffffffef 7fe0000000000001 83c0000ffffffff0
c34f80001fffffff b7fffffe0007ffff 3b5f7ffe2807ddff
0010000000001ff8 4800020000010000 0820020000011ffc
2c4c0000003fffff 230ffffc00400000 0f6bfffc8077fff8
381fffffffbff7fe 8010000000000000 f83fffffffbff7fe
802d3018ea8c241d c007fdffffffffff 0045e23fae5a7253
43e047fffffffffe 4000003ffdfffffe 43f048411df6fffc
c000005fffffffff 403ffffffff00002 c050005ffff7ffd0
3fc8b60e46a80f6d bfdffffffffffffe bfb8b60e46a80f6b
bd5fdffdffffffff 5644b72ace1bbb6b d3b4a27257daf2cd
b80010001fffffff 40e01ffffff7fffe b8f030202037f7fc
407000003ffbfffe 38042862fe8e3368 388428634f2ab547
bf8ffbfff7ffffff c00fffffffffffff 3faffbfff7ffffff
bcafc000003fffff c010000000000001 3ccfc00000400001
47eddf042473ef08 b7e00000fe000000 bfdddf05fea850ca
3fbfffff7fffffef c340ffffffffffbf c310ffffbbffffb5
c02f8000000007ff ffe0000000000001 001f800000000801
002f37ebf6c8eaec c08be464f4c81c69 80cb36000706e168
c00e800000000000 7ffc000000000000 7ff8000000000000
0010000000000000 0000000000000000 0000000000000000
bfffc00000000003 391001ffffffffff b91fc3f800000001
c1db54446247aa52 bfcc001fffffffff 41b7e9d72a43174f
0010000000000000 c0392c59c8e48f37 80592c59c8e48f37
0010000000000000 c0000800000001ff 80200800000001ff
0010000000000000 c1d0000004000fff 81f0000004000fff
4030040000200000 0017055f48beeff5 00570b20a0bf2a70
bc7000000000ffee c1e0001100000000 3e6000110000fff0
c040000000007fff c3b2a6c91c557f56 4402a6c91c56148c
41ffffffff003fff c3b0000007ffffee c5c0000007801fed
21900001dfffffff bf20000017fffffe a0c00001f80002cc
0029954d0f0df5b3 41e00000000003ff 0219954d0f0dfc17
b810000020000001 47ffdfffffffff80 c01fe0003fbfff81
0010000000000000 ffeffff800007fff c00ffff800007fff
0010000000000000 4010000000000000 0030000000000000
bf700000000100ff 401fffffffffffff bfa00000000100fe
37feffffffffffff 47ef8000000fffff 3ffe8400000f7fff
b80f800001fffffe 44e00000ffff7fff bcff8001f9ff041c
0010000000000000 434ffffffffffffe 036ffffffffffffe
41ffffdfffff8000 7fe0000000000001 01efffdfffff8002
b80a16ad02c87cd3 380fffffffffe7fe b02a16ad02c86940
47f0fffffffffffb 7ffc000000000000 7ff8000000000000
0010000000000000 41ffffffffbfff7f 021fffffffbfff7f
0010000000000000 8000000000000000 0000000000000000
c3d00001000001ff b7f60cb3edb38762 3bd60cb54e7ec8fe
0010000000000000 8010000000000001 c030000000000001
43c0007fffdfffff 801ffffffffffffe 83f0007fffdffffd
c7efffffdffffbff bca0000000000001 449fffffdffffc01
0010000000000000 c11ff00000000003 813ff00000000003
0010000000000000 bfd0000000000000 ffefffffffffffff
c0ffffffffeffffe bfdfffffffffffff 40efffffffeffffe
6f7000000001fdff 1510010000000fff 4490010000020e1e
37f002000000000f b1effcfffffffffe a9f0007fd000000d
cc3050bc013d7cd7 bff0000000000000 4c3050bc013d7cd7
0010000000000000 87fff0000000fffe c81ff0000000fffe
0010000000000000 bffffffffffffffe 801ffffffffffffe
43effbfffffff7ff 7fefffffff801ffe 03effbffff8027fa
c015834380f2b995 3f9fff0000000400 bfc5829766d6b4af
0010000000000000 41dfffffc0001000 01ffffffc0001000
0010000000000000 c01fffffffffffff 803fffffffffffff
41e010000000001f c5b04000000fffff c7a050400010101e
3b40018000000000 3ea0400000000100 39f0418600000101
0010000000000000 4cdffeffff7fffff 0cfffeffff7fffff
16dff0001ffffffe 3fb500ae0796659d 16a4f62dc5934871
b7e003ffffffff7f deafffffeffffffd 56a003fff7fdff7e
406000001fffbfff 3f20020000080000 3f900200200bbff8
0010000000000000 7ffc000000000000 7ff8000000000000
439fbffffffbffff bf8454fd38ef0ba0 c3342c533e7aa2e8
c1c000000200007e bf000001ffffffbf 40d000020200007e
480000000008fffe 001637e790e69de2 082637e790f31d52
bffffffc000003fe 3ca0000000000001 bcaffffc000003ff
6b4848a9a8c0dcd5 480ffffffffbdfff 736848a9a8bdbb77

View File

@ -0,0 +1,199 @@
c22000007fffffff 24700000ffffffef a6a00001800007ee
bfc00000000011fe 3fdfffffffffff03 bfb000000000117f
a83100000007fffe 41e0000effffffff aa21000ff0080004
0000000000000000 001ffffffffffffe 0000000000000000
400327ca64d70ec7 3ca0000000000001 3cb327ca64d70ec8
0000000000000000 43e207ffffffffff 0000000000000000
0000000000000000 3fd0000000000000 0000000000000000
0000000000000000 3fdfffffffffffff 0000000000000000
0000000000000000 3fe0000000000000 0000000000000000
c870200000010000 3fefffffffffffff c87020000000ffff
c00aaa4fd557ef13 c3b8917384eb32d0 43d478efdc9216d7
0000000000000000 7ffc000000000000 7ffc000000000000
0000000000000000 c18aca47203438e2 8000000000000000
0000000000000000 4000000000000001 0000000000000000
47efff0008000000 b1dcb0523546117f b9dcaf6cb9e07bdc
43f000ffffff7fff 22300000001fffdf 26300100001f81de
402ff000001fffff 40759558e27de226 40b58a8e3622388d
0000000000000000 40efdeffffffffff 0000000000000000
0000000000000000 434fffffffffffff 0000000000000000
7ffc000000000000 7fe0000000000000 7ffc000000000000
b35e061abc769f3a c078000003fffffe 33e684941119bac1
403a793cfb1e2471 bff0000100007fff c03a793ea2b2c7eb
3d1ffffbfe000000 216898822a24af3f 1e98987f158ae1d8
bfb00000001bffff 7ffc000000000000 7ffc000000000000
37f0000000efffff c3d00007fffffeff bbd0000800efff76
0000000000000000 ffefff8000080000 8000000000000000
3fb00200000000ff c0000000011fffff bfc00200012024fe
41c0000007ffffff 49103fffefffffff 4ae03ffff81ffff6
407effbfffffffff 3e00000040001fff 3e8effc07bff3dfd
c1f00013fffffffe 7ffc000000000000 7ffc000000000000
c3f00004000001ff c3d00bfffffffffe 47d00c04030001fe
403b5ab30b28be12 bfdfffffffffffff c02b5ab30b28be11
0000000000000000 c1cfffffff87ffff 8000000000000000
0000000000000000 bfe0000000000001 8000000000000000
801ffc000007ffff bfeffffffffffffe 001ffc000007fffd
0000000000000000 ffe0000005fffffe 8000000000000000
0000000000000000 bfffffffffffffff 8000000000000000
0000000000000000 c000000000000000 8000000000000000
c3d09308769f3f51 c00fffffffffffff 43f09308769f3f50
0000000000000000 402ffffdfefffffe 0000000000000000
0000000000000000 c010000000000001 8000000000000000
c01fffffffc00fff c01ffffffffffffe 404fffffffc00ffd
c025e14360f49046 412fff0000000003 c165e09456d988a4
0000000000000000 43ee59a2f1155c8b 0000000000000000
3fe0000000008fff 802ffffff7fffff6 801ffffff8011ff4
0000000000000000 ffefffffffffffff 8000000000000000
40401007fffffffe fff0000000000000 fff0000000000000
0000000000000000 c0045abb4860cbf3 8000000000000000
0000000000000000 7ffc000000000000 7ffc000000000000
bffffffec0000000 c000000000003eff 400ffffec0007dfe
48000000004001ff 41f331de979ac49e 4a0331de97e78e7d
3d0fffffbff7ffff 7ffc000000000000 7ffc000000000000
43d3ffffff000000 3caffffffffffffe 4093fffffeffffff
7ffc000000000000 43dfff8004000000 7ffc000000000000
bcaffe0000000008 3fd00008000000ff bc8ffe0fff000206
404ffbfffffffffc c34ffff8003fffff c3affbf8013ff7fb
43e0000000000082 3db000003ffffeff 41a000003fffff81
c1d004000ffffffe 4000000000000000 c1e004000ffffffe
c00fffffc000007e c02ffffdfffffbff 404ffffdc000007d
409dfffbffffffff 4010000000000001 40bdfffc00000001
c120000003ffffe0 c06000fffbffffff 4190010000003fde
3fd1f7ffffffffff c01000001dffffff bff1f80021b0fffe
2e0fefdfffffffff 4030000020000040 2e4fefe03fdfc07f
43c0000803ffffff 3fcfffffffffffff 43a0000803fffffe
c0afffffbffffdfe 3fc07ffdffffffff c0807ffddf0002f6
c0fffffffeffffee 55139bb9349e058c d6239bb9340127b7
41ffdbaf18ce06bd 8010000000000000 821fdbaf18ce06bd
c0e1000000080000 801ffffffffffffe 011100000007ffff
3fbffffff0000007 c807dfffffffffff c7d7dffff4100004
c357b53537b96da5 bfd0000000000000 4337b53537b96da5
401fffffffffffff ffebff8000000000 fff0000000000000
c7eff77bf2b59c3c bfe0000000000001 47dff77bf2b59c3e
380c3f72cc3dec98 c3fffffffbffffff bc1c3f72c8b5fe3e
b8e0000003fbffff c503f4d44f4bf888 3df3f4d454443065
3f3ffffc001fffff c000000000000001 bf4ffffc00200001
c340002000004000 c0db3367e0423019 442b339e47125d6b
4f60000801ffffff 41c07fe000000000 51307fe841fffbff
c1ffffffbfefffff c340000000000001 454fffffbff00001
404fff7fffffff7f 48ab7e2aad4ec686 490b7dbcb4a410dc
7ffc000000000000 ffefffffffffffff 7ffc000000000000
41e189ea1a6fff97 7ffc000000000000 7ffc000000000000
3ff0ee9046c9330f 8479e1e79766e02b 847b63d14ff91acb
d2f805130a8c11df 43effffdfdfffffe d6f8051188ba9004
4f1fffbfffe00000 bcd02000000007ff cc001fdfbfefe7ff
be70000077ffffff c1efffffffffffff 4070000077fffffe
41e1ffffbffffffe 3caffffffffffffe 3ea1ffffbffffffd
3bbd976272fb1d2a c06ffff80007fffe bc3d975b0d29e642
434fff01ffffffff 403dfeffffffffff 439dfe11e7effffe
be6fff7fffffffff 3feffffffffffffe be6fff7ffffffffd
41d007ff80000000 41f0fffffffc0000 43d1087f77fbfe00
ffeef7a206029708 bdcfa4109a3a5b22 7dce9eaa2542875b
3b6ffffffeffffc0 3c7ffffe003ffffe 37fffffdff3fffce
c1d1ffffffbfffff bfcffffefffff800 41b1ffff6fbffb81
2030000000000090 c05e2e90015c47a1 a09e2e90015c48b1
bbf000000007efff 001fe0000007fffe 8000000000000000
41cae866712069f4 c02fffffffffffff c20ae866712069f3
bfce1e32ccf56348 3ca1f66d4c8eeef3 bc80e7fa025544db
ffedfffff0000000 ffeffff000000800 7ff0000000000000
37effffc3ffffffe bca0fffffffffffd b4a0fffe01fffffc
bc950a021bf9dee1 3db0001fffdffffe ba550a2c2fd402ce
fd4fffffdfffffef 41cffffdffffffef ff2ffffde00001de
bfc00000004007ff bcafffffffffffff 3c800000004007fe
c009130b80fe8274 b811571307061a38 382b2cb1993b60f2
c0600000ffffffdf 7feda1b8c591f9c6 fff0000000000000
c1e4af3f8d45e031 3ca0020002000000 be94b1d577cd70df
3800008100000000 b810000020000080 b020008120010280
372ff00000003fff 7fe000fdfffffffe 771ff1fb02003fff
47d00021fffffffe c00fffffffffffff c7f00021fffffffd
bfbc9ea0c2b4884b 43f4a552574073d5 c3c277000b21a4e8
bf1fe0000000ffff c01ffffffffffffe 3f4fe0000000fffd
41ffffffff7ffffb 0027ffffffffeffe 0237ffffff9feffa
c7e040000fffffff ffe0000000000000 7ff0000000000000
7ffc000000000000 3fe0000ffffff7ff 7ffc000000000000
c1effc1fffffffff 7ffc000000000000 7ffc000000000000
c0d000000001ffbf c03ba46e644e4e9c 411ba46e6451c2ba
c4500000005fffff c03a20ab4de47fc9 449a20ab4e8143cb
400e00000000007e 001fffffffffffff 003e00000000007d
45a01fffff7fffff c3c0020200000000 c9702206037fefef
3e8ff800000000ff 3caffffffffffffe 3b4ff800000000fd
be004000000007fe 3fdffff7ff7fffff bdf03ffbefbf07fd
b11000007ffffe00 3fe0000000000000 b10000007ffffe00
b80cef50bd17db40 c05fffc00000000e 387cef16de76611d
3d4000ffffffffff 3d47f68d8eb6b9a4 3a97f80cf78fa50e
ffe3fffffffffffb c03dc3321aaa5380 7ff0000000000000
3ca3fffffffffeff bf02ffafb4e9241d bbb7bf9ba2236bf3
53598c812c3c39dd 3f20000100fffffe 52898c82c69d14b0
c3dffffff8000001 3fe0020000003ffe c3d001fffbffbfff
7ba00800003fffff 3ff9a9a129c791b3 7ba9b675fac31bff
c3d0000fffffffef 7fe0000000000001 fff0000000000000
c34f80001fffffff b7fffffe0007ffff 3b5f7ffe2807ddfe
0010000000001ff8 4800020000010000 0820020000011ffc
2c4c0000003fffff 230ffffc00400000 0f6bfffc8077fff7
381fffffffbff7fe 8010000000000000 8000000000000000
802d3018ea8c241d c007fdffffffffff 0045e23fae5a7253
43e047fffffffffe 4000003ffdfffffe 43f048411df6fffc
c000005fffffffff 403ffffffff00002 c050005ffff7ffd0
3fc8b60e46a80f6d bfdffffffffffffe bfb8b60e46a80f6b
bd5fdffdffffffff 5644b72ace1bbb6b d3b4a27257daf2cd
b80010001fffffff 40e01ffffff7fffe b8f030202037f7fd
407000003ffbfffe 38042862fe8e3368 388428634f2ab547
bf8ffbfff7ffffff c00fffffffffffff 3faffbfff7fffffe
bcafc000003fffff c010000000000001 3ccfc00000400001
47eddf042473ef08 b7e00000fe000000 bfdddf05fea850cb
3fbfffff7fffffef c340ffffffffffbf c310ffffbbffffb6
c02f8000000007ff ffe0000000000001 7ff0000000000000
002f37ebf6c8eaec c08be464f4c81c69 80cb36000706e169
c00e800000000000 7ffc000000000000 7ffc000000000000
0010000000000000 0000000000000000 0000000000000000
bfffc00000000003 391001ffffffffff b91fc3f800000001
c1db54446247aa52 bfcc001fffffffff 41b7e9d72a43174f
0010000000000000 c0392c59c8e48f37 80592c59c8e48f37
0010000000000000 c0000800000001ff 80200800000001ff
0010000000000000 c1d0000004000fff 81f0000004000fff
4030040000200000 0017055f48beeff5 00570b20a0bf2a70
bc7000000000ffee c1e0001100000000 3e6000110000ffef
c040000000007fff c3b2a6c91c557f56 4402a6c91c56148b
41ffffffff003fff c3b0000007ffffee c5c0000007801fed
21900001dfffffff bf20000017fffffe a0c00001f80002cd
0029954d0f0df5b3 41e00000000003ff 0219954d0f0dfc17
b810000020000001 47ffdfffffffff80 c01fe0003fbfff82
0010000000000000 ffeffff800007fff c00ffff800007fff
0010000000000000 4010000000000000 0030000000000000
bf700000000100ff 401fffffffffffff bfa00000000100fe
37feffffffffffff 47ef8000000fffff 3ffe8400000f7ffe
b80f800001fffffe 44e00000ffff7fff bcff8001f9ff041c
0010000000000000 434ffffffffffffe 036ffffffffffffe
41ffffdfffff8000 7fe0000000000001 7ff0000000000000
b80a16ad02c87cd3 380fffffffffe7fe b02a16ad02c86940
47f0fffffffffffb 7ffc000000000000 7ffc000000000000
0010000000000000 41ffffffffbfff7f 021fffffffbfff7f
0010000000000000 8000000000000000 8000000000000000
c3d00001000001ff b7f60cb3edb38762 3bd60cb54e7ec8fd
0010000000000000 8010000000000001 8000000000000000
43c0007fffdfffff 801ffffffffffffe 83f0007fffdffffe
c7efffffdffffbff bca0000000000001 449fffffdffffc01
0010000000000000 c11ff00000000003 813ff00000000003
0010000000000000 bfd0000000000000 8000000000000000
c0ffffffffeffffe bfdfffffffffffff 40efffffffeffffd
6f7000000001fdff 1510010000000fff 4490010000020e1e
37f002000000000f b1effcfffffffffe a9f0007fd000000e
cc3050bc013d7cd7 bff0000000000000 4c3050bc013d7cd7
0010000000000000 87fff0000000fffe 8000000000000000
0010000000000000 bffffffffffffffe 801ffffffffffffe
43effbfffffff7ff 7fefffffff801ffe 7ff0000000000000
c015834380f2b995 3f9fff0000000400 bfc5829766d6b4b0
0010000000000000 41dfffffc0001000 01ffffffc0001000
0010000000000000 c01fffffffffffff 803fffffffffffff
41e010000000001f c5b04000000fffff c7a050400010101e
3b40018000000000 3ea0400000000100 39f0418600000100
0010000000000000 4cdffeffff7fffff 0cfffeffff7fffff
16dff0001ffffffe 3fb500ae0796659d 16a4f62dc5934870
b7e003ffffffff7f deafffffeffffffd 56a003fff7fdff7d
406000001fffbfff 3f20020000080000 3f900200200bbff7
0010000000000000 7ffc000000000000 7ffc000000000000
439fbffffffbffff bf8454fd38ef0ba0 c3342c533e7aa2e8
c1c000000200007e bf000001ffffffbf 40d000020200007d
480000000008fffe 001637e790e69de2 082637e790f31d51
bffffffc000003fe 3ca0000000000001 bcaffffc00000400
6b4848a9a8c0dcd5 480ffffffffbdfff 736848a9a8bdbb76

View File

@ -0,0 +1 @@
0020000803ffffff bfcb4181a9468e24 000fffffffffffff 7fe2f9c2bca0f33c 00092f9c2bca0f33 Wrong zdenorm 18

Binary file not shown.

View File

@ -0,0 +1,116 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main() {
FILE *fp, *fq, *fr;
int cnt=0;
char *ln;
size_t nbytes = 80;
ln = (char *)malloc(nbytes + 1);
// fp = fopen("tb.dat","r");
fp = fopen("testFloat","r");
fq = fopen("tb.v","a");
system("cp tbhead.v tb.v");
int k=0;
for(k=0; k<91 && !feof(fp); k++) {
//3FDBFFFFFFFFFF7F DE608000000001FF 43CFED83C17EDBD0 DE4CE000000002F9 01
// b68ffff8000000ff_3f9080000007ffff_b6307ffbe0080080_00001
char ch;
int i,j;
char *ln;
char xrf[17];
char y[17];
char zrf[17];
char ans[81];
char flags[3];
int rn,rz,rm,rp;
{
//my_string = (char *) malloc (nbytes + 1);
//bytes_read = getline (&my_string, &nbytes, stdin);
if(getline(&ln,&nbytes,fp) < 0) break;
//fprintf(stderr,"%s\n", ln);
strncpy(xrf, ln, 16); xrf[16]=0;
strncpy(y, &ln[17], 16); y[16]=0;
strncpy(zrf, &ln[34], 16); zrf[16]=0;
// fprintf(stdout,"[%s]\n[%s]\n", ln,zrf);
strncpy(ans, &ln[51], 16); ans[16]=0;
strncpy(flags,&ln[68],2); flags[2]=0;
// fprintf(stdout,"[%s]\n[%s]\n", ln,zrf);
fprintf(fq," xrf = 64'h%s;\n",xrf);
fprintf(fq," y = 64'h%s;\n",y);
fprintf(fq," zrf = 64'h%s;\n",zrf);
fprintf(fq," ans = 64'h%s;\n", ans);
// fprintf(fq," flags = 5'h%s;\n", flags);
}
{
//rn=1; rz=0; rm=0; rp=0;
fprintf(fq," rn = %d;\n",1);
fprintf(fq," rz = %d;\n", 0);
fprintf(fq," rm = %d;\n", 0);
fprintf(fq," rp = %d;\n", 0);
}
{
fprintf(fq," earlyres = 64'b0;\n");
fprintf(fq," earlyressel = 0;\n");
}
{
fprintf(fq," bypsel= 2'b0;\n"); //, bysel);
fprintf(fq," bypplus1 = 0;\n"); //, byp1);
fprintf(fq," byppostnorm = 0;\n"); //, bypnorm);
}
fprintf(fq,"#10\n");
// IEEE 754-2008 section 6.3 states "When ether an input or result is NaN, this standard does not interpret the sign of a NaN."
//fprintf(fq," $fwrite(fp, \"%%h %%h %%h %%h \",xrf,y,w, ans);\n");
fprintf(fq," // IEEE 754-2008 section 6.3 states: \"When ether an input or result is NaN, this\n");
fprintf(fq," // standard does not interpret the sign of a NaN.\"\n");
fprintf(fq," nan = (w > 64'h7FF0000000000000 && w < 64'h7FF8000000000000) ||\n");
fprintf(fq," (w > 64'hFFF8000000000000 && w < 64'hFFF8000000000000 ) ||\n");
fprintf(fq," (w >= 64'h7FF8000000000000 && w <= 64'h7FFfffffffffffff ) ||\n");
fprintf(fq," (w >= 64'hFFF8000000000000 && w <= 64'hFFFfffffffffffff );\n");
// fprintf(fq," if(!(~(|xrf[62:52]) && |xrf[51:0] || ~(|y[62:52]) && |y[51:0])) begin\n");
// not looknig at negative zero results right now
//fprintf(fq," if( (nan && (w[62:0] != ans[62:0])) || (!nan && (w != ans)) && !(w == 64'h8000000000000000 && ans == 64'b0)) begin\n");
fprintf(fq," if( (nan && (w[62:0] != ans[62:0])) || (!nan && (w != ans)) ) begin\n");
fprintf(fq," $fwrite(fp, \"%%h %%h %%h %%h %%h Wrong \",xrf,y, zrf, w, ans);\n");
fprintf(fq," if(w == 64'h8000000000000000) $fwrite(fp, \"w=-zero \");\n");
fprintf(fq," if(~(|xrf[62:52]) && |xrf[51:0]) $fwrite(fp, \"xdenorm \");\n");
fprintf(fq," if(~(|y[62:52]) && |y[51:0]) $fwrite(fp, \"ydenorm \");\n");
fprintf(fq," if(~(|zrf[62:52]) && |zrf[51:0]) $fwrite(fp, \"zdenorm \");\n");
fprintf(fq," if(invalid != 0) $fwrite(fp, \"invld \");\n");
fprintf(fq," if(overflow != 0) $fwrite(fp, \"ovrflw \");\n");
fprintf(fq," if(underflow != 0) $fwrite(fp, \"unflw \");\n");
fprintf(fq," if(w == 64'hFFF0000000000000) $fwrite(fp, \"w=-inf \");\n");
fprintf(fq," if(w == 64'h7FF0000000000000) $fwrite(fp, \"w=+inf \");\n");
fprintf(fq," if(w > 64'h7FF0000000000000 && w < 64'h7FF8000000000000 ) $fwrite(fp, \"w=sigNaN \");\n");
fprintf(fq," if(w > 64'hFFF8000000000000 && w < 64'hFFF8000000000000 ) $fwrite(fp, \"w=sigNaN \");\n");
fprintf(fq," if(w >= 64'h7FF8000000000000 && w <= 64'h7FFfffffffffffff ) $fwrite(fp, \"w=qutNaN \");\n");
fprintf(fq," if(w >= 64'hFFF8000000000000 && w <= 64'hFFFfffffffffffff ) $fwrite(fp, \"w=qutNaN \");\n");
fprintf(fq," if(ans == 64'hFFF0000000000000) $fwrite(fp, \"ans=-inf \");\n");
fprintf(fq," if(ans == 64'h7FF0000000000000) $fwrite(fp, \"ans=+inf \");\n");
fprintf(fq," if(ans > 64'h7FF0000000000000 && ans < 64'h7FF8000000000000 ) $fwrite(fp, \"ans=sigNaN \");\n");
fprintf(fq," if(ans > 64'hFFF8000000000000 && ans < 64'hFFF8000000000000 ) $fwrite(fp, \"ans=sigNaN \");\n");
fprintf(fq," if(ans >= 64'h7FF8000000000000 && ans <= 64'h7FFfffffffffffff ) $fwrite(fp, \"ans=qutNaN \");\n");
fprintf(fq," if(ans >= 64'hFFF8000000000000 && ans <= 64'hFFFfffffffffffff ) $fwrite(fp, \"ans=qutNaN \");\n");
fprintf(fq," $fwrite(fp,\"%d\\n\");\n",cnt);
if(cnt == 358)fprintf(fq," $stop;\n");
// fprintf(fq," end\n");
fprintf(fq," end\n");
cnt++;
//if(cnt > 100) break;
fflush(fq);
}
fprintf(fq, "\t$stop;\n\tend\nendmodule");
fclose(fq);
fclose(fp);
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,36 @@
`timescale 1 ns/10 ps
module tb;
reg [63:0] xrf;
reg [63:0] y;
reg [63:0] zrf;
reg [63:0] ans;
reg rn;
reg rz;
reg rm;
reg rp;
reg [63:0] earlyres;
reg earlyressel;
reg [1:0] bypsel;
reg bypplus1;
reg byppostnorm;
wire [63:0] w;
wire [63:0] wbypass;
wire invalid;
wire overflow;
wire underflow;
wire inexact;
integer fp;
reg nan;
localparam period = 20;
fmac UUT(.xrf(xrf), .y(y), .zrf(zrf), .rn(rn), .rz(rz), .rp(rp), .rm(rm),
.earlyres(earlyres), .earlyressel(earlyressel), .bypsel(bypsel), .bypplus1(bypplus1), .byppostnorm(byppostnorm),
.w(w), .wbypass(wbypass), .invalid(invalid), .overflow(overflow), .underflow(underflow), .inexact(inexact));
initial
begin
fp = $fopen("/home/kparry/code/FMAC/tbgen/results.dat","w");

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
testfloat_gen f64_mulAdd -n 6133248 -rnear_even -seed 113355 -level 1 >> testFloat

View File

@ -0,0 +1 @@
awk 'BEGIN {FS = " "; OFS = "_"} {if ($3 == "0000000000000000") print $1, $2, $4;}' testFloat | head -n 1000 > testMini

View File

@ -340,7 +340,7 @@ module freg3adr (
generate generate
for (i = 0; i < numRegs; i = i + 1) begin:register 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])); floprc #(`XLEN) reg[i](.clk(clk), .reset(reset), .clear(clear), .d(regInput[i][`XLEN-1:0]), .q(regOutput[i][`XLEN-1:0]));
end end
endgenerate endgenerate

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) fcsrreg(.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,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

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) freg[i](.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) freg[i](.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) freg[i](.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

View File

@ -47,6 +47,16 @@ module flopr #(parameter WIDTH = 8) (
else q <= #1 d; else q <= #1 d;
endmodule endmodule
// flop with enable
module flopen #(parameter WIDTH = 8) (
input logic clk, en,
input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q);
always_ff @(posedge clk)
if (en) q <= #1 d;
endmodule
// flop with enable, asynchronous reset, synchronous clear // flop with enable, asynchronous reset, synchronous clear
module flopenrc #(parameter WIDTH = 8) ( module flopenrc #(parameter WIDTH = 8) (
input logic clk, reset, clear, en, input logic clk, reset, clear, en,

View File

@ -27,19 +27,18 @@
module hazard( module hazard(
// Detect hazards // Detect hazards
// input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
// input logic MemReadE,
// input logic RegWriteM, RegWriteW,
input logic PCSrcE, CSRWritePendingDEM, RetM, TrapM, input logic PCSrcE, CSRWritePendingDEM, RetM, TrapM,
input logic LoadStallD, MulDivStallD, input logic LoadStallD, MulDivStallD,
input logic InstrStall, DataStall, input logic InstrStall, DataStall,
// Stall outputs // Stall & flush outputs
output logic StallF, StallD, FlushD, FlushE, FlushM, FlushW output logic StallF, StallD, StallE, StallM, StallW,
output logic FlushD, FlushE, FlushM, FlushW
); );
logic BranchFlushDE; logic BranchFlushDE;
logic StallDCause, StallFCause, StallWCause; logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause;
logic FirstUnstalledD, FirstUnstalledE, FirstUnstalledM, FirstUnstalledW;
// stalls and flushes // stalls and flushes
// loads: stall for one cycle if the subsequent instruction depends on the load // loads: stall for one cycle if the subsequent instruction depends on the load
// branches and jumps: flush the next two instructions if the branch is taken in EXE // branches and jumps: flush the next two instructions if the branch is taken in EXE
@ -54,14 +53,27 @@ module hazard(
assign BranchFlushDE = PCSrcE | RetM | TrapM; assign BranchFlushDE = PCSrcE | RetM | TrapM;
assign StallDCause = LoadStallD | MulDivStallD; assign StallFCause = CSRWritePendingDEM & ~(BranchFlushDE);
assign StallFCause = InstrStall | CSRWritePendingDEM; assign StallDCause = LoadStallD | MulDivStallD; // stall in decode if instruction is a load/mul dependent on previous
assign StallWCause = DataStall; // *** not yet used assign StallECause = 0;
assign StallMCause = 0;
assign StallWCause = DataStall | InstrStall;
assign StallD = StallDCause; // Each stage stalls if the next stage is stalled or there is a cause to stall this stage.
assign StallF = StallD | StallFCause; assign StallF = StallD | StallFCause;
assign FlushD = BranchFlushDE | StallFCause; // PCSrcE |InstrStall | CSRWritePendingDEM | RetM | TrapM; assign StallD = StallE | StallDCause;
assign FlushE = StallD | BranchFlushDE; //LoadStallD | PCSrcE | RetM | TrapM; assign StallE = StallM | StallECause;
assign FlushM = RetM | TrapM; assign StallM = StallW | StallMCause;
assign FlushW = TrapM; assign StallW = StallWCause;
assign FirstUnstalledD = (~StallD & StallF);
assign FirstUnstalledE = (~StallE & StallD);
assign FirstUnstalledM = (~StallM & StallE);
assign FirstUnstalledW = (~StallW & StallM);;
// Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush
assign FlushD = FirstUnstalledD || BranchFlushDE; // PCSrcE |InstrStall | CSRWritePendingDEM | RetM | TrapM;
assign FlushE = FirstUnstalledE || BranchFlushDE; //LoadStallD | PCSrcE | RetM | TrapM;
assign FlushM = FirstUnstalledM || RetM || TrapM;
assign FlushW = FirstUnstalledW | TrapM;
endmodule endmodule

View File

@ -33,12 +33,11 @@ module controller(
input logic [2:0] Funct3D, input logic [2:0] Funct3D,
input logic [6:0] Funct7D, input logic [6:0] Funct7D,
output logic [2:0] ImmSrcD, output logic [2:0] ImmSrcD,
input logic StallD, FlushD,
input logic IllegalIEUInstrFaultD, input logic IllegalIEUInstrFaultD,
output logic IllegalBaseInstrFaultD, output logic IllegalBaseInstrFaultD,
// Execute stage control signals // Execute stage control signals
input logic FlushE, input logic StallE, FlushE,
input logic [2:0] FlagsE, input logic [2:0] FlagsE,
output logic PCSrcE, // for datapath and Hazard Unit output logic PCSrcE, // for datapath and Hazard Unit
output logic [4:0] ALUControlE, output logic [4:0] ALUControlE,
output logic ALUSrcAE, ALUSrcBE, output logic ALUSrcAE, ALUSrcBE,
@ -47,14 +46,13 @@ module controller(
output logic [2:0] Funct3E, output logic [2:0] Funct3E,
output logic MulDivE, W64E, output logic MulDivE, W64E,
// Memory stage control signals // Memory stage control signals
input logic FlushM, input logic StallM, FlushM,
input logic DataMisalignedM,
output logic [1:0] MemRWM, output logic [1:0] MemRWM,
output logic CSRWriteM, PrivilegedM, output logic CSRWriteM, PrivilegedM,
output logic [2:0] Funct3M, output logic [2:0] Funct3M,
output logic RegWriteM, // for Hazard Unit output logic RegWriteM, // for Hazard Unit
// Writeback stage control signals // Writeback stage control signals
input logic FlushW, input logic StallW, FlushW,
output logic RegWriteW, // for datapath and Hazard Unit output logic RegWriteW, // for datapath and Hazard Unit
output logic [2:0] ResultSrcW, output logic [2:0] ResultSrcW,
output logic InstrValidW, output logic InstrValidW,
@ -94,10 +92,14 @@ module controller(
7'b0100011: ControlsD = 21'b0_001_01_01_000_0_00_0_0_0_0_0_0_0; // sw 7'b0100011: ControlsD = 21'b0_001_01_01_000_0_00_0_0_0_0_0_0_0; // sw
7'b0110011: if (Funct7D == 7'b0000000 || Funct7D == 7'b0100000) 7'b0110011: if (Funct7D == 7'b0000000 || Funct7D == 7'b0100000)
ControlsD = 21'b1_000_00_00_000_0_10_0_0_0_0_0_0_0; // R-type ControlsD = 21'b1_000_00_00_000_0_10_0_0_0_0_0_0_0; // R-type
else if (Funct7D == 7'b0000001 && `M_SUPPORTED)
ControlsD = 21'b1_000_00_00_100_0_00_0_0_0_0_0_1_0; // Multiply/Divide
else else
ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // non-implemented instruction ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // non-implemented instruction
7'b0111011: if ((Funct7D == 7'b0000000 || Funct7D == 7'b0100000) && `XLEN == 64) 7'b0111011: if ((Funct7D == 7'b0000000 || Funct7D == 7'b0100000) && `XLEN == 64)
ControlsD = 21'b1_000_00_00_000_0_10_0_0_1_0_0_0_0; // R-type W instructions for RV64i ControlsD = 21'b1_000_00_00_000_0_10_0_0_1_0_0_0_0; // R-type W instructions for RV64i
else if (Funct7D == 7'b0000001 && `M_SUPPORTED && `XLEN == 64)
ControlsD = 21'b1_000_00_00_100_0_00_0_0_1_0_0_1_0; // W-type Multiply/Divide
else else
ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // non-implemented instruction ControlsD = 21'b0_000_00_00_000_0_00_0_0_0_0_0_0_1; // non-implemented instruction
7'b1100011: ControlsD = 21'b0_010_00_00_000_1_01_0_0_0_0_0_0_0; // beq 7'b1100011: ControlsD = 21'b0_010_00_00_000_1_01_0_0_0_0_0_0_0; // beq
@ -145,7 +147,7 @@ module controller(
endcase endcase
// Execute stage pipeline control register and logic // Execute stage pipeline control register and logic
floprc #(24) controlregE(clk, reset, FlushE, flopenrc #(24) controlregE(clk, reset, FlushE, ~StallE,
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, TargetSrcD, CSRWriteD, PrivilegedD, Funct3D, W64D, MulDivD, 1'b1}, {RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, TargetSrcD, CSRWriteD, PrivilegedD, Funct3D, W64D, MulDivD, 1'b1},
{RegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, TargetSrcE, CSRWriteE, PrivilegedE, Funct3E, W64E, MulDivE, InstrValidE}); {RegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, TargetSrcE, CSRWriteE, PrivilegedE, Funct3E, W64E, MulDivE, InstrValidE});
@ -168,12 +170,12 @@ module controller(
assign MemReadE = MemRWE[1]; assign MemReadE = MemRWE[1];
// Memory stage pipeline control register // Memory stage pipeline control register
floprc #(12) controlregM(clk, reset, FlushM, flopenrc #(12) controlregM(clk, reset, FlushM, ~StallM,
{RegWriteE, ResultSrcE, MemRWE, CSRWriteE, PrivilegedE, Funct3E, InstrValidE}, {RegWriteE, ResultSrcE, MemRWE, CSRWriteE, PrivilegedE, Funct3E, InstrValidE},
{RegWriteM, ResultSrcM, MemRWM, CSRWriteM, PrivilegedM, Funct3M, InstrValidM}); {RegWriteM, ResultSrcM, MemRWM, CSRWriteM, PrivilegedM, Funct3M, InstrValidM});
// Writeback stage pipeline control register // Writeback stage pipeline control register
floprc #(5) controlregW(clk, reset, FlushW, flopenrc #(5) controlregW(clk, reset, FlushW, ~StallW,
{RegWriteM, ResultSrcM, InstrValidM}, {RegWriteM, ResultSrcM, InstrValidM},
{RegWriteW, ResultSrcW, InstrValidW}); {RegWriteW, ResultSrcW, InstrValidW});

View File

@ -28,13 +28,11 @@
module datapath ( module datapath (
input logic clk, reset, input logic clk, reset,
// Decode stage signals // Decode stage signals
input logic StallD, FlushD,
input logic [2:0] ImmSrcD, input logic [2:0] ImmSrcD,
input logic [31:0] InstrD, input logic [31:0] InstrD,
// Execute stage signals // Execute stage signals
input logic FlushE, input logic StallE, FlushE,
input logic [1:0] ForwardAE, ForwardBE, input logic [1:0] ForwardAE, ForwardBE,
input logic PCSrcE,
input logic [4:0] ALUControlE, input logic [4:0] ALUControlE,
input logic ALUSrcAE, ALUSrcBE, input logic ALUSrcAE, ALUSrcBE,
input logic TargetSrcE, input logic TargetSrcE,
@ -43,13 +41,11 @@ module datapath (
output logic [`XLEN-1:0] PCTargetE, output logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] SrcAE, SrcBE, output logic [`XLEN-1:0] SrcAE, SrcBE,
// Memory stage signals // Memory stage signals
input logic FlushM, input logic StallM, FlushM,
input logic [2:0] Funct3M,
input logic RetM, TrapM,
output logic [`XLEN-1:0] SrcAM, output logic [`XLEN-1:0] SrcAM,
output logic [`XLEN-1:0] WriteDataM, MemAdrM, output logic [`XLEN-1:0] WriteDataM, MemAdrM,
// Writeback stage signals // Writeback stage signals
input logic FlushW, input logic StallW, FlushW,
input logic RegWriteW, input logic RegWriteW,
input logic [2:0] ResultSrcW, input logic [2:0] ResultSrcW,
input logic [`XLEN-1:0] PCLinkW, input logic [`XLEN-1:0] PCLinkW,
@ -85,12 +81,12 @@ module datapath (
extend ext(.InstrD(InstrD[31:7]), .*); extend ext(.InstrD(InstrD[31:7]), .*);
// Execute stage pipeline register and logic // Execute stage pipeline register and logic
floprc #(`XLEN) RD1EReg(clk, reset, FlushE, RD1D, RD1E); flopenrc #(`XLEN) RD1EReg(clk, reset, FlushE, ~StallE, RD1D, RD1E);
floprc #(`XLEN) RD2EReg(clk, reset, FlushE, RD2D, RD2E); flopenrc #(`XLEN) RD2EReg(clk, reset, FlushE, ~StallE, RD2D, RD2E);
floprc #(`XLEN) ExtImmEReg(clk, reset, FlushE, ExtImmD, ExtImmE); flopenrc #(`XLEN) ExtImmEReg(clk, reset, FlushE, ~StallE, ExtImmD, ExtImmE);
floprc #(5) Rs1EReg(clk, reset, FlushE, Rs1D, Rs1E); flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
floprc #(5) Rs2EReg(clk, reset, FlushE, Rs2D, Rs2E); flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
floprc #(5) RdEReg(clk, reset, FlushE, RdD, RdE); flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
mux3 #(`XLEN) faemux(RD1E, ResultW, ALUResultM, ForwardAE, PreSrcAE); mux3 #(`XLEN) faemux(RD1E, ResultW, ALUResultM, ForwardAE, PreSrcAE);
mux3 #(`XLEN) fbemux(RD2E, ResultW, ALUResultM, ForwardBE, WriteDataE); mux3 #(`XLEN) fbemux(RD2E, ResultW, ALUResultM, ForwardBE, WriteDataE);
@ -101,15 +97,15 @@ module datapath (
assign PCTargetE = ExtImmE + TargetBaseE; assign PCTargetE = ExtImmE + TargetBaseE;
// Memory stage pipeline register // Memory stage pipeline register
floprc #(`XLEN) SrcAMReg(clk, reset, FlushM, SrcAE, SrcAM); flopenrc #(`XLEN) SrcAMReg(clk, reset, FlushM, ~StallM, SrcAE, SrcAM);
floprc #(`XLEN) ALUResultMReg(clk, reset, FlushM, ALUResultE, ALUResultM); flopenrc #(`XLEN) ALUResultMReg(clk, reset, FlushM, ~StallM, ALUResultE, ALUResultM);
assign MemAdrM = ALUResultM; assign MemAdrM = ALUResultM;
floprc #(`XLEN) WriteDataMReg(clk, reset, FlushM, WriteDataE, WriteDataM); flopenrc #(`XLEN) WriteDataMReg(clk, reset, FlushM, ~StallM, WriteDataE, WriteDataM);
floprc #(5) RdMEg(clk, reset, FlushM, RdE, RdM); flopenrc #(5) RdMEg(clk, reset, FlushM, ~StallM, RdE, RdM);
// Writeback stage pipeline register and logic // Writeback stage pipeline register and logic
floprc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ALUResultM, ALUResultW); flopenrc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ~StallW, ALUResultM, ALUResultW);
floprc #(5) RdWEg(clk, reset, FlushW, RdM, RdW); flopenrc #(5) RdWEg(clk, reset, FlushW, ~StallW, RdM, RdW);
mux5 #(`XLEN) resultmux(ALUResultW, ReadDataW, PCLinkW, CSRReadValW, MulDivResultW, ResultSrcW, ResultW); mux5 #(`XLEN) resultmux(ALUResultW, ReadDataW, PCLinkW, CSRReadValW, MulDivResultW, ResultSrcW, ResultW);
endmodule endmodule

View File

@ -30,7 +30,7 @@ module forward(
input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW, input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
input logic MemReadE, MulDivE, input logic MemReadE, MulDivE,
input logic RegWriteM, RegWriteW, input logic RegWriteM, RegWriteW,
// Forwaring controls // Forwarding controls
output logic [1:0] ForwardAE, ForwardBE, output logic [1:0] ForwardAE, ForwardBE,
output logic LoadStallD, MulDivStallD output logic LoadStallD, MulDivStallD
); );

View File

@ -49,8 +49,8 @@ module ieu (
input logic [`XLEN-1:0] PCLinkW, input logic [`XLEN-1:0] PCLinkW,
output logic InstrValidW, output logic InstrValidW,
// hazards // hazards
input logic StallD, FlushD, FlushE, FlushM, FlushW, input logic StallE, StallM, StallW,
input logic RetM, TrapM, input logic FlushE, FlushM, FlushW,
output logic LoadStallD, MulDivStallD, output logic LoadStallD, MulDivStallD,
output logic PCSrcE, output logic PCSrcE,

View File

@ -28,13 +28,14 @@
module ifu ( module ifu (
input logic clk, reset, input logic clk, reset,
input logic StallF, StallD, FlushD, FlushE, FlushM, FlushW, input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW,
// Fetch // Fetch
input logic [31:0] InstrF, input logic [`XLEN-1:0] InstrInF,
output logic [`XLEN-1:0] PCF, output logic [`XLEN-1:0] PCF,
output logic [`XLEN-1:0] InstrPAdrF, output logic [`XLEN-1:0] InstrPAdrF,
output logic InstrReadF,
// Decode // Decode
output logic InstrStall,
// Execute // Execute
input logic PCSrcE, input logic PCSrcE,
input logic [`XLEN-1:0] PCTargetE, input logic [`XLEN-1:0] PCTargetE,
@ -50,29 +51,31 @@ module ifu (
input logic IllegalBaseInstrFaultD, input logic IllegalBaseInstrFaultD,
output logic IllegalIEUInstrFaultD, output logic IllegalIEUInstrFaultD,
output logic InstrMisalignedFaultM, output logic InstrMisalignedFaultM,
output logic [`XLEN-1:0] InstrMisalignedAdrM output logic [`XLEN-1:0] InstrMisalignedAdrM,
// bogus
input logic [15:0] rd2
); );
logic [`XLEN-1:0] UnalignedPCNextF, PCNextF; logic [`XLEN-1:0] UnalignedPCNextF, PCNextF;
logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM; logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM;
logic StallExceptResolveBranchesF, PrivilegedChangePCM; logic PrivilegedChangePCM;
logic IllegalCompInstrD; logic IllegalCompInstrD;
logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkE, PCLinkM; logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkE, PCLinkM;
logic CompressedF; logic CompressedF;
logic [31:0] InstrRawD, InstrE; logic [31:0] InstrF, InstrRawD, InstrE, InstrW;
logic [31:0] nop = 32'h00000013; // instruction for NOP logic [31:0] nop = 32'h00000013; // instruction for NOP
// *** put memory interface on here, InstrF becomes output // *** put memory interface on here, InstrF becomes output
assign InstrStall = 0; // ***
assign InstrPAdrF = PCF; // *** no MMU assign InstrPAdrF = PCF; // *** no MMU
//assign InstrReadF = ~StallD; // *** & ICacheMissF; add later
assign InstrReadF = 1; // *** & ICacheMissF; add later
assign PrivilegedChangePCM = RetM | TrapM; assign PrivilegedChangePCM = RetM | TrapM;
assign StallExceptResolveBranchesF = StallF & ~(PCSrcE | PrivilegedChangePCM);
mux3 #(`XLEN) pcmux(PCPlus2or4F, PCTargetE, PrivilegedNextPCM, {PrivilegedChangePCM, PCSrcE}, UnalignedPCNextF); mux3 #(`XLEN) pcmux(PCPlus2or4F, PCTargetE, PrivilegedNextPCM, {PrivilegedChangePCM, PCSrcE}, UnalignedPCNextF);
assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
flopenl #(`XLEN) pcreg(clk, reset, ~StallExceptResolveBranchesF, PCNextF, `RESET_VECTOR, PCF); flopenl #(`XLEN) pcreg(clk, reset, ~StallF, PCNextF, `RESET_VECTOR, PCF);
// pcadder // pcadder
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32 // add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
@ -86,6 +89,15 @@ module ifu (
else PCPlus2or4F = {PCF[`XLEN-1:2], 2'b10}; else PCPlus2or4F = {PCF[`XLEN-1:2], 2'b10};
else PCPlus2or4F = {PCPlusUpperF, PCF[1:0]}; // add 4 else PCPlus2or4F = {PCPlusUpperF, PCF[1:0]}; // add 4
// harris 2/23/21 Add code to fetch instruction split across two words
generate
if (`XLEN==32) begin
assign InstrF = PCF[1] ? {rd2[15:0], InstrInF[31:16]} : InstrInF;
end else begin
assign InstrF = PCF[2] ? (PCF[1] ? {rd2[15:0], InstrInF[63:48]} : InstrInF[63:32])
: (PCF[1] ? InstrInF[47:16] : InstrInF[31:0]);
end
endgenerate
// Decode stage pipeline register and logic // Decode stage pipeline register and logic
flopenl #(32) InstrDReg(clk, reset, ~StallD, (FlushD ? nop : InstrF), nop, InstrRawD); flopenl #(32) InstrDReg(clk, reset, ~StallD, (FlushD ? nop : InstrF), nop, InstrRawD);
@ -107,25 +119,26 @@ module ifu (
// pipeline misaligned faults to M stage // pipeline misaligned faults to M stage
assign BranchMisalignedFaultE = misaligned & PCSrcE; // E-stage (Branch/Jump) misaligned assign BranchMisalignedFaultE = misaligned & PCSrcE; // E-stage (Branch/Jump) misaligned
flopr #(1) InstrMisalginedReg(clk, reset, BranchMisalignedFaultE, BranchMisalignedFaultM); flopenr #(1) InstrMisalginedReg(clk, reset, ~StallM, BranchMisalignedFaultE, BranchMisalignedFaultM);
flopr #(`XLEN) InstrMisalignedAdrReg(clk, reset, PCNextF, InstrMisalignedAdrM); flopenr #(`XLEN) InstrMisalignedAdrReg(clk, reset, ~StallM, PCNextF, InstrMisalignedAdrM);
assign TrapMisalignedFaultM = misaligned & PrivilegedChangePCM; assign TrapMisalignedFaultM = misaligned & PrivilegedChangePCM;
assign InstrMisalignedFaultM = BranchMisalignedFaultM; // | TrapMisalignedFaultM; *** put this back in without causing a cyclic path assign InstrMisalignedFaultM = BranchMisalignedFaultM; // | TrapMisalignedFaultM; *** put this back in without causing a cyclic path
flopr #(32) InstrEReg(clk, reset, FlushE ? nop : InstrD, InstrE); flopenr #(32) InstrEReg(clk, reset, ~StallE, FlushE ? nop : InstrD, InstrE);
flopr #(32) InstrMReg(clk, reset, FlushM ? nop : InstrE, InstrM); flopenr #(32) InstrMReg(clk, reset, ~StallM, FlushM ? nop : InstrE, InstrM);
flopr #(`XLEN) PCEReg(clk, reset, PCD, PCE); flopenr #(32) InstrWReg(clk, reset, ~StallW, FlushW ? nop : InstrM, InstrW); // just for testbench, delete later
flopr #(`XLEN) PCMReg(clk, reset, PCE, PCM); flopenr #(`XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
flopr #(`XLEN) PCWReg(clk, reset, PCM, PCW); // *** probably not needed; delete later flopenr #(`XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW); // *** probably not needed; delete later
// seems like there should be a lower-cost way of doing this PC+2 or PC+4 for JAL. // seems like there should be a lower-cost way of doing this PC+2 or PC+4 for JAL.
// either have ALU compute PC+2/4 and feed into ALUResult input of ResultMux or // either have ALU compute PC+2/4 and feed into ALUResult input of ResultMux or
// have dedicated adder in Mem stage based on PCM + 2 or 4 // have dedicated adder in Mem stage based on PCM + 2 or 4
// *** redo this // *** redo this
flopr #(`XLEN) PCPDReg(clk, reset, PCPlus2or4F, PCLinkD); flopenr #(`XLEN) PCPDReg(clk, reset, ~StallD, PCPlus2or4F, PCLinkD);
flopr #(`XLEN) PCPEReg(clk, reset, PCLinkD, PCLinkE); flopenr #(`XLEN) PCPEReg(clk, reset, ~StallE, PCLinkD, PCLinkE);
flopr #(`XLEN) PCPMReg(clk, reset, PCLinkE, PCLinkM); flopenr #(`XLEN) PCPMReg(clk, reset, ~StallM, PCLinkE, PCLinkM);
flopr #(`XLEN) PCPWReg(clk, reset, PCLinkM, PCLinkW); flopenr #(`XLEN) PCPWReg(clk, reset, ~StallW, PCLinkM, PCLinkW);
endmodule endmodule

View File

@ -0,0 +1,77 @@
///////////////////////////////////////////
// mul.sv
//
// Written: David_Harris@hmc.edu 16 February 2021
// Modified:
//
// Purpose: Multiply instructions
//
// 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.
///////////////////////////////////////////
`include "wally-config.vh"
module mul (
// Execute Stage interface
input logic [`XLEN-1:0] SrcAE, SrcBE,
input logic [2:0] Funct3E,
output logic [`XLEN*2-1:0] ProdE
);
// Number systems
// Let A' = sum(i=0, XLEN-2, A[i]*2^i)
// Unsigned: A = A' + A[XLEN-1]*2^(XLEN-1)
// Signed: A = A' - A[XLEN-1]*2^(XLEN-1)
// Multiplication: A*B
// Let P' = A' * B'
// PA = (A' * B[XLEN-1])
// PB = (B' * A[XLEN-1])
// PP = A[XLEN-1] * B[XLEN-1]
// Signed * Signed = P' + (-PA - PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
// Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2)
// Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
logic [`XLEN*2-1:0] PP1, PP2, PP3, PP4;
logic [`XLEN*2-1:0] Pprime;
logic [`XLEN-2:0] PA, PB;
logic PP;
logic MULH, MULHSU, MULHU;
// portions of product
assign Pprime = {1'b0, SrcAE[`XLEN-2:0]} * {1'b0, SrcBE[`XLEN-2:0]};
assign PA = {(`XLEN-1){SrcAE[`XLEN-1]}} & SrcBE[`XLEN-2:0];
assign PB = {(`XLEN-1){SrcBE[`XLEN-1]}} & SrcAE[`XLEN-2:0];
assign PP = SrcAE[`XLEN-1] & SrcBE[`XLEN-1];
// flavor of multiplication
assign MULH = (Funct3E == 2'b01);
assign MULHSU = (Funct3E == 2'b10);
// assign MULHU = (Funct3E == 2'b11); // signal unused
// Handle signs
assign PP1 = Pprime; // same for all flavors
assign PP2 = {2'b00, (MULH | MULHSU) ? ~PA : PA, {(`XLEN-1){1'b0}}};
assign PP3 = {2'b00, (MULH) ? ~PB : PB, {(`XLEN-1){1'b0}}};
always_comb
if (MULH) PP4 = {1'b1, PP, {(`XLEN-3){1'b0}}, 1'b1, {(`XLEN){1'b0}}};
else if (MULHSU) PP4 = {1'b1, ~PP, {(`XLEN-2){1'b0}}, 1'b1, {(`XLEN-1){1'b0}}};
else PP4 = {1'b0, PP, {(`XLEN*2-2){1'b0}}};
assign ProdE = PP1 + PP2 + PP3 + PP4; //SrcAE * SrcBE;
endmodule

View File

@ -36,7 +36,7 @@ module muldiv (
// Writeback stage // Writeback stage
output logic [`XLEN-1:0] MulDivResultW, output logic [`XLEN-1:0] MulDivResultW,
// hazards // hazards
input logic FlushM, FlushW input logic StallM, StallW, FlushM, FlushW
); );
generate generate
@ -46,6 +46,9 @@ module muldiv (
logic [`XLEN-1:0] QuotE, RemE; logic [`XLEN-1:0] QuotE, RemE;
logic [`XLEN*2-1:0] ProdE; logic [`XLEN*2-1:0] ProdE;
// Multiplier
mul mul(.*);
// Select result // Select result
always_comb always_comb
case (Funct3E) case (Funct3E)
@ -66,8 +69,8 @@ module muldiv (
assign MulDivResultE = PrelimResultE; assign MulDivResultE = PrelimResultE;
end end
floprc #(`XLEN) MulDivResultMReg(clk, reset, FlushM, MulDivResultE, MulDivResultM); flopenrc #(`XLEN) MulDivResultMReg(clk, reset, FlushM, ~StallM, MulDivResultE, MulDivResultM);
floprc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, MulDivResultM, MulDivResultW); flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW);
end else begin // no M instructions supported end else begin // no M instructions supported
assign MulDivResultW = 0; assign MulDivResultW = 0;
end end

View File

@ -28,7 +28,7 @@
module csr ( module csr (
input logic clk, reset, input logic clk, reset,
input logic FlushW, input logic FlushW, StallW,
input logic [31:0] InstrM, input logic [31:0] InstrM,
input logic [`XLEN-1:0] PCM, SrcAM, input logic [`XLEN-1:0] PCM, SrcAM,
input logic CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM, input logic CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
@ -102,7 +102,9 @@ module csr (
// merge CSR Reads // merge CSR Reads
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM | CSRNReadValM; assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM | CSRNReadValM;
floprc #(`XLEN) CSRValWReg(clk, reset, FlushW, CSRReadValM, CSRReadValW); // *** add W stall 2/22/21 dh to try fixing memory stalls
// floprc #(`XLEN) CSRValWReg(clk, reset, FlushW, CSRReadValM, CSRReadValW);
flopenrc #(`XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW);
// merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient // merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient
assign InsufficientCSRPrivilegeM = (CSRAdrM[9:8] == 2'b11 && PrivilegeModeW != `M_MODE) || assign InsufficientCSRPrivilegeM = (CSRAdrM[9:8] == 2'b11 && PrivilegeModeW != `M_MODE) ||

View File

@ -60,15 +60,13 @@ module csrs #(parameter
// Supervisor mode CSRs sometimes supported // Supervisor mode CSRs sometimes supported
generate generate
if (`S_SUPPORTED) begin if (`S_SUPPORTED) begin
logic WriteSTVECM, WriteSEDELEGM, WriteSIDELEGM; logic WriteSTVECM;
logic WriteSSCRATCHM, WriteSEPCM; logic WriteSSCRATCHM, WriteSEPCM;
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW, SATP_REGW; logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW, SATP_REGW;
assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS); assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS);
assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC); assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC);
assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG);
assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG);
assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH); assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH);
assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC)); assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC));
assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE)); assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE));
@ -85,6 +83,9 @@ module csrs #(parameter
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW); flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW); flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW);
if (`N_SUPPORTED) begin if (`N_SUPPORTED) begin
logic WriteSEDELEGM, WriteSIDELEGM;
assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG);
assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG);
flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, zero, SEDELEG_REGW); flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, zero, SEDELEG_REGW);
flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, zero, SIDELEG_REGW); flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, zero, SIDELEG_REGW);
end else begin end else begin

View File

@ -27,7 +27,7 @@
`include "wally-config.vh" `include "wally-config.vh"
module csrsr ( module csrsr (
input logic clk, reset, input logic clk, reset, StallW,
input logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM, input logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM,
input logic TrapM, FloatRegWriteW, input logic TrapM, FloatRegWriteW,
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW, input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
@ -116,9 +116,9 @@ module csrsr (
STATUS_SPIE <= 0; //`S_SUPPORTED; STATUS_SPIE <= 0; //`S_SUPPORTED;
STATUS_UPIE <= 0; // `U_SUPPORTED; STATUS_UPIE <= 0; // `U_SUPPORTED;
STATUS_MIE <= 0; // Per Priv 3.3 STATUS_MIE <= 0; // Per Priv 3.3
STATUS_SIE <= 0; // `S_SUPPORTED; STATUS_SIE <= `S_SUPPORTED;
STATUS_UIE <= 0; // `U_SUPPORTED; STATUS_UIE <= `U_SUPPORTED;
end else begin end else if (~StallW) begin
if (WriteMSTATUSM) begin if (WriteMSTATUSM) begin
STATUS_SUM_INT <= CSRWriteValM[18]; STATUS_SUM_INT <= CSRWriteValM[18];
STATUS_MPRV_INT <= CSRWriteValM[17]; STATUS_MPRV_INT <= CSRWriteValM[17];

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// exceptions.sv // privileged.sv
// //
// Written: David_Harris@hmc.edu 5 January 2021 // Written: David_Harris@hmc.edu 5 January 2021
// Modified: // Modified:
@ -45,7 +45,7 @@ module privileged (
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM, input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
input logic [4:0] SetFflagsM, input logic [4:0] SetFflagsM,
output logic [2:0] FRM_REGW, output logic [2:0] FRM_REGW,
input logic FlushD, FlushE, FlushM, StallD input logic FlushD, FlushE, FlushM, StallD, StallW
); );
logic [1:0] NextPrivilegeModeM, PrivilegeModeW; logic [1:0] NextPrivilegeModeM, PrivilegeModeW;
@ -81,8 +81,8 @@ module privileged (
// PrivilegeMode FSM // PrivilegeMode FSM
always_comb always_comb
if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode) /* if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode) // moved reset to flop
else if (mretM) NextPrivilegeModeM = STATUS_MPP; else */ if (mretM) NextPrivilegeModeM = STATUS_MPP;
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP}; else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
else if (uretM) NextPrivilegeModeM = `U_MODE; else if (uretM) NextPrivilegeModeM = `U_MODE;
else if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8) else if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
@ -96,7 +96,7 @@ module privileged (
else NextPrivilegeModeM = `M_MODE; else NextPrivilegeModeM = `M_MODE;
end else NextPrivilegeModeM = PrivilegeModeW; end else NextPrivilegeModeM = PrivilegeModeW;
flop #(2) privmodereg(clk, NextPrivilegeModeM, PrivilegeModeW); flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, `M_MODE, PrivilegeModeW);
/////////////////////////////////////////// ///////////////////////////////////////////
// decode privileged instructions // decode privileged instructions

View File

@ -44,7 +44,9 @@ module clint (
assign memread = MemRWclint[1]; assign memread = MemRWclint[1];
assign memwrite = MemRWclint[0]; assign memwrite = MemRWclint[0];
assign HRESPCLINT = 0; // OK assign HRESPCLINT = 0; // OK
assign HREADYCLINT = 1; // Respond immediately // assign HREADYCLINT = 1; // Respond immediately
always_ff @(posedge HCLK) // delay response
HREADYCLINT <= memread | memwrite;
// word aligned reads // word aligned reads
generate generate
@ -54,16 +56,21 @@ module clint (
assign #2 entry = {HADDR[15:2], 2'b00}; assign #2 entry = {HADDR[15:2], 2'b00};
endgenerate endgenerate
// DH 2/20/21: Eventually allow MTIME to run off a separate clock
// This will require synchronizing MTIME to the system clock
// before it is read or compared to MTIMECMP.
// It will also require synchronizing the write to MTIMECMP.
// Use req and ack signals synchronized across the clock domains.
// register access // register access
generate generate
if (`XLEN==64) begin if (`XLEN==64) begin
always_comb begin always @(posedge HCLK) begin
case(entry) case(entry)
16'h0000: HREADCLINT = {63'b0, MSIP}; 16'h0000: HREADCLINT <= {63'b0, MSIP};
16'h4000: HREADCLINT = MTIMECMP; 16'h4000: HREADCLINT <= MTIMECMP;
16'hBFF8: HREADCLINT = MTIME; 16'hBFF8: HREADCLINT <= MTIME;
default: HREADCLINT = 0; default: HREADCLINT <= 0;
endcase endcase
end end
always_ff @(posedge HCLK or negedge HRESETn) always_ff @(posedge HCLK or negedge HRESETn)
@ -80,14 +87,14 @@ module clint (
else MTIME <= MTIME + 1; else MTIME <= MTIME + 1;
end end
end else begin // 32-bit end else begin // 32-bit
always_comb begin always @(posedge HCLK) begin
case(entry) case(entry)
16'h0000: HREADCLINT = {31'b0, MSIP}; 16'h0000: HREADCLINT <= {31'b0, MSIP};
16'h4000: HREADCLINT = MTIMECMP[31:0]; 16'h4000: HREADCLINT <= MTIMECMP[31:0];
16'h4004: HREADCLINT = MTIMECMP[63:32]; 16'h4004: HREADCLINT <= MTIMECMP[63:32];
16'hBFF8: HREADCLINT = MTIME[31:0]; 16'hBFF8: HREADCLINT <= MTIME[31:0];
16'hBFFC: HREADCLINT = MTIME[63:32]; 16'hBFFC: HREADCLINT <= MTIME[63:32];
default: HREADCLINT = 0; default: HREADCLINT <= 0;
endcase endcase
end end
always_ff @(posedge HCLK or negedge HRESETn) always_ff @(posedge HCLK or negedge HRESETn)

View File

@ -36,6 +36,9 @@ module dtim (
); );
logic [`XLEN-1:0] RAM[0:65535]; logic [`XLEN-1:0] RAM[0:65535];
logic [18:0] HWADDR;
logic [`XLEN-1:0] HREADTim0;
// logic [`XLEN-1:0] write; // logic [`XLEN-1:0] write;
logic [15:0] entry; logic [15:0] entry;
logic memread, memwrite; logic memread, memwrite;
@ -48,74 +51,56 @@ module dtim (
end else begin end else begin
if (HREADYTim & HSELTim) begin if (HREADYTim & HSELTim) begin
busycount <= 0; busycount <= 0;
HREADYTim <= 0; HREADYTim <= #1 0;
end else if (~HREADYTim) begin end else if (~HREADYTim) begin
if (busycount == 0) begin // TIM latency, for testing purposes if (busycount == 2) begin // TIM latency, for testing purposes
HREADYTim <= 1; HREADYTim <= #1 1;
end else end else begin
busycount <= busycount + 1; busycount <= busycount + 1;
end
end end
end end
/* always_ff @(posedge HCLK, negedge HRESETn)
if (~HRESETn) begin
HREADYTim <= 0;
end else begin
HREADYTim <= HSELTim; // always respond one cycle later
end */
assign memread = MemRWtim[1]; assign memread = MemRWtim[1];
assign memwrite = MemRWtim[0]; assign memwrite = MemRWtim[0];
// always_ff @(posedge HCLK)
// memwrite <= MemRWtim[0]; // delay memwrite to write phase
assign HRESPTim = 0; // OK assign HRESPTim = 0; // OK
// assign HREADYTim = 1; // Respond immediately; *** extend this // assign HREADYTim = 1; // Respond immediately; *** extend this
// Model memory read and write
// word aligned reads
generate generate
if (`XLEN==64) if (`XLEN == 64) begin
assign #2 entry = HADDR[18:3]; // always_ff @(negedge HCLK)
else // if (memwrite) RAM[HWADDR[17:3]] <= HWDATA;
assign #2 entry = HADDR[17:2]; always_ff @(posedge HCLK) begin
endgenerate //if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
assign HREADTim = RAM[entry]; HWADDR <= HADDR;
// assign HREADTim = HREADYTim ? RAM[entry] : ~RAM[entry]; // *** temproary mess up read value before ready HREADTim0 <= RAM[HADDR[17:3]];
if (memwrite && HREADYTim) RAM[HWADDR[17:3]] <= HWDATA;
// write each byte based on the byte mask end
// UInstantiate a byte-writable memory here if possible end else begin
// and drop tihs masking logic. Otherwise, use the masking // always_ff @(negedge HCLK)
// from dmem // if (memwrite) RAM[HWADDR[17:2]] <= HWDATA;
/*generate always_ff @(posedge HCLK) begin
//if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
if (`XLEN==64) begin HWADDR <= HADDR;
always_comb begin HREADTim0 <= RAM[HADDR[17:2]];
write=HREADTim; if (memwrite && HREADYTim) RAM[HWADDR[17:2]] <= HWDATA;
if (ByteMaskM[0]) write[7:0] = HWDATA[7:0]; end
if (ByteMaskM[1]) write[15:8] = HWDATA[15:8];
if (ByteMaskM[2]) write[23:16] = HWDATA[23:16];
if (ByteMaskM[3]) write[31:24] = HWDATA[31:24];
if (ByteMaskM[4]) write[39:32] = HWDATA[39:32];
if (ByteMaskM[5]) write[47:40] = HWDATA[47:40];
if (ByteMaskM[6]) write[55:48] = HWDATA[55:48];
if (ByteMaskM[7]) write[63:56] = HWDATA[63:56];
end
always_ff @(posedge clk)
if (memwrite) RAM[HADDR[18:3]] <= write;
end else begin // 32-bit
always_comb begin
write=HREADTim;
if (ByteMaskM[0]) write[7:0] = HWDATA[7:0];
if (ByteMaskM[1]) write[15:8] = HWDATA[15:8];
if (ByteMaskM[2]) write[23:16] = HWDATA[23:16];
if (ByteMaskM[3]) write[31:24] = HWDATA[31:24];
end
always_ff @(posedge clk)
if (memwrite) RAM[HADDR[17:2]] <= write;
end end
endgenerate */
generate
if (`XLEN == 64)
always_ff @(posedge HCLK) begin
if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
// HREADTim <= RAM[HADDR[17:3]];
end
else
always_ff @(posedge HCLK) begin
if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
// HREADTim <= RAM[HADDR[17:2]];
end
endgenerate endgenerate
assign HREADTim = HREADYTim ? HREADTim0 : 'bz;
endmodule endmodule

View File

@ -45,7 +45,9 @@ module gpio (
assign memread = MemRWgpio[1]; assign memread = MemRWgpio[1];
assign memwrite = MemRWgpio[0]; assign memwrite = MemRWgpio[0];
assign HRESPGPIO = 0; // OK assign HRESPGPIO = 0; // OK
assign HREADYGPIO = 1; // Respond immediately always_ff @(posedge HCLK) // delay response to data cycle
HREADYGPIO <= memread | memwrite;
// assign HREADYGPIO = 1; // Respond immediately
// word aligned reads // word aligned reads
generate generate
@ -67,12 +69,12 @@ module gpio (
// register access // register access
generate generate
if (`XLEN==64) begin if (`XLEN==64) begin
always_comb begin always_ff @(posedge HCLK) begin
case(entry) case(entry)
8'h00: HREADGPIO = {INPUT_EN, INPUT_VAL}; 8'h00: HREADGPIO <= {INPUT_EN, INPUT_VAL};
8'h08: HREADGPIO = {OUTPUT_VAL, OUTPUT_EN}; 8'h08: HREADGPIO <= {OUTPUT_VAL, OUTPUT_EN};
8'h40: HREADGPIO = 0; // OUT_XOR reads as 0 8'h40: HREADGPIO <= 0; // OUT_XOR reads as 0
default: HREADGPIO = 0; default: HREADGPIO <= 0;
endcase endcase
end end
always_ff @(posedge HCLK or negedge HRESETn) always_ff @(posedge HCLK or negedge HRESETn)
@ -86,14 +88,14 @@ module gpio (
if (entry == 8'h40) OUTPUT_VAL <= OUTPUT_VAL ^ HWDATA[31:0]; // OUT_XOR if (entry == 8'h40) OUTPUT_VAL <= OUTPUT_VAL ^ HWDATA[31:0]; // OUT_XOR
end end
end else begin // 32-bit end else begin // 32-bit
always_comb begin always_ff @(posedge HCLK) begin
case(entry) case(entry)
8'h00: HREADGPIO = INPUT_VAL; 8'h00: HREADGPIO <= INPUT_VAL;
8'h04: HREADGPIO = INPUT_EN; 8'h04: HREADGPIO <= INPUT_EN;
8'h08: HREADGPIO = OUTPUT_EN; 8'h08: HREADGPIO <= OUTPUT_EN;
8'h0C: HREADGPIO = OUTPUT_VAL; 8'h0C: HREADGPIO <= OUTPUT_VAL;
8'h40: HREADGPIO = 0; // OUT_XOR reads as 0 8'h40: HREADGPIO <= 0; // OUT_XOR reads as 0
default: HREADGPIO = 0; default: HREADGPIO <= 0;
endcase endcase
end end
always_ff @(posedge HCLK or negedge HRESETn) always_ff @(posedge HCLK or negedge HRESETn)

View File

@ -28,6 +28,7 @@
module imem ( module imem (
input logic [`XLEN-1:1] AdrF, input logic [`XLEN-1:1] AdrF,
output logic [31:0] InstrF, output logic [31:0] InstrF,
output logic [15:0] rd2, // bogus, delete when real multicycle fetch works
output logic InstrAccessFaultF); output logic InstrAccessFaultF);
/* verilator lint_off UNDRIVEN */ /* verilator lint_off UNDRIVEN */
@ -35,7 +36,7 @@ module imem (
/* verilator lint_on UNDRIVEN */ /* verilator lint_on UNDRIVEN */
logic [15:0] adrbits; logic [15:0] adrbits;
logic [`XLEN-1:0] rd; logic [`XLEN-1:0] rd;
logic [15:0] rd2; // logic [15:0] rd2;
generate generate
if (`XLEN==32) assign adrbits = AdrF[17:2]; if (`XLEN==32) assign adrbits = AdrF[17:2];
@ -52,11 +53,19 @@ module imem (
generate generate
if (`XLEN==32) begin if (`XLEN==32) begin
assign InstrF = AdrF[1] ? {rd2[15:0], rd[31:16]} : rd; assign InstrF = AdrF[1] ? {rd2[15:0], rd[31:16]} : rd;
assign InstrAccessFaultF = ~AdrF[31] | (|AdrF[30:16]); // memory mapped to 0x80000000-0x8000FFFF if(`TIMBASE==0) begin
assign InstrAccessFaultF = 0;
end else begin
assign InstrAccessFaultF = ~AdrF[31] | (|AdrF[30:16]); // memory mapped to 0x80000000-0x8000FFFF
end
end else begin end else begin
assign InstrF = AdrF[2] ? (AdrF[1] ? {rd2[15:0], rd[63:48]} : rd[63:32]) assign InstrF = AdrF[2] ? (AdrF[1] ? {rd2[15:0], rd[63:48]} : rd[63:32])
: (AdrF[1] ? rd[47:16] : rd[31:0]); : (AdrF[1] ? rd[47:16] : rd[31:0]);
assign InstrAccessFaultF = (|AdrF[`XLEN-1:32]) | ~AdrF[31] | (|AdrF[30:16]); // memory mapped to 0x80000000-0x8000FFFF] if(`TIMBASE==0) begin
assign InstrAccessFaultF = 0;
end else begin
assign InstrAccessFaultF = (|AdrF[`XLEN-1:32]) | ~AdrF[31] | (|AdrF[30:16]); // memory mapped to 0x80000000-0x8000FFFF]
end
end end
endgenerate endgenerate
endmodule endmodule

View File

@ -27,37 +27,35 @@
module subwordwrite ( module subwordwrite (
input logic [`XLEN-1:0] HRDATA, input logic [`XLEN-1:0] HRDATA,
input logic [31:0] HADDR, input logic [2:0] HADDRD,
input logic [2:0] HSIZE, input logic [3:0] HSIZED,
input logic [`XLEN-1:0] HWDATAIN, input logic [`XLEN-1:0] HWDATAIN,
output logic [`XLEN-1:0] HWDATA output logic [`XLEN-1:0] HWDATA
); );
logic [7:0] ByteM; // *** declare locally to generate as either 4 or 8 bits
logic [15:0] HalfwordM;
logic [`XLEN-1:0] WriteDataSubwordDuplicated; logic [`XLEN-1:0] WriteDataSubwordDuplicated;
logic [7:0] ByteMaskM;
generate generate
if (`XLEN == 64) begin if (`XLEN == 64) begin
logic [7:0] ByteMaskM;
// Compute write mask // Compute write mask
always_comb always_comb
case(HSIZE[1:0]) case(HSIZED[1:0])
2'b00: begin ByteMaskM = 8'b00000000; ByteMaskM[HADDR[2:0]] = 1; end // sb 2'b00: begin ByteMaskM = 8'b00000000; ByteMaskM[HADDRD[2:0]] = 1; end // sb
2'b01: case (HADDR[2:1]) 2'b01: case (HADDRD[2:1])
2'b00: ByteMaskM = 8'b00000011; 2'b00: ByteMaskM = 8'b00000011;
2'b01: ByteMaskM = 8'b00001100; 2'b01: ByteMaskM = 8'b00001100;
2'b10: ByteMaskM = 8'b00110000; 2'b10: ByteMaskM = 8'b00110000;
2'b11: ByteMaskM = 8'b11000000; 2'b11: ByteMaskM = 8'b11000000;
endcase endcase
2'b10: if (HADDR[2]) ByteMaskM = 8'b11110000; 2'b10: if (HADDRD[2]) ByteMaskM = 8'b11110000;
else ByteMaskM = 8'b00001111; else ByteMaskM = 8'b00001111;
2'b11: ByteMaskM = 8'b11111111; 2'b11: ByteMaskM = 8'b11111111;
endcase endcase
// Handle subword writes // Handle subword writes
always_comb always_comb
case(HSIZE[1:0]) case(HSIZED[1:0])
2'b00: WriteDataSubwordDuplicated = {8{HWDATAIN[7:0]}}; // sb 2'b00: WriteDataSubwordDuplicated = {8{HWDATAIN[7:0]}}; // sb
2'b01: WriteDataSubwordDuplicated = {4{HWDATAIN[15:0]}}; // sh 2'b01: WriteDataSubwordDuplicated = {4{HWDATAIN[15:0]}}; // sh
2'b10: WriteDataSubwordDuplicated = {2{HWDATAIN[31:0]}}; // sw 2'b10: WriteDataSubwordDuplicated = {2{HWDATAIN[31:0]}}; // sw
@ -77,19 +75,20 @@ module subwordwrite (
end end
end else begin // 32-bit end else begin // 32-bit
logic [3:0] ByteMaskM;
// Compute write mask // Compute write mask
always_comb always_comb
case(HSIZE[1:0]) case(HSIZED[1:0])
2'b00: begin ByteMaskM = 8'b0000; ByteMaskM[{1'b0, HADDR[1:0]}] = 1; end // sb 2'b00: begin ByteMaskM = 4'b0000; ByteMaskM[HADDRD[1:0]] = 1; end // sb
2'b01: if (HADDR[1]) ByteMaskM = 8'b1100; 2'b01: if (HADDRD[1]) ByteMaskM = 4'b1100;
else ByteMaskM = 8'b0011; else ByteMaskM = 4'b0011;
2'b10: ByteMaskM = 8'b1111; 2'b10: ByteMaskM = 4'b1111;
default: ByteMaskM = 8'b111; // shouldn't happen default: ByteMaskM = 4'b111; // shouldn't happen
endcase endcase
// Handle subword writes // Handle subword writes
always_comb always_comb
case(HSIZE[1:0]) case(HSIZED[1:0])
2'b00: WriteDataSubwordDuplicated = {4{HWDATAIN[7:0]}}; // sb 2'b00: WriteDataSubwordDuplicated = {4{HWDATAIN[7:0]}}; // sb
2'b01: WriteDataSubwordDuplicated = {2{HWDATAIN[15:0]}}; // sh 2'b01: WriteDataSubwordDuplicated = {2{HWDATAIN[15:0]}}; // sh
2'b10: WriteDataSubwordDuplicated = HWDATAIN; // sw 2'b10: WriteDataSubwordDuplicated = HWDATAIN; // sw

View File

@ -48,31 +48,33 @@ module uart (
assign MEMWb = ~MemRWuart[0]; assign MEMWb = ~MemRWuart[0];
assign A = HADDR[2:0]; assign A = HADDR[2:0];
assign HRESPUART = 0; // OK assign HRESPUART = 0; // OK
assign HREADYUART = 1; // Respond immediately //assign HREADYUART = 1; // Respond immediately
always_ff @(posedge HCLK) // delay response to data cycle
HREADYUART <= ~MEMRb | ~MEMWb;
generate generate
if (`XLEN == 64) begin if (`XLEN == 64) begin
always_comb begin always @(posedge HCLK) begin
HREADUART = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout}; HREADUART = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout};
case (HADDR) case (HADDR)
3'b000: Din = HWDATA[7:0]; 3'b000: Din <= HWDATA[7:0];
3'b001: Din = HWDATA[15:8]; 3'b001: Din <= HWDATA[15:8];
3'b010: Din = HWDATA[23:16]; 3'b010: Din <= HWDATA[23:16];
3'b011: Din = HWDATA[31:24]; 3'b011: Din <= HWDATA[31:24];
3'b100: Din = HWDATA[39:32]; 3'b100: Din <= HWDATA[39:32];
3'b101: Din = HWDATA[47:40]; 3'b101: Din <= HWDATA[47:40];
3'b110: Din = HWDATA[55:48]; 3'b110: Din <= HWDATA[55:48];
3'b111: Din = HWDATA[63:56]; 3'b111: Din <= HWDATA[63:56];
endcase endcase
end end
end else begin // 32-bit end else begin // 32-bit
always_comb begin always @(posedge HCLK) begin
HREADUART = {Dout, Dout, Dout, Dout}; HREADUART = {Dout, Dout, Dout, Dout};
case (HADDR[1:0]) case (HADDR[1:0])
2'b00: Din = HWDATA[7:0]; 2'b00: Din <= HWDATA[7:0];
2'b01: Din = HWDATA[15:8]; 2'b01: Din <= HWDATA[15:8];
2'b10: Din = HWDATA[23:16]; 2'b10: Din <= HWDATA[23:16];
2'b11: Din = HWDATA[31:24]; 2'b11: Din <= HWDATA[31:24];
endcase endcase
end end
end end

View File

@ -6,6 +6,7 @@
// //
// Purpose: Universial Asynchronous Receiver/ Transmitter with FIFOs // Purpose: Universial Asynchronous Receiver/ Transmitter with FIFOs
// Emulates interface of Texas Instruments PC16550D // Emulates interface of Texas Instruments PC16550D
// https://media.digikey.com/pdf/Data%20Sheets/Texas%20Instruments%20PDFs/PC16550D.pdf
// Compatible with UART in Imperas Virtio model *** // Compatible with UART in Imperas Virtio model ***
// //
// Compatible with most of PC16550D with the following known exceptions: // Compatible with most of PC16550D with the following known exceptions:

View File

@ -43,6 +43,10 @@ module uncore (
input logic HREADYEXT, HRESPEXT, input logic HREADYEXT, HRESPEXT,
output logic [`AHBW-1:0] HRDATA, output logic [`AHBW-1:0] HRDATA,
output logic HREADY, HRESP, output logic HREADY, HRESP,
// delayed signals
input logic [2:0] HADDRD,
input logic [3:0] HSIZED,
input logic HWRITED,
// bus interface // bus interface
output logic DataAccessFaultM, output logic DataAccessFaultM,
// peripheral pins // peripheral pins
@ -71,7 +75,7 @@ module uncore (
assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported
// Enable read or write based on decoded address // Enable read or write based on decoded address
assign MemRW = {~HWRITE, HWRITE}; assign MemRW = {~HWRITE, HWRITED};
assign MemRWtim = MemRW & {2{HSELTim}}; assign MemRWtim = MemRW & {2{HSELTim}};
assign MemRWclint = MemRW & {2{HSELCLINT}}; assign MemRWclint = MemRW & {2{HSELCLINT}};
assign MemRWgpio = MemRW & {2{HSELGPIO}}; assign MemRWgpio = MemRW & {2{HSELGPIO}};

View File

@ -29,12 +29,13 @@
module wallypipelinedhart ( module wallypipelinedhart (
input logic clk, reset, input logic clk, reset,
output logic [`XLEN-1:0] PCF, output logic [`XLEN-1:0] PCF,
input logic [31:0] InstrF, // input logic [31:0] InstrF,
// Privileged // Privileged
input logic TimerIntM, ExtIntM, SwIntM, input logic TimerIntM, ExtIntM, SwIntM,
input logic InstrAccessFaultF, input logic InstrAccessFaultF,
input logic DataAccessFaultM, input logic DataAccessFaultM,
// Bus Interface // Bus Interface
input logic [15:0] rd2, // bogus, delete when real multicycle fetch works
input logic [`AHBW-1:0] HRDATA, input logic [`AHBW-1:0] HRDATA,
input logic HREADY, HRESP, input logic HREADY, HRESP,
output logic HCLK, HRESETn, output logic HCLK, HRESETn,
@ -45,11 +46,16 @@ module wallypipelinedhart (
output logic [2:0] HBURST, output logic [2:0] HBURST,
output logic [3:0] HPROT, output logic [3:0] HPROT,
output logic [1:0] HTRANS, output logic [1:0] HTRANS,
output logic HMASTLOCK output logic HMASTLOCK,
// Delayed signals for subword write
output logic [2:0] HADDRD,
output logic [3:0] HSIZED,
output logic HWRITED
); );
logic [1:0] ForwardAE, ForwardBE; // logic [1:0] ForwardAE, ForwardBE;
logic StallF, StallD, FlushD, FlushE, FlushM, FlushW; logic StallF, StallD, StallE, StallM, StallW;
logic FlushD, FlushE, FlushM, FlushW;
logic RetM, TrapM; logic RetM, TrapM;
// new signals that must connect through DP // new signals that must connect through DP
@ -72,7 +78,6 @@ module wallypipelinedhart (
logic LoadMisalignedFaultM, LoadAccessFaultM; logic LoadMisalignedFaultM, LoadAccessFaultM;
logic StoreMisalignedFaultM, StoreAccessFaultM; logic StoreMisalignedFaultM, StoreAccessFaultM;
logic [`XLEN-1:0] InstrMisalignedAdrM; logic [`XLEN-1:0] InstrMisalignedAdrM;
logic [`XLEN-1:0] zero = 0;
logic PCSrcE; logic PCSrcE;
logic CSRWritePendingDEM; logic CSRWritePendingDEM;
@ -82,26 +87,35 @@ module wallypipelinedhart (
logic FloatRegWriteW; logic FloatRegWriteW;
// bus interface to dmem // bus interface to dmem
logic [1:0] MemRWAlignedM; logic MemReadM, MemWriteM;
logic [2:0] Funct3M; logic [2:0] Funct3M;
logic [`XLEN-1:0] MemAdrM, MemPAdrM, WriteDataM; logic [`XLEN-1:0] MemAdrM, MemPAdrM, WriteDataM;
logic [`XLEN-1:0] ReadDataM, ReadDataW; logic [`XLEN-1:0] ReadDataW;
logic [`XLEN-1:0] InstrPAdrF; logic [`XLEN-1:0] InstrPAdrF;
logic [`XLEN-1:0] InstrRData;
logic InstrReadF;
logic DataStall, InstrStall; logic DataStall, InstrStall;
logic InstrAckD, MemAckW; logic InstrAckD, MemAckW;
ifu ifu(.*); // instruction fetch unit: PC, branch prediction, instruction cache ifu ifu(.InstrInF(InstrRData), .*); // instruction fetch unit: PC, branch prediction, instruction cache
ieu ieu(.*); // inteber execution unit: integer register file, datapath and controller ieu ieu(.*); // inteber execution unit: integer register file, datapath and controller
dmem dmem(/*.Funct3M(InstrM[14:12]),*/ .*); // data cache unit dmem dmem(.*); // data cache unit
ahblite ebu( // *** make IRData InstrF
.IReadF(1'b1), .IRData(), //.IReady(), ahblite ebu(
.DReadM(MemRWAlignedM[1]), .DWriteM(MemRWAlignedM[0]), //.InstrReadF(1'b0),
.DSizeM(Funct3M[1:0]), .DRData(ReadDataM), //.DReady(), //.InstrRData(InstrF), // hook up InstrF later
.UnsignedLoadM(Funct3M[2]), .MemSizeM(Funct3M[1:0]), .UnsignedLoadM(Funct3M[2]),
.*); .*);
//assign InstrF = ReadDataM[31:0];
// changing from this to the line above breaks the program. auipc at 104 fails; seems to be flushed.
// Would need to insertinstruction as InstrD, not InstrF
/*ahblite ebu(
.InstrReadF(1'b0),
.InstrRData(), // hook up InstrF later
.MemSizeM(Funct3M[1:0]), .UnsignedLoadM(Funct3M[2]),
.*); */
muldiv mdu(.*); // multiply and divide unit muldiv mdu(.*); // multiply and divide unit

View File

@ -56,7 +56,6 @@ module wallypipelinedsoc (
// to instruction memory *** remove later // to instruction memory *** remove later
logic [`XLEN-1:0] PCF; logic [`XLEN-1:0] PCF;
logic [31:0] InstrF;
// Uncore signals // Uncore signals
logic [`AHBW-1:0] HRDATA; // from AHB mux in uncore logic [`AHBW-1:0] HRDATA; // from AHB mux in uncore
@ -64,6 +63,11 @@ module wallypipelinedsoc (
logic InstrAccessFaultF, DataAccessFaultM; logic InstrAccessFaultF, DataAccessFaultM;
logic TimerIntM, SwIntM; // from CLINT logic TimerIntM, SwIntM; // from CLINT
logic ExtIntM = 0; // not yet connected logic ExtIntM = 0; // not yet connected
logic [2:0] HADDRD;
logic [3:0] HSIZED;
logic HWRITED;
logic [15:0] rd2; // bogus, delete when real multicycle fetch works
logic [31:0] InstrF;
// instantiate processor and memories // instantiate processor and memories
wallypipelinedhart hart(.*); wallypipelinedhart hart(.*);

View File

@ -1,11 +1,40 @@
///////////////////////////////////////////
// testbench-imperas.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Wally Testbench and helper modules
// Applies test programs from the Imperas suite
//
// 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.
///////////////////////////////////////////
`include "wally-config.vh" `include "wally-config.vh"
module testbench(); module testbench();
logic clk; logic clk;
logic reset; logic reset;
int test, i, errors, totalerrors;
string memfilename; logic [31:0] sig32[0:10000];
logic [`XLEN-1:0] signature[0:10000];
logic [`XLEN-1:0] testadr;
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW;
logic [`XLEN-1:0] meminit;
string tests[];
logic [`AHBW-1:0] HRDATAEXT; logic [`AHBW-1:0] HRDATAEXT;
logic HREADYEXT, HRESPEXT; logic HREADYEXT, HRESPEXT;
logic [31:0] HADDR; logic [31:0] HADDR;
@ -17,31 +46,167 @@ module testbench();
logic [1:0] HTRANS; logic [1:0] HTRANS;
logic HMASTLOCK; logic HMASTLOCK;
logic HCLK, HRESETn; logic HCLK, HRESETn;
// pick tests based on modes supported
initial
tests = {"../../imperas-riscv-tests/riscv-ovpsim-plus/examples/CoreMark/coremark.RV64I.bare.elf.memfile", "1000"};
string signame, memfilename;
logic [31:0] GPIOPinsIn, GPIOPinsOut, GPIOPinsEn; logic [31:0] GPIOPinsIn, GPIOPinsOut, GPIOPinsEn;
logic UARTSin, UARTSout; logic UARTSin, UARTSout;
// instantiate device to be tested // instantiate device to be tested
assign GPIOPinsIn = 0; assign GPIOPinsIn = 0;
assign UARTSin = 1; assign UARTSin = 1;
assign HREADYEXT = 1; assign HREADYEXT = 1;
assign HRESPEXT = 0; assign HRESPEXT = 0;
assign HRDATAEXT = 0; assign HRDATAEXT = 0;
wallypipelinedsoc dut(.*);
wallypipelinedsoc dut(.*); // Track names of instructions
instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE,
dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
dut.hart.ifu.InstrM, InstrW,
InstrDName, InstrEName, InstrMName, InstrWName);
// initialize tests // initialize tests
initial initial
begin begin
memfilename = "../../imperas-riscv-tests/riscv-ovpsim-plus/examples/CoreMark/coremark.RV64I.bare.elf.memfile"; totalerrors = 0;
// read test vectors into memory
memfilename = tests[0];
$readmemh(memfilename, dut.imem.RAM); $readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM);
reset = 1; # 22; reset = 0; reset = 1; # 22; reset = 0;
end end
// generate clock to sequence tests // generate clock to sequence tests
always always
begin begin
clk = 1; # 5; clk = 0; # 5; clk = 1; # 5; clk = 0; # 5;
end end
endmodule
/* verilator lint_on STMTDLY */
/* verilator lint_on WIDTH */
module instrTrackerTB(
input logic clk, reset, FlushE,
input logic [31:0] InstrD,
input logic [31:0] InstrE, InstrM,
output logic [31:0] InstrW,
output string InstrDName, InstrEName, InstrMName, InstrWName);
// stage Instr to Writeback for visualization
flopr #(32) InstrWReg(clk, reset, InstrM, InstrW);
instrNameDecTB ddec(InstrD, InstrDName);
instrNameDecTB edec(InstrE, InstrEName);
instrNameDecTB mdec(InstrM, InstrMName);
instrNameDecTB wdec(InstrW, InstrWName);
endmodule
// decode the instruction name, to help the test bench
module instrNameDecTB(
input logic [31:0] instr,
output string name);
logic [6:0] op;
logic [2:0] funct3;
logic [6:0] funct7;
logic [11:0] imm;
assign op = instr[6:0];
assign funct3 = instr[14:12];
assign funct7 = instr[31:25];
assign imm = instr[31:20];
// it would be nice to add the operands to the name
// create another variable called decoded
always_comb
casez({op, funct3})
10'b0000000_000: name = "BAD";
10'b0000011_000: name = "LB";
10'b0000011_001: name = "LH";
10'b0000011_010: name = "LW";
10'b0000011_011: name = "LD";
10'b0000011_100: name = "LBU";
10'b0000011_101: name = "LHU";
10'b0000011_110: name = "LWU";
10'b0010011_000: if (instr[31:15] == 0 && instr[11:7] ==0) name = "NOP/FLUSH";
else name = "ADDI";
10'b0010011_001: if (funct7[6:1] == 6'b000000) name = "SLLI";
else name = "ILLEGAL";
10'b0010011_010: name = "SLTI";
10'b0010011_011: name = "SLTIU";
10'b0010011_100: name = "XORI";
10'b0010011_101: if (funct7[6:1] == 6'b000000) name = "SRLI";
else if (funct7[6:1] == 6'b010000) name = "SRAI";
else name = "ILLEGAL";
10'b0010011_110: name = "ORI";
10'b0010011_111: name = "ANDI";
10'b0010111_???: name = "AUIPC";
10'b0100011_000: name = "SB";
10'b0100011_001: name = "SH";
10'b0100011_010: name = "SW";
10'b0100011_011: name = "SD";
10'b0011011_000: name = "ADDIW";
10'b0011011_001: name = "SLLIW";
10'b0011011_101: if (funct7 == 7'b0000000) name = "SRLIW";
else if (funct7 == 7'b0100000) name = "SRAIW";
else name = "ILLEGAL";
10'b0111011_000: if (funct7 == 7'b0000000) name = "ADDW";
else if (funct7 == 7'b0100000) name = "SUBW";
else if (funct7 == 7'b0000001) name = "MULW";
else name = "ILLEGAL";
10'b0111011_001: if (funct7 == 7'b0000000) name = "SLLW";
else if (funct7 == 7'b0000001) name = "DIVW";
else name = "ILLEGAL";
10'b0111011_101: if (funct7 == 7'b0000000) name = "SRLW";
else if (funct7 == 7'b0100000) name = "SRAW";
else if (funct7 == 7'b0000001) name = "DIVUW";
else name = "ILLEGAL";
10'b0111011_110: if (funct7 == 7'b0000001) name = "REMW";
else name = "ILLEGAL";
10'b0111011_111: if (funct7 == 7'b0000001) name = "REMUW";
else name = "ILLEGAL";
10'b0110011_000: if (funct7 == 7'b0000000) name = "ADD";
else if (funct7 == 7'b0000001) name = "MUL";
else if (funct7 == 7'b0100000) name = "SUB";
else name = "ILLEGAL";
10'b0110011_001: if (funct7 == 7'b0000000) name = "SLL";
else if (funct7 == 7'b0000001) name = "MULH";
else name = "ILLEGAL";
10'b0110011_010: if (funct7 == 7'b0000000) name = "SLT";
else if (funct7 == 7'b0000001) name = "MULHSU";
else name = "ILLEGAL";
10'b0110011_011: if (funct7 == 7'b0000000) name = "SLTU";
else if (funct7 == 7'b0000001) name = "MULHU";
else name = "ILLEGAL";
10'b0110011_100: if (funct7 == 7'b0000000) name = "XOR";
else if (funct7 == 7'b0000001) name = "DIV";
else name = "ILLEGAL";
10'b0110011_101: if (funct7 == 7'b0000000) name = "SRL";
else if (funct7 == 7'b0000001) name = "DIVU";
else if (funct7 == 7'b0100000) name = "SRA";
else name = "ILLEGAL";
10'b0110011_110: if (funct7 == 7'b0000000) name = "OR";
else if (funct7 == 7'b0000001) name = "REM";
else name = "ILLEGAL";
10'b0110011_111: if (funct7 == 7'b0000000) name = "AND";
else if (funct7 == 7'b0000001) name = "REMU";
else name = "ILLEGAL";
10'b0110111_???: name = "LUI";
10'b1100011_000: name = "BEQ";
10'b1100011_001: name = "BNE";
10'b1100011_100: name = "BLT";
10'b1100011_101: name = "BGE";
10'b1100011_110: name = "BLTU";
10'b1100011_111: name = "BGEU";
10'b1100111_000: name = "JALR";
10'b1101111_???: name = "JAL";
10'b1110011_000: if (imm == 0) name = "ECALL";
else if (imm == 1) name = "EBREAK";
else if (imm == 2) name = "URET";
else if (imm == 258) name = "SRET";
else if (imm == 770) name = "MRET";
else name = "ILLEGAL";
10'b1110011_001: name = "CSRRW";
10'b1110011_010: name = "CSRRS";
10'b1110011_011: name = "CSRRC";
10'b1110011_101: name = "CSRRWI";
10'b1110011_110: name = "CSRRSI";
10'b1110011_111: name = "CSRRCI";
10'b0001111_???: name = "FENCE";
default: name = "ILLEGAL";
endcase
endmodule endmodule

View File

@ -35,7 +35,7 @@ module testbench();
logic [`XLEN-1:0] signature[0:10000]; logic [`XLEN-1:0] signature[0:10000];
logic [`XLEN-1:0] testadr; logic [`XLEN-1:0] testadr;
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW; //logic [31:0] InstrW;
logic [`XLEN-1:0] meminit; logic [`XLEN-1:0] meminit;
string tests64m[] = '{ string tests64m[] = '{
"rv64m/I-MUL-01", "3000", "rv64m/I-MUL-01", "3000",
@ -90,7 +90,6 @@ string tests64iNOc[] = {
"rv64i/I-MISALIGN_JMP-01","2000" "rv64i/I-MISALIGN_JMP-01","2000"
}; };
string tests64i[] = '{ string tests64i[] = '{
"rv64i/I-LW-01", "4110",
"rv64i/I-ADD-01", "3000", "rv64i/I-ADD-01", "3000",
"rv64i/I-ADDI-01", "3000", "rv64i/I-ADDI-01", "3000",
"rv64i/I-ADDIW-01", "3000", "rv64i/I-ADDIW-01", "3000",
@ -198,7 +197,6 @@ string tests64iNOc[] = {
// "rv32m/I-REMU-01", "2000" // "rv32m/I-REMU-01", "2000"
}; };
string tests32ic[] = '{ string tests32ic[] = '{
// "rv32ic/WALLY-C-ADHOC-01", "2000",
"rv32ic/I-C-ADD-01", "2000", "rv32ic/I-C-ADD-01", "2000",
"rv32ic/I-C-ADDI-01", "2000", "rv32ic/I-C-ADDI-01", "2000",
"rv32ic/I-C-AND-01", "2000", "rv32ic/I-C-AND-01", "2000",
@ -347,9 +345,9 @@ string tests32i[] = {
// Track names of instructions // Track names of instructions
instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE, instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE,
dut.hart.ifu.InstrD, dut.hart.ifu.InstrE, dut.hart.ifu.InstrF, dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
dut.hart.ifu.InstrM, InstrW, dut.hart.ifu.InstrM, dut.hart.ifu.InstrW,
InstrDName, InstrEName, InstrMName, InstrWName); InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// initialize tests // initialize tests
initial initial
@ -452,14 +450,16 @@ endmodule
module instrTrackerTB( module instrTrackerTB(
input logic clk, reset, FlushE, input logic clk, reset, FlushE,
input logic [31:0] InstrD, input logic [31:0] InstrF, InstrD,
input logic [31:0] InstrE, InstrM, input logic [31:0] InstrE, InstrM,
output logic [31:0] InstrW, input logic [31:0] InstrW,
output string InstrDName, InstrEName, InstrMName, InstrWName); // output logic [31:0] InstrW,
output string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// stage Instr to Writeback for visualization // stage Instr to Writeback for visualization
flopr #(32) InstrWReg(clk, reset, InstrM, InstrW); // flopr #(32) InstrWReg(clk, reset, InstrM, InstrW);
instrNameDecTB fdec(InstrF, InstrFName);
instrNameDecTB ddec(InstrD, InstrDName); instrNameDecTB ddec(InstrD, InstrDName);
instrNameDecTB edec(InstrE, InstrEName); instrNameDecTB edec(InstrE, InstrEName);
instrNameDecTB mdec(InstrM, InstrMName); instrNameDecTB mdec(InstrM, InstrMName);