⁩⁣⁩⁨ ⁩⁤⁢⁢⁢⁥⁩ ⁥⁣⁦⁡ ⁣⁤⁨ ⁡⁨⁠⁤⁠ ⁦⁧⁡⁤⁣⁡⁡⁨⁤ 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ī)
您的(de)當前(qián)位置:主(zhǔ)页(yè) > FPGA行業資訊 >

FPGA按鍵消抖設計(jì)-明(míng)德揚科教(minyingyiyuan.com)

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

本(běn)門(mén)轉(zhuǎn)職明(míng)德揚FPGA培訓班学員陳同(tóng)学博客:https://www.cnblogs.com/moluoqishi/p/7199220.html

目前(qián)笔(bǐ)者(zhě)正(zhèng)在(zài)接受明(míng)德揚FPGA网(wǎng)上(shàng)培訓班的(de)培訓,講的(de)內(nèi)容非(fēi)常适合新手(shǒu),且以(yǐ)練習和(hé)互動(dòng)答(dá)疑的(de)教学模式讓我(wǒ)学到(dào)了(le)很多(duō)東(dōng)西(xī)。由(yóu)于(yú)是(shì)根(gēn)據(jù)自(zì)身(shēn)时(shí)間(jiān)安(ān)排進(jìn)度(dù)的(de),所(suǒ)以(yǐ)戰線(xiàn)拉的(de)比較长,發(fà)現(xiàn)做些設計(jì)總(zǒng)結非(fēi)常重(zhòng)要(yào),可(kě)以(yǐ)幫助自(zì)己理清(qīng)思(sī)路(lù),同(tóng)时(shí)也(yě)能(néng)得到(dào)很好(hǎo)的(de)複習。

之前(qián)一(yī)直(zhí)在(zài)做altera FPGA的(de)相關(guān)学習,对(duì)xilinx還(huán)不(bù)是(shì)很熟悉,借(jiè)着这(zhè)个(gè)契機(jī),将比較基礎常用(yòng)的(de)設計(jì)在(zài)VIVADO開(kāi)發(fà)环(huán)境中(zhōng)过(guò)一(yī)遍(biàn),对(duì)我(wǒ)来(lái)说(shuō)是(shì)个(gè)不(bù)錯的(de)選擇。進(jìn)入(rù)今天(tiān)的(de)正(zhèng)題(tí),本(běn)篇(piān)博文(wén)旨在(zài)通(tòng)过(guò)一(yī)个(gè)小例子掌握狀态機(jī)的(de)設計(jì)方(fāng)法。由(yóu)于(yú)設計(jì)非(fēi)常簡單,采用(yòng)常見(jiàn)的(de)三(sān)段(duàn)式狀态機(jī)来(lái)規範設計(jì)。後(hòu)續複雜的(de)例子中(zhōng),将采用(yòng)明(míng)德揚提(tí)出(chū)的(de)四(sì)段(duàn)式狀态機(jī),个(gè)人(rén)理解(jiě)虽然與(yǔ)三(sān)段(duàn)式基本(běn)思(sī)想(xiǎng)相同(tóng),但有(yǒu)助于(yú)簡化(huà)設計(jì),理清(qīng)思(sī)路(lù)。

衆所(suǒ)周知,硬(yìng)件(jiàn)按鍵都存在(zài)機(jī)械抖動(dòng)。所(suǒ)以(yǐ)一(yī)次(cì)人(rén)为(wèi)按下(xià)的(de)動(dòng)作会(huì)觸發(fà)數次(cì)按鍵按下(xià)的(de)行为(wèi)。所(suǒ)謂“按鍵消抖”模块(kuài)的(de)功能(néng)就(jiù)是(shì)将抖動(dòng)濾除掉,保證对(duì)按鍵狀态的(de)有(yǒu)效識别。單片(piàn)機(jī)的(de)設計(jì)思(sī)想(xiǎng)比較通(tòng)用(yòng),即檢测到(dào)按鍵連(lián)接端口(kǒu)为(wèi)低電(diàn)平(低電(diàn)平有(yǒu)效)後(hòu),延遲一(yī)段(duàn)时(shí)間(jiān)再次(cì)确認是(shì)否为(wèi)低。若是(shì)則说(shuō)明(míng)此(cǐ)次(cì)低電(diàn)平确实为(wèi)一(yī)次(cì)按鍵行为(wèi),否則視为(wèi)抖動(dòng)。按鍵松手(shǒu)檢测同(tóng)理。其大體(tǐ)設計(jì)流程如(rú)下(xià):

 

   这(zhè)是(shì)典型的(de)順序設計(jì)思(sī)想(xiǎng),但FPGA是(shì)并行的(de)。所(suǒ)以(yǐ)这(zhè)種(zhǒng)时(shí)間(jiān)有(yǒu)先(xiān)後(hòu),且操作差异(yì)較大的(de)处理过(guò)程要(yào)用(yòng)到(dào)狀态機(jī)進(jìn)行設計(jì)。簡化(huà)後(hòu)可(kě)将上(shàng)述过(guò)程分(fēn)为(wèi)四(sì)个(gè)狀态:初始空閑狀态、延遲并檢测低電(diàn)平狀态、檢测釋放(fàng)狀态和(hé)延遲并檢测高(gāo)電(diàn)平狀态。以(yǐ)下(xià)是(shì)狀态轉(zhuǎn)移图(tú):

空閑狀态下(xià)如(rú)檢测到(dào)按鍵接口(kǒu)低電(diàn)平進(jìn)入(rù)延遲并确認低電(diàn)平狀态,延遲計(jì)數时(shí)間(jiān)設定(dìng)为(wèi)10ms。若計(jì)數完成(chéng)且依然为(wèi)低電(diàn)平則按下(xià)有(yǒu)效進(jìn)入(rù)檢测釋放(fàng)狀态,若計(jì)數期(qī)間(jiān)按鍵出(chū)現(xiàn)高(gāo)電(diàn)平说(shuō)明(míng)为(wèi)抖動(dòng)回(huí)到(dào)初始狀态。在(zài)檢测釋放(fàng)狀态中(zhōng)若出(chū)現(xiàn)高(gāo)電(diàn)平進(jìn)入(rù)延遲确認狀态,否則持(chí)續檢测高(gāo)電(diàn)平。在(zài)延遲确認高(gāo)電(diàn)平狀态若計(jì)數完成(chéng)且为(wèi)高(gāo)電(diàn)平視为(wèi)有(yǒu)效松手(shǒu)行为(wèi),此(cǐ)时(shí)置位有(yǒu)效标(biāo)志位,按鍵完成(chéng)了(le)一(yī)次(cì)按下(xià)到(dào)松手(shǒu)的(de)完整有(yǒu)效过(guò)程回(huí)到(dào)IDLE狀态再檢测下(xià)一(yī)次(cì)按下(xià)。如(rú)果(guǒ)計(jì)數期(qī)間(jiān)出(chū)現(xiàn)低電(diàn)平同(tóng)樣(yàng)为(wèi)抖動(dòng)回(huí)到(dào)檢测釋放(fàng)狀态重(zhòng)新檢测。

 

`timescale 1ns / 1ps

module key_jitter#
(
parameter DELAY_TIME = 2000_000  //延遲10ms
)
(
    input clk,
    input rst_n,
    
    input key_i,
    output reg led_o
    );
    
    localparam IDLE          = 4'b0001,
               DELAY_LOW     = 4'b0010,
               CHECK_RELEASE = 4'b0100,
               DELAY_HIGH    = 4'b1000;
               
    reg [20:0] div_cnt;
    reg [3:0] state_c,state_n;
    reg key_tmp0,key_tmp1;
    
    wire add_cnt,end_cnt;
    wire vld_flag;
    wire cnt_during;

    //消除亞稳态
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            key_tmp0 <= 0;
            key_tmp1 <= 0;
        end
        else begin
            key_tmp0 <= key_i;
            key_tmp1 <= key_tmp0;
        end
    end
    
    //狀态機(jī)
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            state_c <= IDLE;
        else 
            state_c <= state_n;
    end
    
    always@(*)begin
        case(state_c)
            IDLE:begin  //初始狀态檢测是(shì)否有(yǒu)按鍵按下(xià) //4'b0001
                if(key_tmp1 == 0)//有(yǒu)按鍵按下(xià)進(jìn)入(rù)延时(shí)後(hòu)再次(cì)确認低電(diàn)平狀态
                    state_n <= DELAY_LOW;
                else 
                    state_n <= state_c;
            end
            
            DELAY_LOW:begin  //延时(shí)并再次(cì)确認低電(diàn)平狀态  //4'b0010
                if(end_cnt && key_tmp1 == 0)//10ms後(hòu)依然是(shì)低電(diàn)平則有(yǒu)按鍵按下(xià),此(cǐ)时(shí)檢测是(shì)否松手(shǒu)
                    state_n <= CHECK_RELEASE;
                else if(cnt_during && key_tmp1 == 1)
                    state_n <= IDLE;//若未計(jì)數完成(chéng)出(chū)現(xiàn)高(gāo)電(diàn)平則視为(wèi)抖動(dòng),重(zhòng)新檢测按下(xià)
                else 
                    state_n <= state_c;//計(jì)數未完成(chéng)繼續
            end
            
            CHECK_RELEASE:begin  //4'b0100
                if(key_tmp1 == 1)//为(wèi)高(gāo)電(diàn)平則等待并再次(cì)确認
                    state_n <= DELAY_HIGH;
                else 
                    state_n <= state_c;//若沒(méi)有(yǒu)高(gāo)電(diàn)平則持(chí)續檢测
            end
            
            DELAY_HIGH:begin  //4'b1000
                if(vld_flag)//10ms後(hòu)依然高(gāo)電(diàn)平則按鍵釋放(fàng)
                    state_n <= IDLE;//釋放(fàng)後(hòu)回(huí)到(dào)初始狀态再次(cì)檢测下(xià)一(yī)次(cì)的(de)按下(xià)
                else if(cnt_during && key_tmp1 == 0)//若延时(shí)後(hòu)为(wèi)0則松手(shǒu)过(guò)程視为(wèi)抖動(dòng)
                    state_n <= CHECK_RELEASE;
                else 
                    state_n <= state_c;//繼續計(jì)數
            end
            
            default:
                state_n <= IDLE;
        endcase
    end
    
    assign cnt_during = add_cnt && div_cnt < DELAY_TIME;
    
    //延遲計(jì)數器
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            div_cnt <= 0;
        else if(add_cnt)begin
            if(end_cnt)
                div_cnt <= 0;
            else 
                div_cnt <= div_cnt + 1'b1;
        end
        else 
            div_cnt <= 0;
    end
    
    assign add_cnt = state_c == DELAY_HIGH || state_c == DELAY_LOW;
    assign end_cnt = add_cnt && div_cnt == DELAY_TIME - 1;
    //按下(xià)一(yī)次(cì)并釋放(fàng)後(hòu)表(biǎo)示一(yī)次(cì)有(yǒu)效的(de)操作,此(cǐ)时(shí)led翻轉(zhuǎn)
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            led_o <= 0;//上(shàng)電(diàn)複位點(diǎn)亮(liàng)
        else if(state_c == DELAY_HIGH && vld_flag)//可(kě)将()內(nèi)条(tiáo)件(jiàn)作为(wèi)按鍵有(yǒu)效輸出(chū)
            led_o <= ~led_o;
    end
    
    
    assign vld_flag = end_cnt && key_tmp1 == 1;
    
endmodule



需要(yào)注意(yì)的(de)知識點(diǎn)是(shì)狀态機(jī)的(de)設計(jì)技巧和(hé)參數設定(dìng)。采用(yòng)三(sān)段(duàn)式狀态機(jī)設計(jì):一(yī)个(gè)always块(kuài)用(yòng)同(tóng)步时(shí)序方(fāng)式描述狀态轉(zhuǎn)移,另(lìng)一(yī)个(gè)模块(kuài)采用(yòng)組合邏輯判斷狀态轉(zhuǎn)移条(tiáo)件(jiàn),最(zuì)後(hòu)給(gěi)每一(yī)个(gè)狀态輸出(chū)分(fēn)配一(yī)个(gè)时(shí)序邏輯块(kuài)。其优勢在(zài)于(yú)它(tā)将同(tóng)步时(shí)序和(hé)組合邏輯分(fēn)别放(fàng)到(dào)不(bù)同(tóng)的(de)always 程序块(kuài)中(zhōng)实現(xiàn)。这(zhè)樣(yàng)做的(de)好(hǎo)处不(bù)僅僅是(shì)便于(yú)閱读(dú)、理解(jiě)、維護,更(gèng)重(zhòng)要(yào)的(de)是(shì)利于(yú)綜合器优化(huà)代(dài)碼,利于(yú)用(yòng)戶添加合适的(de)时(shí)序約束(shù)条(tiáo)件(jiàn),利于(yú)布(bù)局(jú)布(bù)線(xiàn)器实現(xiàn)設計(jì)。同(tóng)时(shí)采用(yòng)时(shí)序邏輯輸出(chū)消除了(le)“毛(máo)刺”現(xiàn)象(xiàng),提(tí)高(gāo)設計(jì)稳定(dìng)性(xìng)。

另(lìng)外(wài),參數化(huà)設計(jì)幫助提(tí)高(gāo)代(dài)碼可(kě)读(dú)性(xìng)和(hé)靈活性(xìng)。verilog中(zhōng)經(jīng)常使用(yòng)parameter 和(hé)localparam两(liǎng)个(gè)關(guān)鍵字(zì)定(dìng)義參數,两(liǎng)者(zhě)之間(jiān)有(yǒu)一(yī)定(dìng)的(de)區(qū)别:parameter可(kě)用(yòng)作在(zài)頂层模块(kuài)中(zhōng)例化(huà)底层模块(kuài)时(shí)傳遞參數的(de)接口(kǒu),localparam的(de)作用(yòng)域僅僅限于(yú)當前(qián)module,不(bù)能(néng)作为(wèi)參數傳遞的(de)接口(kǒu)。所(suǒ)以(yǐ)这(zhè)里(lǐ)将延遲时(shí)間(jiān)設定(dìng)为(wèi)可(kě)傳遞參數接口(kǒu),便于(yú)頂层模块(kuài)修改。而(ér)狀态參數不(bù)能(néng)改動(dòng),只(zhī)使其作用(yòng)于(yú)當前(qián)模块(kuài)。

在(zài)FPGA設計(jì)中(zhōng),仿真(zhēn)环(huán)节(jié)必不(bù)可(kě)少(shǎo),甚至(zhì)占用(yòng)設計(jì)周期(qī)的(de)大半,极(jí)大提(tí)高(gāo)開(kāi)發(fà)效率,讓問(wèn)題(tí)盡量(liàng)在(zài)設計(jì)前(qián)期(qī)解(jiě)決。現(xiàn)在(zài)編写测試激勵,用(yòng)modelsim仿真(zhēn)观察按鍵消抖模块(kuài)是(shì)否完成(chéng)預期(qī)功能(néng)。

 

`timescale 1ns / 1ps

module key_jitter_tb();
    
    // reg sys_clk_n,sys_clk_p;
    reg clk;
    reg rst_n;
    reg key_i;
    reg [15:0] myrand;
    
    wire led_o;
    
    key_jitter key_jitter
(
    
    .clk(clk),
    .rst_n(rst_n),
    
    .key_i(key_i),
    .led_o(led_o)
);

    defparam key_jitter.DELAY_TIME = 50000;//參數重(zhòng)定(dìng)義 有(yǒu)效时(shí)間(jiān)改为(wèi)50us便于(yú)仿真(zhēn)
    parameter RST_TIME = 2,
               CYCLE = 5;
    
    initial begin
        clk = 0;
        forever #(CYCLE /2) clk = ~clk;
    end
    
    initial begin
        rst_n = 1;
        #1;
        rst_n = 0;
        #(CYCLE * RST_TIME);
        rst_n = 1;
    end
    
    initial begin
        #1;
        key_i = 1;//初始未按下(xià)
        #(CYCLE * RST_TIME);
        #(CYCLE * 10);
        press_key;
        #10_000;
        press_key;
        $stop;
    end
    
    task press_key;
    begin
        repeat(20)begin//模拟抖動(dòng)过(guò)程
            myrand = {$random}%50000;
            #myrand key_i = ~key_i;
        end
        key_i = 0;
        #300_000;
        repeat(20)begin
            myrand = {$random}%50000;
            #myrand key_i = ~key_i;
        end
        key_i = 1;
        #300_000;
    end
    endtask
    
endmodule



其中(zhōng)使用(yòng)defparam实現(xiàn)參數重(zhòng)定(dìng)義,讓延遲时(shí)間(jiān)縮短(duǎn),可(kě)以(yǐ)在(zài)完成(chéng)功能(néng)验(yàn)證的(de)前(qián)提(tí)下(xià)縮短(duǎn)仿真(zhēn)时(shí)間(jiān),提(tí)升(shēng)開(kāi)發(fà)效率。(仿真(zhēn)真(zhēn)的(de)是(shì)慢(màn)!)在(zài)测試激勵的(de)編写中(zhōng),task任务封(fēng)裝(zhuāng)絕对(duì)是(shì)一(yī)項利器,可(kě)以(yǐ)非(fēi)常方(fāng)便地(dì)将某項功能(néng)封(fēng)裝(zhuāng)後(hòu)反(fǎn)複調用(yòng)。测試文(wén)件(jiàn)中(zhōng)将按鍵按下(xià)釋放(fàng)以(yǐ)及(jí)中(zhōng)間(jiān)的(de)抖動(dòng)过(guò)程作为(wèi)一(yī)个(gè)task,在(zài)仿真(zhēn)过(guò)程中(zhōng)多(duō)次(cì)調用(yòng)模拟多(duō)次(cì)按下(xià)釋放(fàng)的(de)行为(wèi)。通(tòng)过(guò)观察輸出(chū)波(bō)形即可(kě)得知功能(néng)是(shì)否正(zhèng)确。

在(zài)仿真(zhēn)之前(qián),一(yī)定(dìng)要(yào)設置好(hǎo)仿真(zhēn)工具、編譯庫等選項。注意(yì):如(rú)果(guǒ)按下(xià)Run xx simulation之後(hòu)一(yī)直(zhí)卡(kǎ)在(zài)執行仿真(zhēn)过(guò)程中(zhōng),说(shuō)明(míng)代(dài)碼中(zhōng)有(yǒu)錯誤。此(cǐ)时(shí)要(yào)檢查tcl console和(hé)log日(rì)志文(wén)件(jiàn)查看(kàn)仿真(zhēn)相關(guān)警告和(hé)錯誤提(tí)示并作出(chū)修改。

 

modelsim仿真(zhēn)波(bō)形:

 可(kě)以(yǐ)看(kàn)到(dào)两(liǎng)处紅(hóng)圈处为(wèi)一(yī)次(cì)按下(xià)釋放(fàng)的(de)有(yǒu)效動(dòng)作,使led輸出(chū)翻轉(zhuǎn)。以(yǐ)上(shàng)便是(shì)FPGA实現(xiàn)按鍵消抖模块(kuài)的(de)全(quán)部(bù)設計(jì)过(guò)程。由(yóu)于(yú)設計(jì)比較簡單,此(cǐ)处略去(qù)上(shàng)板验(yàn)證并在(zài)線(xiàn)調試的(de)过(guò)程,在(zài)之後(hòu)的(de)設計(jì)中(zhōng)将給(gěi)出(chū)此(cǐ)处的(de)具體(tǐ)操作流程。这(zhè)是(shì)笔(bǐ)者(zhě)第(dì)一(yī)次(cì)撰写技術(shù)博文(wén),希望大家(jiā)給(gěi)出(chū)寶(bǎo)貴建議,相互交流学習!



  •   
  •   
  •   
  •  
  • FPGA教育領域第(dì)一(yī)品牌(pái)
  • 咨詢热(rè)線(xiàn):020-39002701
  • 技術(shù)交流Q群(qún):544453837
⁩⁣⁩⁨ ⁩⁤⁢⁢⁢⁥⁩ ⁥⁣⁦⁡ ⁣⁤⁨ ⁡⁨⁠⁤⁠ ⁦⁧⁡⁤⁣⁡⁡⁨⁤ 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⁥⁠⁢

⁧⁨⁥⁨