praabye

Papilio Pro software ADC

Recommended Posts

Hi!

I'm new to this, but already hooked on using the Papilio Pro for development. This has led to a list of interesting projects on a list - giving rise to a lot of questions.

 

I have a LogicStart Wing, and could be using the ADC on that. But once a hacker... So I have looked for a software all-digital ADC-solution. The Xilinx site has one somewhere for the Spartan-3. There isn't much mention of it, and the data are for running it explicitly on the Spartan-3, of course.

 

Has anyone out there tried porting the software ADC to Spartan-6/Papilio Pro? Had any succes? Wanting to share the VHDL code?

 

The hardware ADC solution seems to work, but, really: that's no fun!!!

 

My concrete project is a reciever for DCF77 (european time signal on 77,5 kHz). The AM modulation from this is usually decoded with little prefabricated radios. But I would like to do use phase modulation, it also contains. That should enable a faster time to lock.

 

I do have the hardware for giving me the DCF77 signal in a 3.3 V logic format, and could do it that way around. But I'd really like to tinker with the DSP48 slices and do some filtering, thus the need for ADC functionality. I will of course need some AGC in front of the Papilio Pro, as the ADC probably wouldn't have a higher resolution than maybe 14-16 bits.

 

Yours, etc.

Peter

 

Share this post


Link to post
Share on other sites

 I found some code in VHDL by searching "free dac ip". Not sure if it works or if it will work for your application, but here it is.

 

 

----------------------------------------------------------------------------
----------------------------------------------------------------------------
--  The Free IP Project
--  VHDL Free-DAC Core
--  © 2000, The Free IP Project and David Kessner
--
--
--  FREE IP GENERAL PUBLIC LICENSE
--  TERMS AND CONDITIONS FOR USE, COPYING, DISTRIBUTION, AND MODIFICATION
--
--  1.  You may copy and distribute verbatim copies of this core, as long
--      as this file, and the other associated files, remain intact and
--      unmodified.  Modifications are outlined below.  
--  2.  You may use this core in any way, be it academic, commercial, or
--      military.  Modified or not.  
--  3.  Distribution of this core must be free of charge.  Charging is
--      allowed only for value added services.  Value added services
--      would include copying fees, modifications, customizations, and
--      inclusion in other products.
--  4.  If a modified source code is distributed, the original unmodified
--      source code must also be included (or a link to the Free IP web
--      site).  In the modified source code there must be clear
--      identification of the modified version.
--  5.  Visit the Free IP web site for additional information.
--      http://www.free-ip.com
--
----------------------------------------------------------------------------
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;


package free_dac_lib is
  component dac_ds
    generic (n_bits :integer);
    port (reset :in std_logic;
          clk :in std_logic;
          din :in std_logic_vector (n_bits-1 downto 0);
          dout :out std_logic
         );
  end component;

  component dac_pwm
    generic (n_bits :integer);
    port (reset :in std_logic;
          clk :in std_logic;
          din :in std_logic_vector (n_bits-1 downto 0);
          dout :out std_logic
         );
  end component;

  component dac_pwm2
    generic (n_bits :integer);
    port (reset :in std_logic;
          clk :in std_logic;
          period :in std_logic_vector (n_bits-1 downto 0);
          width :in std_logic_vector (n_bits-1 downto 0);
          dout :out std_logic
         );
  end component;
    
end package;


-----------------------------------------------------------------------------
-- First Order Delta Sigma DAC
-----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library work;
use work.free_dac_lib.all;


entity dac_ds is
    generic (n_bits :integer);
    port (reset :in std_logic;
          clk :in std_logic;
          din :in std_logic_vector (n_bits-1 downto 0); -- Signed integer
          dout :out std_logic
         );
end dac_ds;


architecture arch_dac_ds of dac_ds is
  signal error :std_logic_vector (n_bits+1 downto 0); -- Error accumulator is 2 bits larger
  constant zeros :std_logic_vector (n_bits-1 downto 0) := (others=>'0');

begin
  process (reset, clk, din)
    variable val :std_logic_vector (n_bits+1 downto 0);
  begin
    if reset='1' then
      error <= (others=>'0');
      dout <= '0';
    elsif clk'event and clk='1' then
      -- val := din + error;  din is sign extended to nbits+2
      val := (din(din'high) & din(din'high) & din) + error;

      if val(val'high) = '0' then
        dout <= '1';
        error <= val + ("11" & zeros);
      else
        dout <= '0';
        error <= val + ("01" & zeros);
      end if;
    end if;
  end process;
end arch_dac_ds;


-----------------------------------------------------------------------------
-- DAC via Pulse Width Modulation
-----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library work;
use work.free_dac_lib.all;


entity dac_pwm is
    generic (n_bits :integer);
    port (reset :in std_logic;
          clk :in std_logic;
          din :in std_logic_vector (n_bits-1 downto 0); -- unsigned integer
          dout :out std_logic
         );
end dac_pwm;


architecture arch_dac_pwm of dac_pwm is
  signal period_counter :std_logic_vector (din'range);
  signal width_counter  :std_logic_vector (din'range);
  signal last :std_logic;
  signal last_d :std_logic;
  signal width_flag :std_logic;
  constant zeros :std_logic_vector (n_bits-2 downto 0) := (others=>'0');

begin

  -- The period counter
  process (reset, clk)
  begin
    if reset='1' then
      period_counter <= (others=>'1');
    elsif clk'event and clk='1' then
      period_counter <= period_counter - 1;
    end if;
  end process;


  -- The last cycle flag.  Active on the last cycle of the period
  process (reset, clk)
  begin
    if reset='1' then
      last <= '0';
      last_d <= '0';
    elsif clk'event and clk='1' then
      last_d <= last;
      
      if period_counter = (zeros & "1") then
        last <= '1';
      else
        last <= '0';
      end if;
    end if;
  end process;
      

  -- The width coutner
  process (reset, clk)
  begin
    if reset='1' then
      width_counter <= (others=>'0');
      width_flag <= '0';
    elsif clk'event and clk='1' then
      if width_counter = (zeros & "0") then
        width_flag <= '1';
      else
        width_flag <= '0';
      end if;
      
      if last='1' then
        width_counter <= din;
      else
        width_counter <= width_counter-1;
      end if;
    end if;
  end process;

  -- The output
  process (reset, clk)
  begin
    if reset='1' then
      dout <= '0';
    elsif clk'event and clk='1' then
      if last='1' then
        dout <= '1';
      elsif width_flag='1' then
        dout <= '0';
      end if;
    end if;
  end process;


end arch_dac_pwm;


-----------------------------------------------------------------------------
-- DAC via Pulse Width Modulation - with variable pulse frequency
-----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library work;
use work.free_dac_lib.all;


entity dac_pwm2 is
    generic (n_bits :integer);
    port (reset :in std_logic;
          clk :in std_logic;
          period :in std_logic_vector (n_bits-1 downto 0); -- unsigned
          width :in std_logic_vector (n_bits-1 downto 0); -- unsigned
          dout :out std_logic
         );
end dac_pwm2;


architecture arch_dac_pwm2 of dac_pwm2 is
  signal period_counter :std_logic_vector (period'range);
  signal width_counter  :std_logic_vector (period'range);
  signal last :std_logic;
  signal last_d :std_logic;
  signal width_flag :std_logic;
  constant zeros :std_logic_vector (n_bits-2 downto 0) := (others=>'0');

begin

  -- The period counter
  process (reset, clk)
  begin
    if reset='1' then
      period_counter <= (others=>'1');
    elsif clk'event and clk='1' then
      if last='1' then
        period_counter <= period;
      else
        period_counter <= period_counter - 1;
      end if;
    end if;
  end process;


  -- The last cycle flag.  Active on the last cycle of the period
  process (reset, clk)
  begin
    if reset='1' then
      last <= '0';
      last_d <= '0';
    elsif clk'event and clk='1' then
      last_d <= last;
      
      if period_counter = (zeros & "1") then
        last <= '1';
      else
        last <= '0';
      end if;
    end if;
  end process;
      

  -- The width coutner
  process (reset, clk)
  begin
    if reset='1' then
      width_counter <= (others=>'0');
      width_flag <= '0';
    elsif clk'event and clk='1' then
      if width_counter = (zeros & "0") then
        width_flag <= '1';
      else
        width_flag <= '0';
      end if;
      
      if last='1' then
        width_counter <= width;
      else
        width_counter <= width_counter-1;
      end if;
    end if;
  end process;

  -- The output
  process (reset, clk)
  begin
    if reset='1' then
      dout <= '0';
    elsif clk'event and clk='1' then
      if last='1' then
        dout <= '1';
      elsif width_flag='1' then
        dout <= '0';
      end if;
    end if;
  end process;


end arch_dac_pwm2;


-----------------------------------------------------------------------------
--
-----------------------------------------------------------------------------
 

Share this post


Link to post
Share on other sites

You can also hack a first order delta sigma ADC using the pin input as the sampling element, using two pins and a few resistors and a capacitor, but I would expect this to be particularly accurate and also will not give you reasonable accuracy at the sample rate you want.

 

Also if you want use a hardware AGC chip why not just use a hardware ADC as well, you wont get MSPS ADC working with a pure "software" approach and definitely not better than a product designed for it will.

Share this post


Link to post
Share on other sites

Thank you for your prompt answers! I've looked into the code quoted, and see that there is something, I haven't really thought enough about before asking :)

 

There's the question of the precision of the sample and hold, and of the actual sampling frequency. But then: forums like this is for learning. I think, that I'll settle for the hardware ADC. But the software ADC makes a few other projects realizable!

 

Once again, thank you all!

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