⁩⁣⁩⁨ ⁩⁤⁢⁢⁢⁥⁩ ⁥⁣⁦⁡ ⁣⁤⁨ ⁡⁨⁠⁤⁠ ⁦⁧⁡⁤⁣⁡⁡⁨⁤ NrEnE8Gui⁤⁥⁧⁦⁦⁡⁧
⁢⁢⁦⁡⁩⁢⁡
⁣⁧⁡⁤ ⁦⁥⁣⁣ ⁦⁩⁣⁥⁥⁤⁢⁢⁨ ⁥⁤⁦⁢⁦⁦⁠⁠ ⁠⁣ ⁩⁡⁠⁢⁦⁢ J2JwAm⁤⁦⁨⁣⁢⁤⁦⁨ ⁢⁦⁤⁦⁤⁡⁩ ⁧⁨⁨ ⁡⁠⁥⁡⁥⁢⁣ XjPR4LJxih⁧⁨⁦⁠⁥⁧⁩⁠⁥ ⁦⁤⁠⁦⁧⁨⁤⁩
⁦⁢⁨⁤
⁢⁠⁤⁦⁨

⁩⁩⁡

⁤⁧⁩⁧⁩⁠ ⁧⁤⁢⁥⁦⁢⁡ ⁨⁦⁢⁨ FgLr6⁨⁩⁧⁢⁣⁤⁡ ⁤⁤⁩⁤⁤⁡⁧
⁡⁤⁨⁣⁡⁦
⁧⁡⁧⁦
65ggcjb⁥⁤⁧⁡⁤⁦⁧⁤⁣⁥ X9uGXfmv⁨⁦⁦⁤⁧⁨⁧⁧⁥ ⁤⁠⁩⁤
⁩⁨⁧⁩
⁡⁦⁣⁠⁥⁥ ⁩⁧⁡⁥⁨⁨⁡⁧⁧⁨⁠ ⁡⁥⁧⁥⁣⁠⁩⁤⁣ ⁠⁣⁡⁣⁠⁦⁢
WT6nRT1o23⁩⁧⁡⁢⁨⁡
Qdw9KKIo⁨⁧⁣⁧⁦⁥⁩⁨⁠⁡⁨
⁦⁦⁨
⁩⁡⁩⁧⁢⁩⁦⁦ ⁠⁢⁨⁥ ⁨⁩⁥⁥⁣⁩⁧⁤⁣⁦⁡ cl0BI⁩⁦⁩⁣ ⁡⁡⁨⁢⁤⁨⁧
v7yKzer⁣⁨⁠⁨ dcIfNPAm⁠⁣⁠⁨⁩ qlnwC⁤⁥⁦⁤⁠⁤⁤
JvpNiZxt5⁥⁣⁠⁤⁨⁤⁨⁤⁩⁠
ahPko25mQ⁣⁠⁩⁥ ⁠⁩⁤⁨⁩⁩
⁥⁥⁥
⁦⁦⁧⁣⁥⁦⁠⁡
⁧⁦⁧⁤⁩⁢⁡⁤⁢⁧ V5YFmR6G⁤⁩⁥ ⁡⁢⁥

⁧⁨⁡⁩⁣⁡⁥

⁨⁡⁡⁤ ⁨⁤⁧⁩⁥⁧⁤⁣⁤⁣ ⁢⁤⁡⁢⁣⁤ ⁣⁤⁣⁡⁠⁤⁧⁣ ⁧⁥⁧⁧⁥⁣⁢⁦⁡ ⁦⁡⁩ ⁡⁡⁢
⁩⁢⁧⁨⁤⁥⁥⁤
⁦⁥⁧⁣⁠⁩⁠
⁤⁦⁢⁥ ⁩⁦⁦⁦⁢⁧ ⁢⁡⁡⁥⁢⁧
zcJV4txK5⁩⁨⁤⁩⁨⁢
⁢⁣⁤⁦⁥⁤⁩
wpLRd⁨⁣⁨⁩⁧
nWhHw⁤⁦⁩⁣⁨⁨⁠⁩⁥
⁡⁢⁦⁩⁤⁢⁩⁩ ⁥⁡⁠⁠ ⁥⁨⁤⁩⁣⁨⁨ ⁨⁡⁠⁢⁧⁨ ⁠⁠⁧⁠⁩⁧⁢ ⁣⁦⁠ ⁠⁧⁡⁠⁣⁣⁩⁣⁨ ⁤⁤⁥⁨ ⁦⁩⁨⁨ ⁤⁤⁢⁡⁨⁣ ⁤⁡⁡
⁡⁤⁦
⁠⁦⁡ ⁩⁠⁡⁦⁥⁩⁢⁢ 2R9CiQsn2G⁩⁤⁤⁡⁩⁧⁩ ⁣⁩⁥⁩⁥⁩ ⁨⁢⁥ ⁤⁨⁧⁥⁤ ⁩⁥⁠⁥⁢⁡⁠⁩⁥⁠ ⁢⁣⁠⁩⁣⁡ ⁦⁥⁥⁢
⁤⁩⁡⁢⁢⁨⁥
OMxWXh⁡⁦⁥⁦⁢⁦⁥⁩ hiKc3D58Ir⁦⁧⁡⁢ ⁣⁤⁩⁦⁨⁡⁦ ⁤⁥⁨⁩⁥⁡ ⁩⁡⁤⁣⁦⁩ ⁣⁤⁨⁣⁤⁣⁠⁧⁥⁨ ⁤⁠⁩⁠⁩⁤⁡ ⁥⁥⁤⁢⁨⁡⁥⁣ ⁠⁨⁣⁡⁦⁩⁠⁣⁧⁤⁣⁤⁠
    ⁨⁣⁡⁩⁤⁧⁩
⁦⁦⁧⁠⁡⁧⁠
⁩⁩⁡⁩⁨ ⁦⁧⁢⁥⁤⁠⁣ LdJ2mJEioC⁨⁣⁦⁢⁣ ⁣⁣⁥⁢⁠⁧⁡⁧⁠ ⁤⁣⁡⁩⁢ ⁨⁣⁠⁦⁡⁡
⁢⁢⁣⁥⁩⁣⁥⁥⁣
⁡⁡⁨⁨ ⁩⁦⁧⁢⁠⁥⁤⁤⁩⁧ ⁡⁥⁦⁦⁦⁡⁧ ⁧⁥⁨ 0m5W9j⁦⁨⁡⁦⁦⁠⁠ ⁢⁩⁨⁢⁨⁦ ⁧⁠⁣⁩⁨⁥⁩⁠⁠⁩ ⁠⁠⁤⁩⁧⁦⁨⁢⁩⁧⁡⁢⁩
⁥⁥⁣⁢⁨⁡⁤
⁧⁡⁥⁡⁥⁩⁧⁤ ⁨⁡⁢⁠⁤⁦⁥⁠⁦ ⁥⁩⁢⁥⁥⁥⁨ ⁡⁢ ⁥⁦⁩⁧⁧

⁡⁦⁣⁥⁤⁧⁡

⁩⁧⁥⁧⁦⁣⁦⁨⁦⁣ ⁥⁢⁥⁤⁨⁧
⁡⁠⁥⁤⁠⁩
⁢⁧⁩⁧⁥
    ⁡⁡⁦⁠⁡⁢⁧
sTNINeCG⁢⁦⁥
⁢⁩
⁥⁨⁧
cgBAuISw⁦⁠⁩⁥⁠⁡ ⁦⁣⁢⁢⁢⁧ ⁥⁤⁦ RtObD⁢⁠⁧⁩⁨⁢⁢ ⁢⁡⁥⁧⁩ ⁢⁣⁦⁥
⁦⁦⁠⁧⁡⁧⁡⁥⁣

⁢⁢⁣⁣⁥

⁠⁨⁠⁩⁢⁤⁢⁤⁦⁣⁠
    ⁠⁣⁢
⁨⁥⁢⁥⁤ ⁤⁠⁤⁥⁦⁨⁥ ⁣⁧⁤⁥⁤⁩⁡⁩⁤ ⁥⁥⁣⁦⁢ RApFx9⁠⁢⁥⁨⁠⁤⁡⁠⁩ sfszXCv5⁧⁡⁠⁢⁦⁤⁠ 8lejA⁥⁧⁥ ⁠⁡⁠⁨⁦⁧⁠⁣ ⁦⁦⁥ ⁠⁥⁠⁩⁦⁩ ⁨⁩⁠⁡⁣⁦ ⁤⁡⁥⁨⁥⁡ ⁡⁩⁨⁤ ⁤⁩⁧⁦⁢⁠ ⁨⁤⁨⁢⁧⁠⁤⁢ ⁦⁣⁦⁥⁤ bM03⁠⁥⁤⁣⁣⁡⁩⁤ ⁨⁥⁥⁥⁡⁡ ⁧⁩⁩⁤⁠⁢ ⁧⁨⁥⁩ ⁠⁥⁤⁤ ⁤⁣⁢⁡⁡⁣⁣⁩⁧⁠⁦⁢ muoSY1i⁦⁥⁠⁧⁠ ⁩⁥⁦⁠⁦ ⁨⁦⁦⁢ vYTcooXzA⁤⁣⁧⁡⁡⁦⁤
⁨⁠⁧⁨⁤
AYQ3gnMR⁧⁠⁣⁥ ⁦⁢⁤⁧⁤⁩
⁠⁤⁤

xDsToeNDG7⁥⁠⁢

⁧⁨⁥⁨


官方(fāng)論壇
官方(fāng)淘寶(bǎo)
官方(fāng)博客
微信(xìn)公衆号(hào)
點(diǎn)擊聯系(xì)吴工 點(diǎn)擊聯系(xì)周老(lǎo)师(shī)

【案(àn)例】出(chū)租車計(jì)費系(xì)統設計(jì)

發(fà)布(bù)时(shí)間(jiān):2021-06-16   作者(zhě):admin 浏覽量(liàng):

本(běn)文(wén)为(wèi)明(míng)德揚原創及(jí)录(lù)用(yòng)文(wén)章(zhāng),轉(zhuǎn)载請注明(míng)出(chū)处


1.1 總(zǒng)體(tǐ)設計(jì)


1.1.1 概述


    学習了(le)明(míng)德揚至(zhì)簡設計(jì)法和(hé)明(míng)德揚設計(jì)規範,本(běn)人(rén)設計(jì)了(le)一(yī)个(gè)基于(yú)FPGA的(de)出(chū)租車計(jì)費系(xì)統。該系(xì)統由(yóu)一(yī)个(gè)按鍵表(biǎo)示出(chū)租車上(shàng)是(shì)否有(yǒu)乘客,再通(tòng)过(guò)檢测出(chū)租車的(de)檔位和(hé)轮胎的(de)轉(zhuǎn)速来(lái)獲得乘客所(suǒ)需支付的(de)總(zǒng)費用(yòng)。在(zài)本(běn)案(àn)例的(de)設計(jì)过(guò)程中(zhōng),包(bāo)含了(le)按鍵定(dìng)義和(hé)消抖、計(jì)數器、數碼管(guǎn)顯示等技術(shù)。經(jīng)过(guò)逐步改進(jìn)、調試等一(yī)系(xì)列操作之後(hòu),完成(chéng)了(le)此(cǐ)設計(jì),下(xià)面(miàn)将完整的(de)設計(jì)記(jì)录(lù)與(yǔ)大家(jiā)分(fēn)享。

本(běn)工程使用(yòng)VIVADO進(jìn)行仿真(zhēn),未進(jìn)行上(shàng)板。


1.1.2 設計(jì)目标(biāo)


     此(cǐ)設計(jì)可(kě)以(yǐ)完成(chéng)出(chū)租車計(jì)費的(de)功能(néng)。在(zài)按鍵按下(xià)後(hòu)(乘客上(shàng)車),開(kāi)始按如(rú)下(xià)規則計(jì)費:

   起步價5元(yuán),超过(guò)3KM以(yǐ)每公里(lǐ)2元(yuán)計(jì)費,如(rú)果(guǒ)遇到(dào)紅(hóng)綠(lǜ)燈(dēng)、堵車等需要(yào)停車等待时(shí),則以(yǐ)每20分(fēn)鐘(zhōng)1元(yuán)計(jì)費。

     再按一(yī)下(xià)按鍵(乘客下(xià)車)則計(jì)費結束(shù),算出(chū)乘客所(suǒ)需支付的(de)總(zǒng)費用(yòng),并在(zài)數碼管(guǎn)上(shàng)顯示。

1.1.3 系(xì)統結構框图(tú)

     

 系(xì)統結構框图(tú)如(rú)下(xià)所(suǒ)示:



1.1.4 模块(kuài)功能(néng)



  • key模块(kuài)实現(xiàn)功能(néng)


      由(yóu)于(yú)按鍵信(xìn)号(hào)是(shì)异(yì)步信(xìn)号(hào),所(suǒ)以(yǐ)对(duì)該将信(xìn)号(hào)打(dǎ)两(liǎng)拍处理,将异(yì)步信(xìn)号(hào)同(tóng)步化(huà);

      实現(xiàn)10ms按鍵消抖功能(néng),并輸出(chū)按鍵信(xìn)号(hào)key_flag,每按一(yī)次(cì)按鍵,key_flag取(qǔ)反(fǎn)。

    其中(zhōng)key_flag=1表(biǎo)示有(yǒu)乘客,key_flag=0表(biǎo)示沒(méi)有(yǒu)乘客。

  • speed模块(kuài)实現(xiàn)功能(néng)
    通(tòng)过(guò)按鍵信(xìn)号(hào)key_flag有(yǒu)效,对(duì)轮胎轉(zhuǎn)速進(jìn)行每秒(miǎo)取(qǔ)樣(yàng),進(jìn)而(ér)獲得乘客行駛總(zǒng)的(de)路(lù)程和(hé)判斷按时(shí)計(jì)費的(de)使能(néng)信(xìn)号(hào)en_0是(shì)否有(yǒu)效。

  • fare模块(kuài)实現(xiàn)功能(néng)
    通(tòng)过(guò)speed模块(kuài)的(de)總(zǒng)路(lù)程和(hé)按时(shí)計(jì)費有(yǒu)效使能(néng)信(xìn)号(hào)来(lái)獲得乘客所(suǒ)需支付的(de)總(zǒng)費用(yòng),再取(qǔ)得總(zǒng)費用(yòng)的(de)个(gè)位、十(shí)位和(hé)百(bǎi)位數值并輸出(chū)。

  • show模块(kuài)实現(xiàn)功能(néng)
    采用(yòng)動(dòng)态掃描3个(gè)數碼管(guǎn)的(de)方(fāng)式顯示fare模块(kuài)中(zhōng)獲得的(de)三(sān)个(gè)數值即为(wèi)乘客所(suǒ)需支付的(de)總(zǒng)費用(yòng)。

1.1.5 頂层信(xìn)号(hào)
信(xìn)号(hào)名
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
系(xì)統複位
d_w
輸入(rù)
出(chū)租車的(de)檔位信(xìn)号(hào),空挡为(wèi)0,其他(tā)檔位为(wèi)1
rev
輸入(rù)
出(chū)租車轮胎轉(zhuǎn)速信(xìn)号(hào)。通(tòng)过(guò)該信(xìn)号(hào),可(kě)以(yǐ)用(yòng)来(lái)計(jì)算汽車行駛的(de)距離。
key_in
輸入(rù)
乘客上(shàng)、下(xià)車指示信(xìn)号(hào)。
使用(yòng)按鍵来(lái)表(biǎo)示。
seg_sel
輸出(chū)
3个(gè)數碼管(guǎn)的(de)位選信(xìn)号(hào),在(zài)低電(diàn)平是(shì)該位置數碼管(guǎn)亮(liàng)。
segment
輸出(chū)
段(duàn)選信(xìn)号(hào),共(gòng)8位。由(yóu)低到(dào)高(gāo),分(fēn)别表(biǎo)示數碼管(guǎn)的(de)a,b,c,d,e,f,g,點(diǎn)。當該比特(tè)为(wèi)0时(shí),表(biǎo)示點(diǎn)亮(liàng)相應(yìng)位置;为(wèi)1时(shí)熄滅。

1.1.6 頂层代(dài)碼
module taxi_fare(
    clk     ,
    rst_n   ,
    d_w     ,
    rev     ,
    key_in  ,

    seg_sel  ,
    segment  
    );

    input             clk       ;      
    input             rst_n     ;
    input             d_w       ;          //檔位
    input  [15:0]     rev       ;          //轉(zhuǎn)速
    input             key_in    ;          //按鍵,表(biǎo)示乘客是(shì)否上(shàng)車

    output            seg_sel   ;          //位選信(xìn)号(hào),在(zài)低電(diàn)平是(shì)該位置數碼管(guǎn)亮(liàng)。
    output            segment   ;          //段(duàn)選信(xìn)号(hào),共(gòng)8位。由(yóu)低到(dào)高(gāo),分(fēn)别表(biǎo)示數碼管(guǎn)的(de)a,b,c,d,e,f,g,點(diǎn)。當該比特(tè)为(wèi)0时(shí),表(biǎo)示點(diǎn)亮(liàng)相應(yìng)位置;为(wèi)1时(shí)熄滅。

    wire   [3-1:0]      seg_sel    ;
wire   [8-1:0]      segment   ;

    //中(zhōng)間(jiān)量(liàng)
    wire              key_flag   ;         //有(yǒu)乘客为(wèi)1,无乘客为(wèi)0
    wire              en_0      ;        //按时(shí)間(jiān)計(jì)費使能(néng)信(xìn)号(hào)
    wire   [19:0]     distance   ;         //行駛路(lù)程
    wire   [3:0]      x_g        ;         //總(zǒng)費用(yòng)的(de)个(gè)位值
    wire   [3:0]      x_s        ;         //總(zǒng)費用(yòng)的(de)十(shí)位值
    wire   [3:0]      x_b        ;         //總(zǒng)費用(yòng)的(de)百(bǎi)位值

    key_litter key_litter_0(
        .clk        (clk)      ,
        .rst_n      (rst_n)    ,
        .key_in     (key_in)   ,

        .key_flag   (key_flag)
    );

    speed speed_0(
        .clk           (clk)        ,
        .rst_n         (rst_n)      ,
        .d_w           (d_w)        ,
        .rev           (rev)        ,
        .key_flag      (key_flag)   ,
        //輸出(chū)信(xìn)号(hào)
        .en_0          (en_0)       ,
        .distance      (distance)
    );

    fare fare_0(
        .clk           (clk)         ,
        .rst_n         (rst_n)       ,
        .distance      (distance)    ,
        .en_0          (en_0)        ,
        .key_flag      (key_flag)    ,

        .x_g           (x_g)         ,
        .x_s           (x_s)         ,
        .x_b           (x_b)
    );

    show show_0(
        .clk           (clk)            ,
        .rst_n         (rst_n)          ,
        .din           ({x_b,x_s,x_g})  ,
        .din_vld       (3'b111)         ,
        .disp_en       (1)              ,

        .seg_sel       (seg_sel)        ,
        .segment      (segment)   
         );

endmodule


1.2 key模块(kuài)設計(jì)


1.2.1 接口(kǒu)信(xìn)号(hào)

信(xìn)号(hào)
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
系(xì)統複位
key_in
輸入(rù)
按鍵輸入(rù)。使用(yòng)按鍵来(lái)表(biǎo)示乘客上(shàng)、下(xià)車。
key_flag
輸出(chū)
輸出(chū)表(biǎo)示有(yǒu)无乘客。1为(wèi)有(yǒu)乘客,0为(wèi)沒(méi)有(yǒu)乘客



1.2.2 設計(jì)思(sī)路(lù)


    此(cǐ)模块(kuài)通(tòng)过(guò)一(yī)个(gè)按鍵来(lái)表(biǎo)示車上(shàng)是(shì)否有(yǒu)乘客,複位时(shí)輸出(chū)信(xìn)号(hào)key_flag为(wèi)0,當乘客上(shàng)車时(shí),司機(jī)按一(yī)下(xià)按鍵,key_flag由(yóu)0變(biàn),1,表(biǎo)明(míng)乘客已上(shàng)車,系(xì)統開(kāi)始計(jì)費。到(dào)达(dá)目的(de)地(dì)时(shí),司機(jī)再按一(yī)下(xià)按鍵,key_flag由(yóu)1變(biàn)0,表(biǎo)明(míng)到(dào)达(dá)目的(de)地(dì)乘客下(xià)車,系(xì)統結束(shù)計(jì)費。

  • 硬(yìng)件(jiàn)電(diàn)路(lù)

    

    独立式按鍵工作原理如(rú)上(shàng)图(tú)所(suǒ)示,4条(tiáo)輸入(rù)線(xiàn)接到(dào)FPGA的(de)IO口(kǒu)上(shàng),當按鍵K1按下(xià)时(shí),VCC通(tòng)过(guò)電(diàn)阻R1再通(tòng)过(guò)按鍵K1最(zuì)終(zhōng)進(jìn)入(rù)GND形成(chéng)一(yī)条(tiáo)通(tòng)路(lù),这(zhè)条(tiáo)線(xiàn)路(lù)的(de)全(quán)部(bù)電(diàn)壓都加在(zài)R1上(shàng),則引脚P14是(shì)低電(diàn)平。當松開(kāi)按鍵後(hòu),線(xiàn)路(lù)斷開(kāi),就(jiù)不(bù)会(huì)有(yǒu)電(diàn)流通(tòng)过(guò),P14和(hé)VCC就(jiù)應(yìng)該是(shì)等電(diàn)位,为(wèi)高(gāo)電(diàn)平。我(wǒ)们(men)可(kě)以(yǐ)通(tòng)过(guò)P14这(zhè)个(gè)IO口(kǒu)的(de)高(gāo)低電(diàn)平狀态来(lái)判斷是(shì)否有(yǒu)按鍵按下(xià)。其它(tā)按鍵原理與(yǔ)K1一(yī)致(zhì),當然本(běn)实验(yàn)只(zhī)需要(yào)一(yī)个(gè)按鍵即可(kě),任選一(yī)个(gè)按鍵都可(kě)以(yǐ)。


    從图(tú)中(zhōng)可(kě)以(yǐ)看(kàn)出(chū),如(rú)果(guǒ)我(wǒ)们(men)按下(xià)按鍵,那(nà)麼(me)按鍵就(jiù)会(huì)接通(tòng)并連(lián)接到(dào)電(diàn)平GND,如(rú)果(guǒ)我(wǒ)们(men)沒(méi)有(yǒu)按下(xià),那(nà)麼(me)按鍵就(jiù)会(huì)斷開(kāi)并接到(dào)VCC因(yīn)此(cǐ)按鍵为(wèi)低電(diàn)平有(yǒu)效。通(tòng)常的(de)按鍵所(suǒ)用(yòng)開(kāi)關(guān)为(wèi)機(jī)械弹性(xìng)開(kāi)關(guān),當機(jī)械觸點(diǎn)斷開(kāi)或(huò)者(zhě)閉合时(shí),由(yóu)于(yú)機(jī)械觸點(diǎn)的(de)弹性(xìng)作用(yòng),一(yī)个(gè)按鍵開(kāi)關(guān)在(zài)閉合时(shí)不(bù)会(huì)马上(shàng)稳定(dìng)地(dì)接通(tòng),在(zài)斷開(kāi)时(shí)也(yě)不(bù)会(huì)一(yī)下(xià)子斷開(kāi)。因(yīn)而(ér)機(jī)械式按鍵在(zài)閉合及(jí)斷開(kāi)的(de)瞬間(jiān)均伴随有(yǒu)一(yī)連(lián)串的(de)抖動(dòng),如(rú)果(guǒ)不(bù)進(jìn)行处理,会(huì)使系(xì)統識别到(dào)抖動(dòng)信(xìn)号(hào)而(ér)進(jìn)行不(bù)必要(yào)的(de)反(fǎn)應(yìng),導致(zhì)模块(kuài)功能(néng)不(bù)正(zhèng)常,为(wèi)了(le)避免这(zhè)種(zhǒng)現(xiàn)象(xiàng)的(de)産生(shēng),需要(yào)進(jìn)行按鍵消抖的(de)操作。

  • 按鍵消抖
    按鍵消抖主(zhǔ)要(yào)分(fēn)为(wèi)硬(yìng)件(jiàn)消抖和(hé)软(ruǎn)件(jiàn)消抖。两(liǎng)个(gè)與(yǔ)非(fēi)門(mén)構成(chéng)一(yī)个(gè)RS觸發(fà)器为(wèi)常用(yòng)的(de)硬(yìng)件(jiàn)软(ruǎn)件(jiàn)方(fāng)法抖,即檢测出(chū)鍵閉合後(hòu)執行一(yī)个(gè)延时(shí)程序,抖動(dòng)时(shí)間(jiān)的(de)长短(duǎn)由(yóu)按鍵的(de)機(jī)械特(tè)性(xìng)決定(dìng),一(yī)般为(wèi)5ms20ms讓前(qián)沿抖動(dòng)消失後(hòu)再一(yī)次(cì)檢测鍵的(de)狀态,如(rú)果(guǒ)仍保持(chí)閉合狀态電(diàn)平,則确認按下(xià)按鍵操作有(yǒu)效。當檢测到(dào)按鍵釋放(fàng)後(hòu),也(yě)要(yào)給(gěi)5ms20ms的(de)延时(shí),待後(hòu)沿抖動(dòng)消失後(hòu)才能(néng)轉(zhuǎn)入(rù)該鍵的(de)处理程序。經(jīng)过(guò)按鍵消抖的(de)行人(rén)优先(xiān)按鍵,判斷按鍵有(yǒu)效後(hòu),按鍵信(xìn)号(hào)傳遞給(gěi)控制系(xì)統,控制系(xì)統再進(jìn)入(rù)相應(yìng)的(de)处理程序。如(rú)還(huán)不(bù)明(míng)白之处,見(jiàn)实验(yàn)的(de)PDF。





图(tú)5.1.2按鍵消抖示意(yì)图(tú)


1.2.3 參考代(dài)碼


    使用(yòng)明(míng)德揚的(de)計(jì)數器模板,可(kě)以(yǐ)很快(kuài)速很熟練地(dì)写出(chū)按鍵消抖模块(kuài)。

    每10ms掃描一(yī)次(cì)按鍵輸入(rù)key_in,可(kě)以(yǐ)达(dá)到(dào)消抖的(de)目的(de),再用(yòng)寄存器緩存一(yī)下(xià),按鍵为(wèi)低電(diàn)平有(yǒu)效;但本(běn)实验(yàn)是(shì)需要(yào)按鍵按下(xià)松開(kāi)这(zhè)樣(yàng)一(yī)次(cì)完整的(de)按按鍵操作後(hòu)輸出(chū)key_flag才發(fà)生(shēng)變(biàn)化(huà),所(suǒ)以(yǐ)檢测當檢测到(dào)按鍵有(yǒu)上(shàng)升(shēng)沿變(biàn)化(huà)时(shí),代(dài)表(biǎo)該按鍵被(bèi)按下(xià)松開(kāi),按鍵輸出(chū)key_flag才發(fà)生(shēng)變(biàn)化(huà)。

  本(běn)模块(kuài)設計(jì)了(le)一(yī)个(gè)狀态機(jī),用(yòng)于(yú)按鍵的(de)檢测。該狀态機(jī)共(gòng)包(bāo)括4个(gè)狀态。


  其各(gè)个(gè)狀态的(de)含義如(rú)下(xià)。


  空閑狀态(IDLE):表(biǎo)示按鍵沒(méi)有(yǒu)被(bèi)按下(xià),檢测到(dào)低電(diàn)平進(jìn)入(rù)下(xià)一(yī)狀态。

  延时(shí)确認狀态(S1):開(kāi)始10ms延时(shí)計(jì)數,若計(jì)數完成(chéng)且依然为(wèi)低電(diàn)平則進(jìn)入(rù)下(xià)一(yī)狀态,若計(jì)數期(qī)間(jiān)按鍵出(chū)現(xiàn)高(gāo)電(diàn)平说(shuō)明(míng)为(wèi)抖動(dòng)回(huí)到(dào)初始狀态。

  檢测釋放(fàng)狀态(S2):表(biǎo)示按鍵按下(xià)未松開(kāi),檢测到(dào)高(gāo)電(diàn)平進(jìn)入(rù)下(xià)一(yī)狀态。

  延时(shí)确認狀态(S3):開(kāi)始10ms延时(shí)計(jì)數,若計(jì)數完成(chéng)且依然为(wèi)高(gāo)電(diàn)平視为(wèi)有(yǒu)效松手(shǒu)行为(wèi)進(jìn)入(rù)初始狀态再檢测下(xià)一(yī)次(cì)按鍵按下(xià),若計(jì)數期(qī)間(jiān)按鍵出(chū)現(xiàn)低電(diàn)平说(shuō)明(míng)为(wèi)抖動(dòng)回(huí)到(dào)S2狀态。

   代(dài)碼如(rú)下(xià):

module key_litter(
    clk    ,
    rst_n  ,
    key_in ,

    key_flag
    );

    //消抖的(de)狀态
    parameter      IDLE  =  4'b0000 ;
    parameter      S1  =  4'b0001   ;
    parameter      S2  =  4'b0010   ;
    parameter      S3  =  4'b0100   ;
    parameter      S4  =  4'b1000   ;

    //輸入(rù)信(xìn)号(hào)定(dìng)義
    input               clk    ;
    input               rst_n  ;
    input               key_in ;

    //輸出(chū)信(xìn)号(hào)定(dìng)義
    output              key_flag;                      //輸出(chū),表(biǎo)示是(shì)否有(yǒu)乘客

    //輸出(chū)信(xìn)号(hào)reg定(dìng)義
    reg                 key_flag;

    //中(zhōng)間(jiān)信(xìn)号(hào)定(dìng)義
    reg   [19:0]        cnt     ;

    reg                 key_in_1;                      //寄存器
    reg                 key_in_2;                      //寄存器

    reg         [3:0]        state_c ;
    reg         [3:0]        state_n ;

    wire                 idl2s1_start  ;
    wire                 s12s2_start   ;
    wire                 s12s2_end     ;
    wire                 s22s3_start   ;
    wire                 s32s4_start   ;
    wire                 s32s4_end     ;

    wire                add_cnt       ;                 //計(jì)數進(jìn)行
    wire                end_cnt       ;                 //計(jì)數清(qīng)零(líng)
    wire                cnt_during    ;                 //計(jì)數过(guò)程中(zhōng)

    //打(dǎ)两(liǎng)拍
    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            key_in_1 <= 0;
            key_in_2 <= 0;
        end
        else begin
            key_in_1 <= key_in;
            key_in_2 <= key_in_1;
        end
    end

    //消抖
    //四(sì)段(duàn)式狀态機(jī)

    //第(dì)一(yī)段(duàn):同(tóng)步时(shí)序always模块(kuài),格式化(huà)描述次(cì)态寄存器遷移到(dào)現(xiàn)态寄存器(不(bù)需更(gèng)改)
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            state_c <= IDLE;
        end
        else begin
            state_c <= state_n;
        end
    end
    //第(dì)二(èr)段(duàn):組合邏輯always模块(kuài),描述狀态轉(zhuǎn)移条(tiáo)件(jiàn)判斷
    always@(*)begin
        case(state_c)
            IDLE:begin
                if(idl2s1_start)begin
                    state_n = S1;
                end
                else begin
                    state_n = state_c;
                end
            end
            S1:begin
                if(s12s2_start)begin
                    state_n = S2;
                end
                else if(s12s2_end)begin
                   state_n = IDLE ;
                end
                else begin
                    state_n = state_c;
                end
            end
            S2:begin
                if(s22s3_start)begin
                    state_n = S3;
                end
                else begin
                    state_n = state_c;
                end
            end
            S3:begin
                if(s32s4_start)begin
                    state_n = IDLE;
                end
                else if(s32s4_end)begin
                    state_n = S2;
                end
                else begin
                    state_n = state_c;
                end
            end
            default:begin
                state_n = IDLE;
            end
        endcase
    end
    //第(dì)三(sān)段(duàn):設計(jì)轉(zhuǎn)移条(tiáo)件(jiàn)
    assign idl2s1_start  =  key_in_2 == 0;
    assign s12s2_start =    key_in_2==0 && end_cnt == 1;
    assign s12s2_end  =     key_in_2==1 && cnt_during ;
    assign s22s3_start  =   key_in_2 == 1;
    assign s32s4_start =    key_in_2 == 1 && end_cnt == 1;
    assign s32s4_end  =     key_in_2 == 0 && cnt_during ;
    //第(dì)四(sì)段(duàn):同(tóng)步时(shí)序always模块(kuài),格式化(huà)描述寄存器輸出(chū)(可(kě)有(yǒu)多(duō)个(gè)輸出(chū))
    always  @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            key_flag <=1'b0 ;     //初始化(huà)
        end
        else if(s32s4_start)begin
            key_flag = ~key_flag;
        end
        else begin
            key_flag <= key_flag;
        end
    end

    //計(jì)數器,計(jì)數10ms
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= 0;
        end
        else if(add_cnt)begin
            if(end_cnt)
                cnt <= 0;
            else
                cnt <= cnt + 1;
        end
        else
            cnt <= 0;
    end
    assign add_cnt = state_c == S1 || state_c == S3;      
    assign end_cnt = add_cnt && cnt== /*仿真(zhēn)时(shí)使用(yòng)以(yǐ)減少(shǎo)仿真(zhēn)时(shí)間(jiān)5 - 1;*/ 500000-1;  
    assign cnt_during = add_cnt && end_cnt == 0;  

    endmodule



1.3 speed模块(kuài)設計(jì)


1.3.1 接口(kǒu)信(xìn)号(hào)

信(xìn)号(hào)
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
系(xì)統複位
d_w
輸入(rù)
出(chū)租車檔位信(xìn)号(hào),空挡为(wèi)0、其他(tā)檔位为(wèi)1
rev
輸入(rù)
出(chū)租車轮胎轉(zhuǎn)速信(xìn)号(hào)。通(tòng)过(guò)該信(xìn)号(hào),可(kě)以(yǐ)用(yòng)来(lái)計(jì)算汽車行駛的(de)距離。
key_flag
輸入(rù)
表(biǎo)示有(yǒu)无乘客上(shàng)車,有(yǒu)乘客为(wèi)1,沒(méi)有(yǒu)为(wèi)0
en_o
輸出(chū)
表(biǎo)示出(chū)租車按时(shí)間(jiān)計(jì)費信(xìn)号(hào),1位按时(shí)間(jiān)計(jì)費,0則不(bù)按时(shí)間(jiān)計(jì)費。等待紅(hóng)綠(lǜ)燈(dēng)或(huò)堵車等需要(yào)停車过(guò)程中(zhōng),使用(yòng)时(shí)間(jiān)計(jì)費;行駛过(guò)程中(zhōng),使用(yòng)距離計(jì)費。
distance
輸出(chū)
輸出(chū)乘客乘坐的(de)總(zǒng)路(lù)程



1.3.2 設計(jì)思(sī)路(lù)


   消抖後(hòu)的(de)按鍵信(xìn)号(hào)輸入(rù)到(dào)本(běn)模块(kuài)中(zhōng),同(tóng)樣(yàng)使用(yòng)明(míng)德揚至(zhì)簡設計(jì)法和(hé)計(jì)數器模板,可(kě)以(yǐ)快(kuài)速写出(chū)計(jì)算總(zǒng)路(lù)程和(hé)獲得按时(shí)計(jì)費信(xìn)号(hào)en_0有(yǒu)效的(de)代(dài)碼。當key_flag为(wèi)1有(yǒu)效且轉(zhuǎn)速rev>=3r/s时(shí),計(jì)數器開(kāi)始計(jì)數,每計(jì)一(yī)秒(miǎo)鐘(zhōng)对(duì)轉(zhuǎn)速信(xìn)号(hào)rev取(qǔ)樣(yàng),獲得每秒(miǎo)行駛路(lù)程并累加,當key_flag为(wèi)0时(shí),計(jì)數停止,累加也(yě)停止,此(cǐ)时(shí)獲得的(de)累加值即为(wèi)總(zǒng)路(lù)程。當key_flag为(wèi)1有(yǒu)效且rev<3r/s时(shí),en_0拉高(gāo)为(wèi)1,表(biǎo)示此(cǐ)时(shí)需要(yào)按时(shí)計(jì)費。


1.3.3 參考代(dài)碼
module speed(
    clk    ,
    rst_n  ,
    d_w    ,
    rev    ,
    key_flag,
    //輸出(chū)信(xìn)号(hào)
    en_0   ,
    distance
    );

    //參數定(dìng)義
    parameter      DATA_W =         20;

    //輸入(rù)信(xìn)号(hào)定(dìng)義
    input               clk    ;
    input               rst_n  ;
    input               d_w    ;                         //檔位
    input               rev    ;                         //轉(zhuǎn)速
    input               key_flag;                        //有(yǒu)无乘客信(xìn)号(hào)

    //輸入(rù)信(xìn)号(hào)定(dìng)義
    wire       [15:0]  rev    ;
    //輸出(chū)信(xìn)号(hào)定(dìng)義
    output[DATA_W-1:0]  distance   ;                     //路(lù)程
    output              en_0       ;                     //按时(shí)計(jì)費信(xìn)号(hào)

    //輸出(chū)信(xìn)号(hào)reg定(dìng)義
    reg   [DATA_W-1:0]  distance   ;
    reg                 en_0       ;

    //中(zhōng)間(jiān)信(xìn)号(hào)定(dìng)義
    reg    [15:0]       rev_1      ;                     //每秒(miǎo)取(qǔ)樣(yàng)轉(zhuǎn)速信(xìn)号(hào)
    reg   [25:0]        cnt        ;                     //一(yī)秒(miǎo)的(de)計(jì)數器

    wire                high_en_0  ;                     //拉高(gāo)按时(shí)計(jì)費信(xìn)号(hào)的(de)信(xìn)号(hào)
    wire                add_cnt    ;
    wire                end_cnt    ;

    //按时(shí)計(jì)費
    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            en_0 <= 0;
        end
        else if(high_en_0) begin
            en_0 <= 1;
        end
        else
            en_0 <= 0;
    end
    assign high_en_0 = ( d_w == 0 && rev < 3 || rev < 3 ) && key_flag == 1;

    //計(jì)數1秒(miǎo)
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= 0;
        end
        else if(add_cnt)begin
            if(end_cnt)
                cnt <= 0;
            else
                cnt <= cnt + 1;
        end
        else if(key_flag == 0)
            cnt <= 0;
    end
    assign add_cnt = rev >= 3 && key_flag == 1;      
    assign end_cnt = add_cnt && cnt ==  /*仿真(zhēn)时(shí)使用(yòng)以(yǐ)节(jié)省(shěng)仿真(zhēn)时(shí)間(jiān)500-1;*/50000000-1 ;  

    //每秒(miǎo)取(qǔ)樣(yàng)rev
    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            rev_1 <= 0;
        end
        else if(end_cnt) begin
            rev_1 <= rev;
        end
    end

    //distance
    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            distance <= 0;
        end
        else if(end_cnt) begin
            distance <=distance +  rev_1/3;
        end
    end

    endmodule

1.4 fare模块(kuài)設計(jì)


1.4.1 接口(kǒu)信(xìn)号(hào)


信(xìn)号(hào)
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
系(xì)統複位
distance
輸入(rù)
乘客乘坐總(zǒng)路(lù)程
en_0
輸入(rù)
按时(shí)間(jiān)計(jì)費信(xìn)号(hào),1为(wèi)按时(shí)間(jiān)計(jì)費,0为(wèi)不(bù)按时(shí)間(jiān)計(jì)費
key_flag
輸入(rù)
表(biǎo)示是(shì)否有(yǒu)乘客,有(yǒu)为(wèi)1,沒(méi)有(yǒu)为(wèi)0,且在(zài)沒(méi)有(yǒu)乘客时(shí),所(suǒ)有(yǒu)信(xìn)号(hào)歸0
x_g
輸出(chū)
輸出(chū)總(zǒng)費用(yòng)的(de)个(gè)位數值
x_s
輸出(chū)
輸出(chū)總(zǒng)費用(yòng)的(de)十(shí)位數值
x_b
輸出(chū)
輸出(chū)總(zǒng)費用(yòng)的(de)百(bǎi)位數值



1.4.2 設計(jì)思(sī)路(lù)


     從speed模块(kuài)中(zhōng)得到(dào)乘客乘坐總(zǒng)路(lù)程distance和(hé)按时(shí)計(jì)費使能(néng)信(xìn)号(hào)en_0,然後(hòu)以(yǐ)5元(yuán)起步價,超过(guò)3KM以(yǐ)每滿1公里(lǐ)2元(yuán)的(de)計(jì)費方(fāng)式計(jì)算出(chū)按路(lù)程計(jì)費的(de)總(zǒng)費用(yòng),再通(tòng)过(guò)en_020分(fēn)鐘(zhōng)1元(yuán)的(de)計(jì)費方(fāng)式計(jì)算出(chū)按时(shí)間(jiān)計(jì)費的(de)總(zǒng)費用(yòng),再求和(hé)獲得總(zǒng)費用(yòng),最(zuì)後(hòu)得到(dào)總(zǒng)費用(yòng)得个(gè)位、十(shí)位、百(bǎi)位,分(fēn)别是(shì)x_gx_sx_b

1.4.3 參考代(dài)碼

module fare(
    clk    ,
    rst_n  ,
    distance,
    en_0   ,
    key_flag,

    x_g    ,
    x_s    ,
    x_b   
    );

    //參數定(dìng)義
    parameter      DATA_W =         4;

    //輸入(rù)信(xìn)号(hào)定(dìng)義
    input               clk    ;
    input               rst_n  ;

    input               en_0   ;                           //按时(shí)計(jì)費
    input   [19:0]      distance;                          //路(lù)程
    input               key_flag;                          //有(yǒu)无乘客

    //輸出(chū)信(xìn)号(hào)定(dìng)義
    output[DATA_W-1:0]  x_g    ;                           //數碼管(guǎn)顯示个(gè)位
    output[DATA_W-1:0]  x_s    ;                           //數碼管(guǎn)顯示十(shí)位
    output[DATA_W-1:0]  x_b    ;                           //數碼管(guǎn)顯示百(bǎi)位



    //輸出(chū)信(xìn)号(hào)reg定(dìng)義
    reg   [DATA_W-1:0]  x_g    ;
    reg   [DATA_W-1:0]  x_s    ;
    reg   [DATA_W-1:0]  x_b    ;

    //中(zhōng)間(jiān)信(xìn)号(hào)定(dìng)義
    reg   [9:0]              taxi_fare  ;                   //總(zǒng)車費
    reg   [9:0]              taxi_fare_1;                   //按路(lù)程車費
    reg   [9:0]              taxi_fare_2;                   //按时(shí)間(jiān)車費
    reg   [35:0]             cnt        ;                   //計(jì)數20分(fēn)鐘(zhōng)
    reg                      key_flag1  ;                   //寄存器
    reg                      key_flag2  ;                   //寄存器
    reg                      key_flag_low  ;                //乘客下(xià)車信(xìn)号(hào)
    reg                      key_flag_low1 ;                //乘客下(xià)車後(hòu)隔一(yī)个(gè)时(shí)鐘(zhōng)周期(qī)信(xìn)号(hào)
    reg   [2:0]              state      ;

    wire                 add_taxi_fare_1;                  
    wire                 add_taxi_fare_2;
    wire                 add_cnt        ;
    wire                 end_cnt        ;

    //獲取(qǔ)key_flag下(xià)降沿,表(biǎo)示乘客下(xià)車
    always@(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            key_flag1 <= 0;
        end
        else begin
            key_flag1 <= key_flag;
        end
    end
    always@(posedge clk or negedge rst_n)begin
            if(rst_n==1'b0)begin
                key_flag2 <= 0;
            end
            else begin
                key_flag2 <= key_flag1;
            end
        end
    always@(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            key_flag_low <= 0;
        end
        else if(key_flag2==1&&key_flag1==0)begin
            key_flag_low <= 1;
        end
        else begin
            key_flag_low <= 0;
        end
    end

    always@(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            key_flag_low1 <= 0;
        end
        else
            key_flag_low1 <= key_flag_low;
    end

    //按路(lù)程計(jì)費
    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            taxi_fare_1 <= 0;
        end
        else if(add_taxi_fare_1)begin
            if(distance<=3000)begin
                taxi_fare_1 <= 5;
            end
            else if(distance>3000)begin
                taxi_fare_1 <= 3'd5+ (distance-3000) / 500;//* 0.002;               
            end
        end
    end
    assign add_taxi_fare_1 = key_flag_low && en_0 == 0 ;

    //按时(shí)間(jiān)計(jì)費
    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            taxi_fare_2 <= 0;
        end
        else if(add_taxi_fare_2)begin
            taxi_fare_2 <= taxi_fare_2 + 1;
        end
    end
    assign add_taxi_fare_2 = end_cnt == 1;

    //計(jì)數20分(fēn)鐘(zhōng)
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= 0;
        end
        else if(add_cnt)begin
            if(end_cnt)
                cnt <= 0;
            else
                cnt <= cnt + 1;
        end
    end
    assign add_cnt = en_0 == 1 && key_flag == 1;      
    assign end_cnt = add_cnt && cnt== /*仿真(zhēn)时(shí)使用(yòng)以(yǐ)节(jié)省(shěng)仿真(zhēn)时(shí)間(jiān)500*1200-1;*/ 50000000*1200-1;  

    //獲得總(zǒng)車費
    always@(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            taxi_fare <= 0;
        end
        else if(key_flag_low1==1)begin  
            taxi_fare <= taxi_fare_1+ taxi_fare_2;
        end
    end

    //輸出(chū)
    always  @(*)begin
        if(rst_n == 1'b0)begin
            x_g <= 0;
            x_s <= 0;
            x_b <= 0;
            state <= 1;
        end
        else if(taxi_fare != 0)begin
            case(state)
            1: begin  x_g <= taxi_fare%10;taxi_fare <= taxi_fare/10;state <= 2;end
            2: begin  x_s <= taxi_fare%10;taxi_fare <= taxi_fare/10;state <= 3;end
            3: begin  x_b <= taxi_fare%10;taxi_fare <= taxi_fare/10;state <= 1;end
            endcase
        end
      end

    endmodule




1.5 show模块(kuài)設計(jì)


1.5.1 接口(kǒu)信(xìn)号(hào)


信(xìn)号(hào)
接口(kǒu)方(fāng)向(xiàng)
定(dìng)義
clk
輸入(rù)
系(xì)統时(shí)鐘(zhōng)
rst_n
輸入(rù)
系(xì)統複位
disp_en
輸入(rù)
打(dǎ)開(kāi)數碼管(guǎn)顯示的(de)使能(néng)信(xìn)号(hào)。1表(biǎo)示打(dǎ)開(kāi)顯示,0表(biǎo)示不(bù)顯示。
din
輸入(rù)
輸入(rù)總(zǒng)費用(yòng){x_bx_s,x_g}
din_vld
輸入(rù)
數碼管(guǎn)顯示數據(jù)刷新使能(néng)信(xìn)号(hào)。當其值为(wèi)1有(yǒu)效时(shí),刷新要(yào)顯示的(de)數據(jù)值。
seg_sel
輸出(chū)
3个(gè)數碼管(guǎn)的(de)位選信(xìn)号(hào),在(zài)低電(diàn)平是(shì)該位置數碼管(guǎn)亮(liàng)。
segment
輸出(chū)
段(duàn)選信(xìn)号(hào),共(gòng)8位。由(yóu)低到(dào)高(gāo),分(fēn)别表(biǎo)示數碼管(guǎn)的(de)a,b,c,d,e,f,g,點(diǎn)。當該比特(tè)为(wèi)0时(shí),表(biǎo)示點(diǎn)亮(liàng)相應(yìng)位置;为(wèi)1时(shí)熄滅。



1.5.2 設計(jì)思(sī)路(lù)


    由(yóu)于(yú)在(zài)fare模块(kuài)中(zhōng)已經(jīng)獲得總(zǒng)費用(yòng)的(de)个(gè)位、十(shí)位和(hé)百(bǎi)位的(de)值,所(suǒ)以(yǐ)在(zài)本(běn)模块(kuài)只(zhī)需要(yào)控制3个(gè)數碼管(guǎn)对(duì)其數值進(jìn)行顯示即可(kě)。

    本(běn)模块(kuài)在(zài)設計(jì)过(guò)程中(zhōng)采用(yòng)動(dòng)态掃描3个(gè)數碼管(guǎn)的(de)方(fāng)式進(jìn)行顯示,并且直(zhí)接使用(yòng)明(míng)德楊提(tí)供的(de)數碼管(guǎn)顯示規範代(dài)碼。動(dòng)态掃描方(fāng)式相比于(yú)使用(yòng)3个(gè)独立的(de)數碼管(guǎn)顯示会(huì)节(jié)約資源,硬(yìng)件(jiàn)電(diàn)路(lù)更(gèng)簡單,且數碼管(guǎn)越多(duō)优勢越明(míng)顯。


1.5.3 參考代(dài)碼

接口(kǒu)定(dìng)義:
clk               : 时(shí)鐘(zhōng)信(xìn)号(hào),頻率是(shì)50MHz
rst_n             : 複位信(xìn)号(hào),在(zài)低電(diàn)平时(shí)有(yǒu)效
seg_sel        : 位選信(xìn)号(hào),在(zài)低電(diàn)平是(shì)該位置數碼管(guǎn)亮(liàng)。
segment       : 段(duàn)選信(xìn)号(hào),共(gòng)8位。由(yóu)低到(dào)高(gāo),分(fēn)别表(biǎo)示數碼管(guǎn)的(de)a,b,c,d,e,f,g,點(diǎn)。當該比特(tè)为(wèi)0时(shí),表(biǎo)示點(diǎn)亮(liàng)相應(yìng)位置;为(wèi)1时(shí)熄滅。
**********old.mdy-edu.com 明(míng)德揚科教注釋結束(shù)****************/

module  show(
                 rst_n       ,
                 clk         ,
                 disp_en     ,
                 din         ,
                 din_vld     ,

                 seg_sel     ,
                 segment      
             );

/*********old.mdy-edu.com 明(míng)德揚科教注釋開(kāi)始****************
參數定(dìng)義,明(míng)德揚規範要(yào)求,verilog內(nèi)的(de)用(yòng)到(dào)的(de)數字(zì),都使用(yòng)參數表(biǎo)示。
參數信(xìn)号(hào)全(quán)部(bù)大写
**********old.mdy-edu.com 明(míng)德揚科教注釋結束(shù)****************/

parameter  SEG_WID        =       8;
parameter  SEG_NUM        =       3;
parameter  COUNT_WID      =       26;
parameter  TIME_20US      =       20'd1000;


parameter  NUM_0          =       8'b1100_0000;
parameter  NUM_1          =       8'b1111_1001;
parameter  NUM_2          =       8'b1010_0100;
parameter  NUM_3          =       8'b1011_0000;
parameter  NUM_4          =       8'b1001_1001;
parameter  NUM_5          =       8'b1001_0010;
parameter  NUM_6          =       8'b1000_0010;
parameter  NUM_7          =       8'b1111_1000;
parameter  NUM_8          =       8'b1000_0000;
parameter  NUM_9          =       8'b1001_0000;
parameter  NUM_F          =       8'b1011_1111;
parameter  NUM_ERR        =       8'b1000_0110;


input                             clk       ;
input                             rst_n     ;
input                             disp_en   ;
input  [SEG_NUM*4-1:0]            din       ;
input  [SEG_NUM-1:0]              din_vld   ;
output [SEG_NUM-1:0]              seg_sel   ;
output [SEG_WID-1:0]              segment   ;

reg    [SEG_NUM-1:0]              seg_sel   ;
reg    [SEG_WID-1:0]              segment   ;
reg    [COUNT_WID-1:0]            cnt0      ;
wire                              add_cnt0  ;
wire                              end_cnt0  ;
reg    [SEG_NUM-1:0]              cnt1      ;
wire                              add_cnt1  ;
wire                              end_cnt1  ;
reg    [4*SEG_NUM-1:0]            din_ff0   ;
reg    [        4-1:0]            seg_tmp   ;
wire                              flag_20us ;
integer                           ii        ;


always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt0 <= 0;
    end
    else if(add_cnt0)begin
        if(end_cnt0)
            cnt0 <= 0;
        else
            cnt0 <= cnt0 + 1;
    end
end

assign add_cnt0 = 1;
assign end_cnt0 = add_cnt0 && cnt0==TIME_20US-1 ;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt1 <= 0;
    end
    else if(add_cnt1)begin
        if(end_cnt1)
            cnt1 <= 0;
        else
            cnt1 <= cnt1 + 1;
    end
end

assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1==SEG_NUM-1 ;

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        seg_sel <= {SEG_NUM{1'b1}};
    end
    else if(disp_en)
        seg_sel <= ~(1'b1 << cnt1);
    else
        seg_sel <= {SEG_NUM{1'b1}};
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        din_ff0 <= 0;
    end
    else begin
        for(ii=0;ii<SEG_NUM;ii=ii+1)begin
            if(din_vld[ii]==1'b1)begin
                din_ff0[(ii+1)*4-1 -:4] <= din[(ii+1)*4-1 -:4];
            end
            else begin
                din_ff0[(ii+1)*4-1 -:4] <= din_ff0[(ii+1)*4-1 -:4];
            end
        end
    end
end

always  @(*)begin
    seg_tmp = din_ff0[(cnt1+1)*4-1 -:4];
end


always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        segment<=NUM_0;
    end
    else if(seg_tmp==0)begin
          segment<=NUM_0;
    end
    else if(seg_tmp==1)begin
          segment<=NUM_1;
     end
    else if(seg_tmp==2)begin
          segment<=NUM_2;
    end
    else if(seg_tmp==3)begin
          segment<=NUM_3;
    end
    else if(seg_tmp==4)begin
          segment<=NUM_4;
    end
    else if(seg_tmp==5)begin
          segment<=NUM_5;
    end
    else if(seg_tmp==6)begin
          segment<=NUM_6;
    end
    else if(seg_tmp==7)begin
          segment<=NUM_7;
    end
    else if(seg_tmp==8)begin
          segment<=NUM_8;
    end
    else if(seg_tmp==9)begin
          segment<=NUM_9;
    end
    else if(seg_tmp==4'hf)begin
          segment<=NUM_F;
    end
    else begin
        segment<=NUM_ERR;   
    end
end

endmodule




1.6 效果(guǒ)和(hé)總(zǒng)結



  • 仿真(zhēn)验(yàn)證特(tè)殊说(shuō)明(míng):


    由(yóu)于(yú)本(běn)系(xì)統涉及(jí)1秒(miǎo)、20分(fēn)鐘(zhōng)等时(shí)間(jiān)节(jié)點(diǎn),时(shí)間(jiān)很长,所(suǒ)以(yǐ)在(zài)仿真(zhēn)时(shí)有(yǒu)一(yī)定(dìng)的(de)困難,为(wèi)此(cǐ)我(wǒ)将系(xì)統中(zhōng)的(de)时(shí)間(jiān)节(jié)點(diǎn)全(quán)部(bù)乘上(shàng)10^-5),讓所(suǒ)有(yǒu)狀态提(tí)前(qián)到(dào)达(dá),方(fāng)便我(wǒ)们(men)仿真(zhēn)验(yàn)證。

    由(yóu)于(yú)乘上(shàng)了(le)10^-5),所(suǒ)以(yǐ)原消抖10ms在(zài)仿真(zhēn)中(zhōng)为(wèi)100ns

    系(xì)統中(zhōng)原1s取(qǔ)樣(yàng)轉(zhuǎn)速rev在(zài)仿真(zhēn)中(zhōng)为(wèi)10us;
    原按时(shí)計(jì)費20分(fēn)鐘(zhōng)/元(yuán)在(zài)仿真(zhēn)中(zhōng)为(wèi)12ms/元(yuán);



  • 测試文(wén)件(jiàn)和(hé)理論計(jì)算
    在(zài)测試文(wén)件(jiàn)中(zhōng)轉(zhuǎn)速rev>=3r/s的(de)时(shí)間(jiān)是(shì)50000000ns

    總(zǒng)路(lù)程distance=15/3*50000000/10000=25km;

    由(yóu)于(yú)在(zài)测試文(wén)件(jiàn)中(zhōng)按鍵消抖有(yǒu)一(yī)段(duàn)时(shí)間(jiān)且这(zhè)一(yī)段(duàn)时(shí)間(jiān)在(zài)rev>=3r/s的(de)时(shí)間(jiān)內(nèi),所(suǒ)以(yǐ)系(xì)統实際对(duì)速度(dù)采樣(yàng)的(de)次(cì)數会(huì)少(shǎo)一(yī)次(cì),所(suǒ)以(yǐ)最(zuì)終(zhōng)的(de)總(zǒng)路(lù)程会(huì)少(shǎo)5m

    所(suǒ)以(yǐ),按路(lù)程計(jì)費的(de)總(zǒng)費用(yòng)taxi_fare_1=5+25 - 3*2 – 0.005*2=48.99(元(yuán));

    去(qù)除小數部(bù)分(fēn)taxi_fare_1=48(元(yuán));

    在(zài)测試文(wén)件(jiàn)中(zhōng)轉(zhuǎn)速rev<3r/s的(de)时(shí)間(jiān)是(shì)24000000ns;

    按时(shí)間(jiān)計(jì)費的(de)總(zǒng)費用(yòng)taxi_fare_2=24000000/12000000=2(元(yuán));

    所(suǒ)以(yǐ)總(zǒng)車費taxi_fare_1=taxi_fare_1+taxi_fare_2=50(元(yuán));


`define clk_period 20
module taxi_fare_tb(

    );

    reg             clk       ;
    reg             rst_n     ;
    reg             d_w       ;
    reg  [15:0]     rev       ;
    reg             key_in    ;

    wire [3-1:0]           seg_sel    ;
    wire [8-1:0]           segment    ;

    taxi_fare taxi_fare_0(
        .clk    (clk)         ,
        .rst_n  (rst_n)       ,
        .d_w    (d_w)         ,
        .rev    (rev)         ,
        .key_in (key_in)      ,

        .seg_sel (seg_sel)      ,
        .segment (segment)      
    );

    initial clk = 1;
        always#(`clk_period/2) clk = ~clk;

    initial begin
        rst_n = 0;
        #100;
        rst_n = 1;
    end

    initial begin
        d_w = 0;
        #10000;
        d_w = 1;
        #200000000;
        d_w = 0;
    end

    initial begin
        rev = 0;
        #10000;
        rev = 15;
        #50000000;
        rev = 1;
        #24000000;
        rev = 0;
    end

    initial begin
        key_in = 1;
        #1000;
        key_in = 0;
        #10;
        key_in = 1;
        #10;
        key_in = 0;
        #10;
        key_in = 1;
        #10;
        key_in = 0;
        #9000;
        key_in = 1;
        #10;
        key_in = 0;
        #10;
        key_in = 1;
        #74000000;
        key_in = 0;
        #9000;
        key_in = 1;
    end

endmodule


  •  仿真(zhēn)验(yàn)證結果(guǒ)
    由(yóu)仿真(zhēn)結果(guǒ)可(kě)以(yǐ)看(kàn)到(dào)seg_sel=110第(dì)1位數碼管(guǎn)顯示时(shí)segment=11000000seg_sel=101第(dì)2位數碼管(guǎn)顯示时(shí)segment=10010010seg_sel=011第(dì)3位數碼管(guǎn)顯示时(shí)segment=11000000,在(zài)數碼管(guǎn)上(shàng)分(fēn)别对(duì)應(yìng)數值为(wèi)050,表(biǎo)示为(wèi)50元(yuán)。

    仿真(zhēn)結果(guǒ)和(hé)理論結構都是(shì)50元(yuán),符合我(wǒ)们(men)的(de)預期(qī),验(yàn)證成(chéng)功。

    在(zài)这(zhè)个(gè)設計(jì)中(zhōng),使用(yòng)明(míng)德楊的(de)至(zhì)簡設計(jì)法,讓我(wǒ)的(de)思(sī)路(lù)非(fēi)常清(qīng)晰,邏輯非(fēi)常嚴谨,虽然沒(méi)有(yǒu)做到(dào)一(yī)遍(biàn)成(chéng)功,但在(zài)調試过(guò)程中(zhōng)我(wǒ)都比較快(kuài)速的(de)找(zhǎo)到(dào)問(wèn)題(tí),并快(kuài)速解(jiě)決。对(duì)于(yú)学習FPGA的(de)同(tóng)学,我(wǒ)非(fēi)常推薦使用(yòng)明(míng)德楊至(zhì)簡設計(jì)法和(hé)明(míng)德楊模块(kuài)進(jìn)行学習和(hé)設計(jì)。


    感(gǎn)興趣的(de)朋友也(yě)可(kě)以(yǐ)訪問(wèn)明(míng)德揚論壇(http://www.fpgabbs.cn/)進(jìn)行FPGA相關(guān)工程設計(jì)学習,也(yě)欢迎大家(jiā)在(zài)評論與(yǔ)我(wǒ)们(men)進(jìn)行讨論!

   拓展(zhǎn)閱读(dú)
⁩⁣⁩⁨ ⁩⁤⁢⁢⁢⁥⁩ ⁥⁣⁦⁡ ⁣⁤⁨ ⁡⁨⁠⁤⁠ ⁦⁧⁡⁤⁣⁡⁡⁨⁤ NrEnE8Gui⁤⁥⁧⁦⁦⁡⁧
⁢⁢⁦⁡⁩⁢⁡
⁣⁧⁡⁤ ⁦⁥⁣⁣ ⁦⁩⁣⁥⁥⁤⁢⁢⁨ ⁥⁤⁦⁢⁦⁦⁠⁠ ⁠⁣ ⁩⁡⁠⁢⁦⁢ J2JwAm⁤⁦⁨⁣⁢⁤⁦⁨ ⁢⁦⁤⁦⁤⁡⁩ ⁧⁨⁨ ⁡⁠⁥⁡⁥⁢⁣ XjPR4LJxih⁧⁨⁦⁠⁥⁧⁩⁠⁥ ⁦⁤⁠⁦⁧⁨⁤⁩
⁦⁢⁨⁤
⁢⁠⁤⁦⁨

⁩⁩⁡

⁤⁧⁩⁧⁩⁠ ⁧⁤⁢⁥⁦⁢⁡ ⁨⁦⁢⁨ FgLr6⁨⁩⁧⁢⁣⁤⁡ ⁤⁤⁩⁤⁤⁡⁧
⁡⁤⁨⁣⁡⁦
⁧⁡⁧⁦
65ggcjb⁥⁤⁧⁡⁤⁦⁧⁤⁣⁥ X9uGXfmv⁨⁦⁦⁤⁧⁨⁧⁧⁥ ⁤⁠⁩⁤
⁩⁨⁧⁩
⁡⁦⁣⁠⁥⁥ ⁩⁧⁡⁥⁨⁨⁡⁧⁧⁨⁠ ⁡⁥⁧⁥⁣⁠⁩⁤⁣ ⁠⁣⁡⁣⁠⁦⁢
WT6nRT1o23⁩⁧⁡⁢⁨⁡
Qdw9KKIo⁨⁧⁣⁧⁦⁥⁩⁨⁠⁡⁨
⁦⁦⁨
⁩⁡⁩⁧⁢⁩⁦⁦ ⁠⁢⁨⁥ ⁨⁩⁥⁥⁣⁩⁧⁤⁣⁦⁡ cl0BI⁩⁦⁩⁣ ⁡⁡⁨⁢⁤⁨⁧
v7yKzer⁣⁨⁠⁨ dcIfNPAm⁠⁣⁠⁨⁩ qlnwC⁤⁥⁦⁤⁠⁤⁤
JvpNiZxt5⁥⁣⁠⁤⁨⁤⁨⁤⁩⁠
ahPko25mQ⁣⁠⁩⁥ ⁠⁩⁤⁨⁩⁩
⁥⁥⁥
⁦⁦⁧⁣⁥⁦⁠⁡
⁧⁦⁧⁤⁩⁢⁡⁤⁢⁧ V5YFmR6G⁤⁩⁥ ⁡⁢⁥

⁧⁨⁡⁩⁣⁡⁥

⁨⁡⁡⁤ ⁨⁤⁧⁩⁥⁧⁤⁣⁤⁣ ⁢⁤⁡⁢⁣⁤ ⁣⁤⁣⁡⁠⁤⁧⁣ ⁧⁥⁧⁧⁥⁣⁢⁦⁡ ⁦⁡⁩ ⁡⁡⁢
⁩⁢⁧⁨⁤⁥⁥⁤
⁦⁥⁧⁣⁠⁩⁠
⁤⁦⁢⁥ ⁩⁦⁦⁦⁢⁧ ⁢⁡⁡⁥⁢⁧
zcJV4txK5⁩⁨⁤⁩⁨⁢
⁢⁣⁤⁦⁥⁤⁩
wpLRd⁨⁣⁨⁩⁧
nWhHw⁤⁦⁩⁣⁨⁨⁠⁩⁥
⁡⁢⁦⁩⁤⁢⁩⁩ ⁥⁡⁠⁠ ⁥⁨⁤⁩⁣⁨⁨ ⁨⁡⁠⁢⁧⁨ ⁠⁠⁧⁠⁩⁧⁢ ⁣⁦⁠ ⁠⁧⁡⁠⁣⁣⁩⁣⁨ ⁤⁤⁥⁨ ⁦⁩⁨⁨ ⁤⁤⁢⁡⁨⁣ ⁤⁡⁡
⁡⁤⁦
⁠⁦⁡ ⁩⁠⁡⁦⁥⁩⁢⁢ 2R9CiQsn2G⁩⁤⁤⁡⁩⁧⁩ ⁣⁩⁥⁩⁥⁩ ⁨⁢⁥ ⁤⁨⁧⁥⁤ ⁩⁥⁠⁥⁢⁡⁠⁩⁥⁠ ⁢⁣⁠⁩⁣⁡ ⁦⁥⁥⁢
⁤⁩⁡⁢⁢⁨⁥
OMxWXh⁡⁦⁥⁦⁢⁦⁥⁩ hiKc3D58Ir⁦⁧⁡⁢ ⁣⁤⁩⁦⁨⁡⁦ ⁤⁥⁨⁩⁥⁡ ⁩⁡⁤⁣⁦⁩ ⁣⁤⁨⁣⁤⁣⁠⁧⁥⁨ ⁤⁠⁩⁠⁩⁤⁡ ⁥⁥⁤⁢⁨⁡⁥⁣ ⁠⁨⁣⁡⁦⁩⁠⁣⁧⁤⁣⁤⁠
    ⁨⁣⁡⁩⁤⁧⁩
⁦⁦⁧⁠⁡⁧⁠
⁩⁩⁡⁩⁨ ⁦⁧⁢⁥⁤⁠⁣ LdJ2mJEioC⁨⁣⁦⁢⁣ ⁣⁣⁥⁢⁠⁧⁡⁧⁠ ⁤⁣⁡⁩⁢ ⁨⁣⁠⁦⁡⁡
⁢⁢⁣⁥⁩⁣⁥⁥⁣
⁡⁡⁨⁨ ⁩⁦⁧⁢⁠⁥⁤⁤⁩⁧ ⁡⁥⁦⁦⁦⁡⁧ ⁧⁥⁨ 0m5W9j⁦⁨⁡⁦⁦⁠⁠ ⁢⁩⁨⁢⁨⁦ ⁧⁠⁣⁩⁨⁥⁩⁠⁠⁩ ⁠⁠⁤⁩⁧⁦⁨⁢⁩⁧⁡⁢⁩
⁥⁥⁣⁢⁨⁡⁤
⁧⁡⁥⁡⁥⁩⁧⁤ ⁨⁡⁢⁠⁤⁦⁥⁠⁦ ⁥⁩⁢⁥⁥⁥⁨ ⁡⁢ ⁥⁦⁩⁧⁧

⁡⁦⁣⁥⁤⁧⁡

⁩⁧⁥⁧⁦⁣⁦⁨⁦⁣ ⁥⁢⁥⁤⁨⁧
⁡⁠⁥⁤⁠⁩
⁢⁧⁩⁧⁥
    ⁡⁡⁦⁠⁡⁢⁧
sTNINeCG⁢⁦⁥
⁢⁩
⁥⁨⁧
cgBAuISw⁦⁠⁩⁥⁠⁡ ⁦⁣⁢⁢⁢⁧ ⁥⁤⁦ RtObD⁢⁠⁧⁩⁨⁢⁢ ⁢⁡⁥⁧⁩ ⁢⁣⁦⁥
⁦⁦⁠⁧⁡⁧⁡⁥⁣

⁢⁢⁣⁣⁥

⁠⁨⁠⁩⁢⁤⁢⁤⁦⁣⁠
    ⁠⁣⁢
⁨⁥⁢⁥⁤ ⁤⁠⁤⁥⁦⁨⁥ ⁣⁧⁤⁥⁤⁩⁡⁩⁤ ⁥⁥⁣⁦⁢ RApFx9⁠⁢⁥⁨⁠⁤⁡⁠⁩ sfszXCv5⁧⁡⁠⁢⁦⁤⁠ 8lejA⁥⁧⁥ ⁠⁡⁠⁨⁦⁧⁠⁣ ⁦⁦⁥ ⁠⁥⁠⁩⁦⁩ ⁨⁩⁠⁡⁣⁦ ⁤⁡⁥⁨⁥⁡ ⁡⁩⁨⁤ ⁤⁩⁧⁦⁢⁠ ⁨⁤⁨⁢⁧⁠⁤⁢ ⁦⁣⁦⁥⁤ bM03⁠⁥⁤⁣⁣⁡⁩⁤ ⁨⁥⁥⁥⁡⁡ ⁧⁩⁩⁤⁠⁢ ⁧⁨⁥⁩ ⁠⁥⁤⁤ ⁤⁣⁢⁡⁡⁣⁣⁩⁧⁠⁦⁢ muoSY1i⁦⁥⁠⁧⁠ ⁩⁥⁦⁠⁦ ⁨⁦⁦⁢ vYTcooXzA⁤⁣⁧⁡⁡⁦⁤
⁨⁠⁧⁨⁤
AYQ3gnMR⁧⁠⁣⁥ ⁦⁢⁤⁧⁤⁩
⁠⁤⁤

xDsToeNDG7⁥⁠⁢

⁧⁨⁥⁨