异步边沿检测的核心思想是利用信号的延迟来捕获信号的跳变。对于上升沿检测,我们需要检测信号从低电平到高电平的变化。通常的做法是使用三级寄存器(D触发器链)来实现延迟,然后通过逻辑运算来判断是否发生了上升沿。(一般采用多级寄存器的方法减少亚稳态的发生概率,至少要用三级寄存器来实现。)
异步上升沿检测

input sig_a;
input clk;
input reset_n;
reg sig_a_d1,sig_a_d2,sig_a_d3;
wire sig_a_flag;//posedge信号(上升沿)
assign sig_a_posedge=sig_a_d2&!sig_a_d3;
always@(posedge clk or negedge reset_n)
if(!reset_n)begin
sig_a_d1<=1'b0;
sig_a_d2<=1'b0;
sig_a_d3<=1'b0;
end
else begin
sig_a_d1<=sig_a;
sig_a_d2<=sig_a_d1;
sig_a_d3<=sig_a_d2;
end
工作过程
假设 sig_a 的变化如下:
- 初始状态:
sig_a = 0 - 在某个时刻,
sig_a变为1,并保持一个时钟周期以上。
寄存器的状态变化如下:
-
时钟周期 1:
sig_a_d1 = sig_a = 0sig_a_d2 = sig_a_d1 = 0sig_a_d3 = sig_a_d2 = 0
-
时钟周期 2(
sig_a变为1):sig_a_d1 = sig_a = 1sig_a_d2 = sig_a_d1 = 0(上一周期的值)sig_a_d3 = sig_a_d2 = 0(上一周期的值)
此时,
sig_a_posedge = sig_a_d2 & !sig_a_d3 = 0 & 1 = 0,没有检测到上升沿。 -
时钟周期 3:
sig_a_d1 = sig_a = 1sig_a_d2 = sig_a_d1 = 1sig_a_d3 = sig_a_d2 = 0(上一周期的值)
此时,
sig_a_posedge = sig_a_d2 & !sig_a_d3 = 1 & 1 = 1,检测到上升沿。 -
时钟周期 4:
sig_a_d1 = sig_a = 1sig_a_d2 = sig_a_d1 = 1sig_a_d3 = sig_a_d2 = 1
此时,
sig_a_posedge = sig_a_d2 & !sig_a_d3 = 1 & 0 = 0,没有检测到上升沿。
改进代码优化
可以将 sig_a_posedge 的逻辑直接写在 always 块中,避免使用 assign 语句。
input sig_a;
input clk;
input reset_n;
reg sig_a_d1, sig_a_d2, sig_a_d3;
reg sig_a_posedge;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
sig_a_d1 <= 1'b0;
sig_a_d2 <= 1'b0;
sig_a_d3 <= 1'b1; // 避免复位后立即检测到上升沿
sig_a_posedge <= 1'b0;
end else begin
sig_a_d1 <= sig_a;
sig_a_d2 <= sig_a_d1;
sig_a_d3 <= sig_a_d2;
sig_a_posedge <= sig_a_d2 & !sig_a_d3; // 检测上升沿
end
end
3148

被折叠的 条评论
为什么被折叠?



