繁体   English   中英

Verilog 信号因时钟变化而略有下降?

[英]Verilog slight drops in signal caused by clock change?

我有一个设计用于去抖动开关的电路。 它每 1 ms 采样一次信号,并在移位寄存器中计数 8 ms。 当寄存器计数高信号的 8 个 1ms 滴答时,我们假设信号是干净的并且输出 sig_clean 变高。 出于某种原因,1KHz 时钟(1 ms 时钟)的每一个滴答声,我的干净信号都会下降到 0,然后在板载时钟的下一个滴答声中又恢复原状。 知道为什么会这样吗?

`timescale 1ns / 1ps

module debounce(
    input Clk100MHz, reset_n, Clk1KHzEn, sig,
    output reg sig_clean);

    reg [7:0] sigconfirm;

    initial sigconfirm = 8'b0000_0000;
    initial sig_clean = 0;

always@(posedge Clk100MHz)
    begin
        if(~reset_n)
            sig_clean <= 0;
        else
            if(Clk1KHzEn == 1)
                begin
                    if(sig == 1)
                        begin
                            sigconfirm[7] <= 1;
                            sigconfirm = sigconfirm >> 1;
                        end
                    else
                        begin
                            sigconfirm[7] <= 0;
                            sigconfirm = sigconfirm >> 1;
                        end
                end
    end

always@(posedge Clk100MHz)
    begin
        if(sigconfirm == 8'b1111_1111)
            sig_clean <= 1;
        else
            sig_clean <= 0;
    end 
endmodule

误差波形

测试台:

`timescale 1ns / 1ps

模块 lab_7_top_tb();

reg Clk100MHz, BTNC, BTNU;
wire CA, CB, CC, CD, CE, CF, CG, DP;
wire [7:0] AN;

lab_7_top labtop(
    .Clk100MHz(Clk100MHz),
    .BTNC(BTNC),
    .BTNU(BTNU),
    .CA(CA),
    .CB(CB),
    .CC(CC),
    .CD(CD),
    .CE(CE),
    .CF(CF),
    .CG(CG),
    .DP(DP),
    .AN(AN)
);

initial Clk100MHz = 0;
always #5 Clk100MHz = ~Clk100MHz;

initial begin
    BTNC = 1'b1; BTNU = 1'b0;
    #100;
    BTNC = 1'b0;
    #1000;
    press_BTNU;
    #1000;
    press_BTNU;
    #1000;
    $finish;
end

task press_BTNU;
    begin
        $display("%d Start of press button task", $time);
        BTNU = 0;
        #1000;
        BTNU = 1;
        #1500;
        BTNU = 0;
        #1200;
        BTNU = 1;
        #1800;
        BTNU = 0;
        #1100;
        BTNU = 1;
        #15000;
        BTNU = 0;
        #1800;
        BTNU = 1;
        #1600;
        BTNU = 0;
        #1400;
        BTNU = 1;
        #1100;
        BTNU = 0;
        #15000;
        $display("%d End of press button task", $time);
    end
endtask

结束模块

原来问题是 2 个修复:我像 Serge 建议的那样修复了阻塞分配,我交换了 sigconfirm 移位和分配位的顺序,以获得:

sigconfirm <= sigconfirm >> 1;
sigconfirm[7] <= 1'b1;

现在生活很好!

您将sig_cleanreset放在错误的always块中。 应该

always @(posedge Clk100MHz)
    if (!reset_n)
        sig_clean <= 0; 
    else if(sigconfirm == 8'b1111_1111)
            sig_clean <= 1;
         else
            sig_clean <= 0;
endmodule

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM