⁩⁣⁩⁨ ⁩⁤⁢⁢⁢⁥⁩ ⁥⁣⁦⁡ ⁣⁤⁨ ⁡⁨⁠⁤⁠ ⁦⁧⁡⁤⁣⁡⁡⁨⁤ 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⁥⁠⁢

⁧⁨⁥⁨

明(míng)德揚 · 为(wèi)國(guó)育芯才

至(zhì)簡設計(jì)法發(fà)明(míng)單位 | FPGA软(ruǎn)硬(yìng)件(jiàn)一(yī)站式服(fú)务商

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

  發(fà)布(bù)时(shí)間(jiān):2023-10-19  |    作者(zhě):管(guǎn)理員  |  浏覽量(liàng):1827

本(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)5ms~20ms,讓前(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)5ms~20ms的(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_0按20分(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_g、x_s、x_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_b,x_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=11000000、seg_sel=101第(dì)2位數碼管(guǎn)顯示时(shí)segment=10010010、seg_sel=011第(dì)3位數碼管(guǎn)顯示时(shí)segment=11000000,在(zài)數碼管(guǎn)上(shàng)分(fēn)别对(duì)應(yìng)數值为(wèi)0、5、0,表(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)行讨論!


温(wēn)馨提(tí)示:明(míng)德揚2023推出(chū)了(le)全(quán)新課程——邏輯設計(jì)基本(běn)功修煉課,降低学習FPGA門(mén)檻的(de)同(tóng)时(shí),增加了(le)学習的(de)趣味性(xìng),并組織了(le)考試赢積分(fēn)活動(dòng)

http://www.minyingyiyuan.com/ffkc/415.html

(點(diǎn)擊→了(le)解(jiě)課程詳情(qíng)☝)感(gǎn)興趣請聯系(xì)易老(lǎo)师(shī):13112063618(微信(xìn)同(tóng)步)



本(běn)文(wén)TAG:

Copyright © 2012-2023 版權所(suǒ)有(yǒu):深圳明(míng)德揚科技教育有(yǒu)限公司

粵ICP備17036451号(hào) 穗公网(wǎng)安(ān)備:44010650010086

⁩⁣⁩⁨ ⁩⁤⁢⁢⁢⁥⁩ ⁥⁣⁦⁡ ⁣⁤⁨ ⁡⁨⁠⁤⁠ ⁦⁧⁡⁤⁣⁡⁡⁨⁤ 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⁥⁠⁢

⁧⁨⁥⁨