2013-2014学年度第二学期电子技术基础课程设计--交通灯控制器设计院系:自动化学院专业:班级:姓名:学号:指导教师:目录一、课程设计名称 (3)二、课程设计要求 (3)三、系统设计 (3)1、系统框图与说明 (3)2、状态转换图 (5)3、输入输出设计 (6)四、系统仿真 (6)1、各模块仿真波形 (6)2、实测 (8)五、实验总结 (8)1、心得体会 (8)2、待改进的问题 (10)3、功能扩展 (10)附录 (11)一、课程设计名称交通灯控制器的设计二、设计内容及要求1、设计一个十字路口交通信号灯的控制电路。
要求红、绿灯按一定的规律亮和灭,并在亮灯期间进行倒计时,且将运行时间用数码管显示出来。
2、绿灯亮时,为该车道允许通行信号,红灯亮时,为该车道禁止通行信号。
要求主干道每次通行时间为Tx 秒,支干道每次通行时间为Ty 秒。
每次变换运行车道前绿灯闪烁,持续时间为5秒。
即车道要由X 转换为Y 时,X 在通行时间只剩下5秒钟时,绿灯闪烁显示,Y 仍为红灯。
3、可以对X,Y 车道上交通灯运行的时间进行重新设置,20≦Tx≦99,10≦Ty≦394、对器件进行在系统编程和实验验证。
5、写出设计性实验报告,并打印各层次的源文件和仿真波形,然后作简要说明。
三、系统设计1、系统框图与说明系统时钟分频模块置数模块时间计算状态转换译码模块数码管显示由上图,我们可以清楚地将系统分为六个模块:分频模块,时间设置模块,状态转换模块,时间计算模块,数码管译码模块,LED显示模块。
下面设计者将对每个模块进行详细的说明。
1)分频模块分频模块其作用为:由于DE2板上能够提供的时钟信号为50MHz,而设计所需时钟信号为1Hz,故使用分频模块将50MHz信号分频为1Hz信号。
2)时间设置模块由于系统设计要求可以对主干道,支干道上左转、绿灯运行的时间进行重新设置调整,所以要对系统进行参数化设计。
首先引入一组参数,main_gh,main_gl,main_lh,main_ll,branch_gh,branch_gl,branch_lh,branch_ll(下划线后面的字母分别取green,left,high,low首字母).需要置数时,首先选择对主干道还是支干道时间置数,这里设置一个main_or_branch参数,当main_or_branch为高时设置支干道时间,为低时设置主干道时间。
置数时,通过s_set_button,l_set_button对时间进行设置,具体方法参见代码。
为了置数方便,引入一个add_or_decent参数,低电平时按下button可以增计数,高电平时按下可以减计数。
而在程序设计上,可以运用always语句进行设计,来判断置数键的变化。
因为在Verilog HDL语言中always块中begin end在概念上顺序执行,实质上是并行的,因为每条语句的执行不占用具体时间,所有语句都是在一瞬间执行的,没有时间的先后,但有先后执行之分。
仿真时是逐条执行的。
但要弄清楚阻塞赋值和非阻塞赋值的区别。
如果全部都是非阻塞的赋值的话,才相当于并行的。
而此程序设计刚好要求,主干道绿灯计时的置数,主干道左转计时的置数,支干道绿灯计时的置数,支干道左转计时的置数并行进行,所以选用always语句很合适。
3)状态转换模块本设计将交通灯的整个过程划分为四个基本状态:主干道绿灯、主干道左转、支干道绿灯、支干道左转,用state、s_or_l为00、01、10、11来代表。
每当一个状态的计数器为00时,state、s_or_l发生改变,以实现状态间的转换。
4)时间计算模块由于本设计中加入了左转的时间,因此红灯时间不仅仅是另一干道的直行时间,而是直行时间和左转时间之和,由于在状态转换模块中需要用到大量的时间判断,因此将此模块单独划分。
5)数码管译码模块由于DE2板上无数码管译码电路,所以需要将4位的数码管控制信号译成7位控制信号。
6)LED显示模块由输入信号state、s_or_l、flash,分别取000,001,010,011,100,101,110,111所得到的main_green,main_left,main_red,branch_left,branch_green,branch_red的不同值,来控制主干道,支干道红绿左转灯的亮灭。
其中1表示亮,0表示灭。
如表3-1所示。
由上表可得到:main_green=~state&~s_or_l&(~(flash&clk));main_left=~state&s_or_l&(~(flash&clk));main_red=state;branch_green=state&~s_or_l&(~(flash&clk));branch_left=state&s_or_l&(~(flash&clk));branch_red=~state;2、状态转换图S0状态:主干道绿灯、支干道红灯S1状态:主干道左转、支干道红灯S2状态:支干道绿灯、主干道红灯S3状态:支干道左转、主干道红灯3、输入输出设计本设计硬件基于DE0板,具体输入输出如下:1)输入:开关:main_or_branch,EN,run_or_set,add_or_decent按键:s_set_button,l_set_button时钟:clk2)输出:数码管:OUT1L,OUT1H,OUT2L,OUT2HLED灯:main_green,main_red,main_leftbranch_left,branch_green,branch_red四、系统仿真1、各模块仿真波形1)分频模块2)时间设置模块这里给s_set_button和l_set_button分别设置持续的脉冲信号,可以看到,当main_or_branch为低时为主干道时间置数,为高时支干道时间置数,当add_or_decent为低时加计数,为高时减计数,仿真结果符合预期效果。
3)状态转换模块首先仿真EN为高时的运行状态,给主干道直行左转分别赋值25,15,支干道直行左转分别赋值15,10,主干道红灯时间26,支干道红灯时间41,从输出的state和s_or_l可以清楚的看出状态转换和时间的关系,flash的仿真结果也符合预期。
该图为run_or_set为低时的仿真图,可以看到,就算EN为高,此时数码管显示的也是赋值在counter_play3和counter_play4上的值,即置数值,符合仿真预期。
4)时间计算模块给输入的两个变量分别置数12,34,得到输出47,红灯时间应该等于直行加左转时间再加1,符合预期。
5)LED显示模块该模块即为状态转换仿真,将state,s_or_l,flash赋予相应的波形,可以看出,当state为00时,主干道直行灯亮,支干道红灯亮;01时,主干道左转灯亮,支干道红灯亮;10时,主干道红灯亮,支干道直行灯亮;11时,主干道红灯亮,支干道左转灯亮。
并且flash为高时LED灯出现闪烁,符合仿真结果。
2、实测已经现场验收通过。
五、实验总结1、心得体会看着手边不断变换的交通信号灯以及倒计时显示的数码管,回顾这5周以来为课设所做的所有努力,感慨良多。
只有亲身去努力尝试,才回收获真正的知识和能力。
为了找到切合实际的解决方案,我采用实地调查和网络搜集;为了寻找可能存在的BUG,我反复测试下载后的DE0板子,尽量穷尽各种可能出现的特殊情况,发现问题及时修改。
值得欣慰的是,所有的努力没有白费,到目前为止所做出的成果还是比较令我满意的。
在这里,要感谢龚军老师的教诲,感谢学校开设这门课程设计,给我们了一次充分锻炼,将理论知识付诸实践的机会。
书上的知识再多,都是死的,即使你完全记住,也无法在实际使用中游刃有余地去利用它们,不能让知识为我所用。
同时,在解决问题的时候,会发现自己依旧欠缺的知识,需要我们耐心地去查阅资料,不断补充新的领域的知识。
这样的一种锻炼,可以帮助我们形成一种习惯,在今后工作学习中,自然地去运用相同的方法解决不同的问题。
很多同学说,本科期间做项目找实习的机会太少,其实他们忽略了像课程设计这样的宝贵机会。
大学三年,我们学习了很多工程技术的知识,但却经常性的忽视在这些课程中的课程设计这个关键环节,认为它们只不过是走过场,抄抄代码,写写报告就够了。
其实不然,课程设计本身就是一次做项目的经历,它要求你严格按照项目规程操作,在时间和进度上,都要有项目意识。
虽然我学习过信息系统等软件开发的流程和方法,但是与实际运用严重脱节,没有那种清晰而强烈的工程思想,而是沿用做一步看一步的原始想法。
这次课程设计虽然系统架构不是很复杂,但还是需要一定的规划和思考才能做得快做得好,我们班拿到题目之后,只有很少部分人做了详细的开题报告,事实证明他们确实完成的质量也很高,所以说不能眼高手低,到最后却碌碌无为。
在调试的过程中,我也遇到了很多问题,比如计数器工作不正常,LED灯非正常闪烁,也废了很大的功夫才把BUG解决。
这里我要感谢班上和我做一个题目的同学们,在我绞尽脑汁无法找出BUG的时候,是他们帮助我解决了问题。
这个事情也充分说明了团队合作的重要性,每个人的想法都是极其宝贵的,汲取他人之所长会对自己的工作产生事倍功半的效果。
但是借鉴要有限度,要讲究方式方法。
很多同学容易走两个极端,一种是埋头编程,中途遇到很多困难其实前人也都遇到并且很好地解决了,但是他们还要继续重复地探寻解决途径;另一种是照单全收,完全不明白作者的用意和初衷,只知道看结果对就拿来用,没弄明白其所以然,显然是荒废了学习的机会。
课程设计给了我们把知识转化为能力的机会,这次电子技术课程设计更是让我受益良多,相信在我以后的求学过程中,这次课设给我带来的收获一定会指引我前进。
2、待改进的问题由于技术手段有限,未能加入人行道红绿灯提醒功能。
并且由于对题目理解不是很深刻,在红绿灯时间计算的时候出了一些问题,这些都是以后学弟学妹们做课设时候需要注意的。
3、功能扩展加入了左转功能,更加符合实际十字路口的情况,如果是DE2板,还可以用LCD屏显示状态,但遗憾未能实现。
附录:源代码module jiaotongdeng(clk,main_or_branch,EN,run_or_set,add_or_decent,s_set_button,l_set_button,main_green,main_red,branch_green,branch_red, main_left,branch_left,OUT1L,OUT1H,OUT2L,OUT2H);input clk,main_or_branch,EN,run_or_set,add_or_decent;input s_set_button,l_set_button;outputmain_green,main_red,main_left,branch_left,branch_green,branch_red; output[7:0]OUT1L,OUT1H,OUT2L,OUT2H;wire clk1;wire flash,state,s_or_l;wire[3:0]counter_play1h,counter_play1l;wire[3:0]counter_play2h,counter_play2l;wire[7:0]counter_play3,counter_play4;wire[3:0]branch_rl,branch_rh,main_rh,main_rl;wire[3:0]main_gh,main_gl,main_lh,main_ll,branch_gh,branch_gl,branch_lh,branch_ ll;fenpin f1(clk,clk1);//调用分频模块获得1hz脉冲Rtime f2(main_rh,main_rl,branch_gh,branch_gl,branch_lh,branch_ll);//计算主干道红灯时间Rtime f3(branch_rh,branch_rl,main_gh,main_gl,main_lh,main_ll);//计算支干道红灯时间state_transformer f4(clk1,EN,flash,state,s_or_l,run_or_set,main_gh,main_gl,main_lh,main_ll,branch_gh,branch_gl,branch_lh,bra nch_ll,main_rh,main_rl,branch_rh,branch_rl,counter_play3,counter_play4,counter_play1h,counter_play1l,counter_play2h,counter_play2l);//调用状态转换模块timeset f5(clk,main_or_branch,add_or_decent,s_set_button,l_set_button,main_gh,main_gl,main_lh,main_ll,branch_gh,branch_gl,branch_lh,branch_ ll,counter_play3,counter_play4);//调用时间设置模块LED_displayf6(clk1,flash,state,s_or_l,main_green,main_left,main_red,branch_green, branch_left,branch_red);//调用LED显示模块yima f7(counter_play1h,counter_play1l,OUT1H,OUT1L);//译码显示时间至数码管yima f8(counter_play2h,counter_play2l,OUT2H,OUT2L);endmodulemodule fenpin(clk,clk1);input clk;output clk1;reg clk1;reg[24:0]counter;//定义计数器initialbeginclk1=0;counter=0;endalways@(posedge clk)beginif(counter==25'd2*******)//每25m个时钟周期clk1反向,同时计数器清零beginclk1<=~clk1;counter<=0;endelsecounter<=counter+1'b1;end//end alwaysendmodulemodule yima(Inh,Inl,Out_H,Out_L);input[3:0]Inh,Inl;output[7:0]Out_H,Out_L;reg[7:0]Out_H,Out_L;always@(Inh)begincase(Inh)0:Out_H=8'b11000000;//共阴极数码管译码1:Out_H=8'b11111001;2:Out_H=8'b10100100;3:Out_H=8'b10110000;4:Out_H=8'b10011001;5:Out_H=8'b10010010;6:Out_H=8'b10000010;7:Out_H=8'b11111000;8:Out_H=8'b10000000;9:Out_H=8'b10010000;default Out_H=8'bxxxxxxxx;endcaseendalways@(Inl)begincase(Inl)0:Out_L=8'b11000000;1:Out_L=8'b11111001;2:Out_L=8'b10100100;3:Out_L=8'b10110000;4:Out_L=8'b10011001;5:Out_L=8'b10010010;6:Out_L=8'b10000010;7:Out_L=8'b11111000;8:Out_L=8'b10000000;9:Out_L=8'b10010000;default Out_L=8'bxxxxxxxx;endcaseendendmodulemodule timeset(clk,main_or_branch,add_or_decent,s_set_button,l_set_button,main_gh,main_gl,main_lh,main_ll,branch_gh,b ranch_gl,branch_lh,branch_ll,counter_play3,counter_play4);input s_set_button;input l_set_button;input clk;input main_or_branch;//用来控制counter_play3,counter_play4显示主干道还是支干道设置的时间,0主1支input add_or_decent;//用于控制按钮增减置数值,为0加,为1减output[7:0]counter_play3,counter_play4;//分别显示绿灯、左转设置时间output[3:0]main_gh,main_gl,main_lh,main_ll;output[3:0]branch_gh,branch_gl,branch_lh,branch_ll;reg[7:0]counter_play3,counter_play4;reg[3:0]main_gh,main_gl,main_lh,main_ll;reg[3:0]branch_gh,branch_gl,branch_lh,branch_ll;always@(posedge s_set_button)//直行时间设置if(add_or_decent==0)//增加时间beginif(main_or_branch==0)//设置主干道beginbeginif(main_gl==9)beginmain_gl<=0;if(main_gh==9)main_gh<=0;else main_gh<=main_gh+1;endelse main_gl<=main_gl+1;endendelse//设置支干道beginif(branch_gl==9)beginbranch_gl<=0;if(branch_gh==9)branch_gh<=0;else branch_gh<=branch_gh+1;endelse branch_gl<=branch_gl+1;endend//end add setelse//减少时间beginif(main_or_branch==0)beginif(main_gl==0)beginmain_gl<=9;if(main_gh==0)main_gh<=9;else main_gh<=main_gh-1;endelse main_gl<=main_gl-1;endendelse//设置支干道beginif(branch_gl==0)beginbranch_gl<=9;if(branch_gh==0)branch_gh<=9;else branch_gh<=branch_gh-1;endelse branch_gl<=branch_gl-1;endendalways@(posedge l_set_button)//左转时间设置if(add_or_decent==0)beginif(main_or_branch==0)beginbeginif(main_ll==9)beginmain_ll<=0;if(main_lh==9)main_lh<=0;else main_lh<=main_lh+1;endelse main_ll<=main_ll+1;endendelsebeginif(branch_ll==9)beginbranch_ll<=0;if(branch_lh==9)branch_lh<=0;else branch_lh<=branch_lh+1;else branch_ll<=branch_ll+1;endendelsebeginif(main_or_branch==0)beginbeginif(main_ll==0)beginmain_ll<=9;if(main_lh==0)main_lh<=9;else main_lh<=main_lh-1;endelse main_ll<=main_ll-1;endendelsebeginif(branch_ll==0)beginbranch_ll<=9;if(branch_lh==0)branch_lh<=9;else branch_lh<=branch_lh-1;endelse branch_ll<=branch_ll-1;endendalways@(posedge clk)beginif(main_or_branch==0)//显示主干道设置的时间begincounter_play3<={main_gh,main_gl};counter_play4<={main_lh,main_ll};endelse if(main_or_branch==1)//显示支干道设置的时间begincounter_play3<={branch_gh,branch_gl};counter_play4<={branch_lh,branch_ll};endendendmodulemodule state_transformer(clk,EN,flash,state,s_or_l,run_or_set,main_gh,main_gl,main_lh,main_ll,baranch_gh,baranch_gl,baranch_lh, baranch_ll,main_rh,main_rl,branch_rh,branch_rl,counter_play3,counter_play4,counter_play1h,counter_play1l,counter_play2h,counter_play2l);input clk;input EN,run_or_set;//run_or_set为1时显示运行时的时间,为0显示设置时间input[3:0]main_gh,main_gl,main_lh,main_ll;input[3:0]baranch_gh,baranch_gl,baranch_lh,baranch_ll;input[3:0]main_rh,main_rl,branch_rh,branch_rl;input[7:0]counter_play3,counter_play4;output[3:0]counter_play1h,counter_play1l;output[3:0]counter_play2h,counter_play2l;output flash,state,s_or_l;//输出状态变量reg flash;reg state;reg s_or_l;reg[3:0]main_rhtemp,main_rltemp,branch_rhtemp,branch_rltemp;reg[3:0]main_ghtemp,main_gltemp,main_lhtemp,main_lltemp;reg[3:0]baranch_ghtemp,baranch_gltemp,baranch_lhtemp,baranch_lltemp; reg[3:0]counter_play1h,counter_play1l,counter_play2h,counter_play2l;always@(posedge clk)beginif(EN==0)//EN每置一次0对计数中间变量进行一次初始化beginmain_ghtemp<=main_gh;main_gltemp<=main_gl;baranch_ghtemp<=baranch_gh;baranch_gltemp<=baranch_gl;main_rhtemp<=main_rh;branch_rhtemp<=branch_rh;main_lhtemp<=main_lh;main_lltemp<=main_ll;baranch_lhtemp<=baranch_lh;baranch_lltemp<=baranch_ll;main_rltemp<=main_rl;branch_rltemp<=branch_rl;state<=0;s_or_l<=0;endelse if(EN==1)beginif(state==1)//主干道红灯begincounter_play1h<=main_rhtemp;//主干道显示红灯计数counter_play1l<=main_rltemp;if((main_rltemp==0)&&(main_rhtemp>=1))beginmain_rhtemp<=main_rhtemp-1;main_rltemp<=9;endelse if((main_rltemp>=1)&&(main_rltemp<=9))beginmain_rltemp<=main_rltemp-1;endelse if((main_rhtemp==0)&&(main_rltemp==0))beginmain_rhtemp<=main_rh;main_rltemp<=main_rl;endendif(state==0)//支干道红灯begincounter_play2h<=branch_rhtemp;//支干道显示红灯计数counter_play2l<=branch_rltemp;if((branch_rltemp==0)&&(branch_rhtemp>=1))beginbranch_rhtemp<=branch_rhtemp-1;branch_rltemp<=9;endelse if((branch_rltemp>=1)&&(branch_rltemp<=9))beginbranch_rltemp<=branch_rltemp-1;endelse if((branch_rhtemp==0)&&(branch_rltemp==0))beginbranch_rhtemp<=branch_rh;branch_rltemp<=branch_rl;endendif(state==0&&s_or_l==0)//主干道直行begincounter_play1h<=main_ghtemp;//主干道显示直行时间counter_play1l<=main_gltemp;if((main_gltemp==0)&&(main_ghtemp>=1))beginmain_ghtemp<=main_ghtemp-1;main_gltemp<=9;endif((main_gltemp>=1)&&(main_gltemp<=9))beginif((main_ghtemp==0)&&(main_gltemp==5))beginflash<=1;//绿灯剩余五秒闪烁main_gltemp<=main_gltemp-1;endelsemain_gltemp<=main_gltemp-1;endelse if((main_ghtemp==0)&&(main_gltemp==0))beginstate<=0;s_or_l<=1;//状态转换为主干道左转flash<=0;main_ghtemp<=main_gh;main_gltemp<=main_gl;endendif(state==0&&s_or_l==1)//主干道左转灯begincounter_play1h<=main_lhtemp;//主干道显示左转灯时间counter_play1l<=main_lltemp;if((main_lltemp==0)&&(main_lhtemp>=1))beginmain_lhtemp<=main_lhtemp-1;main_lltemp<=9;endif((main_lltemp>=1)&&(main_lltemp<=9))beginif((main_lhtemp==0)&&(main_lltemp==5))beginflash<=1;main_lltemp<=main_lltemp-1;endelsemain_lltemp<=main_lltemp-1;endelse if((main_lhtemp==0)&&(main_lltemp==0))beginstate<=1;//状态转换为主干道红灯s_or_l<=0;//支干道直行flash<=0;main_lhtemp<=main_lh;main_lltemp<=main_ll;endendif(state==1&&s_or_l==0)//支干道直行begincounter_play2h<=baranch_ghtemp;//支干道显示直行时间counter_play2l<=baranch_gltemp;if((baranch_gltemp==0)&&(baranch_ghtemp>=1))beginbaranch_ghtemp<=baranch_ghtemp-1;baranch_gltemp<=9;endif((baranch_gltemp>=1)&&(baranch_gltemp<=9))beginif((baranch_ghtemp==0)&&(baranch_gltemp==5))beginflash<=1;baranch_gltemp<=baranch_gltemp-1;endelsebaranch_gltemp<=baranch_gltemp-1;endelse if((baranch_ghtemp==0)&&(baranch_gltemp==0)) beginstate<=1;s_or_l<=1;//状态转换为支干道左转flash<=0;baranch_ghtemp<=baranch_gh;baranch_gltemp<=baranch_gl;endendif(state==1&&s_or_l==1)//支干道左转灯begincounter_play2h<=baranch_lhtemp;//支干道显示左转灯时间counter_play2l<=baranch_lltemp;if((baranch_lltemp==0)&&(baranch_lhtemp>=1))beginbaranch_lhtemp<=baranch_lhtemp-1;baranch_lltemp<=9;endif((baranch_lltemp>=1)&&(baranch_lltemp<=9))beginif((baranch_lhtemp==0)&&(baranch_lltemp==5))beginflash<=1;baranch_lltemp<=baranch_lltemp-1;endelsebaranch_lltemp<=baranch_lltemp-1;endelse if((baranch_lhtemp==0)&&(baranch_lltemp==0))beginstate<=0;s_or_l<=0;//状态转换为主干道直行flash<=0;baranch_lltemp<=baranch_ll;baranch_lhtemp<=baranch_lh;endendend//if endif(run_or_set==0)//显示设置时间begincounter_play1h<=counter_play3[7:4];counter_play1l<=counter_play3[3:0];counter_play2h<=counter_play4[7:4];counter_play2l<=counter_play4[3:0];endend//end alwaysendmodulemodule Rtime(OutH,OutL,In1H,In1L,In2H,In2L);//红灯时间计算input[3:0]In1H,In1L,In2H,In2L;output[3:0]OutH,OutL;reg[3:0]OutH,OutL;reg[3:0]outh1,outl1;//定义一组中间变量always@(In1H or In1L or In2H or In2L)//被加数先加1,在加加数beginif((In1L+1)>=4'b1010)//低位大于等于9时的情况beginoutl1<=In1L+1-4'b1010;outh1<=In1H+1'b1;endelsebeginoutl1<=In1L+1;outh1<=In1H;endif((outl1+In2L)>=4'b1010)beginOutL<=outl1+In2L-4'b1010;OutH<=outh1+In2H+1'b1;endelsebeginOutL<=outl1+In2L;OutH<=outh1+In2H;endif((((outl1+In2L)>=4'b1010)&&((outh1+In2H)==4'b1001))||(((outh1+In2H) >4'b1001)))//若直行和左转绿灯时间相加大于99则默认为99beginOutL<=4'b1001;OutH<=4'b1001;endendendmodulemoduleLED_display(clk,flash,state,s_or_l,main_green,main_left,main_red,bran ch_green,branch_left,branch_red);input clk,state,s_or_l,flash;outputmain_green,main_left,main_red,branch_green,branch_left,branch_red;//两个干道各三盏灯,分别代表直行、左转、红灯assign main_green=~state&~s_or_l&(~(flash&clk));//利用真值表获得表达式,闪烁利用flash和clk相与可实现assign main_left=~state&s_or_l&(~(flash&clk));assign main_red=state;assign branch_green=state&~s_or_l&(~(flash&clk));assign branch_left=state&s_or_l&(~(flash&clk));assign branch_red=~state;endmodule。