Lecture 2 : System Realization
All of the block diagram operations we talked about with respect to Laplace transforms still apply. Series (cascade), parallel, and feedback configurations all have the same block diagram simplifications.
The same techniques we used for ``system realization'' of Laplace transforms
still apply for Z-transforms. The only difference is to substitute
for
.
Even though the diagram ends up the same, there may be understanding to be gained
by working through the steps. As before, we will take an example of a third
order transfer function
Break this into two pieces: Let
and let
From
Note that in FIR filters the output depends only on the current
and previous inputs. In IIR filters, the output depends on these and
also on
prior outputs
-- there is some kind of feedback. It is
this feedback that gives them their infinite response.
This realization is useful in a sort of theoretical sense, and gives us a
map of what is going on. But, unlike for continuous-time systems, there is no
practical way of doing this using resistors, capacitors, and op-amps. What the
diagram really represents is a
computer program
. We will now talk about
how this is done. We will start first with an FIR filter. Consider the particular
example of
Transforming back,
,
fprevious[1]
is the last value of
, and so on. Furthermore, let
is keep track of the coefficients in an array called
coefficient
, set up as follows:
coefficient[0] = 2;
coefficient[1] = 3;
coefficient[2] = 4;
coefficient[3] = 5;
Now we will create a filtering routine, and pass the coefficients into it. Note: this code is provided for demonstration purposes only. It may have minor problems with it that the student is expected to be able to understand and correct.
1firfilt1.c
This computes the output and shifts everything down. Note that we have to save the previous values of the outputs so they can be used for the next call to the filter. This has problems -- suppose you have more than one filter -- how do you keep things from getting messed up. Perhaps a cleaner way to do this would be to pass in the previous values to the filter. The cleanest way is probably to use C++ with a constructor that keeps a separate data set for each instantiation of the filter class. I will leave these finessings to the diligent student.
To generalize our simple filter routine, let us allow different numbers of coefficients to be passed in. This means that we have to allocate sufficient space for the previous values, and add everything up in a loop. 1firfilt2.c
For the diligent students interested in speeding things up as much as possible, I pose the following ideas:
- Can the filter loop and the shift loop be combined, so that only one loop needs to be execute to accomplish both functions?
- The shifting operation is slow and unnecessary. How could you use a circular queue to store the previous values so that the shifting operation is no longer necessary?
Enough about FIR filters. Implementing IIR filters will also be addressed
by means of an example. We want to implement the filter represented by
Shifting in time and solving for
numcoeff[0] = 6;
numcoeff[1] = 2; dencoeff[1] = -4;
numcoeff[2] = 3; dencoeff[2] = -5;
Caution
: note that the denominator coefficients are the negative of
the coefficients in the original transfer function. We will keep the
previous input values in an array
fprevious
and keep previous
output values in an array
yprevious
.
1iirfilt1.c
As before, we will generalize this to arbitrary transfer functions of denominator degree degree : 1iirfilt2.c Again, speedups are attainable: merge the shift loop into the filter loop, or get rid of shifting entirely by using a circular queue.