Hello folks, it’s been a while since I wrote something on this blog. I have been quite busy with graduate school so I left this blog aside. Besides, I wanted to write this post because I had a hard time finding material related to the basics of Verilog-A for digital-like modeling of circuits. I think using Verilog-A instead of Verilog in the Virtuoso environment can be less troublesome for simple digital logic. The Verilog requires the Virtuoso Analog Mixed-Signal (AMS) simulator. Moreover, setting up AMS can be quite a pain, it will probably run slower than the same Verilog-A model and AMS has limited simulation functions in ADEL compared to the spectre simulator.
The following Verilog-A block models an FIR filter. The number of filter taps can be set with the “F_SIZE” variable. The output transition between samples can be set with the “trans” variable. In the initial block, the filter coefficients are loaded from a text file, which can be generated by MATLAB for example and transferred to the “coeff” array. The “x_d” vector models the flip-flops inside the FIR. In the continuous block (analog begin) the “@cross” function is an event trigger that will model a flip flop if a certain threshold is crossed. When it happens, the output is calculated by a for loop and the samples are shifted in the “x_d” vector in another for loop.
module yat_FIR(x,clk,y,VDD,VSS);
electrical x,clk,y,VDD,VSS; // I/O and supply ports(VDD and VSS)
integer F_SIZE = 256; // Number of filter taps
real x_d [F_SIZE-1:0]; // Filter flip flops
real coeff[F_SIZE-1:0]; // Filter coefficients
real aux;
parameter trans = 15.625p; // sets transition
integer k,fd,n;
genvar i;
analog initial begin
fd = $fopen("FIR_coefficients.txt","r"); // Coefficients file
n = 0;
for(k=0;k<F_SIZE;k=k+1) begin
$fscanf(fd,"%f\n",coeff[n]); // Load coefficients to array
n = n+1;
end
for(k=0;k<F_SIZE;k=k+1) begin
x_d[k] = 0; // Initialize array
end
end
analog begin
//posedge detection
@(cross( V(clk) - (V(VDD)/2),1,10p) ) begin
aux = 0;
for(i=0;i<256;i=i+1) begin
aux = aux + x_d[i]*coeff[i]; // Multiply accumulate
end
x_d[0] = V(x,VSS); // insert the input at first flip flop
for(i=256-2;i>=0;i=i-1) begin
x_d[i+1] = x_d[i]; // shift the flip flops value
end
end
// Node y voltage receives value of "aux" with transition "trans"
V(y) <+ transition(aux,0,trans);
end
endmodule