2021-01-15 04:37:51 +00:00
///////////////////////////////////////////
// datapath.sv
//
2023-01-17 14:02:26 +00:00
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
// Created: 9 January 2021
2021-01-15 04:37:51 +00:00
// Modified:
//
2021-01-28 20:18:23 +00:00
// Purpose: Wally Integer Datapath
2021-01-15 04:37:51 +00:00
//
2023-01-12 12:35:44 +00:00
// Documentation: RISC-V System on Chip Design Chapter 4 (Figure 4.12)
//
2023-01-11 23:15:08 +00:00
// A component of the CORE-V-WALLY configurable RISC-V project.
2021-01-15 04:37:51 +00:00
//
2023-01-10 19:35:20 +00:00
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
2021-01-15 04:37:51 +00:00
//
2023-01-10 19:35:20 +00:00
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
2021-01-15 04:37:51 +00:00
//
2023-01-10 19:35:20 +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
//
2023-01-10 19:35:20 +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.
2022-01-07 12:58:40 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////
2021-01-15 04:37:51 +00:00
2021-01-23 15:48:12 +00:00
`include " wally-config.vh "
2021-01-15 04:37:51 +00:00
2021-01-25 20:57:36 +00:00
module datapath (
2023-01-17 14:02:26 +00:00
input logic clk , reset ,
2021-01-15 04:37:51 +00:00
// Decode stage signals
2023-01-17 14:02:26 +00:00
input logic [ 2 : 0 ] ImmSrcD , // Selects type of immediate extension
input logic [ 31 : 0 ] InstrD , // Instruction in Decode stage
input logic [ 2 : 0 ] Funct3E , // Funct3 field of instruction in Execute stage
2021-01-15 04:37:51 +00:00
// Execute stage signals
2023-01-17 14:02:26 +00:00
input logic StallE , FlushE , // Stall, flush Execute stage
input logic [ 1 : 0 ] ForwardAE , ForwardBE , // Forward ALU operands from later stages
input logic [ 2 : 0 ] ALUControlE , // Indicate operation ALU performs
input logic ALUSrcAE , ALUSrcBE , // ALU operands
input logic ALUResultSrcE , // Selects result to pass on to Memory stage
input logic JumpE , // Is a jump (j) instruction
input logic BranchSignedE , // Branch comparison operands are signed (if it's a branch)
input logic [ `XLEN - 1 : 0 ] PCE , // PC in Execute stage
input logic [ `XLEN - 1 : 0 ] PCLinkE , // PC + 4 (of instruction in Execute stage)
output logic [ 1 : 0 ] FlagsE , // Comparison flags ({eq, lt})
output logic [ `XLEN - 1 : 0 ] IEUAdrE , // Address computed by ALU
output logic [ `XLEN - 1 : 0 ] ForwardedSrcAE , ForwardedSrcBE , // ALU sources before the mux chooses between them and PCE to put in srcA/B
2021-01-15 04:37:51 +00:00
// Memory stage signals
2023-01-17 14:02:26 +00:00
input logic StallM , FlushM , // Stall, flush Memory stage
2023-01-17 14:47:02 +00:00
input logic FWriteIntM , FCvtIntW , // FPU writes integer register file, FPU converts float to int
input logic [ `XLEN - 1 : 0 ] FIntResM , // FPU integer result
output logic [ `XLEN - 1 : 0 ] SrcAM , // ALU's Source A in Memory stage to privilege unit for CSR writes
2023-01-17 14:02:26 +00:00
output logic [ `XLEN - 1 : 0 ] WriteDataM , // Write data in Memory stage
2021-01-15 04:37:51 +00:00
// Writeback stage signals
2023-01-17 14:02:26 +00:00
input logic StallW , FlushW , // Stall, flush Writeback stage
( * mark_debug = " true " * ) input logic RegWriteW , IntDivW , // Write register file, integer divide instruction
2023-01-17 14:47:02 +00:00
input logic SquashSCW , // Squash a store conditional when a conflict arose
2023-01-17 14:02:26 +00:00
input logic [ 2 : 0 ] ResultSrcW , // Select source of result to write back to register file
2023-01-17 14:47:02 +00:00
input logic [ `XLEN - 1 : 0 ] FCvtIntResW , // FPU convert fp to integer result
2023-01-17 14:02:26 +00:00
input logic [ `XLEN - 1 : 0 ] ReadDataW , // Read data from LSU
2023-01-17 14:47:02 +00:00
input logic [ `XLEN - 1 : 0 ] CSRReadValW , MDUResultW , // CSR read result, MDU (Multiply/divide unit) result
input logic [ `XLEN - 1 : 0 ] FIntDivResultW , // FPU's integer divide result
2022-12-15 01:03:13 +00:00
// Hazard Unit signals
2023-01-17 14:02:26 +00:00
output logic [ 4 : 0 ] Rs1D , Rs2D , Rs1E , Rs2E , // Register sources to read in Decode or Execute stage
output logic [ 4 : 0 ] RdE , RdM , RdW // Register destinations in Execute, Memory, or Writeback stage
2021-01-28 20:18:23 +00:00
) ;
2021-01-15 04:37:51 +00:00
// Fetch stage signals
// Decode stage signals
2023-01-17 14:02:26 +00:00
logic [ `XLEN - 1 : 0 ] R1D , R2D ; // Read data from Rs1 (RD1), Rs2 (RD2)
2023-01-17 18:51:44 +00:00
logic [ `XLEN - 1 : 0 ] ImmExtD ; // Extended immediate in Decode stage
2023-01-17 14:02:26 +00:00
logic [ 4 : 0 ] RdD ; // Destination register in Decode stage
2021-01-15 04:37:51 +00:00
// Execute stage signals
2023-01-17 14:02:26 +00:00
logic [ `XLEN - 1 : 0 ] R1E , R2E ; // Source operands read from register file
2023-01-17 18:51:44 +00:00
logic [ `XLEN - 1 : 0 ] ImmExtE ; // Extended immediate in Execute stage
2023-01-17 14:02:26 +00:00
logic [ `XLEN - 1 : 0 ] SrcAE , SrcBE ; // ALU operands
2023-01-17 14:33:58 +00:00
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
2021-01-15 04:37:51 +00:00
// Memory stage signals
2023-01-17 14:02:26 +00:00
logic [ `XLEN - 1 : 0 ] IEUResultM ; // Address computed by ALU *** According to Figure 4.12, IEUResultM should be called IEUAdrM
2023-01-17 14:47:02 +00:00
logic [ `XLEN - 1 : 0 ] IFResultM ; // Result from either IEU or single-cycle FPU op writing an integer register
2021-01-15 04:37:51 +00:00
// Writeback stage signals
2023-01-17 14:02:26 +00:00
logic [ `XLEN - 1 : 0 ] SCResultW ; // Store Conditional result
logic [ `XLEN - 1 : 0 ] ResultW ; // Result to write to register file
2023-01-17 14:47:02 +00:00
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)
2022-08-23 18:16:36 +00:00
2021-02-03 00:44:37 +00:00
// Decode stage
2021-01-28 03:49:47 +00:00
assign Rs1D = InstrD [ 19 : 15 ] ;
assign Rs2D = InstrD [ 24 : 20 ] ;
assign RdD = InstrD [ 11 : 7 ] ;
2022-02-28 20:50:51 +00:00
regfile regf ( clk , reset , RegWriteW , Rs1D , Rs2D , RdW , ResultW , R1D , R2D ) ;
2023-01-17 14:33:58 +00:00
extend ext ( . InstrD ( InstrD [ 31 : 7 ] ) , . ImmSrcD , . ImmExtD ) ;
2021-01-15 04:37:51 +00:00
// Execute stage pipeline register and logic
2021-12-19 05:26:00 +00:00
flopenrc # ( `XLEN ) RD1EReg ( clk , reset , FlushE , ~ StallE , R1D , R1E ) ;
flopenrc # ( `XLEN ) RD2EReg ( clk , reset , FlushE , ~ StallE , R2D , R2E ) ;
2023-01-17 14:33:58 +00:00
flopenrc # ( `XLEN ) ImmExtEReg ( clk , reset , FlushE , ~ StallE , ImmExtD , ImmExtE ) ;
2021-12-14 19:15:47 +00:00
flopenrc # ( 5 ) Rs1EReg ( clk , reset , FlushE , ~ StallE , Rs1D , Rs1E ) ;
flopenrc # ( 5 ) Rs2EReg ( clk , reset , FlushE , ~ StallE , Rs2D , Rs2E ) ;
flopenrc # ( 5 ) RdEReg ( clk , reset , FlushE , ~ StallE , RdD , RdE ) ;
2021-01-15 04:37:51 +00:00
2022-02-28 20:50:51 +00:00
mux3 # ( `XLEN ) faemux ( R1E , ResultW , IFResultM , ForwardAE , ForwardedSrcAE ) ;
mux3 # ( `XLEN ) fbemux ( R2E , ResultW , IFResultM , ForwardBE , ForwardedSrcBE ) ;
2022-06-21 20:30:33 +00:00
comparator_dc_flip # ( `XLEN ) comp ( ForwardedSrcAE , ForwardedSrcBE , BranchSignedE , FlagsE ) ;
2021-11-17 18:53:17 +00:00
mux2 # ( `XLEN ) srcamux ( ForwardedSrcAE , PCE , ALUSrcAE , SrcAE ) ;
2023-01-17 14:33:58 +00:00
mux2 # ( `XLEN ) srcbmux ( ForwardedSrcBE , ImmExtE , ALUSrcBE , SrcBE ) ;
2021-12-15 20:10:45 +00:00
alu # ( `XLEN ) alu ( SrcAE , SrcBE , ALUControlE , Funct3E , ALUResultE , IEUAdrE ) ;
2023-01-17 14:33:58 +00:00
mux2 # ( `XLEN ) altresultmux ( ImmExtE , PCLinkE , JumpE , AltResultE ) ;
2021-12-15 19:38:26 +00:00
mux2 # ( `XLEN ) ieuresultmux ( ALUResultE , AltResultE , ALUResultSrcE , IEUResultE ) ;
2021-01-15 04:37:51 +00:00
// Memory stage pipeline register
2021-02-08 04:21:55 +00:00
flopenrc # ( `XLEN ) SrcAMReg ( clk , reset , FlushM , ~ StallM , SrcAE , SrcAM ) ;
2021-12-15 19:38:26 +00:00
flopenrc # ( `XLEN ) IEUResultMReg ( clk , reset , FlushM , ~ StallM , IEUResultE , IEUResultM ) ;
2021-12-14 19:15:47 +00:00
flopenrc # ( 5 ) RdMReg ( clk , reset , FlushM , ~ StallM , RdE , RdM ) ;
2022-08-22 20:43:04 +00:00
flopenrc # ( `XLEN ) WriteDataMReg ( clk , reset , FlushM , ~ StallM , ForwardedSrcBE , WriteDataM ) ;
2021-01-15 04:37:51 +00:00
// Writeback stage pipeline register and logic
2022-02-28 20:50:51 +00:00
flopenrc # ( `XLEN ) IFResultWReg ( clk , reset , FlushW , ~ StallW , IFResultM , IFResultW ) ;
2021-12-14 19:15:47 +00:00
flopenrc # ( 5 ) RdWReg ( clk , reset , FlushW , ~ StallW , RdM , RdW ) ;
2021-12-18 13:36:32 +00:00
2022-08-23 18:16:36 +00:00
// floating point inputs: FIntResM comes from fclass, fcmp, fmv; FCvtIntResW comes from fcvt
2022-08-22 20:28:51 +00:00
if ( `F_SUPPORTED ) begin : fpmux
2022-06-28 21:33:31 +00:00
mux2 # ( `XLEN ) resultmuxM ( IEUResultM , FIntResM , FWriteIntM , IFResultM ) ;
2022-08-23 19:17:19 +00:00
mux2 # ( `XLEN ) cvtresultmuxW ( IFResultW , FCvtIntResW , FCvtIntW , IFCvtResultW ) ;
2022-12-15 14:37:55 +00:00
if ( `IDIV_ON_FPU ) begin
2023-01-11 19:46:36 +00:00
mux2 # ( `XLEN ) divresultmuxW ( MDUResultW , FIntDivResultW , IntDivW , MulDivResultW ) ;
2022-12-15 14:37:55 +00:00
end else begin
assign MulDivResultW = MDUResultW ;
end
2022-01-05 14:35:25 +00:00
end else begin : fpmux
2022-08-23 18:16:36 +00:00
assign IFResultM = IEUResultM ; assign IFCvtResultW = IFResultW ;
2022-12-15 01:03:13 +00:00
assign MulDivResultW = MDUResultW ;
2022-01-05 14:35:25 +00:00
end
2022-12-15 01:03:13 +00:00
mux5 # ( `XLEN ) resultmuxW ( IFCvtResultW , ReadDataW , CSRReadValW , MulDivResultW , SCResultW , ResultSrcW , ResultW ) ;
2022-08-22 20:28:51 +00:00
2021-03-01 05:09:45 +00:00
// handle Store Conditional result if atomic extension supported
2022-01-05 14:35:25 +00:00
if ( `A_SUPPORTED ) assign SCResultW = { { ( `XLEN - 1 ) { 1 'b0 } } , SquashSCW } ;
else assign SCResultW = 0 ;
2021-01-15 04:37:51 +00:00
endmodule