This is just a post to show off with my continuous wave sinus generator.
It uses the recursive chebyshev formulation
to compute the values of a Sin waveform. To compute the value it uses only
one multiplication with a
constant(if the sin waveform frequency is constant) and a substraction, so
it has relative low resource usage. Normaly generating a continuous sin
waveform in Hardware/VHDL is done with Direct Digital Synthesis using a
phase accumulater and stored values with interpolation between values and
stuff like that, but i think my design has in some cases advantages over
this approach.
I wanted to do it a long time ago, but with simulation and verifying the
sinus spectrally
it would have been quit a lot of work with VHDL, thanks to myhdl, makeing
this like this is kind of fun.
(i used pylab for the printing with the matplotlib)
Now the Code in
(license: have fun with the code to do whatever you like, or if you can
ask Pafnuty Chebyshev for permission to use):
from myhdl import *
from math import cos,pi
import pylab
def unit_singen(i_clk,i_reset,i_enable,o_outvalue,frequenzSIN,clkfrequnez):
INTERNALWIDTH=len(o_outvalue)-2 #
#OUT_MAX_POSSIBLE=o_outvalue.max
#OUT_MIN_POSSIBLE=o_outvalue.min
KONSTANT_FACTOR=int(cos(2*pi*frequenzSIN*1.0/clkfrequnez)*2**(INTERNALWIDTH))
Reg_T0=Signal(intbv((2**(INTERNALWIDTH))-1,min=o_outvalue.min,max=o_outvalue.max))
Reg_T1=Signal(intbv(KONSTANT_FACTOR,min=o_outvalue.min,max=o_outvalue.max))
@always(i_clk.posedge,i_reset.negedge)
def logicCC():
if i_reset== 0 :
Reg_T0.next=(2**(INTERNALWIDTH))-1
Reg_T1.next=KONSTANT_FACTOR
else:
if i_enable==1:
Reg_T0.next=Reg_T1
Reg_T1.next=((KONSTANT_FACTOR * Reg_T1)>>(INTERNALWIDTH-1)) - Reg_T0
@always_comb
def comb_logic():
#if Reg_T1>=OUT_MAX_POSSIBLE:
#o_outvalue.next=OUT_MAX_POSSIBLE-1
#elif Reg_T1<=OUT_MIN_POSSIBLE:
#o_outvalue.next=OUT_MIN_POSSIBLE
#else:
o_outvalue.next=Reg_T1
return instances()
def test_singen(SimulateNPoints=200):
Sinusvalue=Signal(intbv(0,min=-2**30,max=2**30))
clk=Signal(bool(0))
enable=Signal(bool(0))
reset=Signal(bool(0))
frequenzSIN=1e6 # make a 10 mhz Sinus
clk_frequnez=100e6 # 100 mhz
clk_period=1.0/clk_frequnez
singen_inst =
unit_singen(clk,reset,enable,Sinusvalue,frequenzSIN,clk_frequnez)
@always(delay(int(clk_period*0.5*1e9))) ## delay in nano sekonds
def clkgen():
clk.next = not clk
sinlist=[]
@instance
def stimulus():
while 1:
reset.next=0
enable.next=0
yield clk.posedge
reset.next=1
yield clk.posedge
enable.next=1
for i in range(SimulateNPoints):
yield clk.posedge
#yield delay(10)
sinlist.append(int(Sinusvalue))
print Sinusvalue
pylab.figure(1)
pylab.subplot(211)
pylab.plot(pylab.arange(0.0,clk_period*(len(sinlist)),clk_period),sinlist)
pylab.subplot(212)
pylab.semilogy(pylab.arange(-clk_frequnez/2.0,clk_frequnez/2.0,clk_frequnez/(len(sinlist))),abs(pylab.fftshift(pylab.fft(pylab.array(sinlist)))))
pylab.show()
raise StopSimulation
toVHDL(unit_singen,clk,reset,enable,Sinusvalue,frequenzSIN,clk_frequnez)
return instances()
#
if __name__ == '__main__':
sim = Simulation(test_singen())
sim.run()
#singen_inst = unit_singen(Outvalue,clk,enable,reset,frequenz=20)
#toVHDL(unit_singen,clk,reset,enable,Outvalue,frequenz)
#simulate(2000)
|