[myhdl-list] A continuous sinus waveform generator (alla Pafnuty Chebyshev)
Brought to you by:
jandecaluwe
From: Norbo <Nor...@gm...> - 2011-12-13 16:59:35
|
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) |