I built a verilogA code to work as frequency detector and adjustor for my phase loop which has pretty small BW. I do not have frequency loop yet.
here is the code without compilation problem. However, it has a problem to simulate due to
zero diagonal Jacobian..
It is because the adjustout signal issue I think.
When lock is asserted, the cell needs to follow the vctrl (adjustout signal).
when lock event =1
do this --> adjust = V(adjustout);
else do this
V(adjustout) <+ adjust;
I have tried other method like using case(lock)..
it gave me the same problem
the code work well if commenting out the adjust = V(adjustout).
but the adjust voltage could be very different to vctrl(adjustout)
Code:`include "constants.vams"
`include "disciplines.vams"
module freq_meas_lock(clk, freqout, adjustout, lockout, vcm, lockoutdelay);
parameter real vcc =2 from (0:inf);
parameter real freqin =5e9 from (0:inf);
parameter real freqscale=5e9 from (0:inf);
parameter real ppm=1000 from (0:inf); //ppm=500->0.05% of the freq
parameter integer dir = +1 from [-1:+1] exclude 0;
parameter real adjust_start = 1.2 from (0:inf) ;
parameter real adjust_step = 1e-3 from (0:inf) ;
parameter real delay =1000e-12 from (0:inf);
inout adjustout;
input clk, vcm ;
output freqout, lockout,lockoutdelay;
real current_time, last_time, freq, adjust ;
integer cross_cnt, lock ;
voltage clk, freqout, adjustout,lockout, vcm,lockoutdelay;
analog begin
@( initial_step ) begin
cross_cnt=0;
last_time=0;
current_time=0;
freq=freqin/freqscale;
V(adjustout) <+ adjust_start;
adjust = adjust_start;
lock=0;
end
@(cross(V(clk)-V(vcm), dir, 1, clk.potential.abstol)) begin
cross_cnt = cross_cnt + 1;
last_time = current_time;
current_time = $abstime;
if (freq<1-ppm/1e6) begin
adjust = adjust + adjust_step ;
lock = 0;
end
else if(freq>1+ppm/1e6) begin
adjust = adjust - adjust_step ;
lock = 0;
end
else begin
adjust = V(adjustout)
lock = 1;
end
end
if (cross_cnt < 2) begin
freq=freqin/freqscale;
end
else begin
freq=(1/(current_time-last_time))/freqscale;
end
V(adjustout) <+ adjust;
V(freqout) <+ freq;
V(lockout) <+vcc*lock;
V(lockoutdelay) <+vcc*transition(lock ? 1: 0, delay,10p,10p);
end
endmodule