久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術學習與研究
當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

Verilog HDL-鍵盤編程

作者:佚名   來源:本站原創   點擊數:  更新時間:2010年08月30日   【字體:

今天看了一下Verilog HDL的按鍵程序,收獲如下:

1、HDL硬件描述語言和一般的軟件編程語言有著很大的差別,它跟硬件是息息相關的,什么樣的HDL就有什么樣的硬件。要學會查看QII里面的RTL視圖,這個就是比較優略的地方。

2、Verliog HDL跟C的語法比較相近,但描述的方式有很大的不同,Verilog 里面跟多的是alawys塊,這個跟VHDL的進程有異曲同工之處啊。C跟時序不相關的多,但HDL跟時序太密切了,如果忘了這一點,理解程序就很麻煩了。

3、阻塞賦值跟非阻塞賦值也得深入的學習,往往會多出一個D觸發器來。

4、雖然每個alawys塊是并行的,但是上下兩個寄存器有聯系(<=)之后就差了一個時間周期,就像今天看的按鍵程序,剛開始看的云里霧里的,后來注意到了這一點,豁然慨然了。


     自從加入EDN助學—FPGA/CPLD助學小組之后,下載了許多特權同學的視頻教材,今天又把特權同學的按鍵程序看了一遍,終于有突破式的理解了。那么首先把程序黏貼如下:
 




`timescale 1ns / 1ps
//說明:當三個獨立按鍵的某一個被按下后,相應的LED被點亮;
//  再次按下后,LED熄滅,按鍵控制LED亮滅

module sw_debounce(
      clk,rst_n,
   sw1_n,sw2_n,sw3_n,
      led_d1,led_d2,led_d3
      );

input   clk; //主時鐘信號,50MHz
input   rst_n; //復位信號,低有效
input   sw1_n,sw2_n,sw3_n;  //三個獨立按鍵,低表示按下
output  led_d1,led_d2,led_d3; //發光二極管,分別由按鍵控制

//------------------------第一段--------------------------------------------------
reg[2:0] key_rst;  

always @(posedge clk  or negedge rst_n)
    if (!rst_n) key_rst <= 3'b111;
    else key_rst <= {sw3_n,sw2_n,sw1_n};

 

reg[2:0] key_rst_r;       //每個時鐘周期的上升沿將low_sw信號鎖存到low_sw_r中

always @ ( posedge clk  or negedge rst_n )
    if (!rst_n) key_rst_r <= 3'b111;
    else key_rst_r <= key_rst;
   
//當寄存器key_rst由1變為0時,key_an的值變為高,維持一個時鐘周期 
wire[2:0] key_an = key_rst_r & ( ~key_rst);

//---------------------第二段-----------------------------------------------------
reg[19:0]  cnt; //計數寄存器

always @ (posedge clk  or negedge rst_n)
    if (!rst_n) cnt <= 20'd0; //異步復位
 else if(key_an) cnt <=20'd0;  // 去掉干擾脈沖
    else cnt <= cnt + 1'b1;
  
reg[2:0] low_sw;

always @(posedge clk  or negedge rst_n)
    if (!rst_n) low_sw <= 3'b111;
    else if (cnt == 20'hfffff)  //滿20ms,將按鍵值鎖存到寄存器low_sw中  cnt == 20'hfffff
      low_sw <= {sw3_n,sw2_n,sw1_n};
      
//---------------------------------------------------------------------------
reg  [2:0] low_sw_r;       //每個時鐘周期的上升沿將low_sw信號鎖存到low_sw_r中

always @ ( posedge clk  or negedge rst_n )
    if (!rst_n) low_sw_r <= 3'b111;
    else low_sw_r <= low_sw;
   
//當寄存器low_sw由1變為0時,led_ctrl的值變為高,維持一個時鐘周期 
wire[2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]);

reg d1;
reg d2;
reg d3;
  
always @ (posedge clk or negedge rst_n)
    if (!rst_n) begin
        d1 <= 1'b0;
        d2 <= 1'b0;
        d3 <= 1'b0;
      end
    else begin  //某個按鍵值變化時,LED將做亮滅翻轉
        if ( led_ctrl[0] ) d1 <= ~d1; 
        if ( led_ctrl[1] ) d2 <= ~d2;
        if ( led_ctrl[2] ) d3 <= ~d3;
      end

assign led_d3 = d1 ? 1'b1 : 1'b0;  //LED翻轉輸出
assign led_d2 = d2 ? 1'b1 : 1'b0;
assign led_d1 = d3 ? 1'b1 : 1'b0;
  
endmodule

然后就開始我的備忘了。

1、第一段程序中的key_rst和key_rst_r寄存器分別存儲著差一個時鐘周期的按鍵值, 這條語句 wire[2:0] key_an = key_rst_r & ( ~key_rst)的功能是檢測一個脈沖,也就是說當寄存器key_rst由1變為0時,key_an的值變為高,維持一個時鐘周期 ,這樣就檢測到了一個時鐘周期的脈沖。

2、第二段程序與第一段的程序有點相似,前兩個always語句里其實是做了一個20ms的計數,每隔20ms就會讀取鍵值,把這個鍵值放到寄存器low_sw中,接下來的一個always語句就是把low_sw的值鎖存到low_sw_r里,這樣以來,low_sw和low_sw_r就是前后兩個時鐘周期里的鍵值了,為什么要這樣呢?看下一個語句吧: 

wire [2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]);

       仔細分析,你會發現當沒有鍵按下時,low_sw=low_sw_r=3’b111,此時的led_ctrl=3’b000;只有當low_sw和low_sw_r的某一位分別為0和1時,才可能使led_ctrl的值改變(也就是把led_ctrl的某一位拉高)。那么這意味著當鍵值由1跳變到0時才可能把led_ctrl拉高。回顧前面的20ms賦鍵值,也就是說每20ms內如果出現按鍵被按下,那么有一個時鐘周期里led_ctrl是會被拉高的,而再看后面的程序,led_ctrl的置高就使得相應的LED燈的亮滅做一次改變,這就達到了目的。

3、在單片機的按鍵檢測程序里,當按鍵按下后,然后延時20MS,再判斷是否按下,這樣就起到了按鍵去抖動的作用,而在FPGA中,HDL語言直接對應著實際的硬件電路,沒有單片機里的循環掃描的概念。
 

關閉窗口

相關文章

主站蜘蛛池模板: a在线观看 | 成人福利电影 | 免费视频一区二区 | 日本特黄a级高清免费大片 成年人黄色小视频 | 一区二区在线免费观看 | aaa一区| 久久成| 欧美一区二区三区在线观看 | 午夜视频一区二区 | 视频一区在线 | a级黄色毛片免费播放视频 国产精品视频在线观看 | 国产精品亚洲综合 | 国产精品国产精品国产专区不蜜 | 午夜噜噜噜 | 欧美日本韩国一区二区 | 一区二区三区四区不卡视频 | 国产欧美日韩在线一区 | 国产有码 | 国产乱码精品一区二区三区中文 | 日韩一区二区三区视频 | 国产一区91精品张津瑜 | 久久国产精品免费 | 欧美一级黑人aaaaaaa做受 | 亚洲一区二区三区福利 | 6080亚洲精品一区二区 | 中文字幕亚洲欧美 | 久在线视频播放免费视频 | 99精品欧美一区二区蜜桃免费 | 给我免费的视频在线观看 | 国产精品欧美一区二区三区不卡 | 国产精品自拍视频 | 亚洲综合视频 | 日本不卡在线观看 | 免费高潮视频95在线观看网站 | 欧美涩涩网 | 国产性色视频 | 国产福利资源在线 | 红桃视频一区二区三区免费 | 亚洲欧美日韩一区二区 | 欧美国产精品久久久 | 精品国产欧美日韩不卡在线观看 |