Introduction: L I G H T S
The purpose of this final project was to create something that would focus on sustainability and implement digital design concepts, and to do this, I decided to design a scalable power saving system using vhdl and made for the Basys 3 Board (Artix-7 35T series). Scalable because any number of sensors can be put in a room and any number of these systems can be put around a building or a house. What this system would do, is theoretically save thousands of dollars in commercial building and decrease a large percentage of energy consumption in smaller residential communities by implementing a connected system of actively and passively controlled lights, motion detectors, timers displayed on seven segment displays, and control switches. This example deals with a single system with three motion detectors, a master switch, a manual/normal switch, four seven segment displays, and a single light the system controls.
For example, in a chosen room, several motion detectors would be placed around (this example design has three), and each would send a signal (1) if it detects movement, and (0) if it doesn’t. If at least one of the motion detectors detect movement, the lights turn on if not already on and stay on if already on. At any time all the motion detectors don’t detect anything, a timer starts to count down for a set amount of time (adjustable in code), and the lights stay on while the timer counts down. Once the timer finishes counting down, the timer stops, and the lights turn off. If at least one motion detector detects movement while the timer is counting down, the timer stops and resets. And if at least one motion detector detects movement while the lights are off, the lights immediately turn on.
This system has two modes, one with the timer as stated above, and a second one where there is a switch that controls the lights manually (ignoring sensors). There is a master switch that allows the user to choose which mode they want to use based on whichever one they feel will save more energy overall. Ex. A room such as a hallway could benefit from the passive timer mode- users aren’t sure when people are going to be passing through, but turning on and off the lights each time they enter and leave would be an inconvenience, whereas a room such as a bedroom with a single user would be better manually operated. And the master switch would be helpful in cases such as if the person living in the bedroom were to leave for an extended period of time, then the master switch could be turned off, and the timer mode would work to save energy more efficiently.
So in this system, there are two state machines, one is the main state machine, and another for the countdown timer. The main state machine has five states defined as such: 1. "lights on, movement detected" (id = 000), 2. "lights on, no movement detected" (id = 001), 3. "lights off, no movement detected" (id = 010), 4. "manually switched on" (id = 011), and 5. "manually switched off" (id = 100). This main state machine has four inputs: the master switch (ms), the manual/normal switch (ns), a signal that is high when at least one switch detects movement, and is low otherwise (orx), and a signal that is high once the timer is done, and is low otherwise (td). The main state machine has two outputs: lights (lights) and a signal that indicates when to turn on the countdown timer (timer) or (t) (both are used interchangeably).
The second state machine, the countdown timer, has 12 states: 10 of them have ids associated with the number the seven segment is displaying- “seg 10” (id = 1010), “seg 9” (id = 1001), […] , “seg 2” (id = 0010), “seg 1” (id = 0001), and the other two states both display zero, representing the timer being off- so there’s the first blank "blank 1" (id = 1111) and the second blank "blank 2" (id = 0000). The countdown timer has one input: timer (t), and three outputs: the number displayed in binary with four bits (bin) and a signal indicating the timer is done (td).
Step 1: Black Box Diagram
- The clock is used to clock the main state machine and the seven segment decoder; a slower clock is needed for the down counter, so there is a clock divider module that takes the clock input and outputs a slower clock for the down counter.
- The intermediate variable (orx) in the wrapper is tied to the motion sensors and will be high if at least one of the sensors detect something, and low otherwise; the boolean equation for that is just orx = s(2) or s(1) or s(0).
- The main fsm controls which general state the system is in, depending on the inputs (orx, ms, ns, td) and outputs the current state it’s in (sm) shown simplified with the two signals its used for (timer and lights).
- (timer) is a wrapper signal that is sent to the down counter fsm as its input and is controlled by the main fsm’s current state. It indicates when to turn the timer on.
- (lights) is a wrapper signal is used to control the led and is controlled by the main fsm’s current state.
- The down counter fsm controls what the seven segment displays depending on the input (timer) and outputs the current state it’s in (sd) shown simplified with the two signals its used for (td and bin).
- (td) is a wrapper signal that is sent to the main fsm as its input and is controlled by the down counter fsm’s current state. It functions as a feedback signal that indicates when the timer is done.
- (bin) is a four bit wrapper signal that is concatenated with four bits of zero (“0000” & bin) and the combined eight bits are sent to (q), an eight bit wrapper signal, that is in turn sent to the seven segment decoder under (ALU_VAL).
- The seven segment module is the same one as on Polylearn; its main inputs take in an 8 bit number (bin) to (ALU_VAL) to display on four different seven segment displays using the outputs (SEGMENTS) to wrapper signal (seg) and (DISP_EN) to wrapper (disp_en).
- Since two or more seven segment displays can’t display different digits at the same time, a clock is needed to cycle through the four ssegs, displaying the appropriate digit at a time for each sseg being turned on individually, and cycling quickly enough makes the ssegs appear to be on all at once.
- (sign and valid) are constant throughout this program, so (sign) is permanently set low and (valid) is permanently set high.
- (ALU_VAL) takes in the wrapper signal (q) as an input, which represents the number going to be displayed on the seven segment display in binary.
- The output (SEGMENTS) is sent to an eight bit wrapper signal (seg) and (DISP_EN) to a four bit wrapper signal (disp_en).
- There is also a D flip flop module not explicitly shown in the diagram but is needed for the two state machines as submodules and helps the states transistion synchronously.
- (3) of these are needed for the main fsm since 2^(3) = 8 > 5 states for encoding
- (4) of these are needed for the down counter fsm since 2^4 = 16 > 12 states for encoding
Step 2: State Machines
To properly design the two state machines, the individual states need to be defined clearly, with its outputs and the state it transitions to based on the different possible inputs.
Main fsm states:
“Lights on, movement detected” (id = 000)
Lights are on, at least one of the motion detectors detects movement, so orx must be high and ms is turned on.
- Outputs: lights = 1 and timer = 0
- Stays as this state when ms = 1 and orx = 1.
- Goes to state “lights on, no movement detected” if ms = 1 and orx = 0.
- Goes to state “manually switched on” if ms = 0 and ns = 1.
- Goes to state “manually switched off” if ms = 0 and ns = 0.
“Lights on, no movement detected” (id = 001)
Lights are on, no movement detected from any motion detector, so orx must be low and ms is turned on. Also in the beginning of this state the timer being set high tells the countdown fsm to start counting down, proceeds to count down, and stops counting down once the countdown fsm tells this fsm that it’s done counting.
- Outputs: lights = 1 and timer = 1.
- Stays as this state when ms = 1 and orx = 0 and td (timer is done) = 0.
- Goes to state “lights on, movement detected” if ms = 1 and orx = 1.
- Goes to state “lights off, no movement detected’ if ms = 1 and orx = 0 and td = 1.
- Goes to state “manually switched on” if ms = 0 and ns = 1.
- Goes to state “manually switched off” if ms = 0 and ns = 0.
“Lights off, no movement detected” (id = 010)
Lights are off, no movement detected from any motion sensor and the timer finished counting down, so orx must be low, ms is turned on, and td is off.
- Outputs: lights = 0 and timer = 0.
- Stays as this state when ms = 1 and orx = 0.
- Goes to state “lights on, movement detected” if ms = 1 and orx =1.
- Goes to state “manually switched on” if ms = 0 and ns = 1.
- Goes to state “manually switched off” if ms = 0 and ns = 0.
“Manually switched on” (id = 011)
Lights are on, motion detectors are irrelevant, so ms is turned off, and ns is turned on.
- Outputs: lights = 1 and timer = 0.
- Stays as this state when ms = 0 and ns = 1.
- Goes to state “manually switched off” if ms = 0 and ns = 0.
- Goes to state “lights off, no movement detected if ms = 1.
“Manually switched off” (id = 100)
Lights are off, motion detectors are irrelevant, so ms is turned off, and ns is turned off.
- Outputs: lights = 0 and timer = 0.
- Stays as this state when ms = 0 and ns = 0.
- Goes to state “manually switched on” if ms = 0 and ns = 1.
- Goes to state “lights off, no movement detected if ms = 1.
Down counter states:
“Seg 10” (id = 1010)
Seven segment display shows a 10.
- Outputs: bin = “1010” and td = 0.
- Goes to state “seg 9” if timer = 1.
- Goes to state “blank 2” if timer = 0.
“Seg 9” (id = 1001)
Seven segment display shows a 9.
- Outputs: bin = “1001” and td = 0.
- Goes to state “seg 8” if timer = 1.
- Goes to state “blank 2” if timer = 0.
(States "Seg 8" down to "Seg 2" are omitted because they follow the same pattern as "Seg 10" and "Seg 9" and is not necessary for explanation)
“Seg 1” (id = 0001)
Seven segment display shows a 1.
- Outputs: bin = “0001” and td = 0.
- Goes to state “blank 2” on next rising edge of clock (no input needed).
“Blank 2” (id = 1111)
Seven segment display shows a 0. The purpose of a second blank state is so that there is a separate state for when td = 1 for safety.
- Outputs: bin = “1111” and td = 1.
- Goes to state “blank 1” on next rising edge of clock (no input needed).
“Blank 1” (id = 0000)
Seven segment display shows a 0. This is the state the system stays in when the main state machine is in state “lights off, no movement detected”.
- Outputs: bin = “0000” and td = 0.
- Goes to state “seg 10” if timer = 1.
Step 3: State Machine Truth Tables, Excitation Equations, and Output Equations
The next step is to create truth tables for the two state machines and excitation equations and output equations for each fsm. For each fsm excitation equation, there needs to be equations for each next state encoded bit in terms of the current state and its input signals. For each fsm output equation, there needs to be equations for each output signal in terms of the current state. All four sets of equations can be drawn from the truth tables depicted. (qn is the next state encoded bit for each state machine, and q is the current state)
(000) equivalent to q(2)'q(1)'q(0)', and (0000) equivalent to q(3)'q(2)'q(1)'q(0)'
(ex. (0101) is q(3)'q(2)q(1)'q(0) and (110) is q(2)q(1)q(0)' )
Excitation equations for the main fsm:
- qn(2) = (ms)'(ns)
- qn(1) = (ms)'(ns)' + (ms)(orx)'[(td)(001) + (010)] + (ms)[(011) + (100)]
- qn(0) = (ms)'(ns)' + (ms)(orx)'[(000) + (td)'(001)]
Output equations for the main fsm:
- lights = (000) + (001) + (100)
- timer = (001)
Excitation equations for the down counter fsm:
- qn(3) = t[(0000) + (1010) + (1001) + (0001)]
- qn(2) = t[(1000) + (0111) + (0110) + (0101) + (0001)]
- qn(1) = t[(0000) + (1000) + (0111) + (0100) + (0011) + (0001)]
- qn(0) = t[(1010) + (1000) + (0110) + (0100) + (0010) + (0001)]
Output equations for the down counter fsm:
- td = (1111)
- bin(3) = (1010) + (1001) + (1000) + (1111) + (0000)
- bin(2) = (0111) + (0110) + (0101) + (0100) + (1111) + (0000)
- bin(1) = (1010) + (0111) + (0110) + (0011) + (0010) + (1111) + (0000)
- bin(0) = (1001) + (0111) + (0101) + (0011) + (0001) + (1111) + (0000)
Step 4: Wrapper, Submodules, & Constraint
As explained already in Step 1, these modules are needed for this project and are all tied together with the wrapper module titled "final_proj.vhd". The constraint file titled "Basys3_Master.xdc" is used to link all the wrapper inputs and outputs to switches, the seven segment, and I/O ports on the Basys 3 board. The master switch should be the switch on the board closest to the side the wires are on, the normal/manual switch is the second closest, and the three switches representing the three motion sensors are the three switches immediately next to the normal/manual switch. All the code (boolean equations, module declarations, etc) is already written out in the files, so you don't have to write anything else to make this work.
Step 5: I/O Ports for LED
The last step for this project is to use an led to show whether or not (lights) actually turn on and off. The wiring is shown in the two pictures. Make sure there is a resistor in series with the led (at least 330 ohms) as to not burn out the led and make sure the led’s long pin is connected to the same female header on the basys board as the red wire is shown (top rightmost) and the shorter pin is connected to ground, the same female header as the black wire shown (top, second from left).