<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Direct Digital Synthesis (DDS)
This example shows how to perform direct digital synthesis.
Step1:  Compile and build.
Step2:  We can wire up the GPIO pins to a logic analyzer to verify that our circuit produces the correct sine waveform.
We can also use Saleae's export data feature to output a csv file. We'll load this data into Python and plot the results.
Step3:  TODO
<ASSISTANT_TASK:>
Python Code:
import math
import numpy as np
def sine(x):
    return np.sin(2 * math.pi * x)
x = np.linspace(0., 1., num=256, endpoint=False)
import magma as m
m.set_mantle_target('ice40')
import mantle
def DefineDDS(n, has_ce=False):
    class _DDS(m.Circuit):
        name = f'DDS{n}'
        IO = ['I', m.In(m.UInt(n)), "O", m.Out(m.UInt(n))] + m.ClockInterface(has_ce=has_ce)
        @classmethod
        def definition(io):
            reg = mantle.Register(n, has_ce=has_ce)
            m.wire(reg(m.uint(reg.O) + io.I, CE=io.CE), io.O)
    return _DDS
def DDS(n, has_ce=False):
    return DefineDDS(n, has_ce)()
from loam.boards.icestick import IceStick
icestick = IceStick()
icestick.Clock.on()
for i in range(8):
    icestick.J1[i].input().on()
    icestick.J3[i].output().on()
main = icestick.main()
dds = DDS(16, True)
wavetable = 128 + 127 * sine(x)
wavetable = [int(x) for x in wavetable]
rom = mantle.Memory(height=256, width=16, rom=list(wavetable), readonly=True)
phase = m.concat(main.J1, m.bits(0,8))
# You can also hardcode a constant as the phase
# phase = m.concat(m.bits(32, 8), m.bits(0,8))
# Use counter COUT hooked up to CE of registers to slow everything down so we can see it on the LEDs
c = mantle.Counter(10)
addr = dds( phase, CE=c.COUT)
O = rom( addr[8:] )
m.wire( c.COUT, rom.RE )
m.wire( O[0:8], main.J3 )
m.EndCircuit()
Explanation: Direct Digital Synthesis (DDS)
This example shows how to perform direct digital synthesis.
End of explanation
m.compile('build/dds', main)
%%bash
cd build
cat sin.pcf
yosys -q -p 'synth_ice40 -top main -blif dds.blif' dds.v
arachne-pnr -q -d 1k -o dds.txt -p dds.pcf dds.blif 
icepack dds.txt dds.bin
iceprog dds.bin
Explanation: Compile and build.
End of explanation
import csv
import magma as m
with open("data/dds-capture.csv") as sine_capture_csv:
    csv_reader = csv.reader(sine_capture_csv)
    next(csv_reader, None)  # skip the headers
    rows = [row for row in csv_reader]
timestamps = [float(row[0]) for row in rows]
values = [m.bitutils.seq2int(tuple(int(x) for x in row[1:])) for row in rows]
Explanation: We can wire up the GPIO pins to a logic analyzer to verify that our circuit produces the correct sine waveform.
We can also use Saleae's export data feature to output a csv file. We'll load this data into Python and plot the results.
End of explanation
%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(timestamps[:100], values[:100], "b.")
Explanation: TODO: Why do we have this little bit of jitter? Logic analyzer is running at 25 MS/s, 3.3+ Volts for 1s
End of explanation
<END_TASK>