2.8 數(shù)字時(shí)鐘設(shè)計(jì)-明德?lián)P至簡(jiǎn)設(shè)計(jì)法原理與應(yīng)用
本節(jié)的文檔編號(hào):001600000019
需要看對(duì)應(yīng)的視頻,請(qǐng)點(diǎn)擊視頻編號(hào):001600000042
1.至簡(jiǎn)原理與應(yīng)用配套的案例文檔
2.使用6個(gè)數(shù)碼管實(shí)現(xiàn)數(shù)字時(shí)鐘功能,與數(shù)字時(shí)鐘相同,該功能可以顯示00:00:00到23:59:59范圍的時(shí)間。
3. 這是ALTERA入門學(xué)習(xí)案例文檔
1項(xiàng)目背景
數(shù)字時(shí)鐘用數(shù)字電路技術(shù)實(shí)現(xiàn)時(shí)、分、秒計(jì)時(shí)顯示的裝置。用數(shù)字同時(shí)顯示時(shí),分,秒的精確時(shí)間,并能實(shí)現(xiàn)準(zhǔn)確校時(shí)。與傳統(tǒng)表盤式機(jī)械式時(shí)鐘相比,具有更高的準(zhǔn)確性和直觀性,且無(wú)機(jī)械裝置,具有更長(zhǎng)的使用壽命。不僅如此,還具備體積小、重量輕、抗干擾能力強(qiáng)、對(duì)環(huán)境要求高、高精確性、容易開(kāi)發(fā)等特性。本案例將詳細(xì)介紹用至簡(jiǎn)設(shè)計(jì)法實(shí)現(xiàn)數(shù)字時(shí)鐘的功能。
2?設(shè)計(jì)目標(biāo)
本工程使用6個(gè)數(shù)碼管實(shí)現(xiàn)數(shù)字時(shí)鐘功能。該功能與數(shù)字時(shí)鐘相同,即從00:00:00一直到23:59:59。
上板效果圖如下圖所示。

3?設(shè)計(jì)實(shí)現(xiàn)
3.1?頂層信號(hào)
新建目錄:D:mdy_bookmy_shizhong。在該目錄中,新建一個(gè)名為my_shizong.v的文件,并用GVIM打開(kāi),開(kāi)始編寫代碼。
我們要實(shí)現(xiàn)的功能,概括起來(lái)就是控制8個(gè)數(shù)碼管,讓其中2個(gè)數(shù)碼管常滅,其他6個(gè)數(shù)碼顯示不同的數(shù)字。要控制8個(gè)數(shù)碼管,就需要控制位選信號(hào),即FPGA要輸出一個(gè)8位的位選信號(hào),設(shè)為seg_sel,其中seg_sel[0]對(duì)應(yīng)數(shù)碼管0,seg_sel[1]對(duì)應(yīng)數(shù)碼管1,以此類推,seg_sel[7]對(duì)應(yīng)數(shù)碼管7。
要顯示不同的數(shù)字,就需要控制段選信號(hào),不需要用到DP,一共有7根線,即FPGA要輸出一個(gè)7位的段選信號(hào),設(shè)為seg_ment,seg_ment[6]~segm_ment[0]分別對(duì)應(yīng)數(shù)碼管的abcdefg(注意對(duì)應(yīng)順序)。
我們還需要時(shí)鐘信號(hào)和復(fù)位信號(hào)來(lái)進(jìn)行工程控制。
綜上所述,我們這個(gè)工程需要4個(gè)信號(hào),時(shí)鐘clk,復(fù)位rst_n,輸出的位選信號(hào)seg_sel和輸出的段選信號(hào)seg_ment。

將module的名稱定義為my_shizhong。并且我們已經(jīng)知道該模塊有4個(gè)信號(hào):clk、rst_n、seg_sel和seg_ment,代碼如下:

其中clk、rst_n是1位的輸入信號(hào),seg_sel是8位的輸出信號(hào),seg_ment是7位的輸出信號(hào),根據(jù)此,補(bǔ)充輸入輸出端口定義。代碼如下:

3.2?信號(hào)設(shè)計(jì)
我們先分析要實(shí)現(xiàn)的功能,我們用m_g,m_s,f_g,f_s,s_g,s_s分別表示秒鐘個(gè)位、秒鐘十位、分鐘個(gè)位、分鐘十位、小時(shí)個(gè)位和小時(shí)十位所表示的數(shù)字值,m_g_s,m_s_s,f_g_s,f_s_s,s_g_s,s_s_s分別表示秒鐘個(gè)位、秒鐘十位、分鐘個(gè)位、分鐘十位、小時(shí)個(gè)位和小時(shí)十位所表示數(shù)碼管段選值。
數(shù)碼管0顯示的是秒個(gè)位值,則翻譯成信號(hào)就是seg_sel的值為8’b1111_1110,seg_ment的值為:m_g_s。數(shù)碼管1顯示秒十位,也就是說(shuō)seg_sel的值為8’b1111_1101,seg_ment的值為m_s_s。以此類推,數(shù)碼管5顯示小時(shí)十位,也就是seg_sel的值為8’b1101_1111,seg_ment的值為s_s_s。

圖?289
那么seg_ment和seg_sel多久變化一次呢?我們就需要用到數(shù)碼管動(dòng)態(tài)掃描原理了。
數(shù)碼管動(dòng)態(tài)顯示接口是應(yīng)用最為廣泛的一種顯示方式之一,動(dòng)態(tài)驅(qū)動(dòng)是將所有數(shù)碼管的8個(gè)顯示筆劃"a,b,c,d,e,f,g,dp"的同名端連在一起,另外為每個(gè)數(shù)碼管的公共極COM增加位選通控制電路,位選通由各自獨(dú)立的I/O線控制,當(dāng)要輸出字形碼時(shí),所有數(shù)碼管都接收到相同的字形碼,但究竟是哪個(gè)數(shù)碼管會(huì)顯示出字形,取決于單片機(jī)對(duì)位選通COM端電路的控制,所以我們只要將需要顯示的數(shù)碼管的選通控制打開(kāi),該位就顯示出字形,沒(méi)有選通的數(shù)碼管就不會(huì)亮。通過(guò)分時(shí)輪流控制各個(gè)數(shù)碼管的的COM端,就使各個(gè)數(shù)碼管輪流受控顯示,這就是動(dòng)態(tài)驅(qū)動(dòng)。在輪流顯示過(guò)程中,每位數(shù)碼管的點(diǎn)亮?xí)r間為1~2ms,由于人的視覺(jué)暫留現(xiàn)象及發(fā)光二極管的余輝效應(yīng),盡管實(shí)際上各位數(shù)碼管并非同時(shí)點(diǎn)亮,但只要掃描的速度足夠快,給人的印象就是一組穩(wěn)定的顯示數(shù)據(jù),不會(huì)有閃爍感,動(dòng)態(tài)顯示的效果和靜態(tài)顯示是一樣的,能夠節(jié)省大量的I/O端口,而且功耗更低。
也就是說(shuō),只要刷新時(shí)間為1~2ms,那么人眼看起來(lái)就似乎是所有數(shù)碼管都在顯示。因?yàn)槲覀儼堰@個(gè)刷新時(shí)間定為2ms,也就是如下圖。

圖?290
由波形圖可知,我們需要1個(gè)計(jì)數(shù)器用來(lái)計(jì)算2毫秒的時(shí)間。本工程的工作時(shí)鐘是50MHz,即周期為20ns,計(jì)數(shù)器計(jì)數(shù)到2_000_000/20=100_000個(gè),我們就能知道2毫秒時(shí)間到了。另外,由于該計(jì)數(shù)器是不停地計(jì)數(shù),永遠(yuǎn)不停止的,可以認(rèn)為加1條件一直有效,可寫成:assign add_cnt0==1。綜上所述,該計(jì)數(shù)器的代碼如下。

再次觀察波形圖,我們發(fā)現(xiàn)依次是顯示的是m_g_s、m_s_s、f_g_s、f_s_s、s_g_s和s_s_s,一共6個(gè),循環(huán)進(jìn)行顯示。這說(shuō)明還需要另外一個(gè)計(jì)數(shù)器來(lái)表示第幾個(gè)。該計(jì)數(shù)器每隔2ms加1,因此加1條件為end_cnt0。該計(jì)數(shù)器一共要數(shù)6次。所以代碼為:

有了兩個(gè)計(jì)數(shù)器,我們來(lái)思考輸出信號(hào)seg_sel的變化。概括起來(lái),在第1次的時(shí)候輸出值為8’hfe;在第2次的時(shí)候輸出值為8’hfd;以此類推,在第6次的時(shí)候輸出值為8’hdf。我們用信號(hào)cnt1來(lái)代替第幾次,也就是:當(dāng)cnt1==0的時(shí)候,輸出值為8’hfe;在cnt1==1的時(shí)候輸出值為8’hfd;以此類推,在cnt1==5的時(shí)候輸出值為8’hdf。再進(jìn)一步翻譯成代碼,就變成如下:

或者可以簡(jiǎn)寫成:

對(duì)上面代碼解釋一下,第131行是指先將8’b1向左移位,再取反后的值,賦給seg_sel。假設(shè)此時(shí)cnt1等于0,那么8’b1<<0的結(jié)果是8’b0000_0001,取反的值為8’hfe;假設(shè)cnt1等于3,那么8’b1<<3的結(jié)果為8’b000_1000,取反后的結(jié)果為8’b1111_0111,即8’hf7。與第一種寫法的結(jié)果都是相同的。
我們來(lái)思考輸出信號(hào)seg_ment的變化。seg_ment的值,是m_g、m_s、f_g、f_s、s_g和s_s等數(shù)值分別譯碼成數(shù)碼管顯示的信號(hào)m_g_s、m_s_s、f_g_s、f_s_s、s_g_s和s_s_s。我們一種做法,是將數(shù)值分別轉(zhuǎn)成譯碼信號(hào),然后再挑選出來(lái)給seg_ment。如下面的原理圖:

圖?291
我們還可以是先可以選擇哪一組數(shù)據(jù),選出來(lái)后再做譯碼,其原理圖如下:

圖?292
對(duì)比兩個(gè)原理圖,可以發(fā)現(xiàn),實(shí)現(xiàn)同樣的功能,第二個(gè)原理圖比第一個(gè),少了5個(gè)譯碼電路。這是一個(gè)簡(jiǎn)單的例子,說(shuō)明實(shí)現(xiàn)一個(gè)功能,可以有很多種方法,方法各有優(yōu)勢(shì),能用較少的資源、較快的速度實(shí)現(xiàn)功能,這就是設(shè)計(jì)師的能力,也是FPGA設(shè)計(jì)的魅力所在。
我們采用第二種實(shí)現(xiàn)方案。設(shè)計(jì)一個(gè)信號(hào)sel_data,表示從6個(gè)數(shù)據(jù)中選擇的信號(hào),之后再做譯碼。波形圖更新如下:

圖?293
sel_data的值有可能為0~9中的任意數(shù)字,這些數(shù)字都要轉(zhuǎn)成數(shù)碼管的段選信號(hào)。下表列出不同數(shù)字對(duì)應(yīng)的段選信號(hào)值。

明德?lián)P開(kāi)發(fā)板使用的是共陽(yáng)數(shù)碼管。根據(jù)上表,可寫出下面代碼。

當(dāng)然,也可以寫成case的形式,結(jié)果都是一樣的。

sel_data從m_g、m_s、f_g、f_s、s_g和s_s中選取。當(dāng)cnt1=0,即數(shù)碼管0顯示時(shí),sel_data的值為m_g;當(dāng)cnt1=1,即數(shù)碼管1顯示時(shí),sel_data的值為m_s;當(dāng)cnt1=2,即數(shù)碼管2顯示時(shí),sel_data的值為f_g;當(dāng)cnt1=3,即數(shù)碼管3顯示時(shí),sel_data的值為f_s;當(dāng)cnt1=4,即數(shù)碼管4顯示時(shí),sel_data的值為s_g;當(dāng)cnt1=5,即數(shù)碼管5顯示時(shí),sel_data的值為s_s。為此,sel_data的代碼為:

接下來(lái)我們?cè)O(shè)計(jì)m_g、m_s、f_g、f_s、s_g和s_s信號(hào),按照常識(shí),秒個(gè)位m_g的變化規(guī)律如下:

圖?294
秒個(gè)位的數(shù)據(jù)是0、1、2~9、0這樣有規(guī)律的加1變化,很明顯可以看出這個(gè)m_g其實(shí)就是一個(gè)計(jì)數(shù)器,并且這個(gè)計(jì)數(shù)器每隔1秒時(shí)間才變化加1一次。1秒時(shí)間計(jì)時(shí)也需要一個(gè)計(jì)數(shù)器,設(shè)為cnt2,則cnt2是一直加1的,即可以寫成assign add_cnt2 = 1。cnt2要數(shù)1秒時(shí)間,本工程的工作時(shí)鐘是50MHz,即周期為20ns,計(jì)數(shù)器計(jì)數(shù)到1_000_000_000/20=50_000_000個(gè),我們就能知道1秒時(shí)間到了,所以cnt1的周期是?50_000_000個(gè)。有了cnt1,我們就知道m(xù)_g這個(gè)計(jì)數(shù)器的加1條件是1秒時(shí)間到了,即end_cnt2==1,要計(jì)數(shù)10個(gè)。綜上所述,可以寫出cnt2和m_g的代碼如下:


接下來(lái)思考秒十位m_s,m_s的變化情況如下:

圖?295
m_s秒十位的指示,很明顯每隔10秒就會(huì)加1,很明顯,m_s也是一個(gè)計(jì)數(shù)器,加1條件是10秒時(shí)間到,也就是end_m_g。該計(jì)數(shù)器周期性是數(shù)6個(gè)。所以代碼如下:

接下來(lái)思考分個(gè)位f_g,f_g的變化情況如下:

圖?296
f_g分個(gè)位的指示,很明顯每隔1分鐘即60秒就會(huì)加1,很明顯,f_g也是一個(gè)計(jì)數(shù)器,加1條件是60秒時(shí)間到,也就是end_m_s。該計(jì)數(shù)器周期性是數(shù)10個(gè)。所以代碼如下:

接下來(lái)思考分十位f_s,f_s的變化情況如下:

圖?297
f_s分十位的指示,很明顯每隔10分鐘就會(huì)加1,很明顯,f_s也是一個(gè)計(jì)數(shù)器,加1條件是10分鐘到,也就是end_f_g。該計(jì)數(shù)器周期性是數(shù)6個(gè)。所以代碼如下:

接下來(lái)思考小時(shí)個(gè)位s_g,s_g的變化情況如下:

圖?298
s_g小時(shí)個(gè)位的指示,很明顯每隔1小時(shí)即6分鐘就會(huì)加1,很明顯,s_g也是一個(gè)計(jì)數(shù)器,加1條件是1小時(shí)也就是60分鐘時(shí)間到,也就是end_f_g。
接下來(lái)我們需要好好思考這個(gè)小時(shí)個(gè)位,它的周期是多少。有讀者認(rèn)為是10個(gè),因?yàn)槭切r(shí)個(gè)位會(huì)從0~9這樣變化;有讀者認(rèn)為是24個(gè),因?yàn)橐还彩?4小時(shí);有讀者認(rèn)為是4個(gè),因?yàn)樾r(shí)個(gè)位會(huì)從0~4變化。
認(rèn)為是24小時(shí)的讀者,沒(méi)有認(rèn)識(shí)到我們只是看小時(shí)個(gè)位的變化,而不是小時(shí)個(gè)位和小時(shí)十位整體,整體才是24小時(shí)。我們盯著小時(shí)個(gè)位,會(huì)發(fā)現(xiàn)它是這么一個(gè)規(guī)律:0~9,0~9,0~3,0~9,0~9,0~3。因此正確的答案是,有時(shí)候周期是10,有時(shí)候是4,也就是說(shuō)周期性會(huì)變的。按照明德?lián)P的變量法,設(shè)其周期是x,則可以寫出s_g的代碼如下,而x是怎么來(lái),我們先不考慮,后期再說(shuō)。

接下來(lái)思考小時(shí)十位s_s,s_s的變化情況如下:

圖?299
s_s小時(shí)十位的指示,很明顯當(dāng)小時(shí)個(gè)位要清零時(shí)(注意不是每隔10小時(shí)),s_s就會(huì)加1,很明顯,s_s也是一個(gè)計(jì)數(shù)器,加1條件是小時(shí)個(gè)位要清零了,也就是end_s_g。該計(jì)數(shù)器周期性是數(shù)3個(gè)。所以代碼如下:

最后,我們?cè)倏紤]x,也就是小時(shí)個(gè)位的周期性是多少,并取決于什么因素。我們可以發(fā)現(xiàn),小時(shí)個(gè)位是0~9,0~9,0~3,0~9,0~9,0~3,也就是周期性是10或者是4。至于是10還是4,則取決于小時(shí)十位,即s_s。當(dāng)時(shí)鐘的小時(shí)十位顯示為2時(shí),小時(shí)個(gè)位只要數(shù)到3就行了,沒(méi)有25點(diǎn)的。綜上所術(shù),發(fā)s_s為2時(shí),x=4,否則x=10。所以x的代碼如下:

此次,主體程序已經(jīng)完成。接下來(lái)是將module補(bǔ)充完整。
3.3?信號(hào)定義
接下來(lái)定義信號(hào)類型。
cnt0是用always產(chǎn)生的信號(hào),因此類型為reg。cnt0計(jì)數(shù)的最大值為100_000,需要用17根線表示,即位寬是17位。add_cnt0和end_cnt0都是用assign方式設(shè)計(jì)的,因此類型為wire。并且其值是0或者1,1個(gè)線表示即可。因此代碼如下:

cnt1是用always產(chǎn)生的信號(hào),因此類型為reg。cnt1計(jì)數(shù)的最大值為6,需要用3根線表示,即位寬是3位。add_cnt1和end_cnt1都是用assign方式設(shè)計(jì)的,因此類型為wire。并且其值是0或者1,1根線表示即可。因此代碼如下:

seg_sel是用always方式設(shè)計(jì)的,因此類型為reg,其一共有8根線,即位寬為8。因此代碼如下:

seg_ ment是用always方式設(shè)計(jì)的,因此類型為reg,其一共有7根線,即位寬為7。因此代碼如下:

sel_data是用always設(shè)計(jì)的,所以類型為wire。其最大值為9,所以需要4位位寬。代碼如下:

cnt2是用always產(chǎn)生的信號(hào),因此類型為reg。cnt2計(jì)數(shù)的最大值為50_000_000,需要用26根線表示,即位寬是26位。add_cnt2和end_cnt2都是用assign方式設(shè)計(jì)的,因此類型為wire。并且其值是0或者1,1個(gè)線表示即可。因此代碼如下:

m_g是用always產(chǎn)生的信號(hào),因此類型為reg。m_g計(jì)數(shù)的最大值為9,需要用4根線表示,即位寬是4位。add_m_g和end_m_g都是用assign方式設(shè)計(jì)的,因此類型為wire。并且其值是0或者1,1個(gè)線表示即可。因此代碼如下:

m_s是用always產(chǎn)生的信號(hào),因此類型為reg。m_s計(jì)數(shù)的最大值為5,需要用3根線表示,即位寬是3位。add_m_s和end_m_s都是用assign方式設(shè)計(jì)的,因此類型為wire。并且其值是0或者1,1個(gè)線表示即可。因此代碼如下:

f_g是用always產(chǎn)生的信號(hào),因此類型為reg。f_g計(jì)數(shù)的最大值為9,需要用4根線表示,即位寬是4位。add_f_g和end_f_g都是用assign方式設(shè)計(jì)的,因此類型為wire。并且其值是0或者1,1個(gè)線表示即可。因此代碼如下:

f_s是用always產(chǎn)生的信號(hào),因此類型為reg。f_s計(jì)數(shù)的最大值為5,需要用3根線表示,即位寬是3位。add_f_s和end_f_s都是用assign方式設(shè)計(jì)的,因此類型為wire。并且其值是0或者1,1個(gè)線表示即可。因此代碼如下:

s_g是用always產(chǎn)生的信號(hào),因此類型為reg。s_g計(jì)數(shù)的最大值為9,需要用4根線表示,即位寬是4位。add_s_g和end_s_g都是用assign方式設(shè)計(jì)的,因此類型為wire。并且其值是0或者1,1個(gè)線表示即可。因此代碼如下:

s_s是用always產(chǎn)生的信號(hào),因此類型為reg。s_s計(jì)數(shù)的最大值為2,需要用2根線表示,即位寬是2位。add_s_s和end_s_s都是用assign方式設(shè)計(jì)的,因此類型為wire。并且其值是0或者1,1個(gè)線表示即可。因此代碼如下:

x是用always產(chǎn)生的信號(hào),因此類型為reg。x計(jì)數(shù)的最大值為10,需要用4根線表示,即位寬是4位。

至此,整個(gè)代碼的設(shè)計(jì)工作已經(jīng)完成。

下一步是新建工程和上板查看現(xiàn)象。
4?綜合與上板
4.1?新建工程
首先在d盤中創(chuàng)建名為“my_shizhong”的工程文件夾,將寫的代碼命名為“my_shizhong.v”,頂層模塊名為“my_shizhong”。

圖?300

圖?301
然后打開(kāi)QuartusⅡ,點(diǎn)擊File下拉列表中的New Project Wzard...新建工程選項(xiàng)。

圖?302
3.再出現(xiàn)的界面中直接點(diǎn)擊Next。

圖?303
4.之后出現(xiàn)的是工程文件夾、工程名、頂層模塊名設(shè)置界面。按照之前的命名進(jìn)行填寫,然后點(diǎn)擊Next,在出現(xiàn)的界面選擇empty project。

圖?304

圖?305
5.之后是文件添加界面。添加之前寫的“my_shizhong.v”文件,點(diǎn)擊右側(cè)的“Add”按鈕,之后文件還會(huì)出現(xiàn)在下方大方框里,之后點(diǎn)擊“Next”。

圖?306
器件型號(hào)選擇界面。在上方紅色箭頭處選擇Cyclone?ⅣE,在中間紅色箭頭處選擇EP4CE15F23C8,然后點(diǎn)擊“Next”。

圖?307
EDA工具界面。直接點(diǎn)擊“Next”。

圖?308
8.之后出現(xiàn)的界面,點(diǎn)擊“Finish”。

圖?309
4.2?綜合
1.新建工程步驟完成后,就會(huì)出現(xiàn)以下界面。選中要編譯的文件,點(diǎn)擊編譯按鈕。

圖?310
2.編譯成功后會(huì)出現(xiàn)一下界面。

圖?311
4.3?配置管腳

圖?312
在菜單欄中,選中Assignments,然后選擇Pin Planner,就會(huì)彈出配置管腳的窗口。

圖?313
在配置窗口最下方中的location一列,參考下表中最右兩列配置好FPGA管腳。

配置完成后,關(guān)閉Pin Planner,軟件自動(dòng)會(huì)保存管腳配置信息。
4.4?再次綜合

圖?314
在菜單欄中,選中Processing,然后選擇Start Compilation,再次對(duì)整個(gè)工程進(jìn)行編譯和綜合。

圖?315
出現(xiàn)上面的界面,就說(shuō)明編譯綜合成功。
4.5?連接開(kāi)發(fā)板
圖中,下載器接入電腦USB接口,電源接入電源,然后摁下藍(lán)色開(kāi)關(guān)。

圖?316
4.6?上板
1.雙擊Tasks一欄中”Program Device”。

圖?317
2.會(huì)出現(xiàn)如下界面,點(diǎn)擊add file添加.sof文件,點(diǎn)擊“Start”,會(huì)在“Progress”出顯示進(jìn)度。

圖?318
3.進(jìn)度條中提示成功后,即可在開(kāi)發(fā)板上觀察到相應(yīng)的現(xiàn)象。