Verilog-A 模拟事件

模拟事件 = 模拟域的「事件驱动」。仿真器是连续时间计算,事件语句让内部代码只在特定信号行为发生时执行,简化书写、减少计算量。
事件语句只能放在 analog begin...end 内(absdelta 例外,见下)。

事件触发通用语法

@(eventA or eventB or ...) begin
    // 任一事件发生时执行
end

事件一览

事件 含义 触发时机
initial_step 仿真开始 DC/AC/tran/noise 仿真开始阶段
final_step 仿真结束 仿真正常结束(手动中断不触发)
cross(expr[,dir[,t_tol[,e_tol]]]) 信号穿越 0 值 仅动态仿真(tran 等)
above(expr[,t_tol[,e_tol]]) 信号 > 0 静态也触发(DC/initial_step)
timer(start[,period[,t_tol]]) 周期性事件 按仿真时间
absdelta(expr,delta[,t_tol[,e_tol]]) 变化超过 delta 0 时刻/稳定态/变化超 delta(仅 always 块)

initial_step / final_step

@(initial_step) begin
    // 初始化工作、输出设置信息(整个模块第一个被计算)
end
@(final_step) begin
    // 仿真结束收尾
end

cross(穿越检测)

@(cross(expr1 [, direction [, time_tol [, expr_tol]]])) begin ... end
@(cross(V(in)-vth, 1)) begin
    out = 1;   // 输入超过 vth 时置 1
end

above(大于检测)

@(above(expr1 [, time_tol [, expr_tol]])) begin ... end
@(above(V(in)-vth)) begin
    out = 1;
end

timer(定时器)

@(timer(start_time [, period [, timetol]])) begin ... end
@(timer(0, 10u)) begin
    clk = !clk;             // 生成 10uS 周期时钟
end
V(out) <+ clk*V(vcc, gnd);

absdelta(增量检测)

@(absdelta(expr1, delta [, time_tol [, expr_tol]])) begin ... end
always @(absdelta(V(in), vth)) begin
    out = out + 1;   // 输入每变化 vth 就加 1
end

last_crossing(上次穿越时间)

last_crossing(signal, direction)

ADC 综合示例(事件 + genvar + transition)

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

module adc(out, in, clk);
parameter real fullscale = 1.0;
parameter real td = 0, tt = 0;
parameter real vdd = 5.0;
parameter real thresh = vdd/2;

input in, clk;
output [0:7] out;
voltage in, clk;
voltage [0:7] out;
real sample, midpoint;
integer result[0:7];
integer i;
genvar j;

analog begin
    @(cross(V(clk)-thresh, 1) or initial_step) begin
        sample = V(in);
        midpoint = fullscale/2.0;
        for (i = 7; i >= 0; i = i - 1) begin
            if (sample > midpoint) begin
                result[i] = 1;
                sample = sample - midpoint;
            end else begin
                result[i] = 0;
            end
            sample = 2.0*sample;
        end
    end
    for(j=0;j<8;j=j+1)
        V(out[j]) <+ transition(result[j] ? vdd : 0.0, td, tt);
end
endmodule

结构思路:先在事件内根据输入算出数值结果(数组),再用 genvar 循环赋给输出——减少模拟量互相影响与迭代。

相关笔记