cvw/pipelined/src/ieu/controller.sv

250 lines
12 KiB
Systemverilog
Raw Normal View History

2021-01-15 04:37:51 +00:00
///////////////////////////////////////////
// controller.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Top level controller module
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
2021-01-15 04:37:51 +00:00
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
2021-01-15 04:37:51 +00:00
//
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
// may obtain a copy of the License at
2021-01-15 04:37:51 +00:00
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work distributed under the
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
////////////////////////////////////////////////////////////////////////////////////////////////
2021-01-15 04:37:51 +00:00
`include "wally-config.vh"
2021-01-15 04:37:51 +00:00
module controller(
input logic clk, reset,
// Decode stage control signals
input logic StallD, FlushD,
input logic [31:0] InstrD,
2021-01-15 04:37:51 +00:00
output logic [2:0] ImmSrcD,
2021-02-16 03:27:35 +00:00
input logic IllegalIEUInstrFaultD,
output logic IllegalBaseInstrFaultD,
2021-01-15 04:37:51 +00:00
// Execute stage control signals
2021-10-23 17:51:53 +00:00
input logic StallE, FlushE,
2022-06-21 20:30:33 +00:00
input logic [1:0] FlagsE,
input logic FWriteIntE,
2021-01-15 04:37:51 +00:00
output logic PCSrcE, // for datapath and Hazard Unit
2021-12-08 20:33:53 +00:00
output logic [2:0] ALUControlE,
2021-01-15 04:37:51 +00:00
output logic ALUSrcAE, ALUSrcBE,
2021-12-08 20:33:53 +00:00
output logic ALUResultSrcE,
output logic MemReadE, CSRReadE, // for Hazard Unit
2021-02-16 03:27:35 +00:00
output logic [2:0] Funct3E,
output logic MDUE, W64E,
2021-06-24 22:39:18 +00:00
output logic JumpE,
2022-03-04 00:07:31 +00:00
output logic SCE,
2022-06-21 20:30:33 +00:00
output logic BranchSignedE,
2021-01-15 04:37:51 +00:00
// Memory stage control signals
2021-02-08 04:21:55 +00:00
input logic StallM, FlushM,
2021-01-15 04:37:51 +00:00
output logic [1:0] MemRWM,
output logic CSRReadM, CSRWriteM, PrivilegedM,
output logic [1:0] AtomicM,
2021-01-15 04:37:51 +00:00
output logic [2:0] Funct3M,
output logic RegWriteM, // for Hazard Unit
output logic InvalidateICacheM, FlushDCacheM,
2021-10-23 17:51:53 +00:00
output logic InstrValidM,
output logic FWriteIntM,
2021-01-15 04:37:51 +00:00
// Writeback stage control signals
2021-02-08 04:21:55 +00:00
input logic StallW, FlushW,
output logic RegWriteW, DivW, // for datapath and Hazard Unit
2021-02-16 03:27:35 +00:00
output logic [2:0] ResultSrcW,
2021-01-15 04:37:51 +00:00
// Stall during CSRs
//output logic CSRWriteFencePendingDEM,
output logic CSRWriteFenceM,
output logic StoreStallD
);
2021-01-15 04:37:51 +00:00
logic [6:0] OpD;
logic [2:0] Funct3D;
logic [6:0] Funct7D;
logic [4:0] Rs1D;
2021-12-08 20:33:53 +00:00
`define CTRLW 23
2021-01-15 04:37:51 +00:00
// pipelined control signals
2021-10-23 17:51:53 +00:00
logic RegWriteD, RegWriteE;
logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM;
2021-10-23 17:51:53 +00:00
logic [1:0] MemRWD, MemRWE;
logic JumpD;
2021-01-15 04:37:51 +00:00
logic BranchD, BranchE;
2021-12-08 20:33:53 +00:00
logic ALUOpD;
logic [2:0] ALUControlD;
2021-01-15 04:37:51 +00:00
logic ALUSrcAD, ALUSrcBD;
logic ALUResultSrcD, W64D, MDUD;
logic CSRZeroSrcD;
logic CSRReadD;
logic [1:0] AtomicD;
logic FenceXD;
logic InvalidateICacheD, FlushDCacheD;
2021-01-15 04:37:51 +00:00
logic CSRWriteD, CSRWriteE;
logic InstrValidD, InstrValidE;
2021-01-15 04:37:51 +00:00
logic PrivilegedD, PrivilegedE;
logic InvalidateICacheE, FlushDCacheE;
logic [`CTRLW-1:0] ControlsD;
2021-12-08 20:33:53 +00:00
logic SubArithD;
2021-01-15 04:37:51 +00:00
logic subD, sraD, sltD, sltuD;
logic BranchTakenE;
2023-01-07 13:46:22 +00:00
logic eqE, ltE;
2021-02-17 20:29:20 +00:00
logic unused;
2021-12-08 20:33:53 +00:00
logic BranchFlagE;
logic IEURegWriteE;
logic IllegalERegAdrD;
2022-05-12 15:39:44 +00:00
logic [1:0] AtomicE;
logic FenceD, FenceE, FenceM;
logic SFenceVmaD;
logic DivE, DivM;
2021-12-08 20:33:53 +00:00
// Extract fields
assign OpD = InstrD[6:0];
assign Funct3D = InstrD[14:12];
assign Funct7D = InstrD[31:25];
assign Rs1D = InstrD[19:15];
2021-01-15 04:37:51 +00:00
// Main Instruction Decoder
2022-01-05 14:35:25 +00:00
always_comb
case(OpD)
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MDU_Atomic_Illegal
2022-01-05 14:35:25 +00:00
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'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)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence
else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0; // fence treated as nop
2022-01-05 14:35:25 +00:00
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'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
else
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'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
2022-01-05 14:35:25 +00:00
7'b0101111: if (`A_SUPPORTED) begin
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
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
else
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0;; // amo
end else
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)
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)
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/Divide
else
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'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
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
else
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'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'b1110011: if (`ZICSR_SUPPORTED) begin
if (Funct3D == 3'b000)
2022-01-05 14:35:25 +00:00
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
2022-01-05 14:35:25 +00:00
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs
end else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
2022-01-05 14:35:25 +00:00
default: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
endcase
2021-01-15 04:37:51 +00:00
// unswizzle control bits
// 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.
assign IllegalERegAdrD = `E_SUPPORTED & `ZICSR_SUPPORTED & ControlsD[`CTRLW-1] & InstrD[11];
assign IllegalBaseInstrFaultD = ControlsD[0] | IllegalERegAdrD;
2021-01-15 04:37:51 +00:00
assign {RegWriteD, ImmSrcD, ALUSrcAD, ALUSrcBD, MemRWD,
2021-12-08 20:33:53 +00:00
ResultSrcD, BranchD, ALUOpD, JumpD, ALUResultSrcD, W64D, CSRReadD,
PrivilegedD, FenceXD, MDUD, AtomicD, unused} = IllegalIEUInstrFaultD ? `CTRLW'b0 : ControlsD;
2021-01-15 04:37:51 +00:00
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 SFenceVmaD = PrivilegedD & (InstrD[31:25] == 7'b0001001);
assign FenceD = SFenceVmaD | FenceXD; // possible sfence.vma or fence.i
2021-12-19 21:53:45 +00:00
// ALU Decoding is lazy, only using func7[5] to distinguish add/sub and srl/sra
2021-01-15 04:37:51 +00:00
assign sltD = (Funct3D == 3'b010);
assign sltuD = (Funct3D == 3'b011);
2021-12-19 21:53:45 +00:00
assign subD = (Funct3D == 3'b000 & Funct7D[5] & OpD[5]); // OpD[5] needed to distinguish sub from addi
2021-02-16 03:27:35 +00:00
assign sraD = (Funct3D == 3'b101 & Funct7D[5]);
2021-12-08 21:48:04 +00:00
assign SubArithD = ALUOpD & (subD | sraD | sltD | sltuD); // TRUE for R-type subtracts and sra, slt, sltu
2021-12-08 20:33:53 +00:00
assign ALUControlD = {W64D, SubArithD, ALUOpD};
// Fences
// Ordinary fence is presently a nop
// FENCE.I flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented
if (`ZIFENCEI_SUPPORTED & `ICACHE) begin:fencei
2022-01-05 14:35:25 +00:00
logic FenceID;
assign FenceID = FenceXD & (Funct3D == 3'b001); // is it a FENCE.I instruction?
2022-01-05 14:35:25 +00:00
assign InvalidateICacheD = FenceID;
assign FlushDCacheD = FenceID;
end else begin:fencei
assign InvalidateICacheD = 0;
assign FlushDCacheD = 0;
end
// Decocde stage pipeline control register
flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD);
2021-01-15 04:37:51 +00:00
// Execute stage pipeline control register and logic
flopenrc #(28) controlregE(clk, reset, FlushE, ~StallE,
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, InstrValidD},
{IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE});
2021-01-15 04:37:51 +00:00
// Branch Logic
// The comparator handles both signed and unsigned branches using BranchSignedE
// Hence, only eq and lt flags are needed
2022-06-21 20:30:33 +00:00
assign BranchSignedE = ~(Funct3E[2:1] == 2'b11);
assign {eqE, ltE} = FlagsE;
mux2 #(1) branchflagmux(eqE, ltE, Funct3E[2], BranchFlagE);
2021-12-08 20:33:53 +00:00
assign BranchTakenE = BranchFlagE ^ Funct3E[0];
2021-01-15 04:37:51 +00:00
assign PCSrcE = JumpE | BranchE & BranchTakenE;
2021-12-19 21:53:45 +00:00
// Other execute stage controller signals
assign MemReadE = MemRWE[1];
assign SCE = (ResultSrcE == 3'b100);
assign RegWriteE = IEURegWriteE | FWriteIntE; // IRF register writes could come from IEU or FPU controllers
assign DivE = MDUE & Funct3E[2]; // Division operation
2021-01-15 04:37:51 +00:00
// Memory stage pipeline control register
flopenrc #(20) controlregM(clk, reset, FlushM, ~StallM,
{RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE, DivE},
{RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, DivM});
2021-01-15 04:37:51 +00:00
// Writeback stage pipeline control register
flopenrc #(5) controlregW(clk, reset, FlushW, ~StallW,
{RegWriteM, ResultSrcM, DivM},
{RegWriteW, ResultSrcW, DivW});
2021-01-15 04:37:51 +00:00
// Flush F, D, and E stages on a CSR write or Fence.I or SFence.VMA
assign CSRWriteFenceM = CSRWriteM | FenceM;
// assign CSRWriteFencePendingDEM = CSRWriteD | CSRWriteE | CSRWriteM | FenceD | FenceE | FenceM;
// the synchronous DTIM cannot read immediately after write
// a cache cannot read or write immediately after a write
assign StoreStallD = MemRWE[0] & ((MemRWD[1] | (MemRWD[0] & `DCACHE)) | (|AtomicD));
2021-01-15 04:37:51 +00:00
endmodule