dump glitch 毛刺分析 及 异步复位同步释放

本文详细探讨了Verilog中时钟毛刺(glitch)的产生原因、危害以及如何通过示例进行仿真分析。介绍了同步复位的概念,强调了异步复位同步释放的重要性,并提供了防止毛刺的同步复位电路设计。此外,还讨论了时钟切换时可能产生的问题和解决方案。
摘要由CSDN通过智能技术生成

接上一篇:🔗interface clocking block使用 及 verdi capture delta cycle

Glitch: a transition that occurs on a signal before the signal settles to its intended value.

Glitch一般由竞争导致,有些glitch的时间宽度为0,这种glitch需要加上+fsdb+glitch=0dump才可以在波形上查看到。nWave上View -> Display Glitch在波形上*标记glitch 。

Glitch的危害:🔗eetop_为啥时钟毛刺会毁了整个设计 – min pulse width

示例1:
构造一个delta time = 0glitch:

module top;
	logic val;
	initial begin
		val = 0;
		#10;
		val = 1;
	end
	initial begin
		#10;
		val = 0;
	end
	always @(posedge val or negedge val) begin
		$display("time:%0t,val:%b",$realtime,val);
	end
endmodule

打印结果:
time:0,val:0
time:10,val:0
在这里插入图片描述
从波形上可以看到#10处val值的跳变,从 0->1->0。但是display打印结果只有一个,似乎posedgenegedge中有一个没有被捕捉到。

示例2:
其实0->1 1->0的跳变确实在仿真器中发生了,只不过这两个行为都发生在Active区,导致always @(posedge val or negedge val)只被触发一次。
改成如下,分别通过always @(posedge val ) always @(negedge val)两个进程process捕捉,则可以同时打印。

module top;
	logic val;
	initial begin
		val = 0;
		#10;
		val = 1;
	end
	initial begin
		#10;
		val = 0;
	end
	always @(negedge val) begin
		$display("time:%0t,val:%b",$realtime,val);
	end
	always @(posedge val ) begin
		$display("time:%0t,val:%b",$realtime,val);
	end
endmodule

打印结果:
time:0,val:0
time:10,val:0
time:10,val:0

示例3:
将上例中的val = 0改成val <= 0,看看会有怎样的改变。

module top;
	logic val;
	initial begin
		val = 0;
		#10;
		val = 1;
	end
	initial begin
		#10;
		val <= 0;
	end
	always @(posedge val or negedge val) begin
		$display("time:%0t,val:%b",$realtime,val);
	end
endmodule

打印结果:
time:0,val:0
time:10,val:1
time:10,val:0
此时glitchposedge negedge都被捕捉到。=发生在Actice区,<=发生在NBA区。
posedge处的结果val=1,而在示例2中,val=0
在这里插入图片描述

示例4
这次将val变化置于同一个process中。

module top;
	logic val;
	initial begin
		val = 0;
		#10;
		val = 1;
		val = 0;
		#10;
	end
	
	always @(negedge val) begin
		$display("time:%0t,val:%b",$realtime,val);
	end
	always @(posedge val ) begin
		$display("time:%0t,val:%b",$realtime,val);
	end
endmodule

vcs打印结果:
time:0,val:0

和示例1中使用always @(posedge val or negedge val)情况一样,推测vcs对于同一个process的同一个timeslot的同一个region中的同一个参数的调度,只会发生一次。(扯:看上去有点像C编译器对没有使用 voliate修饰寄存器存取而优化了一样

irun打印结果:
time:10,val:0
time:10,val:0

示例5

module top;
	logic val;
	initial begin
		val = 0;
		#10;
		val = 1;
		val = #0 0;
		#10;
	end
	
	always @(negedge val) begin
		$display("time:%0t,val:%b",$realtime,val);
	end
	always @(posedge val ) begin
		$display("time:%0t,val:%b",$realtime,val);
	end
endmodule

打印结果:
time:0,val:0
time:10,val:1
time:10,val:0
和示例3的打印结果一致,#0的事件发生在In-active区,但是delta expand并不支持In-active区的查看,只显示了Active区。

Note:

  1. 上述示例仿真时是否加上+fsdb+delta并不会影响vcs打印结果。
  2. irun仿真时,默认不打印0时刻, 其他结果与vcs一致。(示例4除外
  3. 对于sv调度机制,IEEE规定了一些准则,但是还有一些没有规定,这部分各家EDA工具实现略有差异,存在不确定性Nondeterminism

最后一个实际示例:

module A(input wire clk,
		 input wire rst_n,
		 output wire req_rst);
	reg req_rst_r;
	always @(posedge clk or negedge rst_n) begin
		if(~rst_n)
			req_rst_r <=0;
		else
			req_rst_r <=1;
	end
	assign req_rst = req_rst_r;
endmodule

module delay_sync #(parameter SYNC_DEPTH = 2)
				   (input wire clk,
				    input wire resetn_in,
				    output wire resetn_out);
	reg [SYNC_DEPTH-1:0] in_dly;

	always @(posedge clk or negedge resetn_in) begin
		if(~resetn_in)
			in_dly <= {SYNC_DEPTH{1'h1}};
		else 
			in_dly <= {in_dly[SYNC_DEPTH-2:0],1'b0};
		end
	assign resetn_out = in_dly[SYNC_DEPTH-1];
endmodule

module top;
	logic clk;
	logic rst_n;
	logic resetn_out;

	always #5 clk = ~clk;
	initial begin
		clk = 'b0;
		rst_n = 'b0;
		#12;
		rst_n = 'b1;
	end
	assign reset_n = rst_n & resetn_out;

	A u_A(.clk(clk),
		  .rst_n(reset_n),
		  .req_rst(req_rst));
	delay_sync #(.SYNC_DEPTH(4)) u_delay_sync(
		  .clk(clk),
		  .resetn_in(req_rst),
		  .resetn_out(resetn_out));
	initial begin
		#60;
		$finish();
	end
	initial begin
		$fsdbDumpfile("wave.fsdb");
		$fsdbDumpvars;
	end
endmodule

上述示例module A req_rst请求reset,通过delay_sync延迟4个cycle。glitch发生在module A rst_n信号上。
在这里插入图片描述
在这里插入图片描述
vcs对NBA中的信号分三次调度:

NBA(0): After delay 4 cycle, in_dly[3] transit from 1 to 0, leading assert A.rst_n

NBA(1): in module A, assert rest_nleading dis-assert A.req_rst

NBA(2): in module delay_syncreq_rst as reset signal. dis-assert req_rstleading in_dly[3] transit from 0 to 1, leading dis-assert A.rest_n

Since A.rst_n change 1->0->1in same time slot,result in delta time =0 glitch.

避免上述glitch发生,可以在A.rst_n路径上加上delay。

从波形上看,A.rst_n虽然被采样到了,并触发了reset行为,但是不满足真实器件的恢复时间Recovery time和去除时间Removal time
功能仿真一般不会check Recovery/Removal time,GateSim中可以在Specify block中判断:
在这里插入图片描述
在这里插入图片描述
带SDF的仿真中也可以反标加入 Recovery/Removal time的check:
在这里插入图片描述
在这里插入图片描述
需要保持良好的RTL coding style避免违例。
在这里插入图片描述

恢复时间(Recovery time):与同步电路中的建立时间类似,是指异步控制信号(如寄存器的异步清除和置位控制信号)在“下个时钟沿”来临之前变无效的最小时间长度。这个时间的意义是,异步控制信号在时钟上升沿来临Trecovery时间就要保持稳定,如果保证不了这个最小恢复时间,也就是说“下个时钟沿”来临时,这个异步控制信号不能保证正常执行。
去除时间(Removal time):与同步电路中的保持时间类似,是指异步控制信号(如寄存器的异步清除和置位控制信号)在“有效时钟沿”之后变无效的最小时间长度。这个时间的意义是,异步控制信号在时钟上升沿后仍需保持Tremoval的稳定时间,如果保证不了这个去除时间,也就是说这个异步控制信号的解除与“有效时钟沿”离得太近,那么依旧不能保证这一异步控制信号能正常执行。
————————————————
版权声明:本文为CSDN博主「CLL_caicai」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/CLL_caicai/article/details/104625791

异步复位同步释放

对于RESET的处理,一般采用异步复位同步释放的方式,参考🔗eetop_同步复位电路 reset synchronizer
异步复位同步释放可以通过VC Spgylass CDC进行静态检查,🔗VC Spyglass CDC(四)CDC检查的流程
也可以加入SVA动态仿真检查,🔗assertion for reset synchronous release

通过两级寄存器完成同步,消除亚稳态:
在这里插入图片描述

同步复位电路 reset synchronizer 的输出 rstn_sync 相对于时钟 clk 有一个固定的时序关系。 在 PR (place & route) 中,工具构造 buffer tree 去 buffer rstn_sync,并算出 buffer 后 rstn_sync 到后续每个 D flip flop 复位端的时间,通过插入或调整 buffer, 保障后续电路中每一个 D flip flop 的复位端都满足 removal/recovery 要求。 反之,如果 rstn_sync 相对于时钟 clk 没有有一个固定的关系,那工具就无从下手了,也就无法保障 removal/recovery 要求了。
顺便说一下,综合工具是不查 removal/recovery time 的。 如果复位电路上有错,通常会在设计流程很后面才发现,改起来代价也会高一些。 所以一定要在一开始就重视复位电路。
1.组合逻辑的输出都有毛刺的可能。2. 尽量避免模拟工程师做的时钟电路,避免在clock path用组合逻辑。

常见的形式采用移位寄存器:

module RESET_SYNC #(parameter SYNC_DEPTH = 2)
				   (input wire clk,
				    input wire resetn_in,
				    output wire resetn_out);
	reg [SYNC_DEPTH-1:0] rn_sync;

	always @(posedge clk or negedge resetn_in) begin
		if(~resetn_in)
			rn_sync <= {SYNC_DEPTH{1'h0}};
		else 
			rn_sync <= {rn_sync[SYNC_DEPTH-2:0],1'b1};
		end
	assign resetn_out = rn_sync[SYNC_DEPTH-1];
endmodule

RESET_SYNC可以用于同步复位,也以为用于IP的restndelay于clock之后产生。

时钟切换

真实器件中,glitch不会是delta time =0的,这是仿真的结果。常见的是在assign clk_o = sel ? clk1:clk2;切换时,产生glitch。 参考🔗verilog glitch_free两个时钟切换电路
🔗时钟切换

  • 16
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Holden_Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值