VerilogA学习 - VCO demo 合集

Verilog-A与其他Verilog语言的不同

  • Verilog-HDL :处理数字信号Digital signal
  • Verilog-A :处理模拟连续时间信号Analog continuous-time signal
  • Verilog-AMS :处理模拟离散时间信号Analog discrete-event signal +处理模拟连续时间信号Analog continuous-time signal +处理数字信号Digital signal

VCO的Verilog-A代码

代码片来源于The Designer’s Guide网站(https://designers-guide.org),主要包括了

  1. 输出为正弦波、不含jitter
  2. 输出为方波,不含jitter
  3. 输出为方波,jitter类型是 white accumulating jitter
  4. 差分正交VCO,输出为方波,jitter类型是 white accumulating jitter

jitter的加入主要用到的是$rdist_normal()函数来产生伪随机噪声,其函数说明如下:

Normal (Gaussian) Distribution
Use the $rdist_normal function to generate random real numbers (or the $dist_normal function to generate integer numbers) that are normally distributed. The $rdist_normal function is not supported in digital contexts.
$rdist_normal ( seed , mean , standard_deviation ) ;
$dist_normal ( seed , mean , standard_deviation ) ;
seed is a scalar integer variable used to initialize the sequence of generated numbers. seed must be a variable because the function updates the value of seed at each iteration. To ensure generation of a normal distribution, change the value of seed only when you initialize the sequence.
mean is an integer or real expression that specifies the value to be approached by the mean value of the generated numbers.
standard_deviation is an integer or real expression that determines the width of spread of the enerated values around mean. Using a larger standard_deviation spreads the generated values over a wider range. To generate a gaussian distribution, use a mean of 0 and a standard_deviation of 1.
For example, the following module returns a series of real numbers that together form a gaussian distribution.
module distcheck (pinout) ;
electrical pinout ;
integer seed ;
real rrandnum ;
analog begin
@ (initial_step) begin
seed = 23 ;
end
rrandnum = $rdist_normal( seed, 0, 1 ) ;
$display (“Random number is %g”, rrandnum ) ;
V(pinout) <+ rrandnum ;
end // of analog block
endmodule

关于如何对PLL中各个模块的jitter建模分析,The Designer’s Guide网站上有篇paper(点击即可直接跳转)讲得很清楚。
如果需要对VCO的输出信号进行相移,可以直接使用下方delay函数而不是transition函数,二者的差别是delay函数对连续信号进行时延,而transition函数主要是对数字信号进行时延,transition更像是对方波做了平滑处理的滤波器,比如将陡峭的上升沿滤成缓坡。

delay(expression, time_delay)
delay(expression, time_delay, max_delay)

这两种使用方式第一种的时延不可变,第二种时延可以在0和max_delay之间发生变化。

transition(expression [ , delay [ , rise_time [ , fall_time]]])

注意在使用了transition之后,AC分析可能不再精确,但是transition的估计值可以使得仿真是足够准确以让我们得出结论的。

另外,该网站还有许多其他的VerilogA代码demo可以参考,安利一波~
具体代码如下,很好用~

// Voltage controlled oscillators
//
// Version 2, 2 April 2019
//
// Ken Kundert
//
// Downloaded from The Designer's Guide (www.designers-guide.org).
// Post any questions to www.designers-guide.org/Forum

`include "disciplines.vams"
`include "constants.vams"


//
// Voltage controlled oscillator
// output is sinusoidal with no jitter
//

module vco0 (out, in);

input in; voltage in;                           // input terminal
output out; voltage out;                        // output terminal
parameter real vmin=0;                          // input voltage that corresponds to minimum output frequency
parameter real vmax=vmin+1 from (vmin:inf);     // input voltage that corresponds to maximum output frequency
parameter real fmin=1 from (0:inf);             // minimum output frequency
parameter real fmax=2*fmin from (fmin:inf);     // maximum output frequency
parameter real va=1;                            // amplitude
real freq, phase;
integer n;

analog begin
    // compute the freq from the input voltage
    freq = (V(in) - vmin)*(fmax - fmin) / (vmax - vmin) + fmin;

    // bound the frequency (this is optional)
    if (freq > fmax) freq = fmax;
    if (freq < fmin) freq = fmin;

    // bound the time step to assure no cycles are skipped
    $bound_step(0.2/freq);

    // phase is the integral of the freq modulo 2 pi
    phase = 2*`M_PI*idtmod(freq, 0.0, 1.0, -0.5);

    V(out) <+ va*sin(phase);
end
endmodule


//
// Voltage controlled oscillator
// output is square wave with no jitter
//

module vco1 (out, in);

input in; voltage in;                           // input terminal
output out; voltage out;                        // output terminal
parameter real vmin=0;                          // input voltage that corresponds to minimum output frequency
parameter real vmax=vmin+1 from (vmin:inf);     // input voltage that corresponds to maximum output frequency
parameter real fmin=1 from (0:inf);             // minimum output frequency
parameter real fmax=2*fmin from (fmin:inf);     // maximum output frequency
parameter real vl=-1;                           // high output voltage
parameter real vh=1;                            // low output voltage
parameter real tt=0.01/fmax from (0:inf);       // output transition time
parameter real ttol=1u/fmax from (0:0.1/fmax);  // time tolerance
real freq, phase;
integer n;

analog begin
    // compute the freq from the input voltage
    freq = (V(in) - vmin)*(fmax - fmin) / (vmax - vmin) + fmin;

    // bound the frequency (this is optional)
    if (freq > fmax) freq = fmax;
    if (freq < fmin) freq = fmin;

    // bound the time step to assure no cycles are skipped
    $bound_step(0.6/freq);

    // phase is the integral of the freq modulo 2 pi
    phase = 2*`M_PI*idtmod(freq, 0.0, 1.0, -0.5);

    // identify the point where switching occurs
    @(cross(phase + `M_PI/2, +1, ttol) or cross(phase - `M_PI/2, +1, ttol))
        n = (phase >= -`M_PI/2) && (phase < `M_PI/2);

    // generate the output
    V(out) <+ transition(n ? vh : vl, 0, tt);
end
endmodule


//
// Voltage controlled oscillator
// output is square wave with white accumulating jitter
//

module vco2 (out, in);

input in; voltage in;                           // input terminal
output out; voltage out;                        // output terminal
parameter real vmin=0;                          // input voltage that corresponds to minimum output frequency
parameter real vmax=vmin+1 from (vmin:inf);     // input voltage that corresponds to maximum output frequency
parameter real fmin=1 from (0:inf);             // minimum output frequency
parameter real fmax=2*fmin from (fmin:inf);     // maximum output frequency
parameter real vl=-1;                           // high output voltage
parameter real vh=1;                            // low output voltage
parameter real tt=0.01/fmax from (0:inf);       // output transition time
parameter real ttol=1u/fmax from (0:0.1/fmax);  // time tolerance
parameter real jitter=0 from [0:0.25/fmax);     // period jitter (produces white accumulating jitter)
real freq, phase, dT;
integer n, seed;

analog begin
    @(initial_step) seed = -561;

    // compute the freq from the input voltage
    freq = (V(in) - vmin)*(fmax - fmin) / (vmax - vmin) + fmin;

    // bound the frequency (this is optional)
    if (freq > fmax) freq = fmax;
    if (freq < fmin) freq = fmin;

    // add the phase noise
    freq = freq/(1 + dT*freq);

    // bound the time step to assure no cycles are skipped
    $bound_step(0.6/freq);

    // phase is the integral of the freq modulo 2 pi
    phase = 2*`M_PI*idtmod(freq, 0.0, 1.0, -0.5);

    // update jitter twice per period
    // `M_SQRT2=sqrt(K), K=2 jitter updates/period
    @(cross(phase + `M_PI/2, +1, ttol) or cross(phase - `M_PI/2, +1, ttol)) begin
        dT = `M_SQRT2*jitter*$rdist_normal(seed,0, 1);
        n = (phase >= -`M_PI/2) && (phase < `M_PI/2);
    end

    // generate the output
    V(out) <+ transition(n ? vh : vl, 0, tt);
end
endmodule


//
// Differential quadrature voltage controlled oscillator
// output is square wave with white accumulating jitter
//

module quadVco (PIout,NIout, PQout,NQout, Pin,Nin);

input Pin, Nin; voltage Pin, Nin;               // input terminals
output PIout, NIout; voltage PIout, NIout;      // output terminals
output PQout, NQout; voltage PQout, NQout;      // output terminals
parameter real vmin=0;                          // input voltage that corresponds to minimum output frequency
parameter real vmax=vmin+1 from (vmin:inf);     // input voltage that corresponds to maximum output frequency
parameter real fmin=1 from (0:inf);             // minimum output frequency
parameter real fmax=2*fmin from (fmin:inf);     // maximum output frequency
parameter real vl=-1;                           // high output voltage
parameter real vh=1;                            // low output voltage
parameter real tt=0.01/fmax from (0:inf);       // output transition time
parameter real ttol=1u/fmax from (0:0.1/fmax);  // time tolerance
parameter real jitter=0 from [0:0.25/fmax);     // period jitter (produces white accumulating jitter)
real freq, phase, dT;
integer i, q, seed;

analog begin
    @(initial_step) seed = 133;

    // compute the freq from the input voltage
    freq = (V(Pin,Nin) - vmin) * (fmax - fmin) / (vmax - vmin) + fmin;

    // bound the frequency (this is optional)
    if (freq > fmax) freq = fmax;
    if (freq < fmin) freq = fmin;

    // add the phase noise
    freq = freq/(1 + dT*freq);

    // bound the time step to assure no cycles are skipped
    $bound_step(0.6/freq);

    // phase is the integral of the freq modulo 2 pi
    phase = 2*`M_PI*idtmod(freq, 0.0, 1.0, -0.5);

    // update jitter where phase crosses p/2
    // 2=sqrt(K), K=4 jitter updates per period
    @(cross(phase - 3*`M_PI/4, +1, ttol) or cross(phase - `M_PI/4, +1, ttol) or
    cross(phase + `M_PI/4, +1, ttol) or cross(phase + 3*`M_PI/4, +1, ttol)) begin
        dT = 2*jitter*$rdist_normal(seed,0,1);
        i = (phase >= -3*`M_PI/4) && (phase < `M_PI/4);
        q = (phase >= -`M_PI/4) && (phase < 3*`M_PI/4);
    end

    // generate the I and Q outputs
    V(PIout) <+ transition(i ? vh : vl, 0, tt);
    V(NIout) <+ transition(i ? vl : vh, 0, tt);
    V(PQout) <+ transition(q ? vh : vl, 0, tt);
    V(NQout) <+ transition(q ? vl : vh, 0, tt);
end
endmodule

Debug Tips

Virtuoso在Verilog-A compile提示这块做的不是很人性化,需要你在菜单>View下面打开Parser Log File才能看到比较详细的提示。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值