Integrated Circuits - Making a 4-Bit Calculator (Part 2)
The most important part of a calculator is undoubtedly the operations. This is the second post of hte integrated CIrcuits series, where we will be assembling the rest of our calculator. We will be making use of the electronic components and the circuit symbols explore previously to see how a calculator IC is designed. Kindly note that a lot of what is mentioned here is my own critical thinking and problem solving (anda lot of it is conventional, found out through research), so it might be subject to errors.
Table of Contents:
Converting Decimal numbers to Binary
Simple 4-bit Addition using Logic Gates
Simple 4-bit Subtraction using Logic Gates
Simple 4-bit Multiplication using Logic Gates
Making the display
DISCLAIMER: The circuit images shown are subject to copyright.
Convert Decimal Numbers to Binary
Amazing progress so far, now that we understood all this theoretical bit, we can now begin actually working on our calculator design. Since we are making 4-bit calculator, let us first understand what that means. 4-bits numbers are the ones which contain four digits when converted into binary. So, these are decimal numbers 0-15. These are the binary conversions for simple four numbers:
What we essentially want do is, since there are always going to be four digits in our binary number, we want to have 10 wires for our decimal digits 0-9, and four wires for our binary number. We want our decimal wires to get triggered (like a switch) at the tap of the user's key. Then we want to connect our decimal wires to the binary, depending on the above binary to decimal conversions:
I know, confusing, I apologise for the ambiguity. If you understand this diagram, you will see that pressing a particular button will map the decimal onto the binary wires in the 'ABCD' format, depending on the 1s and 0s in the number.
However, this set up does not yet cater to all four-bit numbers. Right now it only works for single digit-numbers, so we still need to figure how to work with numbers 10-15. For that we will have to explore the concept of registers and flip-flops, which enable a calculator to have memory and storage.
Flip-flops are components or sequential logic circuits just like logic gates, and their purpose is to store a single bit of data (a 0 or a 1). Registers are nothing but a collections of flip-flops to store multi-bit data. There are two common types of flip-flops, one which is used for permanent storage made to withhold its charge even when the device is powered off, and the other is a 'dynamic' flip-flop which stores data temporarily using capacitors. To achieve our purpose of entering multi-digit numbers, we will be using dynamic flip-flops.
One thing to think about here is that once a digit is entered into our calculator we want the number to be stored in a flip-flop and our decimal wires to reset. Then when the other number is input, we want our original flip flop to reset, store the new input, and send the data over to the next flip-flop (since that digit will now have the tens position). Thus, since we want to shift data, and we will be using the parallel-in parallel-out shift register, which uses four d-type flip flops (d stands for data).
How a data flip flop works is basically like this, it has four ports: the Clock which is like an enable feature and the flip flop only changes state if the clock is active, the Data input which is the data value that the flip-flop will store, the output which is the data output or the stored value, and the inverse of the data output. A data flip-flop looks something like this:
I will not go into detail about how the data flip-flop is made. The D here is the Data input, Q is the output, Q' is the inverse of the output and the triangle is the clock. However, since we want to store four-bit data, we will need four such data flip-flops for our first digit and four more for our next digit, and since we want to deal with all 4-bits together (as they collectively make up the number we want to store), we will be using 4 different 2-bit Serial-in Parallel-out shift registers, one for each bit, and each shift register will contain two flip flops, one for each digit. What SIPO registers do is, they take in input bit-by-bit serially, and output them all together which is exactly what we want. This looks something like this:
What it does is, when the clock is powered on (note that it will only remain active for a second since the user will not press-and-hold the button), it inputs the 4-bits of data into the first flip flop of each register and stores that information, all these register combining to output our 4-bit digit. Then on the second pulse of the clock (press of second button), the existing data on the first flip flop of our register moves into the input of our next flip flop of the register, and the new data is stored immediately into the first flip flop. The entirety of this is then sent as an output from each register, each register sending over 2-bits of data.
However, this does not entirely solve our problem. We now have separate data for both digits (8 bits of data). What we want to do now is figure out how to use these two digits and combine them in a single number. The number we have right now is in the BCD or Binary-coded Decimal form. An example of BCD is 12, which is expressed as 1100 in binary, but 0010 0001 in BCD, where 1 and 2 of the 12 are written separately. We need to convert it into regular binary form so that it is useful to the operators we will makes in the following steps. We can do this using a 74184 IC which is a BCD-to-binary converter (we will do a tutorial on this later), by hooking two of these up in the following circuit:
In the above circuit we have our BCD number IJKLMNOP taken from our shift registers above, where MNOP is the units digit an IJKL is the tens digit. The above circuit converts this into ABCDEFGH - the binary number that we can now use to perform operations on.
One thing to note here is that although we did not actually need all this conversion since we are already aware that our tens digit will be 0 or 1 (it's a four-bit calculator) and that A, B, C, D, I, J and K will always be 0, it is still a good practice for learning's sake to do things in a scalable manner, so this circuit currently works for all two digit numbers possible, and can now be extended for as many place values as we want by hooking up more and more 74184s. However for our purposes, we will be using only EFGH as the input.
And voila! Just like that, we are now able to input multi-digit numbers in our calculator! We will be working on the display a little later, first let us start with basic arithmetic operators.
Simple 4-bit Addition in a Calculator
Great job coming so far! Without beating around the bush too much, let us jump straight to 'sum' business (pun intended). So we now have our first number for the addition, and we will be performing our addition bit-by-bit. Before we get into how we will deal with the second number for the addition, let me just explain to you how binary addition in a calculator works, using something called Half-Adders and Full-Adders.
In bit-by-bit addition, we are going to take two number as inputs which are the addends, and two as output which are the sum and the carry forward. So single-bit binary addition essentially works like this:
0+0 gives us Sum: 0, Carry: 0
0+1 gives us Sum: 1, Carry: 0
1+0 gives us Sum: 1, Carry: 0
1+1 gives us Sum: 0, Carry: 1
With this information, you are now probably starting to relate it with the Logic Gate truth tables that we explored earlier. The sums for the addition follow the XOR logic gate truth table, and the carry uses the AND logic gate. With this information, we can now add using our circuit, using a Half-Adder as follows:
So using this circuit, we know have one output which is the sum of A and B, and another output which is the carry forward (to be added to the next bit) as a result of adding A and B.
We can now do this addition four time for each of the 4 bits in our number. So, in the next addition iteration, we will be adding the next bits of both our numbers. However, as you can see, this circuit has not set-up to add the carry forward to our sum as well. That is the reason this is not currently capable of performing complete addition. For that we use a Full-Adder, which is actually nothing but a combination of two Half-Adders:
Here, after we have added A and B using a half-adder and obtained their sum and carry, we are using another half-adder to add this sum to the carry we received as input. This produces another set of carry and sum for us. The new sum is the one we send to the display. As for the carry, we now have two carries, and we put both of them through an OR gate, so that if either of them are 1, then the final carry for our next addition iteration becomes 1. And voila! We can successfully add single bit numbers!
In order to implement the final four bit addition that we actually require in our calculator, we simply need to group together four such Full-Adders. So if we have two numbers converted into binary, ABCD and EFGH respectively, we can add them in the following manner and obtain a final binary 4-bit or 5-bit sum MIJKL:
Phew! That is very long and looks so exhausting, no? Nevertheless, if you look closely, it is nothing but a combination of four different full adders, a set of input number wires, and a set of out put number wires. So we input numbers into the adders bit-by-bit, display each sum as we receive it, and pass the carry onto the next adder. One thing to note here is that we might sometimes end up having 5-bit output, which is when we have a carry even after the fourth iteration of addition. In this case, that carry becomes our 5th digit in our binary number and that is why we have five wires in our output sum.
Storing the Second Number
Great job! Now we can successfully perform addition. The next problem we will solve, is the storing of numbers and triggering this addition. As we know, we only have one interface for the user to enter numbers, so as soon as the user presses on the add button, we want to store the first number in a shift register, trigger the addition operation, and prepare to take a second input in another register. For this, we will use the same method as we did while inputting double-digit numbers, i.e, we will use Serial-In Parallel-Out Shift Registers. Our final circuit for taking in two inputs will look something like this:
Here we are taking the input we received from our decimal to binary conversion and saving it in our the first flip flop of our registers when the user presses add (triggering our clock). Then, when the user enters the second number and presses the 'equal' sign (we will work on this more later, in the triggering operations section), the second number is stored in our register and both the numbers are parallely sent out of it. After this, we can simply connect our ABCD and EFGH here, to our inputs in the addition circuit above (the final detailed circuit will be shown at the end).
Simple 4-bit Subtraction
Bravo for making it so far; now that we have done addition, subtraction won't be a lot more complicated. Note that in this tutorial we will be focusing only on positive subtraction (bigger number minus a smaller number). Just like addition, we will be performing our subtraction bit-by-bit, and producing a 'difference' and a 'borrow' after each iteration. How binary subtraction works is:
0-0 gives us Diff: 0, Borrow: 0
1-1 gives us Diff: 0, Borrow: 0
1-0 gives us Diff: 1, Borrow: 0
0-1 gives us Diff: 1, Borrow: 1
As we can see, the difference in binary subtraction follows the same XOR logic truth table as our addition. For borrow however, the situation is slightly different. What we want in the case of borrow, is to borrow 1 only and only if our first input (input A) is 0, while the second input B is 1. We can model subtraction using Half Subtractors.
In order to perform bit-by-bit subtraction, we can make use of an AND gate, and an inverter / NOT gate in this way:
In this circuit, the difference works the same as the sum in our addition circuit. For the borrow, the only time it will return a 1 as a borrow, both of the wires connected to it are. Since we are inverting the state of A, we require A to 0 and B to be 1 in order to return a borrow, which is exactly what we found out in our truth table above. With this, we can now perform bit-by-bit subtraction.
Just like Addition, Full Subtractors are nothing but a combination of two half subtractors, and an extra OR gate, which incorporate the borrow from our previous iterations. Let us look at the circuit first and try understand what is happening:
So what we are doing here is, first we subtract A and B, and we take the Borrow output. Then we subtract the previous borrow from the difference of A and B, taking the borrow from that for the next iteration. And in this manner, we now have a difference to display and a borrow to send over.
Just like addition, all we need to do in order to perform 4-bit subtraction is connect 4 different full subtractors in parallel. So, if we have to subtract binary number EFGH from ABCD (ABCD-EFGH), then we will be receiving an output of IJKL as follows:
Note that here we do not need to worry about getting a borrow at the end of the last iteration since we are only dealing with positive outputs right now. We will cover negative in some other tutorial. Anyway, so this circuit essentially allows us to now subtract 4-bit binary numbers without a problem! In order to store multiple numbers, we can add shift registers in a manner similar to what we did in addition (cautiously considering the order of input).
Simple 4-bit Multiplication
The next feature we have to implement in our calculator circuit is multiplication. You should from elementary school Math classes that Multiplication is nothing but repeated addition. This is exactly the phenomenon we will be using to create our multiplication in our calculator, since multiplication is more tedious and requires more iterations of the same number than our previous two operations. So, when we multiply two 4-bit binary numbers, we can obtain an output upto 8-bits. Our single-bit multiplication truth table looks something like this:
1 X 1 = 1
1 X 0 = 0
0 X 1 = 0
0 X 0 = 0
By now you you must have identified that this follows the AND truth table. And as you can see, this operation does not have any carry or borrow, which makes things a lot simpler. (or does it?)
Binary 4-bit Multiplier
We can make a simple binary multiplier through the following circuit, with the use of the 4-bit adders that had produced earlier. So if we have a number ABCD and we multiply it with a number EFGH, we get an output (P0P1P2P3P4P5P6P7):
Let me quickly explain what is happening here. You might be wondering why are using 4-bit adders, since we can clearly see that the addition and multiplication truth tables are different. Well, if you remember the long multiplication from elementary school, you will know that we multiply each digit of input A with each digit of input B, and add all the partial products which we obtain. So, in the above circuit we are obtaining our partial products in each stage using AND logic gates. Then we are inputting these partial products for all bits of our input A into 4-bit adders to obtain our final product, shifting our number one place value at a time. Once you look at the circuit and do the multiplication yourself, it will be much clearer. And with that, we are done with multiplication in our calculator! We can use the same method to take two inputs form the user as the previous to operations.
Here what we want to do is connect our four wires (which contain our input numbers converted from decimal to binary), to the shift registers of our four operations in a manner that the correct operation is triggered at the push of the appropriate button. We can do that with the following circuit, taking the example of addition:
So what is essentially happening here, we are controlling the clock of our data registers for each of the operations, by making use of another data register to 'remember' the operation the user wants to do. So our clock is basically triggered when, either the operation sign is clicked (save first input), or the equal sign (save second input) is clicked. However, we want to make sure that when the equal sign is clicked, the clock for the correct operation is triggered. For that, we store the value of the operation in d-type flip flops. And the clock for the operation is triggered only when the output of the operator flip-flop is true AND the equal sign or the plus sign is pressed.
We can then simply replicate this for the other two operations, subtraction and multiplication
Making the Display
Voila! With that, we have successfully concluded preparing our calculator which is able to to do simple addition, subtraction and multiplication! The last thing we will be covering in this tutorial is how to display our binary output from any of the above operators, into a number which can be displayed on a LCD screen. The 7 segments display is the standard way of displaying something on calculators, where each digit in decimal form is displayed by lighting up 7 segments depending upon the digit.
So, here is basically the segments that we want to light up based on the digits:
Bottom: 2, 3, 5, 6, 8, 9, 0
Bottom-Right: 1, 3, 4, 5, 6, 7, 8, 9, 0
Bottom-Left: 2, 6, 8, 0
Top: 2, 3, 5, 6, 7, 8, 9, 0
Top-Right: 1, 2, 3, 4, 7, 8, 9, 0
Top-Left: 4, 5, 6, 8, 9, 0
Center: 2, 3, 4, 5, 6, 8, 9, 0
Beginning with single digit display, let us now take a look one-by-one at how we can implement the logic for each of the segments above:
LCD Bottom Segment Connection
The logic that we modelled here is, a) B must true and C & D must be same, OR b) one of A and B must be false, C must 0 and D must 1. If either of these conditions are met, only then will the bottom segment NOT light up. In all other cases the bottom segment will light up. In this circuit you can see the Bottom Segment will only light up for digits which have their binary form as 0000, 0010, 0011, 0101, 0110, 1000, 1001. For 1, 4, 7, which are 0001, 0100, and 0111 respectively the segment will not light up.
LCD Bottom-Right Segment Connection
This one is relatively simpler than the previous one. The only number for which do not want this segment to light up is 2, which is binary 0010. Thus the logic for this is, a) either A or B must be true, OR b) either the inverse of C or D must be true. The only number which does not meet this condition is 0010, which is 2. Thus this segment will light for every number except for 2, or binary 0010.
LCD Bottom-Left Segment Connection
The logic for the bottom-left segment is also fairly simple. So our condition is, a) both B and D must be false, OR b) A and D must be false and C and D must be true. The only numbers that we want this segment to light up for are 2, 6, 8, 0, which are binary 0010, 0110, 1000, and 0000 respectively. Naturally, these are the only number which meet our condition. The rest of the numbers 1, 3, 4, 5, 7, 9, do not meet the condition. Thus this segment will only light for 2, 6, 8, and 0.
LCD Top Segment Connection
This circuit is not complex either, involving only three logic gates as such. The logic hereby is, a) both B and D must be the same state, AND b) A and C must both be different state. Only then will the segment NOT light up. The only numbers for which our segment will not light up are 1 and 4, which are binary 0001 and 0100 respectively. For all the other numbers, the condition in the circuit return true, and thus for all those number sou segment will light up.
LCD Top-Right Segment Connection
This part of our circuit also involves three logic gates. The logic here goes like this, a) B must false (since we placed an Inverter or NOT gate), OR b) C and D must be the same state. The only two numbers which do not meet these conditions are 5 and 6, which are binary 0101 and 0110 respectively. Thus for all the other numbers are condition is met and our segment will light up.
LCD Top-Left Segment Connection
The logic we are implementing here, is a) both C and D must not be 1, OR b) either A or B must be true AND C & D must both be false. If either of these conditions are true, then the top-left segment of the LCD will light up. The numbers which meet these conditions are 0, 4, 5, 6, 8, 9, which are 0000, 0100, 0101, 0110, 1000, 1001 respectively. The rest of the numbers, 1, 2, 3, 7 do not meet the conditions, being 0001, 0010, 0011, and 0111 respectively.
LCD Center Segment Connection:
The segment is slightly complicated. Step-by-step, the logic implemented here is, a) Either A or B must be true, OR, either C or D must be true, AND, b) either A or the inverse of D must be true, OR, only one of B and C must be true. If both of these conditions a) and b) are true, only then will the center segment light up. Thus, this segment will light up for the numbers 2, 3, 4, 5, 6, 8, 9. The center segment of the LCD will not light up for numbers 0, 1, and 7 which are 0000, 0001 and 0111 respectively.
Great going! We can now connect all these individual circuits together and combine them to convert our binary numbers 0-9 into decimal numbers and display them.The next step and hopefully the last is to extend this functionality to multi-digit numbers, by splitting into two different digits using binary to BCD (binary-coded decimal) conversion.
For this what we are going to is create a circuit as follows which converts our binary input into BCD:
This circuit utilises something called the Double Dabble algorithm and adds 3 to the numbers each time, more about that in a later tutorial since that is not our focus here. Here we have used an IC called Plus 3, which is made as following:
And after that, we can duplicate two more of our 7-segment display circuits (Note that originally it should come inside of a microchip), since we need one for each digit. We send over our JKLM as the binary input for the display at the units place, we send the NOPQ as the input for the display at the tens place, and the RST to the hundreds place (since it is 4-bit multiplication).
And with that final step, we have now successfully finished our calculator! Bravo!
Wow, that was insanely long but also quite interesting, don't you think? Congratulations, you have not only deepened your understanding of how Integrated Circuits are formed and manipulated, but you have also developed really cool critical thinkings skills by working with these diagrams. I am sincerely grateful to all of you stuck around and I hope you drop your likes and comments if you learnt something worthwhile. Before I sign off, I would like to remind you to let me know of any future topics that you might want to see! And don't forget to keep exploring and experimenting.
Until Next Time ~