?? vhdl交通燈1.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 + -