信号边沿检测

测试程序见 Euler0525@Wiki/programming/verilog/#信号边沿检测

名称 I/O 说明
clk I 时钟信号
rst_n I (同步)复位
edge_pin I 待检测信号
edge_neg O 边沿

测试程序中的 edge_pin 为待检测边沿的信号,edge_d0edge_d1 分别为延迟信号。

1
2
3
4
5
6
7
8
9
always@(posedge clk) begin
if(rst_n == 1'b0) begin
edge_d0 <= 1'b1;
edge_d1 <= 1'b1;
end else begin
edge_d0 <= edge_pin;
edge_d1 <= edge_d0;
end
end

为了检测 edge_pin 的边沿,我暂时可以想到以下几种方法(经测试后仅部分可行)

  • 时序逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
always @(posedge clk ) begin
if(rst_n == 1'b0) begin
edge_neg_pin0 <= 1'b0;
edge_neg_01 <= 1'b0;
end else begin
if (edge_pin == 1'b0 && edge_d0 == 1'b1)
edge_neg_pin0 <= 1'b1;
else
edge_neg_pin0 <= 1'b0;
if (edge_d0 == 1'b0 && edge_d1 == 1'b1)
edge_neg_01 <= 1'b1;
else
edge_neg_01 <= 1'b0;
end
end

仿真结果如下图所示

时序逻辑方法边沿检测

由仿真结果可知,neg_pin0 能够检测到 pin 信号的下降沿,而 neg_01 虽然能够检测到下降沿,但是会延迟一个时钟周期。

edge_neg_pin0 做边沿检测的网表

edge_neg_pin1 做边沿检测的网表
  • 组合逻辑
1
2
assign edge_neg_pin0 = edge_pin && ~edge_d0;
assign edge_neg_01 = edge_d1 && ~edge_d0;

仿真结果如图所示

时序逻辑方法边沿检测

由仿真结果可知,neg_pin0 不能检测到下降沿,neg_01 可以检测到下降沿。

第二次 pin 信号变化不在时钟上升沿,所以 d0 信号不会立刻随之变化,使得 pin0 信号检测到 pin 信号的上升沿;但是 pind0 都会在下 个时钟上升沿变为低电平,所以不能通过 edge_pin && ~edge_d0 检测到 pin 下降沿。

边沿的检测不应该受到时钟边沿变化的影响: 上面代码中 edge_d0edge_d1 的赋值逻辑确保了在时钟周期的任何时刻,edge_d1edge_d0 都有稳定的值,因此它们的异或结果 edge_neg_01 也是稳定的,不会因为时钟边沿的变化而改变。

  • edge_pin && ~edge_d0edge_pin 变化时刻未知:时钟上升沿变化,两者时钟相同,永远检测不到下降沿;其它时刻变化,暂时没在仿真中发现问题;
  • edge_pin && ~edge_d1:得到 edge_d1 前提是有 edge_d0 延迟一个时钟周期,而且 edge_d0edge_pin 更稳定;

edge_d1 && ~edge_d0 做边沿检测的网表