VHDL編寫的數(shù)字鐘.doc
FPGA課程設(shè)計實驗報告題目: VHDL編寫的數(shù)字鐘設(shè)計 學(xué)院: 電子信息學(xué)院 專業(yè): 電子與通訊工程 姓名: 朱振軍 基于FPGA的VHDL數(shù)字鐘設(shè)計 一、功能介紹 1在七段數(shù)碼管上具有時-分-秒的依次顯示。 2時、分、秒的個位記滿十向高位進(jìn)一,分、秒的十位記滿五向高位進(jìn)一,小時按24進(jìn)制計數(shù),分、秒按60進(jìn)制計數(shù)。 3整點(diǎn)報時,當(dāng)計數(shù)到整點(diǎn)時揚(yáng)聲器發(fā)出響聲。 4時間設(shè)置:可以通過按鍵手動調(diào)節(jié)秒和分的數(shù)值。此功能中可通過按鍵實現(xiàn)整體清零和暫停的功能。 5LED燈循環(huán)顯示:在時鐘正常計數(shù)下,LED燈被依次循環(huán)點(diǎn)亮。 待增加功能:1. 實現(xiàn)手動調(diào)節(jié)鬧鈴時間,在制定時間使揚(yáng)聲器發(fā)聲。2. 實現(xiàn)微妙的快速計數(shù)功能,可實現(xiàn)暫停、保存當(dāng)前時間、繼續(xù)計數(shù)的功能。二、設(shè)計方案 本文數(shù)字鐘的設(shè)計采用了自頂向下分模塊的設(shè)計。底層是實現(xiàn)各功能的模塊,各模塊由vhdl語言編程實現(xiàn):頂層采用原理圖形式調(diào)用。其中底層模塊包括秒、分、時三個計數(shù)器模塊、按鍵去抖動模塊、按鍵控制模塊、時鐘分頻模塊、數(shù)碼管顯示模塊共7個模塊。設(shè)計框圖如下: 圖一 數(shù)字鐘系統(tǒng)設(shè)計框圖由圖1可以清晰的看到數(shù)字鐘系統(tǒng)設(shè)計中各功能模塊間連接關(guān)系。系統(tǒng)時鐘50MHZ經(jīng)過分頻后產(chǎn)生1秒的時鐘信號,1秒的時鐘信號作為秒計數(shù)模塊的輸入信號,秒計數(shù)模塊產(chǎn)生的進(jìn)位信號作為分計數(shù)模塊的輸入信號,分計數(shù)模塊的進(jìn)位信號作為時計數(shù)模塊的輸入信號。秒計數(shù)模塊、分計數(shù)模塊、時計數(shù)模塊的計數(shù)輸出分別送到顯示模塊。由于設(shè)計中要使用按鍵進(jìn)行調(diào)節(jié)時間,而按鍵的動作過程中存在產(chǎn)生得脈沖的不穩(wěn)定問題,所以就牽扯到按鍵去抖動的問題,對此系統(tǒng)中設(shè)置了按鍵去抖動模塊,按鍵去抖動模塊產(chǎn)生穩(wěn)定的脈沖信號送入按鍵控制模塊,按鍵控制模塊根據(jù)按鍵的動作對秒、分、時進(jìn)行調(diào)節(jié)。 圖二 數(shù)字鐘的頂層設(shè)計原理圖三、設(shè)計過程由數(shù)字鐘的頂層設(shè)計原理圖可知:系統(tǒng)的外部輸入即為系統(tǒng)的時鐘信號CLK =50MHZ,系統(tǒng)的外部輸出有蜂鳴器信號buzzer,LED顯示信號LED3.1和shan(與按鍵去抖動模塊的o3相連),數(shù)碼管顯示信號xianshi7.0,數(shù)碼管位選信號xuanze7.0。 下面將對內(nèi)部功能模塊進(jìn)行詳細(xì)說明;1.分頻模塊pinlv對系統(tǒng)的時鐘50MHZ進(jìn)行分頻,設(shè)置不同長度的計數(shù)值,當(dāng)系統(tǒng)時鐘clk有變化時計數(shù)器開始計數(shù),當(dāng)計數(shù)到某個值時輸出一個信號,計數(shù)值不同輸出信號的周期也就不同,從而實現(xiàn)了對系統(tǒng)時鐘進(jìn)行不同的分頻,產(chǎn)生不同頻率的信號。由VHDL語言生成的模塊圖和程序說明如下: 圖三 分頻模塊 library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity pinlv isport( clk:in std_logic;-系統(tǒng)時鐘輸入端口 clk2ms:out std_logic; clk500ms:out std_logic; clk1s:out std_logic);-各頻率信號的輸出端口 end; architecture beh of pinlv isbeginp1:process(clk) 進(jìn)程p1variable count1:integer range 0 to 49999999;begin if(clkevent and clk=1)then count1:=count1+1;-在clk 的上升沿計數(shù) if count1<=24999999 then clk1s<=0; elsif count1<=49999999 then clk1s<=1; else count1:=0;-產(chǎn)生周期為1s的時鐘信號 end if; end if; end process p1;-結(jié)束進(jìn)程p1 p2:process(clk)進(jìn)程p2 variable count2:integer range 0 to 99999; begin if(clkevent and clk=1)then count2:=count2+1;-在clk上升沿計數(shù) if count2<=49999 then clk2ms<=0;elsif count2<=99999 then clk2ms<=1;-產(chǎn)生周期為2ms的掃描信號 end if; end if; end process p2;-結(jié)束進(jìn)程p2 p3:process(clk)進(jìn)程p3 variable count3:integer range 0 to 24999999; begin if(clkevent and clk=1)then count3:=count3+1;在clk上升沿計數(shù) if count3<=12499999 then clk500ms<=0; elsif count3<=24999999 then clk500ms<=1;else count3:=0;產(chǎn)生周期為500ms的時鐘信號 end if; end if; end process p3; end beh;2按鍵去抖動模塊qudou本設(shè)計用到FPGA開發(fā)板上的四個按鍵,由于按鍵有反應(yīng)時間、抖動的問題,可能當(dāng)按鍵被按一次時而系統(tǒng)感應(yīng)到幾次,造成誤差。所以應(yīng)該進(jìn)行按鍵消抖的處理,讓每按一次鍵系統(tǒng)只感應(yīng)到一次按鍵??梢圆捎密浖訒r,觸發(fā)反相器等方式進(jìn)行消除抖動,本設(shè)計中采用軟件延時的方式。由VHDL語言生成的模塊圖和程序說明如下: 圖四 按鍵去抖動模塊 library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity qudou isport(clk,k1,k2,k3,k4:in std_logic;o1,o2,o3,o4:out std_logic);-設(shè)置按鍵輸入信號輸出端口end;architecture beh of qudou isbegin process(clk,k1,k2,k3,k4)variable cant1:integer;variable cant2:integer;variable cant3:integer;variable cant4:integer;begin if clkevent and clk=1 then if k1=1 then cant1:=0; end if;-設(shè)置計數(shù)初值 if k2=1 then cant2:=0; end if; -設(shè)置計數(shù)初值 if k3=1 then cant3:=0; end if; if k4=1 then cant4:=0; end if; -設(shè)置計數(shù)初值 if cant1>2499999 then o1<=0; else o1<=1;-延時0.5s end if; if cant2>2499999 then o2<=0; else o2<=1; -延時0.5s end if; if cant3>2499999 then o3<=0; else o3<=1; -延時0.5s end if; if cant4>2499999 then o4<=0; else o4<=1; -延時0.5s end if;cant1:=cant1+1; -加一計數(shù)cant2:=cant2+1; -加一計數(shù)cant3:=cant3+1; -加一計數(shù)cant4:=cant4+1; -加一計數(shù) end if;end process;end beh; -設(shè)置計數(shù)初值在quartus II開發(fā)環(huán)境中進(jìn)行仿真驗證 圖五 按鍵去抖動仿真效果圖由于0.5s太長,在本仿真中設(shè)置了很小的一個量10clk,從圖中可以看出基本實現(xiàn)了按鍵去抖動的效果。無論按鍵怎么抖動,輸出總是保持穩(wěn)態(tài)10clk,當(dāng)下一個觸發(fā)來了以后,就可以觸發(fā)單穩(wěn)態(tài)。3,按鍵控制模塊self1本設(shè)計中使用了兩個按鍵進(jìn)行對時鐘的暫停和調(diào)秒操作,當(dāng)ok2按下時時鐘暫停,再按ok3則進(jìn)行秒個位的加一計數(shù),每按一次進(jìn)行加一處理。當(dāng)調(diào)節(jié)好時間后,在按ok2鍵重新開始計數(shù)。由VHDL語言生成的模塊圖和程序說明如下: 圖六 按鍵控制模塊 library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity self1 isport(c:in std_logic;ok2:in std_logic;ok3:in std_logic;ck:out std_logic);end ;-設(shè)置端口architecture bea of self1 issignal m:std_logic;signal t:std_logic;beginp1:process(ok2,ok3,c)ok2和ok3觸發(fā)進(jìn)程beginif ok2event and ok2=0 then m<=not m;-由ok2 的動作產(chǎn)生m的電平信號 end if; if m=1 then ck<=not(ok3);-把按鍵ok3的脈沖信號給輸出 else ck<=c;-否則把正常計數(shù)時鐘給輸出 end if;end process p1;-結(jié)束進(jìn)程end bea;4,秒、分六十進(jìn)制模塊cantsixty本設(shè)中秒、分的六十進(jìn)制是由個位的十進(jìn)制和十位的六進(jìn)制進(jìn)行組合實現(xiàn)的。當(dāng)個位記到9時自動向高位進(jìn)一,同時個位自動清零。當(dāng)十位記到5并且個位記到9時,自動產(chǎn)生一個進(jìn)位脈沖,同時個位和十位分別從零開始重新計數(shù)。由VHDL語言生成的模塊圖和程序說明如下: 圖七 六十進(jìn)制模塊library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity cantsixty isport(clk:in std_logic; reset:in std_logic; out1:out std_logic_vector(3 downto 0); out2:out std_logic_vector(3 downto 0); c:out std_logic); end;architecture beh of cantsixty issignal ss1,ss2:std_logic_vector( 3 downto 0);beginp1:process(clk,reset) beginif(reset=0)then ss1<="0000"ss2<="0000" elsif(clkevent and clk=1)then if ss1="1001" and ss2="0101" then c<=1;-當(dāng)計數(shù)到59時產(chǎn)生進(jìn)位信號 else c<=0;-否則不產(chǎn)生 end if; if ss1="1001" then ss1<="0000" if ss2="0101" then ss2<="0000" else ss2<=ss2+1; end if; else ss1<=ss1+1;-計數(shù)過程 end if;end if;end process p1;-結(jié)束進(jìn)程out1<=ss1;out2<=ss2;-把信號送輸出end beh;在quartus II開發(fā)環(huán)境中進(jìn)行仿真驗證: 圖八 六十進(jìn)制波形仿真圖由上圖可見,當(dāng)1s的時鐘信號加入時,個位out1從0到9不斷循環(huán),而且當(dāng)個位out1記到9時產(chǎn)生一個進(jìn)位信號 使十位out2加一,以此類推就實現(xiàn)了六十進(jìn)制計數(shù)。基本達(dá)到了正確計數(shù)的理想效果。5.時計數(shù)模塊hourtwenty時計數(shù)模塊是二十四進(jìn)制相對復(fù)雜一點(diǎn),因為當(dāng)十位0或著1時個位需要記到9并產(chǎn)生進(jìn)位信號,當(dāng)十位是2時,個位記到3時,就全部從零開始重新計數(shù)。即是在十位為不同值時個位兩種計數(shù)過程。由VHDL語言生成的模塊圖和程序說明如下: 圖九 二十四進(jìn)制波形仿真圖 在quartus II開發(fā)環(huán)境中進(jìn)行仿真驗證: 圖十 二十四進(jìn)制波形仿真圖 由上圖看出十位為0或1時,個位記到9時,十位才進(jìn)行加一計數(shù),但當(dāng)十位為2時,個位記到3時,十位變成了0,個位又從0重新開始計數(shù),這樣就實現(xiàn)了二十四進(jìn)制的計數(shù)。從圖形的顯示波形可知,設(shè)計基本達(dá)到了正確計數(shù)的功能。6.秒、分、時組合后的仿真驗證 把設(shè)計的秒、分、時模塊連接起來,再通過仿真驗證,各模塊間的進(jìn)位是否正確連接后的原理圖如下 圖十一 秒、分、時組合后原理圖在quartus II開發(fā)環(huán)境中進(jìn)行仿真驗證: 圖十二 組合后波形仿真圖由于需要設(shè)置很長的仿真時間,才能完全觀察到進(jìn)位信號,本次仿真只截取了一小部分,觀察不到分模塊向時模塊的進(jìn)位。由仿真結(jié)果圖可以看到,秒模塊向分鐘模塊的正常進(jìn)位,以及分模塊的正常計數(shù),所以各模塊連接后的計數(shù)狀態(tài)也符合設(shè)計的要求,基本實現(xiàn)了正常計數(shù)。7 .數(shù)碼管顯示模塊 本模塊中包含數(shù)碼管的段選和位選設(shè)計,Led燈循環(huán)設(shè)計,以及整點(diǎn)報時的設(shè)計。模塊的輸入信號有數(shù)碼管掃描頻率clk2ms,秒、分、時各模塊的個位和十位輸入,以及由分模塊向時模塊產(chǎn)生的進(jìn)位脈沖信號。由VHDL語言生成的模塊圖和程序說明如下: 圖十三 數(shù)碼管顯示原理圖 library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity qudong isport(s1,s2,m1,m2,h1,h2:in std_logic_vector(3 downto 0); clk2ms: in std_logic; xiang:in std_logic; led:out std_logic_vector(3 downto 1); buzzer:out std_logic; xianshi:out std_logic_vector(7 downto 0); xuanze:out std_logic_vector( 7 downto 0); end qudong; architecture behav of qudong issignal sel:std_logic_vector( 2 downto 0);signal A:std_logic_vector( 3 downto 0);signal t:std_logic_vector ( 11 downto 0);signal f:std_logic_vector(1 downto 0);signal count1:std_logic_vector(1 downto 0);beginp1:process(clk2ms)beginif clk2msevent and clk2ms=1 then sel<=sel+1;t<=t+1; if t="110010000000" then t<=(others=>0);end if;end if;f<=t(11)&t(10);if f="01" then led(3)<=0;else led(3)<=1;end if;if f="10" then led(2)<=0;else led(2)<=1;end if;if f="11" then led(1)<=0; else led(1)<=1;end if;-led的循環(huán)顯示設(shè)計end process p1;p2:process(sel,s1,s2,m1,m2,h1,h2)begincase sel iswhen "000" =>xuanze<="11111110" A<=s1;-秒個位在數(shù)碼管1上顯示when "001" =>xuanze<="11111101" A<=s2;-秒十位在數(shù)碼管2上顯示when "010" =>xuanze<="11111011" A<="1010"-數(shù)碼管3上顯示橫杠when "011" =>xuanze<="11110111" A<=m1;-分個位在數(shù)碼管4上顯示when "100" =>xuanze<="11101111" A<=m2;-分十位在數(shù)碼管5上顯示when "101" =>xuanze<="11011111" A<="1011"-數(shù)碼管6上顯示橫杠when "110" =>xuanze<="10111111" A<=h1;-時個位在數(shù)碼管7上顯示when "111" =>xuanze<="01111111" A<=h2;-時十位在數(shù)碼管8上顯示when others =>null;end case;end process p2;p3:process(A)begincase A iswhen "0000" => xianshi <="11000000"-顯示0 when "0001" => xianshi <="11111001" -顯示1 when "0010" => xianshi <="10100100" -顯示2 when "0011" => xianshi <="10110000" -顯示3 when "0100" => xianshi <="10011001" -顯示4 when "0101" => xianshi <="10010010" -顯示5 when "0110" => xianshi <="10000010" -顯示6 when "0111" => xianshi <="11111000" -顯示7 when "1000" => xianshi <="10000000" -顯示8 when "1001" => xianshi <="10010000" -顯示9 when "1010" =>xianshi <="10111111" -顯示- when "1011" =>xianshi <="10111111" -顯示- when others =>null; -數(shù)碼管的段選設(shè)計end case;end process p3;P4:process(xiang)begin if xiang=1 then buzzer<=0; -當(dāng)進(jìn)位信號xiang為1時就把低電平給buzzer讓蜂鳴器響 else buzzer<=1; -否則把高電平給buzzer不給蜂鳴器觸發(fā)信號end if;end process p4; -結(jié)束進(jìn)程end behav;四、實驗結(jié)果將調(diào)試好的程序下載到實驗板上進(jìn)行驗證,達(dá)到了設(shè)計的各項功能。時鐘準(zhǔn)確計數(shù),各模塊的進(jìn)位也正確,當(dāng)按下實驗板上的key1鍵時系統(tǒng)復(fù)位清零,實驗板上的key2鍵可實現(xiàn)系統(tǒng)的暫停和開始,在系統(tǒng)暫停的狀態(tài)下,按key3鍵可實現(xiàn)調(diào)節(jié)秒計數(shù),每按一次計數(shù)加一,key4鍵可實現(xiàn)調(diào)節(jié)分模塊,每按一次計數(shù)加一,長按則一直加,當(dāng)達(dá)到整點(diǎn)時,蜂鳴器發(fā)聲。五、實驗小結(jié)與體會這個實驗帶給我的體會很多也很深,我以前沒有對數(shù)字鐘進(jìn)行系統(tǒng)的設(shè)計,這次獨(dú)立的設(shè)計,我遇到了很多問題,也走了很多彎路,還好最后終于通過自己的努力看到了理想的結(jié)果。通過實驗,我對EDA技術(shù)和FPGA技術(shù)有了更進(jìn)一步的理解,掌握了FPGA的層次化設(shè)計電路的方法,掌握了用VHDL語言編寫各個功能模塊并通過波形確定電路設(shè)計是否正確。掌握了下載驗到目標(biāo)器件的過程。實驗中遇到的問題很多,有的是很基礎(chǔ)的但我卻不知道,例如數(shù)碼管的掃描頻率,剛開始時數(shù)碼管不顯示,我找了很多原因都沒想到是掃描頻率的問題,浪費(fèi)了很多時間。還有分頻的時候,看過很多分頻的電路程序,但那些并不是都可以實現(xiàn)準(zhǔn)確的分頻,需要通過波形進(jìn)行驗證。還有計數(shù)器的設(shè)計,我用了很長時間才編寫出來,現(xiàn)在看看,也沒有那么難了??傊液芨兄x這次實驗可以給我這樣的機(jī)會,這個實驗給了我很對的收獲,我相信這會對我以后的學(xué)習(xí)和工作都有幫助。