Verilog-A 语言简单入门教程

前言

由于前些天在进行毕设时,本人需要给某个器件建立一个电路模型,来使这个器件可以在Cadence IC中与电路进行联合仿真,因此学习了一些Verilog-A语言相关的知识,并成功的使用该语言建立了器件的模型。

在学习的过程中,本人主要参考的是OVI_VerilogA文档。但是在学习中本人发现,Verlog-A语言在语法上与普通的Verilog HDL差不多,仅仅是多了一些自己独特的语法罢了。然而在一开始的学习时,本人只顾着看文档,导致最终用了几天的时间才完成了Verilog-A的学习和建模工作。现在回想起来,感觉完全没有必要如此。因此想写一篇教程,如果读者有一定的电路基础知识,并且以前学过Verilog HDL,看了这个教程后因该很快就能入门。

1. 什么是Verilog-A

Verilog-A可以理解为一种使用Verilog的语法来描述模拟电路的行为的语言。

2. 流量(flow)、势(potential)与参考节点(Reference nodes)

在一个保守场中,每个节点都有两个非常重要的特征参数,就是「流量(flow)」和「势(potential)」。对于任一节点来说,连接到每个节点上的所有端子的势相等,并且来自连接在这个节点上的所有终端上的流量之和必须为零。对于保守场来说,「分支(branch)」的概念也十分重要。每一个「分支」都有一个相应的「势」和一个对应的「流量」。而对于一个保守场,它的「参考节点(Reference nodes)」是一个人为规定的具有零的势的节点。其他节点的势都是相对于这个节点而言的。

在电学中,「流量」可以对应为电流(I),「势」可以对应为电压(V),「分支」在电路中可以对应成支路,而「参考节点」可以对应为接地点。而在电学中,每一条支路也都具有电流与电压参数。而对于任一节点上的两个规律在电学中就对应着基尔霍夫电压定律与电流定律(KCL, KVL)。Verilog-A中同样以基尔霍夫电学定律为基础。在Verilog-A的「保守系统(Conservative systems)」描述中,主要是通过定义支路,并将各个支路进行组合来完成对模拟电路的描述的。(此外Verilog-A还有「信号流系统(Signal-flow systems)」和「混合系统(Mixed systems)」描述,本文中不介绍)

3. 数据类型

Verilog-A中支持Verilog HDL中的整型(integer)、实数型(real)以及参数型(parameter)数据类型,同时还有一个比较常用的数据类型叫做 discipline,我也不太知道这个词该怎么翻译,也许可以叫做「约束」?它有点像某些面向对象的编程的语言中定义用来「类(class)」的关键字。

对于整型和实数型数据类型,它的使用方法和Verilog HDL很类似,例如:

integer num = 10; // 单个的整型变量
integer flag [7:0]; // 8个整数组成的数组
real pi = 3.1415926; // 单个的实数型变量

而对于discipline数据类型,我们可以用discipline关键字来定义一个叫electrical的「类」,然后这个「类」有两个「属性」,就是电压和电流。随后,我们就可以用electrical来定义一个「对象」,这个「对象」在电路中就相当于一个节点。而这个electrical「类」的定义,已经被包含进Verilog-A的头文件`include discipline.h中了。

因此在Verilog-A中,我们想要定义一个节点,导入头文件后就直接用electrical node_name;命令就好了,如:

electrical VINN, VINP, VOUT; // 定义VINN、VINP和VOUT三个电路节点

此外,Verilog-A中还有一种数据类型叫做「支路(branch)」,如果电路的拓扑结构比较明确时使用这个数据类型会让写程序变得更方便一些,但是不使用也没什么问题,因此把它放进折叠区块里面介绍,大家可以选择先不了解这个类型,等有需要了再了解或者看文档也不迟:

4. 运算符与表达式

Verilog-A中的运算符与Verilog HDL几乎完全一致,但是由于Verilog-A是一种描述模拟信号的语言,因此其中有大量的自己独有的表达式来对信号进行运算。

4.1 常规运算符

Verilog-A中同样也有Verilog HDL中的那些常规的运算符,比如+ - * / %等等。同时,这些运算符的优先级顺序也是和Verilog HDL语言一致的。这些运算符可以同时应用在常规运算和模拟支路中。

4.2 常规表达式(主要是一些数学函数)

常规表达式主要用来提供一些数学运算功能,以及一些电路中常用到物理量等。例如sin(x); ln(x); exp(x); pow(x,y);等等,以及一些模拟电路中常用的到物理量:

$realtime; // Current simulation time in seconds.
$temperature; // Ambient temperature in kelvin.
$vt Thermal; // voltage (kT/q).
$vt(temp); // Thermal voltage at given temperature.

4.3 模拟信号访问函数

模拟信号访问函数主要用来访问两个节点间的电压、两个节点间的电流或者一条支路上的电压与电流等。使用方法为V(x, y)或者I(x, y)。例如:

V(R1); // 获取支路R1两端的电压(如果R1已经被定义为一个支路)
I(R1); // 获取流过支路R1上的电流(如果R1已经被定义为一个支路)
V(anode, cathode); // 获取anode与cathode节点之间的电压
I(anode, cathode); // 获取流过anode与cathode节点之间的电流
V(G, S); // 获取G和S两个节点之间的电压
I(D, S); // 获取流过D和S两个节点之间的电流
V(G); // 获取节点G与gnd(地)之间的电压(如果G没有被定义为一个支路)
I(S); // 获取从节点S流到gnd的电流(如果S没有被定义为一个支路)

4.4 模拟运算符

在Verilog-A中,用来给上述的模拟信号进行赋值的运算符称为模拟运算符,写作<+。该运算符只能用在analog begin ...... end块中(后面会提到这个块)。使用这个运算符就可以为两个节点之间赋予一个模拟特性,例如:

V(a, b) <+ R * I(a, b); // 赋予节点a和b之间一个电阻特性,阻值为R。(相当于在节点a和b之间定义了一个阻值为R的电阻)

注意这个运算符是累加性的,例如V(a, b) <+ R * I(a, b); V(a, b) <+ VCM;这两个语句的效果相当于V(a, b) = VCM + R * I(a, b);这一个语句。

4.5 模拟表达式

这是一些只能用在 使用模拟运算符<+的式子 中的表达式。这类的表达式也有很多种,这里就不列举了。其中用的最多的就是ddt(x),用来对某一个模拟信号量来求微分。使用方法例如:

I(a, b) <+ C * ddt(V(a, b)); //相当于在节点a,b之间定义了一个电容。

5. Verilog-A的程序结构

上面所描述的是Verilog-A程序的一些语法,这里主要说明的是一个完整的Verilog-A程序是如何组成的。

5.1 宏定义

Verilog-A中的宏定义和Verilog HDL中差不多。比较重要的有`define、`include、`ifdef;等等。

5.2 模拟程序块

在Verilog HDL中,有一种程序块叫做always,在Verilog-A中和这个比较相像的就是analog程序块。analog程序块中的程序在某种意义上和Verilog HDL中的always程序块一样,也是「一直在运行的」。

analog程序块的结构如下:

analog begin
// 这里放内容
end

5.3 条件、分支和循环语句

Verilog-A中的条件、分支和循环语句和Verilog HDL几乎一样。(但是在涉及到模拟运算符和模拟表达式时会有一些细微的差别,这里大家用到时可以自行去看文档)if、if-else、if-else-if、case、forever、while for等等的Verilog HDL语法都是适用的。

5.4 模块、端口和参数

5.4.1 模块(module)

module的程序块结构和Verilog HDL相同,都是:

module module_name (port1, port2, ... , portn)
// 这里写模块内容
endmodule

5.4.2 端口(ports)

在Verilog HDL中,端口分为两部分:端口类型声明和端口数据类型声明。Verilog-A中也有这两部分。其中端口类型有input、output、inout,和Verilog HDL一致。而对于端口数据类型,和Verilog HDL不同,Verilog-A中只会把端口数据类型声明为electrical「类」。例如:

module res (a, b)    // 定义一个叫做res的module
    inout a, b;      // 该module有两个双向端口a和b
    electrical a, b; // 声明这两个端口为electrical数据类型
endmodule

5.4.3 参数

Verilog-A中的参数声明和Verilog HDL几乎一致,也是使用parameter。唯一的区别是在Verilog-A中,声明参数时通常会附带上数据类型,例如:

parameter real slow_rate = 1e-3;
parameter integer gain = 10;

同时,在声明参数时也可以附带上取值范围,取值范围使用form和一个区间的形式来定义。其中[表示闭区间,即可以去到边界值;(表示开区间,即不可以取到边界值,例如:

parameter real slow_rate = 1e-3 from [1e-5, 1e-2); // 取值范围为1e-2到1e-5,不包含1e-2,包含1e-5。
parameter integer gain = 10 from (0, 1000]; // 取值范围为0到1000,不包含0,包含1000。

在Cadnece IC中,调用Verilog-A语言描述的器件后参数显示的效果如下图:

5.5一个简单的示例

有了上面这些基础知识,就可以简单的写一个示例程序来练练手了。这里我们先写一个理想特性的电阻的Verilog-A程序。它的阻值的取值范围为0-100 MOhm,包括边界。

// Cadence 默认调用的两个宏定义,不用管为啥,写上就完事了。
`include "discipline.h"
`include "constants.h" 

module res (vp, vn); // 定义一个叫做res的module,它有俩个端口vp和vn
    inout vp, vn; // 这两个端口都是双向端口
    parameter real r = 0 from [0, 100M]; // 这个模型有一个参数r,取值为0到100M,包括两个边界
    electrical vp, vn; // 定义vp和vn为两个电学节点
    
    analog
        V(vp, vn) <+ r * I(vp, vn); // 赋予vp和vn两个节点之间电阻特性
endmodule

6. 模拟事件

在Verilog HDL描述时序电路时,有一种用的非常多的语句叫做事件控制语句。它使用一个@号作为起始,其后会跟着一些触发条件,比如上升沿触发等等。在Verilog-A中,也有这种类似的事件控制语句,只不过触发条件可以写的更加复杂。下面仅列举几个比较常用的。

6.1 初始事件

在Verilog HDL中,有一种叫做initial的语句,这个语句内的内容会在仿真起始阶段执行一次。Verilog-A中也有类似的事件控制语句@(initial_step),这个控制事件中的语句在仿真迭代开始时会执行一次。一般都用它来赋初值或者计算一些变量的初始值。它的用法是:

analog begin // 事件控制语句必须放在analog语句内部
    @(initial_step) begin
       bits = 0;
       error = 0;
    end
end

6.2 终止事件

和初始事件类似,终止事件中的语句在仿真结束时会执行一次。因此可以用来输出一些仿真结果等。例如:

analog begin 
    @(final_step) begin
       $display("bit error rate = %f%%", 100.0 * errors / bits );
    end
end

6.3 跨越事件

在模拟电路中,可能经常会有这样一种需求,就是当一个输入电压值比另一个恒定的电压值大时,就进行某种操作(例如启动开关等)。这种需求就可以通过跨越事件实现。

跨越事件使用cross函数来进行描述,其基本结构是@(cross(表达式, 电压值)),下面是一个使用该事件完成的采样-保持器的Verilog-A代码:

module sh (in, out, smpl) ;
    output out ;
    input in, smpl ;
    electrical in, out, smpl ;
    real state ;
    analog begin
        @(cross(V(smpl) - 2.5, +1)) // 当控制采样的端口上的电压大于2.5V时进行采样,否则继续保持(+1表示正向跨越,-1表示负向跨越)
            state = V(in) ; // 开始采样
        V(out) <+ transition(state, 0, 10n) ; //将采样\保持结果输出到Vout
    end
endmodule

6.4 其他

Verilog-A中还有很多各种各样的事件控制语句,例如timer等等,可以完成很多功能。要是有需要的话可以查看OVI_VerilogA文档的6.9节。

7. 层次结构

和Verilog HDL一样,Verilog-A中也可以有不同的层次结构,也可以进行模块调用和参数传递等等。关于这部分的内容,可以查看OVI_VerilogA文档的第7章。

8. 一些示例程序

个人认为,学如何写程序的一种非常好的方式就是去研究几个示例程序。所以这里我也放上几个非常简单的示例供大家来学习。

8.1 一个理想电阻

请看本文第5.5节。

8.2 一个理想电容

// Cadence 默认调用的两个宏定义,不用管为啥,写上就完事了。
`include "discipline.h"
`include "constants.h" 

module cap (vp, vn); // 定义一个叫做cap的module,它有俩个端口vp和vn
    inout vp, vn; // 这两个端口都是双向端口
    parameter real c = 1p from [0, 1]; // 这个模型有一个参数c,取值为0到1F,包括两个边界
    electrical vp, vn; // 定义vp和vn为两个电学节点
    
    analog
        I(vp, vn) <+ c * ddt(V(vp, vn)); // 赋予vp和vn两个节点之间电容特性
endmodule

8.3 一个电阻电桥,4个电阻的阻值都可以设定

`include "discipline.h"
`include "constants.h" 

module res_bridge (N, W, S, E); 
    inout N, W, S, E; 
    parameter real R_NW = 0 from [0, 100M];
    parameter real R_NE = 0 from [0, 100M];
    parameter real R_WS = 0 from [0, 100M];
    parameter real R_ES = 0 from [0, 100M];
    electrical N, W, S, E;
    
    analog begin
        V(N, W) <+ R_NW * I(N, W);
        V(N, E) <+ R_NE * I(N, E);
        V(W, S) <+ R_WS * I(W, S);
        V(E, S) <+ R_ES * I(E, S);
    end
endmodule

8.4 一个理想的开关

代码提供者:Bcaritas

`include "discipline.h"
`include "constants.h" 

module sw_with_R(vp, vn, vctrlp, vctrln);
input vctrlp, vctrln;
inout vp, vn;
electrical vp, vn, vctrlp, vctrln;
parameter real vth = 0.5;
parameter real Ron = 1u;
parameter real Roff = 1G;
integer sw_state;
real idc;
	
analog begin
   sw_state = (V(vctrlp,vctrln) > vth) ? 1: 0;

   @ (cross(V(vctrlp, vctrln) - vth, 1, 1.0, vctrlp.potential.abstol) )
     sw_state = 1;
   @ (cross(V(vctrlp, vctrln) - vth, -1, 1.0, vctrlp.potential.abstol) )
     sw_state = 0;

   if (sw_state == 0)begin
       V(vp,vn) <+  I(vp,vn) * Roff;
       idc = I(vp,vn);
   end
   else begin
       V(vp,vn) <+  I(vp,vn) * Ron;
       idc = I(vp,vn);
   end
end
endmodule

8.5 一个理想的具有单极点的全差分运放

该 model 能够用来进行 AC 相关的仿真,但是进行时域仿真会存在一定的稳定时间才能正常工作,目前尚未解决该问题。

// VerilogA for Pipline_amp_t28, Diffamp_model, veriloga

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

// $Date: 1997/08/28 05:45:21 $
// $Revision: 1.1 $
//
//
// Based on the OVI Verilog-A Language Reference Manual, version 1.0 1996
//
//

`define PI  	3.14159265358979323846264338327950288419716939937511

//--------------------
// Diffamp_model
//
// - Differential operational amplifier
//
// VINP,VINN:	differential input voltage [V,A]
// VOUTP, VOUTN: differential	output voltage [V,A]
// VCM:	output common-mode voltage [V,A]
// VDD:	positive supply voltage [V,A]
// VSS:	negative supply voltage [V,A]
//
// INSTANCE parameters
//    Gain           = gain []
//    GBW            = unity gain frequency [Hz]
//    Rin            = input resistance [Ohms]
//    Vin_offset     = input offset voltage referred to negative [V]
//    Iin            = input current [A]
//    Iout_max       = maximum current [A]
//    Slew_rate      = slew rate [A/F]
//    Rout           = output resistance [Ohms]
//    Vsoft          = soft output limiting value [V]
//
// MODEL parameters
//    {none}
//


module Diffamp_model(VINP, VINN, VOUTP, VOUTN, VCM, VDD, VSS);
input VINP, VINN, VCM;
inout VOUTP, VOUTN, VDD, VSS;
electrical VINP, VINN, VOUTP, VOUTN, VCM, VDD, VSS;
parameter real Gain = 1e6;
parameter real GBW  = 1.0e9;
parameter real Rin = 1e9;
parameter real Vin_offset = 0.0;
parameter real Iin = 0.0;
parameter real Iout_max = 3e-3;
parameter real Slew_rate = 1.5e9;
parameter real Rout = 1e-6;
parameter real Vsoft = 0.5;
real co;
real gm_nom;
real ro;
real vmax_in;
real vin_val;
electrical coutp, coutn;
analog begin
    	@ ( initial_step or initial_step("dc") ) begin
	co = Iout_max / (Slew_rate);
	gm_nom = 2 * `PI * GBW * co;
	ro = Gain / gm_nom;
	vmax_in = Iout_max / 2 * gm_nom;
   	end
	vin_val = V(VINP, VINN) + Vin_offset;
    // Input stage.
    I(VINP, VINN) <+ (V(VINP, VINN) + Vin_offset) / Rin;
    I(VINP) <+ Iin;
    I(VINN) <+ Iin;
    // GM stage with slewing
    I(VCM, coutp) <+ V(VCM, coutp)/100e9;
	I(VCM, coutn) <+ V(VCM, coutn)/100e9;
    if (vin_val > vmax_in) begin
       I(VCM, coutp) <+ Iout_max;
       I(VCM, coutn) <+ - Iout_max;
       end
    else if (vin_val < -vmax_in) begin
       I(VCM, coutp) <+ -Iout_max;
       I(VCM, coutn) <+ Iout_max;
       end
    else begin
       I(VCM, coutp) <+ gm_nom * 0.5 * vin_val;
       I(VCM, coutn) <+ -gm_nom * 0.5 * vin_val;
    end
    // Dominant Pole.
    I(coutp, VCM) <+ ddt(co*V(coutp, VCM));
    I(coutp, VCM) <+ V(coutp, VCM)/ro;
    I(coutn, VCM) <+ ddt(co*V(coutn, VCM));
    I(coutn, VCM) <+ V(coutn, VCM)/ro;
    // Output Stage.
    I(VCM, VOUTP) <+ V(coutp, VCM)/Rout;
    I(VOUTP, VCM) <+ V(VOUTP, VCM)/Rout;
	I(VCM, VOUTN) <+ V(coutn, VCM)/Rout;
    I(VOUTN, VCM) <+ V(VOUTN, VCM)/Rout;
    // Soft Output Limiting.
    if (V(VOUTP, VOUTN) > (V(VDD, VSS) - Vsoft)) begin
       I(coutp, VCM) <+ 0.5*gm_nom*(V(VOUTP, VOUTN) - V(VDD, VSS) + Vsoft);
       I(coutn, VCM) <+ -0.5*gm_nom*(V(VOUTP, VOUTN) - V(VDD, VSS) + Vsoft);
   end
   else if (V(VOUTP, VOUTN) < (V(VSS, VDD) + Vsoft)) begin
       I(coutp, VCM) <+ gm_nom*(V(VOUTP, VOUTN) - V(VSS, VDD) - Vsoft);
       I(coutn, VCM) <+ gm_nom*(V(VOUTP, VOUTN) - V(VSS, VDD) - Vsoft);
   end
end

endmodule

8.6 一个不受时钟控制的理想比较器

// VerilogA for Pipline_amp_t28, CMP_Ideal_top, veriloga
//
// INSTANCE parameters
//    sigout_high  = maximum output of the comparator  (val)
//    sigout_low   = minimum output of the comparator  (val)
//    sigin_offset = subtracted from 'sigin' before comparason to sigref (val)
//    comp_slope   = determines the sensitivity of the comparator []
//    tdel, trise, tfall = {usual} [s]
//
// MODEL parameters
//    {none}
//
// Compares ('sigin'-'sigin_offset') to 'sigref' - the output is related to
// their difference by a tanh relationship.
//
// If the difference > 'sigref', 'sigout' is 'sigout_high'.
// If the difference = 'sigref', 'sigout' is ('sigout_high' + 'sigout_low')/2.
// If the difference < 'sigref', 'sigout' is 'sigout_low'.
// Intermediate points are fitting to a tanh scaled by 'comp_slope'.
//

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

module CMP_Ideal_noclk_top(siginp, siginn, sigrefp, sigrefn, sigoutp, sigoutn);
input siginp, siginn, sigrefp, sigrefn;
output sigoutp, sigoutn;
electrical siginp, siginn, sigrefp, sigrefn, sigoutp, sigoutn;
parameter real sigout_high = 1.8;
parameter real sigout_low = 0;
parameter real sigin_offset = 0;
parameter real comp_slope = 10000;
parameter real tdel = 0 from [0:inf);
parameter real trise = 10p from (0:inf);
parameter real tfall = 10p from (0:inf);
real voutp, voutn;

analog begin
	@ ( initial_step ) begin
	 	if (sigout_high <= sigout_low) begin
	    		$display("Range specification error.  sigout_high = (%E) less than sigout_low = (%E).\n", sigout_high, sigout_low);
	 	end
		voutp = 0.5 * (sigout_high - sigout_low) * tanh(comp_slope*(V(siginp, siginn) - sigin_offset - V(sigrefp, sigrefn))) + (sigout_high + sigout_low)/2;
		voutn = 1.8 - (0.5 * (sigout_high - sigout_low) * tanh(comp_slope*(V(siginp, siginn) - sigin_offset - V(sigrefp, sigrefn))) + (sigout_high + sigout_low)/2);
	end
	@ (cross((V(siginp, siginn) - sigin_offset - V(sigrefp, sigrefn)), 1))begin
		voutp = sigout_high;
		voutn = sigout_low;
	end
    @ (cross((V(siginp, siginn) - sigin_offset - V(sigrefp, sigrefn)), -1))begin
		voutp = sigout_low;
		voutn = sigout_high;
	end
	V(sigoutp) <+ transition(voutp, tdel, trise, tfall);
	V(sigoutn) <+ transition(voutn, tdel, trise, tfall);
end

endmodule

8.7 一个受时钟控制的理想比较器

// VerilogA for Pipline_amp_t28, CMP_Ideal_top, veriloga
//
// INSTANCE parameters
//    sigout_high  = maximum output of the comparator  (val)
//    sigout_low   = minimum output of the comparator  (val)
//    sigin_offset = subtracted from 'sigin' before comparason to sigref (val)
//    comp_slope   = determines the sensitivity of the comparator []
//    tdel, trise, tfall = {usual} [s]
//
// MODEL parameters
//    {none}
//
// Compares ('sigin'-'sigin_offset') to 'sigref' - the output is related to
// their difference by a tanh relationship.
//
// If the difference > 'sigref', 'sigout' is 'sigout_high'.
// If the difference = 'sigref', 'sigout' is ('sigout_high' + 'sigout_low')/2.
// If the difference < 'sigref', 'sigout' is 'sigout_low'.
// Intermediate points are fitting to a tanh scaled by 'comp_slope'.
//

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

module CMP_Ideal_withclk_top(clk, siginp, siginn, sigrefp, sigrefn, sigoutp, sigoutn);
input clk, siginp, siginn, sigrefp, sigrefn;
output sigoutp, sigoutn;
electrical clk, siginp, siginn, sigrefp, sigrefn, sigoutp, sigoutn;
parameter real sigout_high = 1.8;
parameter real sigout_low = 0;
parameter real sigin_offset = 0;
parameter real comp_slope = 10000;
parameter real tdel = 0 from [0:inf);
parameter real trise = 10p from (0:inf);
parameter real tfall = 10p from (0:inf);
real voutp, voutn;

analog begin
	@ ( initial_step ) begin
	 	if (sigout_high <= sigout_low) begin
	    		$display("Range specification error.  sigout_high = (%E) less than sigout_low = (%E).\n", sigout_high, sigout_low);
	 	end
		voutp = 0.5 * (sigout_high - sigout_low) * tanh(comp_slope*(V(siginp, siginn) - sigin_offset - V(sigrefp, sigrefn))) + (sigout_high + sigout_low)/2;
		voutn = 1.8 - (0.5 * (sigout_high - sigout_low) * tanh(comp_slope*(V(siginp, siginn) - sigin_offset - V(sigrefp, sigrefn))) + (sigout_high + sigout_low)/2);
	end
	@ (cross((V(clk) - (sigout_high + sigout_low)/2), -1))begin
		if ((V(siginp, siginn) - sigin_offset) >= V(sigrefp, sigrefn))begin
			voutp = sigout_high;
			voutn = sigout_low;
		end else begin
			voutp = sigout_low;
			voutn = sigout_high;
		end
	end
	@ (cross((V(clk) - (sigout_high + sigout_low)/2), 1))begin
		voutp = sigout_high;
		voutn = sigout_high;
	end
	V(sigoutp) <+ transition(voutp, tdel, trise, tfall);
	V(sigoutn) <+ transition(voutn, tdel, trise, tfall);
end

endmodule
后续本人可能会添加更多的Verilog-A例程,但是由于目前本人才刚入门,学艺不精,因此就暂且只写这几个例程了。
另外,OVI_VerilogA这个文档以及Cadence IC的ahdlLib库中中也有很多的例程,大家可以去那里参考学习。

后记

本文只是简单的讲了一下Verilog-A的一些基本的语法。然而Verilog-A还有很多的语法和功能本文中并没有提到。如果大家感兴趣或者需要进一步学习的,可以去看这篇文档:OVI_VerilogA。同时,Verilog-A不仅仅是一个语言,也是一个非常强大的系统级建模的工具。但是由于目前本人才疏学浅,对模拟IC仅处于入门阶段,因此无法详述。如果本文中有错误和不妥之处,也请大家多多指正。

本文采用知识共享 署名 - 非商业性使用 4.0 许可,转载请注明出处;如果有某些问题想和本人讨论,可以发送邮件至:absolutezero@stu.xjtu.edu.cn

评论

  1. 嘿嘿
    Windows Chrome
    2 年前
    2022-8-05 10:44:28

    毕,我的毕,你的博客已经到谷歌首页了୧(๑•̀⌄•́๑)૭

    • 博主
      嘿嘿
      Windows Firefox
      2 年前
      2022-8-05 16:18:37

      啊,感谢寄巨佬捧场,以后混的好了记得提携我一下。

  2. Yihan
    Windows Edge
    2 年前
    2022-9-23 15:25:37

    写的很好!~博主太有心了!

  3. 装触
    Windows Firefox
    2 年前
    2022-11-02 22:24:49

    很有帮助!

  4. MAC
    Windows Edge
    1 年前
    2023-2-03 21:28:04

    简洁有效

  5. 剑川路955号守门人
    Windows Chrome
    12 月前
    2023-7-31 0:09:03

    有用bd

  6. 赵工
    Windows Edge
    10 月前
    2023-9-20 19:05:09

    谢谢分享

  7. 折痕
    Windows Edge
    9 月前
    2023-11-09 15:27:05

    博主大佬好,我想请问使用verilog-A是否可以编写一个自定义的不规则的电压源或者电流源作为电路的激励呢?

    • 博主
      折痕
      Windows Firefox
      8 月前
      2023-11-15 22:31:43

      不知道你说的不规则电压源或者电流源是什么样子的?你现在的这个描述太笼统了,我这边也没办法判断可不可以实现,可以把功能需求描述的在详细一点吗?

  8. xuyuelong
    Windows Edge
    8 月前
    2023-12-02 16:24:40

    博主您好,在一个理想的具有单极点的全差分运放代码中,VCM为啥写成input呢

    • 博主
      xuyuelong
      Windows Firefox
      8 月前
      2023-12-03 18:39:16

      这个是因为通常对于一个全差分放大器而言,会有一个共模反馈电路,这个电路的目的是将运放的输出共模电压稳定在一个给定的数值上,这个输出共模值通常是由一个共模电平输入引脚来确定的,因此全差分运放一般都会有一个共模电平输入端,共模反馈环路会将运放的输出共模电平稳定在这个输入共模值上。这个 verilog-a 模型中 VCM 引脚设置成 INPUT 的目的就是为了模拟这一个共模电平输入功能。

      • xuyuelong
        干饭睡觉真君
        Windows Edge
        8 月前
        2023-12-03 21:25:59

        谢谢博主,学习了,感谢感谢

  9. 松鼠不是白毛控
    Windows Chrome
    6 月前
    2024-1-14 14:46:22

    做毕设又刷到学长的帖子了

  10. 锁相环
    Windows Chrome
    6 月前
    2024-1-19 13:44:12

    有小数DSM和PS分频器的veriloga代码吗?

    • 博主
      锁相环
      Windows Firefox
      6 月前
      2024-1-19 23:32:12

      抱歉,这个没有。

    • yyyy
      锁相环
      Windows Edge
      2 天前
      2024-7-20 22:32:24

      您好,请问现在有小数分频的代码了吗

      • 博主
        yyyy
        Windows Firefox
        14 小时前
        2024-7-22 18:46:03

        抱歉,我这边暂时不做时钟,所以并没有相关代码。

  11. 飞飞飞
    Windows Chrome
    2 月前
    2024-5-25 21:00:02

    请问Verilog-A用什么编译器

    • 博主
      飞飞飞
      Windows Firefox
      2 月前
      2024-5-27 13:36:14

      我这里用的是 Cadence virtuoso,许多支持模拟电路仿真的 EDA 软件都支持 Verilog-A.

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇