我需要实现一个由
触发的块(行为,不是要合成)a)外部事件eflag,或者b)取决于其状态,内部事件iflag,在dt秒之后安排,以先到者为准。
我使用延迟(#)运算符的试验导致阻塞行为,例如一个长的dt确实阻止了下一个eflag。 如果可能的话,我会避免将dtmax作为长dt的计算开销。
工作和预期,但代码失败:
`timescale 1ns/100fs
`define tick 1.0e-9
parameter real dtmax = 1;
initial iflag=1'b0;
initial toggle=1'b0;
always @(eflag, iflag) begin
// time step control
dt = ...;
iticks = dt/`tick;
toggle = !toggle;
end
//------------------------------------------------------
/*
a) time step counter - working
always #1 begin
iticks = iticks - 1;
if (iticks < 1) begin
iflag = !iflag;
iticks=dtmax/`tick;
end
end
*/
// b) intended
always @(toggle) begin
#(iticks) iflag <= !iflag; // failing, not changing iflag
// #(iticks) iflag = !iflag; // failing, blocking simulation
end
你可以在edaplayground上试试 link
THX
答案 0 :(得分:0)
我已经对您的代码进行了分支,这个新代码对我来说很好。如果您认为它不起作用,也许您在理解Verilog模拟时错了。非阻塞延迟会在信号上安排事件。如果在分配该调度之前,另一个事件被调度,具有不同的值,则它将覆盖第一个事件。如果新事件具有相同的值,则保留第一个值。
// Verilog
// self-triggered always block
// block should take time steps <= dtmax
`define tick 1.0e-9
module dut(eflag);
input eflag;
reg iflag;
reg toggle;
integer iticks;
real last_time;
real now;
real dtlast;
real dtmax;
always @(eflag, iflag) begin
now = $time*`tick;
dtlast = now - last_time;
dtmax = iticks*`tick; // from last call
$display( "dtlast: %g",dtlast);
$display( "err: %d",dtlast > dtmax); // giving wrong value in sim?
$display("\nnow: %g",now);
$display( "dtmax: %g",dtmax);
// time step control dummy
iticks <= 7 + $random % 5; //changed because in previous one eflag and toggle always changed at the same time
toggle = !toggle;
last_time = now;
end
initial toggle = 0;
initial iflag = 0;
always @(toggle) begin
#(iticks) iflag <= !iflag;
end
endmodule