Hello and welcome to Part 7 of my Beginning Logic Design series. In this post I will continue to add functionality to the ALU I’ve been working on in the last couple posts.
Using Vivado Via Command Line
This ALU project is making decent progress and I’d like to start managing the code with Git and make my work flow a bit faster. When I talk to engineers that work with FPGAs for a living, it seems like most of them do not use the project flow that I’ve been working with. They favor the command line or batch mode approach.
I’ll first copy my alu.sv
and top.sv
to a new directory so that those files are all I have. To build and test on the command line there are 3 commands I’ll use, xvlog
to parse my SystemVerilog, xelab
to elaborate the design, and xsim
to run the simulation.
xvlog --sv alu.sv top.sv
xelab top
xsim -R top
- xvlog --sv alu.sv top.sv
- xelab top
- xsim -R top
xvlog --sv alu.sv top.sv
xelab top
xsim -R top
Armed with these commands, I can more easily write my code in whichever editor I choose!
I’ll use this Makefile
to give me an easy way to test and clean up the built files and logs.
XVLOG_FILES=xvlog.log xvlog.pb xsim.dir
XELAB_FILES=webtalk*.log webtalk*.jou xelab.log xelab.pb .Xil/
XSIM_FILES=xsim*.log xsim*.jou
all:
@echo "Parsing HDL"
@xvlog --sv *.sv > build.log
@echo "Elaborating design"
@xelab top >> build.log
@echo "Starting simulation"
@xsim -R top
clean:
rm -rf $(XVLOG_FILES) $(XELAB_FILES) $(XSIM_FILES) build.log
- XVLOG_FILES=xvlog.log xvlog.pb xsim.dir
- XELAB_FILES=webtalk*.log webtalk*.jou xelab.log xelab.pb .Xil/
- XSIM_FILES=xsim*.log xsim*.jou
- all:
- @echo "Parsing HDL"
- @xvlog --sv *.sv > build.log
- @echo "Elaborating design"
- @xelab top >> build.log
- @echo "Starting simulation"
- @xsim -R top
- clean:
- rm -rf $(XVLOG_FILES) $(XELAB_FILES) $(XSIM_FILES) build.log
XVLOG_FILES=xvlog.log xvlog.pb xsim.dir
XELAB_FILES=webtalk*.log webtalk*.jou xelab.log xelab.pb .Xil/
XSIM_FILES=xsim*.log xsim*.jou
all:
@echo "Parsing HDL"
@xvlog --sv *.sv > build.log
@echo "Elaborating design"
@xelab top >> build.log
@echo "Starting simulation"
@xsim -R top
clean:
rm -rf $(XVLOG_FILES) $(XELAB_FILES) $(XSIM_FILES) build.log
Implementing Subtraction
Subtraction in binary is nearly identical to addition. In the case of subtraction, carry
is looked at as a borrow
value. Building a subtraction operation in SystemVerilog is the same as addition, but with -
instead of +
.
// Subtract operation internals
logic [7:0] subtract;
logic [6:0] subtract_lower_bits;
logic subtract_borrow_6;
logic subtract_borrow_7;
...
assign {subtract_borrow_6, subtract_lower_bits} = a[6:0] - b[6:0] - carry_in,
{subtract_borrow_7, subtract} = a - b - carry_in;
...
SUBTRACT: begin
y <= subtract;
carry_out <= subtract_borrow_7;
sign <= subtract[7];
overflow <= subtract_borrow_7 ^ subtract_borrow_6;
if (subtract == 0)
zero <= 1;
else
zero <= 0;
end
- // Subtract operation internals
- logic [7:0] subtract;
- logic [6:0] subtract_lower_bits;
- logic subtract_borrow_6;
- logic subtract_borrow_7;
- ...
- assign {subtract_borrow_6, subtract_lower_bits} = a[6:0] - b[6:0] - carry_in,
- {subtract_borrow_7, subtract} = a - b - carry_in;
- ...
- SUBTRACT: begin
- y <= subtract;
- carry_out <= subtract_borrow_7;
- sign <= subtract[7];
- overflow <= subtract_borrow_7 ^ subtract_borrow_6;
- if (subtract == 0)
- zero <= 1;
- else
- zero <= 0;
- end
// Subtract operation internals
logic [7:0] subtract;
logic [6:0] subtract_lower_bits;
logic subtract_borrow_6;
logic subtract_borrow_7;
...
assign {subtract_borrow_6, subtract_lower_bits} = a[6:0] - b[6:0] - carry_in,
{subtract_borrow_7, subtract} = a - b - carry_in;
...
SUBTRACT: begin
y <= subtract;
carry_out <= subtract_borrow_7;
sign <= subtract[7];
overflow <= subtract_borrow_7 ^ subtract_borrow_6;
if (subtract == 0)
zero <= 1;
else
zero <= 0;
end
As with the addition, I’ll make some tests that validate I’m getting the results I expect from the operation.
// Test 100 - 80
operation = SUBTRACT;
a = 100;
b = 80;
#2 assert(y == 20) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 80 - 100
a = 80;
b = 100;
#2 assert(y == 236) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 80 - 176
a = 80;
b = 176;
#2 assert(y == 160) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 208 - 112
a = 208;
b = 112;
#2 assert(y == 96) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 208 - 208
a = 208;
b = 208;
#2 assert(y == 0) else $error("Subtract assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
- // Test 100 - 80
- operation = SUBTRACT;
- a = 100;
- b = 80;
- #2 assert(y == 20) else $error("Subtract assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- assert(carry_out == 0) else $error("Carry assertion failed.");
- assert(overflow == 0) else $error("Overflow assertion failed.");
- // Test 80 - 100
- a = 80;
- b = 100;
- #2 assert(y == 236) else $error("Subtract assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- assert(carry_out == 1) else $error("Carry assertion failed.");
- assert(overflow == 0) else $error("Overflow assertion failed.");
- // Test 80 - 176
- a = 80;
- b = 176;
- #2 assert(y == 160) else $error("Subtract assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- assert(carry_out == 1) else $error("Carry assertion failed.");
- assert(overflow == 1) else $error("Overflow assertion failed.");
- // Test 208 - 112
- a = 208;
- b = 112;
- #2 assert(y == 96) else $error("Subtract assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- assert(carry_out == 0) else $error("Carry assertion failed.");
- assert(overflow == 1) else $error("Overflow assertion failed.");
- // Test 208 - 208
- a = 208;
- b = 208;
- #2 assert(y == 0) else $error("Subtract assertion failed.");
- assert(zero == 1) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- assert(carry_out == 0) else $error("Carry assertion failed.");
- assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 100 - 80
operation = SUBTRACT;
a = 100;
b = 80;
#2 assert(y == 20) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 80 - 100
a = 80;
b = 100;
#2 assert(y == 236) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 80 - 176
a = 80;
b = 176;
#2 assert(y == 160) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 208 - 112
a = 208;
b = 112;
#2 assert(y == 96) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 208 - 208
a = 208;
b = 208;
#2 assert(y == 0) else $error("Subtract assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
Implementing Remaining Operations
Addition and Subtraction are the trickiest operations to implement of the operations planned for this ALU. With two instructions down there are 10 to go,
- Arithmetic Operations
- Add with Carry
- Subtract with Carry
- Increment
- Decrement
- Logic Operations
- AND
- OR
- XOR
- NOT/Negate (not in 6502, but I want my ALU to have it!)
- Shifting Operations
- Arithmetic Shift Left
- Logical Shift Right
- Rotate Left
- Rotate Right
Increment & Decrement
Increment and decrement only affect the sign
and zero
flags, and adds or subtracts 1 from a single operand. To implement them I’ll use assign
again to give me a reference to an incremented and decremented value.
// Increment/Decrement
logic [7:0] incremented;
logic [7:0] decremented;
assign incremented = a + 1,
decremented = a - 1;
- // Increment/Decrement
- logic [7:0] incremented;
- logic [7:0] decremented;
- assign incremented = a + 1,
- decremented = a - 1;
// Increment/Decrement
logic [7:0] incremented;
logic [7:0] decremented;
assign incremented = a + 1,
decremented = a - 1;
Then in my case
statement on operation, I’ll add the INCREMENT
and DECREMENT
cases.
INCREMENT: begin
y <= incremented;
sign <= incremented[7];
if (incremented == 0)
zero <= 1;
else
zero <= 0;
end
DECREMENT: begin
y <= decremented;
sign <= decremented[7];
if (decremented == 0)
zero <= 1;
else
zero <= 0;
end
- INCREMENT: begin
- y <= incremented;
- sign <= incremented[7];
- if (incremented == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- DECREMENT: begin
- y <= decremented;
- sign <= decremented[7];
- if (decremented == 0)
- zero <= 1;
- else
- zero <= 0;
- end
INCREMENT: begin
y <= incremented;
sign <= incremented[7];
if (incremented == 0)
zero <= 1;
else
zero <= 0;
end
DECREMENT: begin
y <= decremented;
sign <= decremented[7];
if (decremented == 0)
zero <= 1;
else
zero <= 0;
end
Then I’ll add some more tests to top
to verify it.
// Test 0++
operation = INCREMENT;
a = 0;
#2 assert(y == 1) else $error("Increment assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 200++
a = 200;
#2 assert(y == 201) else $error("Increment assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 255++
a = 255;
#2 assert(y == 0) else $error("Increment assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 0--
operation = DECREMENT;
a = 0;
#2 assert(y == 255) else $error("Decrement assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 200--
a = 200;
#2 assert(y == 199) else $error("Decrement assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 1--
a = 1;
#2 assert(y == 0) else $error("Decrement assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign a
- // Test 0++
- operation = INCREMENT;
- a = 0;
- #2 assert(y == 1) else $error("Increment assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 200++
- a = 200;
- #2 assert(y == 201) else $error("Increment assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- // Test 255++
- a = 255;
- #2 assert(y == 0) else $error("Increment assertion failed.");
- assert(zero == 1) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 0--
- operation = DECREMENT;
- a = 0;
- #2 assert(y == 255) else $error("Decrement assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- // Test 200--
- a = 200;
- #2 assert(y == 199) else $error("Decrement assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- // Test 1--
- a = 1;
- #2 assert(y == 0) else $error("Decrement assertion failed.");
- assert(zero == 1) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign a
// Test 0++
operation = INCREMENT;
a = 0;
#2 assert(y == 1) else $error("Increment assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 200++
a = 200;
#2 assert(y == 201) else $error("Increment assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 255++
a = 255;
#2 assert(y == 0) else $error("Increment assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 0--
operation = DECREMENT;
a = 0;
#2 assert(y == 255) else $error("Decrement assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 200--
a = 200;
#2 assert(y == 199) else $error("Decrement assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 1--
a = 1;
#2 assert(y == 0) else $error("Decrement assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign a
Logic Operations
The logic operations AND
, OR
, XOR
, and NOT
are the easiest operations to implement. Very similar to what I did for increment and decrement, I’ll name some new variables and keep them assigned to the results for each operation. Then they are added to the case
statement.
// Logic operations
logic [7:0] and_result;
logic [7:0] or_result;
logic [7:0] xor_result;
logic [7:0] not_result;
// Logic assignments
assign and_result = a & b,
or_result = a | b,
xor_result = a ^ b,
not_result = ~a;
...
BIT_AND: begin
y <= and_result;
sign <= and_result[7];
if (and_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_OR: begin
y <= or_result;
sign <= or_result[7];
if (or_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_XOR: begin
y <= xor_result;
sign <= xor_result[7];
if (xor_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_NOT: begin
y <= not_result;
sign <= not_result[7];
if (not_result == 0)
zero <= 1;
else
zero <= 0;
end
- // Logic operations
- logic [7:0] and_result;
- logic [7:0] or_result;
- logic [7:0] xor_result;
- logic [7:0] not_result;
- // Logic assignments
- assign and_result = a & b,
- or_result = a | b,
- xor_result = a ^ b,
- not_result = ~a;
- ...
- BIT_AND: begin
- y <= and_result;
- sign <= and_result[7];
- if (and_result == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- BIT_OR: begin
- y <= or_result;
- sign <= or_result[7];
- if (or_result == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- BIT_XOR: begin
- y <= xor_result;
- sign <= xor_result[7];
- if (xor_result == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- BIT_NOT: begin
- y <= not_result;
- sign <= not_result[7];
- if (not_result == 0)
- zero <= 1;
- else
- zero <= 0;
- end
// Logic operations
logic [7:0] and_result;
logic [7:0] or_result;
logic [7:0] xor_result;
logic [7:0] not_result;
// Logic assignments
assign and_result = a & b,
or_result = a | b,
xor_result = a ^ b,
not_result = ~a;
...
BIT_AND: begin
y <= and_result;
sign <= and_result[7];
if (and_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_OR: begin
y <= or_result;
sign <= or_result[7];
if (or_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_XOR: begin
y <= xor_result;
sign <= xor_result[7];
if (xor_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_NOT: begin
y <= not_result;
sign <= not_result[7];
if (not_result == 0)
zero <= 1;
else
zero <= 0;
end
Then some tests to verify.
// Test 12 & 10
operation = BIT_AND;
a = 12;
b = 10;
#2 assert(y == 8) else $error("AND assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 | 15
operation = BIT_OR;
a = 13;
b = 15;
#2 assert(y == 15) else $error("OR assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 ^ 15
operation = BIT_XOR;
a = 13;
b = 15;
#2 assert(y == 2) else $error("XOR assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 & 15
operation = BIT_NOT;
a = 13;
#2 assert(y == 242) else $error("NOT assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
- // Test 12 & 10
- operation = BIT_AND;
- a = 12;
- b = 10;
- #2 assert(y == 8) else $error("AND assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 13 | 15
- operation = BIT_OR;
- a = 13;
- b = 15;
- #2 assert(y == 15) else $error("OR assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 13 ^ 15
- operation = BIT_XOR;
- a = 13;
- b = 15;
- #2 assert(y == 2) else $error("XOR assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 13 & 15
- operation = BIT_NOT;
- a = 13;
- #2 assert(y == 242) else $error("NOT assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
// Test 12 & 10
operation = BIT_AND;
a = 12;
b = 10;
#2 assert(y == 8) else $error("AND assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 | 15
operation = BIT_OR;
a = 13;
b = 15;
#2 assert(y == 15) else $error("OR assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 ^ 15
operation = BIT_XOR;
a = 13;
b = 15;
#2 assert(y == 2) else $error("XOR assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 & 15
operation = BIT_NOT;
a = 13;
#2 assert(y == 242) else $error("NOT assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
Shifting Operations
The last few operations to add are the shifters. Rotate left and rotate right shift all the bits left or right by one position. In the case of a right shift, the leftmost bit will change to the carry in
bit, and the rightmost bit will become the new carry out
. In the arithmetic and logical shift operations the bit being pushed in will be 0
regardless of the carry in
value.
// Shifting operations
logic [7:0] rotated_left;
logic [7:0] rotated_right;
logic [7:0] shifted_left;
logic [7:0] shifted_right;
// Shifting assignments
assign rotated_left = {a[6:0], carry_in},
rotated_right = {carry_in, a[7:1]},
shifted_left = {a[6:0], 1'b0},
shifted_right = {1'b0, a[7:1]};
...
ROTATE_LEFT: begin
y <= rotated_left;
carry_out <= a[7];
sign <= rotated_left[7];
if (rotated_left == 0)
zero <= 1;
else
zero <= 0;
end
ROTATE_RIGHT: begin
y <= rotated_right;
carry_out <= a[0];
sign <= rotated_right[7];
if (rotated_right == 0)
zero <= 1;
else
zero <= 0;
end
SHIFT_LEFT: begin
y <= shifted_left;
carry_out <= a[7];
sign <= shifted_left[7];
if (shifted_left == 0)
zero <= 1;
else
zero <= 0;
end
SHIFT_RIGHT: begin
y <= shifted_right;
carry_out <= a[0];
sign <= shifted_right[7];
if (shifted_right == 0)
zero <= 1;
else
zero <= 0;
- // Shifting operations
- logic [7:0] rotated_left;
- logic [7:0] rotated_right;
- logic [7:0] shifted_left;
- logic [7:0] shifted_right;
- // Shifting assignments
- assign rotated_left = {a[6:0], carry_in},
- rotated_right = {carry_in, a[7:1]},
- shifted_left = {a[6:0], 1'b0},
- shifted_right = {1'b0, a[7:1]};
- ...
- ROTATE_LEFT: begin
- y <= rotated_left;
- carry_out <= a[7];
- sign <= rotated_left[7];
- if (rotated_left == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- ROTATE_RIGHT: begin
- y <= rotated_right;
- carry_out <= a[0];
- sign <= rotated_right[7];
- if (rotated_right == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- SHIFT_LEFT: begin
- y <= shifted_left;
- carry_out <= a[7];
- sign <= shifted_left[7];
- if (shifted_left == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- SHIFT_RIGHT: begin
- y <= shifted_right;
- carry_out <= a[0];
- sign <= shifted_right[7];
- if (shifted_right == 0)
- zero <= 1;
- else
- zero <= 0;
// Shifting operations
logic [7:0] rotated_left;
logic [7:0] rotated_right;
logic [7:0] shifted_left;
logic [7:0] shifted_right;
// Shifting assignments
assign rotated_left = {a[6:0], carry_in},
rotated_right = {carry_in, a[7:1]},
shifted_left = {a[6:0], 1'b0},
shifted_right = {1'b0, a[7:1]};
...
ROTATE_LEFT: begin
y <= rotated_left;
carry_out <= a[7];
sign <= rotated_left[7];
if (rotated_left == 0)
zero <= 1;
else
zero <= 0;
end
ROTATE_RIGHT: begin
y <= rotated_right;
carry_out <= a[0];
sign <= rotated_right[7];
if (rotated_right == 0)
zero <= 1;
else
zero <= 0;
end
SHIFT_LEFT: begin
y <= shifted_left;
carry_out <= a[7];
sign <= shifted_left[7];
if (shifted_left == 0)
zero <= 1;
else
zero <= 0;
end
SHIFT_RIGHT: begin
y <= shifted_right;
carry_out <= a[0];
sign <= shifted_right[7];
if (shifted_right == 0)
zero <= 1;
else
zero <= 0;
For the shift assignments I use 1'b0
to specify a 1
bit b
inary with the value 0
in the concatenation. As always some tests to validate we’re getting the right behavior.
// Test shift left
operation = SHIFT_LEFT;
carry_in = 1;
a = 136;
#2 assert(y == 16) else $error("Shift left assertion failed.");
assert(carry_out == 1) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test shift right
operation = SHIFT_RIGHT;
a = 8;
#2 assert(y == 4) else $error("Shift right assertion failed.");
assert(carry_out == 0) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test rotate left
operation = ROTATE_LEFT;
a = 8;
#2 assert(y == 17) else $error("Rotate left assertion failed.");
assert(carry_out == 0) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test rotate right
operation = ROTATE_RIGHT;
a = 9;
#2 assert(y == 132) else $error("Rotate right assertion failed.");
assert(carry_out == 1) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
- // Test shift left
- operation = SHIFT_LEFT;
- carry_in = 1;
- a = 136;
- #2 assert(y == 16) else $error("Shift left assertion failed.");
- assert(carry_out == 1) else $error("carry assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test shift right
- operation = SHIFT_RIGHT;
- a = 8;
- #2 assert(y == 4) else $error("Shift right assertion failed.");
- assert(carry_out == 0) else $error("carry assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test rotate left
- operation = ROTATE_LEFT;
- a = 8;
- #2 assert(y == 17) else $error("Rotate left assertion failed.");
- assert(carry_out == 0) else $error("carry assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test rotate right
- operation = ROTATE_RIGHT;
- a = 9;
- #2 assert(y == 132) else $error("Rotate right assertion failed.");
- assert(carry_out == 1) else $error("carry assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
// Test shift left
operation = SHIFT_LEFT;
carry_in = 1;
a = 136;
#2 assert(y == 16) else $error("Shift left assertion failed.");
assert(carry_out == 1) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test shift right
operation = SHIFT_RIGHT;
a = 8;
#2 assert(y == 4) else $error("Shift right assertion failed.");
assert(carry_out == 0) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test rotate left
operation = ROTATE_LEFT;
a = 8;
#2 assert(y == 17) else $error("Rotate left assertion failed.");
assert(carry_out == 0) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test rotate right
operation = ROTATE_RIGHT;
a = 9;
#2 assert(y == 132) else $error("Rotate right assertion failed.");
assert(carry_out == 1) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
It Works!
There it is! An ALU implementation that can handle 12 different 8-bit operations. It took 3 posts to get here, but this is a decently large design. Here’s the final alu.sv
file
`timescale 1ns / 1ps
package ALU;
typedef enum logic [3:0] {
ADD,
SUBTRACT,
INCREMENT,
DECREMENT,
BIT_AND,
BIT_OR,
BIT_XOR,
BIT_NOT,
SHIFT_LEFT,
SHIFT_RIGHT,
ROTATE_LEFT,
ROTATE_RIGHT
} opcode;
endpackage
import ALU::*;
module alu (
input logic clock,
input opcode operation,
input logic [7:0] a,
input logic [7:0] b,
input logic carry_in,
output logic [7:0] y,
output logic zero,
output logic sign,
output logic carry_out,
output logic overflow
);
// Add operation internals
logic [7:0] add;
logic [6:0] add_lower_bits;
logic add_carry_6;
logic add_carry_7;
// Subtract operation internals
logic [7:0] subtract;
logic [6:0] subtract_lower_bits;
logic subtract_borrow_6;
logic subtract_borrow_7;
// Increment/Decrement
logic [7:0] incremented;
logic [7:0] decremented;
// Logic operations
logic [7:0] and_result;
logic [7:0] or_result;
logic [7:0] xor_result;
logic [7:0] not_result;
// Shifting operations
logic [7:0] rotated_left;
logic [7:0] rotated_right;
logic [7:0] shifted_left;
logic [7:0] shifted_right;
// Add assignments
assign {add_carry_6, add_lower_bits} = a[6:0] + b[6:0] + carry_in,
{add_carry_7, add} = a + b + carry_in;
// Subtract assignments
assign {subtract_borrow_6, subtract_lower_bits} = a[6:0] - b[6:0] - carry_in,
{subtract_borrow_7, subtract} = a - b - carry_in;
// Increment/decrement assignments
assign incremented = a + 1,
decremented = a - 1;
// Logic assignments
assign and_result = a & b,
or_result = a | b,
xor_result = a ^ b,
not_result = ~a;
// Shifting assignments
assign rotated_left = {a[6:0], carry_in},
rotated_right = {carry_in, a[7:1]},
shifted_left = {a[6:0], 1'b0},
shifted_right = {1'b0, a[7:1]};
always_ff @ (posedge clock) begin
case (operation)
ADD: begin
y <= add;
carry_out <= add_carry_7;
sign <= add[7];
overflow <= add_carry_7 ^ add_carry_6;
if (add == 0)
zero <= 1;
else
zero <= 0;
end
SUBTRACT: begin
y <= subtract;
carry_out <= subtract_borrow_7;
sign <= subtract[7];
overflow <= subtract_borrow_7 ^ subtract_borrow_6;
if (subtract == 0)
zero <= 1;
else
zero <= 0;
end
INCREMENT: begin
y <= incremented;
sign <= incremented[7];
if (incremented == 0)
zero <= 1;
else
zero <= 0;
end
DECREMENT: begin
y <= decremented;
sign <= decremented[7];
if (decremented == 0)
zero <= 1;
else
zero <= 0;
end
BIT_AND: begin
y <= and_result;
sign <= and_result[7];
if (and_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_OR: begin
y <= or_result;
sign <= or_result[7];
if (or_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_XOR: begin
y <= xor_result;
sign <= xor_result[7];
if (xor_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_NOT: begin
y <= not_result;
sign <= not_result[7];
if (not_result == 0)
zero <= 1;
else
zero <= 0;
end
ROTATE_LEFT: begin
y <= rotated_left;
carry_out <= a[7];
sign <= rotated_left[7];
if (rotated_left == 0)
zero <= 1;
else
zero <= 0;
end
ROTATE_RIGHT: begin
y <= rotated_right;
carry_out <= a[0];
sign <= rotated_right[7];
if (rotated_right == 0)
zero <= 1;
else
zero <= 0;
end
SHIFT_LEFT: begin
y <= shifted_left;
carry_out <= a[7];
sign <= shifted_left[7];
if (shifted_left == 0)
zero <= 1;
else
zero <= 0;
end
SHIFT_RIGHT: begin
y <= shifted_right;
carry_out <= a[0];
sign <= shifted_right[7];
if (shifted_right == 0)
zero <= 1;
else
zero <= 0;
end
endcase
end
endmodule
- `timescale 1ns / 1ps
- package ALU;
- typedef enum logic [3:0] {
- ADD,
- SUBTRACT,
- INCREMENT,
- DECREMENT,
- BIT_AND,
- BIT_OR,
- BIT_XOR,
- BIT_NOT,
- SHIFT_LEFT,
- SHIFT_RIGHT,
- ROTATE_LEFT,
- ROTATE_RIGHT
- } opcode;
- endpackage
- import ALU::*;
- module alu (
- input logic clock,
- input opcode operation,
- input logic [7:0] a,
- input logic [7:0] b,
- input logic carry_in,
- output logic [7:0] y,
- output logic zero,
- output logic sign,
- output logic carry_out,
- output logic overflow
- );
- // Add operation internals
- logic [7:0] add;
- logic [6:0] add_lower_bits;
- logic add_carry_6;
- logic add_carry_7;
- // Subtract operation internals
- logic [7:0] subtract;
- logic [6:0] subtract_lower_bits;
- logic subtract_borrow_6;
- logic subtract_borrow_7;
- // Increment/Decrement
- logic [7:0] incremented;
- logic [7:0] decremented;
- // Logic operations
- logic [7:0] and_result;
- logic [7:0] or_result;
- logic [7:0] xor_result;
- logic [7:0] not_result;
- // Shifting operations
- logic [7:0] rotated_left;
- logic [7:0] rotated_right;
- logic [7:0] shifted_left;
- logic [7:0] shifted_right;
- // Add assignments
- assign {add_carry_6, add_lower_bits} = a[6:0] + b[6:0] + carry_in,
- {add_carry_7, add} = a + b + carry_in;
- // Subtract assignments
- assign {subtract_borrow_6, subtract_lower_bits} = a[6:0] - b[6:0] - carry_in,
- {subtract_borrow_7, subtract} = a - b - carry_in;
- // Increment/decrement assignments
- assign incremented = a + 1,
- decremented = a - 1;
- // Logic assignments
- assign and_result = a & b,
- or_result = a | b,
- xor_result = a ^ b,
- not_result = ~a;
- // Shifting assignments
- assign rotated_left = {a[6:0], carry_in},
- rotated_right = {carry_in, a[7:1]},
- shifted_left = {a[6:0], 1'b0},
- shifted_right = {1'b0, a[7:1]};
- always_ff @ (posedge clock) begin
- case (operation)
- ADD: begin
- y <= add;
- carry_out <= add_carry_7;
- sign <= add[7];
- overflow <= add_carry_7 ^ add_carry_6;
- if (add == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- SUBTRACT: begin
- y <= subtract;
- carry_out <= subtract_borrow_7;
- sign <= subtract[7];
- overflow <= subtract_borrow_7 ^ subtract_borrow_6;
- if (subtract == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- INCREMENT: begin
- y <= incremented;
- sign <= incremented[7];
- if (incremented == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- DECREMENT: begin
- y <= decremented;
- sign <= decremented[7];
- if (decremented == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- BIT_AND: begin
- y <= and_result;
- sign <= and_result[7];
- if (and_result == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- BIT_OR: begin
- y <= or_result;
- sign <= or_result[7];
- if (or_result == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- BIT_XOR: begin
- y <= xor_result;
- sign <= xor_result[7];
- if (xor_result == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- BIT_NOT: begin
- y <= not_result;
- sign <= not_result[7];
- if (not_result == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- ROTATE_LEFT: begin
- y <= rotated_left;
- carry_out <= a[7];
- sign <= rotated_left[7];
- if (rotated_left == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- ROTATE_RIGHT: begin
- y <= rotated_right;
- carry_out <= a[0];
- sign <= rotated_right[7];
- if (rotated_right == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- SHIFT_LEFT: begin
- y <= shifted_left;
- carry_out <= a[7];
- sign <= shifted_left[7];
- if (shifted_left == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- SHIFT_RIGHT: begin
- y <= shifted_right;
- carry_out <= a[0];
- sign <= shifted_right[7];
- if (shifted_right == 0)
- zero <= 1;
- else
- zero <= 0;
- end
- endcase
- end
- endmodule
`timescale 1ns / 1ps
package ALU;
typedef enum logic [3:0] {
ADD,
SUBTRACT,
INCREMENT,
DECREMENT,
BIT_AND,
BIT_OR,
BIT_XOR,
BIT_NOT,
SHIFT_LEFT,
SHIFT_RIGHT,
ROTATE_LEFT,
ROTATE_RIGHT
} opcode;
endpackage
import ALU::*;
module alu (
input logic clock,
input opcode operation,
input logic [7:0] a,
input logic [7:0] b,
input logic carry_in,
output logic [7:0] y,
output logic zero,
output logic sign,
output logic carry_out,
output logic overflow
);
// Add operation internals
logic [7:0] add;
logic [6:0] add_lower_bits;
logic add_carry_6;
logic add_carry_7;
// Subtract operation internals
logic [7:0] subtract;
logic [6:0] subtract_lower_bits;
logic subtract_borrow_6;
logic subtract_borrow_7;
// Increment/Decrement
logic [7:0] incremented;
logic [7:0] decremented;
// Logic operations
logic [7:0] and_result;
logic [7:0] or_result;
logic [7:0] xor_result;
logic [7:0] not_result;
// Shifting operations
logic [7:0] rotated_left;
logic [7:0] rotated_right;
logic [7:0] shifted_left;
logic [7:0] shifted_right;
// Add assignments
assign {add_carry_6, add_lower_bits} = a[6:0] + b[6:0] + carry_in,
{add_carry_7, add} = a + b + carry_in;
// Subtract assignments
assign {subtract_borrow_6, subtract_lower_bits} = a[6:0] - b[6:0] - carry_in,
{subtract_borrow_7, subtract} = a - b - carry_in;
// Increment/decrement assignments
assign incremented = a + 1,
decremented = a - 1;
// Logic assignments
assign and_result = a & b,
or_result = a | b,
xor_result = a ^ b,
not_result = ~a;
// Shifting assignments
assign rotated_left = {a[6:0], carry_in},
rotated_right = {carry_in, a[7:1]},
shifted_left = {a[6:0], 1'b0},
shifted_right = {1'b0, a[7:1]};
always_ff @ (posedge clock) begin
case (operation)
ADD: begin
y <= add;
carry_out <= add_carry_7;
sign <= add[7];
overflow <= add_carry_7 ^ add_carry_6;
if (add == 0)
zero <= 1;
else
zero <= 0;
end
SUBTRACT: begin
y <= subtract;
carry_out <= subtract_borrow_7;
sign <= subtract[7];
overflow <= subtract_borrow_7 ^ subtract_borrow_6;
if (subtract == 0)
zero <= 1;
else
zero <= 0;
end
INCREMENT: begin
y <= incremented;
sign <= incremented[7];
if (incremented == 0)
zero <= 1;
else
zero <= 0;
end
DECREMENT: begin
y <= decremented;
sign <= decremented[7];
if (decremented == 0)
zero <= 1;
else
zero <= 0;
end
BIT_AND: begin
y <= and_result;
sign <= and_result[7];
if (and_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_OR: begin
y <= or_result;
sign <= or_result[7];
if (or_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_XOR: begin
y <= xor_result;
sign <= xor_result[7];
if (xor_result == 0)
zero <= 1;
else
zero <= 0;
end
BIT_NOT: begin
y <= not_result;
sign <= not_result[7];
if (not_result == 0)
zero <= 1;
else
zero <= 0;
end
ROTATE_LEFT: begin
y <= rotated_left;
carry_out <= a[7];
sign <= rotated_left[7];
if (rotated_left == 0)
zero <= 1;
else
zero <= 0;
end
ROTATE_RIGHT: begin
y <= rotated_right;
carry_out <= a[0];
sign <= rotated_right[7];
if (rotated_right == 0)
zero <= 1;
else
zero <= 0;
end
SHIFT_LEFT: begin
y <= shifted_left;
carry_out <= a[7];
sign <= shifted_left[7];
if (shifted_left == 0)
zero <= 1;
else
zero <= 0;
end
SHIFT_RIGHT: begin
y <= shifted_right;
carry_out <= a[0];
sign <= shifted_right[7];
if (shifted_right == 0)
zero <= 1;
else
zero <= 0;
end
endcase
end
endmodule
And the final top.sv
`timescale 1ns / 1ps
import ALU::*;
module top ();
logic clock;
opcode operation;
logic [7:0] a;
logic [7:0] b;
logic carry_in;
logic [7:0] y;
logic zero;
logic sign;
logic carry_out;
logic overflow;
alu myALU (
clock,
operation,
a,
b,
carry_in,
y,
zero,
sign,
carry_out,
overflow
);
initial begin
clock = 0;
operation = ADD;
carry_in = 0;
// Test 208 + 144
a = 208;
b = 144;
#2 assert(y == 96) else $error("Sum assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 208 + 48 (signed -48 + 48)
a = 208;
b = 48;
#2 assert(y == 0) else $error("Sum assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 80 + 80
a = 80;
b = 80;
#2 assert(y == 160) else $error("Sum assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 100 - 80
operation = SUBTRACT;
a = 100;
b = 80;
#2 assert(y == 20) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 80 - 100
a = 80;
b = 100;
#2 assert(y == 236) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 80 - 176
a = 80;
b = 176;
#2 assert(y == 160) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 208 - 112
a = 208;
b = 112;
#2 assert(y == 96) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 208 - 208
a = 208;
b = 208;
#2 assert(y == 0) else $error("Subtract assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 0++
operation = INCREMENT;
a = 0;
#2 assert(y == 1) else $error("Increment assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 200++
a = 200;
#2 assert(y == 201) else $error("Increment assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 255++
a = 255;
#2 assert(y == 0) else $error("Increment assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 0--
operation = DECREMENT;
a = 0;
#2 assert(y == 255) else $error("Decrement assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 200--
a = 200;
#2 assert(y == 199) else $error("Decrement assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 1--
a = 1;
#2 assert(y == 0) else $error("Decrement assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 12 & 10
operation = BIT_AND;
a = 12;
b = 10;
#2 assert(y == 8) else $error("AND assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 | 15
operation = BIT_OR;
a = 13;
b = 15;
#2 assert(y == 15) else $error("OR assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 ^ 15
operation = BIT_XOR;
a = 13;
b = 15;
#2 assert(y == 2) else $error("XOR assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 & 15
operation = BIT_NOT;
a = 13;
#2 assert(y == 242) else $error("NOT assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test shift left
operation = SHIFT_LEFT;
carry_in = 1;
a = 136;
#2 assert(y == 16) else $error("Shift left assertion failed.");
assert(carry_out == 1) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test shift right
operation = SHIFT_RIGHT;
a = 8;
#2 assert(y == 4) else $error("Shift right assertion failed.");
assert(carry_out == 0) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test rotate left
operation = ROTATE_LEFT;
a = 8;
#2 assert(y == 17) else $error("Rotate left assertion failed.");
assert(carry_out == 0) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test rotate right
operation = ROTATE_RIGHT;
a = 9;
#2 assert(y == 132) else $error("Rotate right assertion failed.");
assert(carry_out == 1) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
#1 $finish();
end
always begin
#1 clock = ~clock;
end
endmodule
- `timescale 1ns / 1ps
- import ALU::*;
- module top ();
- logic clock;
- opcode operation;
- logic [7:0] a;
- logic [7:0] b;
- logic carry_in;
- logic [7:0] y;
- logic zero;
- logic sign;
- logic carry_out;
- logic overflow;
- alu myALU (
- clock,
- operation,
- a,
- b,
- carry_in,
- y,
- zero,
- sign,
- carry_out,
- overflow
- );
- initial begin
- clock = 0;
- operation = ADD;
- carry_in = 0;
- // Test 208 + 144
- a = 208;
- b = 144;
- #2 assert(y == 96) else $error("Sum assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- assert(carry_out == 1) else $error("Carry assertion failed.");
- assert(overflow == 1) else $error("Overflow assertion failed.");
- // Test 208 + 48 (signed -48 + 48)
- a = 208;
- b = 48;
- #2 assert(y == 0) else $error("Sum assertion failed.");
- assert(zero == 1) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- assert(carry_out == 1) else $error("Carry assertion failed.");
- assert(overflow == 0) else $error("Overflow assertion failed.");
- // Test 80 + 80
- a = 80;
- b = 80;
- #2 assert(y == 160) else $error("Sum assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- assert(carry_out == 0) else $error("Carry assertion failed.");
- assert(overflow == 1) else $error("Overflow assertion failed.");
- // Test 100 - 80
- operation = SUBTRACT;
- a = 100;
- b = 80;
- #2 assert(y == 20) else $error("Subtract assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- assert(carry_out == 0) else $error("Carry assertion failed.");
- assert(overflow == 0) else $error("Overflow assertion failed.");
- // Test 80 - 100
- a = 80;
- b = 100;
- #2 assert(y == 236) else $error("Subtract assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- assert(carry_out == 1) else $error("Carry assertion failed.");
- assert(overflow == 0) else $error("Overflow assertion failed.");
- // Test 80 - 176
- a = 80;
- b = 176;
- #2 assert(y == 160) else $error("Subtract assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- assert(carry_out == 1) else $error("Carry assertion failed.");
- assert(overflow == 1) else $error("Overflow assertion failed.");
- // Test 208 - 112
- a = 208;
- b = 112;
- #2 assert(y == 96) else $error("Subtract assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- assert(carry_out == 0) else $error("Carry assertion failed.");
- assert(overflow == 1) else $error("Overflow assertion failed.");
- // Test 208 - 208
- a = 208;
- b = 208;
- #2 assert(y == 0) else $error("Subtract assertion failed.");
- assert(zero == 1) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- assert(carry_out == 0) else $error("Carry assertion failed.");
- assert(overflow == 0) else $error("Overflow assertion failed.");
- // Test 0++
- operation = INCREMENT;
- a = 0;
- #2 assert(y == 1) else $error("Increment assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 200++
- a = 200;
- #2 assert(y == 201) else $error("Increment assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- // Test 255++
- a = 255;
- #2 assert(y == 0) else $error("Increment assertion failed.");
- assert(zero == 1) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 0--
- operation = DECREMENT;
- a = 0;
- #2 assert(y == 255) else $error("Decrement assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- // Test 200--
- a = 200;
- #2 assert(y == 199) else $error("Decrement assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- // Test 1--
- a = 1;
- #2 assert(y == 0) else $error("Decrement assertion failed.");
- assert(zero == 1) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 12 & 10
- operation = BIT_AND;
- a = 12;
- b = 10;
- #2 assert(y == 8) else $error("AND assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 13 | 15
- operation = BIT_OR;
- a = 13;
- b = 15;
- #2 assert(y == 15) else $error("OR assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 13 ^ 15
- operation = BIT_XOR;
- a = 13;
- b = 15;
- #2 assert(y == 2) else $error("XOR assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test 13 & 15
- operation = BIT_NOT;
- a = 13;
- #2 assert(y == 242) else $error("NOT assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- // Test shift left
- operation = SHIFT_LEFT;
- carry_in = 1;
- a = 136;
- #2 assert(y == 16) else $error("Shift left assertion failed.");
- assert(carry_out == 1) else $error("carry assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test shift right
- operation = SHIFT_RIGHT;
- a = 8;
- #2 assert(y == 4) else $error("Shift right assertion failed.");
- assert(carry_out == 0) else $error("carry assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test rotate left
- operation = ROTATE_LEFT;
- a = 8;
- #2 assert(y == 17) else $error("Rotate left assertion failed.");
- assert(carry_out == 0) else $error("carry assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 0) else $error("Sign assertion failed.");
- // Test rotate right
- operation = ROTATE_RIGHT;
- a = 9;
- #2 assert(y == 132) else $error("Rotate right assertion failed.");
- assert(carry_out == 1) else $error("carry assertion failed.");
- assert(zero == 0) else $error("Zero assertion failed.");
- assert(sign == 1) else $error("Sign assertion failed.");
- #1 $finish();
- end
- always begin
- #1 clock = ~clock;
- end
- endmodule
`timescale 1ns / 1ps
import ALU::*;
module top ();
logic clock;
opcode operation;
logic [7:0] a;
logic [7:0] b;
logic carry_in;
logic [7:0] y;
logic zero;
logic sign;
logic carry_out;
logic overflow;
alu myALU (
clock,
operation,
a,
b,
carry_in,
y,
zero,
sign,
carry_out,
overflow
);
initial begin
clock = 0;
operation = ADD;
carry_in = 0;
// Test 208 + 144
a = 208;
b = 144;
#2 assert(y == 96) else $error("Sum assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 208 + 48 (signed -48 + 48)
a = 208;
b = 48;
#2 assert(y == 0) else $error("Sum assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 80 + 80
a = 80;
b = 80;
#2 assert(y == 160) else $error("Sum assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 100 - 80
operation = SUBTRACT;
a = 100;
b = 80;
#2 assert(y == 20) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 80 - 100
a = 80;
b = 100;
#2 assert(y == 236) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 80 - 176
a = 80;
b = 176;
#2 assert(y == 160) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
assert(carry_out == 1) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 208 - 112
a = 208;
b = 112;
#2 assert(y == 96) else $error("Subtract assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 1) else $error("Overflow assertion failed.");
// Test 208 - 208
a = 208;
b = 208;
#2 assert(y == 0) else $error("Subtract assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
assert(carry_out == 0) else $error("Carry assertion failed.");
assert(overflow == 0) else $error("Overflow assertion failed.");
// Test 0++
operation = INCREMENT;
a = 0;
#2 assert(y == 1) else $error("Increment assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 200++
a = 200;
#2 assert(y == 201) else $error("Increment assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 255++
a = 255;
#2 assert(y == 0) else $error("Increment assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 0--
operation = DECREMENT;
a = 0;
#2 assert(y == 255) else $error("Decrement assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 200--
a = 200;
#2 assert(y == 199) else $error("Decrement assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test 1--
a = 1;
#2 assert(y == 0) else $error("Decrement assertion failed.");
assert(zero == 1) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 12 & 10
operation = BIT_AND;
a = 12;
b = 10;
#2 assert(y == 8) else $error("AND assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 | 15
operation = BIT_OR;
a = 13;
b = 15;
#2 assert(y == 15) else $error("OR assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 ^ 15
operation = BIT_XOR;
a = 13;
b = 15;
#2 assert(y == 2) else $error("XOR assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test 13 & 15
operation = BIT_NOT;
a = 13;
#2 assert(y == 242) else $error("NOT assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
// Test shift left
operation = SHIFT_LEFT;
carry_in = 1;
a = 136;
#2 assert(y == 16) else $error("Shift left assertion failed.");
assert(carry_out == 1) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test shift right
operation = SHIFT_RIGHT;
a = 8;
#2 assert(y == 4) else $error("Shift right assertion failed.");
assert(carry_out == 0) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test rotate left
operation = ROTATE_LEFT;
a = 8;
#2 assert(y == 17) else $error("Rotate left assertion failed.");
assert(carry_out == 0) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 0) else $error("Sign assertion failed.");
// Test rotate right
operation = ROTATE_RIGHT;
a = 9;
#2 assert(y == 132) else $error("Rotate right assertion failed.");
assert(carry_out == 1) else $error("carry assertion failed.");
assert(zero == 0) else $error("Zero assertion failed.");
assert(sign == 1) else $error("Sign assertion failed.");
#1 $finish();
end
always begin
#1 clock = ~clock;
end
endmodule
With the ALU working I’ll call it a wrap for this post. If you have any questions or feedback be sure to leave a comment. Keep tinkering!