Vous êtes sur la page 1sur 7

• 进入正题,学了几天的 Verilog-A,平台是 Agilent ADS,主要参考“Verilog-AMS L

anguage Reference Manual”和 ADS 的帮助文档。

现在的状态算是入门了,写了个简单的 PLL。总结这几天的学习,觉得效率太低,我以前有一

定 Verilog 基础,研一时学过一点 VHDL-AMS,学到现在这个状态应该半天就够了;入门的话,

30 分钟足矣;跟着这个教程走,你会很快了解和熟悉 Verilog-A。(前提是有一定的 Verilog

基础和电路基础)

1、基尔霍夫定律撑起了整个电路学的大厦(当然也可以认为基尔霍夫定律只是麦克斯韦方程的

简化版),作为模拟电路描述语言 Verilog-A,同样将基尔霍夫定律作为其基本,最重要的两个

概念便是流量(Flow)和位(Potential),在电学里是电流和电压,在力学里可以是力和距离,在

热学里可以是功率和温差,等等。

在 Verilog-A 中,你可以将电阻电容电感等器件用一个方程式来表述,比如 I(out) <+ V(o

ut)/R,这样就产生了一个电阻,最后 Verilog-A 仿真器会用某种算法(迭代是最常见的)将 I(o

ut)和 V(out)求解出来,然后根据这个解去算下一个时刻的 I、V 等,当然这仅仅是指时域仿真。

2、下面讲 Verilog-A 的语法:

begin end //相当于 C 语言的一对大括号,与 Verilog 同

if ( expression ) true_statement ;

[ else false_statement ; ] //与 Verilog 同

case ( expression ) case_item { case_item } endcase

for ( procedural_assignment ; expression;

procedural_assignment ) statement

//case 与 for 语句都跟 Verilog、C 语言类似

cross( expr [, dir [, time_tol [, expr_tol ]]] );

//cross 用来产生一个 event,如:


@(cross(V(sample) -2.0, +1.0))

//指 sample 的电压超过 2.0 时触发该事件,将会执行后面的语句,+1.0 表示正向越过,-1.

0 则相反

ddt( expr ) //求导,如:

I(n1,n2) <+ C * ddt(V(n1, n2)); //表示了一个电容

idt( expr ,[ ic [, assert [, abstol ]]] ) //积分,如:

V(out) <+ gain * idt(V(in) ,0) + gain * V(in);

//比例积分,式中的 0 表示积分的初值

transition( expr [, time_delay [, rise_time [, fall_time [, time_tol ]]]] )

//将 expr 的值 delay 一下并指定上升下降沿时间,相当于一个传输门

laplace_zp( expr ,ζ,ρ)

将 expr 进行拉普拉斯变换,具体表达式参看相关文献,还有 laplace_zd()等

数据类型:

integer、real,另外就是 discipline,不知道怎么翻译比较好,比如说它将电压电流这两个 na

ture 类型作为一个 discipline,这些都在 disciplines.vams 这个头文件里建好了,编程时要`i

nclude "disciplines.vams"。 如果要定义一个电路节点,electrical node_name 就好了

parameter {real | integer} list_of_assignments ;

//定义参数,如 parameter R = 50 from (0:inf];

在一个模块中调另一个模块和 Verilog 差不多,如:

blk_a a1(Input1, a_b1);

blk_a a2(Input2, a_b2);


运算符号:

+ - * / > < == & | && || ^ << >> ?: 等,跟 Verilog 一样

另外,新加的一个符号<+,这个专门给模拟信号赋值用,注意这个赋值符号是可以累加的,就

是说赋两次值的话,它会加起来,而不是覆盖,如:

// model input admittance(导纳)

I(in) <+ V(in)/Rin;

I(in) <+ Cin*ddt(V(in));

预处理&宏:

`define `else `ifdef `include `resetall `undef

跟 Verilog 差不多

3、Verilog-A 程序基本结构:

`include "disciplines.vams" //预处理

module load(p); //定义模块,p 是端口

electrical p, gnd; //定义节点

ground gnd; //定义 gnd 为 ground 节点,电位为 0

parameter real R=50.0; //定义 R 这个参数并赋初值

analog //模拟语句从这开始

V(p) <+ R * I(p, gnd); //在这里表示一个电阻,表示了输出

电压与输出电流的关系

endmodule //模块定义结束

4、上面这些基本上是最常用的了,了解之后,你就能看懂一般的 Verilog-A 程序了,下面是我

写的 PLL 仿真程序,把它看完并看懂(当然第一次并不需要看得很仔细):

提示:振荡频率 4~6G,分频器为 50 分频,Fref 为 100M,鉴相器为电荷泵型。


`include "disciplines.vams"

`include "constants.vams"

//VCO

module my_vco(in, out);

input in;

output out;

electrical in, out;

parameter real gain=2.0e9, fc=4.0e9;

analog

V(out) <+ sin(2*`M_PI*(fc*$realtime + idt(gain*V(in))));

endmodule

//phase detector

module my_pd(ref,rf,outP,outN);

input ref,rf;

output outP,outN;

electrical ref,rf,outP,outN;

real clr,up,down;

parameter real Ro=1e6, Ro2=1;

analog begin

@(cross(V(ref)-0.5,+1))

up = 1;

@(cross(V(rf)-0.5,+1))

down = 1;
clr = absdelay(up && down, 1e-9);

// clr = transition(up && down, 1e-9); //这两条语句都可以

if(clr>0.5) begin

up = 0;

down = 0;

end

if(up) begin

if(V(outP)>= 3)

V(outP) <+ 3-I(outP)*Ro2;

else I(outP) <+ -up*0.01;

end

else begin

I(outP) <+ 0;

end

if(down) begin

if(V(outN) <= 0)

V(outN) <+ 0-I(outN)*Ro2;

else I(outN) <+ down*0.01;

end

else begin

I(outN) <+ 0;

end

end

endmodule
//N divider

module my_divider(in,out);

input in;

output out;

electrical in,out;

integer cnt;

parameter integer K=50;

analog begin

@(cross(V(in),+1))

cnt = cnt+1;

if(cnt>=K)

cnt=0;

if(cnt*2-K>=0)

V(out) <+ 1;

else

V(out) <+ 0;

end

endmodule

以上是 VCO、鉴相器和分频器,原理图我是在 ADS 中画的,如下所示:


以下是仿真结果:

Vous aimerez peut-être aussi