From Python to silicon
 

Sine Wave Generator using Sigma Delta DAC

Description

This is a sinewave generator using a SigmaDelta DAC, i.e. it uses only one ouput bit and does not need external hardware beside the low pass filter. The Delta-Sigma DAC core was created by George Pantazopoulos. For speed reasons we use a modified version. The sine calculation is a modified version of the MyHDL Cookbook Example.

Code

#!/usr/bin/env python
 
"""                                                                            
Sinewave generator using George Pantazopoulos' Sigma Delta DAC.
"""
 
from myhdl import *
from math import log, ceil
 
from dac_dsx1000_hd import dac_dsx1000
from cordic import SinCos
 
# ----------------------------------------------------------------------------
 
def top(clk, pdm_o, CLK_HZ):
    """
    Top-level module.
    Sine wave generator
    """
    __author__    = "Thomas Traber (orgin: George Pantazopoulos http://www.gammaburst.net)"
 
    OUTPUT_FREQ_HZ = 10000.0
    PHASE_RESOLUTION = 16 
    PHASE_INC = int( OUTPUT_FREQ_HZ / CLK_HZ * 2**PHASE_RESOLUTION)
 
    print "CLK_HZ = ", CLK_HZ
    print "OUTPUT_FREQ_HZ = ", OUTPUT_FREQ_HZ
 
    # Reset signal
    rst = Signal(bool(0))
 
    # PCM Audio signal. 
    # Note that we control the (theoretical) resolution of the converter
    # by setting the bit width of this signal.
    DAC_RESOLUTION = 16
    pcmi = Sigint(min=-2**DAC_RESOLUTION/2,max=2**DAC_RESOLUTION/2-1)
    pcmq = Sigint(min=-2**DAC_RESOLUTION/2,max=2**DAC_RESOLUTION/2-1)
    pcm_data = Sigint(N=DAC_RESOLUTION)
 
    ampl = Sig(3,min=-2**15,max=2**15-1)
    done = Sigbool(0)
    samplingclk = Sigbool(0)
    start = Sigbool(0)
 
    # Dummy reset driver
    @always_comb
    def rstDrv():
                rst.next = False
 
    phase_accu = Sigint(min=-2**(PHASE_RESOLUTION-1),max=2**(PHASE_RESOLUTION-1)-1)
    sinegen = SinCos(pcmi,pcmq,done,ampl,phase_accu,clk,clk,rst)
 
    @always(done.posedge)
    def sampler():
        if done:
            pcm_data.next = pcmi + 2**(DAC_RESOLUTION-1)            
 
    @always(clk.posedge)
    def PhaseAccumulator():
        if phase_accu >= phase_accu.max - PHASE_INC:
            phase_accu.next = phase_accu.min
        else:            
            phase_accu.next = phase_accu + PHASE_INC
 
    # Instantiation of our Delta-Sigma DAC
    DAC = dac_dsx1000(clk_i=clk, rst_i=rst, pcm_i=pcm_data, pdm_o=pdm_o)
 
    return instances()
 
# ----------------------------------------------------------------------------
 
def Datasaver(clk,pdm):
    global outfile
    outfile = file("sinewave.dat","w")
 
    @always(clk.posedge)
    def save_data():
        outfile.write("%s\n"%(int(pdm)))
 
    return instances()
 
# ----------------------------------------------------------------------------
 
if __name__=="__main__":
 
 
    # Set this to your FPGA's clock frequency
    CLK_HZ = 81000000
 
    if __name__=="__main__":
        import sys
 
        # Signals connected to the FPGA/CPLD
        clk   = Signal(bool(0))
        pdm_o = Signal(bool(0))
 
        if sys.argv[1]=="v":
            # MyHDL to Verilog conversion
            toVerilog.name = "dsx1000"
            toVerilog(top, clk, pdm_o, CLK_HZ)
        else:
            from testenv import *
            clkgen = Clkgen(clk,2)
            datasaver = Datasaver(clk,pdm_o)
            simulate(2**18,top(clk,pdm_o,CLK_HZ),clkgen,datasaver)

Results

Simulation

Datasaver in the code above saves the simulation data in a file which is examined afterwords using matplotlib.

The low frequency spectrum looks pretty good:

At higher frequencies the Sigma Delta Noise can be seen. This is filtered out by the analog low pass filter in hardware.

The noise step at very high frequencies is supposed to be caused by the non constant sampling rate of the sinewave. The function sampler in the code above samples the sine wave, whenever the cordic calculator signals done.

Measurements

The above code was compiled using quartus and programmed into a cycloneII. The system clock was 81MHz but the internal PLL was used to double the clock.

The level of the harmonics is much worse than in simulation, only -27 dB below the fundamental.

projects/sinewave_generator.txt · Last modified: 2008/06/29 10:04 by thomastraber
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki