当前位置: 首页 > news >正文

数字IC前端学习笔记:锁存器的综合

相关阅读

数字IC前端专栏https://blog.csdn.net/weixin_45791458/category_12173698.html?spm=1001.2014.3001.5482


        锁存器是一种时序逻辑,与寄存器相比面积更小,但它的存在会使静态时序分析(STA)变得更加复杂,因此懂得什么样的设计会综合出锁存器是很重要的,本文就将对此进行详细介绍。 

显式锁存器

        显式锁存器指的是在连续赋值语句或组合逻辑always结构中,将信号显式赋值给自己时出现的锁存器,一般显式锁存器是有意为之的。

连续赋值语句

最直观的锁存器

图1 D型锁存器

// 例1
module NonLatch1 (input wire d,input wire en,output wire q,output wire qbar
);wire set, rst;assign set =  !(en &  d);assign rst =  !(en & !d);assign q    = !(set & qbar);assign qbar = !(rst & q);endmodule

        图2是例1在Design Compiler 2024中的综合结果,可以看出,即使可以综合,综合工具并没有推断出D锁存器,而是综合为存在组合环(Combinational Loop)或者说反馈的结构。

图2 例1的综合结果

使用条件操作符

// 例2
module NonLatch2 (input wire d,input wire en,output wire q,output wire qbar
);assign q = en ? d : q;assign qbar = !q;
endmodule

        图3是例2的综合结果,可以看出,综合工具也没有推断出D锁存器,而是综合为存在组合环(Combinational Loop)或者说反馈的多路选择器。 

图3 例2的综合结果

always结构

        需要注意的是,这里指的是组合逻辑always结构,而不是边沿控制的时序逻辑always块,对于后者,综合工具会推断出触发器而不是锁存器。

使用条件操作符

// 例3
module Latch1 (input wire d,input wire en,output reg q,output reg qbar
);always @(*) beginq = en ? d : q;qbar = !q;endendmodule

        图4是例3的综合结果,可以看出,综合工具将其综合为D锁存器。 

图4 例3的综合结果

使用if-else语句

// 例4
module Latch2 (input wire d,input wire en,output reg q,output reg qbar
);always @(*) beginif (en) beginq = d; qbar = ~d;endelse beginq = q; qbar = qbar;endendendmodule

        图5是例4的综合结果,可以看出,综合工具将其综合为D锁存器,但与图4有一点区别,原因是发生了在优化过程中发生了相位反转和寄存器合并。  

图5 例4的综合结果

隐式锁存器

        隐式锁存器指的是在always结构中,没有将自己显式赋值给自己,但由于意料之外的因素出现的锁存器。

不完整的敏感列表

// 例5
module NonLatch3 (input wire a,input wire b,input wire c,output reg y
);always @(a) beginy = a & b & c;endendmodule

        例5使用组合逻辑always结构描述了一个三输入与门,但敏感列表中只有a而不含b和c,这导致了只有a发生变化时才会激活always结构。对于以前的综合工具,这会导致锁存器的产生;对于现在的综合工具,其对组合逻辑always结构的综合不依赖敏感列表,因此不会有锁存器产生,但这会导致前/后仿真的不一致,因为对于仿真工具根据敏感列表进行判断,因此行为就像是锁存器。

        图6是例5的综合结果,可以看出,综合工具将其综合为三输入与门。 

图6 例5的综合结果

        实际上,由于不完整的敏感列表带来的风险如此巨大,Verilog 2001标准新加了一个*通配符来形成一个完整的敏感列表。使用通配符意味着always结构中RHS表达式、函数和任务调用的参数、case语句的case expression和case item、if语句的expression信号将自动加入敏感列表,如例6所示。 

// 例6
module NonLatch4 (input wire a,input wire b,input wire c,output reg y
);always @(*) beginy = a & b & c;endendmodule

不完整的if语句

// 例7
module Latch3 (input wire a,input wire b,output reg y
);always @(*) beginif (a) y = b;endendmodule

        例7中的if语句缺少else分支,即当a为0时输出保持不变(这其实与例4等价,只不过例4是显式赋值),这是一个锁存器的行为,图7是例7的综合结果,可以看出,综合工具将其综合为D锁存器。 

图7 例7的综合结果

解决方法1

        保持if语句完整且在每个分支中对所有信号的赋值,如例8所示。

// 例8
module NonLatch5 (input wire a,input wire b,output reg y
);always @(*) beginif (a) y = b;else   y = 1'b0;endendmodule

解决方法2

        在always结构的开头对所有信号赋初值,如例9所示。

// 例9
module NonLatch6 (input wire a,input wire b,output reg y
);always @(*) beginy = 1'b0;if (a) y = b;endendmodule

不完整的case语句

// 例10
module Latch4 (input wire [1:0] sel,input wire a,input wire b,output reg y
);always @(*) begincase (sel)2'b00: y = 1'b0;2'b01: y = 1'b1;endcase
endendmodule

        与例7类似,例10中的case语句缺少case item,即当sel[1]为1时输出保持不变,这是一个锁存器的行为,图8是例10的综合结果,可以看出,综合工具将其综合为D锁存器。 

图8 例10的综合结果

解决方法1

        保持case语句完整且在每个分支中对所有信号的赋值(或者干脆使用case default),如例11所示。

// 例11
module NonLatch7 (input wire [1:0] sel,input wire a,input wire b,output reg y
);always @(*) begincase (sel)2'b00: y = a;2'b01: y = b;2'b01: y = 1'b1;2'b01: y = 1'b0;// default: y = 1'b0;endcase
endendmodule

解决方法2

        在always结构的开头对所有信号赋初值,如例12所示。

// 例12
module NonLatch8 (input wire [1:0] sel,input wire a,input wire b,output reg y
);always @(*) beginy = 1'b0;case (sel)2'b00: y = a;2'b01: y = b;endcase
endendmodule

根本原因

        以上这些无意间综合出的锁存器产生的根本原因是出现了在某些情况下需要保持信号值不变的需求,而又使用了组合逻辑always结构,因此只能使用锁存器实现功能。

        思考一个问题:如果不使用本文提到的这些解决方法,不完整的if语句和case语句一定会综合出锁存器吗?例13会综合出锁存器吗?

// 例12
module Latch_or_Not (input wire sel,input wire a,input wire b,output reg y
);reg [1:0] sel_with_constraint;always @(*) beginif (sel) sel_with_constraint = 2'b00;else     sel_with_constraint = 2'b01;
endalways @(*) beginy = 1'b0;case (sel_with_constraint)2'b00: y = a;2'b01: y = b;endcase
endendmodule

        图9是例13的综合结果,如果这与你想的不一样,想想锁存器产生的根本原因,而不是孤立地看待if语句和case语句。

图9 例13的综合结果

http://www.xdnf.cn/news/351343.html

相关文章:

  • Vue3 + Element Plus 动态表单实现
  • 对PyTorch模块进行性能分析
  • 一种海杂波背景下前视海面目标角超分辨成像方法——论文阅读
  • 【Python 元组】
  • Docker容器启动失败?无法启动?
  • 一些模型测试中的BUG和可能解决方法
  • linux系统管理
  • Java+Selenium+快代理实现高效爬虫
  • 通用外设驱动模型(四步法)
  • 探索大型语言模型的 LLM 安全风险和 OWASP 十大漏洞
  • (x ^ 2 + 2y − 1) ^ 3 − x ^ 2 * y ^ 3 = 1
  • React Native 前瞻式重大更新 Skia WebGPU ThreeJS,未来可期
  • AI客服问答自动生成文章(基于deepseek实现)
  • JAVA简单例题+抽象+继承
  • openssl中BIO的使用
  • PostgreSQL创建只读账号
  • 数据中台建设系列(五):SQL2API驱动的数据共享与服务化实践
  • 游戏引擎学习第266天:添加顶部时钟概览视图。
  • TensorFlow深度学习实战(15)——编码器-解码器架构
  • 可视化图解算法36: 序列化二叉树-I(二叉树序列化与反序列化)
  • 用 Java 实现 哲学家就餐问题
  • 数字信号处理|| 离散序列的基本运算
  • IPv6协议
  • 基于Transformer与SHAP可解释性分析的神经网络回归预测模型【MATLAB】
  • 英文单词 do、play、go 的区别
  • 大模型的RAG技术系列(二)
  • ADV7842KBCZ - 5 富利威长期稳定供应
  • MLX-Audio:高效音频合成的新时代利器
  • 【图片识别内容改名】图片指定区域OCR识别并自动重命名,批量提取图片指定内容并重命名,基于WPF和阿里云OCR识别的解决
  • wpf UserControl 更换 自定义基类