在复杂的FPGA或嵌入式系统设计中,电源管理往往是决定系统稳定性的第一道关卡。你是否遇到过这样的情况:板卡上电瞬间电流过大导致芯片复位,或者因为某些外设供电过早而无法正常通信?这些问题的根源,往往在于电源时序。 今天,我们将通过一个具体的工程案例,使用Verilog设计一个通用的多路电源时序控制器,并利用高效的Testbench进行自动化验证。
一、 什么是电源时序控制?
电源时序控制,顾名思义,就是按照预定的顺序和时间间隔,依次开启系统中的不同电源轨。例如,先开启3.3V的主电源,等待系统稳定后,再开启1.8V的核电源,最后开启1.0V的PLL电源。
它的目的在于:
防止浪涌电流:避免所有电源同时开启造成瞬间电流过大,触发过流保护。
满足器件要求:许多芯片(如FPGA、CPU)严格规定了IO电源和核心电源的上电先后顺序。
二、 模块设计
我们设计的 power_sequence_ctrl 模块是一个高度参数化的IP核,可以轻松集成到任何项目中。
1. 接口与参数
模块设计了三个关键参数,使其具备极强的通用性:
CLK_FREQ_HZ:系统时钟频率,适配不同时钟域。
DELAY_MS:每路电源开启的间隔时间。
POWER_WIDTH:受控电源的路数,默认支持8路。
2. 核心逻辑:FSM状态机
代码内部采用了一个经典的三段式状态机,逻辑清晰且易于维护:
IDLE:复位后的初始状态。
DELAY:核心延迟状态。计数器开始工作,直到达到预设的 DELAY_MS 时间。
POWER_ON:动作状态。将当前对应的电源位置1(拉高使能),并准备切换到下一路。
DONE:完成状态。所有电源均已开启,状态机挂起,保持输出。
代码解析:
// 动态计算计数器位宽,避免资源浪费
localparam CNT_WIDTH = $clog2(DELAY_CNT_MAX + 1);
// 依次置位逻辑,保证已开启的电源不掉电
POWER_ON: o_power_enable[power_idx] <= 1'b1;
这种设计利用 power_idx 索引计数器,配合位操作,实现了类似“移位寄存器”的效果,确保电源开启后能够保持高电平,不会回零。
三、 应用场景
这个模块虽然简单,但在实际工程的应用:
多电压系统:例如CPU系列,需要严格控制各级电压的供电顺序。
高速ADC/DAD采集板:模拟电源通常需要先于数字电源稳定,以防止数字噪声锁存进模拟电路。
电机驱动控制:大功率驱动电源与控制逻辑电源必须分时启动,防止上电瞬间的误动作。
四、 验证Testbench设计
设计只是完成了第一步,验证才是质量的保证。在仿真代码 tb_power_sequence_ctrl 中,展示了“高效验证”的技巧。
1. 参数重载加速仿真
实际工程中,上电间隔可能是1000ms(1秒),这在仿真中跑起来太慢。我们在TB中通过参数重载将间隔改为1ms:
localparam DELAY_MS = 1; // 仿真时缩短延迟
这大大减少了仿真时间,同时验证逻辑完全一致。
2. 自检查机制
TB不靠人眼看波形,而是通过代码自动记录时间并判断:
// 检测上升沿并记录时间
if (o_power_enable[i] && !expected_enable[i]) begin
power_on_time[i] = $time;
expected_enable[i] = 1'b1;
end
验证逻辑会自动计算 当前路开启时间 - 上一路开启时间,并与理论值 TOTAL_DELAY_NS 进行比对。如果误差过大,直接报错。
3. 测试用例
检查1:最终状态是否全为1?
检查2:时间间隔是否符合设计?
检查3:是否存在回沟现象(电平拉高后又变低)?
超时保护:如果状态机卡死,TB会自动超时退出,防止仿真跑飞。
五、如何获取?
关注公众号:我是小灰灰的FPGA,关注我,带你从入门到精通数字逻辑设计。
后台回复(建议复制粘贴):power_sequence_ctrl
77