ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

FPGA多路电源时序控制模块设计与调试实践

FPGA多路电源时序控制模块设计与调试实践 电源时序控制这事说起来简单做起来全是坑。尤其在FPGA这类多电压域系统里内核对时序的要求非常严格——核心电压没稳IO电压先上来了轻则配置失败重则芯片直接锁死。我自己在项目里就遇到过因为时序设计不当导致FPGA上电后始终无法完成配置的情况排查了两天才定位到时序配合的问题。所以这次想认真聊聊多路电源时序控制模块到底该怎么设计以及实际调试中那些只有踩过坑才知道的细节。1. 项目背景与核心需求拆解1.1 为什么FPGA系统需要多路电源时序控制现在的FPGA早就不是单一电压供电的时代了。拿一颗典型的FPGA来说它至少需要这几路电源核心电压VCCINT通常0.9V到1.2V、辅助电压VCCAUX常见1.8V或2.5V、IO电压VCCO根据Bank不同可能是1.2V/1.5V/1.8V/2.5V/3.3V、还有某些高速收发器需要的模拟电压比如0.9V/1.0V的VCCAUX_IO。这些电压不是随便什么时候上电都行的。芯片厂商的器件手册里都会明确给出“Power Sequencing Requirements”——也就是电源上电顺序要求。通常的规定是核心电压先建立、再是辅助电压、最后是IO电压。下电顺序则刚好反过来。为什么这么规定因为FPGA内部有大量的ESD保护二极管和寄生PN结如果IO电压先于核心电压建立电流就会通过这些寄生通路灌入内核形成所谓的“latch-up”效应严重时直接烧毁芯片。即便没烧也可能导致内部逻辑处于不确定状态配置控制器无法正常初始化。我见过一个案例某块板子为了省成本把1.8V和3.3V用同一个LDO输出上电时3.3V先稳1.8V后稳结果FPGA的配置芯片死活读不出来。后来用示波器抓上电波形才发现VCCAUX在VCCINT还没到0.8V的时候就已经冲到1.2V了FPGA内部的上电复位电路直接卡死。换了带时序控制的方案后问题立刻消失。1.2 一个典型的FPGA供电架构长什么样要设计时序控制模块先得把供电架构理清楚。以我手头一个Xilinx Artix-7的项目为例板上电源树大概是这样的电源轨电压用途典型电流上电顺序VCCINT1.0VFPGA内核逻辑2A~5A第1路VCCAUX1.8V辅助电路、PLL0.5A~1A第2路VCCBRAM1.0VBlock RAM与VCCINT同源第1路VCCO_343.3VIO Bank 340.3A~1A第3路VCCO_352.5VIO Bank 350.3A~1A第3路VCCAUX_IO1.8V高速IO辅助0.3A第2路注意VCCBRAM一般和VCCINT同源可以共用一路电源但VCCAUX_IO最好跟VCCAUX同源或者至少等VCCAUX稳定之后再上。至于VCCO虽然都是第3路但不同Bank之间可以并联也可以分别控制取决于你的IO电平标准和外部器件要求。这个项目里我用了两片DC-DCTPS54331和一片LDOTPS7A4700来产生这三组核心电压时序控制就靠FPGA自己来管——用一个状态机依次使能各路电源的Enable引脚。1.3 用FPGA自己做时序控制还是用专用芯片这是第一个要做的技术选型。市面上有专门的电源时序控制器比如TI的UCD9090、ADI的ADM1184也有简单的RC延时电路。那为什么还要用FPGA来做先说专用芯片的优点集成度高、引脚少、配置简单很多还带ADC可以监控电压和电流。缺点也很明显灵活性差一旦板子改版、电源路数变了就得重新选型甚至重新画板。而且有些专用芯片的延时精度受温度影响大工业级应用里不太放心。FPGA方案的优势在于完全可编程延时时间、上电顺序、故障响应策略全都可以通过RTL代码修改不需要动硬件易于集成如果FPGA本身就需要控制其他外设比如风扇、指示灯、通信接口时序控制可以作为一个子模块挂在系统总线上可扩展路数不够加几个寄存器就行不增加BOM成本可观测可以把每路电源的状态、故障标志位映射到寄存器里通过串口或以太网读出来方便远程诊断当然缺点也有占用FPGA的IO和逻辑资源而且FPGA本身的上电需要依赖配置芯片如果时序控制模块依赖FPGA运行那FPGA自己上电时谁来管所以实际项目中通常会有一个“最小系统”的时序由硬件RC或专用芯片保证确保FPGA能完成配置上电之后再由FPGA接管更复杂的时序控制。我这次的设计里VCCINT和VCCAUX这两路关键电源由FPGA的Enable信号控制但FPGA配置完成之前这两路电源通过一个简单的RC延时电路先建立起来等FPGA配置完成、时钟稳定后再切换到FPGA控制模式。这样既保证了安全性又保留了灵活性。1.4 设计目标与关键指标定义在动手写代码之前必须先定清楚指标。这个项目我给自己定了这几个KPI支持4路电源独立使能控制预留扩展到8路每路之间的上电延时可以独立配置最小步进1ms最大65535ms上电顺序严格按预设执行支持菊花链式和并行式两种模式下电顺序与上电相反且支持“快速下电”模式所有电源同时关闭每路电源状态反馈Power Good信号需要实时监测如果某路电源在规定时间内没有拉高PG则判定为故障立即执行下电保护故障状态通过LED和寄存器上报整个模块使用50MHz时钟资源占用控制在200个LUT以内这些指标定下来之后代码结构其实就清晰了一个主状态机负责上电和下电的流程控制一个计数器阵列负责延时一个故障检测模块负责监控PG信号再加上寄存器接口供CPU读写配置参数。2. 核心控制逻辑与状态机设计2.1 上电时序的数学模型与参数计算先算清楚每一路电源需要等多久。以TPS54331为例它的软启动时间由SS引脚上的电容决定典型公式是t_ss ≈ C_ss × V_ref / I_ss其中V_ref 0.8V内部基准I_ss 2μA典型值。如果C_ss 10nF那么t_ss ≈ 10nF × 0.8V / 2μA 4ms。也就是说从Enable拉高到输出电压稳定大约需要4ms。再加上输出电容充电和反馈环路稳定的时间保守估计要留6~8ms。所以我的上电时序设计是这样的第1路VCCINTEnable拉高等待8ms检测PG1第2路VCCAUXEnable拉高等待6ms检测PG2第3路VCCO_34Enable拉高等待6ms检测PG3第4路VCCO_35Enable拉高等待6ms检测PG4每路之间的间隔就是前一路的软启动时间加上裕量。如果前一路的PG信号在等待时间内没有拉高状态机直接跳到故障处理状态关断所有电源并置位故障标志。这里有个容易忽略的细节PG信号的极性。有些电源芯片的PG是开漏输出需要上拉电阻高电平表示电源正常有些则是低电平有效。代码里必须用一个参数来配置极性否则调试时会误判。我在第一次调试时就因为没注意极性导致所有电源刚上电就被关断查了半天才发现是PG极性搞反了。2.2 主状态机的状态编码与跳转逻辑状态机是时序控制模块的核心。我用了One-Hot编码虽然占用寄存器多一些但跳转逻辑简单不容易出现毛刺。状态定义如下localparam IDLE 8b0000_0001; localparam PWR1_ON 8b0000_0010; localparam WAIT_PG1 8b0000_0100; localparam PWR2_ON 8b0000_1000; localparam WAIT_PG2 8b0001_0000; localparam PWR3_ON 8b0010_0000; localparam WAIT_PG3 8b0100_0000; localparam PWR4_ON 8b1000_0000; localparam ALL_ON 8b0000_0000; // 实际使用位宽需要更宽这里只是为了说明状态编码思路实际代码中我用了16位One-Hot因为还要包括下电状态和故障状态。主状态机的跳转条件有几个关键点从IDLE到PWR1_ON的触发条件外部使能信号有效sys_en 1且没有故障标志从PWR1_ON到WAIT_PG1延时计数器到达预设值比如8ms从WAIT_PG1到PWR2_ONPG1有效高电平或低电平取决于配置从WAIT_PG1到FAULT延时计数器超时且PG1仍无效每个WAIT状态都有两个出口PG有效则继续PG无效且超时则跳故障。这个“超时”的时间窗口一般设为预期软启动时间的1.5~2倍。比如预期8ms超时设为16ms。这样既能容忍一定的参数偏差又不会让系统卡在等待状态太久。下电过程则是一个反向的状态机从ALL_ON状态开始先关闭最后一路VCCO_35延时后再关VCCO_34依次类推。下电延时不需要等待PG信号因为电源关断是确定性的只需要保证前一路完全放电后再关下一路。放电时间取决于输出电容和负载电流一般1~2ms足够。2.3 延时计数器的实现与精度分析延时计数器看起来简单但要做精确并不容易。我用的是50MHz时钟每个时钟周期20ns。如果要实现1ms的延时计数值是50000。16位计数器最大可以计到65535对应1.31ms不够用。所以需要更宽的计数器或者用两级计数。我的做法是用一个32位计数器低16位用于毫秒级延时高16位用于秒级延时。具体实现reg [31:0] delay_cnt; wire [15:0] delay_ms delay_cnt[31:16]; always (posedge clk or posedge rst) begin if (rst) begin delay_cnt 32d0; end else if (delay_en) begin if (delay_cnt[15:0] 16d49_999) begin delay_cnt[15:0] 16d0; delay_cnt[31:16] delay_cnt[31:16] 1b1; end else begin delay_cnt[15:0] delay_cnt[15:0] 1b1; end end else begin delay_cnt 32d0; end end这样每50000个时钟周期1ms高16位加一最大可以延时65535ms约65秒足够用了。精度方面由于时钟是晶振提供的误差在ppm级别完全满足电源时序控制的需求。需要注意的是如果系统时钟不是50MHz计数值要重新算。比如用25MHz时钟1ms对应25000个周期那低16位的比较值就要改成24999。我一般会用一个参数来定义时钟频率然后在代码里自动计算parameter CLK_FREQ 50_000_000; localparam CNT_PER_MS CLK_FREQ / 1000;这样换时钟频率时只需要改一个参数不容易出错。2.4 电源状态监测与故障响应机制故障响应是电源时序控制里最容易被低估的部分。很多人只做了上电时序却没考虑如果某路电源在运行过程中突然掉电怎么办。比如VCCO_34在正常工作半年后因为负载短路导致PG失效如果系统不响应FPGA的IO可能因为电平不匹配而损坏。我的设计里每个PG信号都经过一个数字滤波器其实就是几级D触发器打拍滤除毛刺后再送进故障检测逻辑。故障检测分两类上电阶段故障在WAIT_PG状态超时后PG仍无效立即执行全局下电置位fault_flag并记录是哪一路出的问题用fault_code寄存器运行阶段故障在ALL_ON状态下如果任何一路PG失效超过10ms也是用计数器触发全局下电置位fault_flag故障发生后系统会锁定在FAULT状态只有收到外部的clear_fault信号可以通过寄存器写1才能重新回到IDLE状态。这个“锁死”机制很重要防止故障未排除时系统反复尝试上电造成更大的损坏。故障码的定义我放在一个寄存器里方便CPU读取fault_code含义4b0000无故障4b0001第1路PG超时4b0010第2路PG超时4b0100第3路PG超时4b1000第4路PG超时运行阶段的故障也会记录在同一个寄存器里只是触发条件不同。CPU读到故障码后可以通过查表知道是哪一路出了问题然后去检查对应的硬件电路。3. Verilog代码实现与关键模块解析3.1 顶层模块的端口定义与参数化设计顶层模块的端口设计要考虑通用性。我的做法是所有可能变化的参数都做成parameter或通过寄存器配置端口只保留必要的时钟、复位、电源使能输出和PG输入。module power_seq_ctrl #( parameter CLK_FREQ 50_000_000, parameter PWR_NUM 4, parameter PG_ACTIVE_HIGH 1, parameter DELAY_MS_1 8, parameter DELAY_MS_2 6, parameter DELAY_MS_3 6, parameter DELAY_MS_4 6, parameter TIMEOUT_MS 16 )( input wire clk, input wire rst_n, input wire sys_en, input wire clear_fault, input wire [PWR_NUM-1:0] pg_in, output reg [PWR_NUM-1:0] pwr_en, output reg all_pwr_ok, output reg [3:0] fault_code, output reg fault_flag );这里把PG极性、延时时间、超时时间都做成参数方便不同项目复用。如果要做成寄存器可配置的就把这些参数接到一个寄存器接口上通过CPU写入。我在这个项目里用了AXI-Lite接口把配置寄存器映射到地址空间CPU可以动态修改延时时间。3.2 上电状态机的Verilog实现细节状态机的核心代码大概长这样省略了部分重复逻辑always (posedge clk or negedge rst_n) begin if (!rst_n) begin state IDLE; pwr_en 4b0000; fault_code 4b0000; fault_flag 1b0; end else begin case (state) IDLE: begin if (sys_en !fault_flag) begin state PWR1_ON; delay_en 1b1; end end PWR1_ON: begin pwr_en[0] 1b1; if (delay_ms DELAY_MS_1) begin state WAIT_PG1; delay_en 1b0; end end WAIT_PG1: begin if (pg_filtered[0] PG_ACTIVE) begin state PWR2_ON; delay_en 1b1; end else if (delay_ms TIMEOUT_MS) begin state FAULT; fault_code 4b0001; end end // ... 后续状态类似 FAULT: begin pwr_en 4b0000; fault_flag 1b1; if (clear_fault) begin state IDLE; fault_flag 1b0; fault_code 4b0000; end end endcase end end有几个细节值得注意delay_en信号的使用只在需要延时的状态拉高其他状态清零。这样可以保证每次进入新的延时状态时计数器从0开始不会因为上次的残留值导致延时不准。pg_filtered信号的生成PG输入先经过三级D触发器打拍再根据PG_ACTIVE_HIGH参数决定是否取反。这样既滤了毛刺又适配了不同极性的PG信号。fault_code的置位用独热码每路电源对应一个bit方便CPU判断是哪一路故障。3.3 PG信号消抖与数字滤波处理PG信号虽然来自电源芯片但在实际板子上经常会有毛刺。尤其是DC-DC的开关噪声可能耦合到PG线上导致误触发。我用了一个简单的数字滤波器reg [2:0] pg_sync; always (posedge clk) begin pg_sync {pg_sync[1:0], pg_in[0]}; end wire pg_filtered_0 (pg_sync 3b111) ? 1b1 : (pg_sync 3b000) ? 1b0 : pg_filtered_0_reg;这段代码的意思是只有当连续三个时钟周期采样到高电平时才认为PG有效连续三个周期低电平才认为无效中间状态保持上一次的值。50MHz时钟下三个周期只有60ns对于电源PG信号来说远远不够。所以我实际用的是级联计数器把滤波窗口做到1ms左右。具体做法是用一个10位的计数器当输入稳定不变时计数器加一输入变化时计数器清零。当计数器达到500001ms时才把输入状态更新到滤波后的输出。这样1ms以内的毛刺全部被滤掉不会触发误判。3.4 下电时序的实现与快速下电模式下电时序的状态机跟上电类似但方向相反。我用了另一个状态机来处理下电或者也可以在主状态机里用方向标志位来区分。我个人倾向于用独立的状态机逻辑更清晰不容易出错。下电状态机的跳转条件跟上电不同它不需要等待PG信号只需要等待固定的放电时间。每路电源关断后延时2ms确保输出电容放电到安全电压再关下一路。最后一路关断后回到IDLE状态。快速下电模式则是所有pwr_en同时拉低不做延时。这个模式用在紧急情况下比如检测到严重故障需要立即断电。不过要注意快速下电时如果负载电容很大可能引起电压反弹所以一般只在故障保护时使用。// 快速下电逻辑 if (fast_shutdown) begin pwr_en 4b0000; state IDLE; end3.5 寄存器接口与CPU通信协议为了能让CPU配置延时参数和读取故障信息我加了一个简单的寄存器接口。如果用AXI-Lite代码会比较长这里为了说明原理我用一个简化的SPI风格的接口地址寄存器名读写功能0x00CTRLRWbit0: sys_en, bit1: clear_fault, bit2: fast_shutdown0x04STATUSRObit0: all_pwr_ok, bit1: fault_flag, bit[7:4]: fault_code0x08DELAY1RW第1路延时时间ms0x0CDELAY2RW第2路延时时间ms0x10DELAY3RW第3路延时时间ms0x14DELAY4RW第4路延时时间ms0x18TIMEOUTRWPG超时时间msCPU通过写DELAY寄存器可以动态调整时序不需要重新综合FPGA。这个设计在调试阶段特别有用——我可以先写一个保守的延时值测出实际软启动时间后再优化不用每次都重新编译。3.6 资源占用分析与时序收敛结果这个模块在Artix-7 XC7A35T上综合后的资源占用如下资源类型使用量可用量占比LUT156208000.75%FF203416000.49%BRAM0500%DSP0900%资源占用非常小对FPGA整体设计几乎没有影响。时序方面50MHz时钟下建立时间余量WNS是7.2ns保持时间余量WHS是0.3ns完全满足要求。如果要把时钟提到100MHz需要重新跑时序但这个模块的逻辑深度很浅估计问题不大。4. 板级调试与实测波形分析4.1 测试环境搭建与仪器配置板子回来之后第一步不是直接上电而是先检查电源对地阻抗。用万用表测每路电源的输出对地电阻确认没有短路。然后给板子输入12V但先不插FPGA配置芯片用示波器逐个测量各路电源的上电波形。我用的仪器是示波器Rigol DS1054Z四通道100MHz带宽电流探头Micsig CP2100B用于测上电浪涌电流电子负载IT8511用于模拟不同负载条件测试时把示波器的四个通道分别接到VCCINT、VCCAUX、VCCO_34、VCCO_35触发方式设为VCCINT上升沿时间基准设为5ms/div这样就可以一次抓完整个上电过程。4.2 上电时序实测波形与问题定位第一次上电测试就发现了问题VCCAUX比VCCINT晚了大约12ms才起来而不是预期的8ms。查了一下TPS54331的数据手册发现它的使能阈值是1.2V而FPGA的IO在配置完成前输出高电平只有1.8V刚好超过阈值但上升沿很缓。加上Enable引脚上的RC滤波100kΩ100nF实际到达阈值的时间比预期晚了4ms。解决方案有两个一是减小RC滤波的电容值从100nF改成10nF二是在FPGA代码里把延时时间调短2ms。我选了第二个方案因为改硬件要重新焊板子改代码只需要重新编译。这也体现了FPGA方案的灵活性——参数调整不用动硬件。调整后重新测试波形就对了VCCINT先起8ms后VCCAUX起再6ms后两路VCCO同时起。每路之间的间隔跟设计值吻合误差在0.5ms以内。4.3 下电时序测试与放电时间验证下电测试用的是“断电重启”场景系统正常工作后拉低sys_en观察下电波形。示波器设置为单次触发下降沿触发。实测发现VCCO_35关断后电压从3.3V降到0.5V用了大约1.8ms比我预期的2ms略快说明负载电流比我估计的大。于是我把下电延时从2ms调整到3ms确保充分放电。这里有个经验下电延时宁长勿短因为放电不完全会导致下次上电时电压反弹可能触发PG误判。另外下电时VCCINT和VCCAUX的关断顺序也很重要。我的设计是先关VCCO再关VCCAUX最后关VCCINT。实测波形确认了这个顺序没有出现电压倒灌现象。4.4 故障注入测试与保护机制验证故障注入测试是验证保护机制是否有效的关键步骤。我用了两种方法断开PG上拉电阻模拟PG信号失效。系统应该在超时后进入FAULT状态关断所有电源LED亮起fault_flag置位。短路某路电源输出用一根导线短暂短接VCCO_34的输出到地模拟负载短路。系统应该在10ms内检测到PG失效并执行保护。实测结果符合预期断开PG后系统在16ms超时后进入FAULT状态所有pwr_en拉低fault_code显示为4b0100第3路故障。短路测试时由于DC-DC本身的限流保护先动作PG信号在5ms内失效系统在10ms后触发全局下电。整个响应时间在15ms以内对FPGA的保护是及时的。有一点要注意故障注入测试可能会损坏电源芯片建议先用电子负载模拟不要直接短路。我是在确认电源芯片有限流保护后才做的短路测试而且只短接了不到1秒。4.5 实测数据整理与设计迭代记录整理一下主要实测数据测试项设计值实测值偏差备注VCCINT上电延时8ms8.2ms0.2ms在允许范围内VCCAUX上电延时6ms6.3ms0.3msRC滤波影响VCCO_34上电延时6ms5.9ms-0.1ms正常VCCO_35上电延时6ms5.8ms-0.2ms正常VCCO_35下电放电3ms2.7ms-0.3ms负载比预期大PG超时保护16ms16.1ms0.1ms正常运行故障响应10ms10.2ms0.2ms正常基于这些数据我做了一轮设计迭代把VCCAUX的延时从6ms调到5ms补偿RC滤波的影响把下电放电时间从2ms调到3ms补偿负载电流的影响。迭代后的版本在第二批板子上验证所有参数都在设计值±5%以内。5. 常见问题与排查技巧实录5.1 电源时序控制中的典型故障模式在实际项目中我遇到过这些问题问题一FPGA配置失败DONE信号不拉高。排查发现是VCCAUX上电太慢在VCCINT还没稳定的时候就已经冲到1.8V了。FPGA内部的上电复位电路要求VCCINT先建立否则配置控制器不工作。解决方法是在VCCAUX的Enable信号上串一个RC延时确保它比VCCINT晚至少5ms。问题二系统运行中随机重启。用示波器抓了很久才发现是VCCO_34的PG信号在负载突变时会产生100ns左右的毛刺被FPGA误判为电源故障触发了保护下电。解决方法是在PG信号上增加数字滤波把滤波窗口做到1ms。问题三下电后再次上电FPGA无法配置。原因是下电时VCCO_35的电容没有完全放电残余电压导致FPGA的配置引脚处于不确定状态。解决方法是在下电时序中增加放电延时并在PCB上给每路电源加一个泄放电阻1kΩ加速放电。5.2 时序配合问题的排查思路遇到时序问题时我的排查步骤是这样的先看波形用示波器同时抓所有电源的上下电波形观察是否有电压倒灌、顺序错乱、延时不够等问题。这是最直接的方法。再查PG信号用示波器测量每路PG信号的上电时间和极性跟电源芯片手册对比。如果PG信号异常先检查上拉电阻和滤波电容。检查FPGA配置状态如果电源波形正常但FPGA配置失败用逻辑分析仪抓配置引脚的信号确认配置时钟和数据是否正常。读故障寄存器如果系统已经跑起来了通过串口或JTAG读出fault_code寄存器直接定位是哪一路电源出的问题。有个技巧在代码里加一个“调试模式”当调试模式使能时延时时间全部缩短到正常值的十分之一这样可以快速验证时序逻辑的正确性不需要等几十毫秒。我在调试初期就是用这个模式几秒钟就能跑完一个完整的上电-下电循环。5.3 常见问题速查表现象可能原因检查方法解决方案FPGA配置失败VCCINT和VCCAUX顺序不对示波器抓上电波形调整Enable RC延时或代码延时系统随机重启PG信号毛刺示波器看PG信号增加数字滤波或RC滤波下电后无法再次上电输出电容放电不完全测量下电后残余电压增加放电延时和泄放电阻某路电源始终不使能pwr_en信号未输出逻辑分析仪抓pwr_en检查状态机是否卡在WAIT_PG故障后无法恢复clear_fault信号未生效读CTRL寄存器检查clear_fault是否被打拍同步延时时间不准时钟频率不对测量实际时钟频率修改CLK_FREQ参数5.4 独家避坑经验分享经验一PG信号一定要做数字滤波。我在这上面栽过两次都是因为电源芯片的PG输出在负载突变时有毛刺。后来养成习惯所有PG输入都先过1ms的数字滤波再送状态机。经验二下电时序比上电时序更容易出问题。上电时电压是慢慢升高的有很多时间余量下电时电压是快速下降的而且负载电容的放电特性跟负载电流有关很难精确预测。所以下电延时一定要留足裕量我一般按计算值的1.5倍来设。经验三故障保护要“锁死”。不要做成自动恢复否则故障未排除时系统会反复尝试上电可能造成连锁损坏。必须让系统停在FAULT状态等人工确认后再清除故障。经验四把配置参数做成寄存器可写。这样调试时不用反复编译FPGA用串口工具改几个寄存器的值就能调整时序。我在调试阶段用Python写了一个小脚本通过串口读写寄存器效率比重新综合高太多了。经验五留出调试用的观测点。在PCB上给每路电源的Enable和PG信号都留测试点最好再留几个LED指示灯。调试时光看波形不够直观有LED辅助能快速判断系统处于哪个状态。5.5 从项目中学到的系统性设计思维这个项目做完之后我最大的体会是电源时序控制看似简单但涉及硬件、FPGA逻辑、PCB布局、电源芯片特性等多个层面。单靠软件或单靠硬件都做不好必须系统性地考虑。比如说PCB布局时电源芯片的输入电容要尽量靠近芯片否则上电时的电压跌落会影响使能阈值判断。再比如FPGA的IO标准要跟电源芯片的Enable引脚电平匹配如果FPGA的IO是1.8V而Enable引脚需要3.3V就要加电平转换。这些细节在写代码之前就要确认好否则代码写得再漂亮也没用。另外测试覆盖率很重要。我给自己定了一个规矩任何电源时序控制模块必须通过至少这五项测试才算合格——上电顺序测试、下电顺序测试、PG超时保护测试、运行故障保护测试、反复上下电测试至少100次。其中反复上下电测试最容易被忽略但它能暴露很多偶发问题比如电容残余电压累积导致的时序漂移。最后再分享一个实用技巧如果板子空间允许在每路电源的输出端加一个电压监控芯片比如TPS3808它的PG输出比电源芯片自带的PG更可靠而且可以独立设置延时和阈值。虽然增加了一点BOM成本但能大大简化FPGA侧的时序设计也更容易通过故障注入测试。我在第二批板子上就改成了这个方案实测效果确实更稳。
返回列表