Verilog 代码详解:交通灯控制模块
该模块名为 'control',包含多个输入和输出端口。
输入端口:
- CLOCK_50: 板载 50MHz 时钟。
- Q_KEY: 按键输入。
- guang1: 南北方向流量传感器接口。
- guang2: 东西方向流量传感器接口。
- KEY: 按键输入,9 位。 输出端口:
- data: 显示时间和模式,16 位。
- liul: 显示流量信息,16 位。
- led: 控制红绿灯,6 位。
其中,'nabeiliu' 和 'dongxiliu' 是用于计数流量的寄存器,'F1'、'F2'、'F3' 和 'F4' 是用于检测时钟的上升沿和下降沿的寄存器。'cnt1'、'cnt' 和 'cnt2' 是用于计数时间的寄存器。't_buf1' 和 't_buf2' 是用于暂存流量值的寄存器。'moshi' 是用于控制不同模式的寄存器。'shijiandx' 和 'shijiannb' 是用于控制南北和东西方向信号灯时间的寄存器。'state' 是用于控制当前红绿灯状态的寄存器。'sec'、'ttnb' 和 'ttdx' 是用于计算时间和显示时间的寄存器。'ff' 是用于夜间模式的寄存器。
代码解析
1. 时钟检测
reg F1,F2;
always @(posedge CLOCK_50 or negedge Q_KEY)
if(!Q_KEY)
begin
F1<=1'b1;
F2<=1'b1;
end
else
begin
F1<=guang1;//需要检测的引脚
F2<=F1;
end
assign SCK_fallingedge1 = F2 && !F1;//检测时钟的下降沿
assign SCK_risingedge1 = F1 && !F2;//检测时钟的上升沿
这段代码利用两个寄存器 'F1' 和 'F2' 来检测时钟的上升沿和下降沿。当按下 'Q_KEY' 时,'F1' 和 'F2' 都被置为 '1'。当 'Q_KEY' 松开后,'F1' 的值会被 'guang1' 的值更新,而 'F2' 则保留 'F1' 的前一个值。通过比较 'F1' 和 'F2' 的值,可以检测出时钟的上升沿和下降沿。
2. 流量计数
reg [7:0] nabeiliu;
reg [7:0] dongxiliu;
reg uu1;
reg uu2;
always @ (posedge CLOCK_50, negedge Q_KEY)
if (!Q_KEY)
begin
nabeiliu<=0;
dongxiliu<=0;
...
end
else
begin
...
if(SCK_fallingedge1 == 1)
begin
uu1=1;
end
if(SCK_fallingedge2 == 1)
begin
uu2=1;
end
if (cnt1 == 9_999_999)
begin
cnt1 <= 0;
if(guang1==1&&uu1==1)
begin
uu1<=0;
nabeiliu<=nabeiliu+1;
end
if(guang2==1&&uu2==1)
begin
uu2<=0;
dongxiliu<=dongxiliu+1;
end
end
else
cnt1 <= cnt1 + 1'b1;
...
end
这段代码利用两个寄存器 'nabeiliu' 和 'dongxiliu' 来计数南北方向和东西方向的流量。当检测到 'guang1' 和 'guang2' 的值发生变化时,并且对应时钟的下降沿被检测到,相应的计数器就会加 1。
3. 模式控制
reg [3:0] moshi;
always @ (posedge CLOCK_50, negedge Q_KEY)
if (!Q_KEY)
begin
...
moshi=0;
...
end
else
begin
...
case (1'b0)
key_val[1] :
begin
moshi=1;//调节时间
...
end
key_val[2] :
begin
moshi=1;//调节时间
...
end
key_val[3] :
begin
moshi=1;//调节时间
...
end
key_val[4] :
begin
moshi=1;//调节时间
...
end
key_val[5] :
begin
moshi=2;//东西方向通行,南北禁止
...
end
key_val[6] :
begin
moshi=3;
...
end
key_val[7] :
begin
moshi=4;
...
end
key_val[8] :
begin
moshi=5;shijiannb=20;shijiandx=20;
...
end
key_val[9] :
begin
moshi=0;
...
end
endcase
...
end
这段代码利用 'moshi' 寄存器来控制不同的模式。通过按下不同的按键,可以改变 'moshi' 的值,从而切换不同的工作模式。
4. 时间控制
reg [6:0] shijiandx,shijiannb;
reg [6:0] ttdx,ttnb;
always @ (posedge CLOCK_50, negedge Q_KEY)
if (!Q_KEY)
begin
...
shijiandx=20;
shijiannb=20;
...
end
else
begin
...
if(moshi==0)
begin
if (cnt == 49_999_999) //1s
begin
cnt <= 0;
if(sec==(shijiannb+shijiandx+11))sec=0;
else sec=sec+1;
if(sec<=shijiannb)//南北通行;东西禁止
begin
state=0;
ttnb=shijiannb-sec;
ttdx=shijiannb-sec+5;
end
else if(sec>shijiannb&&sec<=(shijiannb+5))//南北黄灯5S;东西禁止
begin
state=1;
ttnb=shijiannb-sec+5;
ttdx=shijiannb-sec+5;
end
else if(sec>(shijiannb+5)&&sec<=(shijiannb+shijiandx+1+5))//东西通行;南北禁止
begin
state=2;
ttnb=(shijiannb+shijiandx+1)-sec+10;
ttdx=(shijiannb+shijiandx+1)-sec+5;
end
else if(sec>(shijiannb+shijiandx+6))//东西黄灯5S;南北禁止
begin
state=3;
ttnb=(shijiannb+shijiandx+11)-sec;
ttdx=(shijiannb+shijiandx+11)-sec;
end
end
else
cnt <= cnt + 1'b1;
...
end
else if(moshi==1)//调节时间
begin
...
data[3:0] =shijiannb/10;
data[7:4] =shijiannb%10;
data[11:8] =shijiandx/10;
data[15:12] =shijiandx%10;
end
else if(moshi==5)//按流量通行模式
begin
if (cnt == 49_999_999) //1s
begin
cnt <= 0;
if(sec==(shijiannb+shijiandx+11))
begin
sec=0;
...
end
else sec=sec+1;
if(sec<=shijiannb)//南北通行;东西禁止
begin
state=0;
ttnb=shijiannb-sec;
ttdx=shijiannb-sec+5;
end
...
end
else
cnt <= cnt + 1'b1;
...
end
end
这段代码利用多个寄存器来控制时间和显示时间。'shijiandx' 和 'shijiannb' 用于控制南北和东西方向的信号灯时间。'sec' 用于记录当前秒数。'ttnb' 和 'ttdx' 用于计算剩余时间并显示在 'data' 输出端口上。
5. 红绿灯控制
reg [2:0] state;
always @ (posedge CLOCK_50, negedge Q_KEY)
if (!Q_KEY)
begin
...
end
else
begin
...
if(moshi==0)
begin
if (cnt == 49_999_999) //1s
begin
cnt <= 0;
if(sec==(shijiannb+shijiandx+11))sec=0;
else sec=sec+1;
if(sec<=shijiannb)//南北通行;东西禁止
begin
state=0;
...
end
else if(sec>shijiannb&&sec<=(shijiannb+5))//南北黄灯5S;东西禁止
begin
state=1;
...
end
else if(sec>(shijiannb+5)&&sec<=(shijiannb+shijiandx+1+5))//东西通行;南北禁止
begin
state=2;
...
end
else if(sec>(shijiannb+shijiandx+6))//东西黄灯5S;南北禁止
begin
state=3;
...
end
end
else
cnt <= cnt + 1'b1;
if(state==0)
begin
led<= 6'b011_101;//东西方向:红绿黄 南北方向:红绿黄
end
else if(state==1)
begin
led<= 6'b011_110;//东西方向:红绿黄 南北方向:红绿黄
end
else if(state==2)
begin
led<= 6'b101_011;//东西方向:红绿黄 南北方向:红绿黄
end
else if(state==3)
begin
led<= 6'b110_011;//东西方向:红绿黄 南北方向:红绿黄
end
...
end
...
end
这段代码利用 'state' 寄存器来控制当前红绿灯的状态。根据不同的时间段,'state' 会被更新,从而控制 'led' 输出端口的输出值,实现红绿灯的切换。
6. 流量信息显示
always @ (posedge CLOCK_50)
begin
if(moshi==5)
begin
liul[3:0] <= nabeiliu/10; //南北方向流量 十位
liul[7:4] <= nabeiliu%10;//南北方向流量 个位
liul[11:8] <= dongxiliu/10;//东西方向流量 十位
liul[15:12] <= dongxiliu%10; //东西方向流量 个位
end
else
begin
liul[3:0] <= moshi;
liul[7:4] <= 10;
liul[11:8] <= 10;
liul[15:12] <= 10;
end
end
这段代码将南北方向和东西方向的流量值分别显示在 'liul' 输出端口上。当 'moshi' 等于 5 时,显示实际流量值。其他模式下,显示 'moshi' 的值。
总结
这段 Verilog 代码实现了交通灯控制模块,包括流量计数、模式控制、时间控制和红绿灯显示等功能。代码逻辑清晰,结构简洁,易于理解和维护。
原文地址: https://www.cveoy.top/t/topic/ofbH 著作权归作者所有。请勿转载和采集!