Categories
开发

交通灯控制器的设计——竞赛整理(二)

由于是直接从word中复制过来的,图片无法导入,如果想查看全文,请点击这里下载PDF文档。

关键词
交通信号系统、VHDL语言、ispLEVER、Lattice、ispLSI1032E

题目要求
1. 路型:十字交叉
2. 相变周期:30s
3. 绿闪时间:5s
4. 黄灯时间:2s
5. 绿信比:1:2
6. 定时输入:256Hz TTL
7. 两位数码倒计时
8. 强制放行按钮:东西、南北方向(任意按钮解除)

摘要
 本设计的红绿交通灯信号系统为模拟实际的十字路口交通信号灯。故外部硬件电路方面包括:两组红绿灯、两组七段显示器、一组手动与自动控制开关。软件方面:将红绿灯交通信号系统划分成若干个子电路,赋予VHDL程序代码实现,将各个小电路相连接。交通灯系统可以调整红绿灯电路的强制通行和复位,以增加灵活性。

一、设计状态转移图及软件模块图
1、绘制软件模块图
2、利用状态机绘制状态转移图

二、交通信号系统VHDL模块
 该系统由四个子电路构成(如图):
 
(1) clk_gen 时钟脉冲发生电路(即分频电路)
(2) count_down 倒计时控制电路
(3) traffic_mux 计数秒数选择电路
(4) traffic_fsm 红绿信号灯控制电路

1、 clk_gen 时钟脉冲发生电路
    在红绿交通信号系统中,大多数的情况是通过自动控制的方式指挥交通的。此,为了避免意外事件的发牛,电路必须给一个稳定的时钟才能让系统正常运作。但为了配合高峰时段,防止交通拥挤。有时也必须使用手动控制,即让交警能够顺利指挥交通。clk_gen电路路最主要的功能就是产生—些额外的输出信号,井将其用做后续几个电路的使能控制与同步信号处理。

clk_gen时钟脉冲发生电路VHDL程序:
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity clk_gen is
 port( reset: in std_logic;
  clk: in std_logic;
  ena_two: in std_logic;
  ena_scan: out std_logic;
  ena_1hz: out std_logic;
  flash_1hz: out std_logic);
end;
architecture behavior of clk_gen is
constant scan_bit: positive :=2;
constant scan_val: positive :=4;
constant two_hz_bit: positive :=7;
constant two_hz_val: positive :=125;
signal clk_scan_ff: std_logic_vector(scan_bit-1 downto 0);
signal clk_2hz_ff: std_logic_vector(two_hz_bit-1 downto 0);
signal ena_s: std_logic;
signal ena_one: std_logic;
signal ena_two: std_logic;
begin
scan:process(reset,clk)
 begin
  if reset='1' then
   clk_scan_ff<="00";
   ena_s<='0';
  elsif (clk'event and clk='1') then
   if clk_scan_ff>=scan_val-1 then
    clk_scan_ff<="00";
    ena_s<='1';
   else
    clk_scan_ff<=clk_scan_ff+1;
    ena_s<='0';
   end if;
  end if;
 end process;
 ena_scan<=ena_s;
two_hz:process(reset,clk,ena_s)
 begin
  if reset='1' then
   ena_one<='0';
   ena_two<='0';
   clk_2hz_ff<="0000000";
  elsif (clk'event and clk='1') then
   if ena_s='1' then
    if clk_2hz_ff>=two_hz_val-1 then
     clk_2hz_ff<="0000000";
     ena_two<='1';
     ena_one<=not ena_one;
    else
     clk_2hz_ff<=clk_2hz_ff+1;
     ena_two<='0';
     ena_one<=ena_one;
    end if;
   end if;
  end if;
 end process;
 ena_1hz<=ena_one and ena_two and ena_s;
 flash_1hz<=ena_one;
end behavior;
 

模块波形仿真:

2、count_down 倒计时控制电路
当过马路的时候,绿灯的一方有时会附加—个显示器告诉行人,日前还剩下几秒信号灯将变红。因此,count_down 电路最主要的功能就是负责接收traffic_mux电路输出的倒计时秒数值,然后将其转换成BCD码,利用七显示管显示.让行人能清楚知道再过多久就会变成红灯。

count_down 倒计时控制电路VHDL程序:
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity count_down is
port( reset: in std_logic;
 clk: in std_logic;
 ena_1hz: in std_logic;
 recount: in std_logic;
 load: in std_logic_vector(7 downto 0);
 seg7: out std_logic_vector(15 downto 0);
 next_state: out std_logic);
end;
architecture count_down of count_down is
signal cnt_ff: std_logic_vector(7 downto 0);
begin
count:process(clk,reset)
 begin
  if (reset='1') then
   cnt_ff<="00000000";
   seg7<="0000000000000000";
  elsif (clk'event and clk='1') then
   if ena_1hz='1' then
    if (recount='1') then
     cnt_ff<=load-1;
    else
     cnt_ff<=cnt_ff-1;
    end if;
   end if;
   case conv_integer(cnt_ff) is
    when 0=>seg7(15 downto 0)<="0011111100111111";
    when 1=>seg7(15 downto 0)<="0011111100000110";
    when 2=>seg7(15 downto 0)<="0011111101011011";
    when 3=>seg7(15 downto 0)<="0011111101001111";
    when 4=>seg7(15 downto 0)<="0011111101100110";
    when 5=>seg7(15 downto 0)<="0011111101101101";
    when 6=>seg7(15 downto 0)<="0011111101111101";
    when 7=>seg7(15 downto 0)<="0011111100000111";
    when 8=>seg7(15 downto 0)<="0011111101111111";
    when 9=>seg7(15 downto 0)<="0011111101111011";
    when 10=>seg7(15 downto 0)<="0000011000111111";
    when 11=>seg7(15 downto 0)<="0000011001011011";
    when 12=>seg7(15 downto 0)<="0000011001011011";
    when 13=>seg7(15 downto 0)<="0000011001001111";
    when 14=>seg7(15 downto 0)<="0000011001100110";
    when 15=>seg7(15 downto 0)<="0000011001101101";
    when 16=>seg7(15 downto 0)<="0000011001111101";
    when 17=>seg7(15 downto 0)<="0000011000000111";
    when 18=>seg7(15 downto 0)<="0000011001111111";
    when 19=>seg7(15 downto 0)<="0000011001111011";
    when 20=>seg7(15 downto 0)<="0101101100111111";
    when 21=>seg7(15 downto 0)<="0101101100000110";
    when 22=>seg7(15 downto 0)<="0101101101011011";
    when 23=>seg7(15 downto 0)<="0101101101001111";
    when 24=>seg7(15 downto 0)<="0101101101100110";
    when 25=>seg7(15 downto 0)<="0101101101101101";
    when 26=>seg7(15 downto 0)<="0101101101111101";
    when 27=>seg7(15 downto 0)<="0101101100000111";
    when 28=>seg7(15 downto 0)<="0101101101111111";
    when 29=>seg7(15 downto 0)<="0101101101111011";
    when others=>seg7(15 downto 0)<="0011111100111111";
   end case;
  end if;
 end process;
 next_state<='1' when cnt_ff=1 else '0';
end count_down;
 

模块波形仿真:

3、traffic_mux 计数秒数选择电路
traffic_mux电路最主要的功能就是负责输出显示器需要的倒数秒数值,作为倒数显示器电路的计数秒数。

traffic_mux 计数秒数选择电路VHDL程序:
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity traffic_mux is
 port( reset: in std_logic;
  clk: in std_logic;
  ena_scan: in std_logic;
  recount: in std_logic;
  sign_state: in std_logic_vector(1 downto 0);
  load: out std_logic_vector(7 downto 0));
end;

–define the signal_structure and flow of the device
architecture behavior of traffic_mux is
constant yellow0_time: integer:=5;
constant green0_time: integer:=20;
constant yellow1_time: integer:=5;
constant green1_time: integer:=20;
begin

–to generate a value of counter by load
load_time:process(reset,clk)
 begin
  if reset='1' then
   load<="00000000";
  elsif (clk'event and clk='1') then
   if (ena_scan='1' and recount='1') then
    case sign_state is
     when "00"=>
      load<=conv_std_logic_vector(green1_time,8);
     when "01"=>
      load<=conv_std_logic_vector(yellow0_time,8);
     when "10"=>
      load<=conv_std_logic_vector(green0_time,8);
     when others=>
      load<=conv_std_logic_vector(yellow1_time,8);
    end case;
   end if;
  end if;
 end process;
end behavior;
 

模块波形仿真:

4、traffic_fsm 红绿信号灯控制电路
 在红绿灯交通系统中,大多数的情况是通过自动控制的方式指挥交通的。但为了配合高峰时段,防止交通拥挤,有时还必须使用手动控制,即交警自行指挥交通。因此,traffic_fsm电路除了负责监控路口红绿灯之外,主要的功能就是能够利用开关来切换手动与自动的模式,让交警能够通过外部输入的方式来控制红绿灯交通型号系统的运作。
假如是由于电器效应引起开关误动作,开关抖动的速度是非常快的,故电路可能会产生误动作,本程序的debounce段代码就是为了达到这种抖动消除装置的目的。

traffic_fsm 红绿信号灯控制电路VHDL程序:
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity traffic_fsm is
port( reset: in std_logic;
 clk: in std_logic;
 ena_scan: in std_logic;
 ena_1hz: in std_logic;
 flash_1hz: in std_logic;
 a_m: in std_logic;
 st_butt: in std_logic;
 next_state: in std_logic;
 recount: out std_logic;
 sign_state: out std_logic_vector(1 downto 0);
 red: out std_logic_vector(1 downto 0);
 green: out std_logic_vector(1 downto 0);
 yellow: out std_logic_vector(1 downto 0));
end;
architecture traffic_fsm of traffic_fsm is
type sreg0_type is (r0g1, r0y1, g0r1, y0r1, y0y1, y0g1, g0y1, r0r1);
signal state: sreg0_type;
signal st_transfer: std_logic;
signal light: std_logic_vector(5 downto 0);
begin
debounce:process (reset,clk,ena_scan,st_butt)
 variable rebn_ff: std_logic_vector(5 downto 0);
 begin
  if (st_butt='1' or reset='1') then
   rebn_ff:="111111";
   st_transfer<='0';
  elsif (clk'event and clk='1') then
   if (ena_scan='1') then
    if (rebn_ff>=3) then
     rebn_ff:=rebn_ff-1;
     st_transfer<='0';
    elsif (rebn_ff=2) then
     rebn_ff:=rebn_ff-1;
     st_transfer<='1';
    else
     rebn_ff:=rebn_ff;
     st_transfer<='0';
    end if;
   end if;
  end if;
 end process;

fsm:process (clk,ena_1hz,reset)
 begin
  if(reset='1') then
   state<=r0g1;
   sign_state<="01";
   recount<='1';
  else
   if (clk'event and clk='1') then
    case state is
     when r0g1 =>
      if (a_m='1' and ena_1hz='1') then
       if (next_state='1') then
        recount<='1';
        state<=r0y1;
        sign_state<="01";
       else
        recount<='0';
        state<=r0g1;
       end if;
      elsif (a_m='0' and ena_scan='1') then
       if (st_transfer='0') then
        recount<='1';
        state<=r0g1;
       else
        recount<='1';
        state<=r0y1;
        sign_state<="01";
       end if;
      end if;
     when r0y1 =>
      if (a_m='1' and ena_1hz='1') then
       if (next_state='1') then
        recount<='1';
        state<=g0r1;
        sign_state<="10";
       else
        recount<='0';
        state<=r0y1;
       end if;
      elsif (a_m='0' and ena_scan='1') then
       if (st_transfer='0') then
        recount<='1';
        state<=r0y1;
       else
        recount<='1';
        state<=g0r1;
        sign_state<="10";
       end if;
      end if;
     when g0r1 =>
      if (a_m='1' and ena_1hz='1') then
       if (next_state='1') then
        recount<='1';
        state<=y0r1;
        sign_state<="11";
       else
        recount<='0';
        state<=g0r1;
       end if;
      elsif (a_m='0' and ena_scan='1') then
       if (st_transfer='0') then
        state<=g0r1;
       else
        recount<='1';
        state<=y0r1;
        sign_state<="11";
       end if;
      end if;
     when y0r1 =>
      if (a_m='1' and ena_1hz='1') then
       if (next_state='1') then
        recount<='1';
        state<=y0g1;
        sign_state<="00";
       else
        recount<='0';
        state<=y0r1;
       end if;
      elsif (a_m='0' and ena_scan='1') then
       if (st_transfer='0') then
        recount<='1';
        state<=y0r1;
       else
        recount<='1';
        state<=r0r1;
        sign_state<="00";
       end if;
      end if;
     when others =>
      state<=r0g1;
      recount<='0';
      sign_state<="00";
    end case;
   end if;
  end if;
 end process;
light<="010010" when (state=r0g1) else
 "011000" when (state=r0y1) else
 "100001" when (state=r0y1) else
 "100100" when (state=r0y1) else
 "110000";
red<=light(5 downto 4);
yellow<=light(3 downto 2) and (flash_1hz & flash_1hz);
green<=light(1 downto 0);
end traffic_fsm;

配合完整模块仿真:

三、完整软件波形仿真结果
1、clk_gen 时钟脉冲发生电路(即分频电路)
2、count_down 倒计时控制电路
3、traffic_mux 计数秒数选择电路
4、traffic_fsm 红绿信号灯控制电路
四、ispLS1032E芯片引脚图