System Verilog如何检测信号是否持续保持高电平数微秒
检测指定信号持续高电平达指定微秒数的实现方案
首先纠正一个常见误解:SVA并非只能检测单个时间戳的电平状态,它原生支持跨时间区间的时序逻辑校验,完全可以满足你的检测需求。以下分不同使用场景给出可行方案:
方案1:SVA实现(仅适用于仿真验证场景)
利用SVA的throughout关键字、时间延迟语法,可以非常简便地实现持续高电平检测,示例代码如下:
// 假设仿真时间单位为1ns/1ps,需要检测sig持续高电平至少2us property sig_high_duration; // 触发条件:信号上升沿 $rose(sig) |-> // 检测规则:从触发点开始的2us范围内,sig全程保持高电平 sig throughout ##2us 1'b1; endproperty // 绑定断言检查,不满足时打印错误 ASSERT_SIG_HOLD_2US: assert property(sig_high_duration) else $error("Signal high duration is less than 2us");
如果需要适配不同的检测时长,直接修改##后面的时间参数即可,不需要调整其他逻辑。
方案2:RTL计数器实现(可综合,适用于FPGA/ASIC实际电路)
如果是要在硬件电路中实现该检测逻辑,可以通过计数器方案实现,核心逻辑是对高电平的持续周期做计数,达到目标值后输出检测成功标记。
示例Verilog代码如下:
module high_duration_detect #( parameter CLK_FREQ_MHZ = 50, // 输入时钟频率,单位MHz parameter TARGET_US = 2 // 需要检测的高电平持续时长,单位us )( input clk, input rst_n, input sig_in, // 待检测信号 output detect_done // 检测成功标记,拉高表示已达到目标时长 ); // 计算计数最大值:时钟周期(1/CLK_FREQ_MHZ us) * 计数值 = TARGET_US localparam CNT_MAX = CLK_FREQ_MHZ * TARGET_US - 1; reg [$clog2(CNT_MAX + 1) - 1:0] cnt; // 打两拍处理异步信号,避免亚稳态 reg sig_d1, sig_d2; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin sig_d1 <= 1'b0; sig_d2 <= 1'b0; end else begin sig_d1 <= sig_in; sig_d2 <= sig_d1; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin cnt <= 'd0; end else if(!sig_d2) begin // 信号拉低,复位计数器 cnt <= 'd0; end else if(cnt < CNT_MAX) begin // 信号为高且未计满,继续计数 cnt <= cnt + 1'd1; end end // 计数值达到最大值时输出检测成功 assign detect_done = (cnt == CNT_MAX); endmodule
该方案可以直接综合成硬件电路,调整CLK_FREQ_MHZ和TARGET_US两个参数即可适配不同的使用场景。
方案3:异步电路实现(无时钟场景适用)
如果是没有系统时钟的异步设计,可以将待检测信号一路直接输入与门,另一路经过N微秒的延时单元后输入与门,与门输出为高即代表信号持续高电平达到N微秒。该方案受工艺、温度、电压偏差影响较大,仅建议在精度要求不高的场景使用。
内容的提问来源于stack exchange,提问作者d4mb
相关产品推荐
相关产品推荐

