# Beginning Logic Design – Part 5

Hello and welcome to Part 5 of my Beginning Logic Design series. In this post I will begin building an 8-bit ALU (Arithmetic Logic Unit). Through building this ALU I will cover a few more topics on writing SystemVerilog and using Vivado to simulate the designs. As you learn more SystemVerilog, I suggest keeping this cheat sheet handy as a quick reference to notes regarding language syntax.

# ALU Model

An ALU is a very common component in various processing systems. The common ALU design takes an input opcode (operation code) to select one of various math or logic operations. Based on the operation selected, one or more inputs will be taken and the result of the operation will be output. ALUs may also read and write status signals based on the operation being performed.

The ALU I’ll be designing in this post will be influenced by the classic 6502 processor that’s at the heart of the NES, Apple II and many other early computer systems. This ALU with support 12 operations:

• Arithmetic Operations
• 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

This ALU will also have a few status signals, on the input side it will just have `carry in`, on the output side we’ll have `carry out`, `zero`, `sign` and `overflow`. I’ll dive a bit more into each of these operations and how the interact with status signals as we implement them.

# Building Modules

To get started I’ll fire up Vivado and make a new project that I’ll name `my-alu`. I’ll choose `RTL Project` for the Project Type and will leave `Do not specify sources at this time` unchecked to make a couple files right away.

In the Add Sources page I’ll use the `Create File` button to make two `SystemVerilog` files: `top` and `alu`. It’s easy to accidentally leave the file type on `Verilog` and the syntax for the older Verilog standard is a little different, so be sure to choose SystemVerilog.

For the Add Contraints page I will just hit next. As before for the Default Part page, I’ll select the `xc7a35ticsg324-1L` from the Search drop down to set as the default. After hitting finish I’ll hit OK to skip the module definition prompts.

I’ll then clean up my `top.sv` to look like this:

1. `timescale 1ns / 1ps
2. module top ();
3. endmodule

And my `alu.sv` as:

1. `timescale 1ns / 1ps
2. module alu ();
3. endmodule

My `top` module will help me test my ALU, and the `alu` module will eventually be my fully built ALU.

I want this ALU to work synchronously, so I will add an input clock. I’ll also add 2 8-bit inputs and 1 8-bit output to the `alu` module. To define an 8 bit `logic` variables, I’ll use the syntax `[n:0]` to give it a width of `n+1` bits, in this case `7` to give me `8` bits.

1. `timescale 1ns / 1ps
2. module alu (
3. input logic clock,
4. input logic [7:0] a,
5. input logic [7:0] b,
6. output logic [7:0] y
7. );
8. endmodule

With those inputs and outputs defined, I’ll start to add the `alu` to the `top` module.

I’ll first define a few internal `logic` variables to use to connect to the inputs and outputs of the ALU. Then, to instantiate the ALU, I’ll reference the module name `alu` then name my instance `myALU` and in parenthesis, in the same order as defined in the `alu.sv` file,  I’ll provide my variables to use as inputs and outputs.

1. `timescale 1ns / 1ps
2. module top ();
3. logic clock;
4. logic [7:0] a;
5. logic [7:0] b;
6. logic [7:0] y;
7. alu myALU (
8. clock,
9. a,
10. b,
11. y
12. );
13. endmodule

Now `myALU` exists within my `top` module, and I have hooked up some inputs and outputs to it.

# Setting the Clock

To set the clock, I am going to use some SystemVerilog syntax that is non-synthesizable. This means that actual hardware designs cannot be made from it, it exists in the language specifically for simulation and testing.

I’ll use an `initial` block to set all my input variables to 0 at the start of simulation.

1. initial begin
2. clock = 0;
3. a = 0;
4. b = 0;
5. end

Then I’ll add an `always` block that will repeatedly loop during simulation to invert my `clock` variable. The `#<t>` syntax adds a delay of `t` steps before the statement is executed.

1. always begin
2. #1 clock = ~clock;
3. end

In this case, I’ve used `#1` and with the `timescale` of `1ns / 1ps` this statement will be delayed by `1ns` in simulation.

Here’s how this leaves my `top.sv` file

1. `timescale 1ns / 1ps
2. module top ();
3. logic clock;
4. logic [7:0] a;
5. logic [7:0] b;
6. logic [7:0] y;
7. alu myALU (
8. clock,
9. a,
10. b,
11. y
12. );
13. initial begin
14. clock = 0;
15. a = 0;
16. b = 0;
17. end
18. always begin
19. #1 clock = ~clock;
20. end
21. endmodule

I now want to `Run Simulation` to verify my clock is toggling on and off as I expect it to. Before I do that though, the simulator in Vivado by default runs for `1000 ns`, which is relatively long for this design. I’d like to reduce that to `20 ns` for now.

I’ll go to `Settings` in the `PROJECT MANAGER` portion of the `Flow Navigator` on the left side of Vivado. Then within `Project Settings` I’ll select `Simulation`, open the `Simulation` tab and set `xsim.simulate.runtime` to `20 ns`.

I’ll save my changes there and use `Run Simulation->Run Behavioral Simulation` to fire off the sim. After hitting the zoom fit icon I can validate it does flip every nanosecond.

# Enumerations in SystemVerilog

One of the advantages of using SystemVerilog instead of plain ol’ Verilog is being able to define enumerations. For this ALU, I need to create an input that can select one of the 12 operations I plan this ALU to support. I’ll use unique binary numbers to represent each operation in hardware and can use an enumeration to reference each operation in code by a more readable name.

I’ll also use `typedef` as you would in a language like C to use variables that should be set to a member within my enumeration. I’ll add `logic [3:0]` after `enum` to ensure the new type only uses 4 bits.

1. typedef enum logic [3:0] {
3. SUBTRACT,
4. INCREMENT,
5. DECREMENT,
6. BIT_AND,
7. BIT_OR,
8. BIT_XOR,
9. BIT_NOT,
10. SHIFT_LEFT,
11. SHIFT_RIGHT,
12. ROTATE_LEFT,
13. ROTATE_RIGHT
14. } opcode;

With this `enum` defined, I’ll add `input opcode operation` to my `alu` module’s list of ports.

1. module alu (
2. input logic clock,
3. input opcode operation,
4. input logic [7:0] a,
5. input logic [7:0] b,
6. output logic [7:0] y
7. );
8. endmodule

Now, within the `alu` module definition, I’ll use an `always_ff` block to implement synchronized behavior. I’ll use `@ (posedge clock)` to indicate that I want this block of behavior to occur on every `positive edge` (rise) of my `clock` signal.

Within that `always_ff` block, I will use `case` to vary the behavior based on what `operation` is set to, for now I’ll only add the logic for ADD.

1. always_ff @ (posedge clock) begin
2. case (operation)
4. y <= a + b;
5. end
6. endcase
7. end

In this situation, I use `<=` instead of `=` to store this within a register, which is like a D flip-flop with multiple bits, that will have its output wired to `y`. This keeps my output synchronized with my input.

I’m just about ready to test the addition operation. In order to reference the `opcode` type and enumeration within the `top` module, I need to `package` that up so I can use the `import` statement to refer to it.

I’ll wrap my typedef in `package ALU;``endpackage` to encapsulate it in a package named `ALU`. Then I will use `import ALU::*;` to import all of it for use in my `alu` module.

Here’s how this leaves my `afu.sv`

1. `timescale 1ns / 1ps
2. package ALU;
3. typedef enum logic [3:0] {
5. SUBTRACT,
6. INCREMENT,
7. DECREMENT,
8. BIT_AND,
9. BIT_OR,
10. BIT_XOR,
11. BIT_NOT,
12. SHIFT_LEFT,
13. SHIFT_RIGHT,
14. ROTATE_LEFT,
15. ROTATE_RIGHT
16. } opcode;
17. endpackage
18. import ALU::*;
19. module alu (
20. input logic clock,
21. input opcode operation,
22. input logic [7:0] a,
23. input logic [7:0] b,
24. output logic [7:0] y
25. );
26. always_ff @ (posedge clock) begin
27. case (operation)
29. y <= a + b;
30. end
31. endcase
32. end
33. endmodule

For my `top` module; I’ll also add the `import` line, add an internal variable for `operation` and provide it to `myAFU`. I’ll set `operation` to `ADD` within my `initial` block and add a few more delayed operations to change `a` and `b` at different times within the simulation.

Let’s see how this works out.

I have an easier time verifying the math when the numbers are in decimal format. I can select multiple signals in the wave viewer by the first and holding shift and clicking the last, then right click and go to `Radix->Unsigned Decimal` to change the number format shown.

As you can verify in the simulation, on every rising clock edge the `y` output is updated to show the result of the addition of `a + b`!

With a lot of the foundation set for the ALU I’ll end the post here. In the next post I’ll finish implementing the ADD operation by adding status signal handling to help identify some special conditions that may result from the operation and how to setup better testing to validate the design.  As always, if you have any questions or feedback please leave a note in the comments. Keep tinkering!