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.75Hz
always@(posedge clk_in) cnt <= cnt +1'b1;
assign led= cnt[22]; //12MHz/2^23 ~ 1.5Hz, 接近心跳频率
wire clk_96m;
CLK_96M u5(.CLKI(clk_in), .CLKOP(clk_96m)); //以Lattice的IPCore为例产生高速内部时钟,从12MHz产生96MHz,用以内部的逻辑以及DAC转换
//square wave generated by toggling all data bits from 0-->1--0
//wire cnt_tap = cnt[2]; // we take one bit out of the counter (here bit 7 = the 8th bit)
//assign dac_data = {10{cnt_tap}}; // and we duplicate it 10 times to create the 10-bits DAC value
//assign dac_data = cnt[9:0]; //Sawtooth waveform, frenquency = Fclk/2^10
// Triangle waveform, frequency = Fclk/2^11
//assign dac_data = cnt[10] ? ~cnt[9:0] : cnt[9:0]; // Triangle waveform, frenquency = Fclk/2^11
wire [23:0] next_phase;
wire [7:0] phase;
reg [23:0] accumulator;
assign next_phase = 24'H0DA7 + accumulator;
always @(posedge clk_96m)
accumulator <= #1 next_phase;
assign phase = accumulator[23:16]; // phase is the high 8 bits
wire [9:0] sine_data;
//lookup_tables u_lookup_tables(clk_96m, phase, sine_data);
LUT_sine_table U_lut_sine_table(.Clock(~clk_96m), .ClkEn(1'b1), .Reset(1'b0), .Theta(phase), .Sine(sine_data));
assign dac_data = sine_data[9:0] + 10'h1ff ;
wire [9:0] PWM_in;
//assign PWM_in = 8'd38;
assign PWM_in = dac_data[9:0];
reg [10:0] PWM_DDS_accumulator;
always @(posedge clk_96m) PWM_DDS_accumulator <= PWM_DDS_accumulator[9:0] + PWM_in;
assign pwm_out = PWM_DDS_accumulator[10];
endmodule
/* lookup_tables.v */
module lookup_tables(clk, 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);
sin_table u_sin_table(address,sine_table_out);
sine_table u_sine_table(.Clock(clk), .ClkEn(1'b1), .Reset(1'b0), .Theta(phase), .Sine(sin_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