![]() |
In this Topic Hide
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[0] = 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
This design introduces these language features:
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 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. |
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.
|