This repository contains the circuit for a basic 8-bit ripple adder and its complementary accumulator register. The adder assumes 2s complement inputs and thus supports addition and subtraction. It pushes the result to the bus via tri-state buffer. It also includes a zero flag to support conditional operation as well as a carry flag. These flags are synchronized to the rising edge of the clock and are updated when the adder outputs to the bus.
The accumulator register functions to store the output of the adder. It is synchronized to the positive edge of the clock. The accumulator loads and outputs its value from the bus and is connected via tri-state buffer. The accumulator’s current value is always available as an ouput (and usually connected to the Register A input of the ALU) These two modules work in tandem and are a part of a larger project which includes peripheral and control blocks to ultimately create a functioning, basic, 8-bit CPU.
Name | Verilog | Description | I/O | Width (bits) | Active |
---|---|---|---|---|---|
clk | clk | Clock Signal | Input | 1 | Rising edge |
bus | bus | Connection to bus | IO | 8 | NA |
load | nLa | Load from Bus | Input | 1 | 0 |
enable_out | Ea | Output to Bus | Input | 1 | 1 |
Register A | regA | Accumulator Register | Output | 8 | NA |
reset | rst_n | Reset Signal | Input | 1 | 0 |
Name | Verilog | Description | I/O | Width (bits) | Active |
---|---|---|---|---|---|
clk | clk | Clock Signal | Input | 1 | Rising edge |
enable_out | Eu | Output to Bus | Input | 1 | 1 |
Register A | reg_a | Accumulator Register | Input | 8 | NA |
Register B | reg_b | Register B | Input | 8 | NA |
subtract | sub | Perform Subtraction | Input | 1 | 1 |
bus | bus | Connection to bus | Output | 8 | NA |
Carry Out | CF | Carry-out flag | Output | 1 | 1 |
Result Zero | ZF | Zero flag | Output | 1 | 1 |
The waveform in Figure 1 shows the loading and output functionality of the accumulator (RegA). The yellow marker displays the load functionality of the accumulator: On the rising edge of the clock, when nLa is low, the value from the bus is loaded onto the RegA.
The red marker displays the output functionality of the accumulator: On the rising edge of the clock, when Ea becomes high, the value from the accumulator is pushed onto the bus.
Figure 1: Accumulator Load onto bus and push onto bus
The waveform in Figure 2 demonstrates basic addition done by the adder. Note that at the red marker, Sub is low, thus addition is being performed. The addition is done asynchronously, and the value of Sum goes from 60 (60 + 0) to -10 (60 + -70). At the yellow marker, Ea is high, and thus the result of the addition is pushed onto the bus. Note that the Sum signal is internal.
Similarly, the waveform in Figure 3 demonstrates basic subtraction by the adder. Note that at the red marker, Sub is high, thus subtraction is being performed. In this case, the rest 9-11 is calculated asynchronously resulting in -2. At the yellow marker, when Eu is set high, the result is pushed onto the bus.
Figure 2: Addition and Output onto Bus
Figure 3: Subtraction and Output onto Bus
The waveform in Figure 4 demonstrates the functionality of ZF (zero flag). As described above, at the red marker, the subtraction 42-42 is performed, resulting in 0. The result is the pushed to the bus when Ea is set high. At the rising edge of the clock, when Ea remains high, ZF is also made high, indicating that the result of the operation (in this case, subtraction), was zero.
Figure 4: Zero Flag Functionality of Adder
These modules have been tested under six Testbenches. For the purposes of the tests, all random numbers are between 0 and 255. The tests are briefly detailed below:
This test computes the addition of 50 random pairs of numbers and checks to see if the addition was correct.
This test computes the subtraction of 50 random pairs of numbers and checks to see if the subtraction was correct.
This test computes either addition or subtraction (randomly determined before each operation) of 50 random pairs of numbers and checks to see if the result is correct.
This test loads a random number from the bus onto the accumulator, and checks whether the values on the bus and in the accumulator match.
This test loads a random number from the bus onto the accumulator and checks whether the values on the bus and in the accumulator match. It then outputs the value of the accumulator onto the bus and checks whether the values on the bus and in the accumulator match as expected.
This test performs the accumulator_test_randint_out test consequently with 25 randomly chosen non-repeating values
# | Input | Output | Bidirectional |
---|---|---|---|
0 | bus[0] if ~(Ea|Eu) | bus[0]/regA[0], bus_regA_sel = 1/0 | out_ZF |
1 | bus[1] if ~(Ea|Eu) | bus[1]/regA[1], bus_regA_sel = 1/0 | out_CF |
2 | bus[2] if ~(Ea|Eu) | bus[2]/regA[2], bus_regA_sel = 1/0 | in_sub |
3 | bus[3] if ~(Ea|Eu) | bus[3]/regA[3], bus_regA_sel = 1/0 | in_Eu |
4 | bus[4] if ~(Ea|Eu) | bus[4]/regA[4], bus_regA_sel = 1/0 | in_Ea |
5 | bus[5] if ~(Ea|Eu) | bus[5]/regA[5], bus_regA_sel = 1/0 | in_nLb |
6 | bus[6] if ~(Ea|Eu) | bus[6]/regA[6], bus_regA_sel = 1/0 | in_nLa |
7 | bus[7] if ~(Ea|Eu) | bus[7]/regA[7], bus_regA_sel = 1/0 | in_bus_regA_sel |