This is Part 4 in my series of projects called A Beginner's Guide to FPGAs. Part 1 showed you how to set up the Alchitry Au board and Alchitry Labs software. In Part 2, we built a simple ALU (arithmetic logic unit), which demonstrated the elegance and power of HDLs (hardware description languages). Then in Part 3, we input numbers in binary with the dip switches and display them in decimal on a 4 digit 7-segment display.
Now in Part 4, we will interface a keypad with the 7 segment display on the Alchitry IO board. We want to be able to input numbers from the keypad just like we normally do with a calculator.
Physical Connection of Keypad and Alchitry Au BoardWe need to physically connect our keypad, which we will do through the Alchitry's Br Prototype board.
We also need to create a new Constraint file: brBoard.acf, and place the following in it:
I'm showing you the constraint file now, because it is also your guide to what physically gets connected to pins on the prototype board. By the way, the Br board sits on top of the Au FPGA board and under the IO Element board
Note: I tried to find pins that weren't being used for anything else, but it turns out C49 is also used for one of the push-buttons on the io board. Vivado may generate an error as a result of using it twice. If so, go into the io.acf constraint file and delete the use of pin C49 for the button.
FPGA Interface to the KeypadOur project will read the 16 key keypad and returns both the key pushed, as well as the number on the keypad if the key pushed is a number.
It works as follows:
1. The row inputs from the keypad are normally high as a result of pullup resistors
2. The column select lines to the keypad are normally high outputs, but a counter running at 100 Hz drives each low for 10 msec..
3. When a key is pressed, its row goes low when its column is set low. The combination of a known column and a known row tells us which button was pushed.
4. When a button is pressed, the result is latched and output as myButton.
5. If the button pressed is a number (0 - 9), a new number pulse is generated (newNum) and the number is output as numOut. The numNum pulse lasts about 200 msec. and is used to debounce the button presses.
All of the above happens in a module called poll_switches.
The Keypad to Seven Segment ProjectOur new project, which contains the poll_switches module, also has everything we created last time to put binary numbers onto the 7 segment display. The entire project and all its files are contained in the attached Zip file.
Our project has one more module which deserves a little discussion. It's called bcd2binary and it takes up to four numbers input from the keypad, entering them like you are used to on a calculator, and converts the input into a binary number. It also contains the hardware to clear the binary number, and return the display and all the registers to 0.
It turns out this module is a little more complicated that it first sounds. We have to sequence a series of events as each number is entered, and we don't know if the entry will be 1, 2, 3, or 4 numbers. It took several tweaks to get everything initialized properly and working correctly. You can see more details in the file comments.
Design PhilosophyI am gradually learning by trail and error some things I would probably be taught in a course on digital circuit design. Vivado and HDLs in general have incredible ability to do almost anything with combinational logic - things that I was sure could only be done with sequential processing. An example we saw in Part 2 was the ability of our ALU to do division.
There is a very basic trade-off here. I can design hardware to sequentially do something by using counters. Or I can ask Vivado to do it with combinational logic. The combinational approach minimizes my effort and produces extremely fast processing, but at the expense of using a lot of gates or "real estate" on a chip of silicon.
As a novice building relatively simple circuits, I am going to lean in the direction of letting Vivado do all the work, and not worry about how many gates I am using. But if I was designing hardware for mass production, I would have to be more concerned with efficient use of silicon. A CPU, where almost everything is done sequentially, is probably the best example of efficient use of silicon.
But in some places I am forced to use counters and do things sequentially. An example came in Part 3 where we had to time multiplex our 4 digits in the 7 segment display. And another is what we are doing here in Part 4 - sequentially entering numbers on a keypad. I first designed this with multiple counters and made it quite complicated. Then I realized I can make it much simpler, if I just make Vivado do a lot more combinational logic. So the version I ended up with has just a single counter for the number of digits entered!
On a slightly different subject, at first I was using "else if" statements and "case" statements pretty interchangeably. I have come to prefer "case" - it is slightly more explicit and can always be regarded as building a multiplexer. It also makes me realize how often a multiplexer is the solution to a problem!
What's NextFor Part 5, our last in this series of tutorials, we will construct a simple integer calculator. As you can see in the video, we have already relabeled some of our keypad keys with calculator symbols.
Comments
Please log in or sign up to comment.