tag 标签: 边沿检测

相关博文
  • 热度 19
    2016-4-18 17:37
    1117 次阅读|
    0 个评论
     本次笔记记录的是尖峰脉冲和边沿检测例程          1.尖峰脉冲     尖峰脉冲是电路设计中非常重要的一种信号,很多大型设计中模块间的级联握手信号一般都会使用尖峰脉冲,正确的应用尖峰脉冲信号,可以有效的减少系 统的逻辑冗余,提高系统稳定性和执行效率     本次笔记以统计按键次消抖次数为例,产生尖峰脉冲(详细按键消抖接下笔记细述)     设计系统结构      例程: module Spike_pulse( clk, rst_, key_in, sum ); input clk,rst_; input key_in;//外部信号输入 output reg  sum;//按键按下次数统计 reg rst_n;//异步复位同步释放 always @(posedge clk) rst_n = rst_; reg  cnt;//消抖延时计数 reg state; reg pos_flag;//尖峰脉冲寄存器 always @(posedge clk or negedge rst_n) begin if(!rst_n)begin cnt = 0; state = 0; pos_flag = 0; end else begin case (state) 0: begin if(cnt  10)begin   //消抖延时未开始计数 if(!key_in)      //key_in==0 按键按下 cnt = cnt + 1; else cnt = 0; end else begin pos_flag = 1; cnt = 0; state = 1; end end 1: begin pos_flag = 0; if(key_in)//  key_in==1按键放开 state = 0; end default: state = 0; endcase end end always @(posedge clk or negedge rst_n) if(!rst_n) sum = 0; else if(pos_flag) sum = sum + 1'b1; endmodule  //tb `timescale 1ns/1ns `define clock_period 20 module Spike_pulse_tb; reg clk,rst_; reg key_in; wire  sum; initial clk = 1; always #(`clock_period/2) clk = ~ clk; always @(posedge clk)//随机函数使用 begin #(`clock_period*50) key_in ={$random}%2; end initial begin rst_ = 0; key_in = 1; #(`clock_period*5); rst_ = 1; #(`clock_period + 1); //press_key; #(`clock_period*1000); $stop; end // task press_key;//任务函数的使用 // begin // #500 key_in = 0; // #500 key_in = 1; // #500 key_in = 0; // #500 key_in = 1; // #500 key_in = 0; // #500 key_in = 1; // #500 key_in = 0; // #500 key_in = 1; // #500 key_in = 0; // #500 key_in = 1; // #500 key_in = 0; // #500 key_in = 1; // end // endtask Spike_pulse Spike_pulse( .clk(clk), .rst_(rst_), .key_in(key_in), .sum(sum) ); endmodule 仿真:    2.边沿检测 边沿检测,就是检测输入信号或者FPGA 内部逻辑信号的跳变,即对信号上 升沿或者下降沿的检测 分析一下这个电路结构和工作原理可以得到 ( 1 ) 当信号出现上升沿以后, pos_edge 会出现一个时钟周期的“尖峰脉 冲”  ( 2 ) 当信号出现下降沿以后, neg_edge 会出现一个时钟周期的“尖峰脉 冲” 例程: module Edge_check( clk, rst_n, key, p_edge, n_edge ); input clk,rst_n; input key; output p_edge,n_edge;//上升沿和下降沿检测标志 reg key_r;//键值寄存器 always @(posedge clk or negedge rst_n) if(!rst_n) key_r = 1; else key_r = key; assign n_edge = key_r  (!key);//key由1-0 n_edge = 1; assign p_edge = !key_r  key; //key 由0-1 p_edge = 1; endmodule //tb `timescale 1ns/1ns `define clock_period 20 module Edge_check_tb; reg clk,rst_n; reg key; wire p_edge,n_edge; initial clk = 1; always #(`clock_period/2) clk = ~ clk; always @(posedge clk)//随机函数使用 begin #(`clock_period*50) key ={$random}%2; end initial begin rst_n = 0; key = 1; #(`clock_period*5); rst_n = 1; #(`clock_period + 1); //press_key; #(`clock_period*1000); $stop; end Edge_check Edge_check( .clk(clk), .rst_n(rst_n), .key(key), .p_edge(p_edge), .n_edge(n_edge) ); endmodule 仿真:
  • 热度 19
    2015-3-24 13:41
    1039 次阅读|
    0 个评论
       EDN博客精华文章   作者: tengjingshu   在很多时候都要对输入脉冲进行边沿检测,如PS/2时序,ps2_data数据在ps2_clk时钟下降沿接收。   边沿检测Verilog程序代码:   布线布局后仿真波形如下图: 点击看原图   可以注意到其中的移位寄存器用了非阻塞赋值(=) ps2_clk_r0=ps2_clk; ps2_clk_r1=ps2_clk_r0; ps2_clk_r2=ps2_clk_r1;   如果用阻塞赋值的话,综合的时候会把其中两个寄存器去点,用阻塞赋值(=) ps2_clk_r0=ps2_clk; ps2_clk_r1=ps2_clk_r0; ps2_clk_r2=ps2_clk_r1;   会出来这样的警告:   WARNING:Xst:646 - Signal ps2_clk_r0 is assigned but never used.       Register ps2_clk_r2 equivalent to ps2_clk_r1 has been removed       Found 1-bit register for signal ps2_clk_r1.   WARNING:Xst:2677 - Node ps2_clk_r1 of sequential type is unconnected in block DetecEdge. 点击看原图   从RTL可以看到,只剩ps2_clk_r1一个D触发器。 点击看原图   上图是非阻塞赋值综合后的RTL,可以看出,有三个D触发器做移位寄存器。通过移位,对边沿进行检测。   程序工程文件下载: http://space.ednchina.com/upload/2009/3/24/86bb5e63-8959-47c4-af52-10ac330554d3.rar   代码还有一种写法:   布线布局后仿真波形和之前程序的仿真波形一样 点击看原图   程序文件下载: http://space.ednchina.com/upload/2009/3/24/5286d476-c43c-4b99-b658-5d53865ce19a.rar    参考资料:   1)verilog的PS2键盘解码——特权’s blog    http://blog.ednchina.com/ilove314/153929/message.aspx   2) 模拟PS2协议,丢掉4x4键盘,来用标准键盘吧!_阿虚的电子小屋    http://hi.baidu.com/aokikyon/blog/item/e46dc2368d9f76350a55a99a.html
  • 热度 30
    2015-3-12 11:30
    1212 次阅读|
    0 个评论
    最近一直在看异步时钟域的亚稳态问题,有好多疑问   从简单的电平同步器开始,如上图。 假设clk2 = 1.5clk1(或者更高),用clk2来同步clk1的单bit data,假设data刚好在clk2的上升沿跳变(data在clk2的Tsu和Tth区间类跳变),这时产生亚稳态,导致reg1的输出震荡,输出的值Q1不固定,假设输出0(0是错误值,也有可能输出1正确值),结果导致本来在clk1里只有一个周期的低电平,经clk2同步后出现两个周期的低电平,这样第一级reg1的输出错误值会一直沿着reg2传递下去,这种同步错误应该是无法纠正的。 对于单bit的数据且有效电平只有原时钟域的一拍这种情况,可以用边沿检测 那么问题来了,对于单bit数据但是有效电平不只一拍的情况,假如FPGA作为IIC从机来接收sda过来的数据,我们应该怎么避免或者减少上面情况所带来的问题。