FPGA Verilog移位寄存器应用:边沿检测、信号同步、毛刺滤波

文章目录

      • 1. 端口定义
      • 2. 边沿检测
      • 3. 信号同步
      • 4. 信号滤波
      • 5. 源码
      • 6. 总结

输入信号的边沿检测、打拍同步、毛刺滤波处理,是FPGA开发的基础知识,本文介绍基于移位寄存器的方式,实现以上全部功能:上升沿、下降沿、双边沿检测、输入信号同步、信号滤波。

1. 端口定义

首先是信号定义,以下所有功能的实现都是基于此端口定义。

module get_edge(
    //Inputs
    input clk,
    input rst_n,
    input sig_in,
    
    //Outputs
    output sig_rise,
    output sig_fall,
    output sig_edge
);

2. 边沿检测

最常见的边沿检测设计:

reg sig_reg;

assign sig_rise = (sig_in && !sig_reg); //0->1,可读性差
assign sig_fall = (!sig_in && sig_reg); //1->0,可读性差

assign sig_edge = sig_fall | sig_rise;

always @ (posedge clk) begin
    if(!rst_n) begin
        sig_reg <= 0;
    end
    else begin
        sig_reg <= sig_in;
    end
end

仿真结果如下:
FPGA Verilog移位寄存器应用:边沿检测、信号同步、毛刺滤波_第1张图片
如果sig_in是FPGA管脚输入进来的信号,一般还需要进行打拍去除亚稳态,并同步到FPGA内部的时钟域。

使用移位寄存器如何实现呢?

reg [1:0] sig_in_sreg;

assign sig_rise = (sig_in_sreg == 2'b01);
assign sig_fall = (sig_in_sreg == 2'b10);

always @ (posedge clk) begin
    if(!rst_n) begin
        sig_in_sreg <= 'h0;
    end
    else begin
        sig_in_sreg <= (sig_in_sreg << 1) | sig_in;
        // sig_in_sreg <= {sig_in_sreg[1], sig_in};
    end
end

综合出的电路,和上面的方式是一样的,但是可读性会好很多。

3. 信号同步

如果我要先同步,再检测边沿呢?
常规写法:

reg sig_reg1;
reg sig_reg2;
reg sig_reg3;
reg sig_reg4;

assign sig_rise = (sig_reg3 && !sig_reg4); //0->1
assign sig_fall = (!sig_reg3 && sig_reg4); //1->0

assign sig_edge = sig_fall | sig_rise;

always @ (posedge clk) begin
    if(!rst_n) begin
        sig_reg1 <= 0;
        sig_reg2 <= 0;
        sig_reg3 <= 0;
        sig_reg4 <= 0;
    end
    else begin
        sig_reg1 <= sig_in;
        sig_reg2 <= sig_reg1;
        sig_reg3 <= sig_reg2;
        sig_reg4 <= sig_reg3;
    end
end

FPGA Verilog移位寄存器应用:边沿检测、信号同步、毛刺滤波_第2张图片

移位寄存器写法:

reg [3:0] sig_in_sreg;

assign sig_rise = (sig_in_sreg[3:2] == 2'b01);
assign sig_fall = (sig_in_sreg[3:2] == 2'b10);

always @ (posedge clk) begin
    if(!rst_n) begin
        sig_in_sreg <= 'h0;
    end
    else begin
        sig_in_sreg <= (sig_in_sreg << 1) | sig_in;
        // sig_in_sreg <= {sig_in_sreg[3:1], sig_in};
    end
end

效果一样:
FPGA Verilog移位寄存器应用:边沿检测、信号同步、毛刺滤波_第3张图片

4. 信号滤波

同理,基于移位寄存器,还可以实现对输入信号的毛刺滤波,比如滤除1至N个时钟周期的高脉冲或低脉冲毛刺干扰。


reg [4:0] sig_in_sreg;

assign sig_rise = (sig_in_sreg[4:1] == 4'b0011);    //过滤掉1个clk宽度的毛刺
assign sig_fall = (sig_in_sreg[4:1] == 4'b1100);    //过滤掉1个clk宽度的毛刺

assign sig_edge = sig_fall | sig_rise;

always @ (posedge clk) begin
    if(!rst_n) begin
        sig_in_sreg <= 'h0;
    end
    else begin
        sig_in_sreg <= (sig_in_sreg << 1) | sig_in;
        // sig_in_sreg <= {sig_in_sreg[3:1], sig_in};
    end
end

FPGA Verilog移位寄存器应用:边沿检测、信号同步、毛刺滤波_第4张图片
针对连续的宽度为1个clk的高脉冲、低脉冲连续出现,还可以使用以下方式来判断稳定的边沿:

assign sig_rise = (sig_in_sreg[4:1] == 4'b0111);    
assign sig_fall = (sig_in_sreg[4:1] == 4'b1110);    

5. 源码

/***************************************************************
 * Copyright(C), 2010-2023, CSDN @ whik1194
 * ModuleName : get_edge.v 
 * Date       : 2023年7月16日
 * Time       : 14:36:48
 * Author     : https://blog.csdn.net/whik1194
 * Function   : Edge detection of signals 
 * Version    : v1.0
 *      Version | Modify
 *      ----------------------------------
 *       v1.0    .....
 ***************************************************************/

module get_edge(
    //Inputs
    input clk,
    input rst_n,
    input sig_in,
    
    //Outputs
    output sig_rise,
    output sig_fall,
    output sig_edge
);

reg [4:0] sig_in_sreg;

assign sig_rise = (sig_in_sreg[4:1] == 4'b0011);
assign sig_fall = (sig_in_sreg[4:1] == 4'b1100);

assign sig_edge = sig_fall | sig_rise;

always @ (posedge clk) begin
    if(!rst_n) begin
        sig_in_sreg <= 'h0;
    end
    else begin
        sig_in_sreg <= (sig_in_sreg << 1) | sig_in;
    end
end

/*
// signal filter

reg sig_o;
reg [4:0] sig_in_sreg;
reg [1:0] sig_o_sreg;

wire sig_o_rise = (sig_o_sreg == 2'b01);
wire sig_o_fall = (sig_o_sreg == 2'b10);

// 1.Filter of signals 
always @ (posedge clk) begin
    if(!rst_n) begin
        sig_o <= 0;
    end
    else begin
        if(sreg[4:1] == 4'b1111)
            sig_o <= 1;
        else if(sreg[4:1] == 4'b0000)
            sig_o <= 0;
    end
end

// 2.Edge detection of signals  
always @ (posedge clk) begin
    if(!rst_n) begin
        sreg <= 'h0;
        sig_o_sreg <= 'h0;
    end
    else begin
        sreg <= (sreg << 1) | sig_in;
        sig_o_sreg <= (sig_o_sreg << 1) | sig_o;
    end
end
*/

endmodule   //get_edge end

6. 总结

灵活运用移位寄存器,可以使我们的设计更简洁、可读性更好,模块化程度更高。

你可能感兴趣的:(FPGA,Xilinx,Verilog,边沿,上升沿,滤波,同步)