信号边沿检测

测试程序见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做边沿检测的网表