Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

IIR filter implementation in Cyclone II

Status
Not open for further replies.

allison_www

Newbie level 4
Joined
Jun 14, 2011
Messages
5
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,352
Hi,
I am trying to implement a lock-in amplifier in FPGA. To do tat, I used ALTPLL to generate a locked clock, clk_lock, then I found a piece of Verilog code online to transform the clk_lock into a 14-bit sine wave, which is my reference signal (not sure if it's ok to do it that way...). Then I used a multiplier to mixer my input signal (14-bit) with the reference signal.

Next I want to implement a filter to keep only the DC part. I checked up online and it seemed to me that an IIR filter was better since it's more energy efficient. I generated the specs (154Khz sampling rate, 5khz passband, 8khz stopband) of the filter in matlab fdatool. It's a 5 order iir filter. the coefficients of the transfer function are:
b=[0.00185 -0.00505 0.00323 0.00323 -0.00505 0.00185]
a=[1 -4.76 9.10 -8.77 4.25 -0.828]

I read some material online and find that what I'm supposed to do is to multiply all coefficients by 2^14 and round them as fixed-points values if I want 14-bit coefficients. The problem is, after multiplication, some coeff are bigger than 2^13(the 1st bit is sign), thus I have to broad the bit width of coefficients to 18-bit. I add 4 bit 0000 to the left of the input signal so it is 18bit too.

Then I should write the difference equation as y[n]=b0*x[n-1]...+a0*y[n-1], where I can use registers to store y[n-1],y[n-2]...x[n-1], x[n-2]...and the multiplication should be 36-bit since both input signal and ref signal are 18-bit width. Then I probably should cut the right most 18bit data off so my result is 18bit width...but that doesn't make sense since I may want 14bit signal...i dont know.

SO, could any1 pls tell me if I am on the right track/what is the right way/where I can find the right way to solve the problem? I looked up a lot of information online but still got confused. I am new to FPGA and all I have done before is based on matlab. Thank you!!
 

Hi Allison.

Lots of thing to explain, will try without too much theory. (There are other ways to implement an oscillator, but check if that works for you - I will NOT comment on your filter requirements, I will assume that it is what you need)

About the filter implementation in the FPGA:
First, do not implement the direct form of the 5th order directly, you should implement it using biquads - i.e. as a cascade connection of one and second order filters. Check **broken link removed** for the Matlab function tf2sos, which will give you the coeff. values you need, and some good advice too.

About the wordlenght: There are different ways to estimate an appropriate wordlenght for your filter, just google about filter scaling. For the coeff. wordlenght, you do not need 18 bits, you can have less bits, check 8 bits. BUT, your data path should be greater, maybe 16bits - again, check scaling!

If I were you, I will start by designing everything with a fixed wordlenght of 24 bits (use generics to easy changes latter) - which will be 8 bits for coeff. + 16 bits of datapath. For truncating the data (i.e. after multiplication or output) you should take care about which bits you need to remove, it is not only the MSB but also some of the LSB too. Keep in mind, that if you have two numbers aa.bb * cc.dd = eeee.ffff (where the values after the . are the fractions) you should keep ee.ff

Usually you need a higher wordlenght inside your filter instead of the ADC/DAC bits is because internally the filter would need more space to store results and avoid overflow and limit noise.
 
The "piece of code" if pasted would be helpful.
The input signal needs to be quantized into the corresponding bits.
Then you can do your baseband processing i.e. filtering etc..
For Filtering:
i) an IIR filter stability is much more difficult to achieve than an FIR. You might also want to take causality when looking at the filter design.
ii) Multiplying will inevitably increases the number of bits. You have decide on the required precision.
iii) You want to implement a convolution sum for which you need a loop and generate all the sums.
 

Thanks a lot for the reply, a lot of things have been cleared up:razz:
I may have a 2nd thought about my selection of filters, but either way I wanna complete this question first. Could you help me with a few points that I dont understand in your answer?
About the filter implementation in the FPGA:
First, do not implement the direct form of the 5th order directly, you should implement it using biquads - i.e. as a cascade connection of one and second order filters. Check **broken link removed** for the Matlab function tf2sos, which will give you the coeff. values you need, and some good advice too.

So you mean that I should implement the IIR filter by multiplying together sections of “transfer functions" (as Π(Xi(z)/Yi(z))) with SOS and G? so in difference equation it should be something like y[n]=Σb0i*w[n-i], w[n]=x[n]+Σa0i*w[n-i]? but what if I have three sections?

About the wordlenght: There are different ways to estimate an appropriate wordlenght for your filter, just google about filter scaling. For the coeff. wordlenght, you do not need 18 bits, you can have less bits, check 8 bits. BUT, your data path should be greater, maybe 16bits - again, check scaling!

I'm checking filter scaling in google, haven't found any tutorial etc for beginners. will keep looking...
but suppose my ADC is 16bit, thus my input signal is 16bit width. Then if my coefficient is 8th. How should I transform the coefficient into 8bit word? for example, -1.034, should I do coeff= {1'b1,round(1.304*2^7)=167} which doesn't make sense since 167 >2^7. or coeff={1'b1, 1'b1, round(0.304*(2^5))=10=01010}, the 8bit word is 1bit for sign, 2bit for integer and 5bit for fractions.

If I were you, I will start by designing everything with a fixed wordlenght of 24 bits (use generics to easy changes latter) - which will be 8 bits for coeff. + 16 bits of datapath. For truncating the data (i.e. after multiplication or output) you should take care about which bits you need to remove, it is not only the MSB but also some of the LSB too. Keep in mind, that if you have two numbers aa.bb * cc.dd = eeee.ffff (where the values after the . are the fractions) you should keep ee.ff

Usually you need a higher wordlenght inside your filter instead of the ADC/DAC bits is because internally the filter would need more space to store results and avoid overflow and limit noise.

The truncation thing helps a lot! But one more question, if my DAC is 12bit, and I have 8bit coeff (2.5) times 16bit input (6.10), the result will be 24bit, and is it (2+6.5+10)? then how should I decide which bits to keep?

sorry if my questions dont make sense or I didnt make them clear enough... is there some sorta of tutorial for beginners about questions like that? I am interested in the theory too:smile:

---------- Post added at 14:34 ---------- Previous post was at 14:27 ----------

Thanks for replying!! kalyanasv.

the piece of code I got online is as below:
module sine_cos(clk, reset, en, sine, cos);
input clk, reset, en;
output [13:0] sine,cos;
reg [13:0] sine_r, cos_r;
assign sine = sine_r + {cos_r[13], cos_r[13], cos_r[13], cos_r[13:3]}; //devide by 8, or sample the period by 8
assign cos = cos_r - {sine[13], sine[13], sine[13], sine[13:3]};
always@(posedge clk or negedge reset)
begin
if (!reset) begin
sine_r <= 0;
cos_r <= 120;
end else begin
if (en) begin
sine_r <= sine;
cos_r <= cos;
end
end
end
endmodule // sine_cos

what do you mean by 'corresponding bits'? the ADC bits?
For filtering, I may use a FIR filter instead, but I wanna finish this and understand the implementation for IIR first =)
I am not following what you said about convolution sum for which i need a loop and generate all sums... it's like what we do in matlab, but how can I do that in fpga? could you be more specific?
 

Hi.

By biquad, transfer function is H(z) = H1(z)*H2(z)*H3(z)*X(z), which means that you implement each section as a second/first order filter, and then the output of the preceding section goes into the input of the other one.

For the scaling, maybe use Matlab and use a fixed wordlenght, other methods (including l1-norm) need more work and will require a more complex explanation.

For the coeff. you are right, you need one extra bit for the sign, 1 bit for integer (all coeff. are less than 2) and 8~12 for fraction (total 10~14 bits) If your coeff is less than 1, you do not need bits for the integer part.

About which bits to keep, if you use 6.10 as datapath, then you should keep the same for truncation. You can simulate all in Matlab by implementing the diference equations in a for loop, just round to n decimal digits after each operation - and put each operation in a different line (i.e. instead of writing

y(n) = a0*x(n) + a1*x(n-1) - b1*y(n-1);

write

y(n) = floor( a0*x(n)*2^k ) / 2^k;
y(n) = y(n) + floor( a1*x(n-1)*2^k ) / 2^k;
...
 
Thanks drz, I really appreciate your help!!
just to make sure I understand everything correctly. here is what I would do:

to implement a biquad filter in fpga, it's like
in section 1: w1[n]=b00*x[n]+b10*x[n-1]...+a00*w1[n]+a10*w1[n];
in section 2: w2[n]=b01*w1[n]...+a01*w2[n]+a11*w2[n-1]...
in section 3: y[n]=b02*w2[n]+b12*w2[n-1]...+a02*y[n]...;
b0i, a0i are the coeffs in section i;

about bits to keep, I should expand one 1bit (17bit in total) as sign or just use the MSB bit as the sign bit?
then, if datapath is 6.10 and coeff is 2.6, the result is 8.16, right? then i should keep the 6bit before decimal point and 10bit following the decimal point... if I understand you correctly.

thanks again for your patience.:smile:
Allison
 

Yeap. (it is a00*w1[n-1]+a10*w[n-2]) - just check your equs. again for the [n-...] values

Wordlength is OK, again sim. in Matlab with this values to check if filter works OK, if not increase wordlength values

drz
 

The corresponding bits is your input clk signal i.e. ADC bits.
What you have below is the done is the convolution sum same as matlab.
As dramoz mentioned just cross-verify with matlab.
how to do in an FPGA. You have answered that already yourself.

The only note is that for lock-in amplifiers you need to pay heed to stability as the stopband has to be sharp and your talking about a small passband. You need a high order filter to maintain stability: after you compute the coefficients using matlab. Check the condition number of your transfer function. IIR filters can easily go out of stability. :"cond()". You want a low condition number.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top