Butterworth Filter

Here we present a butterworth filter with arbitrary order. SIMetrix already has something like this built-in, but we show a Verilog-A version to demonstrate arrays, looping constructs and the Laplace analog operators.

The design allows the user to specify the order of the filter using a model parameter. The filter itself is implemented using the analog operator laplace_nd which provides a Laplace transfer function defined by its numerator and denominator polynomial coefficients. To calculate the coefficients for the specified order, we build an array for the denominator coefficients using a for loop. The array only needs to be calculated once so we put this calculation in response to an initial_step event. (Actually it will be recalculated on each dc operating point iteration which is not as efficient as it could be. This is an area that we hope to address in a future revision.)

'include "disciplines.vams"
'include "constants.vams"

module laplace_butter(in,ref,out) ;

real res ;
electrical in, ref, out ;
parameter freq=1.0 ;
parameter integer order=5 ;

real scale, bPrev ;
// Denominator array size
real den[order:0] ;
integer k ;

analog
begin

//	Calculate Butterworth coefficients
@ (initial_step)
begin
scale = 1.0/freq/2/'M_PI ;
bPrev = 1.0 ;
den = 1.0 ;

for (k=1 ; k<order+1 ; k=k+1)
begin
bPrev = scale*cos((k-1.0)/order*('M_PI*0.5))/
sin((k*0.5)/order*'M_PI) * bPrev ;
den[k] = bPrev ;

\$strobe("den coeff %d = %g", k, den[k]) ;
end
end

// Actual Butterworth filter
res = laplace_nd( V(in,ref), {1.0}, den) ;
V(out,ref) <+ res ;
end
endmodule

See Examples/Manual/Butterworth-filter

1. Array variables
2. For loops
3. The lapalace_nd analog operator

In this topic:

Arrays

Verilog-A supports arrays of both variables and parameters. In the example above we use an array to store the denominator coefficients for the laplace_nd analog operator. Array variables must be declared with their range of allowed indexes using this syntax:

type array_name[low_index:high_index] ;
Where:
 type real or integer array_name name of array low_index Minimum index allowed high_index Maximum index allowed

low_index and high_index determine the number of elements in the array to be $\textit{high_index} - \textit{low_index} +1$.

For Loops

For loops use a syntax similar to the 'C' language. This is as follows:

for (initial_assignment ; test_expression ; loop_assignment )
statement
 initial_assignment Assignment statement (in the form variable = expression) that is executed just once on entry to the loop. Typically this would be an assignment that assigns a loop counter variable a constant value. In the example it assigns 1 to the variable k. test_expression Expression is evaluated at the start of each iteration around the loop before statement. If the result of the evaluation is non-zero, statement will be executed. If not the loop will be terminated. loop_assignment Assignment statement that is executed after statement. Typically this would be an assignment that increments or decrements a loop counter variable.In the above it increments k by 1.

laplace_nd Function

The laplace_nd function implements a Laplace transfer function. This is in the form:

$H(s) = \frac{n_0 + n_1s + n_2s^2 + ... + n_ms^m}{d_0 + d_1s +d_2s^2 + ... + d_ms^m}$

where $d_0, d_1, d_2, ..., d_m$ are the denominator coefficients and $n_0, n_1, n_2, ..., n_m$ are the numerator coefficients and the order is $m$.

The laplace_nd function is in the form:

laplace_nd (expr, num_coeffs, den_coeffs, $\epsilon$)

Where
 expr Input expression num_coeffs Numerator coefficients. This can be entered as an array variable or as an array initialiser. An array initialiser is a sequence of comma separated values enclosed with '{' and '}'. E.g: { 1.0, 2.3, 3.4, 4.5}. The values do not need to be constants. den_coeffs Denominator coefficients in the same format as the numerator - see above. In the example this is provided as the array den. The values in den are calculated in the for loop. $\epsilon$ Tolerance parameter currently unused.

If the constant term on the denominator ( d0 in equation above) is zero, the laplace function must exist inside a closed feedback loop. With a zero denominator, the DC gain is infinite; by putting the function inside a loop, the simulator can maintain the input at zero providing a finite output. A singular matrix error will result otherwise.