同一模块中时钟正负沿always块的正确改写方案咨询
时钟正负沿触发模块的正确改写方法
问题背景
了解到同一模块中不要混用同一时钟的上升沿(posedge)和下降沿(negedge)触发(可综合但分析难度大),于是尝试将原有的分别使用always @(posedge clk)和always @(negedge clk)的代码,改写为单个always @(posedge clk)块内的逻辑,但改写后波形与原代码不一致。现附上相关代码,寻求正确改写方案。
原代码(正负沿混用版本)
`timescale 1ns / 1ps module DEFF ( input clk, reset, in, output out ); reg trig1 = 0, trig2 = 0; assign out = trig1 ^ trig2; always @(posedge clk, posedge reset) begin if (reset) trig1 <= 0; trig1 <= in^trig2; end always @(negedge clk, posedge reset) begin if (reset) trig2 <= 0; trig2 <= in^trig1; end endmodule
改写后代码(存在问题)
module DEFF ( input clk, reset, in, output out ); reg clk_prev = 1'b0; reg trig1 = 0, trig2 = 0; reg pos_edge_detected = 0; reg neg_edge_detected = 0; assign out = trig1 ^ trig2; always @(posedge clk, posedge reset) begin if (reset) begin trig1 <= 0; trig2 <= 0; end else begin trig1 <= in ^ trig2; if (!trig1) begin trig2 <= in ^ trig1; end end end endmodule
测试平台
`timescale 1ns / 1ps module TB_DEFF; // Inputs reg clk; reg reset = 0; reg in; // Outputs wire out; // Instantiate the Unit Under Test (UUT) DEFF DUT ( .clk(clk), .reset(reset), .in(in), .out(out) ); always #5 clk = ~clk; // Toggle the clock and input initial begin clk = 0; reset = 1; in = 0; #10 reset = 0; #10 in = 1; #20 in = 0; #20 in = 1; #20 in = 0; #20 $finish; end endmodule
正确改写方案
原代码核心是trig1在时钟上升沿更新、trig2在下降沿更新,且两者互相依赖。要合并到单个上升沿块中,关键是在上升沿逻辑中检测并模拟下降沿的时序行为,具体实现如下:
修正后的代码
`timescale 1ns / 1ps module DEFF ( input clk, reset, in, output out ); reg trig1 = 0, trig2 = 0; reg clk_prev = 1'b0; // 记录上一个时钟周期的电平,用于检测下降沿 assign out = trig1 ^ trig2; always @(posedge clk, posedge reset) begin if (reset) begin trig1 <= 1'b0; trig2 <= 1'b0; clk_prev <= 1'b0; end else begin // 检测下降沿:上一个时钟为高、当前为低,说明两个上升沿之间发生了下降沿 if (clk_prev == 1'b1 && clk == 1'b0) begin // 执行原下降沿逻辑:用当前trig1的值更新trig2 trig2 <= in ^ trig1; end // 执行原上升沿逻辑:用当前trig2的值更新trig1 trig1 <= in ^ trig2; // 更新上一个时钟的电平记录 clk_prev <= clk; end end endmodule
关键说明
- 下降沿检测:通过
clk_prev记录上一个上升沿时的时钟电平,当clk_prev=1且当前clk=0时,即可判断两个上升沿之间发生了下降沿。 - 时序匹配:先处理下降沿的
trig2更新,再处理上升沿的trig1更新,完全匹配原代码中"上升沿更新trig1→下降沿更新trig2"的时序逻辑,确保波形一致。 - 可综合与易分析:这种写法仅使用时钟上升沿触发,避免了正负沿混用的问题,同时保持原有功能,更便于时序分析和维护。
内容的提问来源于stack exchange,提问作者kyw
相关产品推荐
相关产品推荐

