1 |
6 |
root |
/* ********************************************************************************* */
|
2 |
|
|
/* Bi-quad IIR filter section */
|
3 |
|
|
/* */
|
4 |
|
|
/* Author: Chuck Cox (chuck100@home.com) */
|
5 |
|
|
/* */
|
6 |
|
|
/* This module implements an IIR filter section with 2 poles and */
|
7 |
|
|
/* 2 zeros. The filter coefficients are inputs to this module. */
|
8 |
|
|
/* Multiple bi-quad filter sections can be connected together to */
|
9 |
|
|
/* create higher order filters. The filter uses a signed fractional */
|
10 |
|
|
/* 2's complement binary numbering system. For example with 3 bits: */
|
11 |
|
|
/* */
|
12 |
|
|
/* 000 = 0 001 = 0.25 010 = 0.5 011 = 0.75 */
|
13 |
|
|
/* 100 = 0 101 = -.75 110 = -.5 111 = -.25 */
|
14 |
|
|
/* */
|
15 |
|
|
/* The equation for the filter implemented with this module is */
|
16 |
|
|
/* y[n] = b10 * x[n] + b11 * x[n-1] + b12 * x[n-2] + a11 * y[n-1] + a12 * y[n-2] */
|
17 |
|
|
/* */
|
18 |
|
|
/* Multipliers are implemented as calls to seperate modules to allow easy */
|
19 |
|
|
/* conversion to hard or firm macros. Multicycle multipliers can be used */
|
20 |
|
|
/* by not making input data valid on every clock. For a 4 clock multiplier */
|
21 |
|
|
/* data will need to be valid only once every 4 clocks. */
|
22 |
|
|
/* */
|
23 |
|
|
/* */
|
24 |
|
|
/* ********************************************************************************* */
|
25 |
|
|
|
26 |
|
|
|
27 |
|
|
module biquad
|
28 |
|
|
(
|
29 |
|
|
clk, /* clock */
|
30 |
|
|
nreset, /* active low reset */
|
31 |
|
|
x, /* data input */
|
32 |
|
|
valid, /* input data valid */
|
33 |
|
|
a11, /* filter pole coefficient */
|
34 |
|
|
a12, /* filter pole coefficient */
|
35 |
|
|
b10, /* filter zero coefficient */
|
36 |
|
|
b11, /* filter zero coefficient */
|
37 |
|
|
b12, /* filter zero coefficient */
|
38 |
|
|
yout /* filter output */
|
39 |
|
|
);
|
40 |
|
|
|
41 |
|
|
parameter DATAWIDTH = 8;
|
42 |
|
|
parameter COEFWIDTH = 8;
|
43 |
|
|
// Acumulator width is (DATAWIDTH + ACCUM) bits.
|
44 |
|
|
parameter ACCUM = 2; // Must be less than or equal to COEFWIDTH-2
|
45 |
|
|
|
46 |
|
|
input clk;
|
47 |
|
|
input nreset;
|
48 |
|
|
input [DATAWIDTH-1:0] x;
|
49 |
|
|
input valid;
|
50 |
|
|
input [COEFWIDTH-1:0] a11;
|
51 |
|
|
input [COEFWIDTH-1:0] a12;
|
52 |
|
|
input [COEFWIDTH-1:0] b10;
|
53 |
|
|
input [COEFWIDTH-1:0] b11;
|
54 |
|
|
input [COEFWIDTH-1:0] b12;
|
55 |
|
|
output [DATAWIDTH-1:0] yout;
|
56 |
|
|
|
57 |
|
|
reg [DATAWIDTH-1:0] xvalid;
|
58 |
|
|
reg [DATAWIDTH-1:0] xm1;
|
59 |
|
|
reg [DATAWIDTH-1:0] xm2;
|
60 |
|
|
reg [DATAWIDTH-1:0] xm3;
|
61 |
|
|
reg [DATAWIDTH-1:0] xm4;
|
62 |
|
|
reg [DATAWIDTH-1:0] xm5;
|
63 |
|
|
reg [DATAWIDTH+3+ACCUM:0] sumb10reg;
|
64 |
|
|
reg [DATAWIDTH+3+ACCUM:0] sumb11reg;
|
65 |
|
|
reg [DATAWIDTH+3+ACCUM:0] sumb12reg;
|
66 |
|
|
reg [DATAWIDTH+3+ACCUM:0] suma12reg;
|
67 |
|
|
reg [DATAWIDTH+3:0] y;
|
68 |
|
|
reg [DATAWIDTH-1:0] yout;
|
69 |
|
|
|
70 |
|
|
wire [COEFWIDTH-1:0] sa11;
|
71 |
|
|
wire [COEFWIDTH-1:0] sa12;
|
72 |
|
|
wire [COEFWIDTH-1:0] sb10;
|
73 |
|
|
wire [COEFWIDTH-1:0] sb11;
|
74 |
|
|
wire [COEFWIDTH-1:0] sb12;
|
75 |
|
|
wire [DATAWIDTH-2:0] tempsum;
|
76 |
|
|
wire [DATAWIDTH+3+ACCUM:0] tempsum2;
|
77 |
|
|
wire [DATAWIDTH + COEFWIDTH - 3:0] mb10out;
|
78 |
|
|
wire [DATAWIDTH+3+ACCUM:0] sumb10;
|
79 |
|
|
wire [DATAWIDTH + COEFWIDTH - 3:0] mb11out;
|
80 |
|
|
wire [DATAWIDTH+3+ACCUM:0] sumb11;
|
81 |
|
|
wire [DATAWIDTH + COEFWIDTH - 3:0] mb12out;
|
82 |
|
|
wire [DATAWIDTH+3+ACCUM:0] sumb12;
|
83 |
|
|
wire [DATAWIDTH + COEFWIDTH + 1:0] ma12out;
|
84 |
|
|
wire [DATAWIDTH+3+ACCUM:0] suma12;
|
85 |
|
|
wire [DATAWIDTH + COEFWIDTH + 1:0] ma11out;
|
86 |
|
|
wire [DATAWIDTH+3+ACCUM:0] suma11;
|
87 |
|
|
wire [DATAWIDTH+3:0] sy;
|
88 |
|
|
wire [DATAWIDTH-1:0] olimit;
|
89 |
|
|
|
90 |
|
|
|
91 |
|
|
/* Two's complement of coefficients */
|
92 |
|
|
assign sa11 = a11[COEFWIDTH-1] ? (~a11 + 1) : a11;
|
93 |
|
|
assign sa12 = a12[COEFWIDTH-1] ? (~a12 + 1) : a12;
|
94 |
|
|
assign sb10 = b10[COEFWIDTH-1] ? (~b10 + 1) : b10;
|
95 |
|
|
assign sb11 = b11[COEFWIDTH-1] ? (~b11 + 1) : b11;
|
96 |
|
|
assign sb12 = b12[COEFWIDTH-1] ? (~b12 + 1) : b12;
|
97 |
|
|
|
98 |
|
|
assign tempsum = ~xvalid[DATAWIDTH-2:0] + 1;
|
99 |
|
|
assign tempsum2 = ~{4'b0000,mb10out[COEFWIDTH+DATAWIDTH-3:COEFWIDTH-2-ACCUM]} + 1;
|
100 |
|
|
|
101 |
|
|
/* clock data into pipeline. Divide by 8. Convert to sign magnitude. */
|
102 |
|
|
always @(posedge clk or negedge nreset)
|
103 |
|
|
if ( ~nreset )
|
104 |
|
|
begin
|
105 |
|
|
xvalid <= 0;
|
106 |
|
|
xm1 <= 0;
|
107 |
|
|
xm2 <= 0;
|
108 |
|
|
xm3 <= 0;
|
109 |
|
|
xm4 <= 0;
|
110 |
|
|
xm5 <= 0;
|
111 |
|
|
end
|
112 |
|
|
else
|
113 |
|
|
begin
|
114 |
|
|
xvalid <= valid ? x : xvalid;
|
115 |
|
|
xm1 <= valid ? (xvalid[DATAWIDTH-1] ? ({xvalid[DATAWIDTH-1],tempsum}) : {xvalid}) : xm1;
|
116 |
|
|
xm2 <= valid ? xm1 : xm2;
|
117 |
|
|
xm3 <= valid ? xm2 : xm3;
|
118 |
|
|
xm4 <= valid ? xm3 : xm4;
|
119 |
|
|
xm5 <= valid ? xm4 : xm5;
|
120 |
|
|
end
|
121 |
|
|
|
122 |
|
|
/* Multiply input by filter coefficient b10 */
|
123 |
|
|
multb multb10(.clk(clk),.nreset(nreset),.a(sb10[COEFWIDTH-2:0]),.b(xm1[DATAWIDTH-2:0]),.r(mb10out));
|
124 |
|
|
|
125 |
|
|
assign sumb10 = (b10[COEFWIDTH-1] ^ xm1[DATAWIDTH-1]) ? (tempsum2) : ({4'b0000,mb10out[COEFWIDTH+DATAWIDTH-3:COEFWIDTH-2-ACCUM]});
|
126 |
|
|
|
127 |
|
|
/* Multiply input by filter coefficient b11 */
|
128 |
|
|
multb multb11(.clk(clk),.nreset(nreset),.a(sb11[COEFWIDTH-2:0]),.b(xm3[DATAWIDTH-2:0]),.r(mb11out));
|
129 |
|
|
|
130 |
|
|
/* Divide by two and add or subtract */
|
131 |
|
|
assign sumb11 = (b11[COEFWIDTH-1] ^ xm3[DATAWIDTH-1]) ? (sumb10reg - {4'b0000,mb11out[COEFWIDTH+DATAWIDTH-3:COEFWIDTH-2-ACCUM]}) :
|
132 |
|
|
(sumb10reg + {4'b0000,mb11out[COEFWIDTH+DATAWIDTH-3:COEFWIDTH-2-ACCUM]});
|
133 |
|
|
|
134 |
|
|
/* Multiply input by filter coefficient b12 */
|
135 |
|
|
multb multb12(.clk(clk),.nreset(nreset),.a(sb12[COEFWIDTH-2:0]),.b(xm5[DATAWIDTH-2:0]),.r(mb12out));
|
136 |
|
|
|
137 |
|
|
assign sumb12 = (b12[COEFWIDTH-1] ^ xm5[DATAWIDTH-1]) ? (sumb11reg - {4'b0000,mb12out[COEFWIDTH+DATAWIDTH-3:COEFWIDTH-2-ACCUM]}) :
|
138 |
|
|
(sumb11reg + {4'b0000,mb12out[COEFWIDTH+DATAWIDTH-3:COEFWIDTH-2-ACCUM]});
|
139 |
|
|
|
140 |
|
|
/* Twos complement of output for feedback */
|
141 |
|
|
assign sy = y[DATAWIDTH+3] ? (~y + 1) : y;
|
142 |
|
|
|
143 |
|
|
/* Multiply output by filter coefficient a12 */
|
144 |
|
|
multa multa12(.clk(clk),.nreset(nreset),.a(sa12[COEFWIDTH-2:0]),.b(sy[DATAWIDTH+2:0]),.r(ma12out));
|
145 |
|
|
|
146 |
|
|
assign suma12 = (a12[COEFWIDTH-1] ^ y[DATAWIDTH+3]) ? (sumb12reg - {1'b0,ma12out[COEFWIDTH+DATAWIDTH:COEFWIDTH-2-ACCUM]}) :
|
147 |
|
|
(sumb12reg + {1'b0,ma12out[COEFWIDTH+DATAWIDTH:COEFWIDTH-2-ACCUM]});
|
148 |
|
|
|
149 |
|
|
/* Multiply output by filter coefficient a11 */
|
150 |
|
|
multa multa11(.clk(clk),.nreset(nreset),.a(sa11[COEFWIDTH-2:0]),.b(sy[DATAWIDTH+2:0]),.r(ma11out));
|
151 |
|
|
|
152 |
|
|
assign suma11 = (a11[COEFWIDTH-1] ^ y[DATAWIDTH+3]) ? (suma12reg - {1'b0,ma11out[COEFWIDTH+DATAWIDTH:COEFWIDTH-2-ACCUM]}) :
|
153 |
|
|
(suma12reg + {1'b0,ma11out[COEFWIDTH+DATAWIDTH:COEFWIDTH-2-ACCUM]});
|
154 |
|
|
|
155 |
|
|
assign olimit = {y[DATAWIDTH+3],~y[DATAWIDTH+3],~y[DATAWIDTH+3],~y[DATAWIDTH+3],~y[DATAWIDTH+3],
|
156 |
|
|
~y[DATAWIDTH+3],~y[DATAWIDTH+3],~y[DATAWIDTH+3]};
|
157 |
|
|
|
158 |
|
|
/* State registers */
|
159 |
|
|
always @(posedge clk or negedge nreset)
|
160 |
|
|
if ( ~nreset )
|
161 |
|
|
begin
|
162 |
|
|
sumb10reg <= 0;
|
163 |
|
|
sumb11reg <= 0;
|
164 |
|
|
sumb12reg <= 0;
|
165 |
|
|
suma12reg <= 0;
|
166 |
|
|
y <= 0;
|
167 |
|
|
yout <= 0;
|
168 |
|
|
end
|
169 |
|
|
else
|
170 |
|
|
begin
|
171 |
|
|
sumb10reg <= valid ? (sumb10) : (sumb10reg);
|
172 |
|
|
sumb11reg <= valid ? (sumb11) : (sumb11reg);
|
173 |
|
|
sumb12reg <= valid ? (sumb12) : (sumb12reg);
|
174 |
|
|
suma12reg <= valid ? (suma12) : (suma12reg);
|
175 |
|
|
y <= valid ? suma11[DATAWIDTH+3+ACCUM:ACCUM] : y;
|
176 |
|
|
yout <= valid ? (( (&y[DATAWIDTH+3:DATAWIDTH-1]) | (~|y[DATAWIDTH+3:DATAWIDTH-1]) ) ?
|
177 |
|
|
(y[DATAWIDTH-1:0]) : (olimit)) : (yout);
|
178 |
|
|
end
|
179 |
|
|
|
180 |
|
|
|
181 |
|
|
endmodule
|