⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vhdl交通灯1.txt

📁 基于有限状态机的VHDL交通灯程序
💻 TXT
字号:
基于VHDL语言的交通灯控制器设计2008年03月14日 星期五 19:08基于VHDL语言的交通灯控制器设计


【摘 要】以交通灯控制器设计为例, 系统地阐述了用FPGA/CPLD实现数字电路的设计过程, 展示了FPGA/CPLD的强大功能和非凡特性。
关键词: 数字系统,交通灯控制器,EDA,FPGA,CPLD,MAX_plus II
【Abstract 】Through analyzing the design process of TLC(Traffic Light Controller),this paper describes in detail the design process of implementing the digital circuit with FPGA/CPLD,and it shows the powerful function and excellent character of FPGA/CPLD. 
Keywords:digital system,EDA,FPGA/CPLD,MAX+plus II,traffic light controller(TLC)


引言
    自1987年VHDL(Very High Integrated Circuit Hardware Description Language 即超高速集成电路硬件描述语言),被定为IEEE标准IEEE-STD-1076以来,VHDL已被工业界广泛认可,并取得了巨大成功,成为数字系统设计和存档的重要工具,极大的提高了数字系统的设计水平和效率。而八十年代中期诞生的复杂可编程逻辑器件 CPLD 和现场可编程逻辑门阵列 FPGA 以其大大提高了处理速度,可重复编程,功能灵活,降低了初始设计费用等优点,使得它的应用越来越广泛,特别是在产品生产前期和小批量生产中由于成本比使用专用集成电路(ASIC)便宜,因而有着非常广泛的市场潜力。本设计正是基于VHDL语言全文本输入进行底层 CPLD开发。


设计要求

1、显示一个方向的绿、黄、红的指示状态。
2、特殊情况按键能实现特殊的功能,计数器停止计数并保持在原来的状态,显示红灯状态。 特殊状态解除后能继续计数.
3、复位按键实现总体计数清零功能。
4、实现正常的倒计时功能. 用数码管作为倒计时显示, 显示时间为绿灯17s,黄灯3s红灯20s。
|----------------->|--->|-------------------->|
|       绿灯       |黄灯|        红灯         |

设计思想

    首先由晶振产生出发信号,由控制器处理成1HZ的时钟,利用此时钟进行计数,通过判断计数的值来控制交通灯的亮灭。通过每种灯亮的时间总数与计数值比较得到数码管应该显示的数值,利用分位程序将其分成十位和个位。通过译码电路来实现数码管的显示。
    本实验所使用的芯片为EPM7128SLS84-6,实体逻辑单元为64点,结构体逻辑单元为128点,是一种小型芯片。

软件

    本实验使用MAX+plus II 10来进行程序的编写,编译,仿真以及下载。在实验中发现其功能虽然使用,但仍有地方需要改进,不支持MOD取余运算。
(源程序)
    *在MAX+plus II中,汉字很容易出现乱码,建议大家用英文,这里为了考虑到读者的习惯,因此在写论文时都译成中文
Library IEEE;
Use IEEE.std_logic_1164.all;

Entity redgreen is
Port
(
    clock_in:in std_logic;
    hold_state:in std_logic;
    reset_state:in std_logic;
    led_red,led_green,led_yellow:out std_logic;
    select_en:buffer std_logic;
    select_display:out std_logic_vector(0 to 6)
);
end;

Architecture half of redgreen is
constant loop_hz:integer:=800000; --根据晶振实际频率算出来
signal count_time:integer range 0 to loop_hz;
signal clock_buffer:std_logic;
signal clock_out:std_logic;
signal count_num:integer range 0 to 40;
signal display_num:integer range 0 to 20;
signal display_shi:integer range 0 to 9;
signal display_ge:integer range 0 to 9;

constant loop_time:integer:=40; --一个循环周期的时间
constant red_time:integer:=20; --红灯的时间
constant green_time:integer:=17; --绿灯的时间
constant yellow_time:integer:=3; --黄灯的时间
begin
    process(clock_in) --分频进程
    begin
        if rising_edge(clock_in) then
            if count_time=loop_hz then
                count_time<=0;
                clock_buffer<=not clock_buffer;
            else
                count_time<=count_time+1;
            end if;
        end if;
        clock_out<=clock_buffer; --输入1HZ的频率
    end process;

    process(reset_state,clock_out) --计数进程
    begin
        if reset_state=1 then --重启后计数归零
            count_num<=0;
        elsif rising_edge(clock_out) then
            if hold_state=1 then --紧急时计数占停
                count_num<=count_num;
            else
                if count_num=loop_time-1 then
                    count_num<=0;
                else
                    count_num<=count_num+1;
                end if;
            end if;
        end if;
    end process;

    process(clock_out) --交通灯显示
    begin
        if falling_edge(clock_in) then
            if hold_state=1 then --占停时红灯亮
                led_red<=1;
                led_green<=0;
                led_yellow<=0;
            else
                if count_num                    display_num<=green_time-count_num;
                    led_red<=0;
                    led_green<=1;
                    led_yellow<=0;
                elsif count_num                    display_num<=green_time+yellow_time-count_num;
                    led_red<=0;
                    led_green<=0;
                    led_yellow<=1;
                else
                    display_num<=loop_time-count_num;
                    led_red<=1;
                    led_green<=0;
                    led_yellow<=0;
                end if;
            end if;
        end if;
    end process;

    process(display_num) --分位进程
    begin
        if display_num>=20 then
            display_shi<=2;
            display_ge<=display_num-20;
        elsif display_num>=10 then
            display_shi<=1;
            display_ge<=display_num-10;
        else
            display_shi<=0;
            display_ge<=display_num;
        end if;
    end process;

    process(clock_in) --数码管显示
    begin
        if falling_edge(clock_in) then
            select_en<=1;    --因为我们的实验箱采用数码管并联方式,所以这里用动态显示
            case display_shi is
                when 0=>select_display<=1111110;
                when 1=>select_display<=0110000;
                when 2=>select_display<=1101101;
                when others=>select_display<=0000000;
            end case;
            if select_en=1 then
                select_en<=0;
                case display_ge is
                    when 0=>select_display<=1111110;
                    when 1=>select_display<=0110000;
                    when 2=>select_display<=1101101;
                    when 3=>select_display<=1111001;
                    when 4=>select_display<=0110011;
                    when 5=>select_display<=1011011;
                    when 6=>select_display<=1011111;
                    when 7=>select_display<=1110000;
                    when 8=>select_display<=1111111;
                    when 9=>select_display<=1110011;
                    when others=>select_display<=0000000;
                end case;
            end if;
        end if;
    end process;
end;
--由于时间和硬件限制,这个程序仅仅实现了一路交通灯,用类似的方法可以写出两路交通灯的程序。


结论

    这是一次颇有收获的实训,在PLC和单片机实训中我们曾两度设计交通灯课题,这次的课题,我们组仍然选择了交通灯,但所不同的是, 这次的实训中,我们更进一步体会到自主学习和团队合作的乐趣与必要性,我们所使用的VHDL语言,是一种硬件语言,语法结构与我早年学习的PASCAL很像, 但使用起来并不灵活。原因在于它是一种硬件连接语言,不能用纯软件的思维去思考它,再加上编译器Max+plus2的功能限制,使得我在程序编写时相当郁闷, 直到最后一天才调试成功,除了程序的易读性和清晰的结构外,我再没有半点成就感。在学习和制作过程中,老师的态度很明确,让学生自己去作, 这一点使很多人费解,而我为了完成项目,在网络上找到了许多相关资料,大大扩充自己的知识面,使许多以前想解决却无法解决的困难迎刃而解, 这才知道老师的良苦用心。相信以后的我不管是做网络亦或是从事软、硬件开发,都会有一个扎实的基础和良好的开发习惯的。

(2)关于交通灯控制器的VHDL代码设计
                                      


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity jtd is
generic(n:integer:=1);
port(clk_n:in std_logic;
s:in std_logic_vector(1 downto 0);
th1,tl1,th2,tl2:out std_logic_vector(3 downto 0);
gry1,gry2:out std_logic_vector(2 downto 0)); 
end jtd;

architecture one of jtd is
type state1 is(green,yellow,red);
type state2 is(red,green,yellow);
signal clk:std_logic;
signal grya,gryb:std_logic_vector(2 downto 0);
begin 
p1:process(clk_n)
variable cnt:integer range 0 to n;
begin
if(clk_n'event and clk_n='1')then
if(cnt cnt:=cnt+1;
clk<='0';
else
cnt:=0;
clk<='1';
end if;
end if;
end process; 
p2:process(clk)
variable reset:std_logic;
variable th,tl:std_logic_vector(3 downto 0);
variable s1:state1;
begin
if(clk'event and clk='1')then
if(s="11" or s="00")then
case s1 is
when green=>if(reset='0')then
th:="0010";
tl:="0100";
reset:='1';
gry1<="010";
else
if not(th="0000" and tl="0001")then
if(tl="0000")then
tl:="1001";
th:=th-1; 
else
tl:=tl-1; 
end if;
else
th:="0000";
tl:="0000";
reset:='0';
s1:=red;
end if;
end if;
when red=>if(reset='0')then
th:="0001";
tl:="1001";
gry1<="100";
else
if not(th="0000" and tl="0001")then
if(tl="0000")then
tl:="1001";
th:=th-1; 
else
tl:=tl-1; 
end if;
else
th:="0000";
tl:="0000";
reset:='0';
s1:=yellow;
end if;
end if;
when yellow=>if(reset='0')then
th:="0000";
tl:="0100";
reset:='1';
gry1<="001";
else
if not(th="0000" and tl="0001")then
if(tl="0000")then
tl:="1001";
th:=th-1;
else
tl:=tl-1;
end if;
else
th:="0000";
tl:="0000";
reset:='0';
s1:=green;
end if;
end if;
end case;
else

if(s="10")then
if not(tl="0000")then
tl:=tl-1;
gry1<="001";
th:="0000";
else
gry1<="010";
th:="0000";
end if;
end if;
end if;
end if;
th1<=th;
tl1<=tl;
end process;
p3:process(clk)
variable reset:std_logic;
variable th,tl:std_logic_vector(3 downto 0);
variable s2:state2;
begin
if(clk'event and clk='1')then
if(s="00" or s="11")then
case s2 is
when green=>if(reset='0')then
th:="0010";
tl:="0100";
reset:='1';
gry2<="010";
else
if not(th="0000" and tl="0001")then
if(tl="0000")then
tl:="1001";
th:=th-1; 
else
tl:=tl-1; 
end if;
else
th:="0000";
tl:="0000";
reset:='0';
s2:=red;
end if;
end if;
when red=>if(reset='0')then
th:="0001";
tl:="1001";
reset:='1';
gry2<="100";
else
if not(th="0000" and tl="0001")then
if(tl="0000")then
tl:="1001";
th:=th-1; 
else
tl:=tl-1; 
end if;
else
th:="0000";
tl:="0000";
reset:='0';
s2:=yellow;
end if;
end if;
when yellow=>if(reset='0')then
th:="0000";
tl:="0100";
reset:='1';
gry2<="001";
else
if not(th="0000" and tl="0001")then
if(tl="0000")then
tl:="1001";
th:=th-1;
else
tl:=tl-1;
end if;
else
th:="0000";
tl:="0000";
reset:='0';
s2:=green;
end if;
end if;
end case;
else

if not(tl="0000")then
tl:=tl-1;
gry2<="001";
th:="0000";
else
gry2<="100";
th:="0000";
end if;
end if;

end if;
th2<=th;
tl2<=tl;
end process;
end one;
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -