当前位置: 首页 > 范文大全 > 公文范文 >

[北邮数字电路综合实验报告——交通灯控制器VHDL实现]

时间:2021-10-15 13:30:34 来源:网友投稿

 数字电路综合实验报告

 班 级:

 姓 名:

 班内序号:

 学 号:

 日 期:

 目录TOC \o "1-3" \h \u

  30779 一、实验摘要 3

  2634 二、实验任务 3

  13164 1.任务要求 3

  4997 2.任务解析 3

  13415 三、实验设计思路 4

  21293 1.状态转移图 4

  25546 2.流程图 5

  22418 3.模块确定 5

  1551 4.系统框图 7

  11535 四、程序代码 7

  28891 ⒈主程序 7

  19071 ⒉分频模块 9

  8235 ⒊防抖模块 10

  16981 ⒋交通灯控制模块 11

  20860 ⒌数字译码模块 14

  25988 五、实验结果 15

  15778 1.仿真结果 15

  11930 2.实物结果 17

  3563 六、所遇问题分析 17

  16058 七、实验总结 18

 交通灯控制器的VHDL实现

 一、实验摘要

 随着交通情况的日益复杂,交通灯在生活中所处的位置也越来越高。本实验就是基于VHDL语言编程实现了十字路口的交通灯控制器。对于交通等控制器的设计是分模块自顶向下的设计思想,软硬件结合来实现本设计。

 关键字:交通灯、VHDL、控制器

 二、实验任务

 1.任务要求

 南北和东西方向各有一组绿、黄、红灯用于指挥交通,绿灯、黄灯和红灯的持续时间分别为20秒、5秒和25秒;

 当有特殊情况(如消防车、救护车等)时,两个方向均为红灯亮,计时停止,当特殊情况结束后,控制器恢复原来状态,继续正常运行;

 用两组数码管,以倒计时方式显示两个方向允许通行或禁止通行的时间;

 2.任务解析

 东西(A车道)和南北(B车道)方向各有一组绿、黄、红灯用于指挥交通(如图1),绿灯、黄灯和红灯的持续时间分别为 20 秒、5 秒和 25 秒。

 图1 十字路口交通灯模型

 因此,可以设计如下四个状态,其关系为:

 状态

 亮灯情况

 车辆行驶状况

 持续时间(秒)

 下一状态

 A车道

 B车道

 S0

 红亮

 红亮

 紧急状况,A/B车道均禁止通行

 ~

 S1

 S1

 绿亮

 红亮

 A车道通行,B车道禁止通行

 20

 S2

 S2

 黄亮

 红亮

 A车道缓行,B车道禁止通行

 5

 S3

 S3

 红亮

 绿亮

 A车道禁止通行,B车道通行

 20

 S4

 S4

 红亮

 黄亮

 A车道禁止通行,B车道缓行

 5

 S1

 三、实验设计思路

 1.状态转移图

 图2 状态转移图

 2.流程图

 图3 流程图

 3.模块确定

 ⑴分频模块

 设计原因:由于实验板只能提供50MHz的时钟信号,而电路中只能使用较低频率的时钟:

 1Hz时钟信号:计数器count变化时使用;

 20Hz时钟信号:在防抖电路中使用的时钟信号;

 1kHz时钟信号哦:用于数码管位选信号的改变的时钟信号。

 功能:用于将实验板上的50MHz的时钟信号经分频后输出:1kHz、20Hz、1Hz。

 图4 分频模块的输入和输出

 ⑵防抖动模块

 设计原因:只要有按键或是拨码开关,防抖电路就是不可缺少的一个模块。否则,按键信号中的一些毛刺和抖动往往会引起电路不可预知的错误。

 功能:将带有抖动的信号进行识别和判断,输出持续时间超过0.1s的高电平信号。

 图5 防抖动模块的输入和输出

 ⑶交通灯控制模块

 设计原因:这个模块是本程序设计的灵魂,是重中之重!这个模块用于控制电路的状态改变和按键响应,也就是系统中控制器的作用。

 功能:根据按键信号和输入时钟,输出符合交通灯状态变化规律的LED驱动信号、数码管显示的数据、数码管位选信号。

 图6 交通灯控制模块的输入和输出

 ⑷数字译码模块

 设计原因:由于交通灯控制模块输出的为数码管显示的数据,为10进制数,因此必须要一个译码电路,将此十进制数转化为LED灯的驱动信号,而这个功能正是由此模块完成。

 功能:将输入的十进制数转变为相应的8位2二进制数作为数码管的驱动信号。

 图7 数字译码模块的输入和输出

 ⑸整体模块连接图

 图8 模块整体连接图

 4.系统框图

 图9 系统框图

 四、程序代码

 ⒈主程序

 主程序

 library ieee;

 use ieee.std_logic_1164.all;

 entity traffic_lights is

  port(clk:in std_logic; 时钟信号

  emerg,reset:in std_logic; 复位和紧急情况信号

  seg:out std_logic_vector(7 downto 0); 7段数码管显示

  select_led:out std_logic_vector(5 downto 0); 选通输出

  lights:out std_logic_vector(7 downto 0));led发光管输出

 end traffic_lights;

 architecture a of traffic_lights is 分别调用各个模块

  signal cp1k,cp20,cp1,resetout,emergout:std_logic;

  signal number:integer range 0 to 9;

 component freq_divide 分频模块 1k 100hz 1hz

  port(clk_in:in std_logic;

  clk_1,clk_20,clk_1k:out std_logic);

 end component;

 component noshake 分频模块 1k 100hz 1hz

  port(clk_20,keyin:in std_logic;

  keyout:out std_logic);

 end component;

 component traffic 交通灯控制模块

  port(clk1,clk1k:in std_logic;

  emerg,reset:in std_logic;

  num:out integer range 0 to 9;

  lights:out std_logic_vector(7 downto 0);

  select_led:out std_logic_vector(5 downto 0));

 end component;

 component display 数字译码模块

  port(num:in integer range 0 to 9;

  seg:out std_logic_vector(7 downto 0));

 end component;

 begin

  u1:freq_divide port map(clk,cp1,cp20,cp1k); 分频器产生时钟信号

  u2:noshake port map(cp20,reset,resetout); 对复位信号防抖处理

  u3:noshake port map(cp20,emerg,emergout); 对紧急信号防抖处理

  u4:traffic port map(cp1,cp1k,emergout,resetout,number,lights,select_led); 状态机运转

  u5:display port map(number,seg); 数码管显示

 end;

 ⒉分频模块

 分频模块

 library ieee;

 use ieee.std_logic_1164.all;

 use ieee.std_logic_unsigned.all;

 entity freq_divide is

  port(clk_in : in std_logic;

  clk_1,clk_20,clk_1k : out std_logic);

 end;

 architecture a of freq_divide is

  signal count1 : integer range 0 to 24999;

  signal count2 : integer range 0 to 24;

  signal count3 : integer range 0 to 9;

  signal clk_tmp1,clk_tmp2,clk_tmp3: std_logic;

 begin

 50000分频进程

 输出:1kHz的时钟信号

 功能:用于数码管显示时刷新频率

  p1:process(clk_in)

  begin

  if (clk_in'event and clk_in='1') then

  if count1=24999 then

  count1<=0;

  clk_tmp1<= not clk_tmp1;

  else

  count1<=count1+1;

  end if;

  end if;

  end process p1;

 50分频进程

 输出:20Hz的时钟信号

 功能:防抖动电路中使用

  p2:process(clk_tmp1)

  begin

  if (clk_tmp1'event and clk_tmp1='1') then

  if count2=24 then

  count2<=0;

  clk_tmp2<= not clk_tmp2;

  else

  count2<=count2+1;

  end if;

  end if;

  end process p2;

 20分频进程

 输出:1Hz的时钟信号

 用于状态转变的时钟信号

  p3:process(clk_tmp2)

  begin

  if (clk_tmp2'event and clk_tmp2='1') then

  if count3=9 then

  count3<=0;

  clk_tmp3<= not clk_tmp3;

  else

  count3<=count3+1;

  end if;

  end if;

  end process p3;

 

  clk_1<=clk_tmp3;

  clk_20<=clk_tmp2;

  clk_1k<=clk_tmp1;

 

 end;

 ⒊防抖模块

 防抖动模块

 library ieee;

 use ieee.std_logic_1164.all;

 use ieee.std_logic_unsigned.all;

 entity noshake is

  port(clk_20,keyin: in std_logic;

  keyout: out std_logic);

 end;

 architecture a of noshake is

  signal cp:std_logic;

 begin

 只有持续时间高于0.1s的高电平才有效

  process(clk_20)

  variable times:integer range 0 to 2;

  begin

  if (clk_20'event and clk_20='1') then

  if keyin='1' then

  if times=2 then

  times:=times;

  else times:=times+1;

  end if;

  else times:=0;

  end if;

  end if;

  if times=2 then

  cp<='1';

  else cp<='0';

  end if;

  keyout<=cp;

  end process;

 end;

 ⒋交通灯控制模块

 交通灯控制模块

 library ieee;

 use ieee.std_logic_1164.all;

 use ieee.std_logic_unsigned.all;

 entity traffic is

  port(clk1,clk1k:in std_logic;

  emerg,reset:in std_logic;

  num:out integer range 0 to 9;

  lights:out std_logic_vector(7 downto 0);

  select_led:out std_logic_vector(5 downto 0));

 end traffic;

 architecture control of traffic is

  type states is(s0,s1,s2,s3,s4);

  signal state:states;

  signal num1,num2,num3,num4:integer range 0 to 9;

  signal emerg_status,reset_status:std_logic:='0';

  signal count:integer range 1 to 50 :=50;

 begin

 紧急信号的处理进程

  p1:process(emerg)

  begin

  emerg_status<=emerg;

  end process p1;

 

 复位信号处理及计数器count控制进程

  p2:process(reset)

  begin

  reset_status<=reset;

  end process p2;

  p3:process(clk1)

  begin

  if(reset_status='1') then

  count<=50;

  elsif(emerg_status='1') then

  count<=count;

  else

  if(clk1'event and clk1='1') then

  if count=1 then

  count<=50;

  else count<=count-1;

  end if;

  end if;

  end if;

  end process;

 核心状态机

  p4:process(emerg_status,count)根据计数器来选择交通灯状态

  begin

  if(emerg_status='1')then state<=s0; 6个正常状态和1个紧急情况状态

  else

  if(count>=31)then state<=s1;

  elsif(count<=30 and count>=26)then state<=s2;

  elsif(count<=25 and count>=6)then state<=s3;

  else state<=s4;

  end if;

  end if;

  case state is 交通灯状态,用LED发光管模拟交通灯

  when s0=>lights<=; --;RA/RB

  when s1=>lights<=; --;GA/RB

  when s2=>lights<=; --;YA/RB

  when s3=>lights<=; --;RA/GB

  when s4=>lights<=; --;RA/YB

  end case;

  end process;

 

 根据计数器值确定数码管显示数字

  p5:process(emerg_status,count)

  begin

  if(emerg_status='1') 紧急状态下数码管显示8

  then num1<=8;num2<=8;num3<=8;num4<=8;

  else

 

  状态S1

  if(count=50)

  then num1<=2;num2<=0;num3<=2;num4<=5;

  elsif(count>=45 and count<50)

  then num1<=1;num2<=count-40;num3<=2;num4<=count-45;

  elsif(count>=40 and count<=44)

  then num1<=1;num2<=count-40;num3<=1;num4<=count-35;

  elsif(count>=35 and count<=39)

  then num1<=0;num2<=count-30;num3<=1;num4<=count-35;

  elsif(count>=31 and count<=34)

  then num1<=0;num2<=count-30;num3<=0;num4<=count-25;

  状态S2

  elsif(count>=26 and count<=30)

  then num1<=0;num2<=count-25;num3<=0;num4<=count-25;

  状态S3

  elsif(count=25)

  then num1<=2;num2<=5;num3<=2;num4<=0;

  elsif(count>=20 and count<=24)

  then num1<=2;num2<=count-20;num3<=1;num4<=count-15;

  elsif(count>=15 and count<=19)

  then num1<=1;num2<=count-10;num3<=1;num4<=count-15;

  elsif(count>=14 and count<=10)

  then num1<=1;num2<=count-10;num3<=0;num4<=count-5;

  状态S4

  elsif(count>=6 and count<=9)

  then num1<=1;num2<=count;num3<=0;num4<=count-5;

  else num1<=0;num2<=count;num3<=0;num4<=count;

  end if;

  end if;

  end process;

 

 数码管选通信号输出

  p6:process(clk1k)

  variable temp:integer range 0 to 3;

  begin

  if(clk1k'event and clk1k='1')then

  case temp is

  when 0=>num<=num1;temp:=1;select_led<="011111"; 选用4个数码管输出倒计时

  when 1=>num<=num2;temp:=2;select_led<="101111";

  when 2=>num<=num3;temp:=3;select_led<="111101";

  when 3=>num<=num4;temp:=0;select_led<="111110";

  end case;

  end if;

  end process;

 end;

 ⒌数字译码模块

 数字译码模块

 library ieee;

 use ieee.std_logic_1164.all;

 entity display is

  port(num:in integer range 0 to 9;

  seg:out std_logic_vector(7 downto 0));

 end;

 architecture a of display is

 begin

 d1:process(num)

  begin

  case num is

  when 0=>seg<=; 由七位二进制数表示0到9

  when 1=>seg<=;

  when 2=>seg<=;

  when 3=>seg<=;

  when 4=>seg<=;

  when 5=>seg<=;

  when 6=>seg<=;

  when 7=>seg<=;

  when 8=>seg<=;

  when 9=>seg<=;

  when others=>seg<="XXXXXXXX";

  end case;

  end process;

 end;

 五、实验结果

 1.仿真结果

 ⑴仿真说明

 由于分频模块的存在,导致无法整体仿真(可能可以,但是很费时间)。因此,只对核心模块——交通灯控制模块进行仿真。

 为了结果的易读性,现将程序做如下修改。

 ①LED灯的驱动信号lights的修改:

 when s0=>lights<=; --;RA/RB

 when s1=>lights<=; --;GA/RB

 when s2=>lights<=; --;YA/RB

 when s3=>lights<=; --;RA/GB

 when s4=>lights<=; --;RA/YB

 即从S0~S4,相应的lights信号从0~4改变。

 ②数码管位选信号select_led的修改:

 when 0=>num<=num1;temp:=1;select_led<="000000";

 when 1=>num<=num2;temp:=2;select_led<="000001";

 when 2=>num<=num3;temp:=3;select_led<="000010";

 when 3=>num<=num4;temp:=0;select_led<="000011";

 即数码管位选信号循环输出0~3。

 ③输入信号:1Hz和1kHz的时钟信号,仿真时间为110s。

 ⑵仿真波形图

 ①正常状况下

 reset和emerg都为低电平。

 图10 正常状态下的仿真波形

 图11 续图10

 由上两图可见,正常情况下,状态转移完全符合设计要求:,如此循环往复。

 num信号和select_led信号(局部)

 图12 正常运行下的的仿真波形

 数码管显示数字和数码管位选信号也都正常输出。

 ②复位信号响应

 reset信号

 reset信号

 图13 复位情况下的仿真波形

 由上面仿真波形中可见,当reset为高电平时,在时钟沿上状态改变为S1,即复位成功。

 ③紧急信号响应

 紧急信号

 紧急信号

 图14 紧急情况下的仿真波形

 由图14可见,在emerg信号有效时,交通灯状态一直处于S0,一旦emerg信号失效,状态立马恢复到原来(emerg信号之前的状态)。总之,紧急状况处理成功!

 2.实物结果

 总体来说,实验要求的基本功能全部完成,且没有bug。交通灯运行完全符合前面分析的要求。

 六、所遇问题分析

 问题1:状态改变的参考量的确定。

 解决方案:当初设计时,丝毫没有头绪。当参考了以前同学的程序后,心中不由豁然开朗——使用计数器count的值来控制状态改变和数码管显示数字。这个想法确实很巧妙,做到了一个count解决所有控制问题。这样的设计,大大减小了程序的复杂度。

 问题2:reset信号由拨码开关还是由按键来输入。

 解决方案:这点困扰了我好久。最后考虑到如果使用按键输入时,一来与实际情况不符,二来为程序编写增加了难度。难度引入主要是由于按键检测的时钟和按键状态检测的时间,都很难确定,无论使用分频器产生的何种时钟信号都无法满足要求。最后采用拨码开关直接输入,使程序大为简便,也使这一问题得到圆满的解决。

 七、实验总结

 这次实验中,虽然在编程中遇到了不少困难,但是最终还是按时完成实验,确实令人信心倍增啊。

 首先,在实验题目选定之后,对于题目的切入点一直找不到,不知如何下手。于是就在老师的课件中找灵感,万幸的是我竟然找见了!在老师课件中的一些示例中,我慢慢摸索和品味其中的要义,认真思考硬件编程的特点,并在网上查找资料,并重新拜读了去年发的那本《数字电路实验讲义》,从中得到不少启迪。终于在第二次上课前完成了程序原理和状态分析等任务。

 然后,就开始编程了。最先编写的是分频模块——按照数字电路网站上的那个50M分频器的方法,编写出了实验要求的分频模块。接下来就是编写程序的主模块——交通灯控制模块。这个模块的编写借鉴了以前同学的设计思路,因此编写的头绪时很清晰的。最后编写了防抖模块和数字译码模块。这个过程中,始终伴随我的就是编译时的各种warning和error。但是我没有泄气。要知道——兵来将挡,水来土掩;凡事皆有因。有错误,就一句一句排错,最后整体进行逻辑检测。终于在最后一个没有warning和error的程序编写完毕。

 接下来就是仿真和下载。但是在仿真中,发现原先编写的程序有很大的逻辑错误。于是反复修改,反复阅读程序,查找病因。果然是“苦心人,天不负”,终于在最后,一个仿真正常、运行正常的程序编写成功。此时的喜悦真是无以言表。

 在以上过程中,对于硬件编程的理解日渐深刻。这是我使我在平常的软件编写的惯性中,不由停下脚步,慢慢体会硬件编程的思想和技巧。

 数字电路综合实验虽然结束了,但是在实验中学到的知识将使我收益一生。在此,感谢那些“诲人不倦”的老师和同学!

相关热词搜索: 交通灯 控制器 北邮 数字电路 实验