本次笔记记录的是尖峰脉冲和边沿检测例程
1.尖峰脉冲
尖峰脉冲是电路设计中非常重要的一种信号,很多大型设计中模块间的级联握手信号一般都会使用尖峰脉冲,正确的应用尖峰脉冲信号,可以有效的减少系统的逻辑冗余,提高系统稳定性和执行效率
本次笔记以统计按键次消抖次数为例,产生尖峰脉冲(详细按键消抖接下笔记细述)
设计系统结构
例程:
moduleSpike_pulse(clk,rst_,key_in,sum);inputclk,rst_;inputkey_in;//外部信号输入outputreg[3:0]sum;//按键按下次数统计regrst_n;//异步复位同步释放always@(posedgeclk)rst_n<=rst_;reg[9:0]cnt;//消抖延时计数regstate;regpos_flag;//尖峰脉冲寄存器always@(posedgeclkornegedgerst_n)beginif(!rst_n)begincnt<=0;state<=0;pos_flag<=0;endelsebegincase(state)0:beginif(cnt<10)begin//消抖延时未开始计数if(!key_in)//key_in==0按键按下cnt<=cnt+1;elsecnt<=0;endelsebeginpos_flag<=1;cnt<=0;state<=1;endend1:beginpos_flag<=0;if(key_in)//key_in==1按键放开state<=0;enddefault:state<=0;endcaseendendalways@(posedgeclkornegedgerst_n)if(!rst_n)sum<=0;elseif(pos_flag)sum<=sum+1'b1;endmodule//tb`timescale1ns/1ns`defineclock_period20moduleSpike_pulse_tb;regclk,rst_;regkey_in;wire[3:0]sum;initialclk=1;always#(`clock_period/2)clk=~clk;always@(posedgeclk)//随机函数使用begin#(`clock_period*50)key_in={$random}%2;endinitialbeginrst_=0;key_in=1;#(`clock_period*5);rst_=1;#(`clock_period+1);//press_key;#(`clock_period*1000);$stop;end//taskpress_key;//任务函数的使用//begin//#500key_in=0;//#500key_in=1;//#500key_in=0;//#500key_in=1;//#500key_in=0;//#500key_in=1;//#500key_in=0;//#500key_in=1;//#500key_in=0;//#500key_in=1;//#500key_in=0;//#500key_in=1;//end//endtaskSpike_pulseSpike_pulse(.clk(clk),.rst_(rst_),.key_in(key_in),.sum(sum));endmodule
仿真:
2.边沿检测
边沿检测,就是检测输入信号或者FPGA 内部逻辑信号的跳变,即对信号上升沿或者下降沿的检测
分析一下这个电路结构和工作原理可以得到
( 1 ) 当信号出现上升沿以后, pos_edge 会出现一个时钟周期的“尖峰脉冲”
( 2 ) 当信号出现下降沿以后, neg_edge 会出现一个时钟周期的“尖峰脉冲”
例程:
moduleEdge_check(clk,rst_n,key,p_edge,n_edge);inputclk,rst_n;inputkey;outputp_edge,n_edge;//上升沿和下降沿检测标志regkey_r;//键值寄存器always@(posedgeclkornegedgerst_n)if(!rst_n)key_r<=1;elsekey_r<=key;assignn_edge=key_r&(!key);//key由1->0n_edge=1;assignp_edge=!key_r&key;//key由0->1p_edge=1;endmodule//tb`timescale1ns/1ns`defineclock_period20moduleEdge_check_tb;regclk,rst_n;regkey;wirep_edge,n_edge;initialclk=1;always#(`clock_period/2)clk=~clk;always@(posedgeclk)//随机函数使用begin#(`clock_period*50)key={$random}%2;endinitialbeginrst_n=0;key=1;#(`clock_period*5);rst_n=1;#(`clock_period+1);//press_key;#(`clock_period*1000);$stop;endEdge_checkEdge_check(.clk(clk),.rst_n(rst_n),.key(key),.p_edge(p_edge),.n_edge(n_edge));endmodule
仿真: