数字系统设计复习笔记:第八篇
可综合的Verilog
可综合的HDL的语法只是它们自己语言的一个子集。为什么要这么做?
- 减少综合的次数或运行时间,最快得到良好的综合结果
- 采用比较简单的综合约束就可以得到时序和面积的要求
- 提高综合结果网表的性能,简化静态时序分析的过程
什么是逻辑综合?
- 逻辑综合是在标准单元库和特定的设计约束的基础上,把设计的高层次描述转换成优化的门级网表的过程。
- 标准单元库可以包含简单的单元,如:与非门、或非门、与门和或门等基本逻辑门,也可以包含宏单元,如加法器、多路选择器和触发器等。
综合的一般原则
- 综合之前一定要进行仿真,这是因为仿真会暴露逻辑错误,所以建议大家这样做。如果不做仿真,没有发现的逻辑错误会进入综合器,使综合的结果产生同样的逻辑错误。
- 每一次布局布线之后都要进行仿真,在器件编程或流片之前要做最后的仿真。
- 用 VerilogHDL 描述的异步状态机是不能综合的,因此应该避免用综合器来设计;如果一定要设计异步状态机,则可用电路图输入的方法来设计。
- 如果要为电平敏感的锁存器建模,使用连续赋值语句是最简单的方法。
语言指导原则
- 组合逻辑使用阻塞赋值语句描述
- 时序逻辑使用非阻塞赋值语句描述
可综合、不可综合?
可进行逻辑综合的VerilogHDL结构
- 端口:input, inout, output
- 参数:parameter
- 模块定义:module
- 信号变量:wire, reg, tri;允许使用向量表示
- 调用(实例引用):module instance, gate instance
- 函数和任务:function, task;不考虑时序结构
- 过程:always, if, else, case, casex, casez;
- 过程块:begin...end,命名块,disable
- 数据流:assign;不考虑延时
- 循环:for, while, forever;while和forever必须包含@(posedge clock)或@(negedge clock)
几乎所有的操作符都可以被综合,除了两兄弟......?
答案
=== !==
不可综合的Verilog关键字
- time、defparam(不一定支持)、fork、join、initial、wait
- 各种延时
- UDP
- 循环语句: repeat forever while
- 过程持续赋值: assign deassign force release
小心锁存器
always always...
always
的敏感列表一定要写全。不然,总是会产生透明锁存器。这是非常非常糟糕的。
1 | input a, b, c; |
此外,不能混用沿触发和电平触发。
但是上升沿和下降沿可以混用,不过并不推荐。
写全所有可能情况
注意'bx
和n'bx
的用法。
避免在综合时引入锁存器的方法
- 组合函数的输出必须在每个可能的控制路径中被赋值
- 每次执行always块时,在生成组合逻辑的always块中赋值的所有信号都必须有明确的值
- 组合电路的每一个if描述语句都对应一个else语句
- 每一个case语句都对应一个default语句(在没有优先级的情况下优先使用,设计路径延时要小于if-else)
可综合的Verilog HDL模块实例
组合逻辑电路
指令译码电路
1 |
|
比较器
1 | module compare ( |
3-8译码器
1 | module decoder ( |
8-3编码器
1 | module encoder1 ( |
时序逻辑电路
八位计数器
1 | module counter2( out, cout, data, load, cin, clk); |
移位寄存器
1 | module shifter( din, clk, clr, |
良好的Verilog可综合代码风格
- 采用异步复位,控制电路中所有的FF和latch的异步置位或者清零;
- 只使用时钟的上升沿/或下降沿;
- Reset, set, Clock采用clean信号(或者外部输入信号);采用gated clock时要保证信号没有glitch;
- vector range的定义采用descending order;
- 模块调用采用显式端口连接,并保持与模块定义中端口顺序一致;
- 模块端口定义按照input、output顺序;
- 芯片内部模块避免使用inout端口;
- reg变量禁止在多个always块中赋值(除了三态总线,最好三态总线也避免使用);
- FSM至少采用两个进程描述,分别产生组合逻辑和时序逻辑,状态编码使用
parameter
语句; - always语句中的敏感量表要完整,但也不要多余;
- verilog组合逻辑描述不要引起多余的或者不期望的Latch;
- 除了仿真调试用的语句外,要采用可综合的描述。仿真调试用的部分可以加注编译指令
synopsys translate_off
; - 组合逻辑采用阻塞赋值(=),时序逻辑采用非阻塞赋值(<=);
- 一个block中不要混合使用阻塞和非阻塞赋值;
- 复杂表达式要采用括号分割;
- 每行只写一个verilog语句;
- 每个子模块的输出信号最好是DFF的寄存输出;
- 尽可能不要对信号赋值x,不要使用casex语句;
- 注释:采用简洁的注释,包括文件头注释,语句模块注释;文件头注释应包括:Filename,Author、VersionHistory,Function Description,parameter等;
好的代码风格可以加快综合速度!
1 | always@(a or b or in1 or in2) |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Esing的小站!
评论
WalineGitalk