IC设计——Verilog HDL学习笔记

导读:本篇文章讲解 IC设计——Verilog HDL学习笔记,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    小生才疏学浅,孤陋寡闻,下文若有不当之处,还请赐教

1 代码编写

1. 编写规范  

  • 排版
    input,output,inout,reg,wire,parameter不缩进,且每次声明各占一行;
    always,task,function不缩进;
    输入输出信号的宽度定义与关键字之间,信号名与宽度间用空格分开;相同类型的定义对齐;
    always中一般要用begin end区分,if else中仅有一个语句时,不使用begin end
  • 命名风格
    端口,信号,变量名所用字母小写,若含义较复杂,可分段描述(三段),如tx_data_val;
    函数名,宏定义,参数定义用大写;
    低电平有效信号,后加”_n”
    无条件寄存的寄存信号在原信号上加ff1,ff2…如data_in_ff1;
    不能用reg作为后缀名,因为综合工具会给寄存器自动加_reg,此时会扰乱网表可读性
  • 表达式书写
    在长式子中适当添加括号;
    赋值时需给常数注明比特宽度
  • 条件判断语句
    if else必须配合使用,case中也要添加default
  • FSM
    状态机的时序逻辑部分和组合逻辑部分要分开写
    推荐使用三段式写法,即两个组合逻辑电路和一个时序逻辑电路
  • 注释
    最好每个always前都要加注释

2.Verilog硬件描述编写

(一)数据类型
Verilog里面出来parameter,整形等类型外,硬件电路类型只有reg和wire两种。输出尽量设置成reg类型,采用寄存器输出方式。原因是组合逻辑输出存在毛刺,寄存器输出非常干净,毛刺较少

由于verilog中没有定义大小(size)整数缺省为32位,因此定义数字最好用完整形式 如8’d50

  1. wire
    线网型,可作任意表达式的输入
    通常做组合逻辑的赋值,即如果某信号出现在assign等号的左边,则该信号必为wire型
    四值系统,取指为0,1,x(未知态),z(高阻态/浮空量)
    出现X的情况通常是信号没有赋值,或者一个变量的赋值有多个来源;
    出现Z的情况通常是wire类型悬空;
  2. reg
    表示“线”或“寄存器”,可做任意表达式的输入
    通常作为时序逻辑的赋值,即如果某信号在always或initial模块中被赋值,则该信号必为reg型
    取指为0,1,x
  3. integer
    表示循环变量,即循环次数
    结合for循环使用
    初值为x
  4. parameter
    定义符号常量
    用标识符代替常量,提高代码可读性
     
  5. 定义数组(reg型的扩展)
    也被称为memory 型数据。在Verilog中通过对reg数据建立数组来对存储器进行建模,verilog中没有多维数组存在,memory型数据是通过扩展reg型数据的地址范围实现的。存储器的地址索引必须是常数表达式(n-1,m-1等必须是常量,符号常量也可以)。

    如:reg      [n-1:0]   array [0:m-1];    //包含了m个n位数据的数组array。
    在这里[n-1:0]定义了存储器中每一个存储单元的大小,即n位寄存器。array名后面的[0:m-1],表示定义的存储器中有多少个这样的寄存器。

(二)语句

  • 条件说明语句(if-else/case)

条件说明语句必须放在always和Initial过程块内部;同时语句必须完整if-else/case-default,否则可能会综合出锁存器。

if else和case的选择:
if else的综合是由与或非门构成的,也可能一组多路选择器;case结构的综合是由一条多路选择器组成。
对于要写出平行结构的条件,优先写成case结构,例如地址译码等;而条件之间由重复和嵌套的情况则写成if else结构

  • always过程语句块
    描述逻辑功能(组合/时序逻辑)
  1. 一个always块的执行需要触发条件
  2. 一个always块可以多次执行
  3. 多个always块并发执行
  4. 单个过程块内是顺序执行的
  5. 多个过程块(包括initial过程块)在仿真一开始便并行执行,他们之间的同步是通过信号的变化(event触发)、对特定事件的等待(时钟周期)或时间(固定延时)来完成。
  6. 分为电平敏感和边沿敏感
    电平敏感:一般描述组合逻辑,敏感列表必须包含所有出现在等式右边和条件中的信号,always块中赋值对象不能出现在等号右边。例如:always @(a or b)、always @(*)等
    边沿敏感:一般描述时序逻辑,等号左边的变量可以出现在等号的右边
  • assign——持续赋值语句

用来描述组合逻辑

  1. 一个assign语句等式右边的变量变化即执行
  2. 一个assign可以多次执行,始终处于活跃状态
  3. 多个assign并发执行
  4. assign和always不可互相嵌套
  5. assign语句中的赋值对象必须是wire型
  • 有限状态机

同步时序逻辑电路的一种描述方式,表示电路状态的一种改变

  • 过程赋值语句:阻塞赋值(=)和非阻塞赋值(<=)

如果后面的赋值语句要等前面的赋值语句完成才执行,称为阻塞,即一个begin/end中的阻塞赋值语句是顺序执行的;
如多条语句同时执行,则称为非阻塞,即一个begin/end中的非组设赋值是并发执行的

        (1)  always块中时序电路建模时,用非阻塞赋值。时序电路中,对于阻塞赋值,硬件没有对应的电路,因而综合结果未知
        (2)  always块中建立时序和组合逻辑电路时,用非阻塞赋值。
        (3)  always块建立组合逻辑模型时,用阻塞赋值。
        (4)  在同一个always块中不要既用非阻塞赋值又用阻塞赋值。
        (5)  不要在一个以上的always块中为同一个reg变量赋值。

(三)符号

  • 某些特殊符号
  1. { }
    表示拼接,{第一位,第二位…};
    {{ }}表示拼接运算,例如:{4{a}}等同于{a,a,a,a};
  2. $
    表示系统任务和函数,用于仿真、调试和验证
    在系统任务名称前加$使之与用户定义的任务和函数相区分,比如常用的$display(显示信号值),$monitor(监视信号值),$time(返回当前仿真时间),$stop(暂停仿真),$finish(结束仿真)等
  3. #
    (1) #(a,b,c…….)表示改变参数型常量(parameter)的值。
    (2) #10 表示延时10个时间单位。
  4. <<和>>
    Verilog中存在移位运算
  5. ^     
    异或,位操作
  6. ~和!
    ~表示位操作,与&、|同类
    !表示逻辑操作,与&&、||同类
  7. === / !==
    判断全等或不等,可包含x,z判断
  8. `
    宏定义标志
  9. 数组: ram[i*8 +: 8]
    从“:”左边索引开始,一共有“:”右边数字的位数,其中 +号是递增,-号是递减,ram[2*8+:8]表示为: ram[23 : 16]
    如addr[20+3:3]表示为:addr[25:3]
  10. 缩减运算符:|   & 等
    参考链接:https://blog.csdn.net/weixin_46022434/article/details/106311870

(四)预编译处理

  • 功能
  1. 对预编译处理命令进行预处理
  2. 通常当宏定义过多时,`include和`define可配合使用,将所有宏定义均放在include的文件中。
  • 预编译处理命令
  1. `include
    将一个源文件包含到另一个源文件中,支持重复使用,资源共享

    格式:`include “文件名”  或`include “路径/文件名”

  2. `define
    使用有意义的名字替代没有意义的数字、符号、表达式——提高可读性,可移植性。即用标识符代表字符串,无论数字还是算术运算符,都被视为“字符串”,在预编译阶段处理时将宏名替换为字符串。
    功能类似parameter,但`define可在模块外使用,而parameter只能在模块内使用

3.testbench编写

参见链接:https://blog.csdn.net/qq_39815222/article/details/108045488

2. verilog代码优化

1 电路结构优化

  • 通过插入寄存器实现电路的流水化,从而提升电路的主频
  • 同步时序逻辑电路和异步电路

能用同步时序逻辑电路就尽量使用同步时序逻辑电路。

在SoC设计中,各个IP和CPU等运行速率不一致,可能会使用多种时钟,从而采用异步时序逻辑电路。

2 代码优化

  • 尽量使用移位操作或加法器替代乘法器,尽量用选择器替代加法器
  • 注意硬件电路算术逻辑计算的特征

参考链接:https://blog.csdn.net/qq_39815222/article/details/111187460

3 编码errors/warnings

  • 编码错误
  1. 信号指定不明

    例如:
    output [31:0] count;      #定义信号
    reg count;

    该写法错误,count会被综合成1 bit。

1. wire和reg型被综合的情况
区分在组合逻辑电路和时序逻辑电路综合情况,组合逻辑主要是由门级网表构成的,时序逻辑主要由门级网表和D触发器构成。

2. 冒险和竞争
    
 一个逻辑门的两个输入端的信号同时向相反方向变化,而变化的时间有差异的现象称为竞争,推荐使用非阻塞赋值或特定的信号延迟来解决同步的问题。
     由竞争而可能产生输出干扰脉冲的现象称为冒险。

3.语句执行顺序

verilog是描述硬件的语言,因此对于代码的执行需要根据电路来理解。always之间均是并行执行;begin-end内是顺序执行,但如果里面是非阻塞赋值(<=),该赋值部分则是并行执行

4. 不可综合的verilog
描述事件的语句,无法用门来实现,如:
===    !==   /    %    delay      Initial     Repeat    forever      wait     fork     join    event

5.全局时钟资源语句

大型设计一般推荐使用同步时序电路。同步时序电路基于时钟触发沿设计,对时钟的周期、占空比、延时和抖动提出了更高的要求。为了满足同步时序设计的要求,一般在FPGA设计中采用全局时钟资源驱动设计的主时钟,以达到最低的时钟抖动和延迟。与全局时钟资源相关的原语常用的与全局时钟资源相关的Xilinx器件原语包括:IBUFG、IBUFGDS、BUFG、BUFGP、BUFGCE、BUFGMUX、BUFGDLL和DCM

IBUFG:输入全局缓冲,是与专用全局时钟输入管脚相连接的首级全局缓冲。所有从全局时钟管脚输入的信号必须经过IBUF元,否则在布局布线时会报错。 IBUFG支持AGP、CTT、GTL、GTLP、HSTL、LVCMOS、LVDCI、LVDS、LVPECL、LVTTL、PCI、PCIX和 SSTL等多种格式的IO标准。

IBUFGDS:IBUFG的差分形式,当信号从一对差分全局时钟管脚输入时,必须使用IBUFGDS作为全局时钟输入缓冲。

BUFG:全局缓冲,它的输入是IBUFG的输出,BUFG的输出到达FPGA内部的IOB、CLB、选择性块RAM的时钟延迟和抖动最小。

BUFGCE:带有时钟使能端的全局缓冲。它有一个输入I、一个使能端CE和一个输出端O。只有当BUFGCE的使能端CE有效(高电平)时,BUFGCE才有输出。

BUFGMUX:全局时钟选择缓冲,它有I0和I1两个输入,一个控制端S,一个输出端O。当S为低电平时输出时钟为I0,反之为I1。需要指出的是BUFGMUX的应用十分灵活,I0和I1两个输入时钟甚至可以为异步关系

BUFGP:相当于IBUG加上BUFG。

BUFGDLL:全局缓冲延迟锁相环,相当于BUFG与DLL的结合。BUFGDLL在早期设计中经常使用,用以完成全局时钟的同步和驱动等功能。随着数字时钟管理单元(DCM)的日益完善,目前BUFGDLL的应用已经逐渐被DCM所取代。

DCM:数字时钟管理单元,主要完成时钟的同步、移相、分频、倍频和去抖动等。DCM与全局时钟有着密不可分的联系,为了达到最小的延迟和抖动,几乎所有的DCM应用都要使用全局缓冲资源。DCM可以用Xilinx ISE软件中的Architecture Wizard直接生成。
 

4 Verilog综合及仿真

  • EDA工具的数字系统设计流程

无论是针对FPGA还是ASIC编写verilog代码,使用EDA工具的流程一般分为一下几步:

  1. 设计输入
  2. 仿真测试
  3. 综合实现
  4. 编程下载
  5. 系统测试
  • verilog仿真器
    仿真器不同,结果可能不同
  1. Verilog-XL:
    cadence开发的解释仿真器,“解释”即有一个运行时间的解释工具执行每一条Verilog指令并且与时间队列进行交流。该仿真器在cadence系统里是一个默认的verilog仿真器,但一直未被cadence更新,不具备verilog的新特点。
  2. NC-Verilog:
    cadence的编译仿真器,把Verilog转换成该程序的定制仿真器,即先转换成C程序,再编译成仿真器。与Verilog-2001大部分兼容。
  3. VCS:
    synopsys开发的编译仿真器,可以与该公司的其他工具集成在一起。兼容Verilog-2001
  • Verilog综合成电路的方法
  1. behavioral(行为级RTL):
    用高层次的Verilog描述所希望的系统行为,随后用综合工具综合成硬件电路。
  2. structural(结构级):
    Verilog完全由一个标准单元库基本门的实例构成。该Verilog可以完全是文本的,或是采用标准库中逻辑门符号的层次化原理图。
  • 编译综合过程
  1. 编译阶段
    工具通过阅读目标代码,进行语法和语义分析,将每个模块分别编入库中
  2. 建模阶段
    工具将各模块按照设计集成关系最终组成顶层模块,主要包括模块例化,接口例化,程序例化,层次集成,计算参数,解决层次信号引用,建立模块连接等。类似软件编译的link阶段。
  3. 仿真阶段
    通过读取建模后的对象文件,建立硬件RTL模型和验证环境,以周期驱动或事件驱动进行仿真。

5. FPGA补充

FPGA中的寄存器是SRAM型

  • FPGA的组成

当今FPGA内部有多中部件,如DSP、BLOCK RAM,BLOCK ROM等,但最基本单元式CLB逻辑块,CLB的组成有查找表LUT,寄存器Flip-flop,多路选择器Mux。

  1. LUT
    用于实现组合逻辑电路,具体作用是存储组合逻辑电路计算的所有结果(因此EDA工具生成的烧进FPGA的是bitstream文件)
  2. Mux
    多路选择,配合LUT实现根据输入选择结果
     

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/82536.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!