mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of github.com:davidharrishmc/riscv-wally into boot
This commit is contained in:
commit
a0c6399969
@ -487,11 +487,11 @@ add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RdM
|
|||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RdW
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RdW
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD1D
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD1D
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2D
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2D
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ExtImmD
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ImmExtD
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RdD
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RdD
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD1E
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD1E
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2E
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2E
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ExtImmE
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ImmExtE
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ForwardedSrcAE
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ForwardedSrcAE
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/SrcAE
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/SrcAE
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/SrcBE
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/SrcBE
|
||||||
@ -513,7 +513,7 @@ add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/regf/rd2
|
|||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/regf/i
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/regf/i
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ext/InstrD
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ext/InstrD
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ext/ImmSrcD
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ext/ImmSrcD
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ext/ExtImmD
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ext/ImmExtD
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD1EReg/clk
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD1EReg/clk
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD1EReg/reset
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD1EReg/reset
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD1EReg/clear
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD1EReg/clear
|
||||||
@ -524,11 +524,11 @@ add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2EReg/reset
|
|||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2EReg/clear
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2EReg/clear
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2EReg/d
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2EReg/d
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2EReg/q
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/RD2EReg/q
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ExtImmEReg/clk
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ImmExtEReg/clk
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ExtImmEReg/reset
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ImmExtEReg/reset
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ExtImmEReg/clear
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ImmExtEReg/clear
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ExtImmEReg/d
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ImmExtEReg/d
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ExtImmEReg/q
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/ImmExtEReg/q
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/Rs1EReg/clk
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/Rs1EReg/clk
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/Rs1EReg/reset
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/Rs1EReg/reset
|
||||||
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/Rs1EReg/clear
|
add wave -noupdate -radix hexadecimal /testbench/dut/core/ieu/dp/Rs1EReg/clear
|
||||||
|
@ -30,38 +30,40 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module alu #(parameter WIDTH=32) (
|
module alu #(parameter WIDTH=32) (
|
||||||
input logic [WIDTH-1:0] A, B,
|
input logic [WIDTH-1:0] A, B, // Operands
|
||||||
input logic [2:0] ALUControl,
|
input logic [2:0] ALUControl, // With Funct3, indicates operation to perform
|
||||||
input logic [2:0] Funct3,
|
input logic [2:0] Funct3, // With ALUControl, indicates operation to perform
|
||||||
output logic [WIDTH-1:0] Result,
|
output logic [WIDTH-1:0] Result, // ALU result
|
||||||
output logic [WIDTH-1:0] Sum);
|
output logic [WIDTH-1:0] Sum); // Sum of operands
|
||||||
|
|
||||||
logic [WIDTH-1:0] CondInvB, Shift, SLT, SLTU, FullResult;
|
// CondInvB = ~B when subtracting, B otherwise. Shift = shift result. SLT/U = result of a slt/u instruction.
|
||||||
logic Carry, Neg;
|
// FullResult = ALU result before adjusting for a RV64 w-suffix instruction.
|
||||||
logic LT, LTU;
|
logic [WIDTH-1:0] CondInvB, Shift, SLT, SLTU, FullResult; // Intermediate results
|
||||||
logic W64, SubArith, ALUOp;
|
logic Carry, Neg; // Flags: carry out, negative
|
||||||
logic Asign, Bsign;
|
logic LT, LTU; // Less than, Less than unsigned
|
||||||
|
logic W64; // RV64 W-type instruction
|
||||||
|
logic SubArith; // Performing subtraction or arithmetic right shift
|
||||||
|
logic ALUOp; // 0 for address generation addition or 1 for regular ALU ops
|
||||||
|
logic Asign, Bsign; // Sign bits of A, B
|
||||||
|
|
||||||
// Extract control signals
|
// Extract control signals from ALUControl.
|
||||||
// W64 indicates RV64 W-suffix instructions acting on lower 32-bit word
|
|
||||||
// SubArith indicates subtraction or arithmetic right shift
|
|
||||||
// ALUOp = 0 for address generation addition or 1 for regular ALU
|
|
||||||
assign {W64, SubArith, ALUOp} = ALUControl;
|
assign {W64, SubArith, ALUOp} = ALUControl;
|
||||||
|
|
||||||
// addition
|
// Addition
|
||||||
assign CondInvB = SubArith ? ~B : B;
|
assign CondInvB = SubArith ? ~B : B;
|
||||||
assign {Carry, Sum} = A + CondInvB + {{(WIDTH-1){1'b0}}, SubArith};
|
assign {Carry, Sum} = A + CondInvB + {{(WIDTH-1){1'b0}}, SubArith};
|
||||||
|
|
||||||
// Shifts
|
// Shifts
|
||||||
shifter sh(.A, .Amt(B[`LOG_XLEN-1:0]), .Right(Funct3[2]), .Arith(SubArith), .W64, .Y(Shift));
|
shifter sh(.A, .Amt(B[`LOG_XLEN-1:0]), .Right(Funct3[2]), .Arith(SubArith), .W64, .Y(Shift));
|
||||||
|
|
||||||
// condition code flags based on subtract output Sum = A-B
|
// Condition code flags are based on subtraction output Sum = A-B.
|
||||||
// Overflow occurs when the numbers being subtracted have the opposite sign
|
// Overflow occurs when the numbers being subtracted have the opposite sign
|
||||||
// and the result has the opposite sign of A
|
// and the result has the opposite sign of A.
|
||||||
|
// LT is simplified from Overflow = Asign & Bsign & Asign & Neg; LT = Neg ^ Overflow
|
||||||
assign Neg = Sum[WIDTH-1];
|
assign Neg = Sum[WIDTH-1];
|
||||||
assign Asign = A[WIDTH-1];
|
assign Asign = A[WIDTH-1];
|
||||||
assign Bsign = B[WIDTH-1];
|
assign Bsign = B[WIDTH-1];
|
||||||
assign LT = Asign & ~Bsign | Asign & Neg | ~Bsign & Neg; // simplified from Overflow = Asign & Bsign & Asign & Neg; LT = Neg ^ Overflow
|
assign LT = Asign & ~Bsign | Asign & Neg | ~Bsign & Neg;
|
||||||
assign LTU = ~Carry;
|
assign LTU = ~Carry;
|
||||||
|
|
||||||
// SLT
|
// SLT
|
||||||
@ -70,7 +72,7 @@ module alu #(parameter WIDTH=32) (
|
|||||||
|
|
||||||
// Select appropriate ALU Result
|
// Select appropriate ALU Result
|
||||||
always_comb
|
always_comb
|
||||||
if (~ALUOp) FullResult = Sum; // Always add for ALUOp = 0
|
if (~ALUOp) FullResult = Sum; // Always add for ALUOp = 0 (address generation)
|
||||||
else casez (Funct3) // Otherwise check Funct3
|
else casez (Funct3) // Otherwise check Funct3
|
||||||
3'b000: FullResult = Sum; // add or sub
|
3'b000: FullResult = Sum; // add or sub
|
||||||
3'b?01: FullResult = Shift; // sll, sra, or srl
|
3'b?01: FullResult = Shift; // sll, sra, or srl
|
||||||
@ -81,8 +83,8 @@ module alu #(parameter WIDTH=32) (
|
|||||||
3'b111: FullResult = A & B; // and
|
3'b111: FullResult = A & B; // and
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// support W-type RV64I ADDW/SUBW/ADDIW/Shifts that sign-extend 32-bit result to 64 bits
|
// Support RV64I W-type addw/subw/addiw/shifts that discard upper 32 bits and sign-extend 32-bit result to 64 bits
|
||||||
if (WIDTH==64) assign Result = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult;
|
if (WIDTH == 64) assign Result = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult;
|
||||||
else assign Result = FullResult;
|
else assign Result = FullResult;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// comparator.sv
|
// comparator.sv
|
||||||
//
|
//
|
||||||
// Written: David_Harris@hmc.edu 8 December 2021
|
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
|
||||||
|
// Created: 8 December 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: Branch comparison
|
// Purpose: Branch comparison
|
||||||
@ -30,26 +31,26 @@
|
|||||||
|
|
||||||
// This comparator is best
|
// This comparator is best
|
||||||
module comparator_dc_flip #(parameter WIDTH=64) (
|
module comparator_dc_flip #(parameter WIDTH=64) (
|
||||||
input logic [WIDTH-1:0] a, b,
|
input logic [WIDTH-1:0] a, b, // Operands
|
||||||
input logic sgnd,
|
input logic sgnd, // Signed operands
|
||||||
output logic [1:0] flags);
|
output logic [1:0] flags); // Output flags: {eq, lt}
|
||||||
|
|
||||||
logic eq, lt, ltu;
|
logic eq, lt; // Flags: equal (eq), less than (lt)
|
||||||
logic [WIDTH-1:0] af, bf;
|
logic [WIDTH-1:0] af, bf; // Operands with msb flipped (inverted) when signed
|
||||||
|
|
||||||
// For signed numbers, flip most significant bit
|
// For signed numbers, flip most significant bit
|
||||||
assign af = {a[WIDTH-1] ^ sgnd, a[WIDTH-2:0]};
|
assign af = {a[WIDTH-1] ^ sgnd, a[WIDTH-2:0]};
|
||||||
assign bf = {b[WIDTH-1] ^ sgnd, b[WIDTH-2:0]};
|
assign bf = {b[WIDTH-1] ^ sgnd, b[WIDTH-2:0]};
|
||||||
|
|
||||||
// behavioral description gives best results
|
// Behavioral description gives best results
|
||||||
assign eq = (a == b);
|
assign eq = (a == b); // eq = 1 when operands are equal, 0 otherwise
|
||||||
assign lt = (af < bf);
|
assign lt = (af < bf); // lt = 1 when a less than b (taking signed operands into account)
|
||||||
assign flags = {eq, lt};
|
assign flags = {eq, lt};
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Other comparators evaluated
|
Other comparators evaluated:
|
||||||
|
|
||||||
module donedet #(parameter WIDTH=64) (
|
module donedet #(parameter WIDTH=64) (
|
||||||
input logic [WIDTH-1:0] a, b,
|
input logic [WIDTH-1:0] a, b,
|
||||||
@ -86,7 +87,7 @@ module comparator_sub #(parameter WIDTH=64) (
|
|||||||
assign flags = {eq, lt, ltu};
|
assign flags = {eq, lt, ltu};
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
// *** eventually substitute comparator_flip, which gives slightly better synthesis
|
// comparator_flip, gives slightly better synthesis
|
||||||
module comparator #(parameter WIDTH=64) (
|
module comparator #(parameter WIDTH=64) (
|
||||||
input logic [WIDTH-1:0] a, b,
|
input logic [WIDTH-1:0] a, b,
|
||||||
output logic [2:0] flags);
|
output logic [2:0] flags);
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// controller.sv
|
// controller.sv
|
||||||
//
|
//
|
||||||
// Written: David_Harris@hmc.edu 9 January 2021
|
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
|
||||||
|
// Created: 9 January 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: Top level controller module
|
// Purpose: Top level controller module
|
||||||
@ -30,86 +31,87 @@
|
|||||||
|
|
||||||
|
|
||||||
module controller(
|
module controller(
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
// Decode stage control signals
|
// Decode stage control signals
|
||||||
input logic StallD, FlushD,
|
input logic StallD, FlushD, // Stall, flush Decode stage
|
||||||
input logic [31:0] InstrD,
|
input logic [31:0] InstrD, // Instruction in Decode stage
|
||||||
output logic [2:0] ImmSrcD,
|
output logic [2:0] ImmSrcD, // Type of immediate extension
|
||||||
input logic IllegalIEUInstrFaultD,
|
input logic IllegalIEUInstrFaultD, // Illegal IEU instruction
|
||||||
output logic IllegalBaseInstrFaultD,
|
output logic IllegalBaseInstrFaultD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers
|
||||||
// Execute stage control signals
|
// Execute stage control signals
|
||||||
input logic StallE, FlushE,
|
input logic StallE, FlushE, // Stall, flush Execute stage
|
||||||
input logic [1:0] FlagsE,
|
input logic [1:0] FlagsE, // Comparison flags ({eq, lt})
|
||||||
input logic FWriteIntE,
|
input logic FWriteIntE, // Write integer register, coming from FPU controller
|
||||||
output logic PCSrcE, // for datapath and Hazard Unit
|
output logic PCSrcE, // Select signal to choose next PC (for datapath and Hazard unit)
|
||||||
output logic [2:0] ALUControlE,
|
output logic [2:0] ALUControlE, // ALU operation to perform
|
||||||
output logic ALUSrcAE, ALUSrcBE,
|
output logic ALUSrcAE, ALUSrcBE, // ALU operands
|
||||||
output logic ALUResultSrcE,
|
output logic ALUResultSrcE, // Selects result to pass on to Memory stage
|
||||||
output logic MemReadE, CSRReadE, // for Hazard Unit
|
output logic MemReadE, CSRReadE, // Instruction reads memory, reads a CSR (needed for Hazard unit)
|
||||||
output logic [2:0] Funct3E,
|
output logic [2:0] Funct3E, // Instruction's funct3 field
|
||||||
output logic IntDivE, MDUE, W64E,
|
output logic IntDivE, // Integer divide
|
||||||
output logic JumpE,
|
output logic MDUE, // MDU (multiply/divide) operatio
|
||||||
output logic SCE,
|
output logic W64E, // RV64 W-type operation
|
||||||
output logic BranchSignedE,
|
output logic JumpE, // jump instruction
|
||||||
|
output logic SCE, // Store Conditional instruction
|
||||||
|
output logic BranchSignedE, // Branch comparison operands are signed (if it's a branch)
|
||||||
// Memory stage control signals
|
// Memory stage control signals
|
||||||
input logic StallM, FlushM,
|
input logic StallM, FlushM, // Stall, flush Memory stage
|
||||||
output logic [1:0] MemRWM,
|
output logic [1:0] MemRWM, // Mem read/write: MemRWM[1] = 1 for read, MemRWM[0] = 1 for write
|
||||||
output logic CSRReadM, CSRWriteM, PrivilegedM,
|
output logic CSRReadM, CSRWriteM, PrivilegedM, // CSR read, write, or privileged instruction
|
||||||
output logic [1:0] AtomicM,
|
output logic [1:0] AtomicM, // Atomic (AMO) instruction
|
||||||
output logic [2:0] Funct3M,
|
output logic [2:0] Funct3M, // Instruction's funct3 field
|
||||||
output logic RegWriteM, // for Hazard Unit
|
output logic RegWriteM, // Instruction writes a register (needed for Hazard unit)
|
||||||
output logic InvalidateICacheM, FlushDCacheM,
|
output logic InvalidateICacheM, FlushDCacheM, // Invalidate I$, flush D$
|
||||||
output logic InstrValidM,
|
output logic InstrValidM, // Instruction is valid
|
||||||
output logic FWriteIntM,
|
output logic FWriteIntM, // FPU controller writes integer register file
|
||||||
// Writeback stage control signals
|
// Writeback stage control signals
|
||||||
input logic StallW, FlushW,
|
input logic StallW, FlushW, // Stall, flush Writeback stage
|
||||||
output logic RegWriteW, IntDivW, // for datapath and Hazard Unit
|
output logic RegWriteW, IntDivW, // Instruction writes a register, is an integer divide
|
||||||
output logic [2:0] ResultSrcW,
|
output logic [2:0] ResultSrcW, // Select source of result to write back to register file
|
||||||
// Stall during CSRs
|
// Stall during CSRs
|
||||||
//output logic CSRWriteFencePendingDEM,
|
output logic CSRWriteFenceM, // CSR write or fence instruction; needs to flush the following instructions
|
||||||
output logic CSRWriteFenceM,
|
output logic StoreStallD // Store (memory write) causes stall
|
||||||
output logic StoreStallD
|
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [6:0] OpD;
|
logic [6:0] OpD; // Opcode in Decode stage
|
||||||
logic [2:0] Funct3D;
|
logic [2:0] Funct3D; // Funct3 field in Decode stage
|
||||||
logic [6:0] Funct7D;
|
logic [6:0] Funct7D; // Funct7 field in Decode stage
|
||||||
logic [4:0] Rs1D;
|
logic [4:0] Rs1D; // Rs1 source register in Decode stage
|
||||||
|
|
||||||
`define CTRLW 23
|
`define CTRLW 23
|
||||||
|
|
||||||
// pipelined control signals
|
// pipelined control signals
|
||||||
logic RegWriteD, RegWriteE;
|
logic RegWriteD, RegWriteE; // RegWrite (register will be written)
|
||||||
logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM;
|
logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM; // Select which result to write back to register file
|
||||||
logic [1:0] MemRWD, MemRWE;
|
logic [1:0] MemRWD, MemRWE; // Store (write to memory)
|
||||||
logic JumpD;
|
logic JumpD; // Jump instruction
|
||||||
logic BranchD, BranchE;
|
logic BranchD, BranchE; // Branch instruction
|
||||||
logic ALUOpD;
|
logic ALUOpD; // 0 for address generation, 1 for all other operations (must use Funct3)
|
||||||
logic [2:0] ALUControlD;
|
logic [2:0] ALUControlD; // Determines ALU operation
|
||||||
logic ALUSrcAD, ALUSrcBD;
|
logic ALUSrcAD, ALUSrcBD; // ALU inputs
|
||||||
logic ALUResultSrcD, W64D, MDUD;
|
logic ALUResultSrcD, W64D, MDUD; // ALU result, is RV64 W-type, is multiply/divide instruction
|
||||||
logic CSRZeroSrcD;
|
logic CSRZeroSrcD; // Ignore setting and clearing zeros to CSR
|
||||||
logic CSRReadD;
|
logic CSRReadD; // CSR read instruction
|
||||||
logic [1:0] AtomicD;
|
logic [1:0] AtomicD; // Atomic (AMO) instruction
|
||||||
logic FenceXD;
|
logic FenceXD; // Fence instruction
|
||||||
logic InvalidateICacheD, FlushDCacheD;
|
logic InvalidateICacheD, FlushDCacheD;// Invalidate I$, flush D$
|
||||||
logic CSRWriteD, CSRWriteE;
|
logic CSRWriteD, CSRWriteE; // CSR write
|
||||||
logic InstrValidD, InstrValidE;
|
logic InstrValidD, InstrValidE; // Instruction is valid
|
||||||
logic PrivilegedD, PrivilegedE;
|
logic PrivilegedD, PrivilegedE; // Privileged instruction
|
||||||
logic InvalidateICacheE, FlushDCacheE;
|
logic InvalidateICacheE, FlushDCacheE;// Invalidate I$, flush D$
|
||||||
logic [`CTRLW-1:0] ControlsD;
|
logic [`CTRLW-1:0] ControlsD; // Main Instruction Decoder control signals
|
||||||
logic SubArithD;
|
logic SubArithD; // TRUE for R-type subtracts and sra, slt, sltu
|
||||||
logic subD, sraD, sltD, sltuD;
|
logic subD, sraD, sltD, sltuD; // Indicates if is one of these instructions
|
||||||
logic BranchTakenE;
|
logic BranchTakenE; // Branch is taken
|
||||||
logic eqE, ltE;
|
logic eqE, ltE; // Comparator outputs
|
||||||
logic unused;
|
logic unused;
|
||||||
logic BranchFlagE;
|
logic BranchFlagE; // Branch flag to use (chosen between eq or lt)
|
||||||
logic IEURegWriteE;
|
logic IEURegWriteE; // Register write
|
||||||
logic IllegalERegAdrD;
|
logic IllegalERegAdrD; // RV32E attempts to write upper 16 registers
|
||||||
logic [1:0] AtomicE;
|
logic [1:0] AtomicE; // Atomic instruction
|
||||||
logic FenceD, FenceE, FenceM;
|
logic FenceD, FenceE, FenceM; // Fence instruction
|
||||||
logic SFenceVmaD;
|
logic SFenceVmaD; // sfence.vma instruction
|
||||||
logic IntDivM;
|
logic IntDivM; // Integer divide instruction
|
||||||
|
|
||||||
|
|
||||||
// Extract fields
|
// Extract fields
|
||||||
@ -122,58 +124,58 @@ module controller(
|
|||||||
always_comb
|
always_comb
|
||||||
case(OpD)
|
case(OpD)
|
||||||
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MDU_Atomic_Illegal
|
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MDU_Atomic_Illegal
|
||||||
7'b0000000: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // illegal instruction
|
7'b0000000: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Illegal instruction
|
||||||
7'b0000011: ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // lw
|
7'b0000011: ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // lw
|
||||||
7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // flw - only legal if FP supported
|
7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // flw - only legal if FP supported
|
||||||
7'b0001111: if(`ZIFENCEI_SUPPORTED)
|
7'b0001111: if (`ZIFENCEI_SUPPORTED)
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence
|
||||||
else
|
else
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0; // fence treated as nop
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0; // fence treated as nop
|
||||||
7'b0010011: ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU
|
7'b0010011: ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU
|
||||||
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
|
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
|
||||||
7'b0011011: if (`XLEN == 64)
|
7'b0011011: if (`XLEN == 64)
|
||||||
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
|
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
|
||||||
else
|
else
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
|
||||||
7'b0100011: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // sw
|
7'b0100011: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // sw
|
||||||
7'b0100111: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // fsw - only legal if FP supported
|
7'b0100111: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // fsw - only legal if FP supported
|
||||||
7'b0101111: if (`A_SUPPORTED) begin
|
7'b0101111: if (`A_SUPPORTED) begin
|
||||||
if (InstrD[31:27] == 5'b00010)
|
if (InstrD[31:27] == 5'b00010)
|
||||||
ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0; // lr
|
ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0; // lr
|
||||||
else if (InstrD[31:27] == 5'b00011)
|
else if (InstrD[31:27] == 5'b00011)
|
||||||
ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0; // sc
|
ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0; // sc
|
||||||
else
|
else
|
||||||
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0;; // amo
|
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0; // amo
|
||||||
end else
|
end else
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
|
||||||
7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000)
|
7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000)
|
||||||
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type
|
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type
|
||||||
else if (Funct7D == 7'b0000001 & `M_SUPPORTED)
|
else if (Funct7D == 7'b0000001 & `M_SUPPORTED)
|
||||||
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/Divide
|
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/divide
|
||||||
else
|
else
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
|
||||||
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
|
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
|
||||||
7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000) & `XLEN == 64)
|
7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000) & `XLEN == 64)
|
||||||
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
|
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
|
||||||
else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64)
|
else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64)
|
||||||
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
|
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
|
||||||
else
|
else
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
|
||||||
7'b1100011: ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches
|
7'b1100011: ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches
|
||||||
7'b1100111: ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr
|
7'b1100111: ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr
|
||||||
7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0; // jal
|
7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0; // jal
|
||||||
7'b1110011: if (`ZICSR_SUPPORTED) begin
|
7'b1110011: if (`ZICSR_SUPPORTED) begin
|
||||||
if (Funct3D == 3'b000)
|
if (Funct3D == 3'b000)
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules
|
||||||
else
|
else
|
||||||
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs
|
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs
|
||||||
end else
|
end else
|
||||||
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
||||||
default: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
default: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// unswizzle control bits
|
// Unswizzle control bits
|
||||||
// squash control signals if coming from an illegal compressed instruction
|
// Squash control signals if coming from an illegal compressed instruction
|
||||||
// On RV32E, can't write to upper 16 registers. Checking reads to upper 16 is more costly so disregard them.
|
// On RV32E, can't write to upper 16 registers. Checking reads to upper 16 is more costly so disregard them.
|
||||||
assign IllegalERegAdrD = `E_SUPPORTED & `ZICSR_SUPPORTED & ControlsD[`CTRLW-1] & InstrD[11];
|
assign IllegalERegAdrD = `E_SUPPORTED & `ZICSR_SUPPORTED & ControlsD[`CTRLW-1] & InstrD[11];
|
||||||
assign IllegalBaseInstrFaultD = ControlsD[0] | IllegalERegAdrD;
|
assign IllegalBaseInstrFaultD = ControlsD[0] | IllegalERegAdrD;
|
||||||
@ -183,7 +185,7 @@ module controller(
|
|||||||
|
|
||||||
|
|
||||||
assign CSRZeroSrcD = InstrD[14] ? (InstrD[19:15] == 0) : (Rs1D == 0); // Is a CSR instruction using zero as the source?
|
assign CSRZeroSrcD = InstrD[14] ? (InstrD[19:15] == 0) : (Rs1D == 0); // Is a CSR instruction using zero as the source?
|
||||||
assign CSRWriteD = CSRReadD & !(CSRZeroSrcD & InstrD[13]); // Don't write if setting or clearing zeros
|
assign CSRWriteD = CSRReadD & !(CSRZeroSrcD & InstrD[13]); // Don't write if setting or clearing zeros
|
||||||
assign SFenceVmaD = PrivilegedD & (InstrD[31:25] == 7'b0001001);
|
assign SFenceVmaD = PrivilegedD & (InstrD[31:25] == 7'b0001001);
|
||||||
assign FenceD = SFenceVmaD | FenceXD; // possible sfence.vma or fence.i
|
assign FenceD = SFenceVmaD | FenceXD; // possible sfence.vma or fence.i
|
||||||
|
|
||||||
@ -197,7 +199,7 @@ module controller(
|
|||||||
|
|
||||||
// Fences
|
// Fences
|
||||||
// Ordinary fence is presently a nop
|
// Ordinary fence is presently a nop
|
||||||
// FENCE.I flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented
|
// fence.i flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented
|
||||||
if (`ZIFENCEI_SUPPORTED & `ICACHE) begin:fencei
|
if (`ZIFENCEI_SUPPORTED & `ICACHE) begin:fencei
|
||||||
logic FenceID;
|
logic FenceID;
|
||||||
assign FenceID = FenceXD & (Funct3D == 3'b001); // is it a FENCE.I instruction?
|
assign FenceID = FenceXD & (Funct3D == 3'b001); // is it a FENCE.I instruction?
|
||||||
@ -243,7 +245,7 @@ module controller(
|
|||||||
|
|
||||||
// Flush F, D, and E stages on a CSR write or Fence.I or SFence.VMA
|
// Flush F, D, and E stages on a CSR write or Fence.I or SFence.VMA
|
||||||
assign CSRWriteFenceM = CSRWriteM | FenceM;
|
assign CSRWriteFenceM = CSRWriteM | FenceM;
|
||||||
// assign CSRWriteFencePendingDEM = CSRWriteD | CSRWriteE | CSRWriteM | FenceD | FenceE | FenceM;
|
// assign CSRWriteFencePendingDEM = CSRWriteD | CSRWriteE | CSRWriteM | FenceD | FenceE | FenceM;
|
||||||
|
|
||||||
// the synchronous DTIM cannot read immediately after write
|
// the synchronous DTIM cannot read immediately after write
|
||||||
// a cache cannot read or write immediately after a write
|
// a cache cannot read or write immediately after a write
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// datapath.sv
|
// datapath.sv
|
||||||
//
|
//
|
||||||
// Written: sarahleilani@gmail.com and David_Harris@hmc.edu 9 January 2021
|
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
|
||||||
|
// Created: 9 January 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: Wally Integer Datapath
|
// Purpose: Wally Integer Datapath
|
||||||
@ -29,73 +30,75 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module datapath (
|
module datapath (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
// Decode stage signals
|
// Decode stage signals
|
||||||
input logic [2:0] ImmSrcD,
|
input logic [2:0] ImmSrcD, // Selects type of immediate extension
|
||||||
input logic [31:0] InstrD,
|
input logic [31:0] InstrD, // Instruction in Decode stage
|
||||||
input logic [2:0] Funct3E,
|
input logic [2:0] Funct3E, // Funct3 field of instruction in Execute stage
|
||||||
// Execute stage signals
|
// Execute stage signals
|
||||||
input logic StallE, FlushE,
|
input logic StallE, FlushE, // Stall, flush Execute stage
|
||||||
input logic [1:0] ForwardAE, ForwardBE,
|
input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages
|
||||||
input logic [2:0] ALUControlE,
|
input logic [2:0] ALUControlE, // Indicate operation ALU performs
|
||||||
input logic ALUSrcAE, ALUSrcBE,
|
input logic ALUSrcAE, ALUSrcBE, // ALU operands
|
||||||
input logic ALUResultSrcE,
|
input logic ALUResultSrcE, // Selects result to pass on to Memory stage
|
||||||
input logic JumpE,
|
input logic JumpE, // Is a jump (j) instruction
|
||||||
input logic BranchSignedE,
|
input logic BranchSignedE, // Branch comparison operands are signed (if it's a branch)
|
||||||
input logic [`XLEN-1:0] PCE,
|
input logic [`XLEN-1:0] PCE, // PC in Execute stage
|
||||||
input logic [`XLEN-1:0] PCLinkE,
|
input logic [`XLEN-1:0] PCLinkE, // PC + 4 (of instruction in Execute stage)
|
||||||
output logic [1:0] FlagsE,
|
output logic [1:0] FlagsE, // Comparison flags ({eq, lt})
|
||||||
output logic [`XLEN-1:0] IEUAdrE,
|
output logic [`XLEN-1:0] IEUAdrE, // Address computed by ALU
|
||||||
output logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B
|
output logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU sources before the mux chooses between them and PCE to put in srcA/B
|
||||||
// Memory stage signals
|
// Memory stage signals
|
||||||
input logic StallM, FlushM,
|
input logic StallM, FlushM, // Stall, flush Memory stage
|
||||||
input logic FWriteIntM, FCvtIntW,
|
input logic FWriteIntM, FCvtIntW, // FPU writes integer register file, FPU converts float to int
|
||||||
input logic [`XLEN-1:0] FIntResM,
|
input logic [`XLEN-1:0] FIntResM, // FPU integer result
|
||||||
output logic [`XLEN-1:0] SrcAM,
|
output logic [`XLEN-1:0] SrcAM, // ALU's Source A in Memory stage to privilege unit for CSR writes
|
||||||
output logic [`XLEN-1:0] WriteDataM,
|
output logic [`XLEN-1:0] WriteDataM, // Write data in Memory stage
|
||||||
// Writeback stage signals
|
// Writeback stage signals
|
||||||
input logic StallW, FlushW,
|
input logic StallW, FlushW, // Stall, flush Writeback stage
|
||||||
(* mark_debug = "true" *) input logic RegWriteW, IntDivW,
|
(* mark_debug = "true" *) input logic RegWriteW, IntDivW, // Write register file, integer divide instruction
|
||||||
input logic SquashSCW,
|
input logic SquashSCW, // Squash a store conditional when a conflict arose
|
||||||
input logic [2:0] ResultSrcW,
|
input logic [2:0] ResultSrcW, // Select source of result to write back to register file
|
||||||
input logic [`XLEN-1:0] FCvtIntResW,
|
input logic [`XLEN-1:0] FCvtIntResW, // FPU convert fp to integer result
|
||||||
input logic [`XLEN-1:0] ReadDataW,
|
input logic [`XLEN-1:0] ReadDataW, // Read data from LSU
|
||||||
input logic [`XLEN-1:0] CSRReadValW, MDUResultW,
|
input logic [`XLEN-1:0] CSRReadValW, MDUResultW, // CSR read result, MDU (Multiply/divide unit) result
|
||||||
input logic [`XLEN-1:0] FIntDivResultW,
|
input logic [`XLEN-1:0] FIntDivResultW, // FPU's integer divide result
|
||||||
// Hazard Unit signals
|
// Hazard Unit signals
|
||||||
output logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E,
|
output logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, // Register sources to read in Decode or Execute stage
|
||||||
output logic [4:0] RdE, RdM, RdW
|
output logic [4:0] RdE, RdM, RdW // Register destinations in Execute, Memory, or Writeback stage
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fetch stage signals
|
// Fetch stage signals
|
||||||
// Decode stage signals
|
// Decode stage signals
|
||||||
logic [`XLEN-1:0] R1D, R2D;
|
logic [`XLEN-1:0] R1D, R2D; // Read data from Rs1 (RD1), Rs2 (RD2)
|
||||||
logic [`XLEN-1:0] ExtImmD;
|
logic [`XLEN-1:0] ImmExtD; // Extended immediate in Decode stage
|
||||||
logic [4:0] RdD;
|
logic [4:0] RdD; // Destination register in Decode stage
|
||||||
// Execute stage signals
|
// Execute stage signals
|
||||||
logic [`XLEN-1:0] R1E, R2E;
|
logic [`XLEN-1:0] R1E, R2E; // Source operands read from register file
|
||||||
logic [`XLEN-1:0] ExtImmE;
|
logic [`XLEN-1:0] ImmExtE; // Extended immediate in Execute stage
|
||||||
logic [`XLEN-1:0] SrcAE, SrcBE;
|
logic [`XLEN-1:0] SrcAE, SrcBE; // ALU operands
|
||||||
logic [`XLEN-1:0] ALUResultE, AltResultE, IEUResultE;
|
logic [`XLEN-1:0] ALUResultE, AltResultE, IEUResultE; // ALU result, Alternative result (ImmExtE or PC+4), computed address *** According to Figure 4.12, IEUResultE should be called IEUAdrE
|
||||||
// Memory stage signals
|
// Memory stage signals
|
||||||
logic [`XLEN-1:0] IEUResultM;
|
logic [`XLEN-1:0] IEUResultM; // Address computed by ALU *** According to Figure 4.12, IEUResultM should be called IEUAdrM
|
||||||
logic [`XLEN-1:0] IFResultM;
|
logic [`XLEN-1:0] IFResultM; // Result from either IEU or single-cycle FPU op writing an integer register
|
||||||
// Writeback stage signals
|
// Writeback stage signals
|
||||||
logic [`XLEN-1:0] SCResultW;
|
logic [`XLEN-1:0] SCResultW; // Store Conditional result
|
||||||
logic [`XLEN-1:0] ResultW;
|
logic [`XLEN-1:0] ResultW; // Result to write to register file
|
||||||
logic [`XLEN-1:0] IFResultW, IFCvtResultW, MulDivResultW;
|
logic [`XLEN-1:0] IFResultW; // Result from either IEU or single-cycle FPU op writing an integer register
|
||||||
|
logic [`XLEN-1:0] IFCvtResultW; // Result from IEU, signle-cycle FPU op, or 2-cycle FCVT float to int
|
||||||
|
logic [`XLEN-1:0] MulDivResultW; // Multiply always comes from MDU. Divide could come from MDU or FPU (when using fdivsqrt for integer division)
|
||||||
|
|
||||||
// Decode stage
|
// Decode stage
|
||||||
assign Rs1D = InstrD[19:15];
|
assign Rs1D = InstrD[19:15];
|
||||||
assign Rs2D = InstrD[24:20];
|
assign Rs2D = InstrD[24:20];
|
||||||
assign RdD = InstrD[11:7];
|
assign RdD = InstrD[11:7];
|
||||||
regfile regf(clk, reset, RegWriteW, Rs1D, Rs2D, RdW, ResultW, R1D, R2D);
|
regfile regf(clk, reset, RegWriteW, Rs1D, Rs2D, RdW, ResultW, R1D, R2D);
|
||||||
extend ext(.InstrD(InstrD[31:7]), .ImmSrcD, .ExtImmD);
|
extend ext(.InstrD(InstrD[31:7]), .ImmSrcD, .ImmExtD);
|
||||||
|
|
||||||
// Execute stage pipeline register and logic
|
// Execute stage pipeline register and logic
|
||||||
flopenrc #(`XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E);
|
flopenrc #(`XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E);
|
||||||
flopenrc #(`XLEN) RD2EReg(clk, reset, FlushE, ~StallE, R2D, R2E);
|
flopenrc #(`XLEN) RD2EReg(clk, reset, FlushE, ~StallE, R2D, R2E);
|
||||||
flopenrc #(`XLEN) ExtImmEReg(clk, reset, FlushE, ~StallE, ExtImmD, ExtImmE);
|
flopenrc #(`XLEN) ImmExtEReg(clk, reset, FlushE, ~StallE, ImmExtD, ImmExtE);
|
||||||
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
|
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
|
||||||
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
|
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
|
||||||
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
|
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
|
||||||
@ -104,9 +107,9 @@ module datapath (
|
|||||||
mux3 #(`XLEN) fbemux(R2E, ResultW, IFResultM, ForwardBE, ForwardedSrcBE);
|
mux3 #(`XLEN) fbemux(R2E, ResultW, IFResultM, ForwardBE, ForwardedSrcBE);
|
||||||
comparator_dc_flip #(`XLEN) comp(ForwardedSrcAE, ForwardedSrcBE, BranchSignedE, FlagsE);
|
comparator_dc_flip #(`XLEN) comp(ForwardedSrcAE, ForwardedSrcBE, BranchSignedE, FlagsE);
|
||||||
mux2 #(`XLEN) srcamux(ForwardedSrcAE, PCE, ALUSrcAE, SrcAE);
|
mux2 #(`XLEN) srcamux(ForwardedSrcAE, PCE, ALUSrcAE, SrcAE);
|
||||||
mux2 #(`XLEN) srcbmux(ForwardedSrcBE, ExtImmE, ALUSrcBE, SrcBE);
|
mux2 #(`XLEN) srcbmux(ForwardedSrcBE, ImmExtE, ALUSrcBE, SrcBE);
|
||||||
alu #(`XLEN) alu(SrcAE, SrcBE, ALUControlE, Funct3E, ALUResultE, IEUAdrE);
|
alu #(`XLEN) alu(SrcAE, SrcBE, ALUControlE, Funct3E, ALUResultE, IEUAdrE);
|
||||||
mux2 #(`XLEN) altresultmux(ExtImmE, PCLinkE, JumpE, AltResultE);
|
mux2 #(`XLEN) altresultmux(ImmExtE, PCLinkE, JumpE, AltResultE);
|
||||||
mux2 #(`XLEN) ieuresultmux(ALUResultE, AltResultE, ALUResultSrcE, IEUResultE);
|
mux2 #(`XLEN) ieuresultmux(ALUResultE, AltResultE, ALUResultSrcE, IEUResultE);
|
||||||
|
|
||||||
// Memory stage pipeline register
|
// Memory stage pipeline register
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// extend.sv
|
// extend.sv
|
||||||
//
|
//
|
||||||
// Written: David_Harris@hmc.edu 9 January 2021
|
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
|
||||||
|
// Created: 9 January 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: Produce sign-extended immediates from various formats
|
// Purpose: Produce sign-extended immediates from various formats
|
||||||
@ -29,27 +30,27 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module extend (
|
module extend (
|
||||||
input logic [31:7] InstrD,
|
input logic [31:7] InstrD, // All instruction bits except opcode (lower 7 bits)
|
||||||
input logic [2:0] ImmSrcD,
|
input logic [2:0] ImmSrcD, // Select what kind of extension to perform
|
||||||
output logic [`XLEN-1:0 ] ExtImmD);
|
output logic [`XLEN-1:0 ] ImmExtD); // Extended immediate
|
||||||
|
|
||||||
localparam [`XLEN-1:0] undefined = {(`XLEN){1'bx}}; // could change to 0 after debug
|
localparam [`XLEN-1:0] undefined = {(`XLEN){1'bx}}; // could change to 0 after debug
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
case(ImmSrcD)
|
case(ImmSrcD)
|
||||||
// I-type
|
// I-type
|
||||||
3'b000: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:20]};
|
3'b000: ImmExtD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:20]};
|
||||||
// S-type (stores)
|
// S-type (stores)
|
||||||
3'b001: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]};
|
3'b001: ImmExtD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]};
|
||||||
// B-type (branches)
|
// B-type (branches)
|
||||||
3'b010: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0};
|
3'b010: ImmExtD = {{(`XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0};
|
||||||
// J-type (jal)
|
// J-type (jal)
|
||||||
3'b011: ExtImmD = {{(`XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
|
3'b011: ImmExtD = {{(`XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
|
||||||
// U-type (lui, auipc)
|
// U-type (lui, auipc)
|
||||||
3'b100: ExtImmD = {{(`XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
|
3'b100: ImmExtD = {{(`XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
|
||||||
// Store Conditional: zero offset
|
// Store Conditional: zero offset
|
||||||
3'b101: if (`A_SUPPORTED) ExtImmD = 0;
|
3'b101: if (`A_SUPPORTED) ImmExtD = 0;
|
||||||
else ExtImmD = undefined;
|
else ImmExtD = undefined;
|
||||||
default: ExtImmD = undefined; // undefined
|
default: ImmExtD = undefined; // undefined
|
||||||
endcase
|
endcase
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// forward.sv
|
// forward.sv
|
||||||
//
|
//
|
||||||
// Written: David_Harris@hmc.edu 9 January 2021
|
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
|
||||||
|
// Created: 9 January 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: Determine datapath forwarding
|
// Purpose: Determine datapath forwarding
|
||||||
@ -30,17 +31,17 @@
|
|||||||
|
|
||||||
module forward(
|
module forward(
|
||||||
// Detect hazards
|
// Detect hazards
|
||||||
input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
|
input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW, // Source and destination registers
|
||||||
input logic MemReadE, MDUE, CSRReadE,
|
input logic MemReadE, MDUE, CSRReadE, // Execute stage instruction is a load (MemReadE), divide (MDUE), or CSR read (CSRReadE)
|
||||||
input logic RegWriteM, RegWriteW,
|
input logic RegWriteM, RegWriteW, // Instruction in Memory or Writeback stage writes register file
|
||||||
input logic FCvtIntE,
|
input logic FCvtIntE, // FPU convert float to int
|
||||||
input logic SCE,
|
input logic SCE, // Store Conditional instruction
|
||||||
// Forwarding controls
|
// Forwarding controls
|
||||||
output logic [1:0] ForwardAE, ForwardBE,
|
output logic [1:0] ForwardAE, ForwardBE, // Select signals for forwarding multiplexers
|
||||||
output logic FCvtIntStallD, LoadStallD, MDUStallD, CSRRdStallD
|
output logic FCvtIntStallD, LoadStallD, MDUStallD, CSRRdStallD // Stall due to conversion, load, multiply/divide, CSR read
|
||||||
);
|
);
|
||||||
|
|
||||||
logic MatchDE;
|
logic MatchDE; // Match between a source register in Decode stage and destination register in Execute stage
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
ForwardAE = 2'b00;
|
ForwardAE = 2'b00;
|
||||||
|
@ -29,67 +29,66 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module ieu (
|
module ieu (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
// Decode Stage interface
|
// Decode stage signals
|
||||||
input logic [31:0] InstrD,
|
input logic [31:0] InstrD, // Instruction
|
||||||
input logic IllegalIEUInstrFaultD,
|
input logic IllegalIEUInstrFaultD, // Illegal instruction
|
||||||
output logic IllegalBaseInstrFaultD,
|
output logic IllegalBaseInstrFaultD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers
|
||||||
// Execute Stage interface
|
// Execute stage signals
|
||||||
input logic [`XLEN-1:0] PCE,
|
input logic [`XLEN-1:0] PCE, // PC
|
||||||
input logic [`XLEN-1:0] PCLinkE,
|
input logic [`XLEN-1:0] PCLinkE, // PC + 4
|
||||||
input logic FWriteIntE, FCvtIntE, FCvtIntW,
|
input logic FWriteIntE, FCvtIntE, // FPU writes to integer register file, FPU converts float to int
|
||||||
output logic [`XLEN-1:0] IEUAdrE,
|
output logic [`XLEN-1:0] IEUAdrE, // Memory address
|
||||||
output logic IntDivE, W64E,
|
output logic IntDivE, W64E, // Integer divide, RV64 W-type instruction
|
||||||
output logic [2:0] Funct3E,
|
output logic [2:0] Funct3E, // Funct3 instruction field
|
||||||
output logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // these are the src outputs before the mux choosing between them and PCE to put in srcA/B
|
output logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU src inputs before the mux choosing between them and PCE to put in srcA/B
|
||||||
|
output logic [4:0] RdE, // Destination register
|
||||||
// Memory stage interface
|
// Memory stage signals
|
||||||
input logic SquashSCW, // from LSU
|
input logic SquashSCW, // Squash store conditional, from LSU
|
||||||
output logic [1:0] MemRWM, // read/write control goes to LSU
|
output logic [1:0] MemRWM, // Read/write control goes to LSU
|
||||||
output logic [1:0] AtomicM, // atomic control goes to LSU
|
output logic [1:0] AtomicM, // Atomic control goes to LSU
|
||||||
output logic [`XLEN-1:0] WriteDataM, // write data to LSU
|
output logic [`XLEN-1:0] WriteDataM, // Write data to LSU
|
||||||
|
output logic [2:0] Funct3M, // Funct3 (size and signedness) to LSU
|
||||||
output logic [2:0] Funct3M, // size and signedness to LSU
|
output logic [`XLEN-1:0] SrcAM, // ALU SrcA to Privileged unit and FPU
|
||||||
output logic [`XLEN-1:0] SrcAM, // to privilege and fpu
|
output logic [4:0] RdM, // Destination register
|
||||||
output logic [4:0] RdE, RdM,
|
input logic [`XLEN-1:0] FIntResM, // Integer result from FPU (fmv, fclass, fcmp)
|
||||||
input logic [`XLEN-1:0] FIntResM,
|
output logic InvalidateICacheM, FlushDCacheM, // Invalidate I$, flush D$
|
||||||
output logic InvalidateICacheM, FlushDCacheM,
|
output logic InstrValidM, // Instruction is valid
|
||||||
|
// Writeback stage signals
|
||||||
// Writeback stage
|
input logic [`XLEN-1:0] FIntDivResultW, // Integer divide result from FPU fdivsqrt
|
||||||
input logic [`XLEN-1:0] FIntDivResultW,
|
input logic [`XLEN-1:0] CSRReadValW, MDUResultW, // CSR read value, MDU (multiply/divide unit) result
|
||||||
input logic [`XLEN-1:0] CSRReadValW, MDUResultW,
|
input logic [`XLEN-1:0] FCvtIntResW, // FPU's float to int conversion result
|
||||||
input logic [`XLEN-1:0] FCvtIntResW,
|
input logic FCvtIntW, // FPU converts float to int
|
||||||
output logic [4:0] RdW,
|
output logic [4:0] RdW, // Destination register
|
||||||
input logic [`XLEN-1:0] ReadDataW,
|
input logic [`XLEN-1:0] ReadDataW, // LSU's read data
|
||||||
output logic InstrValidM,
|
// Hazard unit signals
|
||||||
// hazards
|
input logic StallD, StallE, StallM, StallW, // Stall signals from hazard unit
|
||||||
input logic StallD, StallE, StallM, StallW,
|
input logic FlushD, FlushE, FlushM, FlushW, // Flush signals
|
||||||
input logic FlushD, FlushE, FlushM, FlushW,
|
output logic FCvtIntStallD, LoadStallD, // Stall causes from IEU to hazard unit
|
||||||
output logic FCvtIntStallD, LoadStallD, MDUStallD, CSRRdStallD,
|
output logic MDUStallD, CSRRdStallD, StoreStallD,
|
||||||
output logic PCSrcE,
|
output logic PCSrcE, // Select next PC (between PC+4 and IEUAdrE)
|
||||||
output logic CSRReadM, CSRWriteM, PrivilegedM,
|
output logic CSRReadM, CSRWriteM, PrivilegedM,// CSR read, CSR write, is privileged instruction
|
||||||
output logic CSRWriteFenceM,
|
output logic CSRWriteFenceM // CSR write or fence instruction needs to flush subsequent instructions
|
||||||
output logic StoreStallD
|
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [2:0] ImmSrcD;
|
logic [2:0] ImmSrcD; // Select type of immediate extension
|
||||||
logic [1:0] FlagsE;
|
logic [1:0] FlagsE; // Comparison flags ({eq, lt})
|
||||||
logic [2:0] ALUControlE;
|
logic [2:0] ALUControlE; // ALU Control
|
||||||
logic ALUSrcAE, ALUSrcBE;
|
logic ALUSrcAE, ALUSrcBE; // ALU source operands
|
||||||
logic [2:0] ResultSrcW;
|
logic [2:0] ResultSrcW; // Source of result in Writeback stage
|
||||||
logic ALUResultSrcE;
|
logic ALUResultSrcE; // ALU result
|
||||||
logic SCE;
|
logic SCE; // Store Conditional instruction
|
||||||
logic FWriteIntM;
|
logic FWriteIntM; // FPU writing to integer register file
|
||||||
logic IntDivW;
|
logic IntDivW; // Integer divide instruction
|
||||||
|
|
||||||
// forwarding signals
|
// forwarding signals
|
||||||
logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E;
|
logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E; // Source and destination registers
|
||||||
logic [1:0] ForwardAE, ForwardBE;
|
logic [1:0] ForwardAE, ForwardBE; // Select signals for forwarding multiplexers
|
||||||
logic RegWriteM, RegWriteW;
|
logic RegWriteM, RegWriteW; // Register will be written in Memory, Writeback stages
|
||||||
logic MemReadE, CSRReadE;
|
logic MemReadE, CSRReadE; // Load, CSRRead instruction
|
||||||
logic JumpE;
|
logic JumpE; // Jump instruction
|
||||||
logic BranchSignedE;
|
logic BranchSignedE; // Branch does signed comparison on operands
|
||||||
logic MDUE;
|
logic MDUE; // Multiply/divide instruction
|
||||||
|
|
||||||
controller c(
|
controller c(
|
||||||
.clk, .reset, .StallD, .FlushD, .InstrD, .ImmSrcD,
|
.clk, .reset, .StallD, .FlushD, .InstrD, .ImmSrcD,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// regfile.sv
|
// regfile.sv
|
||||||
//
|
//
|
||||||
// Written: David_Harris@hmc.edu 9 January 2021
|
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
|
||||||
|
// Created: 9 January 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: 3-port register file
|
// Purpose: 3-port register file
|
||||||
@ -30,26 +31,26 @@
|
|||||||
|
|
||||||
module regfile (
|
module regfile (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic we3,
|
input logic we3, // Write enable
|
||||||
input logic [ 4:0] a1, a2, a3,
|
input logic [ 4:0] a1, a2, a3, // Source registers to read (a1, a2), destination register to write (a3)
|
||||||
input logic [`XLEN-1:0] wd3,
|
input logic [`XLEN-1:0] wd3, // Write data for port 3
|
||||||
output logic [`XLEN-1:0] rd1, rd2);
|
output logic [`XLEN-1:0] rd1, rd2); // Read data for ports 1, 2
|
||||||
|
|
||||||
localparam NUMREGS = `E_SUPPORTED ? 16 : 32; // only 16 registers in E mode
|
localparam NUMREGS = `E_SUPPORTED ? 16 : 32; // only 16 registers in E mode
|
||||||
|
|
||||||
(* mark_debug = "true" *) logic [`XLEN-1:0] rf[NUMREGS-1:1];
|
(* mark_debug = "true" *) logic [`XLEN-1:0] rf[NUMREGS-1:1];
|
||||||
integer i;
|
integer i;
|
||||||
|
|
||||||
// three ported register file
|
// Three ported register file
|
||||||
// read two ports combinationally (A1/RD1, A2/RD2)
|
// Read two ports combinationally (a1/rd1, a2/rd2)
|
||||||
// write third port on rising edge of clock (A3/WD3/WE3)
|
// Write third port on rising edge of clock (a3/wd3/we3)
|
||||||
// write occurs on falling edge of clock
|
// Write occurs on falling edge of clock
|
||||||
// register 0 hardwired to 0
|
// Register 0 hardwired to 0
|
||||||
|
|
||||||
// reset is intended for simulation only, not synthesis
|
// reset is intended for simulation only, not synthesis
|
||||||
// can logic be adjusted to not need resettable registers?
|
// can logic be adjusted to not need resettable registers?
|
||||||
|
|
||||||
always_ff @(negedge clk) // or posedge reset) // *** make this a preload in testbench rather than reset
|
always_ff @(negedge clk)
|
||||||
if (reset) for(i=1; i<NUMREGS; i++) rf[i] <= 0;
|
if (reset) for(i=1; i<NUMREGS; i++) rf[i] <= 0;
|
||||||
else if (we3) rf[a3] <= wd3;
|
else if (we3) rf[a3] <= wd3;
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// shifter.sv
|
// shifter.sv
|
||||||
//
|
//
|
||||||
// Written: David_Harris@hmc.edu 9 January 2021
|
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
|
||||||
|
// Created: 9 January 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: RISC-V 32/64 bit shifter
|
// Purpose: RISC-V 32/64 bit shifter
|
||||||
@ -29,19 +30,19 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module shifter (
|
module shifter (
|
||||||
input logic [`XLEN-1:0] A,
|
input logic [`XLEN-1:0] A, // Source
|
||||||
input logic [`LOG_XLEN-1:0] Amt,
|
input logic [`LOG_XLEN-1:0] Amt, // Shift amount
|
||||||
input logic Right, Arith, W64,
|
input logic Right, Arith, W64, // Shift right, arithmetic, RV64 W-type shift
|
||||||
output logic [`XLEN-1:0] Y);
|
output logic [`XLEN-1:0] Y); // Shifted result
|
||||||
|
|
||||||
logic [2*`XLEN-2:0] z, zshift;
|
logic [2*`XLEN-2:0] z, zshift; // Input to funnel shifter, shifted amount before truncated to 32 or 64 bits
|
||||||
logic [`LOG_XLEN-1:0] amttrunc, offset;
|
logic [`LOG_XLEN-1:0] amttrunc, offset; // Shift amount adjusted for RV64, right-shift amount
|
||||||
|
|
||||||
// Handle left and right shifts with a funnel shifter.
|
// Handle left and right shifts with a funnel shifter.
|
||||||
// For RV32, only 32-bit shifts are needed.
|
// For RV32, only 32-bit shifts are needed.
|
||||||
// For RV64, 32 and 64-bit shifts are needed, with sign extension.
|
// For RV64, 32- and 64-bit shifts are needed, with sign extension.
|
||||||
|
|
||||||
// funnel shifter input (see CMOS VLSI Design 4e Section 11.8.1, note Table 11.11 shift types wrong)
|
// Funnel shifter input (see CMOS VLSI Design 4e Section 11.8.1, note Table 11.11 shift types wrong)
|
||||||
if (`XLEN==32) begin:shifter // RV32
|
if (`XLEN==32) begin:shifter // RV32
|
||||||
always_comb // funnel mux
|
always_comb // funnel mux
|
||||||
if (Right)
|
if (Right)
|
||||||
@ -62,13 +63,13 @@ module shifter (
|
|||||||
else z = {63'b0, A};
|
else z = {63'b0, A};
|
||||||
else z = {A, 63'b0};
|
else z = {A, 63'b0};
|
||||||
end
|
end
|
||||||
assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32 or 64-bit shift
|
assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32- or 64-bit shift
|
||||||
end
|
end
|
||||||
|
|
||||||
// opposite offset for right shfits
|
// Opposite offset for right shifts
|
||||||
assign offset = Right ? amttrunc : ~amttrunc;
|
assign offset = Right ? amttrunc : ~amttrunc;
|
||||||
|
|
||||||
// funnel operation
|
// Funnel operation
|
||||||
assign zshift = z >> offset;
|
assign zshift = z >> offset;
|
||||||
assign Y = zshift[`XLEN-1:0];
|
assign Y = zshift[`XLEN-1:0];
|
||||||
endmodule
|
endmodule
|
||||||
|
Loading…
Reference in New Issue
Block a user