Hi Ken, thanks so much for your reply!
I tried the approach you suggested and after some tweaking I think I got it, but to be honest I am not really sure why I needed to code my solution the way I did, and not as I first intended; let me explain a bit.
Using the code below I get the waves shown in Fig. 5, which are correct. In particular, it can be seen in this figure that the 2nd rising edge of the input (green curve), happening at 20.5ns, correctly appears at the output (pink curve) after 10ns, i.e., at 30.5ns. This is in agreement with the signal "actual_delay", whose value at this crossing event is 10ns (orange curve).
Code:`include "discipline.h"
`include "constants.h"
module delaycell (vIN, vCTRL, vOUT);
input vIN; electrical vIN; // signal input
input vCTRL; electrical vCTRL; // control input
output vOUT; electrical vOUT; // signal output
parameter real K__V_to_delay = 10n from [0:inf); // [s/V]
parameter real zero_input_delay = 0 from [0:inf); // [s]
parameter real Vth_rising = 1.0; // [V]
parameter real Vth_falling = 1.0; // [V]
parameter real VHI = 2.0; // [V]
parameter real VLOW = 0.0; // [V]
parameter real cross__time_tol = 1f from [0:inf); // [s]
parameter real transition__rise_time = 1n from [0:inf); // [s]
parameter real transition__fall_time = 1n from [0:inf); // [s]
real actual_delay;
real s_vOUT;
analog begin
// Rising edge delay
@(cross(V(vIN)-Vth_rising,+1,cross__time_tol)) begin
actual_delay = K__V_to_delay*V(vCTRL)+zero_input_delay;
s_vOUT = VHI;
end
// Falling edge delay
@(cross(V(vIN)-Vth_falling,-1,cross__time_tol)) begin
actual_delay = K__V_to_delay*V(vCTRL)+zero_input_delay;
s_vOUT = VLOW;
end
V(vOUT) <+ transition(s_vOUT,actual_delay,transition__rise_time,transition__fall_time);
end
endmodule
Now the problem that I don't understand. At first I tried using the code below (lines not shown are identical as in the previous code), which produced the output in Fig. 6, which is wrong: the 2nd rising edge of the input at 20.5ns incorrectly appears at the output only after 1.5ns, i.e., at 22ns! This is despite the fact that when this crossing event occurs (20.5ns), the instantaneous value of the signal "actual_delay" is 10ns (see orange wave).
Code:analog begin
// Actual delay value
actual_delay = K__V_to_delay*V(vCTRL)+zero_input_delay;
// Rising edge delay
@(cross(V(vIN)-Vth_rising,+1,cross__time_tol)) begin
s_vOUT = VHI;
end
// Falling edge delay
@(cross(V(vIN)-Vth_falling,-1,cross__time_tol)) begin
s_vOUT = VLOW;
end
V(vOUT) <+ transition(s_vOUT,actual_delay,transition__rise_time,transition__fall_time);
end
My question is then, why is it necessary to sample the "actual_delay" value at each crossing event? Why can't I just use the 1-line approach to define this signal as in the code above? I would be really grateful if you could please explain me why Spectre behaves as it does here.
Thanks again for your help.
Cheers,
Jorge.