跳至主要内容

高云FPGA Linux下调制PWM

· 閱讀時間約 9 分鐘
w0x7ce
MySelf

发布于 2024-09-06 20:47:44(微信公众号导出记录)。

本文来自公众号后台的“导出文章内容”功能。博客正文由导出长图进行本地 OCR 转写,并保留原始排版图用于逐段核对。

原文链接:查看原文

OCR 转写有效文字约 6344 字;代码、流程图和版式以文末原始排版图为准。

正文(本地 OCR 转写)

original wex7ce EI V1ajero 2824年9月6日 28:47 波兰

1.引言

本指南提供了FPGAPWM实现的全面分析,特别聚焦于TangNano9K开发板。我们将深人探讨 PWM的理论基础、代码实现、资源利用、频率限制、占空比调节以及在L1nux环境下的开发流 程。

2.PWM基础理论

脉冲宽度调制(PiM)是一种通过调整信号的占空比来控制平均功率的技术。在FPGA中,PWM通 常通过计数器和比较器来实现。

3.FPGA PWM实现

3.1PWM生成器代码

nodule pwm_generator ( 1nput clk, input [6:e] duty_cycle_in [0:3]. // 新增:外部占空比输人 output reg [3:0] pwm_out 7 ; localparan TARGET_FREQ = 100_000; // PkM须率: 100 kHz 1ocalparan CL0CK_FREQ = 27_808_e66; // B时神源率: 27 HHz localparan CoUNT_MAX = CLOCK_FREQ / TARGET_FREQ - 1; reg[7:θ]count=8;//8位计数器,最大值269 reg [6:e] duty_cycle[0:3];// 4个7份占登比额存器,兹国e-100 wlre [7:e] thresh_3 - (couNT_MAx • duty_cycle[2]) / 100; always @(posedge clk) begin count <= (count < CouNT_MAX) ? count + 1 : ; pw_out[0]<= (count < thresh_1]; pw_out[3]<= (count < thresh_4]; //更折占空比 [8]uao<np => [a]a>As<np duty_cycle[1] <= duty_cycle_in[1]: []utaoAs<np => [e]aAs<np pua endnodule

3.2顶层模块实现

nodule uart_loop_back ( input clk,

  • xen ndu

output uart_tx, output [5:e] led, putput [3:e] pun_out, output tine_tx 7 : wire [7:8] rxData; reg txDatavalid; wire txBusy; wire current_bit; reg [6:8] pun_duty_cycles [9:3]; // PMM占空比存储 //UART接收模块实例化 uart_rx #( .DELAY_FRAMES(69)) uart_rx_inst ( .clk(ctk) , .uart_rx(uart_rx), .rxData(rxData), .rxDataVal1d(rx) 1: //UART发送模块实例化 uart_Lx #( -DELAY_FRAMES(69)) uart_Lx_inst ( ,clk(clk), .txData{txData), .txbatavalid(txDatavalid), .txBusy(txBusy),.uart_tx(uart_tx) 1: //PWM生成器实例化 ,clk(clk), .duty_cycle_in( pwm_duty_cycles) , pwtt_out (pwn out) //时间发运器实例化 time_sender #(.CLocK_FREQ(8_eee_eee)) tine_sender_inst ( clk(clk), .uart_tx(tine_tx), ,current_bit(current_bit) reg [7:8] loopback_buffer; always @(posedge clk) begin 1f (rxDataValid) begin loopback_buffer <= rxData; loopback_ready <= 1; //使用接收到的数揭更新PWM占空比 case (rxData[7:6]) 2′b01: pwm_duty_cycles[1] <= rxData[6:8]; 2′b11: pwm_duty_cycles[3] <= rxData[6:] ; endcase end if (loopback_ready && 1txBusy) begin txData <= lopback_buffer; txDatavalid <= 1; Loopback_ready <= 0; end else if (11oopback_ready)1 begin txDataValid <= 0; end led[3:0] <= pMm_out; led[5] <= current_bit; end endnodule

3.3参数计算与配置

L.PWM频率计算: 5 - 1 - 0006 / 0002 - 1 - 0131 / 030 - X10 COUNT_MAX = CL0CK_FREQ / TARGET_FREQ - 1 = 27,080,808 / 168,699 - 1 = 265 .占空比计算: thresh_x = (CouNT_MAX + duty_cycle[x]) / 100

3.4FPGA PWM的频率限制

为什么频率不能过低: L.资源占用增加:低频PWM需要更大的计数器,这直接影响FPGA资源的使用、例如,对于1Hz 的PWM领率和27MHz的时钟: COUNT_MAX - 27,068,600 / 1 - 1 - 26,999,999 这需要一个25位的计数器,相比于180kHzPWM的8位计数器,使用了更多的触发器和逻辑 资源。 具体影响:

  • 更多的触发器(FLip-FLops)用于实现大计数器

  • 更复杂的比较逻辑,需要更多的LUT资源

  • 可能需要使用块RAM来存储大型查找表(用于复杂的占空比计算)

2.定时精度:低频PwM在高速时钟下可能导致jitter增加,影响输出信号的稳定性。

3.响应时间:低频PWM会增加系统响应时间,不适合需要快速反应的应用。

为什么频率不能过高: L.时序限制:FPGA有最大时钟频率限制,过高的PWM频率可能违反时序要求

2.信号完整性:高频PM信号更容易受到噪声和干扰的影响

3.功耗增加:高频切换会增加动态功耗、

3.5占空比调节

在本设计中,占空比通过以下方式调节: L.顶层模块(uart_Loop_back)中定义了pun_duty_cycLes 数组来存储各个PwM通道的占 空比值。

2.通过UART接收的数据来更新占空比:

case (rxData[7:6]] 2'b1e: pwm_duty_cycles[2] c- rxata[6:0] ; endcase 这允许通过串口动态调整每个PMM通道的占空比

3.更新后的占空比值传递给PWM生成器模块:

pMm_generator pMm_gen [ .clk(clk), .duty_cycle_in( pmn_duty_cycles).

  • Pem_out(pon aut)

1.在PWM生成器内部,占空比值用于计算比较阅值:

wire [7:e] thresh_1 = (couNT_HAx * duty_cycle[e]) / 100; 这种设计允许灵活且动态地调整PnM的占空比,同时保持了模块化的结构。

4.Linux环境下的TangNano9K开发流程

4.1环境准备

L,安装依赖: sudo apt-get install build-essential clang bison flex libreadline-dev gawk tcl-dev lihffi-dev git graphviz xdot pkg-confic python3 libboost-systen-dev libboost-python-dev
Aop-6ta1nz ap-wasAsa1t-1so0qg1 ?.克隆并编译Yosys: git clone https=//github.con/YesysHQ/yosys.git cd yo5ys make -1$(nproc)

3.克隆并编译nextpnr-gowin:

git clane https://github-con/YosysHQ/nextpnr.git cd nextpnr cnake -DARCH=goMin -DGOWIN_BBA_EXECUTABLE=/usr/local/bin/gowin_bba (ooudu)s[- ayeu 1letsut axeu opns cd ..

1.安装OpenFPGALoader:

git clone https=//github.con/trabucayre/openFPGALcader.git cd openFPGALoader mkdir build &6 cd build cnake (odu)s[- aou llersut ayeu opns cd ....

4.2项目结构

uart_loophack/ —1inpl/ I= src/ —— pw_generator. v T time_sender.v |——uart_loopback.cst uart_tx v I—— 9k_uart_loopback,gprj I Linux_conplie.nd . 2 L- README_cn.nd

4.3约束文件(uart_Loopback.cst)

I0_L0c "clk" 52; I0 PORT "clk* PULL_MODE=UP; t .[9]p. 0noI I0_L0c "led[1]* 11; I0_L0C "led[2]* 13;

  • [ [≤]p

"led[4]* 15; I0_L0C gt .[s1pa1 10_L0C tx4uen. I0_PORT "uart_tx* IO_TYPE=LVCNOS33; "uart rx* 18; I0 L0C IO_PORT "uart_rx* IO_TYPE=LVCMO533; sz[0]anound I0_LOC

1.3

ccsoA7=3dl 0I [al1no md., Iaod 0I I0_L0C 92 -[t]4no umd. 16 "pw_out[2] 27; I0_L0C I0_PORT "pwm_out[2]* I0_TYPE=LVCH0533; I0_LOC "pwm_out[3]* 28; 67 ccso7=3dl oI [c11no md. Iaod 0I :0E ,x>= I0_L0C I0_PORT "tine_tx* I0_TYPE=LVCM0S33;

4.4编译流程

1.综合:

yosys -p read_verilog src/.v; synth_gowin -top uart_loop_back -json inf .布局布线: nextpnr-govin --1son impl/uart_loopback. 1son --freq 27 --write Impl/uart,

3.生成比特流:

2s[ Jud yoeqdoo1 1uen/1duT s,*yoeqdoon 1Jen/ldut 0- 26-NTNo p- yoed utMob

1.烧录FPGA:

openFPGALoader -b tangnano9k -f 1mol/uart_loopback.fs

5.性能分析与优化

5.1资源利用分析

基于编译日志,我们可以分析资源利用信况: Sunnary Nunber of LUT4s: 566 LE6 194 Nunber of DFFs: 79 14 Nunber of HUX2_LUT6: 5 Nunber of HUX2_LUTB: 这些微据表明: L.LUT利用适中,表明逻辑复杂度合理。

2.DFF数量较少,主要用于状态存储和同步。

3.存在一些复杂的多路选择逐辑(MUX2_LUT5到MUX2_LUT8),这可能是由于PkM通道的多路

复用和占空比调节逻输造成的。

1.ALU的使用量较大(937个),这可能是由于PWM阅值计算和UART通信逻辑引起的。可以考

虑使用查找表(LUT)来优化一些常用的计算结果,以减少ALU使用。

5.2时序分析

基于编译日志: Max frequency for clock pwm_gen.clk: 34.62 MHz (PAS5 at 27.ee MHz)

  • > posedge pwm_gen.c1k: 2,72 ns

Max delay <async> Hax delay posedge pvn_gen.clk -> <async> : 9.56 ns 这表明: L.设计在27MHz时钟下有足够的时序裕度,最高可支持到34.62MHz。

2.存在一些异步路径,特别是从时钟到异步输出的9.56ns延迟,可能需要进一步优化。

5.3优化策略

1.时钟管理:

  • 考虑使用FPGA的PLL资源生成更精确的时钟。

  • 对于不同功能模块(如PWM和UART),可以使用不同的时钟域以优化性能。

.流水线化:

  • 对于PwM阔值计算等复杂逐辑,考虑增加流水线stages以提高最大可能频率。

  • 示例:

reg [7:0] thresh teip: reg [3:e] pmn_out_tenp: always o(posedge clk) begin thresh_tenp <= (couNT_MAx * duty_cycle[e] / 1ee; pwm_out_templo] <= (count < thresh_temp); pwn out[e] c= pwn_out_tenp[0]; end

3.资源共享:

  • 对于多通道PMM,考虑时分复用技术。例如,使用一个高频计数器和比较器,通过多路复

用器输出到不同通道。

  • 示例:

rcg [1:e] channol_select = θ; always @(posedge clk) begin channel_select s= channel _select + 1; 2'boe: pum_out[e] <= (count < thresh_1); 2'bll: pum_out[3] <= (count < thresh_4); endcase end 10

1.预计算:

  • 对于固定或较少变化的参数,使用查找表代替实时计算。

  • 示例:

reg [7:0] duty_to_thresh [0:100]; initial begin for (int i = 0; i <= 100; i++) begin duty_to_thresh[i] =(coUNT_MAX * i) / 100; end wire [7:0] thresh_1 = duty_to_thresh[duty_cycle[o]];

5.异步路径优化:

  • 检查并优化长延迟的异步路径,可能需要增加寄存器stages来分割长路径。

  • 确保关键信号使用专用的全局时钟网络。

5.占空比调节优化:

  • 考虑使用增量式调节而不是直接赋值,可以减少大幅度变化带来的瞬态影响。

  • 示例:

always @(posedge clk) begin if (duty_cycle[0] < target_duty[0])

  • [o]ao<n => [o]aon

else if (duty_cycle[o] > target_duty[o])

  • [o]an => [o]an

end

FPGA·目录三 <上一篇 下一篇> HDLBits系列入门题目详解之Vector FPGA design a UART Loopback System

原始排版图

高云FPGA Linux下调制PWM:微信公众号导出原始排版图