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

输入信号的边沿检测、打拍同步、毛刺滤波处理,是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

仿真结果如下:

如果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

移位寄存器写法:

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

效果一样:

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


针对连续的宽度为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. 总结

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

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
边沿检测电路的verilog实现可以使用以下方法之一: 1. 上升沿检测方法:可以使用触发器和比较器来实现。当输入信号从低电平变为高电平时,触发器的输出状态会改变,从而检测上升沿。这个方法可以通过编写verilog代码来描述触发器和比较器的逻辑。 2. 双边沿检测方法:双边沿检测可以检测信号上升沿和下降沿。同样可以使用触发器和比较器来实现,当输入信号从低电平变为高电平或从高电平变为低电平时,触发器的输出状态会改变,从而检测边沿。这个方法也可以通过编写verilog代码来描述触发器和比较器的逻辑。 需要注意的是,边沿检测电路的设计思路是侧重于电路的设计,而不是代码的书写能力。可以根据具体的需求和电路设计原则来选择合适的方法实现边沿检测电路。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [边沿检测上升沿检测、下降沿检测、双边沿检测-verilog代码-Testbench-RTL电路图-仿真结果)](https://download.csdn.net/download/Loudrs/87855942)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [FPGA学习笔记二:输入电路的各种边沿检测(内含Verilog代码)](https://blog.csdn.net/m0_51272018/article/details/113662445)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [FPGA基础学习——Verilog实现的边沿检测上升沿下降沿检测)及Modelsim仿真](https://blog.csdn.net/H19981118/article/details/112534176)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

whik1194

如果对你有帮助,欢迎打赏。谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值