-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathALU(Comments).v
More file actions
312 lines (262 loc) · 10.3 KB
/
Copy pathALU(Comments).v
File metadata and controls
312 lines (262 loc) · 10.3 KB
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 30.03.2025 15:57:11
// Design Name:
// Module Name: ArithmeticLogicUnit
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// This ALU performs a wide range of operations on 32-bit inputs. For some
// operations only the upper 16 bits (with sign extension) are used; for others,
// the full 32-bit operands are processed. Supported operations include pass-
// through, bitwise logic (NOT, AND, OR, XOR, NAND), arithmetic (addition and
// subtraction with overflow and carry detection), logical/arithmetic shifts, and
// circular (rotate) shifts that incorporate a carry bit. The status flags are
// generated internally and updated synchronously.
//
// Flags (output FlagsOut) are defined as follows (bit order from MSB to LSB):
// FlagsOut[3] = Zero flag (Z)
// FlagsOut[2] = Carry flag (C)
// FlagsOut[1] = Negative flag (N)
// FlagsOut[0] = Overflow flag (O)
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// Detailed inline documentation is provided below.
//////////////////////////////////////////////////////////////////////////////////
module ArithmeticLogicUnit (
input wire [31:0] A, // 32-bit input A
input wire [31:0] B, // 32-bit input B
input wire [4:0] FunSel, // 5-bit function select signal
input wire WF, // Write flag: enables updating of FlagsOut
input wire Clock, // Clock signal (for synchronous flag update)
output reg [3:0] FlagsOut, // Status flags: {Zero, Carry, Negative, Overflow}
output reg [31:0] ALUOut // 32-bit ALU result output
);
// Internal flag register: internalFlags holds computed flag values.
// Bit assignment: [3]=Zero, [2]=Carry, [1]=Negative, [0]=Overflow.
reg [3:0] internalFlags;
//--------------------------------------------------------------------------
// Input Splitting and Sign Extension for 16-bit Operations
//--------------------------------------------------------------------------
// Lower 16 bits (unused for 16-bit upper-half operations).
wire [15:0] A_L, B_L;
assign A_L = A[15:0];
assign B_L = B[15:0];
// Sign-extend the upper 16 bits of A and B to full 32 bits.
wire [31:0] sign_extended_A_H, sign_extended_B_H;
assign sign_extended_A_H = {{16{A[31]}}, A[31:16]};
assign sign_extended_B_H = {{16{B[31]}}, B[31:16]};
//--------------------------------------------------------------------------
// Key Bit Extraction for Flag Calculations
//--------------------------------------------------------------------------
// Most significant bits (MSB) and least significant bits (LSB) of full A and B.
wire MSB_A, MSB_B, LSB_A;
assign MSB_A = A[31];
assign MSB_B = B[31];
assign LSB_A = A[0];
// LSB of the sign-extended upper half of A.
wire LSB_A_H;
assign LSB_A_H = sign_extended_A_H[0];
//--------------------------------------------------------------------------
// Intermediate Signals for Arithmetic Operations
//--------------------------------------------------------------------------
// Sum is a 33-bit register to capture carry-out; Res holds the 32-bit result.
reg [32:0] Sum;
reg [31:0] Res;
//--------------------------------------------------------------------------
// Combinational Logic: Compute ALUOut and internalFlags Based on FunSel
//--------------------------------------------------------------------------
always @(*) begin
// Reset intermediate values.
Sum = 33'b0;
Res = 32'b0;
case (FunSel)
//////////// 16-bit Operations on Upper Halves (using sign_extended_A_H/B_H) ////////////
5'b00000: begin
// Pass-through: Output sign-extended upper half of A.
ALUOut = sign_extended_A_H;
end
5'b00001: begin
// Pass-through: Output sign-extended upper half of B.
ALUOut = sign_extended_B_H;
end
5'b00010: begin
// Bitwise NOT on sign_extended_A_H.
ALUOut = ~sign_extended_A_H;
end
5'b00011: begin
// Bitwise NOT on sign_extended_B_H.
ALUOut = ~sign_extended_B_H;
end
5'b00100: begin
// 16-bit Addition: sign_extended_A_H + sign_extended_B_H.
{internalFlags[2], ALUOut} = sign_extended_A_H + sign_extended_B_H;
end
5'b00101: begin
// 16-bit Addition with Carry: Add sign-extended halves and current carry.
{internalFlags[2], ALUOut} = sign_extended_A_H + sign_extended_B_H + FlagsOut[2];
internalFlags[0] = (MSB_A == MSB_B) && (ALUOut[31] != MSB_A);
end
5'b00110: begin
// 16-bit Subtraction: Compute A_H - B_H as A_H + ~B_H + 1.
{internalFlags[2], ALUOut} = sign_extended_A_H + ~sign_extended_B_H + 1'b1;
if ((MSB_A == 1'b0 && MSB_B == 1'b1 && ALUOut[31] == 1'b1) ||
(MSB_A == 1'b1 && MSB_B == 1'b0 && ALUOut[31] == 1'b0))
internalFlags[0] = 1;
end
5'b00111: begin
// Bitwise AND on upper halves.
ALUOut = sign_extended_A_H & sign_extended_B_H;
end
5'b01000: begin
// Bitwise OR on upper halves.
ALUOut = sign_extended_A_H | sign_extended_B_H;
end
5'b01001: begin
// Bitwise XOR on upper halves.
ALUOut = sign_extended_A_H ^ sign_extended_B_H;
end
5'b01010: begin
// Bitwise NAND on upper halves.
ALUOut = ~(sign_extended_A_H & sign_extended_B_H);
end
5'b01011: begin
// Logical Left Shift on upper half:
// Shift sign_extended_A_H left by one bit; new carry is original MSB_A.
internalFlags[2] = MSB_A;
ALUOut = {{16{sign_extended_A_H[14]}}, sign_extended_A_H[14:0], 1'b0};
end
5'b01100: begin
// Logical Right Shift on upper half:
// Shift sign_extended_A_H right by one bit; new carry is LSB_A_H.
internalFlags[2] = LSB_A_H;
ALUOut = {17'b0, sign_extended_A_H[15:1]};
end
5'b01101: begin
// Arithmetic Right Shift on upper half:
// Preserve sign by replicating MSB_A.
ALUOut = {{17{MSB_A}}, sign_extended_A_H[15:1]};
end
5'b01110: begin
// Circular (Rotate) Left Shift on upper half using carry:
// Shift left by one bit, insert current carry (FlagsOut[2]) as LSB,
// and the original MSB (A[31]) becomes the new carry.
internalFlags[2] = MSB_A;
ALUOut = {{16{sign_extended_A_H[14]}}, sign_extended_A_H[14:0], FlagsOut[2]};
end
5'b01111: begin
// Circular (Rotate) Right Shift on upper half using carry:
// Shift right by one bit, insert current carry (FlagsOut[2]) at MSB,
// and the original LSB of sign_extended_A_H becomes the new carry.
internalFlags[2] = LSB_A_H;
ALUOut = {{16{FlagsOut[2]}}, FlagsOut[2], sign_extended_A_H[15:1]};
end
//////////// 32-bit Operations (Full A and B) ////////////
5'b10000: begin
// 32-bit Pass-through: Output full A.
ALUOut = A;
end
5'b10001: begin
// 32-bit Pass-through: Output full B.
ALUOut = B;
end
5'b10010: begin
// 32-bit Bitwise NOT on A.
ALUOut = ~A;
end
5'b10011: begin
// 32-bit Bitwise NOT on B.
ALUOut = ~B;
end
5'b10100: begin
// 32-bit Addition: A + B.
{internalFlags[2], ALUOut} = A + B;
internalFlags[0] = (MSB_A == MSB_B) && (ALUOut[31] != MSB_A);
end
5'b10101: begin
// 32-bit Addition with Carry: A + B + Cin.
{internalFlags[2], ALUOut} = A + B + FlagsOut[2];
internalFlags[0] = (MSB_A == MSB_B) && (ALUOut[31] != MSB_A);
end
5'b10110: begin
// 32-bit Subtraction: A - B as A + ~B + 1.
{internalFlags[2], ALUOut} = A + ~B + 1;
if ((MSB_A == 1'b0 && MSB_B == 1'b1 && ALUOut[31] == 1'b1) ||
(MSB_A == 1'b1 && MSB_B == 1'b0 && ALUOut[31] == 1'b0))
internalFlags[0] = 1;
end
5'b10111: begin
// 32-bit Bitwise AND: A & B.
ALUOut = A & B;
end
5'b11000: begin
// 32-bit Bitwise OR: A | B.
ALUOut = A | B;
end
5'b11001: begin
// 32-bit Bitwise XOR: A ^ B.
ALUOut = A ^ B;
end
5'b11010: begin
// 32-bit Bitwise NAND: ~(A & B).
ALUOut = ~(A & B);
end
5'b11011: begin
// 32-bit Logical Left Shift: Shift A left by one bit.
internalFlags[2] = MSB_A;
ALUOut = {A[30:0], 1'b0};
end
5'b11100: begin
// 32-bit Logical Right Shift: Shift A right by one bit.
internalFlags[2] = LSB_A;
ALUOut = {1'b0, A[31:1]};
end
5'b11101: begin
// 32-bit Arithmetic Right Shift: Shift A right by one bit (preserve sign).
ALUOut = {MSB_A, A[31:1]};
end
5'b11110: begin
// 32-bit Circular (Rotate) Left Shift:
// Shift A left by one bit; insert current carry (FlagsOut[2]) at LSB.
// The original MSB becomes the new carry.
internalFlags[2] = MSB_A;
ALUOut = {A[30:0], FlagsOut[2]};
end
5'b11111: begin
// 32-bit Circular (Rotate) Right Shift:
// Shift A right by one bit; insert current carry (FlagsOut[2]) at MSB.
// The original LSB becomes the new carry.
internalFlags[2] = LSB_A;
ALUOut = {FlagsOut[2], A[31:1]};
end
default: begin
// Default operation: output zero.
ALUOut = 32'b0;
end
endcase
// Common flag assignments:
// Zero flag: 1 if ALUOut is zero.
internalFlags[3] = (ALUOut == 32'b0);
// Negative flag: taken from the MSB of ALUOut.
internalFlags[1] = ALUOut[31];
end
//--------------------------------------------------------------------------
// Synchronous Update of FlagsOut
//--------------------------------------------------------------------------
// On the rising edge of Clock, if WF is asserted, update the external flag output.
// Flag bit order: {Zero, Carry, Negative, Overflow} (MSB to LSB).
always @(posedge Clock) begin
if (WF) begin
FlagsOut[3] <= internalFlags[3]; // Zero flag
FlagsOut[2] <= internalFlags[2]; // Carry flag
FlagsOut[1] <= internalFlags[1]; // Negative flag
FlagsOut[0] <= internalFlags[0]; // Overflow flag
end
end
endmodule