差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
pwm_verilog [2022/02/22 13:40]
gongyusu [2 用于产生PWM的几种形式]
pwm_verilog [2022/05/07 13:23] (当前版本)
gongyu [5. 双PWM产生更高频率的信号]
行 2: 行 2:
  
 ### 1 PWM的工作原理 ### 1 PWM的工作原理
-可以阅读[[PWM|如何玩转PWM]]以及以下的公众号文章:+可以阅读[[PWM|关于PWM]]以及以下的公众号文章:
   - [[https://​mp.weixin.qq.com/​s/​K5vfUTsczIkjUpAO3EsWjQ|漫谈“独臂神通”PWM(1):用1根管脚、1个电阻和1个电容实现DAC]]   - [[https://​mp.weixin.qq.com/​s/​K5vfUTsczIkjUpAO3EsWjQ|漫谈“独臂神通”PWM(1):用1根管脚、1个电阻和1个电容实现DAC]]
   - [[https://​mp.weixin.qq.com/​s/​aiS0zHgxrH72Q1a8IVqi6w|漫谈“独臂神通”PWM(2):DAC的低通滤波器设计]]   - [[https://​mp.weixin.qq.com/​s/​aiS0zHgxrH72Q1a8IVqi6w|漫谈“独臂神通”PWM(2):DAC的低通滤波器设计]]
行 61: 行 61:
 ##### 1阶的sigma-delta调制 ##### 1阶的sigma-delta调制
 一个简单的一阶sigma-delta调制器代表了一个PWM,​如果你使用滤波器的话它有着更好的频率响应。创建一个一阶sigma-delta调制器的最简单的方法就是使用一个硬件累加器,每次累加器溢出,输出为“1”, 否则输出'​0'​,用FPGA非常容易实现。 一个简单的一阶sigma-delta调制器代表了一个PWM,​如果你使用滤波器的话它有着更好的频率响应。创建一个一阶sigma-delta调制器的最简单的方法就是使用一个硬件累加器,每次累加器溢出,输出为“1”, 否则输出'​0'​,用FPGA非常容易实现。
 +相对于通常固定频率/​改变占空比的PWM方式,Sigma-Delta是在给定最高时钟的条件下,在保证占空比的前提下尽可能采用更高的脉冲频率,在用作PWM-DAC的情况下,相当于大大提高了DAC的转换频率,从而减少了对合成频率的频段内的混叠。
  
 <code verilog> <code verilog>
行 77: 行 78:
 输入的值越高,计数器溢出的越快("​PWM_accumulator[8]"​),​ 输出"​1"​的频率也越快。 输入的值越高,计数器溢出的越快("​PWM_accumulator[8]"​),​ 输出"​1"​的频率也越快。
  
 +### 3 PWM的应用
 +#### 3.1PWM产生可调直流电压
 +通过PWM的方式产生可调的直流电压是PWM最基础、最广泛的应用,比如在电路中用作直流偏压、控制LED的亮度,PWM本身是个数字信号,其占空比对应得到的直流量。
  
-#### PWM产生可调直流电压+{{::​pwm_1.gif|}} 
 + 
 +PWM-DAC得到模拟量,需要根据需要加一个低通滤波器,我们知道很多器件具有天然的频带特性,比如LED,我们人眼的视觉暂留就是天然的低通滤波器,所以直接用PWM信号控制LED,就可以得到某种亮度。用PWM-DAC驱动喇叭,喇叭本身就是一个带通滤波器(取决于你选用的喇叭的具体指标),如果你要滤出的高频信号远离喇叭的频带范围,即便不加RC滤波器,那些高频的干扰也不会对系统的性能产生任何影响。
  
 ---- ----
-##### 1位的DAC+#### 3.2 PWM-DAC播放音乐
 只用FPGA的一个管脚,连接一个扬声器来听MP3音乐?简单!我们可以先用PC解码一个MP3,并将解码的数据通过UART传送给FPGA,由FPGA的一根管脚做成1位的DAC来驱动扬声器播放音乐。 只用FPGA的一个管脚,连接一个扬声器来听MP3音乐?简单!我们可以先用PC解码一个MP3,并将解码的数据通过UART传送给FPGA,由FPGA的一根管脚做成1位的DAC来驱动扬声器播放音乐。
  
行 94: 行 100:
  
 --- ---
-#### 尝试播放一下MP3音乐+##### 尝试播放一下MP3音乐
 第一步是解码MP3音乐文件,这个可以在PC上执行,解码后的文件为“PCM”数据,通过串口传到FPGA。串口能够传输的最大速率为115.2Kbps(大约每秒11.5KBytes),所以需要现将音乐下取样到11KHz 8bit,这些处理在PC上都是非常简单的。 第一步是解码MP3音乐文件,这个可以在PC上执行,解码后的文件为“PCM”数据,通过串口传到FPGA。串口能够传输的最大速率为115.2Kbps(大约每秒11.5KBytes),所以需要现将音乐下取样到11KHz 8bit,这些处理在PC上都是非常简单的。
  
行 123: 行 129:
 --- ---
  
-#### 测试+#### 3.3 测试
  
 下面是基于两种PWM方式产生的PWM波形及经过低通滤波器以后得到的直流电压的波形图,供理解PWM的构成和效果进行参考。 下面是基于两种PWM方式产生的PWM波形及经过低通滤波器以后得到的直流电压的波形图,供理解PWM的构成和效果进行参考。
行 139: 行 145:
   * {{ :​pwm_180h_sawtooth.png |}} <WRAP centeralign>​ Sigma-Delta方式的PWM产生的180HZ锯齿波 </​WRAP>​   * {{ :​pwm_180h_sawtooth.png |}} <WRAP centeralign>​ Sigma-Delta方式的PWM产生的180HZ锯齿波 </​WRAP>​
  
-###PWM用DDS的DAC产生任意波形+### 4. DDS+PWM-DAC产生任意波形 
 +PWM-DAC可以来产生任意波形,DDS的逻辑部分与采用高速并行DAC是一样的,只是用一根线代替了高速并行DAC的8、10或12根数据线,这在管脚数量受限的场合又要想得到任意波形,采用PWM-DAC就更有优势。得益于FPGA内部时钟可以运行高达400MHz(比如小脚丫外部12MHz通过内部PLL可以得到396MHz的内部时钟),用PWM-DAC的方式生成一个等效于10bit的DAC,其对应的DAC转换率可以到396MHz/​1024,约为387Ksps,也就是说相当于一个10位精度、387Ksps的并行DAC,降低精度,比如8bit,可以得到1.55Msps的转换率;另一个极端,如果你想得到16位的精度,能够保证到396MHz/​65536,约为6Ksps 
 + 
 +^DAC精度^转换率^生成模拟信号(搭配合适的滤波器,比如7阶椭圆滤波器,截止频率为转换率的40%)^ 
 +|6|6.19Msps|2.5MHz| 
 +|8|1.55Msps|600KHz| 
 +|10|387Ksps|150KHz| 
 +|12|97Ksps|40KHz| 
 +|16|6Ksps|2.4KHz|
  
 --- ---
行 155: 行 169:
 {{ ::​pulse-width-modulation-implementation-using-fpga-and-cpld-ics.pdf |采用FPGA和CPLD实现PWM的方法 }},这是一篇非常基础的文章,详细介绍了PWM的构成原理、构成方式、以及应用。 {{ ::​pulse-width-modulation-implementation-using-fpga-and-cpld-ics.pdf |采用FPGA和CPLD实现PWM的方法 }},这是一篇非常基础的文章,详细介绍了PWM的构成原理、构成方式、以及应用。
  
-### 3采用双PWM产生更高频率的信号 +### 5. 双PWM产生更高频率的信号 
-  - 设置FPGA内部工作频率为12MHz x 33 = 396MHz(有时序报警,但可以忽略) +如果将PWM和R-2R的原理结合起来,会如何?比如如果你的板子上有两根数字IO,能否通过这两根数字IO上的PWM-DAC得到更好的性能提升?比如我们如果想得到一个10位分辨率的DAC,如果只是用1根数字IO,396MHz的主频,相当于转换率为396MHz/​1024, 如果用2根数字IO,两个PWM输出,一个PWM负责10位中的高5位,另一个PWM负责处理10位中的低5位,二者之间合成的时候按照R-2R的原理,也就是其中一个的负载阻抗是另一个的1/​32,转换率就提升了32倍,也就是最高转换率可以达到396MHz/​32 = 12.375Msps,理论上生成5MHz以内的任意波形是没有问题了。 
-  - 设置PWM DAC的精度为8位,使用两个输出管脚分别驱动外部电阻1.5K和24K(1.5x16),查找表的高4位分配给连接1.5K的输出管脚,查找表的低4位分配给连接24K的输出管脚。 +{{ :​daul_pwm_schem_sm.jpg |}}  
-  - DAC的转换时钟为12MHz*33/​16 = 24.75MHz,相当于一个24.75MHz的并行8位DAC,正弦波表的查找时钟也使用这个24.75MHz的时钟+ 
 +如果要生成我们最常用的8位DAC呢? 
 +  - 设置FPGA内部工作频率为12MHz x 33 = 396MHz 
 +  - 设置PWM DAC的精度为8位,使用两个输出管脚分别驱动外部电阻1.5K和24K(1.5x16),查找表的高4位分配给连接1.5K的输出管脚,查找表的低4位分配给连接24K(1.5K的16倍)的输出管脚。 
 +  - DAC的转换时钟为12MHz*33/​16 = 24.75MHz,相当于一个24.75MHz的并行8位DAC,正弦波表的查找时钟也使用这个24.75MHz的时钟,最高可以生成10MHz的任意波形(按照主时钟40%的转换率 + 7阶椭圆滤波器的方式) 
 + 
 +下面为双PWM-DAC为DDS生成正弦波信号发生器的代码: 
 + 
 +Verilog代码: 
 +<code verilog>​ 
 +module dds_dual_pwm(clk_in,​ pwm_oh, pwm_ol); 
 +input clk_in; ​             //12MHz 
 +output pwm_oh, pwm_ol; ​    //pwm output pins for higher 4bits and lower 4bits 
 + 
 +wire clk_pll_o;​ 
 + 
 +CLK_PLL u5(.CLKI(clk_in),​ .CLKOP(clk_pll_o));​ 
 + 
 +reg [3:0] cnt;          
 +always@(posedge clk_pll_o) ​ cnt <= cnt +1'​b1;​ 
 + 
 +assign lut_clk = cnt[3]; 
 + 
 +wire   ​ [23:​0] next_phase;​ 
 +wire   ​ [7:​0]     phase; 
 +reg    [23:0] accumulator;​ 
 + 
 +assign next_phase = 24'​H0AFFFF + accumulator; ​ //​24'​H0AFFFF is the frequency word for dds 
 + 
 +always @(posedge lut_clk)  
 +      accumulator <= #1 next_phase;​ 
 + 
 +assign phase = accumulator[23:​16]; ​   // phase is the high 8 bits 
 + 
 +wire [7:0] sine_data;​ 
 + 
 +lookup_tables u_lookup_tables(phase,​ sine_data);​ 
 + 
 +wire [3:0] PWM_upper4;​ 
 +assign PWM_upper4 = sine_data[7:​4];​ 
 +reg [4:0] PWM_upper_accumulator;​ 
 +always @(posedge clk_pll_o) PWM_upper_accumulator <= PWM_upper_accumulator[3:​0] + PWM_upper4;​ 
 +assign pwm_oh = PWM_upper_accumulator[4];​ 
 + 
 +wire [3:0] PWM_lower4;​ 
 +assign PWM_lower4 = sine_data[3:​0];​ 
 +reg [4:0] PWM_lower_accumulator;​ 
 +always @(posedge clk_pll_o) PWM_lower_accumulator <= PWM_lower_accumulator[3:​0] + PWM_lower4;​ 
 +assign pwm_ol = PWM_lower_accumulator[4];​ 
 + 
 +endmodule 
 +</​code>​
  
-得到的结果: 
  
 +改变频率控制字可以得到不同的输出信号频率:
 +{{ :​dualpwmwave.jpg |}}<WRAP centeralign>​ 生成的3.077MHz的正弦波形图 </​WRAP>​
 +{{ :​dualpwmfft.jpg |}}<WRAP centeralign>​ 生成的3.09375MHz的频谱 </​WRAP>​