One of the main goals of Project 6: Stack-based Calculators was to learn and become more familiar with stacks and memory by utilizing a RAM. A RAM stands for Random Access Memory and is crucial for temporarily storing information and memory. The RAM was used to execute the stack-based calculator. The calculator has the ability to perform four different functions: addition, subtraction, multiplication, and division. I was able to create the RAM through quartus and code the stack-based calculator in Calculator.vhd.
How to Use the Calculator:
To use the Calculator, the user sets the value switches to the binary value of their choice. Then, they press the capture button(button 2) to move the number into the MBR. By doing so, the number should show up on the 7-segment display. Once they see the number on the display, they should click the Enter button(button 3). The user should then set the value switches to the second binary number of their choice. After doing so, they should press the capture button to move the second number into the MBR, which should show up on the 7-segment display. The user should choose an operation with the operation switches. (00 = addition, 01 = subtraction, 10 = multiplication, 11 = division). Finally, the user should press the action button(button 4) to add the MBR to the top value of the stack. The outcome of the operation should show up on the seven-segment display. To reset, the user should press button 1.
Stacker.vhd GHDL output:
State Machine Diagram:
Top-level design: Calculator.vhd
|clk: clock signal||digit0: the output value for the seven-segment displa||state: calculator states|
|reset: button 1, the reset signal||digit1: the output value for the seven-segment display||RAM_input|
|b2: button 2, capture||stackview: stack debugging||RAM_output|
|b3: button 3, enter||RAM_we: RAM write enable signal|
|b4: button 4, action||stack_ptr: stack pointer|
|op: operation switches||mbr: memory buffer register|
data: the inputted binary numbers for calculation
|tempmbr: temporary memory buffer register|
In addition to the various inputs, outputs, and internal signals, Calculator.vhd was also port mapped to memram.vhd and sevenSegmentDriver.vhd. This is because memram.vhd provided the RAM necessary for the four-function calculator and sevenSegmentDriver.vhd was necessary to make the hexadecimal numbers show up on the seven segment display. The different states listed in Calculator.vhd are "000", "001", "100", "101", "110", "111", and others. When the state was "000" and the capture button was pressed, the data signal would be assigned to the MBR and the next state would be "111". When the state was "000" and the enter button was pressed, MBR would be assigned to the RAM_input and '1' would be assigned to RAM_we. The next state would be "001". When the state was "000" and the action button was pressed, the stack pointer would decrement if it was not 0. It would then move to state "100". At "001", the RAM_we would be assigned 0 and stack pointer would increment. Then it would move to state "111". State "100" moves on to state "101" and state "101" moved on to state "110". When the state is "110" there are a series of if-else statements carrying out all the addition, subtraction, multiplication, and division operations. To add, I simply added mbr and the RAM_output. For example, mbr <= std_logic_vector(unsigned(mbr) + unsigned(RAM+output)). To subtract, I subtracted the mbr from the RAM_output. To divide, I simply divided the RAM_output and mbr. Multiplying was trickier. Because multiplying two 8 bit numbers would produce a 16-bit number, I had to create a temporary register. After multiplying the mbr and RAM_output, I stored it in tempmbr which was a 16-bit std_logic_vector. Then, in state "111", I had mbr take the 8 low bits of tempmbr. After the operations in state "110", the next state was "111". If all the buttons were released, the next state would be "000".
Extension 1: Adding more operations = calculating the power of 2, 3, and 4 of any number inputted by the user
In order to calculate the powers of 2, 3, and 4, I multiplied multiple unsigned(mbr) according to the power. Then I assigned it to a tempmbr. I made multiple tempmbrs. This is because each time the unsigned(mbr) is multiplied, the number of bits increase. At state "111" I had if else statements assign the 7 low bits of the tempmbr to the mbr depending on the operation.
Extension 2: Adding more operations = calculating the remainder of two numbers
In order to calculate the remainder of two numbers, I utilized "rem". For example: "unsigned(RAM_output) rem unsigned(mbr)"
Extension 3: Write a test bench program in VHDL that you can use to test your circuit with GHDL
My first couple attempts After trying to fix it by making buttons push on the rising clock edge
Using the stackertest as a model, I made a GTKwave of my Calculator with Calculatortest.vhd. The Calculatortest tests the following: 3, capture, enter, 5, add, action, enter, 4, capture, divide, action, enter, 3, capture, multiply, action, enter, 1, capture, subtract, action. After outlining this, carefully spaced out each action with the nanoseconds. This was extremely tedious. After doing so, I also added a value output so that the value of each step could be viewed. However, after talking with Bruce, I realized that my buttons were not pushed on the clock's rising edge. As a result, I tried fixing the buttons by making them pushed down on the rising edge (shown above). However, after spending three hours trying to get the right outcome, I could not get it right. I have tried very hard on this extension and have learned a lot despite the fact that I was not successful.
People Worked With: