对外部触发信号做出反应的最快方法

时间:2019-04-30 21:33:55

标签: verilog fpga

外部触发信号发送到FPGA。仅当在接收到触发时and1和and2也为高电平时,才应接受触发信号。如果触发被接受,则应创建一个持续时间为10微秒的触发输出脉冲。目的是尝试尽量减少FPGA接受/拒绝此外部触发信号所需的时间。

module trigger(
input CLK, 
input trigger,
input and1,
input and2,

output triggerOut, 
);

以下是第一个解决方案的尝试;

assign triggerOut = trigger & and1 & and2;

反应时间很快,但我认为这不能实现10微秒的触发时间。

当前解决方案如下;

always @(posedge CLK) begin

  if(trigger & and1 & and2)
    triggerOut <= 1;

end

此解决方案允许添加一个计数器,该计数器允许实现10微秒的触发脉冲。需要注意的是,现在对外部触发的反应时间与CLK的频率有关。通过增加CLK频率可以缩短反应时间,但是CLK可以增加多高是有限制的。

另一种可能的解决方案可能是对更改触发输入的敏感性;

always @(posedge trigger) begin

  if(trigger & and1 & and2)
    triggerOut <= 1;

end

我已经读到这可能是不好的做法。我不清楚为什么为什么使用@(posege CLK)优于@(posedge trigger)。是什么定义了FPGA对@(posege trigger)之类的灵敏度的反应时间?我想这仍然必须与CLK相关联-这种方法可能更快吗?

有没有更好的方法来改善对触发输入的反应时间?

1 个答案:

答案 0 :(得分:0)

不借助异步逻辑很难实现该目标。幸运的是,最近的FPGA将电平触发锁存器作为原语,因此不完整的组合总块并不总是一个坏习惯。

OTOH,宽度为10us的triggerOutput信号需要一个同步时钟来计数时间,但是在第一种方法中,该定时器将由异步输入触发。这肯定会带来跨域时钟问题,而简单的解决方案(与两个触发器同步)会引入一些延迟,因此10us脉冲可能不会在内部接受触发的同时开始,并且/或者宽度恰好是10us 。为避免使用triggerOutput的亚稳定性问题,可以将其用作1到10计数器的异步复位信号。

总而言之,该模块是对触发器检测器和接受器的异步方法的实现:

module detect_trigger (
  input wire clk,  // let's say it's 1 MHz (period = 1us)
  input wire trigger,
  input wire and1,
  input wire and2,
  output reg triggerOut
  );

  reg [3:0] cnt = 4'd0;
  initial triggerOut = 1'b0;
  always @* begin
    if (cnt >= 4'd11)
      triggerOut = 1'b0;
    else if (trigger && and1 && and2)
      triggerOut = 1'b1;
  end

  always @(posedge clk or negedge triggerOut) begin
    if (triggerOut == 1'b0)
      cnt <= 4'd0;
    else if (cnt < 4'd11)
      cnt <= cnt + 4'd1;
  end
endmodule

测试平台模块可能是这样的:

module tb;
  reg clk;
  reg trigger;
  reg and1, and2;
  wire triggerOut;

  detect_trigger uut (
    .clk(clk),
    .trigger(trigger),
    .and1(and1),
    .and2(and2),
    .triggerOut(triggerOut)
  );

  initial begin
    $dumpfile ("dump.vcd");
    $dumpvars(1, tb);
    clk = 1'b0;
    and1 = 1'b0;
    and2 = 1'b0;
    trigger = 1'b0;

    repeat (5) begin
      #3023;
      and1 = 1'b1;
      #2419;
      and2 = 1'b1;
      #1865;
      and1 = 1'b0;
      and2 = 1'b0;
    end
    $finish;
  end

  always begin
    clk = #500 ~clk;
  end

  always begin
    trigger = 1'b0;
    #1753;
    trigger = 1'b1;
    #2;
  end
endmodule

该测试台的输出如下:

Wave output for this test bench

您可以在此处使用EDA Playground修改并运行上述设计: https://www.edaplayground.com/x/3SGs