Project 3: Reaction Timer
Due Tuesday October 6 2026
Purpose: to start exploring sequential digital circuits by creating a reaction timer.
Tasks
Problem Statement: The purpose of this project is to build a circuit that will test a (potentially simulated) user's reaction time. At the heart foof the program is a state machine written in VHDL. You will also need your 7-segment display driver and a top-level file (VHDL for simulation or BDF for programming the board).
The circuit should work as follows. The user should press the reset button (Button 1) to start the circuit from the begining. It begins in an idle state with two digits displaying 00 and the rightmost green LED (green LED 0) on. When the user hits the start button (Button 1), the circuit should light up Green Led 1 and wait for a period of time. Then the circuit should light up green LED 9 (the rightmost light) and start counting (approximate milliseconds), showing the count on the two digits. When the user hits the reaction button, the count should stop and freeze. If the user hits the reaction button before green LED 9 lights up, the counter should show FF and the system should go back to the idle state. When the user hits the start button, the digit display should be set back to zeros.
I have made a short video explaining how the board should operate. Check it out.
- If you are using the board, follow these instructions
+ (more detail)
- Make a new Quartus project
- Start Quartus and then create a new project, putting it in a new subdirectory. Call it reaction (you are welcome to call it whatever you like, but I will refer to the project and the top level file as reaction).
- Copy your 7-segment driver file from project 2 (bdf or vhd) to your new project directory.
- Open your 7-segment driver file, then select Project->Add to project. Then select File->Create/Update->Make symbol file.
- Define the state machine behavior
- Define the entity and port for the circuit
Create a new VHDL file with an entity called timer and name the file timer.vhd. Insert the Moore state machine template. The timer circuit should have a clock, a reset, a start input, and a react input (all of type std_logic). It should have two outputs: one 8-bit unsigned that sends the time (in ~ms, so call it mstime) and a 3-bit std_logic_vector that sends the values of the three green LEDs.
- Define internal variables for the circuit
Name the states for your state machine as sIdle, sWait, and sCount. Your circuit should initially be in the sIdle state. When the user hits the start button it should move to the sWait state, stay there for a while, and then move to the sCount state. When the user hits the react button, the sCount state should move back to the sIdle state. If the user hits the react button while the system is in the wait state, then the counter should be set to all 1s and the system should go back to the sIdle state.
In order to both wait and count, you need an internal counter. To make this counter provide useful information to the user, we would like to report the count in milliseconds on two 7-segment displays, which means we would like and 8-bit counter to increment at a rate of 1KHz. But the clock we will use runs at 50 MHertz, which is too fast. To find bits that increase at a rate of approximately 1 KHz (and approximate is the word, since Stephanie ultimately had to figure this out by trial and error because the math doesn't work as well as she thought it should), we will report the bits 27 down to 20 from a counter that has at least 28 bits. Since we will also be using this counter to control the wait time, it needs to be able to count up to a number that has units of approximately seconds (so the user can wait somewhere between 0.5 and 2 seconds). Counting this high requires at least 27 bits. We will use 28.
Create an internal signal of type unsigned with 28 bits. Put its declaration between the architecture statement and the begin, along with the state signal declaration. You'll also need to add
use ieee.numeric_std.allto your header section above the entity statement.signal count : unsigned (27 downto 0);
- Define the behavior on reset
Set up the reset condition so it activates on a '0'. It should set the state to sIdle and set the count to all zeros (28 of them). You can do this either with a double-quoted string of 28 zeros, or using a handle VHDL short-cut notation:
count <= (others=>'0');
- Define the behavior on a rising edge
Set up the rest of the state machine. Use the count variable to both have the circuit wait a while and to count how long the user's reaction is. If you set count to what is effectively a large number and add one to it, you will eventually get to 0 (which is an easy test).
- Define the entity and port for the circuit
- Define the output behavior
For the output, get rid of the second process statement in the template. Replace it with a few simple conditional signal assignments (remember, they all run in parallel all the time).
- If the state is sIdle, then assign '1' to the 0th green LED and '0' to the others.
- If the state is sWait, then assign '1' to the 1th green LED and '0' to the others.
- If the state is sCount, then assign '1' to the 2th green LED and '0' to the others.
- Assign a string of 8 zeros to mstime when the state is sWait, otherwise assign it bits 27 downto 20 of the internal counter.
- Connect the pieces of the circuit
Create a new bdf file to be the top level file for your project. Call it reaction.bdf. Within it, place two instances of your 7-segment driver and one instance of the timer. Set up appropriate inputs and outputs for the circuit. (As an extension, make your top level file a VHDL file and use component and port map statements to connect the various elements.)
- Test your circuit
Compile your circuit, assign pins, and then test it out. Document your circuit's behavior.
- Make a new Quartus project
- If you are not using the boards, follow these instructions.
+ (more detail)
- Make a new Quartus project
- Start Quartus and then create a new project, putting it in a new subdirectory. Call it reaction (you are welcome to call it whatever you like, but I will refer to the project and the top level file as reaction).
- Copy your 7-segment driver file from project 2 (bdf or vhd) to your new project directory.
- Open your 7-segment driver file, then select Project->Add to project. Then select File->Create/Update->Make symbol file.
- Define the state machine behavior
- Define the entity and port for the circuit
Create a new VHDL file with an entity called timer and name the file timer.vhd. Insert the Moore state machine template. The timer circuit should have a clock, a reset, a start input, and a react input (all of type std_logic). It should have two outputs: one 8-bit unsigned that sends the time (which counts clock cycles, so call it cycles) and a 3-bit std_logic_vector that sends the values of the three green LEDs.
- Define internal variables for the circuit
Name the states for your state machine as sIdle, sWait, and sCount.
In order to both wait and count, you need an internal counter. Create an internal signal of type unsigned with 8 bits. Put its declaration between the architecture statement and the begin, along with the state signal declaration. You'll also need to add
use ieee.numeric_std.allto your header section above the entity statement.signal count : unsigned (7 downto 0);
- Define the behavior on reset
Set up the reset condition so it activates on a '0'. It should set the state to sIdle and set the count to all zeros (8 of them). You can do this either with a double-quoted string of 8 zeros, or using a handle VHDL short-cut notation:
count <= (others=>'0');
- Define the behavior on a rising edge
Set up the rest of the state machine. Your circuit should initially be in the sIdle state. When the user hits the start button it should move to the sWait state, stay there for a while, and then move to the sCount state. When the user hits the react button, the sCount state should move back to the sIdle state. If the user hits the react button while the system is in the wait state, then the counter should be set to all 1s and the system should go back to the sIdle state.
Use the count variable to both have the circuit wait a while and to count how long the user's reaction is. Since you are simulating it makes sense to wait just 2-4 clock cycles. A simple strategy is to count up (increment by one during each clock cycle). If the count is 4, then it is time to move on to the sCount state, so you should set the count to 0 and change the state.
- Define the entity and port for the circuit
- Define the output behavior
For the output, get rid of the second process statement in the template. Replace it with a few simple conditional signal assignments (remember, they all run in parallel all the time).
- If the state is sIdle, then assign '1' to the 0th green LED and '0' to the others.
- If the state is sWait, then assign '1' to the 1th green LED and '0' to the others.
- If the state is sCount, then assign '1' to the 2th green LED and '0' to the others.
- Assign a string of 8 zeros to cycles when the state is sWait, otherwise assign it the value of the internal counter.
- Write the testbench file and debug the project
Make a new VHDL testbench file named
timingtest.vhdusing brighttest as a model. Set the times of the reset, start, and react button presses ('0') and releases ('1') to debug your state machine. Be sure to set the press and release times to allow for the system to move from the wait state to the count state. To figure out how long that is, note that a clock cycle is 10 ns. Compile it with ghdl and use GtkWave to see the signals.Note: if you click on the plus sign next to the top-level module name, then it will show the component modules, so that you can examine wires in the components. Also, note that the state will not show up in the list. If you want to debug the state, I suggest making a separate signal that is a number, and have that signal change whenever the state changes.
- Demonstrate your working circuit
Simulate good and bad user behavior. In your report, describe your strategy and demonstrate that your circuit is correct. Be sure to include at least one scenario in which the user presses reset, then start, then react after the green light goes on. And one case in which the user presses reset, then start, but reacts too soon.
- Make a new Quartus project
Extensions
- If you demonstrated the reaction timer on the board, it is an extension to also simulated it. Write a testbench VHDL program for your circuit and simulate it using ghdl. You can use the brighttest.vhd file as a template.
- Add a linear feedback shift register [LFSR] to generate random wait times. See wikipedia for a reasonable explanation of LFSRs.
- Add the ability to keep track of the shortest reaction time. Display the fastest reaction time on the other two digits, and enable the ability to clear it.
- Make it a game for two players, with two reaction buttons, and report who is faster.
- Be creative.
Report
Create a Word/Pages/etc document for your report. For each task, write a short description of the task, in your own words.
- Include a picture of the state machine diagram for your reaction circuit.
- If you used simulation only, include pictures of your simulations. Be thorough and make sure you test all the states and inputs.
- If you used the boards, Include a picture/diagrm of your top-level design. Also, describe the hardware testing you undertook to prove the circuit works. A video of the circuit in action is a good demonstration. Be thorough and make sure you test all the states and inputs.
- Include a description, and pictures, of any extensions, including proof of testing.
- Include an Acknowledgements section in which you list any resources you con sulted. These could be on-line (movies or web pages) or people (peers, TA's, professors). This is your opportunity to celebrate the community you were able to plug into.
Handin
Put your bdf, vhd, and write-up files in a folder called Project3_<username>, zip it up (so its name will be Project3_<username>), and upload the zip file to the Google classroom assignment for this project.
Fall 2026