2021-01-15 04:37:51 +00:00
///////////////////////////////////////////
// alu.sv
//
2023-03-04 05:52:34 +00:00
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu, kekim@hmc.edu
2023-01-11 23:20:41 +00:00
// Created: 9 January 2021
2023-03-04 05:52:34 +00:00
// Modified: 3 March 2023
2021-01-15 04:37:51 +00:00
//
// Purpose: RISC-V Arithmetic/Logic Unit
2023-01-12 00:52:46 +00:00
//
// Documentation: RISC-V System on Chip Design Chapter 4 (Figure 4.4)
2021-01-15 04:37:51 +00:00
//
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
module alu # ( parameter WIDTH = 32 ) (
2023-03-05 06:44:03 +00:00
input logic [ WIDTH - 1 : 0 ] A , B , // Operands
input logic [ 2 : 0 ] ALUControl , // With Funct3, indicates operation to perform
input logic [ 2 : 0 ] ALUSelect , // ALU mux select signal
2023-03-24 05:20:37 +00:00
input logic [ 1 : 0 ] BSelect , // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction
2023-03-05 06:44:03 +00:00
input logic [ 2 : 0 ] ZBBSelect , // ZBB mux select signal
input logic [ 2 : 0 ] Funct3 , // With ALUControl, indicates operation to perform NOTE: Change signal name to ALUSelect
input logic [ 1 : 0 ] CompFlags , // Comparator flags
input logic [ 2 : 0 ] BALUControl , // ALU Control signals for B instructions in Execute Stage
2023-03-06 14:19:01 +00:00
output logic [ WIDTH - 1 : 0 ] Result , // ALU result
2023-03-05 06:44:03 +00:00
output logic [ WIDTH - 1 : 0 ] Sum ) ; // Sum of operands
2021-01-15 04:37:51 +00:00
2023-02-12 05:22:33 +00:00
// CondInvB = ~B when subtracting, B otherwise. Shift = shift result. SLT/U = result of a slt/u instruction.
2023-01-17 14:02:26 +00:00
// FullResult = ALU result before adjusting for a RV64 w-suffix instruction.
2023-03-24 05:20:37 +00:00
logic [ WIDTH - 1 : 0 ] CondMaskInvB , Shift , FullResult , ALUResult ; // Intermediate Signals
2023-03-24 05:22:25 +00:00
logic [ WIDTH - 1 : 0 ] CondMaskB ; // Result of B mask select mux
logic [ WIDTH - 1 : 0 ] CondShiftA ; // Result of A shifted select mux
logic [ WIDTH - 1 : 0 ] CondExtA ; // Result of Zero Extend A select mux
logic Carry , Neg ; // Flags: carry out, negative
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
2023-03-07 18:57:06 +00:00
logic shSignA ;
2023-02-28 19:41:40 +00:00
2023-03-02 23:28:43 +00:00
// Extract control signals from ALUControl.
assign { W64 , SubArith , ALUOp } = ALUControl ;
2023-03-24 04:56:03 +00:00
// A, A sign bit muxes
2023-03-07 18:57:06 +00:00
if ( WIDTH = = 64 ) begin
mux3 # ( 1 ) signmux ( A [ 63 ] , A [ 31 ] , 1 'b0 , { ~ SubArith , W64 } , shSignA ) ;
2023-03-24 13:18:06 +00:00
mux3 # ( 64 ) extendmux ( { { 32 { 1 'b0 } } , A [ 31 : 0 ] } , { { 32 { A [ 31 ] } } , A [ 31 : 0 ] } , A , { ~ W64 , SubArith } , CondExtA ) ; // bottom 32 bits are always A[31:0], so effectively a 32-bit upper mux
2023-03-07 18:57:06 +00:00
end else begin
mux2 # ( 1 ) signmux ( 1 'b0 , A [ 31 ] , SubArith , shSignA ) ;
assign CondExtA = A ;
end
2023-02-25 01:09:56 +00:00
2023-01-17 14:02:26 +00:00
// Addition
2023-03-05 22:06:24 +00:00
assign CondMaskInvB = SubArith ? ~ CondMaskB : CondMaskB ;
2023-03-10 22:17:38 +00:00
assign { Carry , Sum } = CondShiftA + CondMaskInvB + { { ( WIDTH - 1 ) { 1 'b0 } } , SubArith } ;
2021-01-15 04:37:51 +00:00
2023-03-02 19:45:32 +00:00
// Shifts (configurable for rotation)
2023-03-24 13:49:26 +00:00
shifter sh ( . A ( CondExtA ) , . Sign ( shSignA ) , . Amt ( B [ `LOG_XLEN - 1 : 0 ] ) , . Right ( Funct3 [ 2 ] ) , . W64 , . Y ( Shift ) , . Rotate ( BALUControl [ 2 ] ) ) ;
2021-12-18 18:25:40 +00:00
2023-01-17 14:02:26 +00:00
// Condition code flags are based on subtraction output Sum = A-B.
2021-12-19 05:26:00 +00:00
// Overflow occurs when the numbers being subtracted have the opposite sign
2023-01-17 14:02:26 +00:00
// and the result has the opposite sign of A.
// LT is simplified from Overflow = Asign & Bsign & Asign & Neg; LT = Neg ^ Overflow
2021-12-14 19:15:47 +00:00
assign Neg = Sum [ WIDTH - 1 ] ;
2022-04-17 16:49:51 +00:00
assign Asign = A [ WIDTH - 1 ] ;
assign Bsign = B [ WIDTH - 1 ] ;
2023-01-17 14:02:26 +00:00
assign LT = Asign & ~ Bsign | Asign & Neg | ~ Bsign & Neg ;
2021-12-14 19:15:47 +00:00
assign LTU = ~ Carry ;
2021-12-08 20:33:53 +00:00
2021-12-14 19:15:47 +00:00
// Select appropriate ALU Result
2023-03-23 23:02:38 +00:00
always_comb begin
if ( ~ ALUOp ) FullResult = Sum ; // Always add for ALUOp = 0 (address generation)
else casez ( ALUSelect ) // Otherwise check Funct3 NOTE: change signal name to ALUSelect
3 'b000 : FullResult = Sum ; // add or sub
3 'b001 : FullResult = Shift ; // sll, sra, or srl
3 'b010 : FullResult = { { ( WIDTH - 1 ) { 1 'b0 } } , LT } ; // slt
3 'b011 : FullResult = { { ( WIDTH - 1 ) { 1 'b0 } } , LTU } ; // sltu
3 'b100 : FullResult = A ^ CondMaskInvB ; // xor, xnor, binv
3 'b101 : FullResult = ( `ZBS_SUPPORTED | `ZBB_SUPPORTED ) ? { { ( WIDTH - 1 ) { 1 'b0 } } , { | ( A & CondMaskB ) } } : Shift ; // bext
3 'b110 : FullResult = A | CondMaskInvB ; // or, orn, bset
3 'b111 : FullResult = A & CondMaskInvB ; // and, bclr
endcase
2023-02-17 17:51:49 +00:00
end
2023-02-15 17:13:10 +00:00
2023-03-06 14:20:25 +00:00
// 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 ALUResult = W64 ? { { 32 { FullResult [ 31 ] } } , FullResult [ 31 : 0 ] } : FullResult ;
else assign ALUResult = FullResult ;
2023-02-18 04:15:12 +00:00
// Final Result B instruction select mux
2023-03-24 03:42:49 +00:00
if ( `ZBC_SUPPORTED | `ZBS_SUPPORTED | `ZBA_SUPPORTED | `ZBB_SUPPORTED ) begin : bitmanipalu
2023-03-24 13:49:26 +00:00
bitmanipalu # ( WIDTH ) balu ( . A , . B , . ALUControl , . BSelect , . ZBBSelect ,
2023-03-24 05:28:21 +00:00
. Funct3 , . CompFlags , . BALUControl , . CondExtA , . ALUResult , . FullResult ,
2023-03-24 13:49:26 +00:00
. CondMaskB , . CondShiftA , . Result ) ;
2023-03-24 03:42:49 +00:00
end else begin
assign Result = ALUResult ;
assign CondMaskB = B ;
assign CondShiftA = A ;
end
2023-02-12 05:22:33 +00:00
endmodule