一、功能介绍 交通红绿灯,具有红黄绿三个小指示灯和一个行人按钮,正常情况下,机动车道指示灯按照60时钟周期绿灯,5个时钟周期黄灯,10个时钟周期红灯循环。当行人按钮按下,如果剩余绿灯时间大于10个时钟,则缩短为10个时钟,小于10个时钟则保持不变。红绿灯的顺序为:红黄绿。(注:机动车道的指示灯和人行道指示灯应该是配对的,当机动车道的灯为绿或者黄时,人行道的灯为红;当机动车道的灯为红时,人行道的灯为绿,为简便起见,只考虑机动车道的指示灯。)
二、信号接口图
三、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 计数器实现一个初始延迟,确保在系统复位之后,交通灯会先保持红灯状态一段时间,然后进入正常的红黄绿循环。
四、运行结果图
五、总结 该模块通过多个计时器和状态变量实现了一个简单的交通灯控制系统。它通过时钟信号来控制红、黄、绿灯的倒计时,并且在特定情况下(如行人通过请求时)调整倒计时值。此外,该模块还通过 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
。
总结 该模块通过多个计时器和状态变量实现了一个简单的交通灯控制系统。它通过时钟信号来控制红、黄、绿灯的倒计时,并且在特定情况下(如行人通过请求时)调整倒计时值。此外,该模块还通过 flag
和 flag_cnt
实现了初始状态的控制。
flag
和 flag_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
红灯控制 flag
和 flag_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时熄灭。
初始状态的实现 flag
和 flag_cnt
的主要作用是确保系统在启动时进入一个初始状态,在这个状态下红灯保持一段时间(flag_cnt
从10递减到8的时间段)。这个初始状态可以确保交通灯系统在启动时有一个确定的、稳定的开始。
示例 假设系统刚刚启动并复位信号解除:
flag
被设置为1,flag_cnt
被设置为10。
在接下来的时钟周期中,只要 flag
为1,flag_cnt
每个周期递减1。
当 flag_cnt
变为8时,flag
被清零,并且 flag_cnt
被重置为0。
在这个过程中,红灯会在 flag_cnt
为8的那个周期被点亮,保持一段时间,直到其他控制逻辑接管。
代码中的其他部分 除了 flag
和 flag_cnt
,代码还定义了红灯、黄灯和绿灯的倒计时器(red_cnt
、yellow_cnt
和 green_cnt
),它们按照特定的逻辑递减和重置,从而实现交通灯的循环控制。flag
和 flag_cnt
的主要作用是提供一个初始状态控制机制,确保系统在启动时有一个确定的状态。
总结
flag
和 flag_cnt
用于系统启动后的初始状态控制。
它们确保在系统启动时红灯能够点亮,并保持一段时间。
当 flag_cnt
变为8时,触发红灯点亮,从而为系统提供一个稳定的启动状态。 这样,通过 flag
和 flag_cnt
的控制,交通灯系统可以在启动时按照预期进入一个确定的状态,并在之后正常工作。