Verilog 交通灯控制模块代码解析及优化
这是一个 Verilog 模块,用于控制交通灯的状态。下面是每一句的解释:
-
module control ( ... ):定义模块名为'control',并设置了一些输入输出端口。 -
input CLOCK_50:输入端口,代表板载 50MHz 时钟。 -
input Q_KEY:输入端口,代表按键的状态。 -
input guang1:输入端口,代表南北方向流量传感器接口。 -
input guang2:输入端口,代表东西方向流量传感器接口。 -
input [9:1] KEY:输入端口,代表按键的值。 -
output reg[15:0] data:输出端口,代表数码管显示的数据。 -
output reg[15:0] liul:输出端口,代表流量计数器的值。 -
output reg[5:0] led:输出端口,代表 LED 灯的状态。 -
reg[7:0] nabeiliu:定义一个 8 位寄存器,代表南北方向的流量计数。 -
reg[7:0] dongxiliu:定义一个 8 位寄存器,代表东西方向的流量计数。 -
reg F1,F2:定义两个 1 位寄存器,用于检测南北方向流量传感器的引脚信号。 -
always @(posedge CLOCK_50 or negedge Q_KEY):定义一个时序逻辑块,当 CLOCK_50 上升沿或 Q_KEY 下降沿到来时触发。 -
if(!Q_KEY):判断按键是否按下,如果按下,则执行以下代码。 -
F1<=1'b1; F2<=1'b1;:将 F1 和 F2 寄存器置为 1,用于初始化。 -
else:如果按键没有按下,则执行以下代码。 -
F1<=guang1; F2<=F1;:将 F1 寄存器赋值为 guang1 信号,将 F2 寄存器赋值为 F1 寄存器。 -
assign SCK_fallingedge1 = F2 && !F1:定义一个组合逻辑块,当 F2 为 1 且 F1 为 0 时,SCK_fallingedge1 为 1,表示检测到时钟下降沿。 -
assign SCK_risingedge1 = F1 && !F2:定义一个组合逻辑块,当 F1 为 1 且 F2 为 0 时,SCK_risingedge1 为 1,表示检测到时钟上升沿。 -
reg F3,F4:定义两个 1 位寄存器,用于检测东西方向流量传感器的引脚信号。 -
reg aa,bb:定义两个 1 位寄存器,用于保存流量计数状态。 -
always @(posedge CLOCK_50 or negedge Q_KEY):定义一个时序逻辑块,当 CLOCK_50 上升沿或 Q_KEY 下降沿到来时触发。 -
if(!Q_KEY):判断按键是否按下,如果按下,则执行以下代码。 -
F3<=1'b1; F4<=1'b1;:将 F3 和 F4 寄存器置为 1,用于初始化。 -
else:如果按键没有按下,则执行以下代码。 -
F3<=guang2; F4<=F3;:将 F3 寄存器赋值为 guang2 信号,将 F4 寄存器赋值为 F3 寄存器。 -
assign SCK_fallingedge2 = F4 && !F3:定义一个组合逻辑块,当 F4 为 1 且 F3 为 0 时,SCK_fallingedge2 为 1,表示检测到时钟下降沿。 -
assign SCK_risingedge2 = F3 && !F4:定义一个组合逻辑块,当 F3 为 1 且 F4 为 0 时,SCK_risingedge2 为 1,表示检测到时钟上升沿。 -
reg [25:0] cnt2:定义一个 26 位寄存器,用于计数。 -
reg [25:0] cnt1:定义一个 26 位寄存器,用于计数。 -
reg [25:0] cnt:定义一个 26 位寄存器,用于计数。 -
reg uu1:定义一个 1 位寄存器,用于保存流量计数状态。 -
reg uu2:定义一个 1 位寄存器,用于保存流量计数状态。 -
reg [7:0] t_buf1:定义一个 8 位寄存器,用于保存流量计数状态。 -
reg [7:0] t_buf2:定义一个 8 位寄存器,用于保存流量计数状态。 -
reg [3:0] moshi:定义一个 4 位寄存器,用于保存工作模式。 -
reg[2:0] state:定义一个 3 位寄存器,用于保存交通灯状态。 -
reg [6:0] shijiandx,shijiannb:定义两个 7 位寄存器,用于保存南北和东西方向的通行时间。 -
reg ff:定义一个 1 位寄存器,用于保存夜间模式状态。 -
reg [7:0] sec:定义一个 8 位寄存器,用于保存计时秒数。 -
reg [6:0] ttdx,ttnb:定义两个 7 位寄存器,用于保存南北和东西方向的剩余时间。 -
wire [9:1] key_val:定义一个 9 位线网,用于保存按键的值。 -
key_debounce u0( ... ):实例化一个名为 u0 的 key_debounce 模块,用于按键去抖。 -
always @(posedge CLOCK_50, negedge Q_KEY):定义一个时序逻辑块,当 CLOCK_50 上升沿或 Q_KEY 下降沿到来时触发。 -
if(!Q_KEY):判断按键是否按下,如果按下,则执行以下代码。 -
nabeiliu<=0; dongxiliu<=0; cnt1 <= 0; cnt <= 0;:初始化流量计数器和计时器。 -
sec=0; moshi=0; shijiandx=20; shijiannb=20; cnt2=0; sec=0;:初始化时间设置和计时器。 -
else:如果按键没有按下,则执行以下代码。 -
case (1'b0):根据按键值执行不同的操作。 -
key_val[1] : moshi=1;:当按键 1 被按下时,进入时间调节模式。 -
key_val[2] : moshi=1;:当按键 2 被按下时,进入时间调节模式。 -
key_val[3] : moshi=1;:当按键 3 被按下时,进入时间调节模式。 -
key_val[4] : moshi=1;:当按键 4 被按下时,进入时间调节模式。 -
key_val[5] : moshi=2;:当按键 5 被按下时,进入东西方向通行模式。 -
key_val[6] : moshi=3;:当按键 6 被按下时,进入南北方向通行模式。 -
key_val[7] : moshi=4;:当按键 7 被按下时,进入夜间模式。 -
key_val[8] : moshi=5;:当按键 8 被按下时,进入按流量通行模式。 -
key_val[9] : moshi=0;:当按键 9 被按下时,进入正常模式。 -
if(SCK_fallingedge1 == 1):判断南北方向流量传感器是否检测到时钟下降沿。 -
uu1=1;:将 uu1 寄存器置为 1,表示检测到流量。 -
if(SCK_fallingedge2 == 1):判断东西方向流量传感器是否检测到时钟下降沿。 -
uu2=1;:将 uu2 寄存器置为 1,表示检测到流量。 -
if (cnt1 == 9_999_999):判断 cnt1 计数器是否达到最大值。 -
cnt1 <= 0;:将 cnt1 计数器复位。 -
if(guang1==1&&uu1==1):判断南北方向流量传感器是否检测到流量信号。 -
uu1<=0; nabeiliu<=nabeiliu+1;:将 uu1 寄存器复位,南北方向流量计数器加 1。 -
if(guang2==1&&uu2==1):判断东西方向流量传感器是否检测到流量信号。 -
uu2<=0; dongxiliu<=dongxiliu+1;:将 uu2 寄存器复位,东西方向流量计数器加 1。 -
else:如果 cnt1 计数器没有达到最大值,则执行以下代码。 -
cnt1 <= cnt1 + 1'b1;:将 cnt1 计数器加 1。 -
if(moshi==0):判断是否处于正常模式。 -
if (cnt == 49_999_999):判断 cnt 计数器是否达到最大值。 -
cnt <= 0;:将 cnt 计数器复位。 -
if(sec==(shijiannb+shijiandx+11))sec=0; else sec=sec+1;:将 sec 计时器加 1,如果达到最大值,则复位。 -
if(sec<=shijiannb):判断当前时间是否小于南北方向的通行时间。 -
state=0; ttnb=shijiannb-sec; ttdx=shijiannb-sec+5;:设置交通灯状态为南北方向通行,并计算剩余时间。 -
else if(sec>shijiannb&&sec<=(shijiannb+5)):判断当前时间是否在南北方向黄灯时间内。 -
state=1; ttnb=shijiannb-sec+5; ttdx=shijiannb-sec+5;:设置交通灯状态为南北方向黄灯,并计算剩余时间。 -
else if(sec>(shijiannb+5)&&sec<=(shijiannb+shijiandx+1+5)):判断当前时间是否在东西方向通行时间内。 -
state=2; ttnb=(shijiannb+shijiandx+1)-sec+10; ttdx=(shijiannb+shijiandx+1)-sec+5;:设置交通灯状态为东西方向通行,并计算剩余时间。 -
else if(sec>(shijiannb+shijiandx+6)):判断当前时间是否在东西方向黄灯时间内。 -
state=3; ttnb=(shijiannb+shijiandx+11)-sec; ttdx=(shijiannb+shijiandx+11)-sec;:设置交通灯状态为东西方向黄灯,并计算剩余时间。 -
else:如果 cnt 计数器没有达到最大值,则执行以下代码。 -
cnt <= cnt + 1'b1;:将 cnt 计数器加 1。 -
if(state==0):判断交通灯状态是否为南北方向通行。 -
led<= 6'b011_101:设置 LED 灯状态为南北方向通行。 -
else if(state==1):判断交通灯状态是否为南北方向黄灯。 -
led<= 6'b011_110:设置 LED 灯状态为南北方向黄灯。 -
else if(state==2):判断交通灯状态是否为东西方向通行。 -
led<= 6'b101_011:设置 LED 灯状态为东西方向通行。 -
else if(state==3):判断交通灯状态是否为东西方向黄灯。 -
led<= 6'b110_011:设置 LED 灯状态为东西方向黄灯。 -
data[3:0] =ttnb/10; data[7:4] =ttnb%10; data[11:8] =ttdx/10; data[15:12] =ttdx%10;:将南北和东西方向的剩余时间显示在数码管上。 -
else if(moshi==1):判断是否处于时间调节模式。 -
led<= 6'b111_111;:设置 LED 灯状态为时间调节模式。 -
data[3:0] =shijiannb/10; data[7:4] =shijiannb%10; data[11:8] =shijiandx/10; data[15:12] =shijiandx%10;:将南北和东西方向的通行时间显示在数码管上。 -
else if(moshi==2):判断是否处于东西方向通行模式。 -
led<= 6'b101_011:设置 LED 灯状态为东西方向通行。 -
data[3:0] =10; data[7:4] =10; data[11:8] =10; data[15:12] =10;:将所有数码管显示为 10。 -
else if(moshi==3):判断是否处于南北方向通行模式。 -
led<= 6'b011_101:设置 LED 灯状态为南北方向通行。 -
data[3:0] =10; data[7:4] =10; data[11:8] =10; data[15:12] =10;:将所有数码管显示为 10。 -
else if(moshi==4):判断是否处于夜间模式。 -
if (cnt2 == 24_999_999):判断 cnt2 计数器是否达到最大值。 -
cnt2 = 0;:将 cnt2 计数器复位。 -
if(ff==0)ff=1; else ff=0;:切换夜间模式状态。 -
else:如果 cnt2 计数器没有达到最大值,则执行以下代码。 -
cnt2=cnt2+1;:将 cnt2 计数器加 1。 -
if(ff==0) led<= 6'b110_110; else led<= 6'b111_111:根据夜间模式状态设置 LED 灯状态。 -
data[3:0] =10; data[7:4] =10; data[11:8] =10; data[15:12] =10;:将所有数码管显示为 10。 -
else if(moshi==5):判断是否处于按流量通行模式。 -
if (cnt == 49_999_999):判断 cnt 计数器是否达到最大值。 -
cnt <= 0;:将 cnt 计数器复位。 -
if(sec==(shijiannb+shijiandx+11)):判断 sec 计时器是否达到最大值。 -
sec=0;:将 sec 计时器复位。 -
if((nabeiliu>=(dongxiliu+10))&&(nabeiliu<(dongxiliu+20))):判断南北方向流量是否比东西方向流量多 10 到 20。 -
shijiannb=40;shijiandx=20;:设置南北方向通行时间为 40 秒,东西方向通行时间为 20 秒。 -
else if((nabeiliu>=(dongxiliu+20))):判断南北方向流量是否比东西方向流量多 20 以上。 -
shijiannb=60;shijiandx=20;:设置南北方向通行时间为 60 秒,东西方向通行时间为 20 秒。 -
else if((dongxiliu>=(nabeiliu+10))&&(dongxiliu<(nabeiliu+20))):判断东西方向流量是否比南北方向流量多 10 到 20。 -
shijiannb=20;shijiandx=40;:设置南北方向通行时间为 20 秒,东西方向通行时间为 40 秒。 -
else if((dongxiliu>=(nabeiliu+20))):判断东西方向流量是否比南北方向流量多 20 以上。 -
shijiannb=20;shijiandx=60;:设置南北方向通行时间为 20 秒,东西方向通行时间为 60 秒。 -
else:如果流量差异不满足上述条件。 -
shijiannb=20;shijiandx=20;:设置南北方向通行时间为 20 秒,东西方向通行时间为 20 秒。 -
dongxiliu<=0; nabeiliu<=0;:将东西和南北方向流量计数器复位。 -
else:如果 sec 计时器没有达到最大值,则执行以下代码。 -
sec=sec+1;:将 sec 计时器加 1。 -
if(sec<=shijiannb):判断当前时间是否小于南北方向的通行时间。 -
state=0; ttnb=shijiannb-sec; ttdx=shijiannb-sec+5;:设置交通灯状态为南北方向通行,并计算剩余时间。 -
else if(sec>shijiannb&&sec<=(shijiannb+5)):判断当前时间是否在南北方向黄灯时间内。 -
state=1; ttnb=shijiannb-sec+5; ttdx=shijiannb-sec+5;:设置交通灯状态为南北方向黄灯,并计算剩余时间。 -
else if(sec>(shijiannb+5)&&sec<=(shijiannb+shijiandx+1+5)):判断当前时间是否在东西方向通行时间内。 -
state=2; ttnb=(shijiannb+shijiandx+1)-sec+10; ttdx=(shijiannb+shijiandx+1)-sec+5;:设置交通灯状态为东西方向通行,并计算剩余时间。 -
else if(sec>(shijiannb+shijiandx+6)):判断当前时间是否在东西方向黄灯时间内。 -
state=3; ttnb=(shijiannb+shijiandx+11)-sec; ttdx=(shijiannb+shijiandx+11)-sec;:设置交通灯状态为东西方向黄灯,并计算剩余时间。 -
else:如果 cnt 计数器没有达到最大值,则执行以下代码。 -
cnt <= cnt + 1'b1;:将 cnt 计数器加 1。 -
if(state==0):判断交通灯状态是否为南北方向通行。 -
led<= 6'b011_101:设置 LED 灯状态为南北方向通行。 -
else if(state==1):判断交通灯状态是否为南北方向黄灯。 -
led<= 6'b011_110:设置 LED 灯状态为南北方向黄灯。 -
else if(state==2):判断交通灯状态是否为东西方向通行。 -
led<= 6'b101_011:设置 LED 灯状态为东西方向通行。 -
else if(state==3):判断交通灯状态是否为东西方向黄灯。 -
led<= 6'b110_011:设置 LED 灯状态为东西方向黄灯。 -
data[3:0] =ttnb/10; data[7:4] =ttnb%10; data[11:8] =ttdx/10; data[15:12] =ttdx%10;:将南北和东西方向的剩余时间显示在数码管上。 -
always @(posedge CLOCK_50):定义一个时序逻辑块,当 CLOCK_50 上升沿到来时触发。 -
if(moshi==5):判断是否处于按流量通行模式。 -
liul[3:0] <= nabeiliu/10; liul[7:4] <= nabeiliu%10; liul[11:8] <= dongxiliu/10; liul[15:12] <= dongxiliu%10;:将南北和东西方向的流量计数显示在数码管上。 -
else:如果当前模式不处于按流量通行模式。 -
liul[3:0] <= moshi; liul[7:4] <= 10; liul[11:8] <= 10; liul[15:12] <= 10;:将数码管显示为当前模式和 10。 -
endmodule:模块结束。
代码优化建议:
- 可以使用状态机来实现交通灯的控制逻辑,提高代码的可读性和可维护性。
- 可以使用参数化来定义计数器和时间的最大值,方便修改。
- 可以使用更简洁的代码来实现流量计数逻辑,提高代码效率。
- 可以使用 Verilog 的一些高级特性,例如任务和函数,提高代码的复用性。
代码解析总结:
该 Verilog 模块主要通过检测流量传感器信号和按键状态,来控制交通灯的状态,并显示相关信息在数码管和 LED 上。代码中使用了多个寄存器和计数器,以及状态机来实现复杂的控制逻辑。通过代码解析和优化建议,读者可以更好地理解 Verilog 代码并进行相关应用。
进一步学习:
- Verilog 语言基础
- 状态机设计
- 交通灯控制系统
原文地址: https://www.cveoy.top/t/topic/jnzn 著作权归作者所有。请勿转载和采集!