Skip to content

Instantly share code, notes, and snippets.

@neilzheng
Created August 30, 2025 02:53
Show Gist options
  • Save neilzheng/6c6d138c584fa762f34a3ce5e6bbcfbb to your computer and use it in GitHub Desktop.
Save neilzheng/6c6d138c584fa762f34a3ce5e6bbcfbb to your computer and use it in GitHub Desktop.
// Description: Implements various bitwise shift and rotate operations
// (logical, arithmetic, rotate).
module shift_unit
import cpu_defines::*;
(
// Inputs
input logic [XLEN-1:0] shift_in_data, // Data to be shifted/rotated
input logic [SHIFT_WIDTH-1:0] shift_amount, // Number of bit positions to shift/rotate
input shift_ops_t shift_op, // Type of shift/rotate operation
// Outputs
output logic [XLEN-1:0] shift_out_data, // Result of the operation
output logic carry_out_flag, // Last bit shifted out or wrapped around
output logic zero_flag, // 1 if alu_result is all zeros
output logic negative_flag // 1 if MSB of alu_result is 1 (signed negative)
);
// Combinational logic block: outputs update immediately with input changes.
always_comb begin
// Default outputs (when disabled or for unhandled cases)
shift_out_data = '0;
carry_out_flag = '0;
// Handle zero shift amount as a special case
if (shift_amount == 0) begin
shift_out_data = shift_in_data; // Data remains unchanged
end else begin
// Handle shift amounts greater than zero
case (shift_op)
SLL_OP: begin
// Shift Left Logical: Zeros fill from LSB
// 4 bit number should never greater than or equal to 16
shift_out_data = shift_in_data << shift_amount;
carry_out_flag = shift_in_data[SHIFT_WIDTH'(XLEN) - shift_amount]; // Last bit shifted out
end
SRL_OP: begin
// Shift Right Logical: Zeros fill from MSB
shift_out_data = shift_in_data >> shift_amount;
carry_out_flag = shift_in_data[shift_amount - SHIFT_WIDTH'(1)]; // Last bit shifted out
end
SRA_OP: begin
// Shift Right Arithmetic: Sign bit fills from MSB
shift_out_data = $signed(shift_in_data) >>> shift_amount;
carry_out_flag = shift_in_data[shift_amount - 1]; // Last bit shifted out
end
ROR_OP: begin
// Rotate Right: Bits wrap around from LSB to MSB
shift_out_data = (shift_in_data >> shift_amount) |
(shift_in_data << (SHIFT_WIDTH'(XLEN) - shift_amount));
carry_out_flag = shift_in_data[shift_amount - 1]; // Bit that wrapped
end
default: ;
endcase
end
zero_flag = (shift_out_data == '0);
negative_flag = shift_out_data[XLEN-1];
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment