module dds_main(clk_in,led,dac_data,pwm_out);
input clk_in;                 // 小脚丫FPGA的外部时钟频率位12MHz
                              // 内部可以通过PLL产生12MHz整数倍的高速时钟
                              // 比如96MHz、108MHz、120MHz...216MHz
output led;                   // 用以指示状态或帮助调试的LED
                              // 小脚丫模块上有8个单色LED和2个三色LED,可选择其一
output [9:0] dac_data;        // 10位数据输出送给外部的R-2R节点
output pwm_out;               // 用以产生PWM波形,进而可以产生直流或任意波形,取决于外接的低通滤波器的参数
 
reg [23:0] cnt;               // 自由运行的计数器,共计24位,最低频率为cnt[23]的12MHz/2^24= 0.7Hz
always@(posedge clk_in)  cnt <= cnt + 1'b1;
assign led= cnt[22];          //12MHz/2^23 ~ 1.5Hz, 接近心跳频率
 
 
//通过同时改变所有的数据位从0-->1--0来产生方波
//wire cnt_tap = cnt[2];      // 从计数器中取出其中的一位(这的bit7 = 第8位)
//assign dac_data = {10{cnt_tap}};   // 复制10次,给每一位赋同样的值,产生一个10-bits DAC值 
 
//assign dac_data = cnt[9:0];  //锯齿波, 频率 = Fclk/2^10
//assign dac_data = cnt[10] ? ~cnt[9:0] : cnt[9:0];  // 三角波形,频率 = Fclk/2^11
 
reg [23:0] 	phase_acc;
always @(posedge clk_in) phase_acc <= phase_acc + 24'd27962;  //主时钟为12MHz,产生20KHz的正弦波信号
lookup_tables u_lookup_tables(.phase(phase_acc[23:16]), .sine_data(dac_data));
 
wire [9:0] PWM_in;
//assign PWM_in = 8'd38;           // 产生直流电压
assign PWM_in = dac_data[9:0];     // 变化的数据产生变化的PWM占空比,从而产生变化的输出波形
 
reg [10:0] PWM_DDS_accumulator;
 
always @(posedge clk_in) PWM_DDS_accumulator <= PWM_DDS_accumulator[9:0] + PWM_in;
 
assign pwm_out = PWM_DDS_accumulator[10];
 
// 可以通过内部PLL产生更高频率的时钟信号,比如120MHz,如下面的例子,只需要将上述代码中的clk_in都改为PLL产生的时钟,比如clk_120m就可以了
//wire clk_120m;                               // 内部高倍时钟的名字
//CLK_PLL u5(.CLKI(clk_in), .CLKOP(clk_120m)); // 以Lattice的IPCore为例产生高速内部时钟
                                               // 从12MHz产生120MHz,用以内部的逻辑以及DAC转换
 
 
endmodule
/* lookup_tables.v */
 
module lookup_tables(phase, sin_out);
input  	[7:0] 	phase;
output 	[9:0] 	sin_out;
 
wire     [9:0]   sin_out;
 
reg   	[5:0] 	address;
wire   	[1:0] 	sel;
wire   	[8:0] 	sine_table_out;
 
reg     [9:0]   sine_onecycle_amp;
 
//assign sin_out = {4'b0, sine_onecycle_amp[9:4]} + 9'hff;  // 可以调节输出信号的幅度
assign sin_out = sine_onecycle_amp[9:0];
 
	assign sel = phase[7:6];
 
   	sin_table u_sin_table(address,sine_table_out);
 
always @(sel or sine_table_out)
begin
	case(sel)
	2'b00: 	begin
			sine_onecycle_amp = 9'h1ff + sine_table_out[8:0];
			address = phase[5:0];
	     	end
  	2'b01: 	begin
			sine_onecycle_amp = 9'h1ff + sine_table_out[8:0];
			address = ~phase[5:0];
	     	end
  	2'b10: 	begin
			sine_onecycle_amp = 9'h1ff - sine_table_out[8:0];
			address = phase[5:0];
     		end
  	2'b11: 	begin
			sine_onecycle_amp = 9'h1ff - sine_table_out[8:0];
			address = ~ phase[5:0];
     		end
	endcase
end
 
endmodule
 
module sin_table(address,sin);
output [8:0] sin;
input  [5:0] address;
 
reg    [8:0] sin;
 
always @(address)
	begin
                  case(address)	
                      6'h0: sin=9'h0;
                      6'h1: sin=9'hC;
                      6'h2: sin=9'h19;
                      6'h3: sin=9'h25;
                      6'h4: sin=9'h32;
                      6'h5: sin=9'h3E;
                      6'h6: sin=9'h4B;
                      6'h7: sin=9'h57;
                      6'h8: sin=9'h63;
                      6'h9: sin=9'h70;
                      6'ha: sin=9'h7C;
                      6'hb: sin=9'h88;
                      6'hc: sin=9'h94;
                      6'hd: sin=9'hA0;
                      6'he: sin=9'hAC;
                      6'hf: sin=9'hB8;
                      6'h10: sin=9'hC3;
                      6'h11: sin=9'hCF;
                      6'h12: sin=9'hDA;
                      6'h13: sin=9'hE6;
                      6'h14: sin=9'hF1;
                      6'h15: sin=9'hFC;
                      6'h16: sin=9'h107;
                      6'h17: sin=9'h111;
                      6'h18: sin=9'h11C;
                      6'h19: sin=9'h126;
                      6'h1a: sin=9'h130;
                      6'h1b: sin=9'h13A;
                      6'h1c: sin=9'h144;
                      6'h1d: sin=9'h14E;
                      6'h1e: sin=9'h157;
                      6'h1f: sin=9'h161;
                      6'h20: sin=9'h16A;
                      6'h21: sin=9'h172;
                      6'h22: sin=9'h17B;
                      6'h23: sin=9'h183;
                      6'h24: sin=9'h18B;
                      6'h25: sin=9'h193;
                      6'h26: sin=9'h19B;
                      6'h27: sin=9'h1A2;
                      6'h28: sin=9'h1A9;
                      6'h29: sin=9'h1B0;
                      6'h2a: sin=9'h1B7;
                      6'h2b: sin=9'h1BD;
                      6'h2c: sin=9'h1C3;
                      6'h2d: sin=9'h1C9;
                      6'h2e: sin=9'h1CE;
                      6'h2f: sin=9'h1D4;
                      6'h30: sin=9'h1D9;
                      6'h31: sin=9'h1DD;
                      6'h32: sin=9'h1E2;
                      6'h33: sin=9'h1E6;
                      6'h34: sin=9'h1E9;
                      6'h35: sin=9'h1ED;
                      6'h36: sin=9'h1F0;
                      6'h37: sin=9'h1F3;
                      6'h38: sin=9'h1F6;
                      6'h39: sin=9'h1F8;
                      6'h3a: sin=9'h1FA;
                      6'h3b: sin=9'h1FC;
                      6'h3c: sin=9'h1FD;
                      6'h3d: sin=9'h1FE;
                      6'h3e: sin=9'h1FF;
                      6'h3f: sin=9'h1FF;
                   endcase
              end
endmodule