Lab 3: VHDL
The purpose of this lab is to give you more practice working with VHDL and to introduce you to the concept of a state machine.
Starting with this lab, you may work with a partner.
- Start Quartus. Follow the new project wizard and create a new directory for lab 3. Call your project bright. This is the name of the project and the top level entity. You're free to use any name you like, just make sure it is also the name of your entity and top level file.
Select File->New and create a new VHDL file. Then insert the template
for a Moore state machine (VHDL->Full Designs->State machines).
Change the entity name to bright in both the entity and architecture
Aside: a state machine is a way of representing a sequential process. You can think of each state as a step in the process. A state machine changes states according to the rules of each state and the values of the inputs used by the state machine. Note that not every state will necessarily care about every input.
In a Moore state machine, the state identifier provides a complete description of what the circuit should output and how it should respond to inputs. How the state machine arrived at its current state is immaterial.
We're going to make a simple state machine that recognizes when you
have pressed three buttons in the proper sequence. Consider the
following description of a state machine.
- In the Idle state no buttons have been pushed. If the first button is pushed, then move to the One state
- In the One state, the first button has been pushed. If the second button is pressed, then move to the Two state. But if the third button is pressed, move to the Idle state.
- In the Two state, the first and second buttons have been pressed in sequence. If the third button is preseed, then move to the Three state. But if the first button is pressed, move to the Idle state.
- In the Three state, all three buttons have been pressed, so turn on an LED. If button one or two are pressed, move back to the Idle state.
The following is a visualization of this state machine.
In the definition of state_type, change the state names to sIdle, sOne, sTwo, and sThree.
Modify the inputs to the entity so there is a signal for each button,
in addition to the clock and reset. Make each one a std_logic signal,
as shown below.
buttonOne : in std_logic; buttonTwo : in std_logic; buttonThree : in std_logic;
Going to the body of the architecture, notice the structure of the
code. This is a standard Moore state machine structure. In VHDL, a
process statement is like a code block. Inside a process statement you
can use if statements, case statements, and assignments, so it is kind
of like a standard programming block, but don't let that fool you, it
behaves somewhat differently.
Aside: Think of a process like a function. The process statement itself is sensitive to the signals in its parameter list. For a Moore state machine, the important signals are the clock and the reset signals. Any time one of those values changes, the process block should execute.
While executing, however, the process block does not act like a sequential computer. The instructions are not executed in order, in the sense that if you assign a value to A on line 1 and then use A on line 2, A will have the value you assigned it on line 1. Program flow instructions, like if-statements, are executed in the order in which they appear. But assignments to not actually move data; assignments schedule a value to be assigned to a variable. All actual data movement occurs simultaneously at the end of the block. Therefore, it is important that a variable be scheduled an assigned value (appear on the left side of a signal) only once in the process block, given the program flow. Having an assignment to variable A in the two cases of an if-statement, for example, is fine because only one of the cases will execute.
Inside the process, there is an if statement the tests for a reset signal. Anything that should be done on a reset signal should go there.
The elsif case looks for a rising edge of the clock. All state machine changes take place on the rising edge of the clock, so everything else goes there.
Inside the rising edge block there is a case statement that switches on the current state. Within each state, there is an implementation of what events cause a state change. One thing that is critical is to note that the state variable will only ever get assigned a new value once inside the process.
Edit the reset case so the state gets assigned sIdle. Also, change the test to reset = '0' so that pushing the button causes a reset.
Edit the other four state cases to use the proper names and make the proper tests. Remember that when the user pushes a button its value will be '0'.
- The second process statement modifies the output depending upon the state. Change the state names, but otherwise leave it as it is so we can watch the state progression.
- Set up the pins so buttons one, two, and three are pins R21, T22, and T21. Set up the reset to be pin R22. Then set up the two outputs to go to pins R20 and R19. Set the clock to A12.
Make the EDA netlist and simulate the circuit. Give the clock a 50ns
period over 1000ns. Then make constant signals for the three buttons
and the reset signal, then use the Edit mode of the waveform window to
adjust the signals as appropriate.
To get to the edit mode in the waveform window, look for the icon set below.
Click the fourth button from the left. With this tool active, you can click and drag on a waveform to select it. Then you can right-click on the selected area and pick Wave Editor from the popup menu. Then you have the option to Invert, Mirror, or set a specific Value for the waveform.
- Once you have simulated the circuit, download it to the board and test it out.
When you have completed the lab assignment, go ahead and get started on the second project.