-
Notifications
You must be signed in to change notification settings - Fork 0
/
alu.v
105 lines (89 loc) · 3.3 KB
/
alu.v
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
module alu(
input [11:0] alu_op ,
input [31:0] alu_src1 ,
input [31:0] alu_src2 ,
output [31:0] alu_result,
output overflow
);
wire op_add; // 加法操作
wire op_sub; // 减法操作
wire op_slt; // 有符号比较,小于置位
wire op_sltu; // 无符号比较,小于置位
wire op_and; // 按位与
wire op_nor; // 按位或非
wire op_or; // 按位或
wire op_xor; // 按位异或
wire op_sll; // 逻辑左移
wire op_srl; // 逻辑右移
wire op_sra; // 算术右移
wire op_lui; // 立即数置于高半部分
// control code decomposition
assign op_add = alu_op[ 0];
assign op_sub = alu_op[ 1];
assign op_slt = alu_op[ 2];
assign op_sltu = alu_op[ 3];
assign op_and = alu_op[ 4];
assign op_nor = alu_op[ 5];
assign op_or = alu_op[ 6];
assign op_xor = alu_op[ 7];
assign op_sll = alu_op[ 8];
assign op_srl = alu_op[ 9];
assign op_sra = alu_op[10];
assign op_lui = alu_op[11];
wire [31:0] add_sub_result;
wire [31:0] slt_result ;
wire [31:0] sltu_result ;
wire [31:0] and_result ;
wire [31:0] nor_result ;
wire [31:0] or_result ;
wire [31:0] xor_result ;
wire [31:0] lui_result ;
wire [31:0] sll_result ;
wire [63:0] sr64_result ;
wire [31:0] sr_result ;
// 32-bit adder
wire [31:0] adder_a ;
wire [31:0] adder_b ;
wire adder_cin ;
wire [31:0] adder_result;
wire adder_cout ;
assign adder_a = alu_src1;
assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2;
assign adder_cin = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0;
assign {adder_cout, adder_result} = adder_a + adder_b + adder_cin;
// ADD, SUB result
assign add_sub_result = adder_result;
// SLT result
assign slt_result[31:1] = 31'b0;
assign slt_result[0] = (alu_src1[31] & ~alu_src2[31])
| ((alu_src1[31] ~^ alu_src2[31]) & adder_result[31]);
// SLTU result
assign sltu_result[31:1] = 31'b0;
assign sltu_result[0] = ~adder_cout;
// bitwise operation
assign and_result = alu_src1 & alu_src2;
assign or_result = alu_src1 | alu_src2;
assign nor_result = ~or_result;
assign xor_result = alu_src1 ^ alu_src2;
assign lui_result = {alu_src2[15:0], 16'b0};
// SLL result
assign sll_result = alu_src2 << alu_src1[4:0];
// SRL, SRA result
assign sr64_result = {{32{op_sra & alu_src2[31]}}, alu_src2[31:0]} >> alu_src1[4:0];
assign sr_result = sr64_result[31:0];
// final result mux
assign alu_result = ({32{op_add|op_sub}} & add_sub_result)
| ({32{op_slt }} & slt_result )
| ({32{op_sltu }} & sltu_result )
| ({32{op_and }} & and_result )
| ({32{op_nor }} & nor_result )
| ({32{op_or }} & or_result )
| ({32{op_xor }} & xor_result )
| ({32{op_lui }} & lui_result )
| ({32{op_sll }} & sll_result )
| ({32{op_srl|op_sra}} & sr_result );
assign overflow = (op_add & ~(alu_src1[31]) & ~(alu_src2[31]) & add_sub_result[31])
| (op_add & (alu_src1[31]) & (alu_src2[31]) & ~add_sub_result[31])
| (op_sub & ~(alu_src1[31]) & (alu_src2[31]) & add_sub_result[31])
| (op_sub & (alu_src1[31]) & ~(alu_src2[31]) & ~add_sub_result[31]);
endmodule