FPGA学习笔记二:输入电路的各种边沿检测(内含Verilog代码)

 

一、边沿检测的简述

我们通常会把边沿检测用在按键输入的检测,这一检测手段并不唯一(单片机也可以实现)。按键按下时,输入信号key出现一个下降沿,擡起后又变为一个上升沿。如果输入信号是不存在毛刺和抖动的理想信号,边沿检测就显得尤为重要,当然能够滤除毛刺与抖动的优化的检测电路也在本篇博客的讨论范围之内。

二、上升沿与双边沿的检测方法

1.上升沿的检测方法(下降沿方法自行类比)

(1)设计思路

 *******检测电路其侧重电路的设计而非代码的书写能力*******
  • 1

我们的设计目标是能够在一个时钟周期内(两个上升沿之间)检测到输入信号的上升沿(即由0到1的跳变)。因此要明确:电路中至少要有时序逻辑电路的存在才让输入的前后状态实现比较。设计步骤如下:

  1. 先用一个D触发器来记录之前的输入的状态(last_state);

  2. 把之前输入的状态和当前的状态(current_state)进行组合逻辑来实现在last_state == 0&& current_state == 1时电路的输出positive_edge=1;画出真值表可以发现:这一组合逻辑电路通过:assign positive_edge=~last_state&current_state
    这一条连续赋值语句就可以达到我们的目标(可参考以下真值表);

  3. 到现在为止,理论上,我们已经可以检测到一个周期内的边沿变化;

(2)实现与功能评估

根据上述思路编写代码。编写时注意:上述思路中的last_state就是下述代码片中的din;current_state对应的就是代码片中的输入端口in。代码如下::

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] positive_edge
);
    reg  [7:0]din;
    always @(posedge clk) begin
       din<= in;
    end
    assign positive_edge=~din&in;
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

波形仿真结果(为了便于便于直观体现输出特性,笔者在粘贴代码时对输出端口的命名进行了修改,代码中的positive_edge端口就是下图波形仿真图中的pedge):
initial waveform
由上图仿真波形可以看出,此时的边沿检测,代码部分输出通过连续赋值语句实现,因此输出会被两个输入信号驱动,分别为声明的reg寄存器型变量din和输入信号in。也就是说输出信号pedge不会等待时钟的到来,而是会在检测到一个第一个上升沿后立刻发生响应。 事实上这种响应方式是不严谨的。
原因是: 联系波形仿真图还有RTL仿真图,如果这一段代码应用于纯电路设计,那似乎是可以满足要求,但试想我们使用边沿检测的场合通常是按键检测,现实生活中的按键其簧片在按下后会伴随着一段时间的抖动,因此这种使用连续赋值语句的组合逻辑输出自然会让检测结果带上毛刺。或者我们可以这样理解:虽然我们对于输入信号做了延时处理(通过一个D触发器来实现),但是在最终的2输入与门的其中一个输入端是输入信号in,in在一个非常小的时间段内的任意电平变化都会在assign语句所表征的组合逻辑电路的输出即刻体现,让之前的D触发器延迟效果彻底失效。因此我们需要让最终的positive_edge输出能够稳定地检测到一段在很短时间内(通常是小于半个时钟周期)存在毛刺或者抖动的边沿信号。

(3)改进与代码实现

  • 改进的思路:在组合逻辑电路的后端再加上一个时序逻辑电路模块,在此处依旧是通过简单的D触发器来实现。这样问题就被简单化了:只要在两个时钟中间出现了上升沿(无论中间发生了多少次抖动),上升沿检测输出端口positive_edge都会在第二个时钟同步地发出检测信号,并且经过一个时钟后回零。改进后的代码如下:
module top_module(
	input clk,
	input [7:0] in,
	output reg [7:0] positive_edge);	
	reg [7:0] din;				
	always @(posedge clk) begin
		din <= in;			
		positive_edge <= in & ~din;	
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 波形仿真结果(为了便于便于直观体现输出特性,笔者依旧是对输出端口的命名进行了修改,代码中的positive_edge端口就是下图波形仿真图中的pedge):
    在这里插入图片描述

2.双边沿的检测方法

(1)设计思路

有了单边沿检测的思路作为借鉴,双边沿的检测其设计思路基本相同。比较它与前者的功能与波形区别:双边沿需要在上升沿和下降沿时都让输出为1,因此只需要改变其组合电路部分的真值表(真值表如下)即可,时序电路部分不需要做出改变。

last_state (din) current_state(in) positive_edge
0 0 0
0 1 1
1 0 1
1 1 0

根据真值表可写出其逻辑表达式:assign anyedge= last_state^current_state; 同样,为了让电路能够容忍毛刺的存在,在组合电路输出再加上一个D触发器实现一个时钟的延迟。

(2)代码实现

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] anyedge
);
    reg [7:0]din;
    always @(posedge clk) begin
    	din<=in;
        anyedge<=din^in;
    end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

波形仿真见下图:
在这里插入图片描述
如上图所示,在in[1]的第一个上升沿到来时,anyedge[1]在随后的第二个时钟上升沿置一并在第三个时钟上升沿变为零(说明检测到了最低位的一个边沿变化)。随后的一个in[1]的一对双沿变化(先是下降沿然后是上升沿),随后anyedge[1]检测信号持续了两个时钟,说明两个边沿变化都被检测到了。
在这里插入图片描述

三、边沿捕捉电路

首先说明一点:这一部分的电路基于笔者在HDLBits上碰到的一道题目,解决是碰到了一些困惑,因此一并归入了边沿检测电路的部分进行整理、总结和分享。先上题目传送门:HDLBits:边沿捕捉电路。按照题目的所提出的要求, 边沿捕捉与边沿检测的区别在于,边沿捕捉是在检测到输入信号的边沿变化之后输出变为高电平,而“捕捉”的特点就是这个高电平会一直保持直到复位信号reset被置一有效!!!

  • 此题要求检测输入信号中的下降沿,同时根据捕捉的定义,检测到的输出结果out会一直保持直到reset清零复位。

1.设计思路

我们可以把对于题目要求分割为两个部分来实现:一是能够检测到下降沿;二是下降沿需要一直保持直到reset有效将其复位。 那么解题就简单化了:
(1) 第一个部分是对本博客之前讨论过的上升沿检测的变形,只要修改其中的组合逻辑电路部分就可以实现: assign capture=~in&temp;//capture用来储存捕捉结果.
(2) 第二个部分即需要在后边一个触发器(这里说的比较笼统,读者可参考前文的设计思路应该能体会到后边的触发器是哪个)加上时序电路的复位信号,同时还需要对组合电路部分进行改进,让输出信号out在置高后一直保持输出☞: assign out=out|capture;//将捕捉结果保持.

-根据设计思路可以在大脑中大致综合出如下电路图(为了方便理解,暂时将代码改成了三位输入和输出,但各个位上的边沿捕捉原理相同):
在这里插入图片描述

2.代码实现

module top_module (clk,reset,in,out);
    input clk;
    input reset;
    input [31:0] in;
    output [31:0] out;
    reg [31:0] temp;
    wire [31:0] capture;

    assign capture = ~in & temp;//检测到上升沿之后,来确定我们的输出
    always @ (posedge clk)
        begin
            temp <= in;
            if(reset)
                out <= 32'b0;
            else
                out<=out|capture;
        end
endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

最终计算机给出的综合波形图如下:
在这里插入图片描述

四、总结

本文主要介绍了边沿检测与边沿捕捉的原理与设计思路。实际上,后者可以基于前者的设计思路进行完善和设计。无论是边沿检测还是捕捉,都需要通过寄存器来抓住其last_state和current_state(即前后态)的变化,通过画出真值表找出对应的组合逻辑,并且为了排除毛刺和抖动的影响通过延迟输出来提高响应与检测精度。其它的边沿检测问题基本都可以基于这一思路根据所需功能进行改进,但改进的核心部分还是着重于组合电路模块。

五、其它补充

本次博客主要是本人在HDLBits中碰到的几个问题和自己完成题目后的个人理解及对波形的分析。如有错误欢迎读者在评论区或者私信留言指正,之后如果再碰到类似于边沿检测或捕捉的其它问题都会及时地更新。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章