FPGA双模式交通灯的设计
一、设计要求
1.模块一:模拟十字路口主干道与辅道灯光变化情况:
a.FPGA板上电后,控制显示的开关拨至高电平,进行五秒的倒计时,然后出现第一次红绿灯转换;
b.接下来会根据所处不同的状态有不同的倒计时,实现一个四状态的红绿灯转换,最大限度模拟了实际路况。
具体实现要求为:
(1)主路按照绿灯,黄灯,红灯的顺序循环闪烁;
(2)支路按照红灯,绿灯,黄灯的顺序循环闪烁;
(3)两路的灯光状态转换要分别独立按照次序完成且要有各自的计时显示;
(4)可以任意调整计时时间,在计时结束后自动进入下一循环。
2.模块二:模拟双行道间歇式红绿灯及行人通过的情况:
a.FPGA板上电后,控制显示的开关拨至低电平,输出数码管与LED灯进入此模块,自然情况下一直为绿灯,且数码管不会改变;
b.如果行人按键为高电平时,进入倒计时状态,结束后会更新数码管数字且LED灯变为红灯;
c.等待行人通过后,重新进入自然状态,等待下一次行人按键的触发。
具体实现要求为:
(1)没有行人时,两个灯均为绿灯,数码管维持数字9;
(2)有行人按下按键后,此时还是绿灯,数码管进行9秒的倒计时;
(3)倒计时结束后,两个灯均变为红灯,数码管进行9秒的倒计时;
(4)倒计时结束后,恢复触发之前的状态,并检测按键的高低电平判断是否进行下一次状态转换。
二、设计思路
整体思路:
首先,要实现不同状态的转换,需要通过状态机来实现,这在两个模块里都是通用的。然后,围绕着状态机的设置,我们可以依据具体的数码管显示和三色灯的颜色变化进行逻辑结构的设计。同时,分频电路和数码管转换部分在将逻辑电路实现在FPGA上是不可缺少的一部分。而对于两个交通灯模块,需要进一步具体分析。
对于自动计时实现状态转换的十字交叉路口交通灯电路,我们设计的重点是两个方向交通灯的红、绿、黄三种颜色的独立转换,从而更好的模拟实际路况。由于硬件的限制,所以在实现三色灯状态转换的同时,数码管显示状态转换间隔的时间。而对于如何控制每一个灯下一状态是维持原状还是跳转这一问题,我们使用一个计数器模块进行控制,当其满足跳转要求方可进入下一状态。
对于行人主动触发的主干道双向交通灯电路,我们在状态机的变换上相较于上一程序更加简单,只有红和绿两种模式;但是,添加了一个主动触发的信号,作为自然状态的唯一触发条件,用来控制状态机的跳变。而计时器模块充当了过程中的触发条件,当满足跳转要求进入下一状态,同时灯光也会变化。而经过一个周期后,需要判断行人是否再次触发了信号,如果是,进入新的一轮周期;如果不是,此模块回到并保持自然状态。
最后,为了代码的整洁性与使用者的方便性,故设计顶层模块,调用这两个子模块,通过一个信号控制两种模式的转换显示,但是两种交通灯模块在同时运行,只是分时输出结果。
分频思路:
第一种思路:
(1)复位信号时,计数器清零,输出时钟置低电平。
(2)计数器到 N/2- 1 时,时钟翻转,计数器继续累加
(3)计数器到 N-1 时,时钟翻转,计数器清零
(4)计数器在其他值是输出保持,计数器继续累加
这种思路的思想是,在计数器为 0~N/2-1时,输出时钟保持一个状态,N/2~N-1时保持另一个状态。
第二种思路:
(1)复位信号时,计数器清零,输出时钟置低电平。
(2)计数器到 N/2-1 时,时钟翻转,计数器清零。
(3)计数器为其余值时,继续保持加一。
这种思路的思想是,在计数器为 0~N/2-1 时,输出时钟保持一个状态 ,在计数器为 下一个0~N/2-1时保持另一个状态。
具体思路:
秒脉冲发生器是该系统中计数器模块、状态转换的标准时钟信号源,计数器模块主要为状态转换模块提供两个转换信号,译码显示模块将计数器的计数状态译码并通过数码管进行显示,状态转换模块是系统的主要部分,由它控制红绿灯的状态转换,译码模块将状态转换模块所处状态进行译码,并驱动红绿灯进行状态显示;
其中红绿状态正常输出,黄灯状态由红加绿输出显示,数码管具体显示如下:
S1:主路绿灯点亮,支路红灯点亮,持续5s;
S2:主路黄灯点亮,支路红灯点亮,持续6s;
S3:主路红灯点亮,支路绿灯点亮,持续4s;
S4:主路红灯点亮,支路黄灯点亮,持续7s;
三、各模块具体功能分析
1、分频模块
由于系统自带的时钟信号频率偏高,故需要通过分频的方式得到满足实际需求的频率,输入clk,输出满足要求的clk1。具体程序如下:
2、traffic模块
此模块实现了自动计时的十字交叉路口交通灯电路,作为子模块也需要调用分频器模块作为驱动的输入,包括状态机的转换和数码管电路与三色灯的输出。具体程序如下:
3、button模块
此模块实现了行人触发的双直行路口交通灯电路,作为子模块也需要调用分频器模块作为驱动的输入,包括行人触发信号的转换、状态机的转换和数码管电路与三色灯的输出。具体程序如下:
4、top模块
此模块作为顶层模块,需要调用分频器模块、traffic模块和button模块,通过层次化设计,极大的简化了程序,同时又保证了使用者的良好体验。具体代码如下:
四、Verilog源程序
完整代码如下所示:
顶层模块
module top(clk,rst_n,M,T,out,seg_led);
input clk;
input rst_n; //清零信号
input M; //button模块中的行人触发按键
input T; //模式转换按键
output reg[5:0] out; //两个三色灯的输出
output reg[8:0] seg_led; //数码管的输出
wire [8:0] seg_led1,seg_led2; //线网类型变量
wire [5:0] out1,out2;
//时钟信号分频
divider #(.N(6000000),.WIDTH(24)) divider1
(
.clk(clk),
.rst(rst_n),
.clk_out(clk1)
);
//traffic模块的调用
traffic traffic1
(
.clk(clk),
.rst_n(rst_n),
.out(out1),
.seg_led(seg_led1)
);
//button模块的调用
button button1
(
.clk(clk),
.rst_n(rst_n),
.M(M),
.out(out2),
.seg_led(seg_led2)
);
//外部按键控制输出两种模式的显示
always @ (*) begin
if(T) begin
out=out1;
seg_led=seg_led1;
end
else begin
out=out2;
seg_led=seg_led2;
end
end
endmodule
分频器模块
module divider(
inout clk,
input rst,
output reg clk_out
);
parameter N=6000000,WIDTH=24;
reg [WIDTH-1:0] cnt;
always @(posedge(clk),negedge(rst)) begin
if(rst==1'b0)
cnt<=24'b0;
else if (cnt==N-1)
cnt<=24'b0;
else
cnt<=cnt+1;
end
always @(posedge(clk),negedge(rst)) begin
if(rst==1'b0)
clk_out<=1'b0;
else if(cnt==N-1)
clk_out<=~clk_out;
else
clk_out<=clk_out;
end
endmodule
十字路口交通灯模块
module traffic(clk,rst_n,out,seg_led);
input clk,rst_n;
output reg[5:0] out;
output [8:0] seg_led; //高9位为高位数码管,低9位为低位数码管
reg[1:0] current_state,next_state;
reg [8:0] seg[9:0];
reg[2:0] timecout; //timecout作为时间计数标志,
//为1代表之前持续的状态结束,进入下一状态,不为1代表之前持续的状态未结束,维持此状态
parameter s0=2'b00,s1=2'b01,s2=2'b10,s3=2'b11; //状态机的状态编码
parameter time_s0=3'b101,time_s1=3'b110,time_s2=3'b100,time_s3=3'b111; //一个周期的4种时间间隔
parameter led_s0=6'b101011, //led2亮绿灯,led1亮红灯
led_s1=6'b001011, //led2亮黄灯,led1亮红灯
led_s2=6'b011101, //led2亮红灯,led1亮绿灯
led_s3=6'b011001; //led2亮红灯,led1亮黄灯
//数码管初始电路设置,使每一个二进制码与数码管显示的数字一一对应
initial
begin
seg[0] = 9'h3f; //7段显示数字 0
seg[1] = 9'h06; //7段显示数字 1
seg[2] = 9'h5b; //7段显示数字 2
seg[3] = 9'h4f; //7段显示数字 3
seg[4] = 9'h66; //7段显示数字 4
seg[5] = 9'h6d; //7段显示数字 5
seg[6] = 9'h7d; //7段显示数字 6
seg[7] = 9'h07; //7段显示数字 7
seg[8] = 9'h7f; //7段显示数字 8
seg[9] = 9'h6f; //7段显示数字 9
end
//时钟信号分频
divider #(.N(6000000),.WIDTH(24)) divider1
(
.clk(clk),
.rst(rst_n),
.clk_out(clk1)
);
//次态到现态的转换
always @ (posedge clk1,negedge rst_n) begin
if(!rst_n)
current_state <= s0; //同步清零
else
current_state <= next_state; //在clk的上升沿触发器状态改变
end
//组合逻辑描述状态转移的判断
always @ (current_state,rst_n,timecout) begin
if(!rst_n)
next_state<=s0;
else begin
case(current_state)
s0:begin
if(timecout==1) //timecout作为时间计数标志
next_state=s1; //为1代表之前持续的状态结束,进入下一状态
else
next_state=s0; //不为1代表之前持续的状态未结束,维持此状态
end
s1:begin
if(timecout==1)
next_state=s2;
else
next_state=s1;
end
s2:begin
if(timecout==1)
next_state=s3;
else
next_state=s2;
end
s3:begin
if(timecout==1)
next_state=s0;
else
next_state=s3;
end
endcase
end
end
//判断时间计数是否结束,及输出led
always @ (posedge(clk1),negedge(rst_n)) begin
if(!rst_n) begin
out<=led_s0;
timecout<=time_s0;
end
else begin
case(next_state)
s0:begin
out<=led_s0;
if(timecout==1) //即上一个状态结束后timecout为1,需要重新赋值
timecout<=time_s0;
else
timecout<=timecout-1;
end
s1:begin
out<=led_s1;
if(timecout==1)
timecout<=time_s1;
else
timecout<=timecout-1;
end
s2:begin
out<=led_s2;
if(timecout==1)
timecout<=time_s2;
else
timecout<=timecout-1;
end
s3:begin
out<=led_s3;
if(timecout==1)
timecout<=time_s3;
else
timecout<=timecout-1;
end
endcase
end
end
assign seg_led = seg[timecout];
endmodule
行人触发双直行交通灯模块
module button(clk,rst_n,M,out,seg_led);
input clk,rst_n;
input M; //行人触发按键,按下后进入倒计时,然后方可通过马路
output reg[5:0] out;
output [8:0] seg_led; //高9位为高位数码管,低9位为低位数码管
reg current_state;
reg next_state=1'b0;
reg start; //按键触发的标志
reg[3:0] timecout;
reg [8:0] seg[9:0];
parameter s0=1'b0,s1=1'b1; //状态机的状态编码
parameter time_s0=4'b1001,time_s1=4'b1001; //一个周期的2种时间间隔
parameter led_s0=6'b101101, //led2,led1均亮绿灯,代表双行道车辆畅行
led_s1=6'b011011; //led2,led1均亮红灯,代表行人过马路
//数码管初始电路设置,使每一个二进制码与数码管显示的数字一一对应
initial
begin
seg[0] = 9'h3f; //7段显示数字 0
seg[1] = 9'h06; //7段显示数字 1
seg[2] = 9'h5b; //7段显示数字 2
seg[3] = 9'h4f; //7段显示数字 3
seg[4] = 9'h66; //7段显示数字 4
seg[5] = 9'h6d; //7段显示数字 5
seg[6] = 9'h7d; //7段显示数字 6
seg[7] = 9'h07; //7段显示数字 7
seg[8] = 9'h7f; //7段显示数字 8
seg[9] = 9'h6f; //7段显示数字 9
end
//时钟信号分频
divider #(.N(6000000),.WIDTH(24)) divider1
(
.clk(clk),
.rst(rst_n),
.clk_out(clk1)
);
//状态转换
always @ (posedge clk1,negedge rst_n) begin
if(!rst_n)
current_state <= s0; //同步清零
else
current_state <= next_state; //在clk的上升沿触发器状态改变
end
//判断触发条件
always @ (posedge clk1,negedge rst_n,posedge M) begin
if(!rst_n)
start<=0;
else if(M)
start<=1;
else
start<=0;
end
//组合逻辑描述状态转移的判断
always @ (current_state,rst_n,timecout) begin
if(!rst_n) begin
next_state<=s0;
end
else begin
case(current_state)
s0:begin
if(start==0)
next_state<=s0;
else begin
if(timecout==1) //timecout作为时间计数标志
next_state<=s1; //为1代表之前持续的状态结束,进入下一状态
else
next_state<=s0; //不为1代表之前持续的状态未结束,维持此状态
end
end
s1:begin //因为到达s1后下一个状态的转换只取决于倒计时是否结束,所以不用考虑start的状态
if(timecout==1)
next_state<=s0;
else
next_state<=s1;
end
endcase
end
end
//判断时间计数是否结束,及输出led和数码管显示
always @ (posedge(clk1),negedge(rst_n)) begin
if(!rst_n) begin
out<=led_s0;
timecout<=time_s0;
end
else begin
case(next_state)
s0:begin
out<=led_s0;
if(start==1) begin
if(timecout==1) //即上一个状态结束后timecout为1,需要重新赋值
timecout<=time_s0;
else
timecout<=timecout-1;
end
else
timecout=9;
end
s1:begin
out<=led_s1; //start省略,原因和上面一样
if(start==1) begin
if(timecout==1)
timecout<=time_s1;
else
timecout<=timecout-1;
end
end
endcase
end
end
assign seg_led = seg[timecout];
endmodule
五、调试过程
1、Analysis&Synthesis成功的截图 :
2、管脚分配表的截图 :
3、Compile Design成功的截图 :
4、programmer成功的截图:
六、实验板演示
1.十字交叉路口交通灯模块演示:
2.行人触发双直行交通灯模块演示:
七、故障分析与解决
1、出现问题:在数码管状态转换时出现了灯光闪烁不正常的现象,如按照设置规律应当显示红黄结果显示了红绿的情况。
解决方法:可以确定是时序逻辑的转换出现了问题,在always语句中更改为准确的触发条件即可解决这一问题。
2、出现问题:顶层设计中在将两个子模块程序分时显示时出现报错,系统认为输出没有指定变量类型
解决方法:将两个子程序的输出指定为wire类型,即可满足要求。
3、出现问题:LED灯的展示中没有出现问题,但当到了数码管显示中就会发现从第一个倒计时转到第二个倒计时时就会发现无法实现正常循环。
解决方法:时序逻辑的问题,改正always敏感条件后即可解决。
八、心得体会
1、在本次实验中,我们学到了非常多的东西,懂得了集思广益对于综合实验的重要性,一个人的思考很难得到有建设性的效果,且很容易走进思维的死胡同。在遇到问题后,多查阅资料与请教他人可以得到更多的解决思路。
2、在实验中,思考和动手是非常重要的,像我们这次实验设计之初遇到了很多问题,也常常出错,在经过相关知识的系统学习和实际动过手之后,我们更迅速地掌握了其中的原理和实践方法,并加深了知识的记忆。
3、在实验中我们通过自顶向下的分析方法确定了设计原理和流程,查阅相关资料,进行Verilog HDL语言程序的编写,进行了分频器,状态转换电路,数码管电路等设计,对于层次化设计和分块思想有了更深的理解。
4、在此小组合作中,我们大家明确分工,提高了实验设计和报告总结的效率,经过多次交流沟通,使得这次实验的任务圆满完成。
FPGA双模式交通灯的设计相关推荐
- 基于fpga的交通灯的设计
课题一:交通灯控制设计 1.课程设计的目的与要求 1.1目的 以FPGA为核心,设计一个交通灯控制器,每个路口都有红.黄.绿三盏灯.该交通信号灯控制器由一条车道A和一条车道B汇合成十字路口,在每个入口 ...
- 51单片机 时间控制的不同时段交通灯控制设计(简单版)
这个交通灯的设计时简单版,只有一个路口(不是十字路口)的那种(想要实现十字路口可以对代码稍加修改) 使用的开发软件:Keil uVision5 单片机类型为:C51 语言类型:C语言 在这里说一下实现 ...
- 基于单片机的十字路口交通灯课程设计
1.设计要求: 设计一个十字路口交通灯控制器.用单片机控制LED灯模拟指示.模拟东西方向的十字路口交通信号控制情况.东西向通行时间为80s,南北向通行时间为60s,缓冲时间为3s. 2.设计思路: 通 ...
- C语言红绿灯课程设计,C语言版交通灯课程设计.doc
C语言版交通灯课程设计 微机控制课程设计报告 课程名称 基于C语言单片机交通灯 学生姓名 张 万 双 学号 51102022004 专业班级 电子信息科学与技术2班 指导老师 2013年12月5日 目 ...
- 52单片机交通灯课程设计
单片机交通灯课程设计 1. 实验目的和器件 1.1实验目的 (1)通过单片机课程设计,熟练掌握C语言的编写方法,将理论联系到实际中去,提高我们的动手和动脑能力. (2)通过交通信号灯控制系统的设计,掌 ...
- 现代交通灯的设计C语言编程,交通灯设计_优秀论文.doc
. PAGE .. 毕业论文(设计) 题 目 基于单片机控制的 交通灯的设计 _ 学生姓名 学 号 专业班级 指导教师 完成时间: 201 年 月 日 . PAGE .. 摘 要 交通信号灯的出现,使 ...
- 【Arduino】交通灯控制设计 四位数码管
实验现象 在Arduino开发板上设计红黄绿Led灯定时循环同步数码管显示,以数码管时间显示进行定时循环控制,要求红绿灯定时15秒,黄灯定时5秒.并在此基础之上设计串口通信键盘输入变量进行红黄绿LED ...
- c语言交通灯控制设计和原理图,十字路口交通灯控制设计(附电路图及源代码).doc...
十字路口交通灯控制设计(附电路图及源代码) <计算机控制技术> 课程设计报告 课题名称 交通灯控制设计 专 业 班 级 学生姓名 学 号 指导教师 201*年 6 月 8日 目录 TOC ...
- FPGA(7)--有限状态机--交通灯
文章目录 一.实验目的 二.实验内容 三.实验设计与结果 四.实验思考与小结 一.实验目的 掌握有限状态机的编程和使用方法. 二.实验内容 设计一个十字路口交通灯控制器,东西(b).南北(a)方向有红 ...
最新文章
- 当思想与机器融合:脑机接口与人类的现在、困境与未来
- 这也不能一直在这儿瞎忙活
- Xamarin.Forms支持的地图显示类型
- MJExtension 模型嵌套模型数组
- 限制数据记录查询数量
- Java写十进制和二进制互转
- 第二章 数据类型和文件操作
- Python学习笔记:Day 9 编写API
- 【Android】关于Android控件EditText的属性InputType的一些经验
- 失血多少会贫血_阿胶糕治贫血两大好处,治疗贫血两大方法要掌握
- struct and union
- 一个项目有两个pom_Python Selenium设计模式之POM设计模式
- 浅谈第三方电子支付平台测试方法的研究
- NLP高阶实战必读:一文走遍完整自然语言处理流程 文章
- 百度开源的 71 个炸天项目
- 计算机四级题库百度云,四级题库免费
- 计算机主机放电,电脑需要放电才能开机_电脑主板放电才能开机
- 全外显子测序助力疾病诊疗
- Simulink-repeating squence
- zyb的面试 字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛