Verilog下降沿检测

时间:2017-09-12 07:34:07

标签: synchronization verilog clock hdl

我正在编写用于在FPGA上实现的UART的Verilog代码,并且在第一个之后同步到START位字节时遇到一些麻烦。

我的经理建议同步我接收到的信号,并使用某种中断作为与我的FSM通信的方式,以确认已启动。

我已经阅读了关于上升沿检测的技术,我觉得我可以这样做:

module StartDetectionUnit (
    input clk, state, signal_in,
    output trigger
    );   

    reg signal_d;

    always @(posedge clk)
        begin
            signal_d <= signal_in;
        end
    assign trigger = signal_in & (!signal_d);

endmodule    

根据我的理解,这样的描述会检测到RISING边缘,而不是FALLING边缘,但RS-232通信中的“START”是逻辑“0”。

另外,我想在IDLE状态[硬编码为000]时实际分配标志,但对最终作业进行疯狂选通对我来说听起来并非硬件。

tldr,两个问题

  1. 检测异步输入信号的通用下降沿
  2. 在FSM的单一特定状态下执行此操作
  3. 非常感谢,我是Verilog的新手,也是HDL的新手

3 个答案:

答案 0 :(得分:1)

如果您的信号signal_in来自您的设计之外,它将无法正确同步。在您的设计中,您只使用一个d-latch,需要两个。

reg signal_d;
always @(posedge clk)
    begin
        signal_d <= signal_in;
    end

这将只合成一个d锁存器。要正确同步信号,必须为两个d-latch实例化声明第二个信号:

reg signal_d;
reg signal_sync;
always @(posedge clk)
    begin
        signal_d <= signal_in;
        signal_sync <= signal_d;
    end

并且不应在您的设计中使用signal_d。然后要进行边缘检测,你必须声明第三个信号:

reg signal_d;
reg signal_sync;
reg signal_sync_old;
always @(posedge clk)
    begin
        signal_d <= signal_in;
        signal_sync <= signal_d;
        signal_sync_old <= signal_sync;
    end

对于下降沿检测,请执行:

assign trigger = signal_sync_old & (!signal_sync);

有关同步的更多信息的好网站: https://www.doulos.com/knowhow/fpga/synchronisation/

据我了解,您的信号'状态'以3位编码,然后您可以执行:

assign trigger = (state == 3'b000) ? (signal_sync_old & (!signal_sync)):0;

答案 1 :(得分:0)

我有同样的问题。我认为当您的主时钟采样率很高时,基本的下降沿检测将失败。传入的波特信号从高电平变为低电平需要花费时间。一旦检测到高低转换(在下降的波特信号的中间),就有可能在实际达到最终的低值之前再次尝试检测到它。在这种情况下,您将具有从低到低的检测率,因此丢失了下降过渡。我要解决的方法是在检测到下降沿时立即将检测器锁住,以便必须手动重启才能检测到第二次。

答案 2 :(得分:-3)

对于同步设计,可以通过这种方式进行下降沿检测。

module StartDetectionUnit (
    input clk, state, signal_in,
    output trigger
    );   

    reg signal_d;

    always @(posedge clk)
        begin
            signal_d <= !signal_in;
        end
    assign trigger = !(signal_in | signal_d);
endmodule    

以下是上述逻辑的状态图和计算。

Falling Edge Detection - Synchronous

下降沿检测可以通过以下方式完成。

assign sout = !(sin | (!sin));