This article is a summary of the state machine-traffic light part of the article Verilog learning code summary .
This state machine is a mealy type sequential circuit.
Adopt three-stage design.
topic
Design a traffic light controller. At an intersection, the east-west direction is the main road (HighWay), and the north-south direction is the secondary road (CountryWay). There are very few vehicles on the secondary arterial road, so there is a vehicle detector (Sensor) at the intersection to determine whether there are cars on the secondary arterial road. If there are no cars, the main road will always have a green light; if there are cars on the secondary road, the main road will have a red light (Red) after 40 seconds of passage on the main road, while the secondary road will have a green light, and the passage time will be 20 seconds. At this time, regardless of whether there are cars on the sub-trunk road, the sub-trunk road will have a red light, while the main road will have a green light. There is a 4-second yellow light in the transition from green light to red light.
Require:
1. Draw a finite state machine and indicate the state transition conditions;
2. Write program code, mark instructions and explanations;
3. Write a verification program to fully verify the design.
State transition diagram
source code
The program source code is divided into 2 sub-modules (counter module + traffic light module) + top module
Counter module
module counter(out,clk,enable,rst);
output[6:0] out;
input clk, rst,enable;
reg[6:0] out;
always @ (posedge rst or posedge clk) begin
if (rst) begin
out <= 8'b0;
end else if (enable) begin
out <= (out + 1)%69;
end
end
endmodule
traffic light module
module light(highWay,countryWay,counter_enable,clk,rst,senor,count);
input clk,rst,senor;
input [6:0] count;
output counter_enable;
output [1:0] highWay,countryWay;
reg counter_enable;
reg [1:0] highWay,countryWay;
//标志计数状态
wire [6:0] count;
//主干状态,副干状态与之对应
reg [1:0] cur_state,next_state;
//灯输出结果常量
parameter GREEN = 2'b00,
YELLOW = 2'b01,
RED = 2'b11;
//状态常量
parameter PASS = 2'b00,
WAIT1 = 2'b01,
WAIT2 = 2'b10,
STOP = 2'b11;
//根据下一状态或重置改变现在状态
always @(posedge rst or posedge clk) begin
if(rst) begin
cur_state <= PASS;
next_state <= PASS;
counter_enable <= 0;
end else begin
cur_state <= next_state;
end
end
//不同状态不同输出
always @(cur_state) begin
case (cur_state)
PASS:begin
highWay = GREEN;
countryWay = RED;
end
WAIT1:begin
highWay = YELLOW;
countryWay = YELLOW;
end
WAIT2:begin
highWay = YELLOW;
countryWay = YELLOW;
end
STOP:begin
highWay = RED;
countryWay = GREEN;
end
default: begin
highWay = GREEN;
countryWay = RED;
end
endcase
end
//根据输入改变下一预设状态
always @(senor or count) begin
next_state = PASS;
case (cur_state)
PASS:begin
if (senor) begin
if (count==40) begin
next_state = WAIT1;
end
counter_enable = 1;
end else begin
counter_enable = 0;
end
end
WAIT1:begin
next_state = (count==44)?STOP:WAIT1;
end
WAIT2:begin
next_state = (count==68)?PASS:WAIT2;
end
STOP:begin
next_state = (count==64)?WAIT2:STOP;
end
endcase
end
endmodule
top-level module
module top(highWay,countryWay,clk,rst,senor);
input clk,rst,senor;
output [1:0] highWay,countryWay;
wire counter_enable;
wire [6:0] count;
light i1(.highWay(highWay),.countryWay(countryWay),
.counter_enable(counter_enable),
.clk(clk),.rst(rst),
.senor(senor),.count(count));
counter c1(.out(count),.clk(clk),
.enable(counter_enable),.rst(rst));
endmodule
Note: In the current code, the trunk and deputy trunk states correspond to each other by default, red (main)-green (deputy), yellow (main)-yellow (deputy), green (main)-red (deputy).
But that's not the case.
When designing many traffic lights, a yellow light only needs to be interspersed when red->green, just like the last sentence of the question. Therefore, my design actually does not meet the requirements of the question.
If you want to make it more realistic, then you need to add two more variables: cur_state2
and next_state2
to save the status of the deputy leader. At the same time, delete the state in the state machine WAIT1
so that it PASS
points directly STOP
.
test code
`timescale 1ns/1ns
module tb_light;
reg clk,rst,senor;
wire [1:0] highWay,countryWay;
parameter INTERVAL = 10;
//初始化各值
initial begin
clk = 1'b0;
rst = 1'b0;
senor = 1'b0;
end
//设定时钟周期
initial
forever #(INTERVAL/2) clk = ~clk;
//重置模块
initial begin
#INTERVAL rst = 1;
#INTERVAL rst = 0;
end
initial begin
//测试副干有车情况
#(5*INTERVAL) senor = 1'b1;
//测试副干无车情况
#(60*INTERVAL) senor = 1'b0;
#(100*INTERVAL) $finish;
end
//实例化模块
top t1(highWay,countryWay,clk,rst,senor);
endmodule
Note: The traffic light module is senor
used to determine whether it is in the timing state. If in the test code, the time senor=0
is in PASS
the state of the main trunk ( senor=0
meaning that the deputy trunk car is gone, in the trunk PASS
state, the original car of the assistant trunk suddenly disappears? It may be too late to turn around at the intersection... so it is a false proposition in itself ——Of course, this excludes equipment failure). Note that the traffic light module does not clear the counter module, so the next time it is used, the senor=1
trunk traffic time may be less than 40S.