手册可以解决99.9%的问题:VerilogAMS_Reference_2011.pdf
数字量控制模拟量的基本思路如下:
always @(posedge/negedge sig)
等方式完成一个 real
形变量的控制;或者可以直接传输外部的 input logic
直接到模拟参与运算。real
型变量是突变的,所以在 analog 域要通过 transition(realValue, delayTime, riseTime, [fallTime])
的方式缓慢地应用这个突变到模拟,否则容易造成不收敛;
module ibias_top(AVDD,AGND,SW,EN,IST,IDT);
inout AVDD,AGND,SW,EN,IST,IDT;
electrical AVDD,AGND,SW,EN,IST,IDT;
electrical ISTOUT;
initial beign
rsw = SW? 1: 1T;
end
always @(*) begin
rsw = SW? 1: 1T;
end
analog begin
I(AVDD,IST) <+ transition(EN*0.5u,0,100n) - (limexp(V(IST,AVDD)/$vt)-1);
I(IDT,AGND) <+ transition(EN*0.5u,0,100n) - (limexp(V(AGND,IDT)/$vt)-1);
// 如果IST这个电流源要通过一个电阻rsw后才能出去,那么可以如下建模
V(IST,ISTOUT) <+ I(IST,ISTOUT)*transtion(rsw,0,100n);
end
在 VerilogAMS中,对于一个 reg [7:0] config [3:0]
config[3] config[2] config[1] config[0]
寄存器,config[0]
中,含有8bit数据,config[0][7:0]
对于reg [7:0] config [3:0]
这个数组,对于一个 integer i,v
我们是可以通过 config[i][v]
直接操作某一位的,但是我们不能直接截取操作 config[i][v:v-1]
数组切片操作过程中,是可以直接截取 config [1][3:0]
中的数据直接操作的,但是需要注意这里的 3:0
中的 3
和 0
是需要常量而不能是一个变量。这样就会很不方便。一个实现方法是
在 Verilog-AMS 中,使用变量作为数组切片的索引时,索引必须是编译时常量,不能使用rawData[i:i-8]
,要使用rawData[i -:9]
。否则会报错illegal operand for constant expression
要解决这个问题,可以使用固定宽度的位选择运算符 [a -: width]
或 [a +: width]
,其中 a
是变量,width
是常量。
[a -: width]
:从索引 a
开始,向下选择 width
位。[a +: width]
:从索引 a
开始,向上选择 width
位。reg [7:0] data = 8'b11011010;
reg [2:0] slice;
integer a;
initial begin
a=5;
slice = data[a -: 3]; // 从索引 5 开始,向下选择 3 位
// slice = data[5:3] = 3'b011
a=2;
slice = data[a +: 3]; // 从索引 2 开始,向上选择 3 位
// slice = data[4:2] = 3'b110
end
在 VerilogAMS 中,因为最终仿真的网表是也是一个 VerilogAMS 的,那么是可以这届操作其它 cell 中的一个网线/寄存器/电气线(wire/reg/electrical)
这样做的目的是,不破坏顶层连接关系,方便读取/控制内部的某个模块的行为。
通过 Hierachy Instance Name 的方式索引到具体的一根线网,
assign I_DUT.I_ANALOG.I_BIAS_TOP.en = 1'b1;
real voltageVal;
voltageVal = V(I_DUT.I_ANALOG.I_BIAS_TOP.VIN);
inital begin
I_DUT.I_ANALOG.I_BIAS_TOP.reg1 = 8'h01;
end
在建模中,我们有时候需要三态端口,例如 CLK PIN 可以作为 主机的输入,接收来自芯片的时钟;也可以当作输出,驱动芯片作为时钟源;这样就意味该端口要有输入输出的功能,同时要有Z
可以通过 wire
和 reg
结合方式实现这点;
module (clk);
inout wire clk;
reg clk_drive=1'b0;
reg clk_en = 1'b0;
reg clk_report = 1'b0;
integer clk_ns = 1000;
integer clk_count = 0;
real clk_value = 0.0;
assign clk = clk_drive;
// clk frequency measurement
always @(poedge clk) begin
if(clk_count == 10) clk_value = $realtime;
if(clk_count == 20) begin
clk_value = 10.0/($realtime-clk_value)*(10**6);
clk_count = 0;
if(clk_report == 1) begin
$display("[DBG_INFO]: %1.3F US, f(CLK)=%1.1fKHz",$realtime/1000,clk_value);
clk_report = 0;
end
end
clk_count = clk_count + 1;
end
// clk generator
always @(*) begin
#clk_ns;
if(clk_en == 1) clk_drive = ~clk_drive;
end
initial begin
// enable clk output;
clk_ns = 1000;clk_drive = 1'b1;clk_en = 1'b1;
// measure f(clk) drived by other module;
clk_en = 1'b0;clk_drive = 1'bz;clk_report = 1'b1;clk_count = 1'b0;
end
在 Cadence IC 617 中可以使用SMG完成建模操作,详见 Schematic-Model-Generator-SOP