alu.v 2.62 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
`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