Verilog 实现十字路口交通灯控制器设计
首先需要定义输入输出端口:
module traffic_light_controller(
input clk,
input reset,
output reg [2:0] ew_light, //东西方向的红绿黄灯
output reg [2:0] ns_light, //南北方向的红绿黄灯
output reg [7:0] display //数码管显示
);
为方便起见,我们使用 'ew_light' 和 'ns_light' 来表示东西方向和南北方向的红绿黄灯状态,分别使用 3 位二进制数表示,其中第 0 位表示绿灯状态,第 1 位表示黄灯状态,第 2 位表示红灯状态。例如,当 'ew_light' 的值为 3'b010 时,表示东西方向的黄灯亮,其他灯都不亮。
接下来,我们需要定义状态机来控制交通灯的状态转移。在这个状态机中,我们需要考虑交通灯的 3 种状态(绿灯、黄灯、红灯),以及两个方向的交通灯状态转移的同步问题。
reg [2:0] ew_state; //东西方向交通灯状态
reg [2:0] ns_state; //南北方向交通灯状态
parameter EW_GREEN = 3'b001;
parameter EW_YELLOW = 3'b010;
parameter EW_RED = 3'b100;
parameter NS_GREEN = 3'b100;
parameter NS_YELLOW = 3'b010;
parameter NS_RED = 3'b001;
//状态转移
always @(posedge clk, negedge reset) begin
if (reset) begin //复位状态
ew_state <= EW_RED;
ns_state <= NS_GREEN;
end else begin
case (ew_state)
EW_GREEN: begin
if (ns_state == NS_RED) begin
ew_state <= EW_YELLOW;
ns_state <= NS_RED;
end else begin
ew_state <= EW_YELLOW;
ns_state <= NS_GREEN;
end
end
EW_YELLOW: begin
ew_state <= EW_RED;
ns_state <= NS_RED;
end
EW_RED: begin
if (ns_state == NS_GREEN) begin
ew_state <= EW_GREEN;
ns_state <= NS_YELLOW;
end else begin
ew_state <= EW_GREEN;
ns_state <= NS_GREEN;
end
end
endcase
case (ns_state)
NS_GREEN: begin
if (ew_state == EW_RED) begin
ns_state <= NS_YELLOW;
ew_state <= EW_RED;
end else begin
ns_state <= NS_YELLOW;
ew_state <= EW_GREEN;
end
end
NS_YELLOW: begin
ns_state <= NS_RED;
ew_state <= EW_RED;
end
NS_RED: begin
if (ew_state == EW_GREEN) begin
ns_state <= NS_GREEN;
ew_state <= EW_YELLOW;
end else begin
ns_state <= NS_GREEN;
ew_state <= EW_GREEN;
end
end
endcase
end
end
在状态转移过程中,我们需要注意同步问题。例如,在东西方向的绿灯状态下,如果南北方向的交通灯状态为红灯,那么在东西方向的黄灯状态下,南北方向的交通灯状态依然应该是红灯。
接下来,我们需要根据交通灯状态来控制红绿黄灯的亮灭。同时,我们也需要设计一个倒计时电路来控制数码管的显示。
reg [3:0] countdown; //倒计时计数器
always @(posedge clk, negedge reset) begin
if (reset) begin //复位状态
countdown <= 4'b0000;
ew_light <= EW_RED;
ns_light <= NS_GREEN;
display <= 8'b00000000;
end else begin
countdown <= countdown + 1;
case (ew_state)
EW_GREEN: begin
ew_light <= 3'b001; //绿灯亮
ns_light <= 3'b100; //红灯亮
if (countdown == 5000) begin //倒计时 5s
countdown <= 4'b0000;
ew_light <= 3'b010; //黄灯亮
end
end
EW_YELLOW: begin
ew_light <= 3'b010; //黄灯亮
ns_light <= 3'b100; //红灯亮
if (countdown == 3000) begin //倒计时 3s
countdown <= 4'b0000;
ew_light <= 3'b100; //红灯亮
end
end
EW_RED: begin
ew_light <= 3'b100; //红灯亮
ns_light <= 3'b001; //绿灯亮
if (countdown == 8000) begin //倒计时 8s
countdown <= 4'b0000;
ns_light <= 3'b010; //黄灯亮
end
end
endcase
case (ns_state)
NS_GREEN: begin
ns_light <= 3'b001; //绿灯亮
ew_light <= 3'b100; //红灯亮
if (countdown == 5000) begin //倒计时 5s
countdown <= 4'b0000;
ns_light <= 3'b010; //黄灯亮
end
end
NS_YELLOW: begin
ns_light <= 3'b010; //黄灯亮
ew_light <= 3'b100; //红灯亮
if (countdown == 3000) begin //倒计时 3s
countdown <= 4'b0000;
ns_light <= 3'b100; //红灯亮
end
end
NS_RED: begin
ns_light <= 3'b100; //红灯亮
ew_light <= 3'b001; //绿灯亮
if (countdown == 8000) begin //倒计时 8s
countdown <= 4'b0000;
ew_light <= 3'b010; //黄灯亮
end
end
endcase
//倒计时电路
case ({ew_light, ns_light})
6'b001100, 6'b001010, 6'b100001, 6'b010001: display <= 8'b00001000; //绿灯,显示 5s
6'b010100, 6'b100010, 6'b001001, 6'b000101: display <= 8'b00000100; //黄灯,显示 3s
6'b100010, 6'b010001, 6'b001100, 6'b000110: display <= 8'b00001000; //红灯,显示 8s
default: display <= 8'b00000000;
endcase
end
end
在倒计时电路中,我们根据当前的红绿黄灯状态来判断需要显示多长时间,然后将倒计时的值通过 'display' 输出到数码管上。
完整代码如下:
module traffic_light_controller(
input clk,
input reset,
output reg [2:0] ew_light, //东西方向的红绿黄灯
output reg [2:0] ns_light, //南北方向的红绿黄灯
output reg [7:0] display //数码管显示
);
reg [2:0] ew_state; //东西方向交通灯状态
reg [2:0] ns_state; //南北方向交通灯状态
reg [3:0] countdown; //倒计时计数器
parameter EW_GREEN = 3'b001;
parameter EW_YELLOW = 3'b010;
parameter EW_RED = 3'b100;
parameter NS_GREEN = 3'b100;
parameter NS_YELLOW = 3'b010;
parameter NS_RED = 3'b001;
//状态转移
always @(posedge clk, negedge reset) begin
if (reset) begin //复位状态
ew_state <= EW_RED;
ns_state <= NS_GREEN;
end else begin
countdown <= countdown + 1;
case (ew_state)
EW_GREEN: begin
ew_light <= 3'b001; //绿灯亮
ns_light <= 3'b100; //红灯亮
if (countdown == 5000) begin //倒计时 5s
countdown <= 4'b0000;
ew_light <= 3'b010; //黄灯亮
end
end
EW_YELLOW: begin
ew_light <= 3'b010; //黄灯亮
ns_light <= 3'b100; //红灯亮
if (countdown == 3000) begin //倒计时 3s
countdown <= 4'b0000;
ew_light <= 3'b100; //红灯亮
end
end
EW_RED: begin
ew_light <= 3'b100; //红灯亮
ns_light <= 3'b001; //绿灯亮
if (countdown == 8000) begin //倒计时 8s
countdown <= 4'b0000;
ns_light <= 3'b010; //黄灯亮
end
end
endcase
case (ns_state)
NS_GREEN: begin
ns_light <= 3'b001; //绿灯亮
ew_light <= 3'b100; //红灯亮
if (countdown == 5000) begin //倒计时 5s
countdown <= 4'b0000;
ns_light <= 3'b010; //黄灯亮
end
end
NS_YELLOW: begin
ns_light <= 3'b010; //黄灯亮
ew_light <= 3'b100; //红灯亮
if (countdown == 3000) begin //倒计时 3s
countdown <= 4'b0000;
ns_light <= 3'b100; //红灯亮
end
end
NS_RED: begin
ns_light <= 3'b100; //红灯亮
ew_light <= 3'b001; //绿灯亮
if (countdown == 8000) begin //倒计时 8s
countdown <= 4'b0000;
ew_light <= 3'b010; //黄灯亮
end
end
endcase
//倒计时电路
case ({ew_light, ns_light})
6'b001100, 6'b001010, 6'b100001, 6'b010001: display <= 8'b00001000; //绿灯,显示 5s
6'b010100, 6'b100010, 6'b001001, 6'b000101: display <= 8'b00000100; //黄灯,显示 3s
6'b100010, 6'b010001, 6'b001100, 6'b000110: display <= 8'b00001000; //红灯,显示 8s
default: display <= 8'b00000000;
endcase
end
end
endmodule
原文地址: https://www.cveoy.top/t/topic/lxzU 著作权归作者所有。请勿转载和采集!