Verilog交通灯存档

一、功能介绍

交通红绿灯,具有红黄绿三个小指示灯和一个行人按钮,正常情况下,机动车道指示灯按照60时钟周期绿灯,5个时钟周期黄灯,10个时钟周期红灯循环。当行人按钮按下,如果剩余绿灯时间大于10个时钟,则缩短为10个时钟,小于10个时钟则保持不变。红绿灯的顺序为:红黄绿。(注:机动车道的指示灯和人行道指示灯应该是配对的,当机动车道的灯为绿或者黄时,人行道的灯为红;当机动车道的灯为红时,人行道的灯为绿,为简便起见,只考虑机动车道的指示灯。)

二、信号接口图

Alt Text

三、Verilog代码

1、输入描述:

clk:系统时钟信号。
rst_n:复位信号,低电平有效。
pass_request:行人按钮信号,当该信号为1,表示按钮按下,如果剩余绿灯时间大于10个时钟,则缩短为10个时钟,小于10个时钟则保持不变。

2、输出描述:

clock:当前灯计时器值,8位宽度。
red:红灯信号。
yellow:黄灯信号。
green:绿灯信号。
red_cnt:红灯倒计时计数器,8位宽度。
yellow_cnt:黄灯倒计时计数器,8位宽度。
green_cnt:绿灯倒计时计数器,8位宽度
clock_cnt:当前灯的倒计时值。
flag:控制红灯初始状态的标志信号。
flag_cnt:标志信号倒计时计数器,4位宽度。

3、具体代码:

module triffic_light
(
input rst_n,
input clk,
input pass_request,
output wire[7:0]clock,
output reg red,
output reg yellow,
output reg green,
output reg[7:0] red_cnt,
output reg[7:0] yellow_cnt,
output reg[7:0] green_cnt,
output reg[7:0] clock_cnt,
output reg flag,
output reg[3:0] flag_cnt
);

always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
flag <= 1;
flag_cnt <= 10;
end
else if (flag_cnt == 8)begin
flag_cnt <=0;
flag <=0;
end
else if(flag)
flag_cnt <= flag_cnt - 1;

end

always@(posedge clk or negedge rst_n)begin
if(!rst_n)
green_cnt <= 60;
else if(pass_request)begin
if(green_cnt>10)
green_cnt <= 10;
else
green_cnt <= green_cnt;
end
else if(green)
green_cnt <= green_cnt-1;
else if(yellow_cnt==1)
green_cnt <= 60;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
yellow_cnt <= 5;
else if(yellow)
yellow_cnt <= yellow_cnt-1;
else if(red_cnt==1)
yellow_cnt <= 5;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
red_cnt <= 0;
else if(red)
red_cnt <= red_cnt-1;
else if(green_cnt==1||flag_cnt==8)
red_cnt <= 10;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
green <= 0;
else if(yellow_cnt==1)
green <= 1;
else if(green_cnt==1)
green <= 0;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
yellow <= 0;
else if(red_cnt==1)
yellow <= 1;
else if(yellow_cnt==1)
yellow <= 0;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
red <= 0;
else if(flag_cnt==8||green_cnt==1)
red <= 1;
else if(red_cnt==1)
red <= 0;
end
always@(*)begin
if(!rst_n)
clock_cnt <= 10;
else if(red)
clock_cnt <= red_cnt;
else if(yellow)
clock_cnt <= yellow_cnt;
else if(green)
clock_cnt <= green_cnt;
else
clock_cnt <= flag_cnt;
end
assign clock = clock_cnt;
endmodule

// testbeach代码
module traffic_tb;

// Inputs
reg rst_n;
reg clk;
reg pass_request;

// Outputs
wire [7:0] clock;
wire red;
wire yellow;
wire green;
wire [7:0] red_cnt;
wire [7:0] yellow_cnt;
wire [7:0] green_cnt;
wire [7:0] clock_cnt;
wire flag;
wire [3:0] flag_cnt;

// Instantiate the Unit Under Test (UUT)
triffic_light uut (
.rst_n(rst_n),
.clk(clk),
.pass_request(pass_request),
.clock(clock),
.red(red),
.yellow(yellow),
.green(green),
.red_cnt(red_cnt),
.yellow_cnt(yellow_cnt),
.green_cnt(green_cnt),
.clock_cnt(clock_cnt),
.flag(flag),
.flag_cnt(flag_cnt)
);

// Clock generation
initial begin
clk = 0;
forever #5 clk = ~clk; // Generate a clock with 100 MHz frequency
end

// Initial Conditions and Test Stimuli
initial begin
// Initialize Inputs
rst_n = 0;
pass_request = 0;

// Reset the system
#10;
rst_n = 1;

// Wait for system to stabilize
#10;

// Test pass request functionality
#50 pass_request = 1;
#20 pass_request = 0;

// Continue the simulation for more scenarios
#100;

// Test traffic light behavior without requests
#200;

// Introduce another pass request
#50 pass_request = 1;
#20 pass_request = 0;

// End simulation
#300 $finish;
end

// Optional: Display output values for debugging
initial begin
$monitor("Time = %t, rst_n = %b, clk = %b, pass_request = %b, red = %b, yellow = %b, green = %b, red_cnt = %d, yellow_cnt = %d, green_cnt = %d, flag = %b, flag_cnt = %d, clock = %d",
$time, rst_n, clk, pass_request, red, yellow, green, red_cnt, yellow_cnt, green_cnt, flag, flag_cnt, clock);
end

endmodule

4、flag和flag_cnt的作用:

flag信号和 flag_cnt 计数器实现一个初始延迟,确保在系统复位之后,交通灯会先保持红灯状态一段时间,然后进入正常的红黄绿循环。

四、运行结果图

Alt Text

五、总结

该模块通过多个计时器和状态变量实现了一个简单的交通灯控制系统。它通过时钟信号来控制红、黄、绿灯的倒计时,并且在特定情况下(如行人通过请求时)调整倒计时值。此外,该模块还通过 flag 和 flag_cnt 实现了初始状态的控制。

代码分析

这段Verilog代码实现了一个交通灯控制模块 triffic_light,它基于输入时钟 clk 和复位信号 rst_n,以及行人通过请求信号 pass_request 来控制红灯、黄灯和绿灯的状态。下面是对这段代码的详细分析:

模块端口说明

  • 输入端口
    • rst_n:复位信号,低电平有效。
    • clk:时钟信号。
    • pass_request:行人通过请求信号。
  • 输出端口
    • clock:当前灯计时器值,8位宽度。
    • red:红灯信号。
    • yellow:黄灯信号。
    • green:绿灯信号。
    • red_cnt:红灯倒计时计数器,8位宽度。
    • yellow_cnt:黄灯倒计时计数器,8位宽度。
    • green_cnt:绿灯倒计时计数器,8位宽度。
    • clock_cnt:当前灯的倒计时值。
    • flag:控制红灯初始状态的标志信号。
    • flag_cnt:标志信号倒计时计数器,4位宽度。

主要功能模块

flag和flag_cnt的控制

always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
flag <= 1;
flag_cnt <= 10;
end else if (flag_cnt == 8) begin
flag_cnt <= 0;
flag <= 0;
end else if(flag) begin
flag_cnt <= flag_cnt - 1;
end
end
  • 在复位时,flag 被设置为1,flag_cnt 被设置为10。
  • flag_cnt 倒计时到8时,flag 被清零,flag_cnt 被重置为0。
  • 如果 flag 为1,flag_cnt 每个时钟周期递减。

绿灯计时器green_cnt的控制

always@(posedge clk or negedge rst_n) begin
if(!rst_n)
green_cnt <= 60;
else if(pass_request) begin
if(green_cnt > 10)
green_cnt <= 10;
else
green_cnt <= green_cnt;
end else if(green)
green_cnt <= green_cnt - 1;
else if(yellow_cnt == 1)
green_cnt <= 60;
end
  • 在复位时,green_cnt 被设置为60。
  • 当有行人通过请求时,如果 green_cnt 大于10,则将 green_cnt 设置为10。
  • 如果绿灯亮 (green 为1),则 green_cnt 每个时钟周期递减。
  • 如果黄灯计时器 yellow_cnt 倒计时到1时,green_cnt 被重置为60。

黄灯计时器yellow_cnt的控制

always@(posedge clk or negedge rst_n) begin
if(!rst_n)
yellow_cnt <= 5;
else if(yellow)
yellow_cnt <= yellow_cnt - 1;
else if(red_cnt == 1)
yellow_cnt <= 5;
end
  • 在复位时,yellow_cnt 被设置为5。
  • 如果黄灯亮 (yellow 为1),则 yellow_cnt 每个时钟周期递减。
  • 如果红灯计时器 red_cnt 倒计时到1时,yellow_cnt 被重置为5。

红灯计时器red_cnt的控制

always@(posedge clk or negedge rst_n) begin
if(!rst_n)
red_cnt <= 0;
else if(red)
red_cnt <= red_cnt - 1;
else if(green_cnt == 1 || flag_cnt == 8)
red_cnt <= 10;
end
  • 在复位时,red_cnt 被设置为0。
  • 如果红灯亮 (red 为1),则 red_cnt 每个时钟周期递减。
  • 如果绿灯计时器 green_cnt 倒计时到1或者 flag_cnt 为8时,red_cnt 被重置为10。

绿灯信号green的控制

always@(posedge clk or negedge rst_n) begin
if(!rst_n)
green <= 0;
else if(yellow_cnt == 1)
green <= 1;
else if(green_cnt == 1)
green <= 0;
end
  • 在复位时,green 被设置为0。
  • 当黄灯计时器 yellow_cnt 倒计时到1时,green 被设置为1(绿灯亮)。
  • 当绿灯计时器 green_cnt 倒计时到1时,green 被清零(绿灯灭)。

黄灯信号yellow的控制

always@(posedge clk or negedge rst_n) begin
if(!rst_n)
yellow <= 0;
else if(red_cnt == 1)
yellow <= 1;
else if(yellow_cnt == 1)
yellow <= 0;
end
  • 在复位时,yellow 被设置为0。
  • 当红灯计时器 red_cnt 倒计时到1时,yellow 被设置为1(黄灯亮)。
  • 当黄灯计时器 yellow_cnt 倒计时到1时,yellow 被清零(黄灯灭)。

红灯信号red的控制

always@(posedge clk or negedge rst_n) begin
if(!rst_n)
red <= 0;
else if(flag_cnt == 8 || green_cnt == 1)
red <= 1;
else if(red_cnt == 1)
red <= 0;
end
  • 在复位时,red 被设置为0。
  • flag_cnt 为8或者绿灯计时器 green_cnt 倒计时到1时,red 被设置为1(红灯亮)。
  • 当红灯计时器 red_cnt 倒计时到1时,red 被清零(红灯灭)。

当前灯倒计时值clock_cnt的控制

always@(*) begin
if(!rst_n)
clock_cnt <= 10;
else if(red)
clock_cnt <= red_cnt;
else if(yellow)
clock_cnt <= yellow_cnt;
else if(green)
clock_cnt <= green_cnt;
else
clock_cnt <= flag_cnt;
end
  • 在复位时,clock_cnt 被设置为10。
  • 如果红灯亮,clock_cnt 等于 red_cnt
  • 如果黄灯亮,clock_cnt 等于 yellow_cnt
  • 如果绿灯亮,clock_cnt 等于 green_cnt
  • 否则,clock_cnt 等于 flag_cnt

总结

该模块通过多个计时器和状态变量实现了一个简单的交通灯控制系统。它通过时钟信号来控制红、黄、绿灯的倒计时,并且在特定情况下(如行人通过请求时)调整倒计时值。此外,该模块还通过 flagflag_cnt 实现了初始状态的控制。

flagflag_cnt 详细作用

初始状态设置

当系统复位(rst_n 为低)时,flag 被设置为1,flag_cnt 被设置为10。这表示在系统启动时,我们处于一个初始状态。

if (!rst_n) begin
flag <= 1;
flag_cnt <= 10;
end

标志计数器控制

在每一个时钟上升沿,如果 flag 为1,flag_cnt 会递减1,直到 flag_cnt 变为8,此时 flag 被清零,flag_cnt 被重置为0。

else if (flag_cnt == 8) begin
flag_cnt <= 0;
flag <= 0;
end else if (flag) begin
flag_cnt <= flag_cnt - 1;
end

红灯控制

flagflag_cnt 直接影响红灯的状态。

always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
red <= 0;
end else if (flag_cnt == 8 || green_cnt == 1) begin
red <= 1;
end else if (red_cnt == 1) begin
red <= 0;
end
end

在复位时,红灯被设置为0(熄灭)。当 flag_cnt 等于8(即 flag 由1变为0的时刻)或者绿灯计时器 green_cnt 变为1时,红灯被点亮。红灯会在红灯计时器 red_cnt 变为1时熄灭。

初始状态的实现

flagflag_cnt 的主要作用是确保系统在启动时进入一个初始状态,在这个状态下红灯保持一段时间(flag_cnt 从10递减到8的时间段)。这个初始状态可以确保交通灯系统在启动时有一个确定的、稳定的开始。

示例

假设系统刚刚启动并复位信号解除:

  1. flag 被设置为1,flag_cnt 被设置为10。
  2. 在接下来的时钟周期中,只要 flag 为1,flag_cnt 每个周期递减1。
  3. flag_cnt 变为8时,flag 被清零,并且 flag_cnt 被重置为0。
  4. 在这个过程中,红灯会在 flag_cnt 为8的那个周期被点亮,保持一段时间,直到其他控制逻辑接管。

代码中的其他部分

除了 flagflag_cnt,代码还定义了红灯、黄灯和绿灯的倒计时器(red_cntyellow_cntgreen_cnt),它们按照特定的逻辑递减和重置,从而实现交通灯的循环控制。flagflag_cnt 的主要作用是提供一个初始状态控制机制,确保系统在启动时有一个确定的状态。

总结

  • flagflag_cnt 用于系统启动后的初始状态控制。
  • 它们确保在系统启动时红灯能够点亮,并保持一段时间。
  • flag_cnt 变为8时,触发红灯点亮,从而为系统提供一个稳定的启动状态。
    这样,通过 flagflag_cnt 的控制,交通灯系统可以在启动时按照预期进入一个确定的状态,并在之后正常工作。