资源描述
一、设计任务要求
交通灯控制器:用于十字路口的交通灯控制器.
实验要求:
1. 东西方向各有一组红,黄,绿灯用于指挥交通,红,黄,绿的持续时间分别为25s,5s,20s。
2. 当有紧急情况(如消防车)时,两个方向均为红灯亮,计时停止,当特殊情况结束后,控制器恢复原来状态,正常工作。
3. 组数码管,以倒计时方式显示两个方向允许通行或禁止通行的时间.
二、设计思路及总体结构框图
设计思路:
1.硬件:由设计任务要求可知,总体输入电路有:
(1)在开始计时之前的等待状态,复位键reset接低电位,接通电源后,首先要将它接高电位,表示计时开始。
(2)当按一下(on_off)键,表示紧急情况发生,两个方向均为红灯亮,计时停止,当再次按下(on_off)键时,控制器恢复原来状态,正常工作。
输出电路:
(1)由于东西和南北方向都要显示时间,因此需要4个数码管,这样在设计中就需要四条输出线choose4,用来选通指定一个LED七段显示数码管。
(2)显示器的每一位都采用LED七段显示数码管进行显示,每一个LED七段显示数码管都要有七条输出线控制,一共使用4个七段数码管,故输出电路使用四个七位输出信号:showtime1,showtime2,showtime3,showtime4。
(3)东西和南北方向都有交通灯亮的情况,故输出电路中要有两个状态控制信号state1,state2分别控制东西和南北的灯,每个方向上有4个灯(增加了左、右转弯显示控制功能),所以state1,state2的类型应该是4位数组型的。
东西方向交通灯
外部电路图如下:
State1
State2
Showtime1
Showtime2
Showtime3
Showtime4
Choose4
clk 4/
stas
reset
南北方向交通灯
on_off 4/
7/
7/
7/
7/
4/
2.软件:
(1)在VHDL设计描述中,采用自顶向下的设计思路,该思路,首先要描述顶层的接口,上面的描述已经规定了交通灯控制的输入输出信号:
输入信号:复位开关信号reset;
紧急情况控制信号on_off;
外部时钟信号clk。
输出信号:LED七段显示数码管的选通信号choose4(3 downto 0);
LED七段显示数码管的输出信号showtime1(6 downto 0),showntime2(6 downto 0),showtime3(6 downto 0),showtome4(6 downto 0);
交通灯状态控制信号state1(3 downto 0),state2(3 downto 0)。
(2)在自顶向下的VHDL设计描述中,通常把整个设计的系统划分为几个模块,然后采用结构描述方式对整个系统进行描述。根据实验设计的结构功能,来确定使用哪些模块以及这些模块之间的关系。
由于紧急情况控制信号是采用按键的输入方式,其产生时刻和持续时间的长短是随机不定的,且存在因开关簧片反弹引起的电平抖动现象,因此必须在每个开关后面安排一个消抖和同步化电路模块,以保证系统能捕捉到输入脉冲,故需要有防抖动的模块.
由于外部时钟信号clk的频率为1MHz,而实际需要的内部计时时钟频率为1Hz,提供给消抖同步电路的频率为50Hz(满足按键)和提供给产生选通信号电路的时钟频率为200Hz(满足视觉暂留效应).
当正常计时开始后,需要进行定时计数操作,由于东西和南北两个方向上的时间显示器是由两个LED七段显示数码管组成的,因此需要产生两个2位的计时信息:2个十位信号,2个个位信号,这个定时计数操作可以由一个定时计数器来完成,又因为交通灯的状态变化是在计时为0的情况下才能进行的,因此需要一个计时电路来产生使能信号,因此定时计数的功能就是用来产生2个2位计时信息和使能信号。
另外还需要将时间显示出来,为了节省资源,我采用了循环点亮LED七段显示数码管的方法来显示计时输出。通过信号choose4(3 downto 0)来对4个LED七段显示数码管进行选择.
由于不能使用7448自动译码集成电路,故在LED七段显示数码管显示时间时,要把计时结果转换为七段码输出到相应的LED七段显示数码管上,因此还需要一个转换电路.
交通灯状态控制也需要一个电路,当有使能信号及无紧急情况下,交通灯状态不发生变化,有紧急情况时,两个方向上均为红灯亮,紧急情况消除后,回到原来状态,无使能信号时,交通灯状态不变。
通过上面的分析,不难得知可以把交通灯控制系统划分为6个模块:键输入模块,时钟分频模块,计时模块,选通模块,显示模块,控制模块.各个模块之间的连接关系如下:
计时模块
转换模块
键输入模块
reset showtime
on_off
reset0 on_off0
clk1
选通模块
时钟分频模块
选通模块
timel,times
clk2 clk0 choose4
三、总体结构框图
通电
复位
No
yes
东西为红,南北为绿,计时开始
是否有紧急情况
Yes
No
计时到20s
No
两方向均为红,计时停止
Yes
东西为黄,南北为绿
是否有紧急情况
是否消除?
No
Yes Yes
No
计时到5s
No
Yes
东西为红,南北为绿
是否有紧急情况
Yes
No
计时到20s
No
Yes
东西为红,南北为黄
是否有紧急情况
Yes
计时到5s
No
Yes
四、分块电路设计。
(1)键输入模块(keyin)
输入信号:紧急情况on_off;用来消除抖动的时钟信号clk1,由时钟分频模块提供。
输出信号:去抖后的提示信号on_off0。
(2)时钟分频模块(clk_div)
输入信号:外部时钟信号clk;
输出信号:消除抖动的时钟信号clk1;计时内部时钟信号clk2;产生选通信号的时钟信号clk0.
(3)计时模块(time):
输入信号:定时计时时钟clk2,由时钟分频模块提供;去抖动后的提示信号on_off0;复位信号reset;状态提示信号state(1 downto 0);
输出信号:东西方向的十位信号eq1(3 downto 0);东西方向的个位信号eq0(3 downto 0);南北方向的十位信号sq1(3 downto 0);南北方向的个位信号sq0(3 downto 0);使能信号timel,times.
(4)选通模块(choose):
输入信号:选通时钟信号clk0,由时钟分频模块提供。
输出信号:选通信号choose4(3 downto 0)。
(5)显示模块(display):
输入信号:计时的十位或个位信号;
输出信号:控制LED七段显示数码管的七位数组型信号.
(6)控制模块(keep):
输入信号:复位信号reset;去抖后的紧急情况提示信号on_off0;定时计时时钟信号clk2;使能信号timel,times;
输出信号:东西方向交通灯状态控制信号state1(3 downto 0);南北方向交通灯状态控制信号state2(3 downto 0);交通灯状态提示信号state(1 downto 0)。
五、总体电路图(图形法).
六、仿真波形
状态变化仿真图:以下显示选通信号的仿真波形
七、源程序
主模块:-—-———-—--traffic module——-—-—-——
library ieee;
use ieee。std_logic_1164。all;
use ieee。std_logic_arith。all;
use ieee。std_logic_unsigned.all;
entity tracfic is
port(reset : in std_logic;-—---——--—----—-—-—————复位信号
clk : in std_logic;—--——-—-——--——--—--——--外部时钟信号
showtime1,showtime2,showtime3,showtime4: out std_logic_vector(6 downto 0);--——-————-———---——-----—-— 控制LED七段显示数码管的七位数组型信号
choose4 : out std_logic_vector(3 downto 0);—--—-—--选通信号
on_off : in std_logic;—-———-—-——-—-——----—-———紧急情况控制信号
state1,state2 : out std_logic_vector(3 downto 0));--—交通灯状态控制信号
end tracfic;
architecture system of tracfic is——----———--—---——元件例化调用
component keyin--———-———————--—--———--————---——-去抖动模块
port(a,b:in std_logic;
c :out std_logic);
end component;
component time———————---———————-————--——-———-———-计时模块
port(a,b,k:in std_logic;
c:in std_logic_vector(1 downto 0);
d,e,f,g:out std_logic_vector(3 downto 0);
j,h:out std_logic);
end component;
component choose -—-—————-——-——————-—-——————-—--—选通模块
port(a:in std_logic;
b:out std_logic_vector(3 downto 0));
end component;
component display ————----————-——————————----————显示模块
port(a:in std_logic_vector(3 downto 0);
b:out std_logic_vector(6 downto 0));
end component;
component clk_div-—————-—-—--——————--——-—---—————时钟分频模块
port(a:in std_logic;
b,c,d:out std_logic);
end component;
component keep——-——-————-——--———-———-———--——-—-—-状态控制模块
port(a,b,c,g,j:in std_logic;
d,e:out std_logic_vector(3 downto 0);
f:out std_logic_vector(1 downto 0));
end component;
signal on_off0:std_logic; 紧急情况经去抖后的输出信号;
signal state:std_logic_vector(1 downto 0); 控制计数器的状态提示信号;
signal clk0,clk1,clk2:std_logic; 时钟分频后的输出信号;
signal eq0,sq0:std_logic_vector(3 downto 0); 南北和东西计数器的个位输出;
signal eq1,sq1:std_logic_vector(3 downto 0); 南北和东西计数器的十位输出;
signal timel,times:std_logic; 计数器对控制器的反馈信号;
begin 用信号把各个模块连起来;
u1:keyin port map(clk1,on_off,on_off0);
u3:time port map(clk2,on_off0,reset,state,eq0,eq1,sq0,sq1,timel,times);
u4:choose port map(clk0,choose4);
u5:display port map(eq0,showtime1);
u6:display port map(eq1,showtime2);
u7:display port map(sq0,showtime3);
u8:display port map(sq1,showtime4);
u9:keep port map(on_off0,timel,times,clk2,reset,state1,state2,state);
u10:clk_div port map(clk,clk0,clk1,clk2);
end system;
去抖模块:-——--———keyin module———-—
library ieee;
use ieee.std_logic_1164。all;
entity keyin is
port(A,B :in std_logic;
C :out std_logic);
end keyin;
architecture keyin_arc of keyin is
component kand2
port(A,B :in std_logic;
C :out std_logic);
end component;
component kdf
port(A,B :in std_logic;
C,D :out std_logic);
end component;
component knand2
port(A,B :in std_logic;
C :out std_logic);
end component;
signal TMP1,TMP2,TMP3,TMP4,TMP5,TMP6:std_logic;
begin
u0: knand2 port map(A,TMP1,TMP2);
u1: knand2 port map(TMP2,TMP3,TMP1);
U2: kdf port map(TMP2,B,TMP4,TMP3);
U3: kdf port map(TMP4,B,TMP6,TMP5);
u4: kand2 port map(TMP4,TMP5,C);
end keyin_arc;
library ieee;-—-two inputs and gate description
use ieee。std_logic_1164.all;
entity kand2 is
port(A,B :in std_logic;
C :out std_logic);
end kand2;
architecture kand2_arc of kand2 is
begin
C<=A and B;
end kand2_arc;—-—end of two inputs and gate description
library ieee;——-two inputs and_not gate description
use ieee.std_logic_1164。all;
entity knand2 is
port(A,B :in std_logic;
C :out std_logic);
end knand2;
architecture knand2_arc of knand2 is
begin
C〈=not(A and B);
end knand2_arc;-—-end of two inputs and_not gate description
library ieee;———D trigger description
use ieee。std_logic_1164.all;
entity kdf is
port(A,B :in std_logic;
C,D :out std_logic);
end kdf;
architecture kdf_arc of kdf is
begin
process(B)
begin
if(B'event and B='1’)then C〈=A;D<=not A;
end if;
end process;
end kdf_arc;
选通模块:该模块是为节省资源而设的,实验中有四个LED七段数码管显示计数,点亮一个LED需电流5-50mA,同时点亮4个LED,CPLD可能无法负荷这样的电流驱动,而且功率太大,散热也是问题。同时这么做也容易造成电路被烧毁,因此需要逐个循环点亮。又为使显示结果持续不致闪烁抖动,只需每个扫描频率超过人眼视觉暂留频率24Hz以上,就能达到。选择200Hz作为时钟,分到4个数码管,每个数码管50Hz(大于24Hz),故不会有闪烁.
library ieee;——-——-—choose module—-—-———--—
use ieee。std_logic_1164。all;
use ieee。std_logic_unsigned。all;
entity choose is
port(a:in std_logic;
b:out std_logic_vector(3 downto 0));
end choose;
architecture choose_arc of choose is
signal m :integer range 0 to 3;
begin
process(a)
begin
if(a’event and a='1')then
if(m=3)then m〈=0;
else m<=m+1;
end if;
end if;
case m is when 0 =>b〈="0111”;
when 1 =>b<=”1011”;
when 2 =>b〈=”1101";
when 3 =〉b<=”1110”;
end case;
end process;
end choose_arc;
分频模块:实验中需要三个不同频率的时钟:消抖电路需要10Hz的时钟,选通电路需要200Hz的时钟,计时需要1Hz的时钟。外部提供的时钟的频率为1MHz,故需要经过分频得到,但由于外部时钟的频率和我们所需要的时钟的频率相差太远,一次分频到底又占用太多的资源,所以我采用的是先对外部时钟进行一定的分频,再依次向下分,得到我们需要的时钟,这样可以节省很多资源。
library ieee;—-—-—clk_div module————-——
use ieee.std_logic_1164。all;
entity clk_div is
port(a:in std_logic;——————-————--———-—-—--—————-——外部时钟信号
b:out std_logic;—-—-——————-——————--—--—-———-—频率为200Hz的时钟信号
c:out std_logic;—----————-———-—--————-—-—————频率为10Hz的时钟信号
d:out std_logic);-—-—-—-———--———-—-————--—---频率为1Hz的时钟信号
end clk_div;
architecture clk_div_arc of clk_div is
signal clk_10k:std_logic;
signal clk_200:std_logic;
signal clk_10:std_logic;
signal clk_1:std_logic;
signal m:integer range 0 to 100;
signal n:integer range 0 to 50;
signal l:integer range 0 to 20;
signal g:integer range 0 to 10;
begin
p1: process(a)——————-————先对外部时钟进行100分频,得到频率为10KHz的时钟信号
begin
if(a'event and a=’1’)then
if m=99 then m〈=0;
else m〈=m+1;
end if;
if (m<=49) then clk_10k<=’0’;
else clk_10k〈='1’;
end if;
end if;
end process;
p2:process(clk_10k)——-——--对10KHz的时钟信号再进行50分频,得到200Hz的时钟信号
begin
if (clk_10k’event and clk_10k=’1')then
if n=49 then n〈=0;
else n〈=n+1;
end if;
if n<=24 then clk_200<=’0’;
else clk_200〈=’1’;
end if;
end if;
end process;
b<=clk_200;
p3:process(clk_200)---—对200Hz的时钟信号进行20分频,得到10Hz的时钟信号
begin
if(clk_200'event and clk_200=’1’)then
if l=19 then l〈=0;
else l〈=l+1;
end if;
if l<=9 then clk_10〈='0’;
else clk_10<=’1’;
end if;
end if;
end process;
c<=clk_10;
p4:process(clk_10)—-—-对10Hz的时钟信号进行10分频,得到需要的1 Hz的时钟信号
begin
if (clk_10’event and clk_10=’1’)then
if g=9 then g〈=0;
else g〈=g+1;
end if;
if g<=4 then clk_1〈=’0’;
else clk_1〈=’1’;
end if; end if ;
end process;
d〈=clk_1;
end clk_div_arc;
显示模块:——-—-—display module-—--—--—
library ieee;
use ieee。std_logic_1164.all;
use ieee。std_logic_signed.all;
use ieee。std_logic_unsigned。all;
entity display is
port(a:in std_logic_vector(3 downto 0);———--——---———输入记数结果
b:out std_logic_vector(6 downto 0));-————-—--译码成七段数码管的控制信号
end display;
architecture display_arc of display is
signal a0:std_logic_vector(3 downto 0);
begin
process(a0)
begin
a0〈=a;
case a0 is when ”0000" =〉b〈=”0111111";————---——以下是译码部分
when ”0001” =>b〈=”0000110”;
when ”0010” =〉b〈="1011011”;
when "0011” =>b〈="1001111”;
when ”0100" =>b〈="1100110”;
when "0101” =〉b〈=”1101101";
when "0110" =>b〈=”1111101”;
when "0111" =〉b<="0000111”;
when ”1000" =〉b<="1111111”;
when "1001” =〉b〈=”1101111";
when others=〉b<=”ZZZZZZZ";
end case;
end process;
end display_arc;
控制模块:—----—-——keep module--—-—-——-
library ieee;
use ieee。std_logic_1164.all;
entity keep is
port( a,b,c,g,j : in std_logic;
d,e : out std_logic_vector(3 downto 0);
f : out std_logic_vector(1 downto 0));
end keep;
architecture keep_arc of keep is
type state_type is (s0,s1,s2,s3,s4);
signal current_state:state_type;
signal new_state:state_type;
begin
newstate_logic:
process(current_state,b,a,g)
variable m:integer range 0 to 3;
begin
if(g=’0’)then new_state<=s1;——--———————-———-通电后给交通灯状态赋初值
else case current_state is
when s1 =〉m:=0;
if(b=’1'and j=’0'and a='0')then———当计数到20s且无紧急情况时,交通灯跳至下一状态
new_state〈=s2;
elsif(a='1’)thennew_state〈=s0;——-——有紧急情况时,交通灯变为紧急状态
elsenew_state〈=s1;--——---—--——--—-—-计时未到的时候保持原状态不变
end if;
when s2 =〉m:=1;
if(b='1’and j=’1'and a=’0')thennew_state〈=s3;———-—当记数到5s且无紧急情况时,交通灯变为下一状态
elsif(a='1')thennew_state〈=s0;—-—-—-有紧急情况时,交通灯变为紧急状态
else new_state<=s2; --—-—--—--计时未到的时候保持原状态不变
end if;
when s3 =〉m:=2;
if(j=’1'and b=’0’and a=’0')thennew_state〈=s4;-——---——-当记数到20s且无紧急情况时,交通灯变为下一状态
elsif(a=’1')thennew_state<=s0;————有紧急情况时,交通灯变为紧急状态
else new_state〈=s3; ——-——-—-——-————计时未到的时候保持原状态不变
end if;
when s4 =〉m:=3;
if(j=’1’and b=’1’and a='0’)thennew_state〈=s1;———-——————当记数到5s且无紧急情况时,交通灯变为下一状态
elsif(a=’1’)thennew_state〈=s0;—————有紧急情况时,交通灯变为紧急状态
else new_state〈=s4; ————-——---—————-计时未到的时候保持原状态不变
end if;
when s0=〉if(a=’0’)then——-——-—————-—紧急情况消除后,回到原来状态
case m iswhen 0 =〉new_state〈=s1;
when 1 =〉new_state〈=s2;
when 2 =〉new_state<=s3;
when 3 =〉new_state〈=s4;
end case;
else new_state〈=s0;
end if;
end case;
end if;
end process;
state_register:process(c)
begin
if(c’event and c='1')thencurrent_state〈=new_state;-——---—当时钟上升沿触发时,交通灯状态发生改变
end if;
end process;
output_logic:
process(current_state)——-——产生与交通灯状态相对应的提示信号,以控制计时模块的不同状态下的不同赋植
begin
case current_state iswhen s0 =〉 d<=”0100”;e〈="0100”;
when s1 =〉 d〈=”0100";e〈=”1001”;f〈=”00”;
when s2 =〉 d<=”0100”;e〈="0010";f<=”01”;
when s3 =〉 d〈="1001”;e〈=”0100”;f<=”10”;
when s4 =〉 d〈="0010”;e〈=”0100”;f〈="11”;
end case;
end process;
end keep_arc;
计时模块:—-—-——-time module—-——-—-
library ieee;
use ieee。std_logic_1164。all;
use ieee.std_logic_unsigned。all;
entity time is
port(a,b,k:in std_logic;
c :in std_logic_vector(1 downto 0);
d,e,f,g :out std_logic_vector(3 downto 0);
j,h :out std_logic);
end time;
architecture time_arc of time is
signal l,m,n,p:std_logic_vector(3 downto 0);
begin
process(a,b,k)
begin
if(k='0’)thenl<=”0101";m<="0010”;n〈="0000”;p<=”0010";————通电后赋初值
else if(a’event and a=’1’)then
if(b='1’)thenl<=l;m〈=m;n<=n;p〈=p;--—-—-—有紧急情况时,计时停止
else
if(n=”0001" and p=”0000”)thencase c is ——-—当东西方向倒计时到0时,重新赋值,并产生使能信号控制交通灯的状态
when ”00” =〉n〈="0101”;p〈=”0000”;j<=’1’;
when "01”=〉n<="0101”;p<="0010”;j<=’1’;
when "11”=〉n〈="0000”;p〈="0010";j<='1';
when "10”=〉n〈="0000”;p<="0010";j〈='1’;
when others =>null
展开阅读全文