Papilio Pro software ADC


praabye

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

 

Link to comment
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;


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

Link to comment
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.

Link to comment
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!

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.