FPGA知识大梳理(四)FPGA中的复位系统大汇总-转自 清霜一梦
本文整合特权(吴厚航)和coyoo(王敏志)两位大神的博文。我也很推崇这两位大神的书籍,特权的书籍要偏基础一下,大家不要一听我这么说就想买coyoo的。我还是那一句话,做技术就要step by step。闲言少叙,直入正题。
一,异步复位
先看这个电路,就是异步复位的例子。reset使用了reg的复位端
用代码实现的话是这个样子
module reset_test ( clk , rst_n , i_data, o_data ); input clk ; input rst_n ; input i_data ; output reg o_data ; always @ (posedge clk or negedge rst_n) if(!rst_n) o_data <= 1'd0 ; else o_data <= i_data ; endmodule
二,同步复位
首先也是先看电路,这是QuartusPrime15.1综合同步复位程序后的 RTL Viewer
代码如下
module reset_test ( clk , rst_n , i_data, o_data ); input clk ; input rst_n ; input i_data ; output reg o_data ; always @ (posedge clk ) if(!rst_n) o_data <= 1'd0 ; else o_data <= i_data ; endmodule
细心的同学有没有发现,很多的博文里面贴出的电路图,输入端那里不是一个2选1多路选择器,而是一个与门。所以我才说明我的综合器是QuartusPrime15.1。当然这个不是重点,重点是同步复位比异步复位多用了器件。数据也是多穿过一个器件。
对比:
异步复位的优点:1,节省了器件,这个在ASIC中显的尤为重要。2,减小了数据路径的传播延时。提高了系统响应频率。3,即刻生效,不依赖于时钟是否到来。
异步复位的缺点:由于reset信号时序是不定的,reset释放的时候会让异步复位系统出现亚稳态。
同步复位的优点:1,降低了亚稳态的出现。注意是降低了,而不是完全消除。如果reset毛刺或者是触发时间点不在clock上升沿的setup和hold时间内那就万事大吉,可是如果不是这个时间点,依然会有亚稳态。2,有利于时序分析。由于同步的reset信号必须由clock捕获到才有效,所以容易被时序分析工具分析到它的余量slack
同步复位的缺点:1,多使用了器件。2,增加了数据路劲传输时间
节省器件和增大F是asic的必争之地,所以目前大神们也喜欢在它身上进行改进,叫 异步复位的同步释放
3,异步复位的同步释放第一版
此种方式是事先将reset信号打一拍,去除了reset的毛刺同时,reset释放的时候也能实现与clock同步。表面上看可以说是一个完美的方案。
然而问题出来了,一梦君曾经在面试一个岗位的时候被问过这个异步复位同步释放的问题,当我画出电路图的时候,面试官当即问我一句:如果clock挂了,你的系统岂不是还不能复位了?我顿时哑口无言。随后只好说,你说的没错,这个确实没有考虑到。当然我说这个绝对不是想去责怪谁,如果没有这些大神们在博客上奉献着他们的技术资料,我们不可能了解到这么多,只怪自己没有去深究。同时也希望读者们能深究我的博文缺陷。
这里非常感谢白菜小弟,在 FPGA知识大梳理(三)verilogHDL语法入门(2)知识汇总这篇博文中指出 “assign中使用的 blocking ”这一句话的原本意思是想告诉大家assign后面是使用 “=”,而不能使用“<=”。这么理解是没有错,但是表述不对,根据VerilogHDL_2001_standard,assign是Continuous assignments (连续性赋值语句)不存在阻塞非阻塞之分,阻塞非阻塞只针对于procedural assignment(过程性赋值语句) ,所以assign后面当然是“=”。
好了,说了这么多,该回到这个同步复位的异步释放问题上来了
4,改进型的异步复位同步释放
程序是
//`default_nettype none module reset_test ( clock , reset_n , data_a, data_b, out_a, out_b ); input clock,reset_n ; input data_a,data_b ; output out_a,out_b ; reg reg1 ,reg2 ; reg reg3 ,reg4 ; wire rst_n ; assign out_a = reg1 , out_b = reg2 , rst_n = reg4 ; always @ (posedge clock or negedge reset_n) if(!reset_n) begin reg3 <= 1'd0 ; reg4 <= 1'd0 ; end else begin reg3 <= 1'd1 ; reg4 <= reg3 ; end always @ (posedge clock or negedge rst_n) if(!rst_n) begin reg1 <= 1'b0 ; reg2 <= 1'd0 ; end else begin reg1 <= data_a ; reg2 <= data_b ; end endmodule
reg3,reg4 . 异步复位产生rst_n ,由于异步复位的及时性,所有的reg都会复位。reset_n释放后,只有在clock到来之后,VCC传输到rst_n系统才会运转。所以实现了同步释放。
这个样子就万事大吉了吗?还缺一点点。在reset_n前面需要加一个滤波去抖的模块才算完美。如果你觉得有更完美的方案,欢迎提出来!
5,异步复位同步释放PLL版
在绝大多数的 工程中需要使用到PLL,那么有PLL的工程复位系统又有点不一样了哦。
也就是在pll没有准备好的时候,系统还是在复位的状态等待
代码实现是
module reset_test ( clock , reset_n , data_a, data_b, out_a, out_b ); input clock,reset_n ; input data_a,data_b ; output out_a,out_b ; reg reg1 ,reg2 ; reg reg3 ,reg4 ; wire rst_n ; wire pll_clk ,pll_lock; assign out_a = reg1 , out_b = reg2 , rst_n = reg4 ; always @ (posedge clock or negedge reset_n) if(!reset_n) begin reg3 <= 1'd0 ; reg4 <= 1'd0 ; end else if(pll_lock) begin //pll clock is ready reg3 <= 1'd1 ; reg4 <= reg3 ; end else begin reg3 <= 1'd0 ; reg4 <= 1'd0 ; end //data flow ------------------------------- always @ (posedge clock or negedge rst_n) if(!rst_n) begin reg1 <= 1'b0 ; reg2 <= 1'd0 ; end else begin reg1 <= data_a ; reg2 <= data_b ; end altera_pll_0 U_0 ( .areset (!reset_n) , .inclk0 (clock), .c0 (pll_clk), .locked (pll_lock) ); endmodule
这复位算是告一段落了。如果你有更好的设计,请赐教。
最后留下一个小问题,也是一梦君本人之前一直用的复位方式。如下图。 或者是inst(reg3)和inst1(reg4)都没有,直接将pll_locked直接连接到后续data flow部分的reset端。读者自行对比哦,哈哈
转自:清霜一梦 https://www.cnblogs.com/sepeng/p/5263128.html
原文地址:https://www.cnblogs.com/lcq-manji/p/15154202.html
- github 提交报403 forbidden的错误解决
- Apache thrift - 使用,内部实现及构建一个可扩展的RPC框架
- redis主从集群搭建及容灾部署(哨兵sentinel)
- 浅谈ASP.NET的Postback
- redis配置详解(中英文)
- 我所理解的Remoting(1):Marshaling & Activation[下篇]
- 5分钟短视频,带你走进日志易SPL,助你日志分析更容易
- Unity Application Block 1.2 for Silverlight - December 2008
- 算法学堂 - 二分查找及其变形
- Zookeeper权限管理与Quota管理
- 刘鹏:保大还是保小?无人汽车也将面临这样的道德窘境
- 浅谈DNS
- silverlight寻奇 - Graphite
- 程序运算性能测量
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- kbone 是什么?这可能是最好的小程序开源框架
- jQuery根据填写的input的数值导出excel表格
- 小程序根据返回值英文渲染出对应的中文
- redis灵魂拷问:聊一聊AOF日志重写
- 小程序返回的时间戳转化成时间
- JSP 报错:ReferenceError: $ is not defined
- 小程序使用 组件库 vant-weapp详细教程
- DEBUG=1 宏定义对 @weakify 和 @strongify 的影响分析
- 为什么 demangle 会失败?
- js使用webgl
- Java 后台开发面试题分享三
- llvm 对 copy 属性的优化(1)
- Zookeeper 分布式技术入门
- llvm 对 copy 属性的优化(2)
- 为什么 Linux 默认页大小是 “4KB”?