文章目录
一、FPGA边沿检测
边沿检测时利用中间变量为被检测信号打拍,然后将中间变量通过一定的逻辑运算得到边沿跳变信号。
1、通过组合逻辑得到边沿跳变信号
1.1 图形示意图
1.2 边沿检测原理
(1)、touch_key_in为输入的被检测信号,touch_key_1和touch_key_2为中间变量。
(2)、touch_key_1在检测到touch_key_in变化后在时钟上升沿执行对touch_key_in信号的跟随。
(3)、touch_key_2在检测到touch_key_1变化后在时钟上升沿执行对touch_key_1信号的跟随。
(4)、所以touch_key_2的信号跳变比touch_key_1的信号跳变总是晚一个周期,利用这个特点,产生边沿检测的标志脉冲就完成的边沿检测。
(5)即当touch_key_1为低电平且touch_key_2为高电平时产生一个下降沿的信号脉冲,标志检测到下降沿。
(6)同理touch_key_1为高电平且touch_key_2为低电平时产生一个上升沿的信号脉冲,标志检测到上升沿。
1.3 边沿检测程序
1.3 .1 边沿检测模块代码
module touch_ctrl_led (
input wire sys_clk,
input wire sys_rst_n,
input wire touch_key_in,
output reg led_out
);
reg touch_key_1;
reg touch_key_2;
wire touch_key_flag;
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0) begin
touch_key_1 <= 1'b0;
touch_key_2 <= 1'b0;
end
else begin
if (touch_key_in == 1'b0) begin
touch_key_1 <= 1'b0;
touch_key_2 <= touch_key_1;
end
else begin
touch_key_1 <= 1'b1;
touch_key_2 <= touch_key_1;
end
end
end
assign touch_key_flag = (touch_key_1 == 1'b0)&&(touch_key_2 == 1'b1);
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0) begin
led_out <= 1'b0;
end
else begin
if (touch_key_flag == 1'b1) begin
led_out <= ~led_out;
end
end
end
endmodule
1.3 .2 边沿检测仿真代码
`timescale 1ns/1ns
module tb_touch_ctrl_led ();
reg sys_clk;
reg sys_rst_n;
reg key_in;
wire led_out;
initial begin
sys_clk <= 1'b0;
sys_rst_n <= 1'b0;
key_in <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
always #10 sys_clk <= ~sys_clk;
always #300 key_in <= ~key_in;
touch_ctrl_led touch_ctrl_led_inst(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.touch_key_in (key_in),
.led_out (led_out)
);
endmodule
1.4 仿真效果
2、通过时序逻辑得到边沿跳变信号
2.1 图形示意图
2.2 边沿检测原理
(1)、touch_key_in为输入的被检测信号,touch_key_1和touch_key_2为中间变量。
(2)、touch_key_1在检测到touch_key_in变化后在时钟上升沿执行对touch_key_in信号的跟随。
(3)、touch_key_2在检测到touch_key_1变化后在时钟上升沿执行对touch_key_1信号的跟随。
(4)、所以touch_key_2的信号跳变比touch_key_1的信号跳变总是晚一个周期,利用这个特点,产生边沿检测的标志脉冲就完成的边沿检测。
(5)、即当touch_key_1为低电平且touch_key_2为高电平时在下一个时钟上升沿产生一个下降沿的信号脉冲,标志检测到下降沿。
(6)、同理touch_key_1为高电平且touch_key_2为低电平时在下一个时钟上升沿产生一个上升沿的信号脉冲,标志检测到上升沿。
(7)、因为产生标志脉冲信号时要等待下一个时钟上升沿的到来,所以用时序逻辑的边沿检测要比组合逻辑边沿信号的输出晚一个周期。
2.3 边沿检测程序
2.3 .1 边沿检测模块代码
module touch_ctrl_led (
input wire sys_clk,
input wire sys_rst_n,
input wire touch_key_in,
output reg led_out
);
reg touch_key_1;
reg touch_key_2;
reg touch_key_flag;
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0) begin
touch_key_1 <= 1'b0;
touch_key_2 <= 1'b0;
end
else begin
if (touch_key_in == 1'b0) begin
touch_key_1 <= 1'b0;
touch_key_2 <= touch_key_1;
end
else begin
touch_key_1 <= 1'b1;
touch_key_2 <= touch_key_1;
end
end
end
//时序逻辑的方法
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0) begin
touch_key_flag <= 1'b0;
end
else begin
if ((touch_key_1 == 1'b0)&&(touch_key_2 == 1'b1)) begin
touch_key_flag <= 1'b1;
end
else begin
touch_key_flag <= 1'b0;
end
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0) begin
led_out <= 1'b0;
end
else begin
if (touch_key_flag == 1'b1) begin
led_out <= ~led_out;
end
end
end
endmodule
2.3 .2 边沿检测仿真代码
同1.3 .2