This hexadecimal calculator is a demonstration of a VHDL project designed for the Digilent A7-100T FPGA board, built through the Xilinx Vivado WebPACK Suite. The core program uses three VHDL source files (hexcalc.vhd, keypad.vhd, leddec16.vhd) and one Vivado constraint file (hexcalc.xdc) together with a Digilent PMOD KYPD hardware extension in the JA port to implement a simple calculator operating in Base16.
Once synthesizing, implementing and programming the FPGA with the baseline program, the FPGA LED panel will default to a 4-bit hex representation of 0, awaiting an input from the PMOD KYPD (shown to the left). As a user types in the first operand values, it will appear on the lefthand LED panel and move towards the right, creating a big-endian hex representation of the data value (user must enter the least significant digit first; most significant digit is stored at 'lowest memory location').
Once the first operand is entered, the user can press the FPGA's BTNU button, assigned as the addition (+) operator for our calculator. The 4-bit value will disappear, and the system will be ready for the input of a second operand, following the same process as the first operand. Once fully entered, the user can press the BTNL button, assigned as the execute operator (=), to execute the hexidecimal addition - the summed value will be displayed to the screen
A few notes:
This project was completed in self-quarantine during the 2020 global COVID-19 pandemic - the necessary PMOD KYPD hardware to run the hexadecimal calculator program was inaccessible to the designer. The following project notes are not tested to the satisfaction of the engineering design process. Rather, they represent suggested additions to the program based on fundamental VHDL principles.
The first request from the client was to remove leading zeros in our operand values. When running the baseline program, the decimal value of 18 would appear in hexadecimal as "1300". However, this value is misleading in the best case, and erroneous in the worst case, as the zeros represent empty placeholders, rather than proper digits (0x13=18, but 0x1300=4864). Therefore, replacing these 'leading zeros' with empty space should make the represented value more clear to the user.
Suppressing these leading zeros can be succinctly addressed in the leddec16.vhd source VHDL file, by modifying the state of the anode standard logic output signal at the conclusion of the architecture's body, as shown to the left. The anode is essentially a bitmask for our four LED displays - a given digit will be ON if its bit if OFF in the anode signal. The commented-out code snippet shows the initial setup that led to leading zeroes; the "dig" signal takes on one of four states, each corresponding to a specific digit to turn on. The default '1111' exists at the end to catch errors, but during normal runtime, it will never get triggered as 'dig' will never take a state beyond 00,01,10,11 - all displays are always on.
To suppress leading zeroes, we must add a condition to each of these branches - checking the 2-bit 'dig' signal is insufficient to determine if the digit is on or off. If a given digit is to be ON, we must confirm that every bit between it and the most significant bit (MSB) is zero, i.e. we will suppress digits past our most significant digit of value. We add an 'AND' logical statement, and sample a range from our standard input vector 'data' - this signal contains 16 bits and represents the full 4-digit hex value. In order for the digit to be ON, we compare the range between this digit and 'data's MSB to a hex bit string literal expressing the proper length of 0 that should exist. If the 'not equals' boolean returns false, then the anode will be set to its default value, and the digit will not be turned on. The functionality of this edit seems to be confirmed when programming the FPGA - the initial value of '0000' turns into '____', as the 4 active digits turn off:
The second client request was to include a subtraction function on the calculator - by default, the only instructions included were addition (BTNU Button), execute (BTNL Button), and clear all states (BTNC Button). In the proposed new version, the BTND button would be used to indicate subtraction in the same manner the BTNU button is used to indicate addition; once both operands are input, the same BTNL button would be used to execute the operation and display the difference.
The first necessary edit will be to uncomment line 13 in the hexcalc.xdc constraint file, allowing us to measure input from the BTND button (we will be using the default value of BTND, but this name may be changed here and in the following sections).
Next, a new signal must be added to the hexcount entity interface specification found within hexcount.vhd - this port will serve as an input to our component for the signal to perform subtraction. See the full entity declaration with the new subtraction signal added in the top code snippet.
Within the same source file, a new signal must be added to the architecture signal definition section. This signal is responsible for storing the state of our mathematical operation - when the operation is addition, its state will be ON, and when the operation is subtraction, its state will be OFF. This signal, named 'operation_addsub', is shown to the right among the hexcount architecture signal definitions:
Then, we must modify the conditionals in the ENTER_ACC state to test for subtraction as well as addition. We can find these within the sm_comb_pr process, inside the pr_state case statement (used to determine which state we are in based on pressed buttons). This code can be found in the third righthand snippet - we add a single line under the existing addition conditional to store the state in our new 'operation' signal, and a new 'ELSIF' conditional for the new subtraction operation.
A final edit must be made farther down the same case statement, in the ''ENTER_OP' branch. This is where the mathematical operation is actually executed; the first operand is stored as 'acc' and the second operand is stored as 'operand'. Initially, a single IF statement checked if bt_eq was ON; if it was, addition was performed between the operands and the state was changed to SHOW_RESULT. Now, an additional ELSIF statement has been added and both branches are compared to the 'operation' signal to determine whether our operation is addition or subtraction and perform the correct operation.
Note: this calculator has no fail-safe for overflow (values > 65535) or negative results, so avoid if possible. Once the PMOD hardware is available, these contingencies can be tested and avoided