FPGA设计心得(2)边沿检测的问题进一步说明(仿真中一定能得到上升沿的设计)

举报
李锐博恩 发表于 2021/07/15 02:00:45 2021/07/15
【摘要】 文章目录 背景新检测方法旧检测方法改进旧检测方法 设计介绍设计代码仿真情况仿真图 最后想提出的问题同行邀请工程分享 背景 关于边沿检测,写过的博文也很多,不下于4篇了,当然都是学习过程中边学边记的,过了那么久设计的沉淀,又过了一个疫情的荒诞时光,安静下来,还谈一下这个问题,并给出一种新的写法(其实都是一个原理)。也许你觉得不值一提,但总会有点意义...

背景

关于边沿检测,写过的博文也很多,不下于4篇了,当然都是学习过程中边学边记的,过了那么久设计的沉淀,又过了一个疫情的荒诞时光,安静下来,还谈一下这个问题,并给出一种新的写法(其实都是一个原理)。也许你觉得不值一提,但总会有点意义。

新检测方法

这种写法在Vivado中进行行为仿真时,tb文件中,即使在上升沿给0变1数据,也能检测到边沿。如下:

initial begin //sys_rst = 1; vio_txen = 0; #7 //sys_rst = 0; @(posedge sys_clk) vio_txen = 1; # 64 vio_txen = 0; // #26 // @(posedge sys_clk) vio_txen = 1; // # 20 vio_txen = 0; end // initial

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

李锐博恩

真正实现了边沿的检测。
对于tb文件中不在0到1时给输入数据,更不在话下:

  initial begin //sys_rst = 1; vio_txen = 0; #7 //sys_rst = 0; @(negedge sys_clk) vio_txen = 1; # 64 vio_txen = 0; #26 @(posedge sys_clk) vio_txen = 1; # 20 vio_txen = 0; end // initial

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述总之,检测能力一流!

旧检测方法

我们最常用的边沿检测方式,以上升沿检测为例,大概就是对输入数据寄存一拍,然后用寄存后的数据取反,逻辑与上输入数据:

//____________________code start___________________

module rise_detect_traditionnal( input sys_clk, input sys_rst, input vio_txen, output vio_txen_rise

); reg vio_txen_r		; //------------------Code Start Here-----------------// always @ (posedge sys_clk or posedge sys_rst)
		begin if(sys_rst) vio_txen_r <= 1'b0 ; else vio_txen_r <= vio_txen ;
		end assign vio_txen_rise = ~ vio_txen_r & vio_txen;

endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

这种方法诚然没有问题,但存在让人迷惑的地方,在vivado仿真时候,如果输入数据是在时钟上升沿从0到1的一个数据,那么就看不到检测的上升沿:
测试文件同上!
仿真图如下:
在这里插入图片描述可见,后一个上升沿没有检测到。
当然这种问题的解释也在上一篇博客的最后讲到了。

改进旧检测方法

当然对于上一种旧检测方案的改进是,首先将待检测数据同步到时钟域内,之后再寄存一拍,最后用同步数据和寄存数据取上升沿检测逻辑。也就是打两拍,保证没有问题。这也是最最标准且常见的。
如下:

module rise_detect_improved(
	input sys_clk, input sys_rst, input vio_txen, output vio_txen_rise );

	reg vio_txen_r1;
	reg vio_txen_r2;

	always @(posedge sys_clk) begin if (sys_rst) begin vio_txen_r1 <= 0; vio_txen_r2 <= 0; end else begin vio_txen_r1 <= vio_txen; vio_txen_r2 <= vio_txen_r1; end 
	end //always

	assign vio_txen_rise = (~vio_txen_r2)& vio_txen_r1;
endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

仿真图如下:
在这里插入图片描述可见,没有任何问题,这种也是我最喜欢用的方式。

设计介绍

背景已经把所有的基本上都讲了,这里主要提的还是今天博客的主题,就是一种新写法。可能在你眼里不是新写法,但请考虑下萌新哈。

设计代码



module rising_detect( input sys_clk, input sys_rst, input vio_txen, output reg vio_txen_rise

); wire vio_txen			;
	reg vio_txen_r		; //------------------Code Start Here-----------------// always @ (posedge sys_clk or posedge sys_rst)
		begin if(sys_rst) vio_txen_r <= 1'b0 ; else vio_txen_r <= vio_txen ;
		end always @ (posedge sys_clk or posedge sys_rst)
		begin if(sys_rst) vio_txen_rise <= 1'b0 ; else if((~vio_txen_r) & vio_txen) vio_txen_rise <= 1'b1 ; else vio_txen_rise <= 1'b0 ;
		end

endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

仿真情况

module rise_detect_tb();
	//______________ wire and reg definition ___________________________________ reg sys_clk; reg sys_rst; reg vio_txen; wire vio_txen_rise; //____________________ simulation code start _______________________________ //____________________generate system clock ________________________________ initial begin sys_clk  = 0; forever begin # 5 sys_clk = ~sys_clk; end // forever  end // initial //______________________ generate input data ________________________________ initial begin sys_rst = 1; vio_txen = 0; #7 sys_rst = 0; @(negedge sys_clk) vio_txen = 1; # 64 vio_txen = 0; #26 @(posedge sys_clk) vio_txen = 1; # 20 vio_txen = 0; end // initial //_____________________ instantiation the design under test ___________________ rising_detect inst_rising_detect
		( .sys_clk (sys_clk), .sys_rst (sys_rst), .vio_txen (vio_txen), .vio_txen_rise (vio_txen_rise)
		); endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

仿真图

在这里插入图片描述

最后想提出的问题

各位有没有注意到这个仿真图:
在这里插入图片描述延迟一拍的数据和原数据一致,但是为什么还可以产生正常的上升沿检测结果?
放大看看:
在这里插入图片描述
评论区留言,提出你的见解呗?

同行邀请

FPGA/IC技术交流2020

工程分享

在这里插入图片描述
链接
提取码:48ka

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/106028122

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。