forked from ggeeyyi/loongson-cpu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
alu.v
173 lines (154 loc) · 4.32 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
module alu(
/*
32位alu模块
clk: 时钟
resetn: 复位信号
alu_op: 操作码
alu_src1: 源操作数1
alu_src2: 源操作数2
alu_result: 结果
complete: 计算完成信号
*/
input wire clk,
input wire resetn,
// input wire [11:0] alu_op,
input wire [18:0] alu_op,
input wire [31:0] alu_src1,
input wire [31:0] alu_src2,
output wire [31:0] alu_result,
output wire complete
);
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;
wire op_mul;
wire op_mulh;
wire op_mulhu;
wire op_div;
wire op_divu;
wire op_mod;
wire op_modu;
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];
assign op_mul = alu_op[12];
assign op_mulh = alu_op[13];
assign op_mulhu= alu_op[14];
assign op_div = alu_op[15];
assign op_divu = alu_op[16];
assign op_mod = alu_op[17];
assign op_modu = alu_op[18];
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;
wire [31:0] mod_result;
wire [31:0] div_result;
wire [63:0] mul_result;
//加法器
wire [31:0] adder_a;
wire [31:0] adder_b;
wire adder_cin;
wire [31:0] adder_result;
wire adder_cout;
// 除法器
wire div_en;
wire div_complete;
wire mul_en;
reg mul_complete;
always @(posedge clk) begin
if(~resetn)
mul_complete <= 1'b0;
else if(mul_en & ~mul_complete)
mul_complete <= 1'b1;
else
mul_complete <= 1'b0;
end
assign adder_a = alu_src1;
assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2; //src1 - src2 rj-rk
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;
// SLL result
assign sll_result = alu_src1 << alu_src2[4:0];
// SRL, SRA result
assign sr64_result = {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0];
assign sr_result = sr64_result[31:0];
// Mul, Div, Mod
assign mul_en = op_mul | op_mulh | op_mulhu;
assign div_en = op_mod | op_modu | op_div | op_divu;
Wallace_Mul u_mul(
.mul_clk(clk),
.resetn(resetn),
.mul_signed(op_mulh|op_mul),
.x(alu_src1),
.y(alu_src2),
.result(mul_result)
);
Div u_div(
.div_clk(clk),
.resetn(resetn),
.div(div_en),
.div_signed(op_mod | op_div),
.x(alu_src1),
.y(alu_src2),
.s(div_result),
.r(mod_result),
.complete(div_complete)
);
// 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)
| ({32{op_mod|op_modu}} & mod_result)
| ({32{op_div|op_divu}} & div_result)
| ({32{op_mul }} & mul_result[31:0])
| ({32{op_mulh|op_mulhu}} & mul_result[63:32]);
assign complete = (~|alu_op[18:12]) | div_complete & div_en | mul_complete & mul_en | ~div_en & ~mul_en;
endmodule