1555|1

323

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

边沿检测方法 [复制链接]

边沿检测方法.zip (10.22 KB, 下载次数: 5)



 

此帖出自FPGA/CPLD论坛

最新回复

替你转发到回帖中吧 1.1.1.原理介绍 学习HDL语言设计与其他语言不一样,HDL语言设计需要考虑更多的信号的电气特性,时序特性。我们先看一下边沿检测的基本原理。       如上图,为我们待检测信号,可以看出边沿的特性:边沿两侧信号的电平发生了变化。红色为上升沿,绿色为下降沿。上升沿之前电平为低,上升沿之后电平为高。下降沿之前为电平为高,下降沿之后电平为低。   设计思路:设计一个多位寄存器key_sfr[2:0],每当系统时钟来一次,就将key_sfr寄存器低2位与输入信号i_key拼接{key_sfr[1:0],i_key},然后再赋值给key_sfr[2:0]寄存器,这样就把i_key信号同步到了key_sfr寄存器的bit0,而之前bit0移位到了bit1,bit1移位到bit2。容易理解key_sfr[1]为key_sfr[0]前一时刻状态,而key_sfr[2]又为key_sfr[1]前一时刻状态。我们通过key_sfr[2:1]既可以判断相邻时刻,输入信号的电平是否发生了变化。当key_sfr[2:1]=2’b01,表示按键前一时刻为低电平,而后一时刻为高电平,相邻时刻,输入信号的电平发生了变化,此时为上升沿。当key_sfr[2:1]=2’b10,表示按键前一时刻为高电平,而后一时刻为低电平,此时为下降沿。   1.1.2.  代码实现 代码主要实现了按键按下时,LED指示灯输出不同的状态,循环8次按下按键,LED分别输出8种不同的指示灯状态。   1. module edge_detect 2. ( 3. input i_clk ,//模块输入时钟 ,50mhz 4. input i_rst_n ,//复位信号,低电平有效 5. input i_key ,//按键输入 6. output reg [3:0] o_led_out //LED指示灯输出 7. ); 8. reg [2:0] key_sfr ; //按键同步移位寄存器 9. wire w_key_rise ;//按键上升沿 10. wire w_key_fall ;//按键下降沿 11. //------------------------------------------------------------------- 12. // 同步i_key信号,i_key为按键输入异步时钟域信号,应同步到本地时钟域 13. //------------------------------------------------------------------- 14. always @ (posedge i_clk or negedge i_rst_n) 15. begin 16. if(!i_rst_n) 17. key_sfr <=3'b000; 18. else 19. key_sfr <={key_sfr[1:0],i_key} ; // key_sfr[2]信号是 i_key经过同步3拍后的信号 20. end 21. //------------------------------------------------------------------- 22. // 判别i_key信号的边沿 23. //------------------------------------------------------------------- 24. assign w_key_rise=(key_sfr[2:1]==2'b01)?1'b1:1'b0; 25. //------------------------------------------------------------------- 26. // 按键按下时,计数器加1,循环记数从0-7. 27. //------------------------------------------------------------------- 28. always @ (posedge i_clk or negedge i_rst_n) 29. begin 30. if(!i_rst_n) 31. key_cnt <=3'b000; 32. else if(w_key_rise) 33. key_cnt <=key_cnt + 1'b1; 34. end 35. //------------------------------------------------------------------- 36. // 计数器在不同状态时输出不同的LED指示灯状态 37. //------------------------------------------------------------------- 38. always @ (posedge i_clk or negedge i_rst_n) 39. begin 40. if(!i_rst_n) 41. o_led_out <=4'b1110; 42. else begin 43. case(key_cnt) //计数器不同状态,输出指示灯状态不同 44. 3'b000: o_led_out<= 4'b1110; 45. 3'b001: o_led_out<= 4'b1101; 46. 3'b010: o_led_out<= 4'b1011; 47. 3'b011: o_led_out<= 4'b0111; 48. 3'b100: o_led_out<= 4'b1100; 49. 3'b101: o_led_out<= 4'b1001; 50. 3'b110: o_led_out<= 4'b0011; 51. 3'b111: o_led_out<= 4'b0000; 52. default: o_led_out<= o_led_out; 53. endcase 54. end 55. end 56. endmodule   1.1.3.  功能仿真 我们不再列出仿真代码,大家可以参考sim文件夹下的代码。双击的批处理文件modelsim_run.bat,就可以启动仿真,调出仿真结果,如下图。可以看到我们模拟8次按键操作,每次按键松开时,LED指示灯都切换至不同的输出状态。       下面我们再通过仿真,具体看一下边沿检测的时序仿真结果。我们找到任意一个i_key信号的上升沿,放大至下图。可以看到i_key先置1,而key_sfr的bit0延迟了一个时钟周期后才置1。key_sfr的bit1则比i_key信号延迟了2个时钟周期,而key_sfr的bit2则比i_key信号延迟了3个时钟周期。上升沿标志信号w_key_rise比实际i_key上升沿是延迟了2个时钟周期的。大家在今后的设计中一定要注意这些时序的小细节,考虑这些延迟是否会给你的设计带来问题。       1.1.4.  实验结果 根据第四章2.4.6节介绍的程序烧写方法,将工程烧写文件烧写至FPGA中,观察现象,并验证设计的正确性。     详情 回复 发表于 2020-6-10 16:00
点赞 关注
 

回复
举报

86

帖子

751

TA的资源

一粒金砂(中级)

沙发
 

替你转发到回帖中吧


1.1.1.原理介绍

学习HDL语言设计与其他语言不一样,HDL语言设计需要考虑更多的信号的电气特性,时序特性。我们先看一下边沿检测的基本原理。

 

 

 

如上图,为我们待检测信号,可以看出边沿的特性:边沿两侧信号的电平发生了变化。红色为上升沿,绿色为下降沿。上升沿之前电平为低,上升沿之后电平为高。下降沿之前为电平为高,下降沿之后电平为低。

 

设计思路:设计一个多位寄存器key_sfr[2:0],每当系统时钟来一次,就将key_sfr寄存器低2位与输入信号i_key拼接{key_sfr[1:0],i_key},然后再赋值给key_sfr[2:0]寄存器,这样就把i_key信号同步到了key_sfr寄存器的bit0,而之前bit0移位到了bit1,bit1移位到bit2。容易理解key_sfr[1]为key_sfr[0]前一时刻状态,而key_sfr[2]又为key_sfr[1]前一时刻状态。我们通过key_sfr[2:1]既可以判断相邻时刻,输入信号的电平是否发生了变化。当key_sfr[2:1]=2’b01,表示按键前一时刻为低电平,而后一时刻为高电平,相邻时刻,输入信号的电平发生了变化,此时为上升沿。当key_sfr[2:1]=2’b10,表示按键前一时刻为高电平,而后一时刻为低电平,此时为下降沿。

 

1.1.2.  代码实现

代码主要实现了按键按下时,LED指示灯输出不同的状态,循环8次按下按键,LED分别输出8种不同的指示灯状态。

 

1.  module edge_detect

 

2.      (

 

3.          input                  i_clk        ,//模块输入时钟 ,50mhz

 

4.          input                  i_rst_n      ,//复位信号,低电平有效

 

5.          input                  i_key        ,//按键输入

 

6.          output reg [3:0]       o_led_out       //LED指示灯输出

 

7.      );

 

8.      reg    [2:0]               key_sfr               ;   //按键同步移位寄存器

 

9.      wire                       w_key_rise            ;//按键上升沿

 

10.     wire                       w_key_fall            ;//按键下降沿  

 

11. //-------------------------------------------------------------------

 

12. //  同步i_key信号,i_key为按键输入异步时钟域信号,应同步到本地时钟域

 

13. //-------------------------------------------------------------------

 

14.     always @ (posedge i_clk or negedge i_rst_n)

 

15.     begin

 

16.         if(!i_rst_n)

 

17.             key_sfr      <=3'b000; 

 

18.         else 

 

19.             key_sfr      <={key_sfr[1:0],i_key}   ; // key_sfr[2]信号是                          i_key经过同步3拍后的信号                          

 

20.     end

 

21. //-------------------------------------------------------------------

 

22. //  判别i_key信号的边沿

 

23. //-------------------------------------------------------------------  

 

24.     assign  w_key_rise=(key_sfr[2:1]==2'b01)?1'b1:1'b0;

 

25. //-------------------------------------------------------------------

 

26. //  按键按下时,计数器加1,循环记数从0-7.

 

27. //-------------------------------------------------------------------    

 

28.     always @ (posedge i_clk or negedge i_rst_n)

 

29.     begin

 

30.         if(!i_rst_n)

 

31.             key_cnt        <=3'b000;

 

32.         else if(w_key_rise)

 

33.             key_cnt        <=key_cnt  +   1'b1;

 

34.     end

 

35. //-------------------------------------------------------------------

 

36. //  计数器在不同状态时输出不同的LED指示灯状态

 

37. //-------------------------------------------------------------------     

 

38.     always @ (posedge i_clk or negedge i_rst_n)

 

39.     begin

 

40.         if(!i_rst_n)

 

41.             o_led_out   <=4'b1110;   

 

42.         else begin

 

43.             case(key_cnt)  //计数器不同状态,输出指示灯状态不同

 

44.                 3'b000:     o_led_out<=  4'b1110;      

 

45.                 3'b001:     o_led_out<=  4'b1101;  

 

46.                 3'b010:     o_led_out<=  4'b1011; 

 

47.                 3'b011:     o_led_out<=  4'b0111; 

 

48.                 3'b100:     o_led_out<=  4'b1100;     

 

49.                 3'b101:     o_led_out<=  4'b1001;                                                            

 

50.                 3'b110:     o_led_out<=  4'b0011;

 

51.                 3'b111:     o_led_out<=  4'b0000;

 

52.                 default:    o_led_out<=  o_led_out;               

 

53.             endcase     

 

54.         end

 

55.     end    

 

56. endmodule

 

1.1.3.  功能仿真

我们不再列出仿真代码,大家可以参考sim文件夹下的代码。双击的批处理文件modelsim_run.bat,就可以启动仿真,调出仿真结果,如下图。可以看到我们模拟8次按键操作,每次按键松开时,LED指示灯都切换至不同的输出状态。

 

 

 

下面我们再通过仿真,具体看一下边沿检测的时序仿真结果。我们找到任意一个i_key信号的上升沿,放大至下图。可以看到i_key先置1,而key_sfr的bit0延迟了一个时钟周期后才置1。key_sfr的bit1则比i_key信号延迟了2个时钟周期,而key_sfr的bit2则比i_key信号延迟了3个时钟周期。上升沿标志信号w_key_rise比实际i_key上升沿是延迟了2个时钟周期的。大家在今后的设计中一定要注意这些时序的小细节,考虑这些延迟是否会给你的设计带来问题。

 

 

 

1.1.4.  实验结果

根据第四章2.4.6节介绍的程序烧写方法,将工程烧写文件烧写至FPGA中,观察现象,并验证设计的正确性。

 

此帖出自FPGA/CPLD论坛
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表