13.菜鸟初入FPGA之尖峰脉冲和边沿检测
0赞
发表于 4/7/2016 9:21:14 PM
阅读(6150)
本次笔记记录的是尖峰脉冲和边沿检测例程
1.尖峰脉冲
尖峰脉冲是电路设计中非常重要的一种信号,很多大型设计中模块间的级联握手信号一般都会使用尖峰脉冲,正确的应用尖峰脉冲信号,可以有效的减少系统的逻辑冗余,提高系统稳定性和执行效率
本次笔记以统计按键次消抖次数为例,产生尖峰脉冲(详细按键消抖接下笔记细述)
设计系统结构

例程:
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仿真:

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
仿真:

