2021-01-15 04:37:51 +00:00
///////////////////////////////////////////
// shifter.sv
//
2023-02-25 01:33:47 +00:00
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu, Kevin Kim <kekim@hmc.edu>
2023-01-17 14:02:26 +00:00
// Created: 9 January 2021
2023-02-06 17:55:37 +00:00
// Modified: 6 February 2023
2021-01-15 04:37:51 +00:00
//
// Purpose: RISC-V 32/64 bit shifter
//
2023-01-12 12:35:44 +00:00
// Documentation: RISC-V System on Chip Design Chapter 4 (Figure 4.5, Table 4.3)
//
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
2023-03-02 19:45:32 +00:00
module shifter (
2023-03-24 15:27:30 +00:00
input logic [ `XLEN - 1 : 0 ] A , // shift Source
input logic [ `LOG_XLEN - 1 : 0 ] Amt , // Shift amount
input logic Right , Rotate , W64 , SubArith , // Shift right, rotate, W64-type operation, arithmetic shift
output logic [ `XLEN - 1 : 0 ] Y ) ; // Shifted result
2021-01-15 04:37:51 +00:00
2023-03-24 16:01:07 +00:00
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 ] TruncAmt , Offset ; // Shift amount adjusted for RV64, right-shift amount
2023-03-24 15:27:30 +00:00
logic Sign ; // Sign bit for sign extension
assign Sign = A [ `XLEN - 1 ] & SubArith ; // sign bit for sign extension
2023-03-24 18:52:51 +00:00
if ( `XLEN = = 32 ) begin // rv32
if ( `ZBB_SUPPORTED ) begin : rotfunnel32 //rv32 shifter with rotates
2023-02-06 17:55:37 +00:00
always_comb // funnel mux
2023-02-25 01:33:47 +00:00
case ( { Right , Rotate } )
2023-03-24 16:01:07 +00:00
2 'b00 : Z = { A [ 31 : 0 ] , 31 'b0 } ;
2 'b01 : Z = { A [ 31 : 0 ] , A [ 31 : 1 ] } ;
2 'b10 : Z = { { 31 { Sign } } , A [ 31 : 0 ] } ;
2023-03-24 22:47:26 +00:00
2 'b11 : Z = { A [ 30 : 0 ] , A [ 31 : 0 ] } ;
2023-02-25 01:33:47 +00:00
endcase
2023-03-24 18:52:51 +00:00
end else begin : norotfunnel32 //rv32 shifter without rotates
always_comb // funnel mux
2023-03-24 22:47:26 +00:00
if ( Right ) Z = { { 31 { Sign } } , A [ 31 : 0 ] } ;
else Z = { A [ 31 : 0 ] , 31 'b0 } ;
2023-03-24 18:52:51 +00:00
end
2023-03-24 22:47:26 +00:00
assign TruncAmt = Amt ; // shift amount
2023-03-24 18:52:51 +00:00
end else begin // rv64
logic [ `XLEN - 1 : 0 ] A64 ;
mux3 # ( 64 ) extendmux ( { { 32 { 1 'b0 } } , A [ 31 : 0 ] } , { { 32 { A [ 31 ] } } , A [ 31 : 0 ] } , A , { ~ W64 , SubArith } , A64 ) ; // bottom 32 bits are always A[31:0], so effectively a 32-bit upper mux
if ( `ZBB_SUPPORTED ) begin : rotfunnel64 // rv64 shifter with rotates
2023-03-24 13:49:26 +00:00
// shifter rotate source select mux
logic [ `XLEN - 1 : 0 ] RotA ; // rotate source
mux2 # ( `XLEN ) rotmux ( A , { A [ 31 : 0 ] , A [ 31 : 0 ] } , W64 , RotA ) ; // W64 rotatons
2023-02-06 17:55:37 +00:00
always_comb // funnel mux
2023-02-25 01:33:47 +00:00
case ( { Right , Rotate } )
2023-03-24 22:47:26 +00:00
2 'b00 : Z = { A64 [ 63 : 0 ] , { 63 'b0 } } ;
2 'b01 : Z = { RotA [ 63 : 0 ] , RotA [ 63 : 1 ] } ;
2 'b10 : Z = { { 63 { Sign } } , A64 [ 63 : 0 ] } ;
2 'b11 : Z = { RotA [ 62 : 0 ] , RotA [ 63 : 0 ] } ;
2023-02-25 01:33:47 +00:00
endcase
2023-03-24 18:52:51 +00:00
end else begin : norotfunnel64 // rv64 shifter without rotates
2023-02-06 17:55:37 +00:00
always_comb // funnel mux
2023-03-24 22:47:26 +00:00
if ( Right ) Z = { { 63 { Sign } } , A64 [ 63 : 0 ] } ;
else Z = { A64 [ 63 : 0 ] , { 63 'b0 } } ;
2023-02-06 17:55:37 +00:00
end
2023-03-24 22:47:26 +00:00
assign TruncAmt = W64 ? { 1 'b0 , Amt [ 4 : 0 ] } : Amt ; // 32- or 64-bit shift
2023-02-06 17:55:37 +00:00
end
2023-02-25 01:33:47 +00:00
2023-01-17 14:02:26 +00:00
// Opposite offset for right shifts
2023-03-24 16:01:07 +00:00
assign Offset = Right ? TruncAmt : ~ TruncAmt ;
2021-12-18 18:01:12 +00:00
2023-01-17 14:02:26 +00:00
// Funnel operation
2023-03-24 16:01:07 +00:00
assign ZShift = Z > > Offset ;
assign Y = ZShift [ `XLEN - 1 : 0 ] ;
2021-01-15 04:37:51 +00:00
endmodule