Verilog 对外部触发信号作出反应的最快方式
外部触发信号被发送到FPGA。只有在接收到触发器时and1和and2也为高电平时,才应接受触发器信号。如果接受触发,则应产生持续时间为10微秒的触发输出脉冲。目标是尽量减少FPGA接受/拒绝该外部触发信号所需的时间Verilog 对外部触发信号作出反应的最快方式,verilog,fpga,Verilog,Fpga,外部触发信号被发送到FPGA。只有在接收到触发器时and1和and2也为高电平时,才应接受触发器信号。如果接受触发,则应产生持续时间为10微秒的触发输出脉冲。目标是尽量减少FPGA接受/拒绝该外部触发信号所需的时间 module trigger( input CLK, input trigger, input and1, input and2, output triggerOut, ); 解决方案的第一次尝试如下: assign triggerOut = trigger & an
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
始终@(posedge CLK)开始
if(触发器与and1和and2)
triggerOut如果不采用异步逻辑,就很难达到这个目标。幸运的是,最近的FPGA将电平触发锁存器作为原语,因此不完整的组合始终块并不总是一种坏的做法
OTOH,10us width Trigger输出信号需要一个同步时钟来计数时间,但在第一种方法中,该计时器将由异步输入触发。这肯定会带来跨域时钟问题,而简单的解决方案(与两个触发器同步)将引入一些延迟,因此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
该试验台的输出如下:
您可以在此处使用EDA修改并运行上述设计:
如果不采用异步逻辑,很难达到这个目标。幸运的是,最近的FPGA将电平触发锁存器作为原语,因此不完整的组合始终块并不总是一种坏的做法
OTOH,10us width Trigger输出信号需要一个同步时钟来计数时间,但在第一种方法中,该计时器将由异步输入触发。这肯定会带来跨域时钟问题,而简单的解决方案(与两个触发器同步)将引入一些延迟,因此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
该试验台的输出如下:
您可以在此处使用EDA修改并运行上述设计:
如果触发器是FPGA内部的时钟,这是一种不错的做法。也就是说,它绑定到时钟输入板,和/或分配到FPGA内部的全局缓冲区。需要注意的是,10us计数器仍应绑定到clk,这将导致跨域时钟问题,在该问题中,由clk控制的顺序块必须接受与clk不同步但与触发器同步的输入。无论如何,无论您检测到该触发器的速度有多快。只要10us计数器与时钟相连,反应时间就可以慢到一个完整的时钟周期。如果触发器是FPGA内部的时钟,这是一种不错的做法。也就是说,它绑定到时钟输入板,和/或分配到FPGA内部的全局缓冲区。需要注意的是,10us计数器仍应绑定到clk,这将导致跨域时钟问题,在该问题中,由clk控制的顺序块必须接受与clk不同步但与触发器同步的输入。无论如何,无论您检测到该触发器的速度有多快。只要10us计数器与CLK相连,反应时间就可以慢到一整段CLK。
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