-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArithmeticLogicUnit.v
290 lines (248 loc) · 7.34 KB
/
ArithmeticLogicUnit.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
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
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 18:14:26 04/13/2020
// Design Name:
// Module Name: ArithmeticLogicUnit
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ArithmeticLogicUnit (clk, enable, reset, in1, in2, carry_in, mode, func,
result, carry_out, sign, zero, parity, equal, greater_than);
// 16 bit ALU ( 1 bit MSB reserved for signed bit)
// Works on positive edge of clock
// Input signals are active high
// Uses Signed Magnitude format of data to process
/* Inputs */
// clk regulates working of program counter
// enable to control working of alu
// reset to clear contents of alu
// in1 and in2 are two data inputs to alu
// carry_in is input from flag register
// mode to control alu (1 for Arithmetic and 0 for Logic operations)
// func to select operation to perform
/* Outputs */
// result is output of alu after operation
// carry_out to show carry signal of result
// sign to show if result is negative
// zero to show if result is zero (16'h0000)
// parity to show if there is even parity in result (EXCLUDING sign bit)
// equal to show if both inputs to alu are equal
// greater_than to show if the 1st input is greater than 2nd input
parameter word_size = 16;
parameter high_impedance = 16'hzzzz;
/* Arithmetic functions (Mode = 1) */
// All arithmatic functions are compatible with any combination
// of negative numbers as input
parameter addition = 4'h0;
parameter substraction = 4'h1;
parameter increment = 4'h2; // increment of 1st input by 1
parameter decrement = 4'h3; // decrement of ist input by 1
/* Logic functions (Mode = 0) */
parameter xor_op = 4'h0;
parameter and_op = 4'h1;
parameter or_op = 4'h2;
parameter xnor_op = 4'h3;
parameter nand_op = 4'h4;
parameter nor_op = 4'h5;
parameter high = 4'hf; // all output lines are logic high
parameter low = 4'he; // all output lines are logic low
parameter input1 = 4'hd; // reflect 1st input as output
parameter input2 = 4'hc; // reflect 2nd input as output
parameter invert_in1 = 4'hb; // invert 1st input as output
parameter invert_in2 = 4'ha; // invert 2nd input as output
input clk, enable, reset, carry_in, mode;
input [word_size-1 : 0] in1, in2;
input [3 : 0] func;
output reg [word_size-1 : 0] result;
output reg carry_out, sign, zero, parity, equal, greater_than;
reg [word_size-1 : 0] temp_in1, temp_in2;
reg [word_size : 0] temp_result;
integer count;
// Initializing reg variables
initial begin
result = 0;
carry_out = 0;
sign = 0;
zero = 0;
parity = 0;
equal = 0;
greater_than = 0;
temp_in1 = 0;
temp_in2 = 0;
temp_result = 0;
count = 0;
end
always @ (posedge clk) begin
if(enable === 1'b1) begin // only perform when enable is high
temp_in1 = in1;
temp_in2 = in2;
temp_result = 0;
equal = ( temp_in1 === temp_in2 )? 1'b1 : 1'b0;
if (temp_in1[15] > temp_in2[15])
greater_than = 1'b0;
else if (temp_in1 > temp_in2)
greater_than = 1'b1;
else
greater_than = 1'b0;
if (mode === 1'b1) begin // Arithmetic operations
case (func)
addition: begin
// both inputs are positive
if ( {temp_in1[15] , temp_in2[15]} === 2'b00) begin
temp_result = adder (temp_in1, temp_in2, carry_in);
if ( temp_result [15] === 1) begin
temp_result [15] = 0;
temp_result [16] = 1;
end
end
else begin // any or both of input/s is/are negative
// 1st input is negative
if (temp_in1[15] === 1'b1)
temp_in1 = comp2 (temp_in1); // taking 2's complement
// 2nd input is negative
if (temp_in2[15] === 1'b1)
temp_in2 = comp2 (temp_in2); // taking 2's complement
temp_result = adder (temp_in1, temp_in2, carry_in);
// result is negative
if (temp_result[15] === 1'b1) begin
temp_result = comp2 (temp_result);
if(temp_result[15] === 1'b0)
temp_result[15] = 1;
else
temp_result[15] = 0;
end
end
carry_out = temp_result[16];
end
substraction: begin
// both inputs are positive
if ( {temp_in1[15] , temp_in2[15]} === 2'b00)
temp_in2 = comp2 (temp_in2);
// 1st input is negative
else if (temp_in1[15] === 1'b1) begin
temp_in1 = comp2 (temp_in1); // taking 2's complement
temp_in2 = comp2 (temp_in2);
end
// 2nd input is negative
else
temp_in2[15] = 0; // considering 2nd input as positive
temp_result = adder (temp_in1, temp_in2, carry_in);
// result is negative
if (temp_result[15] === 1'b1) begin
temp_result = comp2 (temp_result);
if(temp_result[15] === 1'b0)
temp_result[15] = 1;
else
temp_result[15] = 0;
end
end
increment: begin
temp_result = adder (temp_in1, 16'h0001, 0);
end
decrement: begin
temp_result = adder (temp_in1, comp2 (16'h0001), 0);
end
default: begin
temp_result = 17'h0000;
end
endcase
end
else begin // mode=0 for logical operation
case (func)
xor_op: begin
temp_result = temp_in1 ^ temp_in2;
end
and_op: begin
temp_result = temp_in1 & temp_in2;
end
or_op: begin
temp_result = temp_in1 | temp_in2;
end
xnor_op: begin
temp_result = (temp_in1 ^ temp_in2);
temp_result = invert (temp_result);
end
nand_op: begin
temp_result = (temp_in1 & temp_in2);
temp_result = invert (temp_result);
end
nor_op: begin
temp_result = (temp_in1 | temp_in2);
temp_result = invert (temp_result);
end
high: begin
temp_result[15:0] = 16'hffff;
end
low: begin
temp_result[15:0] = 16'h0000;
end
input1: begin
temp_result = temp_in1;
end
input2: begin
temp_result = temp_in2;
end
invert_in1: begin
temp_result = invert (temp_in1);
end
invert_in2: begin
temp_result = invert (temp_in2);
end
default: begin
temp_result = 17'h0000;
end
endcase
end
if (reset === 1'b1) begin
temp_result = 0;
end
zero = ( temp_result [15 : 0] === 16'h0000 )? 1'b1 : 1'b0;
parity = ~^temp_result [15 : 0];
sign = temp_result [15];
result = temp_result [15 : 0];
end
end
function automatic [word_size-1 : 0] comp2;
input [word_size-1 : 0] data_in;
reg [word_size-1 : 0] temp;
begin
temp = invert (data_in);
comp2 = adder (temp, 16'h0001, 0);
end
endfunction
function automatic [word_size-1 : 0] invert;
input [word_size-1 : 0] in;
begin
invert = ~in;
end
endfunction
function automatic [word_size : 0] adder;
input [word_size-1 : 0] in1, in2;
input cin;
reg [word_size-1 : 0] p, g, c;
integer i;
begin
p = in1 ^ in2;
g = in1 & in2;
c[0] = g[0] | (cin&p[0]);
adder[0] = p[0] ^ cin;
for (i=1; i<16; i=i+1) begin
c[i] = g[i] | (c[i-1] & p[i]);
adder[i] = p[i] ^ c[i-1];
end
adder[16] = c[15];
end
endfunction
endmodule