cvw/wally-pipelined/src/ebu/amoalu.sv

67 lines
2.8 KiB
Systemverilog
Raw Normal View History

///////////////////////////////////////////
// amoalu.sv
//
// Written: David_Harris@hmc.edu 10 March 2021
// Modified:
//
// Purpose: Performs AMO operations
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module amoalu (
input logic [`XLEN-1:0] a, b,
input logic [6:0] funct,
input logic [1:0] width,
output logic [`XLEN-1:0] result);
logic [`XLEN-1:0] y;
// *** see how synthesis generates this and optimize more structurally if necessary to share hardware
// a single carry chain should be shared for + and the four min/max
// and the same mux can be used to select b for swap.
always_comb
case (funct[6:2])
5'b00001: y = b; // amoswap
5'b00000: y = a + b; // amoadd
5'b00100: y = a ^ b; // amoxor
5'b01100: y = a & b; // amoand
5'b01000: y = a | b; // amoor
5'b10000: y = (a < b) ? a : b; // amomin
5'b10100: y = (a >= b) ? a : b; // amomax
5'b11000: y = ({1'b0, a} < {1'b0, b}) ? a : b; // amominu
5'b11100: y = ({1'b0, a} >= {1'b0, b}) ? a : b; // amomaxu
default: y = 'bx; // undefined; *** could change to b for efficiency
endcase
// sign extend if necessary
generate
if (`XLEN == 32) begin
assign result = y;
end else begin // `XLEN = 64
always_comb
if (width == 2'b10) // sign-extend word-length operations
result = {{32{y[31]}}, y[31:0]};
else result = y;
end
endgenerate
endmodule