verilog语言编写规范笔记_华为

一、命名规则
   
二、Modules
1. 顶层模块应只是内部模块间的互连。除了内部的互连和模块的调用外,尽量避免再做逻辑,如不能再出现对reg变量赋值等,这样做的目的是为了更有效的综合。因为
    在顶层模块中出现中间逻辑 Synopsys 的design compiler 就不能把子模块中的逻辑综合到最优。
2. 每一个模块应在开始处注明文件名、功能描述、引用模块、设计者、设计时间及版权信息等。
   
3. 不要对Input进行驱动, 在module 内不要存在没有驱动的信号 更不能在模块端口中出现没有驱动的输出信号 避免在仿真或综合时产生warning 干扰错误定位。
4. 每行应限制在80个字符以内,以保持代码的清晰、美观和层次感。一条语句占用一行,如果较长(超出80个字符),则要换行。
5. 电路中调用的module名用Uxx标示。向量大小表示要清晰 采用基于名字(name_based)的调用而非基于顺序的(order_based)。
   
6. 用一个时钟的上沿或下沿采样信号,不能一会儿用上沿,一会儿用下沿。如果既要用上沿又要用下沿,则应分成两个模块设计。建议在顶层模块中对Clock做一非门,
     在层次模块中如果要用时钟下沿就可以用非门产生的Posedge Clk_ ,这样的好处是在整个设计中采用同一种时钟沿触发,有利于综合。(基于时钟的综合策略 )
7. 在模块中增加注释。
8. Module 名要用大写标示,且应与文件名保持一致。
   
9.  严格芯片级模块的划分。
    只有顶层包括IO引脚(pads) ,中间层是时钟产生模块、JTAG、 芯片的内核(CORE),这样便于对每个模块加以约束仿真,对时钟也可以仔细仿真。
10. 模块输出寄存器化
      对所有模块的输出加以寄存(如图1 ),使得输出的驱动强度和输入的延迟可以预测,从而使得模块的综合过程更简单。
     - 输出驱动的强度都等于平均的触发器驱动强度
    
11. 将关键路径逻辑和非关键路径逻辑放在不同模块。
       保证DC可以对关键路径模块实现速度优化,而对非关键路径模块实施面积优化。在同一模块DC无法实现不同的综合策略。
12. 将相关的组合逻辑放在同一模块。有助于DC对其进行优化,因为DC通常不能越过模块的边界来优化逻辑。
三、Net and Register 
1. 一个reg变量只能在一个always语句中赋值。
2. 向量有效位顺序的定义一般是从大数到小数。推荐Data[4:0]这种格式的定义。
3. 对net和register类型的输出要做声明 (在PORT中)。如果一个信号名没做声明 Verilog将假定它为一位宽的wire变量。
4. 线网的多种类型。寄存器的类型。
四、Expressions
1. 用括号来表示执行的优先级,尽管操作符本身有优先顺序但用括号来表示优先级对读者更清晰,更有意义。
     If ((alpha < beta) && (gamma >= delta)).... 比下面的表达更合意  
     If (alpha < beta && gamma >= delta)...
2. 用一个函数(function)来代替表达式的多次重复
五、IF 语句
1. 向量比较时,比较的向量要相等。
2. 每一个If 都应有一个else 和它相对应。
3. 应注意If ..else if ...else if ...else 的优先级。
4. 如果变量在If-else 或case 语句中做非完全赋值,则应给变量一个缺省值。
六、case 语句
1. case语句通常综合成一级多路复用器(图的右边部分),而if-then-else则综合成优先编码的串接的多个多路复用器(如图的左边部分)。 通常,使用case 语句要比if语句
快,优先编码器的结构仅在信号的到达有先后时使用。条件赋值语句也能综合成多路复用器,而case 语句仿真要比条件赋值语句快。
2. 所有的Case 应该有一个default case ,允许空语句
    Default :   ;
七、Writing functions
1.   在function的最后给function赋值。
2. 函数中避免使用全局变量,否则容易引起HDL行为级仿真和门级仿真的差异。
    最好直接在端口加以定义 。注意,函数与任务的调用均为静态调用。
八、Assignment
1. Verilog 支持两种赋值:过程赋值(procedural) 和连续赋值(continuous) 。过程赋值用于过程代码(initial, always, task or function)中给reg 和integer变量、time\realtime、
    real赋值,而连续赋值一般给wire 变量赋值。
2. Always @(敏感表),敏感表要完整,如果不完整,将会引起仿真和综合结果不一致。
3. Assign/deassign 仅用于仿真加速,仅对寄存器有用。
4. Force/release 仅用于debug,对寄存器和线网均有用。
5. 避免使用Disable。
6. 对任何reg赋值用非阻塞赋值代替阻塞赋值,reg 的非阻塞赋值要加单位延迟,但异步复位可加可不加。
九、Combinatorial Vs Sequential Logic
1. 如果一个事件持续几个时钟周期,设计时就用时序逻辑代替组合逻辑。
2. 内部总线不要悬空。在default状态,要把它上拉或下拉。
   
十、Macros
1. 为了保持代码的可读性,常用“`define“做常数声明。
2. 把“`define”放在一个独立的文件中。
    参数 parameter 必须在一个模块中定义,不要传替参数到模块(仿真测试向量例外),“`define”可以在任何地方定义,要把所有的“`define”定义在一个文件中,
    在编译原代码时首先要把这个文件读入。如果希望宏的作用域仅在一个模块中,就用参数来代替。
十一、Comments
1. 对更新的内容更新要做注释。
2. 在语法块的结尾做标记。
3. 每一个模块都应在模块开始处做模块级的注释(参考前面标准模块头)。
4. 在模块端口列表中出现的端口信号,都应做简要的功能描述。
十二、FSM
1. VerilogHDL状态机的状态分配
    VerilogHDL描述状态机时必须由parameter分配好状态,这与VHDL不同,VHDL状态机状态可以在综合时分配产生。
2. 组合逻辑和时序逻辑分开用不同的进程。
   组合逻辑包括状态译码和输出,时序逻辑则是状态寄存器的切换。
3. 必须包括对所有状态都处理,不能出现无法处理的状态,使状态机失控。
4. Mealy机的状态和输入有关,而Moore机的状态转换和输入无关。
十三、代码编写中容易出现的问题
1. 在for-loop中包括不变的表达式,浪费运算时间。
2. 资源共享问题
    条件算子中不存在资源共享,如 z = (cond) ? (a + b) : (c + d);   必须使用两个加法器;
     而等效的条件if-then-else语句则可以资源共享,如
     
       只要加法器的输入端复用,就可以实现加法器的共享,使用一个加法器实现。
3. 由于组合逻辑的位置不同而引起过多的触发器综合。
4. 谨慎使用异步逻辑。
5. 对组合逻辑的描述有多种方式,其综合结果是等效的。
6. 考虑综合的执行时间  
    通常会推荐将模块划分得越小越好,事实上要从实际的设计目标、面积和时序要求出发。好的时序规划和合适的约束条件要比电路的大小对综合时间的影响要大。
    最好在设计阶段就做好时序规划,通过综合的约束scripts来满足时序规划。从代码设计讲,500~5000行的长度是合适的。
7. 避免点到点的例外
    所谓点到点例外(Point-to-point exception),就是从一个寄存器的输出到另一个寄存器的输入的路径不能在一个周期内完成。多周期路径就是其典型情况。
    避免使用多周期路径,如果确实要用,应将它放在单独一个模块,并且在代码中加以注释。 
8. 避免伪路径(False path)
    伪路径是那些静态时序分析(STA) 认为是时序失败,而设计者认为是正确的路径。通常会人为忽略这些warning ,但如果数量较多时,就可能将其他真正的问题错
    过了。
9. 避免使用Latch 
     使用Latch必须有所记录,可以用All_registers -level_sensitive来报告设计中用到的Latch。不希望使用Latch时,应该对所有输入情况都对输出赋值,或者将条件赋值语
     句写全,如在if语句最后加一个else,case语句加defaults。当你必须使用Latch时,为了提高可测性,需要加入测试逻辑。
10. 避免使用门控时钟
      使用门控时钟(Gated clock)不利于移植,可能引起毛刺,带来时序问题,同时对扫描链的形成带来问题。门控钟在低功耗设计中要用到,但通常不要在模块级代码中使
      用。可以借助于Power compiler来生成,或者在顶层产生。
11. 避免使用内部产生的时钟
       在设计中最好使用同步设计。如果要使用内部时钟,可以考虑使用多个时钟。
12. 避免使用内部复位信号
       模块中所有的寄存器最好同时复位。如果要使用内部复位,最好将其相关逻辑放在单独的模块中,这样可以提高可阅读性。
13. 如果确实要使用内部时钟,门控时钟,或内部的复位信号,将它们放在顶层。
      将这些信号的产生放在顶层的一个独立模块,这样所有的子模块分别使用单一的时钟和复位信号。一般情况下内部门控时钟可以用同步置数替代。例如:
     
 
参考:大规模逻辑设计指导书_华为




posted @ 2013-04-04 20:41  茜茜的技术空间  阅读(2032)  评论(0编辑  收藏  举报