边沿检测指的是检测一个信号的上升沿或者下降沿,如果发现上升沿或者下降沿,则给出一个信号指示出来。边沿检测电路 一般分为上升沿检测电路、下降沿检测电路和双沿检测电路。
复杂的逻辑设计里面,很多情况都需要检测信号的跳变,如果一个信号发生跳变,则给出一个指示,这个指示用来触发其他的动作,这里就需要有一个边沿检测电路 。
上升沿检测电路
信号检测由 0变 1的过程 ,就是上升沿检测电路( posedge edge 信号检测由1变0的过程 就是下降沿检测电路( negedge edge)。若上升沿和下降沿都检测,则这个电路就是双沿检测电路( double edge)。
在always块的敏感信号列表中可以直接用 posedge和 negedge来提取上升沿和下降沿,但是如果要在 always程序块的内部检测上升沿或者下降沿呢?还是用 poesedge和 negedge吗? 我们来实验下我们的推测,代码如下:
module edge_test
(
input clk , // system clock 50Mhz on board
input rst_n, // system rst, low active
input a ,
input b ,
output reg y // output signal
);
//==============================================================
// ------------------------- MAIN CODE ------------------------
//==============================================================
always @ (posedge clk or negedge rst_n or posedge a) begin
if (rst_n == 1'b0)
y <= 1'b0 ;
else
y <= b ;
end
endmodule
always块的信号敏感变量有三个,一个是时钟clk,一个是复位rst_n,一个是a信号。y信号是在时钟clk或者a信号的上升沿进行跳变,在复位的rst_n下降沿进行复位。
通过Quartus或者 Vivado等工具进行全编译,在 Quartus里面发现是可以编译成功的, 编译后的Quartus RTL viewer显示的电路结构如下:
这个只是一个组合逻辑的选择电路,并没有寄存器,分析告警,
这个意思是说输出y和clk或者a都没有关系,也就是说这个边沿检测电路不可行。这个地方也间接说明always块的信号敏感变量只能有一个时钟和一个复位。带时钟的always块电路都是寄存器,而寄存器一般只有一个时钟信号,所以边沿检测不能直接利用always块的信号敏感变量作为边沿检测。
如上图所示,a信号是一个持续2个时钟周期的信号,如果想得到a信号的上升沿,这个上升沿就是a_posedge信号。a_posedge信号是一个持续1个时钟周期的脉冲信号,把a信号寄存一拍,得到a_dly1信号,再用a信号和a_dly1取反再相与,就可以得到一个持续1个时钟周期的脉冲信号,这个a_posedge信号就是a的上升沿指示信号。
下降沿检测电路。
如上图所示,a信号是一个持续2个时钟周期的信号,如果想得到a信号的下降沿,这个下降沿就是a_negedge信号。a_negedge信号是一个持续1个时钟周期的脉冲信号,把a信号寄存一拍,得到a_dly1信号,再把a信号取反,用a取反的信号和a_dly1相与,就可以得到一个持续1个时钟周期的脉冲信号,这个a_negedge信号就是a的下降沿指示信号。
下双沿检测电路
如上图所示,a信号是一个持续2个时钟周期的信号,如果想得到a信号的上升沿和下降沿,这个信号就是a_edge信号。a_edge信号刚好是a和a_dly1信号不同的地方为高电平,也就是a和a_dly1异或的结果就是a_edge信号,这个信号在a的上升沿持续一个时钟周期,然后在a的下降沿后又持续一个时钟周期。
程序设计
module edge_test
(
input clk , // system clock 50Mhz on board
input rst_n, // system rst, low active
input a ,
output y1 , // output signal
output y2 , // output signal
output y3 // output signal
);
reg a_dly1 ;
//================================================================
// ------------------------- MAIN CODE --------------------------
//================================================================
always @ (posedge clk or negedge rst_n ) begin
if (rst_n == 1'b0)
a_dly1 <= 1'b0 ;
else
a_dly1 <= a ;
end
assign y1 = a & ( ~a_dly1 ) ;
assign y2 = ~a & a_dly1 ;
assign y3 = a ^ a_dly1 ;
endmodule
从上图可以看出,a_dly1是a寄存一拍的结果,y1是上升沿检测输出,y2是下降沿检测输出,y3是双沿检测输出(异或门)。
参考引用学习:
《正点原子逻辑设计指南 V1.9》