From Hamsterworks Wiki!
Please make sure that you have completed the earlier modules of FPGA course.
Having problems with your code? Do I need to change something? Want a reference solution to the project? Email me at "email@example.com", after removing the "nospam-" bit. I'll try to get back to you in a day or so.
Aims of module
- Use the VHDL "case" statement
- Build a component to display on the four seven segment displays
- Practice building a nice self-contained reusable component
- Use something other than the LEDs for displaying values
The VHDL 'case' statement
Much like "switch()" in C, VHDL has the CASE statement that allows you to choose different paths through your code. Although it is largely functionally equivalent to nested 'IF's it is far easier to write. The CASE construct are implemented
it looks much like this:
CASE input(2 downto 0) IS WHEN "000" => output1 <= '1'; output2 <= '1'; WHEN "001" => output1 <= '0'; output2 <= '1'; WHEN "110" => output1 <= '1'; output2 <= '0'; WHEN OTHERS => output1 <= '0'; output2 <= '0'; END CASE;
It differs from most similar constructs in programming languages in that all possible cases must be covered, so it pays to remember that STD_LOGIC signal can have other states than just '1' or '0' - most designer choose to use the 'least harmful' actions on an unexpected value. Like an "IF" statement, "CASE" can only be used inside a process - and remember to include the signals being tested in the process's sensitivity list!
Excellent practice for using the CASE statement is driving the seven segment display - you can use it twice. One CASE statement decodes which segments to light, and a second CASE statement selects which digit is active at any time.
These projects are a lot of work and might take a couple of sittings, but you will build up a great understanding of the seven segment displays. If you are feeling confident combine a few of the steps and race through.
- Add "anodes(3 downto 0)" and "sevenseg(6 downto 0)" as outputs to your top level design, and then add the following constraints to your ucf file:
NET "sevenseg<0>" LOC = "L14"; NET "sevenseg<1>" LOC = "H12"; NET "sevenseg<2>" LOC = "N14"; NET "sevenseg<3>" LOC = "N11"; NET "sevenseg<4>" LOC = "P12"; NET "sevenseg<5>" LOC = "L13"; NET "sevenseg<6>" LOC = "M12"; NET "dp" LOC = "N13"; NET "anodes<3>" LOC = "K14"; NET "anodes<2>" LOC = "M13"; NET "anodes<1>" LOC = "J12"; NET "anodes<0>" LOC = "F12";
Note: these are the Basys2 pin mappings - must be changed for other boards
- In your top level design, connect the output to 'sevenseg' and 'dp' to the switches. set anodes to "1110" then build the design. (The anodes are "active low", so this value should enable only the rightmost digit of the sevenseg displays).
- Work out and document the the switch patterns required to give the digits 0 through 9, and the letters A through F.
- Build a 'CASE' statement to decode the binary of switches(3 downto 0) and display it on the first seven segment display - remember that at least switches(3 downto 0) has to be included in the sensitivity list of the process acting on them
If each digit is displayed quick succession the eye can be fooled into seeing all four displays as being lit at the same time. As we have four digits we can use to two bits of a suitably sized counter to select which is to be lit. Switch digits too fast will not give them enough time to light up, and too slow will call flickering. Something around 200Hz to 1kHz seems to work best.
|counter bits||value for anodes||values for sevenseg()|
You can either decide to decode the four digits in each option of the CASE statement (using nested CASE statements), or maybe create a signal "thisdigit : STD_LOGIC_VECTOR(3 downto 0)" with the digit to be decoded within the case, and then just decode that signal.
- Update your project to multiplex all four display and showing the values of switches(3 downto 0) on all digits
- Update your project to multiplex all four display and showing the values of switches(3 downto 0) on digit 0 and 1, and the value of switches(7 downto 4) on digit 2 and 3
- Update your project show the highest 16 bits of a counter over all four digits.
- Create a new module that can display four digits on the seven segment display. This will be useful for any project you design that uses the sevenseg displays. Its interface signals should something like
clk : in std_logic digit0 : in std_logic_vector(3 downto 0) digit1 : in std_logic_vector(3 downto 0) digit2 : in std_logic_vector(3 downto 0) digit3 : in std_logic_vector(3 downto 0) anodes : out std_logic_vector(3 downto 0) sevenseg : out std_logic_vector(6 downto 0) dp : out std_logic
- Can you make the display count only in decimal rather than hexadecimal?
- Can you make the display count in minutes and seconds?
Ready to carry on?
Click here to carry on to the next module.