交通灯控制器
专 业: 电子信息科学与技术_
班 级:
学 号:
学生姓名:
******************
摘要
交通灯是城市交通监管系统的重要组成部分,对于保证机动车辆的安全运行,维持城市道路的顺畅起到了重要作用。目前很多城市交叉路口的交通灯实行的是定时控制,灯亮的时间是预先设定好的,在时间和空间方面的应变性能较差,一定程度上造成了交通资源的浪费,加重了道路交通压力。本文在EDA技术的基础上,利用FPGA的相关知识设计了交通灯控制系统,可以根据实际情况对灯亮时间进行自由调整,通过数码管显示等待时间,点阵显示运行状态,蜂鸣器提示紧急状况,很好地维护了道路的交通规则。整个设计系统通过Quartus Ⅱ软件中的Verilog HDL语言进行代码编写,并下载到FPGA器件中进行硬件调试,验证了设计的交通信号灯控制电路完全可以实现预定的功能,具有一定的实用性。
关键字:交通灯、定时控制、FPGA、Verilog HDL
一、设计原理
根据交通灯循环顺序表可以得到如表1的循环状态表,遇到紧急状况的时候,这时候有东西通行、南北通行和全部禁行三种情况,紧急状态结束后条件满足的情况下状态依次往后跳转。
| 状态 | 东西方向 | 南北方向 | 时间 |
| 0 | 红灯亮 | 绿灯亮 | 20s |
| 1 | 黄灯亮 | 绿灯亮 | 10s |
| 2 | 绿灯亮 | 红灯亮 | 20s |
| 3 | 绿灯亮 | 黄灯亮 | 10s |
1. 方案比较
方案一: 直接用GPIO口驱动双色点阵;
方案二:用两块3-8译码器控制双色点阵,一个控制红色,另一个控制绿色;
方案三:用一块4-16选择器控制双色点阵;
通过比较方案一需要24个GPIO,方案二需要14个GPIO口,而方案三只需要12个GPIO口,考虑到IO口的数量和资源的优化,故选择方案三,硬件部分还包括Led灯和蜂鸣器,用洞洞板搭建好了硬件电路。
2.系统框架
图1 状态机状态转换图
随着现代生活节奏的加快,人们出门便更多地选择自家的交通工具,这无疑加大了交通流量,如何控制十字路口的红绿灯,便显得相当的重要。简单的,有效地控制红绿灯,是减小客流量,甚至减少交通事故的重要保障。而此次课题,我选择了交通灯控制电路,能熟悉 Verilog HDL 硬件描述语言在现实生活中的重要意义,为以后的学习和工作打好基础。
二、总体设计
1. 主体结构
根据确定的系统设计方案,运用模块化的设计思路,我们在Quartus II13.0软件系统中设计了整个交通灯控制器的逻辑结构。交通灯控制器包括分频模块、交通灯模块、蜂鸣器控制模块、数码管显示模块、点阵显示模块和时间调整模块。50M的系统时钟分频到1Hz、2Hz和1KHz用于计时,点阵显示当前处于哪种状态,数码管显示模块提示等待的时间,按键调整时间用于调整时间减少客流量,紧急开关用于发生突发事故是禁止车辆通行。特殊运行状态结束后,控制器恢复原来的状态,继续运行。通过各个模块程序之间的端口合理连接和协调,成功设计出交通灯控制器的电路。
图2 交通灯控制原理图
2. 分模块的设计
(1) 分频模块
分频模块的功能是将50MHz的时钟频率分频到1Hz、2Hz和1KHz,输出给其他模块调用。在红绿灯交通信号系统中,大多数的情况是通过自动控制的方式指挥交通的。因此,为了避免意外事件的发生,电路必须给出一个稳定的时钟才能让系统正常的工作。因此时钟发生模块最主要的功能就是产生一些稳定的输出信号,并将其用做后面几个电路的使能控制与同步信号。
always @ (posedge Clk)
begin
if(cnt1==26'd25_000_000) //分频产生1Hz时钟
begin
cnt1 <= 26'd0;
Clk_1Hz <= ~Clk_1Hz;
end
else
cnt1 <= cnt1+1;
if(cnt2 == 15'd25000) //分频产生1KHz时钟
begin
cnt2 <= 15'd0;
Clk_1k <= ~Clk_1k;
end
else
cnt2 <= cnt2+1'b1;
if(cnt3 == 23'd12_499_999) //分频产生2Hz时钟
begin
cnt3 <= 23'd0;
Clk_2Hz <= ~Clk_2Hz;
end
else
cnt3 <= cnt3+1'b1;
end
(2) 数码管显示模块
数码管显示模块的功能是将当前倒计时的数值输出显示,控制数码管显示,提示车辆应该等待的时间。
always @ (posedge Clk_1k)
begin
case(Mode) //模式切换
2'd0 : Time <= Time1;
2'd1 : Time <= Time2;
default : Time <= Time3;
endcase
Del <= ~Del; //选择十位和个位
if(Key > 3'd0)
Seg <= 8'd0;
else
Seg <= (Del == 2'b01) ? (seg[Time/10]) : (seg[Time%10]);
End
(3) 蜂鸣器模块
如果实现发生紧急事件,如救护车、警车、抢险车通过,蜂鸣器响5声关闭,特别地,全部禁行的优先级比东西禁行和南北禁行的优先级要高,可以覆盖掉这两种方式,同时蜂鸣器也会响5声关闭,可以提醒其他车辆禁止通行。
always @ (posedge Clk_1Hz)
begin
if(Key >3'd0)
begin
if(Key[0]==1'b0 && Key>1'b1)
Flag3 <= 1'b0;
if(Flag2 < 4'd10)
begin
Beep <= ~Beep;
Flag2 <= Flag2+1'b1;
end
else
if(Key[0]==1'b1 && Flag3 == 1'b0)
begin
Flag3 <= 1'b1;
Flag2 <= 4'd0;
end
else
Flag2 <= 4'd10;
end
else
begin
Beep <= 1'b0;
Flag2 <= 4'd0;
end
end
(4) 点阵模块
点阵可以显示当前状态,使用的时双色点阵,正常运行时显示绿色的“PASS笑脸”字样,刹车时显示红色的“STOP哭脸”字样,模式切换时显示红色“MODE爱心”字样。
always @ (posedge Clk_1k)
begin
Col <= Num;
if(Key>3'd0 || Mode>2'd0)
begin
if(Key==3'd0 && Mode>2'd0)
Row <= data2[Num+count]; //"MODE爱心"
else
Row <= data1[Num+count]; //" STOP哭脸"
if(Num >= 4'd7)
Num <= 4'd0;
else
Num <= Num+1'b1;
end
else
begin
Row <= data[Num+count-8]; //" PASS笑脸"
if(Num == 4'd15 || Num<8)
Num <= 4'd8;
else
Num <= Num+1'b1;
end
if(cnt == 10'd200) //计数,控制点阵移屏速度
begin
cnt <= 10'd0;
if(count == 6'd47)
count <= 6'd0;
else
count <= count+1'b1;
end
else
cnt <= cnt+1'b1;
end
(5) 按键模块
第一个按键是模式切换按键,同时Led1、Led2会点亮,提示时选择的是长时间,第二下是短时间,第三下恢复到正常状态。第二、三个按键分别是控制数码管显示的等待时间增加、减少。
always @ (posedge Clk_2Hz)
begin
if(key[2] == 1'b0) //模式切换
Mode <= Mode+1'b1;
if(Mode == 2'd3)
Mode <= 3'd0;
if(key[1] == 1'b0) //时间增加
if(Mode == 2'd1) //长、短时间选择
if(Time2 == 8'd99)
Time2 <= 8'd0;
else
Time2 <= Time2+1'b1;
else
if(Mode == 2'd2)
if(Time3 == 8'd99)
Time3 <= 8'd0;
else
Time3 <= Time3+1'b1;
if(key[0] == 1'b0) // 时间减少
if(Mode == 2'd1) //长、短时间选择
if(Time2 == 8'd0)
Time2 <= 8'd99;
else
Time2 <= Time2-1'b1;
else
if(Mode == 2'd2)
if(Time3 == 8'd0)
Time3 <= 8'd99;
else
Time3 <= Time3-1'b1;
end
(6) 交通灯模块
四个方向的Led显示运行状态,东西方向的灯对应相同,南北方向的灯对应相同。正常运行是按照交通灯规则执行,刹车开关按下时东西禁行时,东西方向红灯,南北方向绿灯;东西南北禁行时,东西方向绿灯,南北方向红灯;全禁行时,东西和南北方向都是红灯;模式切换时,Led灯熄灭。
always @ (posedge Clk_1Hz)
begin
if(Key[2] == 1'b1) //东西通行
begin
Led <= 6'b110000; //东西方向绿灯亮
Led1 <= 6'b000011; //南北方向红灯亮
end
if(Key[1] == 1'b1) //南北通行
begin
Led <= 6'b000011; //东西方向红灯亮
Led1 <= 6'b110000; //南北方向绿灯亮
end
if(Key[0] == 1'b1) //全部禁行
begin
Led <= 6'b000011; //东西方向红灯亮
Led1 <= 6'b000011; //南北方向红灯亮
end
if(Key > 3'd0)
Flag <= 1'b1; //标志,用于恢复初始状态
else
if(Flag == 1'b1)//恢复初始状态
begin
Flag <= 1'b0;
Time1 <= Time2;
Led <= 6'b110000;
Led1 <= 6'b000011;
end
else
begin
if(Status == 2'd0) //状态0
if(Time1 == 8'd0)
begin
Led <= 6'b001100; //黄灯亮
Led1 <= 6'b000011; //红灯亮
Status <= 2'd1; //转到状态1
Time1 <= Time3; //短时间
end
else
Time1 <= Time1-1'b1;
if(Status == 2'd1) //状态1
if(Time1 == 8'd0)
begin
Led <= 6'b000011; //红灯亮
Led1 <= 6'b110000; //绿灯亮
Status <= 2'd2;//转到状态2
Time1 <= Time2; //长时间
end
else
Time1 <= Time1-1'b1;
if(Status == 2'd2) //状态2
if(Time1 == 8'd0)
begin
Led <= 6'b000011; //红灯亮
Led1 <= 6'b001100; //黄灯亮
Status <= 2'd3;//转到状态3
Time1 <= Time3; //短时间
end
else
Time1 <= Time1-1;
if(Status==2'd3) //状态3
if(Time1 == 8'd0)
begin
Led <= 6'b110000; //绿灯亮
Led1 <= 6'b000011; //红灯亮
Status <= 2'd0; //返回状态0
Time1 <= Time2;//长时间
end
else
Time1 <= Time1-1'b1;
case(Mode)
2'd0 : Led2 <= 3'b000; //正常模式
2'd1 : Led2 <= 3'b110; //长时间模式
default : Led2 <= 3'b101; //短时间模式
endcase
if(Mode >2'd0)
begin
Flag1 <= 1'b1;
Led <= 6'd0;
Led1 <= 6'd0;
end
else
if(Flag1 == 1'b1)
begin
Flag1 <= 1'b0;
Time1 <= Time2;
Led <= 6'b110000; //绿灯亮
Led1 <= 6'b000011; //红灯亮
end
end
end
3.工程总体结构
所设计的交通信号灯控制电路,主要适用于在两条干道汇合点形成的十字交叉路口,路口设计两组红绿灯分别对两个方向上的交通运行状态进行管理。所设计的这个系统的主要逻辑设计由一片型号为EP4CE115F29C7芯片完成,编写的Verilog HDL源程序在经过编译和功能仿真测试后,针对下载芯片进行管脚配置,下载到芯片中,进行相应的硬件调试,调试结果与软件仿真的结果相吻合,验证了设计完成了预定功能。基于Verilog HDL设的交通灯控制器,外围电路少、功耗低、可靠性高,便于系统功能的修改,设计效率高。
图3 总的电路图结构
三、问题和解决方案
1. 在 QuartusII 软件上进行仿真时,发现不能得到预期的效果,分析得知由于分频过大的原因,导致时序出现问题。经过同学的讨论决定在软件更改时钟信号的分频操作,问题得以解决。
2. 对于 Verilog 语言的编程方面,特别在对变量给予初值时,完全不同于 C 语言编程,我们在对许多变量进行了初值设置,此后编译每每都不通过,在认真思考后,查阅了课本,发现在 Verilog HDL 编程中,不能对变量初值。我恍然大悟,在以后的编程中我们牢记住了这一点。
3. 在添加数码管显示过程中现实出现混论,经过检查后发现错误是由于高位和低位由于是对引脚配置的错误导致的。改正后发现显示正常。
4. 因为代码的不严谨,出现了各种逻辑错误,导致实际硬件调试的时候,灯、数码管、蜂鸣器不按程序对应的要求执行,经过代码认真分析和同学讨论,解决了问题。
四、总结
通过本设计,我对FPGA的设计的基本流程与相关概念有了进一步的理解。我学会了用Verilog语言写分频器、按键控制、点亮LED、控制数码管和点阵的显示等。在写设计代码时,我对always块的书写有了进一步的理解和掌握。
在下载到板子上的时候出现了各种问题,一边解决问题一边进步。有时候许多的错误就来源于一个小小的错误。因此,编写程序必须的十分的细心,尤其当程序比较长的时候,编程水平的高低可以在体现程序的简洁程度。多花点时间是值得的,如果时间充足应该可以做的更好。这次运用专业知识做一个生活中可以用到的东西,加强了理论与实践的联系。培养了我思考、动手操作的能力,在做设计的时候,学会了很多学习的方法,这是日后最实用的。这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和思考的能力。
参考文献
[1] 全国大学生电子设计获奖作品汇编[J].北京理工大学出版社,2005
[2] 康华光.电子技术基础-数字部分[M].高等教育出版社,1998
[3] 谭会生等.EDA技术及应用[M].西安电子科技大学出版社,2001
[4] 潘松等.EDA技术实用教程[M].科学出版社,2006
附录:
图4 实物1
图5 实物2
图6 实物3
程序清单:
//031341205 谢亮
//交通灯设计
module traffic (Led, Led1, Led2, Key, key, Clk, Beep, Del, Seg, Col, Row);
input Clk; // 系统时钟50MHz
input [2:0] Key; //紧急开关,分为东西通行,南北通行,全部禁行
input [2:0] key; //调整时间,分别为模式选择,长时间,短时间
output reg [2:0] Led2; //调整时间的显示模式
output reg Beep; //911报警,响5声后关闭
output reg [7:0] Row; //点阵行控制
output reg [3:0] Col; //4-16器进行列控制
output reg [5:0] Led; //东西方向指示灯
output reg [5:0] Led1; //南北方向指示灯
output reg [1:0] Del; //共阴数码管位选
output reg [7:0] Seg; //数码管段选
reg [1:0] Status; //指示灯的4种状态
reg [3:0] Num; //点阵计数中间变量
reg [7:0] seg [9:0]; //数码管初值0~9
reg [9:0] cnt; //计数,用于控制点阵移动速度
reg [26:0] cnt1; //计数,用于产生1Hz时钟
reg [14:0] cnt2; //计数,用于产生1KHz时钟
reg [22:0] cnt3; //计数,用于产生2Hz时钟
reg [5:0] count; //计数,用于点阵移屏显示
reg [3:0] Flag2; //标志状态,控制蜂鸣器
reg Flag, Flag1, Flag3; //标志状态,调节或紧急刹车后恢复初始状态
reg Clk_1k, Clk_1Hz, Clk_2Hz; //1KHz, 1Hz, 2Hz时钟信号
reg [1:0] Mode; //正常显示、长时间、短时间三种模式切换
reg [7:0] data [47:0], data1 [47:0], data2 [47:0]; //储存字模数据
reg [7:0] Time, Time1, Time2, Time3; //计数,用于数码管显示,1计数,2长时间,3短时间
//初始化赋值
initial
begin
Led = 6'b110000; //绿灯亮
Led1 = 6'b000011; //红灯亮
Time1 = 8'd20; //数码管初值
Time2 = 8'd20; //长时间初值
Time3 = 8'd10; //短时间初值
Del = 2'b01; //数码管位选初值
seg[0] = 8'b00111111; //数码管"0~9"
seg[1] = 8'b00000110;
seg[2] = 8'b01011011;
seg[3] = 8'b01001111;
seg[4] = 8'b01100110;
seg[5] = 8'b01101101;
seg[6] = 8'b01111101;
seg[7] = 8'b00000111;
seg[8] = 8'b01111111;
seg[9] = 8'b01101111;
data[0] = 8'h00;//点阵" PASS笑脸"
data[1] = 8'h00;
data[2] = 8'h00;
data[3] = 8'h00;
data[4] = 8'h00;
data[5] = 8'h00;
data[6] = 8'h00;
data[7] = 8'h00; /* */
data[8] = 8'h44;
data[9] = 8'h7C;
data[10] = 8'h54;
data[11] = 8'h14;
data[12] = 8'h14;
data[13] = 8'h14;
data[14] = 8'h08;
data[15] = 8'h00;/*P*/
data[16] = 8'h40;
data[17] = 8'h60;
data[18] = 8'h78;
data[19] = 8'h2C;
data[20] = 8'h28;
data[21] = 8'h70;
data[22] = 8'h60;
data[23] = 8'h40;/*A*/
data[24] = 8'h00;
data[25] = 8'h48;
data[26] = 8'h54;
data[27] = 8'h54;
data[28] = 8'h54;
data[29] = 8'h54;
data[30] = 8'h24;
data[31] = 8'h00;/*S*/
data[32] = 8'h00;
data[33] = 8'h48;
data[34] = 8'h54;
data[35] = 8'h54;
data[36] = 8'h54;
data[37] = 8'h54;
data[38] = 8'h24;
data[39] = 8'h00;/*S*/
data[40] = 8'h7E;
data[41] = 8'h91;
data[42] = 8'hA5;
data[43] = 8'hA1;
data[44] = 8'hA1;
data[45] = 8'hA5;
data[46] = 8'h91;
data[47] = 8'h7E;/*笑脸*/
data1[0] = 8'h00;//点阵" STOP哭脸"
data1[1] = 8'h00;
data1[2] = 8'h00;
data1[3] = 8'h00;
data1[4] = 8'h00;
data1[5] = 8'h00;
data1[6] = 8'h00;
data1[7] = 8'h00; /* */
data1[8] = 8'h00;
data1[9] = 8'h48;
data1[10] = 8'h54;
data1[11] = 8'h54;
data1[12] = 8'h54;
data1[13] = 8'h54;
data1[14] = 8'h24;
data1[15] = 8'h00;/*S*/
data1[16] = 8'h04;
data1[17] = 8'h04;
data1[18] = 8'h44;
data1[19] = 8'h7C;
data1[20] = 8'h44;
data1[21] = 8'h04;
data1[22] = 8'h04;
data1[23] = 8'h00; /*T*/
data1[24] = 8'h38;
data1[25] = 8'h44;
data1[26] = 8'h44;
data1[27] = 8'h44;
data1[28] = 8'h44;
data1[29] = 8'h44;
data1[30] = 8'h38;
data1[31] = 8'h00; /*O*/
data1[32] = 8'h44;
data1[33] = 8'h7C;
data1[34] = 8'h54;
data1[35] = 8'h14;
data1[36] = 8'h14;
data1[37] = 8'h14;
data1[38] = 8'h08;
data1[39] = 8'h00; /*P*/
data1[40] = 8'h7E;
data1[41] = 8'hA1;
data1[42] = 8'h95;
data1[43] = 8'h91;
data1[44] = 8'h91;
data1[45] = 8'h95;
data1[46] = 8'hA1;
data1[47] = 8'h7E; /*哭脸*/
data2[0] = 8'h00;//点阵"MODE爱心"
data2[1] = 8'h00;
data2[2] = 8'h00;
data2[3] = 8'h00;
data2[4] = 8'h00;
data2[5] = 8'h00;
data2[6] = 8'h00;
data2[7] = 8'h00; /* */
data2[8] = 8'h44;
data2[9] = 8'h7C;
data2[10] = 8'h0C;
data2[11] = 8'h70;
data2[12] = 8'h0C;
data2[13] = 8'h7C;
data2[14] = 8'h44;
data2[15] = 8'h00;/*M*/
data2[16] = 8'h38;
data2[17] = 8'h44;
data2[18] = 8'h44;
data2[19] = 8'h44;
data2[20] = 8'h44;
data2[21] = 8'h44;
data2[22] = 8'h38;
data2[23] = 8'h00;/*O*/
data2[24] = 8'h44;
data2[25] = 8'h7C;
data2[26] = 8'h44;
data2[27] = 8'h44;
data2[28] = 8'h44;
data2[29] = 8'h44;
data2[30] = 8'h38;
data2[31] = 8'h00;/*D*/
data2[32] = 8'h44;
data2[33] = 8'h7C;
data2[34] = 8'h54;
data2[35] = 8'h54;
data2[36] = 8'h54;
data2[37] = 8'h54;
data2[38] = 8'h44;
data2[39] = 8'h00;/*E*/
data2[40] = 8'h1C;
data2[41] = 8'h22;
data2[42] = 8'h42;
data2[43] = 8'h84;
data2[44] = 8'h84;
data2[45] = 8'h42;
data2[46] = 8'h22;
data2[47] = 8'h1C;/*爱心*/
end
//50M系统时钟分频
always @ (posedge Clk)
begin
if(cnt1==26'd25_000_000) //分频产生1Hz时钟
begin
cnt1 <= 26'd0;
Clk_1Hz <= ~Clk_1Hz;
end
else
cnt1 <= cnt1+1;
if(cnt2 == 15'd25000) //分频产生1KHz时钟
begin
cnt2 <= 15'd0;
Clk_1k <= ~Clk_1k;
end
else
cnt2 <= cnt2+1'b1;
if(cnt3 == 23'd12_499_999) //分频产生2Hz时钟
begin
cnt3 <= 23'd0;
Clk_2Hz <= ~Clk_2Hz;
end
else
cnt3 <= cnt3+1'b1;
end
//指示灯的4种状态
always @ (posedge Clk_1Hz)
begin
if(Key[2] == 1'b1) //东西通行
begin
Led <= 6'b110000; //东西方向绿灯亮
Led1 <= 6'b000011; //南北方向红灯亮
end
if(Key[1] == 1'b1) //南北通行
begin
Led <= 6'b000011; //东西方向红灯亮
Led1 <= 6'b110000; //南北方向绿灯亮
end
if(Key[0] == 1'b1) //全部禁行
begin
Led <= 6'b000011; //东西方向红灯亮
Led1 <= 6'b000011; //南北方向红灯亮
end
if(Key > 3'd0)
Flag <= 1'b1; //标志,用于恢复初始状态
else
if(Flag == 1'b1)//恢复初始状态
begin
Flag <= 1'b0;
Time1 <= Time2;
Led <= 6'b110000;
Led1 <= 6'b000011;
end
else
begin
if(Status == 2'd0) //状态0
if(Time1 == 8'd0)
begin
Led <= 6'b001100; //黄灯亮
Led1 <= 6'b000011; //红灯亮
Status <= 2'd1; //转到状态1
Time1 <= Time3; //短时间
end
else
Time1 <= Time1-1'b1;
if(Status == 2'd1) //状态1
if(Time1 == 8'd0)
begin
Led <= 6'b000011; //红灯亮
Led1 <= 6'b110000; //绿灯亮
Status <= 2'd2;//转到状态2
Time1 <= Time2; //长时间
end
else
Time1 <= Time1-1'b1;
if(Status == 2'd2) //状态2
if(Time1 == 8'd0)
begin
Led <= 6'b000011; //红灯亮
Led1 <= 6'b001100; //黄灯亮
Status <= 2'd3;//转到状态3
Time1 <= Time3; //短时间
end
else
Time1 <= Time1-1;
if(Status==2'd3) //状态3
if(Time1 == 8'd0)
begin
Led <= 6'b110000; //绿灯亮
Led1 <= 6'b000011; //红灯亮
Status <= 2'd0; //返回状态0
Time1 <= Time2;//长时间
end
else
Time1 <= Time1-1'b1;
case(Mode)
2'd0 : Led2 <= 3'b000; //正常模式
2'd1 : Led2 <= 3'b110; //长时间模式
default : Led2 <= 3'b101; //短时间模式
endcase
if(Mode >2'd0)
begin
Flag1 <= 1'b1;
Led <= 6'd0;
Led1 <= 6'd0;
end
else if(Flag1 == 1'b1)
begin
Flag1 <= 1'b0;
Time1 <= Time2;
Led <= 6'b110000; //绿灯亮
Led1 <= 6'b000011; //红灯亮
end
end
end
//时间调整
always @ (posedge Clk_2Hz)
begin
if(key[2] == 1'b0) //模式切换
Mode <= Mode+1'b1;
if(Mode == 2'd3)
Mode <= 3'd0;
if(key[1] == 1'b0) //时间增加
if(Mode == 2'd1) //长、短时间选择
if(Time2 == 8'd99)
Time2 <= 8'd0;
else
Time2 <= Time2+1'b1;
else
if(Mode == 2'd2)
if(Time3 == 8'd99)
Time3 <= 8'd0;
else
Time3 <= Time3+1'b1;
if(key[0] == 1'b0) // 时间减少
if(Mode == 2'd1) //长、短时间选择
if(Time2 == 8'd0)
Time2 <= 8'd99;
else
Time2 <= Time2-1'b1;
else
if(Mode == 2'd2)
if(Time3 == 8'd0)
Time3 <= 8'd99;
else
Time3 <= Time3-1'b1;
end
//蜂鸣器禁止通行
always @ (posedge Clk_1Hz)
begin
if(Key >3'd0)
begin
if(Key[0]==1'b0 && Key>1'b1)
Flag3 <= 1'b0;
if(Flag2 < 4'd10)
begin
Beep <= ~Beep;
Flag2 <= Flag2+1'b1;
end
else
if(Key[0]==1'b1 && Flag3 == 1'b0)
begin
Flag3 <= 1'b1;
Flag2 <= 4'd0;
end
else
Flag2 <= 4'd10;
end
else
begin
Beep <= 1'b0;
Flag2 <= 4'd0;
end
end
//数码管动态显示
always @ (posedge Clk_1k)
begin
case(Mode) //模式切换
2'd0 : Time <= Time1;
2'd1 : Time <= Time2;
default : Time <= Time3;
endcase
Del <= ~Del; //选择十位和个位
if(Key > 3'd0)
Seg <= 8'd0;
else
Seg <= (Del == 2'b01) ? (seg[Time/10]) : (seg[Time%10]);
end
//点阵移屏显示
always @ (posedge Clk_1k)
begin
Col <= Num;
if(Key>3'd0 || Mode>2'd0)
begin
if(Key==3'd0 && Mode>2'd0)
Row <= data2[Num+count]; //"MODE爱心"
else
Row <= data1[Num+count]; //" STOP哭脸"
if(Num >= 4'd7)
Num <= 4'd0;
else
Num <= Num+1'b1;
end
else
begin
Row <= data[Num+count-8]; //" PASS笑脸"
if(Num == 4'd15 || Num<8)
Num <= 4'd8;
else
Num <= Num+1'b1;
end
if(cnt == 10'd200) //计数,控制点阵移屏速度
begin
cnt <= 10'd0;
if(count == 6'd47)
count <= 6'd0;
else
count <= count+1'b1;
end
else
cnt <= cnt+1'b1;
end
endmodule下载本文