久久久久久久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語言直接對應著實際的硬件電路,沒有單片機里的循環掃描的概念。
 

關閉窗口

相關文章

主站蜘蛛池模板: 精品久久久久香蕉网 | 亚洲欧洲在线视频 | 色婷综合网 | 亚洲一二三区在线观看 | 亚洲视频一区在线观看 | 成人免费在线视频 | 青草福利 | 久久国产区 | 精品国产乱码久久久久久丨区2区 | 日本成人福利 | 国产一区二区三区 | www.97zyz.com | 国产欧美精品区一区二区三区 | 国产一级淫片a直接免费看 免费a网站 | 一区二区三区欧美在线 | 国产91在线 | 欧美 | 成人国产精品久久 | 成人免费看片 | 粉嫩一区二区三区四区公司1 | 最近最新中文字幕 | 超碰人人做 | 中文一区| 国产一二区视频 | 欧美8一10sex性hd | 九九九久久国产免费 | 神马久久久久久久久久 | 狼人伊人影院 | 做a的各种视频 | 欧美日产国产成人免费图片 | 成人妇女免费播放久久久 | 国产精品日日做人人爱 | 久久爆操 | 成人美女免费网站视频 | 久久久久久免费观看 | 在线观看av网站永久 | 激情视频网站 | 天天干在线播放 | 日韩欧美一区二区三区四区 | 天久久 | 欧美性久久久 | 国产精品电影网 |