差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
pwm_awg [2021/02/25 19:53] gongyusu [FPGA代码] |
pwm_awg [2021/03/08 17:57] (当前版本) gongyusu |
||
---|---|---|---|
行 1: | 行 1: | ||
## DDS+PWM产生任意波形 | ## DDS+PWM产生任意波形 | ||
### 工作原理 | ### 工作原理 | ||
+ | * DDS部分 | ||
+ | * PWM部分 | ||
+ | * 模拟链路部分 | ||
- | ### 模拟电路 | + | ### 模拟电路功能介绍 |
{{ :fpga_pwm_awg.png |}} <WRAP centeralign> 任意波形发生器模拟电路部分原理图 </WRAP> | {{ :fpga_pwm_awg.png |}} <WRAP centeralign> 任意波形发生器模拟电路部分原理图 </WRAP> | ||
通过调节PWM的占空比(0.5V/3.3V ~ 3V/3.3V)得到等效幅度为0.5V - 3V之间的模拟信号,幅度变化的范围为2.5V,要得到幅度为5Vpp的模拟信号,则放大器的增益设定为G = 2: | 通过调节PWM的占空比(0.5V/3.3V ~ 3V/3.3V)得到等效幅度为0.5V - 3V之间的模拟信号,幅度变化的范围为2.5V,要得到幅度为5Vpp的模拟信号,则放大器的增益设定为G = 2: | ||
行 20: | 行 23: | ||
如果通过10个点 | 如果通过10个点 | ||
- | {{ :undefined:fpgascope_simulation.jpg |}} <WRAP centeralign> 任意波形发生器模拟电路部分的仿真 </WRAP> | + | {{ ::pwm_awg_analog_spred.png |}} <WRAP centeralign> 任意波形发生器模拟电路部分的仿真 - 频率响应(100Hz- 10MHz) </WRAP> |
+ | {{ :pwm_awg_analog_wave.png |}} <WRAP centeralign> 任意波形发生器模拟电路部分的仿真 - 波形(100KHz正弦波) </WRAP> | ||
### FPGA代码 | ### FPGA代码 | ||
+ | |||
#### DDS得到任意波形 | #### DDS得到任意波形 | ||
+ | 相位累加器代码: | ||
+ | <code verilog> | ||
+ | wire [23:0] next_phase; | ||
+ | wire [7:0] phase; | ||
+ | reg [23:0] accumulator; | ||
+ | |||
+ | assign next_phase = 24'H002222 + accumulator; // set frequency = 24'H002222 / 2^24 * clock, if PLL not used, clock = 12MHz, output frequency = 6.25KHz | ||
+ | |||
+ | always @(posedge clk_hs) accumulator <= #1 next_phase; | ||
+ | |||
+ | assign phase = accumulator[23:16]; // phase is the high 8 bits as address of the look up table | ||
+ | |||
+ | wire [9:0] sine_data; // sine table is 8 bit wide, 10bit resolution. | ||
+ | |||
+ | lookup_tables u_lookup_tables(phase, sine_data); | ||
+ | |||
+ | </code> | ||
+ | |||
+ | 查找表代码: | ||
+ | <code verilog> | ||
+ | module lookup_tables(phase, sin_out); | ||
+ | input [7:0] phase; //sine table is 8bits wide, 10 bits resolution | ||
+ | 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 = {1'b0, sine_onecycle_amp[9:1]} + 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 or phase) | ||
+ | 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 | ||
+ | |||
+ | </code> | ||
+ | |||
#### 调用DDS结果通过PWM生成需要的波形 | #### 调用DDS结果通过PWM生成需要的波形 | ||
+ | |||
<code verilog> | <code verilog> | ||
+ | //Generate AWG using 10bit resolution PWM + external RC LPF as DAC, up to 100KHz | ||
+ | wire [9:0] PWM_WAV_in; | ||
+ | assign PWM_WAV_in = sine_data[9:0]; | ||
+ | |||
+ | reg [10:0] PWM_WAV_accumulator; | ||
+ | always @(posedge clk_hs) PWM_WAV_accumulator <= PWM_WAV_accumulator[9:0] + PWM_WAV_in; | ||
+ | assign pwm_awg = PWM_WAV_accumulator[10]; | ||
</code> | </code> | ||