OpenCores
URL https://opencores.org/ocsvn/biquad/biquad/trunk

Subversion Repositories biquad

[/] [biquad/] [web_uploads/] [biquad.v] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.