• 0
hadjovitch

filter implementation on nexys2

Question

hi so , i need to convert an analog signal with the Pmod AD1 and filtering this signal with two RII filters ( low pass and high pass ) and recover the filtering signal with the DAC Pmod .
 
i need the implementation code with vhdl  and how to make synchronisation between conversion and filtering
 
 
note : i use Digilent nexys 2 board 
 
i need your help plz :)

 

Share this post


Link to post
Share on other sites

8 answers to this question

Recommended Posts

  • 0

Hi Hadjovitch,

 

It sounds like you are doing an assignment :)

 

If you want to go off-piste (aka outside of your course material) read chapters 14 through 16 of "The Scientist and Engineer's Guide to

Digital Signal Processing" (free at http://www.dspguide.com/pdfbook.htm). It's really good.

 

If you are not worried about efficiency, the general FIR DSP filter could be implemented something like

if rising_edge(clk) then
    output <= total( [ a suitable range of bits to avoid division] );
    total <= term0 + term1 + term2 +term3 +term4 + term5 + term6 + term7 +term8;
 
    term0  <= sample0 * kernel0;
    term1  <= sample1 * kernel1;
    term2  <= sample2 * kernel2;
    term3  <= sample3 * kernel3;
    term4  <= sample4 * kernel4;
    term5  <= sample5 * kernel5;
    term6  <= sample6 * kernel6;
    term7  <= sample7 * kernel7;
    term8  <= sample8 * kernel8;

    if new_sample_data_enable = 1 then
       sample8 <= sample7;
       sample7 <= sample6;
       sample6 <= sample5;
       sample5 <= sample4;
       sample4 <= sample3;
       sample3 <= sample2;
       sample2 <= sample1;
       sample1 <= sample0;
       sample0 <= new_sample;
    end if;
end if;








If the 'kernel' figures are appropriately chosen (see the referenced book) it will give you filtered signal, with maybe 8 cycles of latency, and could process a new sample every clock cycle.

 

So how do you choose the correct kernel values? Once you have the filter kernel in floating point multiply them by a power of two (say 65536), and check that they all add up to 65536, then change this line to drop the lowest 16 bits.

    output <= total(total'high downto 16);
 
If you design the filter as a low pass filter, then you can check in simulation (or on paper) that if you set all the 'sample' values to the same value, that output will end up being calculated as the same value (i.e. a DC signal will pass through unchanged).
 
Because the filter doesn't alter the phase of the different frequencies, you can get a high pass filter for almost free - just subtract the output from the input, and what is left over is the high frequency part:
 
     ...
    output_lowpass <= total(total'high downto 16);
    output_highpass <=  sample4 - total(total'high downto 16);
    ....

Anyhow, that book is the go-to place for it, and Xilinx has plenty of APPnotes on more efficient implementations.

Share this post


Link to post
Share on other sites
  • 0

@hadjovitch, you will need to find and SPI/Micro wire interface to the PMOD ADC1.  Once you have the samples in the FPGA then you can implemented a digital filter (FIR, IIR).  The first step is to find a design example or create the serial interface to the ADC.

Share this post


Link to post
Share on other sites
  • 0

hi @cfelton , first thanks for your reply , my problem is not in the conversion 

 

the conversion with the Pmod is done , my problem now is with the filters ( low pass and high pass ) , my analog signal is not filtered :/ so i'am searching about how 

 

to make synchronisation between conversion and the filter ...

 

                           i hope you understand me :)

Share this post


Link to post
Share on other sites
  • 0

Hi hadjovitch,

 

With the PmodAD1, your Nexys 2 board will be receiving all digital signals from the Pmod and one does not generally filter a digital signal. You probably could do it with DSP, but that's well beyond my expertise. 

 

What I think would be the easiest to do is set up a small external circuit using discrete components that filters your analog signal before it is ever received by the PmodAD1. Then you wouldn't even need to worry about any additional lines of code.

 

Let me know if you have any more questions.

 

Thanks,

JColvin

Share this post


Link to post
Share on other sites
  • 0

hi @hamster realy thanks for your answer , but as u see i need IIR filter and not FIR :)

 

i need to enter an analog signal to my nexys2 and filtered it and show the output of filtered signal on scope 

 

this is what i need exactlly .... my project name is ( implementation of Pan and Tompkins filters on nexy2 ) 

Share this post


Link to post
Share on other sites
  • 0

FIR filters are a little bit different. You have to maintain a history of the outputs, and use them in the math rather than a history of the samples.

 

Assuming you are using PmodAD1 and PmodDAC2. here is how I would use them.

 

To get the two DACs talking 'in sync' you will need to find a clock rate that works for both (which looks to be about 16 MHz) and then just clock out the frames. I would be looking at something like this on the ADC:

   signal state_sr : std_logic_vector(16 downto 0) := (0=>'1', others => '0');
   signal data_sr : std_logic_vector(15 downto 0) := (others => '0');
 
....
   if rising_edge(clk) then
      -- Move the shift register around.
      state_sr <= state_sr(state_sr'high-1 downto 0) & state_sr(state_sr'high);
      -- Add the next bit to the data from the ADC
      data_sr <= data_sr(data_sr'high-1 downto 0) & adc_data;
 
      -- this will pulse the CS for one cycle every 17 cycles.
      adc_cs <= state_sr(0);
 
      -- you will have to tweak the number here to get the data aligned correctly 
      -- Either read the datasheets or use trail and error. 
      if state_sr(15) = '1' then
           data_out <= data_sr;
           data_out_enable <= '1';
      else
           data_out_enable <= '0';
      end if;
   end if;

And you can use something much the same on the DAC:

   signal state_sr : std_logic_vector(16 downto 0) := (0=>'1', others => '0');
   signal data_sr : std_logic_vector(15 downto 0) := (others => '0');
 
....
   if rising_edge(clk) then
      -- Move the shift register around.
      state_sr <= state_sr(state_sr'high-1 downto 0) & state_sr(state_sr'high);
 
      -- pulse the SYNC signal one cycle every 17 cycles
      -- and send the data bits to the ADC
      dac_sync   <= state_sr(0);
      dac_data <= data_sr(data_sr'high);

      -- you will have to tweak the number here to get the data aligned correctly 
      -- Either read the datasheets and simulation or use trail and error. 
      if state_sr(15) = '1' then
           -- move the output value into the shift register.
           data_sr <= data_in;
      else
           data_sr <= data_sr(data_sr_high-1 downto 0) & '1'; 
      end if;
   end if;

Share this post


Link to post
Share on other sites
  • 0

@hadjovitch, others have a better nose for **homework** assignments than I do.  If this is truly a homework assignment you need to be asking more specific questions and outlining, where you are stuck and what you have tried.  No one should be providing example solutions if we believe this is a homework assignment.  Googling "FPGA digital filtering" and/or "FPGA IIR filtering" will provide many starting points.

 

Where are you running into trouble?  Understanding what/how to do digital filtering or what/how to implement a digital filter in an FPGA?

 

Typical difficulties with digital filtering in an FPGA:

  • number representation
  • resource utilization (how many multipliers do you want inferred)

Regards,
Chris

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now