sv2v/test/relong/alu.v

73 lines
2.6 KiB
Verilog

`default_nettype none
module ALU(
input wire [2:0] operation,
input wire [31:0] left, right,
output reg [31:0] result
);
// 1. Unsigned should be a no-op so simply remove those function calls
// 2. Signed modifiers don't appear to be supported on VTR, so they might need to be expanded with logic for actually doing the signed operation.
// 3. Likewise, the triple shift (arithmetic shift) operator doesn't appear to be supported in VTR so it also might need to be expanded manually.
always @* begin
result = 32'b0;
case(operation)
3'd0: begin
// Right logical shift
// Only need the lowest 5 bits for 32 bit input
result = left >> right[4:0];
end
3'd1: begin
// Right arithmetic shift
result = $signed(left) >>> right[4:0];
end
3'd2: begin
// Signed Comparison
result = $signed(left) < $signed(right);
end
3'd3: begin
// Unsigned comparison
result = left < right;
end
endcase
end
// Extra stuff for example
reg [31:0] result2;
reg [31:0] __temp;
// sameResult: assert property (result == result2);
always @* begin
result2 = 32'b0;
__temp = 32'b0;
case(operation)
3'd0: begin
// Right logical shift
// Only need the lowest 5 bits for 32 bit input
result2 = left >> right[4:0];
end
3'd1: begin
// Right arithmetic shift
// 1. Take the MSB and replicate it to form a mask
// 2. Create a mask for the bits that the shift will set correctly and mask them off of the MSB replication (sets 32 - shift bits correctly)
// 3. Combine the shift part and the masked part
__temp = {32{left[31]}} & ~ ((33'd1 << (6'd32 - right[4:0])) - 33'd1);
result2 = __temp | (left >> right[4:0]);
end
3'd2: begin
// Signed Comparison
case({left[31], right[31]})
2'b00: result2 = left < right; // Both positive
2'b01: result2 = 32'd0; // + < - (always false)
2'b10: result2 = 32'd1; // - < + (always true)
2'b11: result2 = -left > -right; // Both negative
endcase
end
3'd3: begin
// Unsigned comparison
result2 = left < right;
end
endcase
end
endmodule