|
| 1 | + |
| 2 | +module alu( |
| 3 | + input [2:0] func3, |
| 4 | + input [6:0] func7, |
| 5 | + input [63:0] a, b, |
| 6 | + output reg [63:0] out); |
| 7 | + |
| 8 | + // https://riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf |
| 9 | + // Page 104 |
| 10 | + wire ADD = func7 == 'b0000000 & func3 == 'b000; |
| 11 | + wire SUB = func7 == 'b0100000 & func3 == 'b000; |
| 12 | + wire SLL = func7 == 'b0000000 & func3 == 'b001; |
| 13 | + wire SLT = func7 == 'b0000000 & func3 == 'b010; |
| 14 | + wire SLTU = func7 == 'b0000000 & func3 == 'b011; |
| 15 | + wire XOR = func7 == 'b0000000 & func3 == 'b100; |
| 16 | + wire SRL = func7 == 'b0000000 & func3 == 'b101; |
| 17 | + wire SRA = func7 == 'b0100000 & func3 == 'b101; |
| 18 | + wire OR = func7 == 'b0000000 & func3 == 'b110; |
| 19 | + wire AND = func7 == 'b0000000 & func3 == 'b111; |
| 20 | + |
| 21 | + wire subtraction = SUB || SLT || SLTU; |
| 22 | + wire [64:0] a_ext = {SLT ? a[63] : 0, a}; |
| 23 | + wire [64:0] b_ext = {SLT ? b[63] : 0, b}; |
| 24 | + wire [64:0] b_inv = (subtraction?~b_ext:b_ext); |
| 25 | + wire [64:0] adder_out = a_ext + b_inv + subtraction; |
| 26 | + |
| 27 | + always_comb case(1) |
| 28 | + ADD || SUB: out <= adder_out[63:0]; |
| 29 | + SLL: out <= a << b[4:0]; |
| 30 | + SLT || SLTU: out <= adder_out[64]; |
| 31 | + XOR: out <= a ^ b; |
| 32 | + SRL: out <= a >> b[4:0]; |
| 33 | + SRA: out <= $signed(a) >>> b[4:0]; |
| 34 | + OR: out <= a | b; |
| 35 | + AND: out <= a & b; |
| 36 | + default: out <= 0; |
| 37 | + endcase |
| 38 | + |
| 39 | + wire [9:0] op = {func7, func3}; |
| 40 | + pADD: assert final (op == {7'b0000000, 3'b000} -> out == a + b); |
| 41 | + pSUB: assert final (op == {7'b0100000, 3'b000} -> out == a - b); |
| 42 | + pSLL: assert final (op == {7'b0000000, 3'b001} -> out == a << b[4:0]); |
| 43 | + pSLT: assert final (op == {7'b0000000, 3'b010} -> out == ($signed(a) < $signed(b))); |
| 44 | + pSLTU: assert final (op == {7'b0000000, 3'b011} -> out == (a < b)); |
| 45 | + pXOR: assert final (op == {7'b0000000, 3'b100} -> out == (a ^ b)); |
| 46 | + pSRL: assert final (op == {7'b0000000, 3'b101} -> out == a >> b[4:0]); |
| 47 | + pSRA: assert final (op == {7'b0100000, 3'b101} -> out == $signed(a) >>> b[4:0]); |
| 48 | + pOR: assert final (op == {7'b0000000, 3'b110} -> out == (a | b)); |
| 49 | + pAND: assert final (op == {7'b0000000, 3'b111} -> out == (a & b)); |
| 50 | + |
| 51 | +endmodule |
0 commit comments