案例十 交通灯 一、案例说明 1.设计一个十字路口的交通灯控制系统,用实验平台上的LED发光二极管显示车辆通过的方向(东西和南北各一组),用数码管显示该方向的剩余时间。要求:工作顺序为东西方向红灯亮45秒,前40秒南北方向绿灯亮,后5秒黄灯亮。然后南北方向红灯亮45秒,前40秒东西方向绿灯亮,后5秒黄灯亮。依次重复。有紧急事件时允许将某方向一直开绿灯或者开红灯,另外允许特定情况两方向均为红灯,车辆禁行,比如十字路口恶性交通事故时,东西,南北两个方向均有两位数码管适时显示该方向亮灯时间。 2.题目分析与整体构思 (1).该交通灯控制器应具备的功能 设东西和南北方向的车流量大致相同,因此红、黄、绿灯的时长也相同,定为红灯45sec,黄灯5sec,绿灯40sec,同时用数码管指示当前状态(红、黄、绿)剩余时间。另外,设计一个紧急状态,当紧急状态出现时,两个方向都禁止通行,指示红灯。紧急状态解除后,重新计数并指示时间。 (2).实现方案 从题目中计数值与交通灯的亮灭的关系如图(1)所示  二、硬件电路结构图
(1)分频器 分频器实现的是将高频时钟信号转换成底频的时钟信号,用于触发控制器、计数器和扫描显示电路。该分频器实现的是一千分频,将一千赫兹的时钟信号分频成一赫兹的时钟信号。  (2)控制器设计 控制器的作用是根据计数器的计数值控制发光二极管的亮、灭,以及输出倒计时数值给七段数码管的分位译码电路。此外,当检测到特殊情况(HOLD=‘1’)发生时,无条件点亮红灯的二极管。本控制器可以有两种设计方法,一种是利用时钟烟的下降沿读取前级计数器的计数值,然后作出反应;另一种则是将本模块设计成纯组合逻辑电路,不需要时钟驱动。这两种方法各有所长,必须根据所用器件的特性进行选择:比如有些FPGA有丰富的寄存器资源,而且可用与组合逻辑的资源则相对较少,那么使用第一种方法会比较节省资源;而有些CPLD的组合逻辑资源则比较多,用第二种方法可能更好。  (3)计数器设计 这里需要的计数器的计数范围为0-90。计到90后,下一个时钟沿回复到0,开始下一轮计数。此外,当检测到特殊情况(HOLD=‘1’)发生是,计数器暂停计数,而系统复位信号RESET则使计数器异步清零。 
(4)分位译码电路设计--1 因为控制器输出的到计时数值可能是1位或者2位十进制数,所以在七段数码管的译码电路前要加上分位电路(即将其分为2个1位的十进制数,如25分为2和5,7分为0和7)。 与控制器一样,分位电路同样可以由时钟驱动,也可以设计成纯组合逻辑电路。控制器中,引入了寄存器。为了让读者开拓眼界,分位电路就用组合逻辑电路实现。  (5)分位译码电路设计—2
(6)数码管驱动设计 串行连接,即每个数码管对应的引脚都接在一起(如每个数码管的a引脚都接到一起,然后再接到CPLD/FPGA上的一个引脚上),通过控制公共端为高电平控制相应数码管的亮、灭(共阴极数码管的公共端为高电平时,LED不亮;共阳极的公共端为低电平时,LED不亮)。 串行法的优点在于消耗的系统资源少,占用的I/O口少,N个数码管只需要(7+N)个引脚(如果需要小数点,则是(8+N)个引脚)。其缺点是控制起来不如并行法容易。
(7)下图为交通灯控制器的顶层文件连接图
 三、软件设计 (1)分频器的设计
LIBRARY IEEE; USE IEEE.Std_Logic_1164.ALL;
ENTITY FreDevider IS PORT (Clkin:IN Std_Logic; Clkout:OUT Std_Logic); END;
ARCHITECTURE Devider OF FreDevider IS CONSTANT N:Integer:=499; signal counter:Integer range 0 to N; signal Clk:Std_Logic; BEGIN PROCESS(Clkin) begin IF rising_edge(Clkin)THEN IF Counter=N then counter<=0; Clk<=not clk; else counter<=counter+1; end if; end if; end process; clkout<=clk; end;
(2)控制设计 控制器的作用是根据计数器的计数值控制发光二极管的亮、灭,以及输出倒计时数值给七段译管的分译码电路。此外,当检测到特殊情况(Hold=‘1’)发生时,无条件点亮红色的发光二极管。 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY countroller IS PORT (Clock:IN STD_LOGIC; Hold:in std_logic; CountNum:in INTEGER RANGE 0 TO 89; NumA,NumB:out INTEGER RANGE 0 TO 45; RedA,GreenA,YellowA:out std_logic; RedB,GreenB,YellowB:out std_logic); END; ARCHITECTURE behavior OF Countroller IS BEGIN process(Clock) BEGIN IF falling_edge(Clock)THEN IF Hold='1' THEN RedA<='1'; RedB<='1'; GreenA<='0'; GreenA<='0'; YellowA<='0'; YellowB<='0'; ELSIF CountNum<=39 THEN NumA<=40-CountNum; RedA<='0'; GreenA<='1'; YellowA<='0'; ELSIF CountNum<=44 THEN NumA<=45-CountNum; RedA<='0'; GreenA<='0'; YellowA<='1'; ELSE NumA<=90-CountNum; RedA<='1'; GreenA<='0'; YellowA<='0'; END IF;
IF CountNum<=44 THEN NumB<=45-CountNum; RedB<='1'; GreenB<='0'; YellowB<='0'; ELSIF CountNum<=84 THEN NumB<=85-CountNum; RedB<='0'; GreenB<='1'; YellowB<='0'; ELSe NumB<=90-CountNum; RedB<='0'; GreenB<='0'; YellowB<='1'; END IF; END IF; END PROCESS; END;
(3)计数器的设计 这里计数器的计数范围为0—45S 。计到45后,下一个时钟沿回复到0,开始下一轮计数.此外,当检测到特殊情况(Hold=‘1‘)发生时,计数器暂停计数,而系统复位号Reset则使计数器异步清0。 程序如下:
LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY counter IS PORT (clock:IN STD_LOGIC; reset:in std_logic; Hold:in std_logic; countNum:BuFFeR INTEGER RANGE 0 TO 90); END; ARCHITECTURE behavior OF counter IS BEGIN process(reset,Clock) BEGIN IF Reset='1' THEN countNum<=0; ELSIF rising_edge(Clock) THEN IF Hold='1' then countNum<=countNum; ELSE IF countNum=90 THEN countNum<=0; ELSE countNum<=countNum+1; END IF; END IF; END IF; END PROCESS; END;
(4)分位译码电路设计--1 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY Fenwei IS PORT (Numin:IN integer RANGE 0 TO 45; NumA,NumB:OUT Integer RANGE 0 to 9 ); END; ARCHITECTURE behavior OF Fenwei IS BEGIN process(Numin) BEGIN IF Numin>=40 THEN NumA<=4; NumB<=Numin-40; ELSIF Numin>=30 THEN NumA<=3; NumB<=Numin-30; ELSIF Numin>=20 THEN NumA<=2; NumB<=Numin-20; ELSIF Numin>=10 THEN NumA<=1; NumB<=Numin-10; ELSE NumA<=0; NumB<=Numin; END IF; END PROCESS; END;
(5)分位译码电路设计—2 USE IEEE.STD_LOGIC_1164.ALL; ENTITY Fenwei2 IS PORT (Numin:IN integer RANGE 0 TO 45; NumC,NumD:OUT Integer RANGE 0 to 9 ); END; ARCHITECTURE behavior OF Fenwei2 IS BEGIN process(Numin) BEGIN IF Numin>=40 THEN NumC<=4; NumD<=Numin-40; ELSIF Numin>=30 THEN NumC<=3; NumD<=Numin-30; ELSIF Numin>=20 THEN NumC<=2; NumD<=Numin-20; ELSIF Numin>=10 THEN NumC<=1; NumD<=Numin-10; ELSE NumC<=0; NumD<=Numin; END IF; END PROCESS; END;
(6)数码管驱动设计 LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY bcd_data IS PORT (bcd_data:in STD_LOGIC_VECTOR(3 downto 0); segout: out STD_LOGIC_VECTOR(6 downto 0) ); END; ARCHITECTURE behavior OF bcd_data IS BEGIN process(bcd_data) BEGIN case bcd_data is when "0000"=>segout<="1111110"; when "0001"=>segout<="0110000"; when "0010"=>segout<="1101101"; when "0011" =>segout<="1111001" ; when "0100" =>segout<="0110011" ; when "0101"=>segout<="1011011" ; when "0110"=>segout<="0011111" ; when "0111"=>segout<="1110000" ; when "1000" =>segout<="1111111" ; when "1001" =>segout<="1110011"; when others =>null; END CASE; END PROCESS; END; LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_unsigned.ALL; ENTITY dtsm IS PORT(clk:in STD_LOGIC; NumA,NumB,NumC,NumD: in STD_LOGIC_VECTOR(3 downto 0); segout1:out STD_LOGIC_VECTOR(6 downto 0); led_sel: out STD_LOGIC_VECTOR(3 downto 0)); END dtsm; architecture bhv of dtsm is component bcd_data is port (bcd_data:in STD_LOGIC_VECTOR(3 downto 0); segout:out STD_LOGIC_VECTOR(6 downto 0)); end component; signal x:STD_LOGIC_VECTOR(3 downto 0); signal q:STD_LOGIC_VECTOR(1 downto 0); begin p1:process(clk) begin if clk'event and clk ='1' then Q<= Q + '1'; end if; end process;
p2:process(Q) begin case Q is when"00"=>led_sel<="1110";x<=NumD; when"01"=>led_sel<="1101";x<=NumC; when"10"=>led_sel<="1011";x<=NumB; when"11"=>led_sel<="0111";x<=NumA; when others=>null; end case; end process; u1:bcd_data PORT map(bcd_data=>x,segout=>segout1); end
四﹑设计创新 1.模块化编程,模块化接线,再编译总原理图,思路比较清楚解容易。 2.可以比较容易的改变红绿灯的时间。 3.有的模块可以供其它任务通用。
|