Traffic Light Controller: Using VHDL

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 22

PROJECT ON

Traffic light controller


Using vhdl
Synopsis

Submitted by-
Srishti- 2K7-Mrce-Aei-052
Bhavika Khanna-2k7-Mrce-Aei-051
Sumedha Sardana-2k7-Mrce-Aei-053
1.ABSTRACT.
The purpose of this project is to design and implement a traffic light controller for a single
intersection.
The controller is constructed from a finite state machine used to control the actual operation of
the
traffic lights. The remainder of the system consists of supporting subsystems, including RAM, a
Timer, Divider, and various synchronizers. Time values used by the finite state machine are
written
to and read from the RAM. The design used VHDL code compiled to a Cypress 374i CPLD and
various digital hardware parts from the 6.111 Kit.

II. Description
A. Functional Specifications
As mentioned earlier, the intersection to be controlled is between a busy (Main) street and a
somewhat less busy (Side) street. Both streets have ordinary (Red, Yellow, Green) signal lights.
The
intersection is fitted with a sensor for side-street traffic and with a walk request button. Figure 1
shows the layout of the intersection.

Figure 1: Layout of Intersection


There are four timing parameters in the system. They are the base interval (TBASE), the
extended
interval (TEXT), the time for a yellow light (TYEL), and a blink interval (TBLINK). These
timing
parameters are expressed in number ‘tics’ of a one-second long clock.
The operating sequence is that the Main street has a green light for a period of time equal to
TBASE
+ TEXT, then the system cycles to Main being yellow/red and Side yellow for TYEL. After this
the
system goes to side green for TBASE, through yellow/red, and back to Main street green. The
cycle
is then repeated.
The period of time during which the Main Street has a green light is regarded as two time
periods,
TBASE and TEXT. If, at the end of the Main yellow interval there is a WALK request pending,
the
system goes to the walk state, where both the Main and Side streets are yellow/red. It stays in
this
mode for TEXT that we take to be the length of the WALK interval. At the end of the walk mode
the system goes back to Side green.
Note that the WALK request is handles only after the Main Street has been yellow. The request
is
taken by a push button that latches the WALK value until the system needs to use it. Note also
that
the WALK request must be explicitly un-latched by the controller, at the time the WALK signal
is
serviced. The WALK light stays on for only one period of TEXT at a time, and ignores any
WALK
requests made while the WALK light is on.
Normally, the side street stays green for TBASE. If at the end of this interval the traffic sensor
shows there is still traffic, the green light stays on for an additional TBASE. Thus, in theory, the
side street could stay green forever, as long as the traffic sensor is depressed.
Finally, as happens late at night or when something in the system is not working, the light must
go
into a “blinking” pattern. This involves the traffic light alternating between Main yellow plus
Side
red and Main red plus Side yellow. The interval for each of these is TBLINK, which is the fourth
timing parameter.
The timing parameters are all stored in a static RAM (SRAM). The traffic light controller is in
charge of loading these SRAM locations with timing parameters and of displaying these
parameters
by reading the RAM locations.

B. Top Level Design


A simple block diagram of the traffic light controller is shown in Figure 2. The FSM is the heart
of
the system. It controls reads and writes to the RAM and is in charge of cycling the states
properly in
the traffic light. The FSM can execute four functions specified by two functions switches. These
functions are listed in Table 1. The FSM is a VHDL file compiled to a Cypress 347i CPLD.
Figure 2: Top Level Block Diagram
Table 1: Table of Functions
F1 F0 Function
0 0 Examine memory location specified by address switches
0 1 Store new value in memory location of address switches
1 0 Run traffic light
1 1 Light blinks
The RAM is where the timing parameters are stored. The values stored in the RAM represent
time
durations in seconds.
The divider is a series of LS163 synchronous counters driven by a crystal oscillator that produces
the
system clock at 440 MHz. The system clock is used to clock all the components of the system,
from
the FSM, to the timer. The clock also into a component called secpulse on the CPLD.
Secpulse divides down the system clock further and creates a one second pulse clock. I call it
a
pulse clock because it is not like a normal clock; instead it is high for one system clock cycle per
second, and low for the rest of the second.

Another important unit is the Timer. It counts for a number one-second intervals that are
specified
by data stored in the SRAM. It then sends a signal, the EXPIRED bit; to the FSM notifying that
it
is time to change state. The Timer is implemented as a LS169 synchronous up/down counter and
some and-logic to generate the expired bit.
Lastly, there are various synchronizers that ensure that all inputs to the FSM are synchronized to
the
system clock. The synchronization is done using VHDL on the CPLD. The WALK signal is a
special case of synchronization, since it also has to be latched too. This way pressing the WALK
button once ensures that a WALK request will be queued. The logic to do this is also
implemented
in VHDL on the CPLD.
C. FSM
The inputs and outputs to the FSM are denoted in Table 2 and Table 3.
Table 2: FSM Inputs
RESET Go back to reset state (from switch)
GS Synchronized GO signal, start function (from pulse-shaper fed by pushbutton)
F1 and F0 Determines one or the four different functions (from switches)
L1 and L0 Specify a location in the SRAM (from switches)
WS Synchronized walk request signal (from re-settable latch fed by pushbutton)
TS Traffic Sensor (from flip-flop fed by switch)
EXPIRED Signals when a pre-specified time has elapsed (from Timer)
Table 3: FSM Outputs
A1 and A0 Specifies an address in SRAM (to SRAM address lines)
/WE Drives value from switches onto bus, write into SRAM
STARTTIMER Resets 1-second clock and Timer, enables loading of new value in Timer
Gm, Ym, Rm,
Gs, Ys, Rs
Traffic light control signals
The FSM has four functions, as listed in Table 1. Incorporating these functions and the various
states of the traffic light, a state transition diagram for the FSM was generated. It is reproduced
as
Figure 4 on the next page. The diagram shows the four separate functions of the FSM. The ‘idle’
state of the machine is something called the RESET state. In this state, none of the lights are on,
and the system does not do anything. The system will stay in the RESET state until the GO
button
is pressed. At this time the system will enter the state denoted by the F0 and F1 switches. We
will
now look at each of the functions of the FSM in greater detail.

RESET
Read RAM
Write RAM
BLINK MODE
Side Red
Main Yellow
BLINK MODE
Side Yellow
Main Red
Side Green
Main Red
TBASE
Side Yellow
Main Red/Yellow
TYEL
Side Red
Main Green
TBASE
Side Red
Main Green
TEXT
Side Yellow/Red
Main Yellow
TYEL
WALK
Side Yellow/Red
Main Yellow/Red
TEXT
TS = 1
TS = 0
WS = 1
WS = 0
F1 = 1, F0 = 0, GS = 1
GS = 0
F1 = 1, F0 = 1, GS = 1
F1 = 0, F0 = 0, GS = 1
F1 = 0, F0 = 1, GS = 1
X
X
X
X
X
X
X
X
State Transition Diagram
6.111 Laboratory 2
Sourav Dey
X denotes 'always make this transition
RESET is asynchronous, hitting reset in any state
will send system back to RESET state

1. Read (F1 = 0, F0 = 0)
The FSM can read locations in the RAM and display the contents to a HEX led. The data path
exercised is shown in Figure 5. A read is only executed upon a press of the GO button. If both F1
and F0 are 0 at this point, the FSM goes into the read state for ONE clock cycle, and then returns
to
the RESET state immediately afterwards. The value of the address read is kept showing on the
hex
LEDs.
Figure 4: FSM Read/Write Data Path
The exact timing issues are interesting. First off, there is an important aside. The GO signal is an
asynchronous signal generated by the user pressing a pushbutton. This signal is NOT directly
passed to the FSM. It first goes thru the gosync unit, which acts as a pulse-shaper. Gosync
asserts GS high for only ONE clock cycle, no matter how long GO is depressed. There is more
on
this in the Synchronizer section, but this fact must be mentioned here because the fact that GS is
only high for one clock cycle is used over and over again.
Once in the read state, the FSM asserts A1 = L1 and A0 = L0. Since the /OE on the RAM is
grounded, asserting the address bit immediately causes the RAM to dump the contents of that
address onto the I/O bus. This value is then sent to a HEX led where the user can see it. In
addition, the FSM remember what address was read and stores that value internally as a signal
called
HOLDADDR. After the Read the FSM goes immediately back to the RESET state. In the
RESET
state, A1 and A0 are set to HOLDADDR. Thus the value of the last address read is constantly
shown on the hex LEDs, even in the RESET state.
The timing diagram is shown in Figure 5. Note how the address A1-A0 read is held in the
RESET
state.
Figure 5: Timing Diagram for Read Operation

2. Write (F1 = 0, F0 = 1)
The FSM can write new timing parameters to the RAM. The data path exercised is also shown in
Figure 4. A write is only executed upon a press of the GO button. As long at F1 = 0 and F0 = 1
when GO is pressed, the FSM goes into the write state for only ONE clock cycle. It returns to the
RESET state immediately afterwards.
In the write state, the FSM asserts A1 = L1 and A0 = L0. In addition it asserts /WE low for the
one clock cycle of the write state. This enables the tri-state buffer, which pushes the values of
switches C0-C3 on the RAM I/O bus. The actual write to the RAM occurs when both the /CLK
and /WE are low. The exact timing details of this operation are discussed in the RAM section.
A timing diagram of the signals coming out of the FSM is shown in Figure 6. Note again, how
the
GS signal is only high for one clock cycle. Also note how the system returns to the original
addresses after the write is completed. This feature is a little annoying because the user cannot
see
what is written. Instead, the user must explicitly do another read on that address to see what was
written there. This can be easily changed, but I opted not do so in fear of breaking something else
in the process.

Figure 6: Timing Diagram for Write Operation

3. Traffic Light Cycle (F1 = 1, F0 = 0)


The FSM controls the cycling of the traffic lights in this mode. The data path used by the FSM is
shown in Figure 7on the next page. To put the FSM into the cycle, the user has to set F1 = 0 and
F0 = 0 and then hit the GO button. This sends the system into the first state of the traffic light
cycle, Side Green and Main Red. This transition can be seen on the timing diagram in Figure 8.
Note that the STARTTIMER signal must be asserted for one clock cycle when the system first
goes
into the traffic light cycle. This is because the STARTTIMER signal enables loading of the
Timer.
If it were not asserted, then no timing parameter would be loaded into the timer, and the traffic
light
would get stuck in the Side Green/Main Red mode for an indeterminate amount of time.
While in the traffic light cycle, the GO button is ignored. Transitions are instead determined by
the
EXPIRED input. The EXPIRED bit comes from the Timer unit. The Timer counts the number
of seconds the traffic light is supposed to be in a certain state. Once time is up, the Timer asserts
EXPIRED high. The FSM catches the high-EXPIRED bit on a rising clock edge. This signals the
FSM to change to the next state.
This is perhaps the most complex transition in the FSM. A lot of thought and planning went into
the design of this transition, it can also be seen on Figure 8. The one-second clock causes the
Timer
to hit ‘0000’. This causes the EXPIRED to go high. At the next clock edge the FSM catches the
high EXPIRED and starts transitioning. The addresses, A1 and A0, change to their new values,
as
do the light signals. STARTTIMER also follows EXPIRED through a flip-flop. Thus at the
clockedge
that catches EXPIRED, STARTTIMER goes low.
The interplay between STARTTIMER and the Timer unit is extremely important because
STARTTIMER serves as a LOAD enable. The Timer is just a LS169 up/down counter. At every
transition, it is loaded with the timing parameter for the next state. For example, in the transition
from Side Green/Main Red to Side Yellow/ Main Yellow/Red, the Timer has to be loaded with
TYEL from the RAM. Since the Timer loads synchronously on a clock edge, the RAM outputs
had
to be valid by the time the Timer was trying to load.
The issue is expressed in the timing diagram of Figure 9. In the one clock cycle after the FSM
catches the EXPIRED bit, both the addresses and RAM outputs have to change. Then at the next
clock cycle these values are loaded into the Timer. This load also causes the EXPIRED bit to go
low again, because now the Timer is not at 0000. The STARTIMER goes hi again at the next
clock
edge, after enabling another load.
STARTTIMER also serves as a RESET for the secpulse clock. For the two clock cycles
STARTTIEMR is asserted, the secpulse clock is reset and unable to count. It only starts
counting again at the clock edge after STARTTIMER goes hi. Thus the system is in a ‘transition’
state for three clock cycles. These three clock cycles are extra. Not a part of any timing
parameter,
they are just tacked onto the time of the next state. Since the clock is so fast, the effect is almost
negligible over the one-second intervals we are concerned with.
Figure 7: Traffic Light Cycle Data Path
Figure 9: Timing Diagram of State Transition in Traffic Light Cycle
STARTTIMER has some other interesting properties. As mentioned earlier, it has to follow GS
at
the initial transition into the traffic light cycle. But after that, it has to ignore GS and just follow
the
EXPIRED bit. Thus the FSM has to differentiate between states that it cares about the EXPIRED
bit, and others where it does not.
I made a flag called EXPMODE that denotes exactly this. This flag serves as the select on a
multiplexer. Depending on the value of EXP MODE, STARTIMER will follow GS or
EXPIRED.
See Figure 7. Table 4 shows the various states and the value of EXPMODE in those states.
Table 4: Exp Mode Flag Values
State EXP MODE
Reset 0
Write 0
Read 0
All Blink States 1
All Traffic Light States 1
This solves our problem in the traffic light cycle. Because now when the system is transitioning
from the RESET state, EXPMODE is 0, and STARTTIMER follows GS. Thus STARTTIMER
will be asserted in that transition from RESET to the traffic light cycle. Once the system is in the
traffic light cycle though, EXPMODE is 1. Thus STARTTIMER will follow EXPIRED.

Most transitions in the traffic light cycle are taken no matter what. They are denoted by an X on
the
state transition diagram (Figure 3. However, in two cases an input matters. In the transition from
Side Green/Main Red to Side Yellow, the FSM checks first to see if the Traffic Sensor is
depressed.
If it is, the next state is set to Side Green/ Main Red again for TBASE. The traffic sensor is
simulated using a switch on the kit.
The second case occurs on the transition from Main Yellow/Side Red/Yellow. On this transition,
the FSM checks if there is a pending WALK request. If there is, the next state is the WALK
state,
where both Main and Side are Yellow/Red. Otherwise, if there is no Walk request present, the
FSM
just goes to Side Green/ Main Red. The Walk request is queued using a latch mechanism
attached
to a push button. Thus, in WALK mode this signal must be explicitly Unlatched. To do this and
ensure that no WALK requests can be taken while in the Walk state, the WALKRESET signal is
asserted high for the entire WALK state.

4. Blink Mode (F1 = 1, F0 = 1)


The FSM uses the same data path as in blink mode as it did in the normal traffic light cycle. The
timing issues are all identical too. The only difference is that blink mode is a little simpler, since
there are only two states. A timing diagram is shown as Figure 10. The traffic light just
transitions
between Main Yellow/Side Red and Main Red/Side Yellow every time the EXPIRED bit signals
a
transition.

Figure 10: Timing Diagram for Blink Mode


D. RAM
A HM 6264 SRAM is used to store the timing parameters. There are only four parameters, so we
used only four locations on the RAM. Table 5 shows the meaning of the four RAN locations
used.
The values stored in the RAM represent time duration in seconds. The unused RAM address
lines
were tied to GND.
Figure 11shows the RAM chip as it was wired in this laboratory. CS2 was wired to +5V, and
/OE
was tied to ground. The operation of the chip is then controlled by /CS1, which is tied to the
system CLK, and /WE, which is controlled by the FSM. The two address bits, A1 and A0 are
also
controlled by the FSM.

Figure 11: RAM Logic Diagram


1. Write cycle
It is important to have a robust write cycle. Robustness means that the address bits must be stable
for the duration of the write. If the address bits were to change while the RAM is write enabled,
the
ensuing transitions would corrupt the data at many other addresses in the RAM.
Locations in RAM can only be written when /WE is low, and both the Chip Selects are enabled.
The truth table in Table 5 illustrates this fact.
Since CS2 and /OE are always active, we ignore them. The write cycle is controlled solely by
/CS1
and /WE. /CS1 is tied to the clock and /WE is asserted for exactly ONE clock cycle by the FSM.
Figure 9reproduces the timing diagram. The write takes place when both /WE and /CS1 are low
for half a clock cycle. After this /WE goes hi again, and the RAM goes back to Read mode.
Since
the write cycle is so short, only half a clock cycle of the 440 MHz system clock, there is almost
no
chance the user can flip the address switches to screw up the write operation. By the time the
user
releases the GO button, the write operation has already been completed.
To prevent bus contention, the input data to the RAM is passed through a tri-state buffer. /WE
becoming activates this buffer, so there is input data on the bus on during the write cycle.
Afterwards, the buffer is deactivated and the output from the RAM is put back on the bus.
Sourav Dey
6.111 Laboratory #2
19
2. Read cycle
As long as the RAM is not writing, it is in Read mode. The value of the address being read is
displayed on HEX LEDs A0-A4 on the NUBUS interface. When the FSM cycles to the read
state,
all it does is change the address bits. The tri-state buffer solves bus contention problems.
E. Divider

Figure 12: Divider Logic Diagram


The divider consists of a crystal oscillator, a LS393 chip, and a LS163 chip. The logic diagram is
shown as Figure 12. The 1.8 MHz clock of the crystal oscillator is divided down 256 times by
the
LS393. The 163 then divides the output of the 393 by another factor of 16, to give us a total
division of 4096, and a system clock of 440Hz. The output of the 163 is buffered through two
inverters on a LS04 to increase the loading capabilities. This clock is then used to synchronize all
the different parts of the controller, including the RAM, FSM, and Timer.
F. SecPulse
Secpulse is our one-second clock. It is implemented using VHDL. It has two inputs, the system
CLK and STARTIMER. All the code does is increment a counter 440 times until it reaches a
maximum value. At that point, the output, SECPULSE is asserted hi and the count is reset. Thus
SECPULSE is high for one clock cycle every second. STARTTIMER serves as an asynchronous
reset, setting the count back to 0. The output, SECPULSE, is inverted before going to the Timer
because the Timer loads on /LOAD ENABLE low.
G. Timer
The timer is implemented as a LS169 up/down counter. The wiring diagram is shown in Figure
13
Figure 13: Timer Logic Diagram
/ENT is connected to the SECPULSE output from the one-second clock on the CPLD. /LD is
connected to STARTTIMER. Inputs A-D are connected to the I/O bus from the RAM. The
UP/DOWN signal is connected to GND, making the chip always count down.
The timing issues for this unit are especially complex. We will look at them in two parts,
counting
and loading. Although the 169 is connected to the system clock, it does not count down at every
clock edge. This is because /ENT is not active most of the time. It is active only one clock cycle
every second, since it is connected to SECPULSE. Thus the clock only counts down once every
second.
The 169 counts down until it hits 0000. At this point, the AND logic sitting at the outputs
recognizes the 0000 and asserts EXPIRED hi. The FSM catches the EXPIRED bit on the next
clock edge and starts to transition. The address bits change, and soon there after the
corresponding
RAM outputs become valid. At the same clock edge, STARTTIMER also goes low, thus
enabling
the 169 for a load.
Sourav Dey
6.111 Laboratory #2
21
Finally on the next clock edge, the RAM outputs are valid, and /LD is low, thus a load takes
place.
This causes the output of the 169 to change, causing the EXPIRED bit to go back low again. One
clock cycle later, after another load, STARTTIMER goes high again and the 169 is ready to
count
again.
The one-second pulse to count comes in exactly one-second after the load has taken place. This
is
because the secpulse unit is reset with the same STARTTIMER signal, so it starts to count only
after
STARTTIMER goes high again. The timing diagram for this operation was shown previously as
Figure 9
H. Latches and Synchronizers
1. Walk Latch

Fig
ure 14: Walk Latch Logic Diagram
The walk signal is latched so that when the user pushes the walk button once the signal is queued
until the FSM needs it. Figure 14shows this unit. It is implemented in VHDL on the CPLD. The
FSM can also reset the latch by asserting the WALKRESET signal. While the WALKRESET
signal
is high, the latch cannot hold any walk requests. The signal is passed through a flip-flop to
synchronize it to the system clock.
2. Go Sync
Figure 15: Go Pulse Shaper Logic Diagram
The gosync unit is a pulse-shaper. It ensures that no matter how long the GO button is depressed,
GS is only asserted for one clock cycle. It is implemented in VHDL on the CPLD. Figure 15
shows a close up of the unit. The design is taken from 6.111 Lecture 7 notes.
3. Traffic Sensor
The TRAFFIC SENSOR signal is synchronized by simply passing it through a flip-flop.

III. Testing and Debugging


A methodical approach was taken to the implementation of this system. Each component was
rigorously tested after implementing it. What follows is a chronological description of the testing
and debugging process.
A. VHDL
1. Gosync and Walk Latch
These subsystems were implemented first, because they were simple and gave a chance to hone
my
VHDL and Nova skills. Nova was used to thoroughly test both units. They were basically correct
on the first try, since the designs were lifted from the Lecture Notes.
2. SecPulse
This was also tested using Nova. The max value was set to 10 for testing purposes, since making
the
Nova window 440 clock cycles long was infeasible.
3. FSM
The FSM was implemented in steps. First the read and write operations were written and tested
thoroughly in Nova. One problem initially was that the read operation did not constantly show
the
data being read. It only showed it for one clock cycle, and then went back to the default values in
the RESET state. Creating an internal signal to remember the last address read solved the
problem.
Once read and write were giving satisfactory results, blink mode was implemented. While
designing
blink mode all the timing issues involved with the EXPIRED and STARTTIMER were slowly
worked out. There was some difficulty in reasoning through how long each should be asserted
for,
but some discussions with the TA’s and reading the spec sheets for the 169 helped clear those
issues
up.
Blink mode was tested in Nova by generating EXPIRED bits just like the LS169 would in the
real
system. Once finished with blink mode, the traffic light cycle was easy to implement.
There was one major error in the initial design – STARTTIMER was not asserted when the
controller initially entered the traffic light cycle or blink mode. A classmate pointed this issue out
before the FSM was tested on the board. The problem was fixed using a MUX and an extra
EXPMODE flag.
After this the top-level file for my CPLD, connecting the FSM, secpulse, gosync, and walk-latch
was
created. The full controller was then thoroughly tested in Nova. All of the functions, states, and
inputs were exercised.

B. Hardware
1. Divider
The two counter chips and the crystal oscillator were fairly easy to set up. The period of the
clock
was verified using the oscilloscope. It was almost exactly the 440 Hz.
2. Tri-State Buffer and RAM
The tri-state and the RAM were tested together. A1 and A0 on the RAM were hooked up directly
to some switches and the outputs were routed to a HEX led. /WE and /CS2 were connected to
switches too. Using this setup the operation of the RAM was verified.
3. Timer
After this the LS169 was hooked up to RAM and its /LD and /ENT inputs were connected to
switches. Another HEX led was attached to the outputs of the LS169. The loading and counting
operations were then tested with the RAM.

IV. Conclusion
When the switch was flipped on the system for the first time, nothing worked. Thus began the
daunting task of debugging. Probing the system in a few places found that the one-second pulse
coming from the FSM was positive logic, whereas the LS169 needed negative logic for the /ENT
signal. Instead of changing the VHDL code to fix the problem, an inverter was placed on
SECPULSE.
This simple fix caused the system to ALMOST work. The only problem now was that the system
I
was counting one extra second in every state. This was thought to be a problem in my VHDL.
But
after some time looking over the code the VHDL was found to not be the problem. Instead it was
found that the RCO on the LS169 that was generating the EXPIRED signal was not being
asserted
for the two clock cycles expected. This was because /RCO is only asserted when /ENT is active.
Thus instead of using the RCO, external AND logic was used to determine when the Timer hit
0000. After these two relatively minor errors were fixed, the system worked perfectly.
An iterative approach was taken to the problem, building skeletal functionality and adding more
and
more features as more design issues came up. Each subcomponent was constructed and tested
thoroughly before moving onto the next one. Also, all the design issues were addressed as they
came up, instead of plugging it into the board and debugging from there. Progress went slowly,
but
in the end, this is the reason the lab went fairly smoothly.
All in all, the design is robust. There are no ‘hack’ solutions, and all the design decisions were
scrutinized thoroughly before implementation. Overall, the design and implementation of the
traffic
light controller is a good first step in designing more complex system. It stressed the importance
of
designing subsystems one at a time and drew attention to various control, data path, and timing
issues common in large digital systems. Most importantly though, the lab served to teach proper
techniques engineers should use when building complex systems.

Appendix A: Logic Diagram


Figure 16: Logic Diagram of Full System

You might also like