summaryrefslogtreecommitdiff
path: root/verilog/alu.v
blob: 5a4e6c01acec69e39c735485cefba2b91cd289ba (plain) (blame)
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
`default_nettype none
`timescale 1us/1ns

`define ADDSUB          3'b000
`define XOR             3'b100
`define OR              3'b110
`define AND             3'b111
`define SLL             3'b001
`define SR              3'b101
`define SLT             3'b010
`define SLTU            3'b011

module alu
(
input wire [31:0] A,
input wire[31:0] B,
input wire[4:0] OP,
output reg[31:0] C,
output wire Branch
);

wire [31:0] sum = A + ({32{(OP[3] | OP[1])}} ^ B) + {31'b0, (OP[3] | OP[1])};
wire [31:0] right = (A >> B[4:0] | (OP[3] == 0 ? 32'b0 :
	(32'hFFFFFFFF << {~B[4] , ~B[3], ~B[2], ~B[1], ~B[0]})));

assign Branch = |C;

always @ (*) begin
	case(OP[2:0])
		`ADDSUB:  C = sum;
		`XOR:     C = A ^ B;
		`OR:      C = A | B;
		`AND:     C = A & B;
		`SLL:     C = |B[31:5] ? 32'b0 : A << B[4:0];
		`SR:      C = right;
		`SLT:     C = {31'b0, sum[31]};
                `SLTU:    C = {31'b0, A < B};
		default:  C = 32'b0;
	endcase
	if (OP[4]) begin
		C = B;
	end
end

endmodule