侧边栏壁纸
    • 累计撰写 302 篇文章
    • 累计收到 527 条评论
    [Verilog]ASIC/FPGA实现边沿检测电路(上升/下降沿)
    我的学记|刘航宇的博客

    [Verilog]ASIC/FPGA实现边沿检测电路(上升/下降沿)

    刘航宇
    2022-07-14 / 0 评论 / 1,243 阅读 / 正在检测是否收录...

    1、什么是边沿检测

    边沿检测用于检测信号的上升沿或下降沿,通常用于使能信号的捕捉等场景。

    2、采用1级触发器的边沿检测电路设计(以下降沿为例)

    2.1、设计方法

    设计波形图如下所示:
    Test
    各信号说明如下:

    sys_clk:基准时钟信号(这里设定为50MHz,周期20ns)
    sys_rst_n:低电平有效的复位信号
    in:输入信号,需要对其进行下降沿检测
    ~in:输入信号的反相信号
    in_d1:对输入信号寄存一拍
    in_neg:得到的下降沿指示信号,该信号为 ind1 && ~in
    对上图进行分析:

    信号in是我们需要对其进行下降沿检测的信号
    信号~in是将信号in反向
    信号in_d1是使用寄存器寄存in信号,即对其进行打拍,或者说是同步到系统时钟域下
    输入信号开始为高电平,在L2处变为低电平,产生第1个下降沿,在L5出产生第2个下降沿
    A处为产生的第1个下降沿指示信号,B处为产生的第2个下降沿指示信号

    2.2、Verilog实现

    根据上文分析不难编写Verilog代码如下:

    //使用1级寄存器的下降沿检测电路
    module detect_1
    (
        input        sys_clk,        //时钟(设定为 50MHz)
        input        sys_rst_n,        //复位信号(n 表示低电平有效)
        input        in,                //需要进行下降沿检测的输入信号
        
        output        in_neg            //输出的下降沿指示信号
    );        
    //reg  定义        
    reg        in_d1;                    //寄存一拍的信号
     
    assign in_neg = ~in && in_d1;    //组合逻辑得到下降沿
    //上升沿: assign in_pos = in && ~in_d1;
    //双边沿: assign in_pos = in ^ in_d1;
     
    //寄存模块,将输入信号打一拍
    always@(posedge sys_clk or negedge sys_rst_n)begin
        if(!sys_rst_n)
            in_d1 <= 1'b0;            //复位清零    
        else 
            in_d1 <= in;            //寄存一拍    
    end
     
    endmodule

    2.3、RTL电路

    Test
    上图为生成的RTL电路:该电路由一级D触发器+与逻辑门构成。

    2.4、Testbench

    Testbench文件需要例化刚刚设计好的模块,并设置好激励。

    `timescale 1ns/1ns        //时间刻度:单位1ns,精度1ns
     
    module tb_detect_1();    //仿真模块
     
    //输入reg 定义
    reg    sys_clk;            
    reg sys_rst_n;
    reg in;
     
    //输出wire定义
    wire in_neg;
     
    //设置初始化条件和输入激励
    initial begin
        sys_clk = 1'b0;        //初始时钟为0
        sys_rst_n <= 1'b0;    //初始复位
        in <= 1'b0;            //初始化输入信号
    /*****以下部分为设置的激励,以产生2个下降沿*******/
        #10                    //10个时间单位后
        sys_rst_n <= 1'b1;  //拉高复位(此时复位无效)
        in <= 1'b1;            //拉高输入
        #20                    //20个时间单位后
        in <= 1'b0;          //拉低输入,制造第1个下降沿
        #80                    //80个时间单位后
        in <= 1'b1;          //拉高输入
        #60                    //60个时间单位后
        in <= 1'b0;          //拉低输入,制造第2个下降沿    
    end
     
    //always代表重复进行,#10代表每10个时间单位
    //每10个时间单位反转时钟,即时钟周期为20个时间单位(20ns)
    always #10 sys_clk = ~sys_clk;    
     
    //例化被测试模块
    detect_1 detect_1_inst
    (
        .sys_clk     (sys_clk ),         
        .sys_rst_n     (sys_rst_n ),                 
        .in            (in),
        
        .in_neg     (in_neg)         
    );
        
    endmodule
     

    2.5、仿真结果

    使用ModelSim执行仿真,仿真出来的波形如所示:
    Test
    从波形图可以看到:

    10ns后停止复位
    在第1条参考线处输入信号 in 产生了第1个下降沿信号
    在第3条参考线处输入信号 in 产生了第2个下降沿信号
    在第1条参考线和第2条参考线之间的产生了一个周期的下降沿指示信号 in_neg
    在第3条参考线和第4条参考线之间的产生了一个周期的下降沿指示信号 in_neg

    3、采用2级触发器的边沿检测电路(以下降沿为例)

    3.1、设计方法

    设计波形图如下所示:
    Test
    各信号说明如下:

    sys_clk:基准时钟信号(这里设定为50MHz,周期20ns)
    sys_rst_n:低电平有效的复位信号
    in:输入信号,需要对其进行下降沿检测
    in_d1:对输入信号寄存1拍
    in_d2:对输入信号寄存2拍
    ~in_d1:in_d1信号的反相信号
    in_neg:得到的下降沿指示信号,该信号为 ~ind1 && ind2
    对上图进行分析:

    信号in是我们需要对其进行下降沿检测的信号
    信号in_d1是使用寄存器寄存in信号,即对其打1拍
    信号in_d2是使用寄存器寄存in_d1信号,即对其打1拍
    信号~in_d1是将信号in_d1反向
    输入信号开始为高电平,在L2处变为低电平,产生第1个下降沿,在L5出产生第2个下降沿
    A处为产生的第1个下降沿指示信号,B处为产生的第2个下降沿指示信号
    输出的下降沿指示信号落后下降沿一个时钟周期,这是因为对输入信号进行了寄存以消除亚稳态

    3.2、Verilog实现

    根据上文分析不难编写Verilog代码如下:

    //使用1级寄存器的下降沿检测电路
    module detect_2
    (
        input        sys_clk,        //时钟(设定为 50MHz)
        input        sys_rst_n,        //复位信号(n 表示低电平有效)
        input        in,                //需要进行下降沿检测的输入信号
        
        output        in_neg            //输出的下降沿指示信号
    );        
    //reg  定义        
    reg        in_d1;                    //寄存1拍的信号
    reg        in_d2;                    //寄存2拍的信号    
     
    assign in_neg = ~in_d1 && in_d2;//组合逻辑得到下降沿
    //上升沿: assign in_pos = in && ~in_d1;
    //双边沿: assign in_pos = in ^ in_d1;
     
    //寄存模块,将输入信号打1拍、打2拍
    always@(posedge sys_clk or negedge sys_rst_n)begin
        if(!sys_rst_n)begin
            in_d1 <= 1'b0;            //复位清零
            in_d2 <= 1'b0;
        end
        else begin
            in_d1 <= in;            //寄存1拍
            in_d2 <= in_d1;            //寄存2拍
        end
    end
     
    endmodule

    3.3、RTL电路

    Test
    上图为生成的RTL电路:该电路由2级D触发器+与逻辑门构成。

    3.4、Testbench

    Testbench文件同2.4章。

    3.5、仿真结果

    使用ModelSim执行仿真,仿真出来的波形如所示:
    Test
    从波形图可以看到:

    10ns后停止复位
    在第1条参考线处输入信号 in 产生了第1个下降沿信号
    在第4条参考线处输入信号 in 产生了第2个下降沿信号
    在第2条参考线和第3条参考线之间的产生了一个周期的下降沿指示信号 in_neg
    在第5条参考线和第6条参考线之间的产生了一个周期的下降沿指示信号 in_neg
    两级寄存器构成的边沿检测电路可以有效的防止亚稳态的产生,产生的使能信号会落后一个时钟周期。

    4、参考文献

    【从零开始走进FPGA】你想干嘛——边沿检测技术
    FPGA的边沿检测
    FPGA基础入门篇(四) 边沿检测电路

    1
    【Verilog】创建12小时时钟的计数器
    « 上一篇 2022-07-15
    【Verilog】卡诺图到电路Karnaugh Map to Circuit
    下一篇 » 2022-07-11

    评论 (0)

    取消