Augus

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

0
阅读(3731)

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

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



Baidu
map