Augus

13.菜鸟初入FPGA之尖峰脉冲和边沿检测

0
阅读(3885)

        本次笔记记录的是尖峰脉冲和边沿检测例程       

 1.尖峰脉冲

    尖峰脉冲是电路设计中非常重要的一种信号,很多大型设计中模块间的级联握手信号一般都会使用尖峰脉冲,正确的应用尖峰脉冲信号,可以有效的减少系统的逻辑冗余,提高系统稳定性和执行效率

    本次笔记以统计按键次消抖次数为例,产生尖峰脉冲(详细按键消抖接下笔记细述)

    设计系统结构

    2016-04-07_195955.jpg

例程:

module Spike_pulse(
							clk,
							rst_,
							key_in,
							sum
						);
						
	input clk,rst_;
	input key_in;//外部信号输入
	
	output reg [3:0]sum;//按键按下次数统计
	
	reg rst_n;//异步复位同步释放
	always @(posedge clk)
		rst_n <= rst_;
	
	reg [9:0]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 [3:0]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

仿真:

2016-04-07_204804.jpg


 2.边沿检测

边沿检测,就是检测输入信号或者FPGA 内部逻辑信号的跳变,即对信号上升沿或者下降沿的检测

2016-04-07_210412.jpg

分析一下这个电路结构和工作原理可以得到

( 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
	

仿真:

2016-04-07_212155.jpg