type
date
status
slug
summary
tags
category
password
icon
😀
Verilog HDL, 当下最流行的硬件描述语言之一。一般用于RTL级建模及行为级验证。

Verilog变量类型

两大变量类型:
  • 线网型: 表示电路间的物理连接;
  • 寄存器型: Verilog中的一个抽象的存储数据单元。
需要遵守的规则:
  • 凡是在always和initial语句中赋值的变量,一定是寄存器变量;
  • 在assign中赋值的一定是线网型变量。

线网类型

  • wire、tri: 表示电路间连线,tri主要用于多驱动源建模;
  • wor、trior: 表示该连线具有“线或”功能;
  • wand、triand: 表示该连线具有“线与”功能;
  • trireg: 表示该连线具有总线保持功能;
  • tri1、tri0: 表示当无驱动时,连线状态为1(tri1)和0(tri0);
  • supply1、supply2: 分别表示电源和地信号。
NOTICE:以上类型,除trireg未初始化时为“X”外,其余的未初始化值为“Z”。

寄存器类型

  • reg: 是最常用的寄存器类型,可以是一位或多位,或者是二维数组(存储器);
  • integer: 整型数据,存储一个至少32位的整数;
  • time: 时间类型,存储一个至少64位的时间值;
  • real、realtime: 实数和实数时间寄存器。
存储器声明举例:
与一维的reg变量不同的是,存储器中的存储单元不能再做位选择或部分选择,但每个单元可以单独整体赋值。
integer变量通常用于高层次建模,也常用在for语句的索引中,例如:
此外,time变量用于存储和处理系统时间,real和realtime用来存储实数和实数时间。

驱动和赋值(driving and assigning)

  • 线网是被驱动的,该值不被保持,在任意一个仿真步进上都需要重新计算;
  • 寄存器是被赋值的,且该值在仿真过程中被保持,直到下一个赋值出现。

参数(parameter)

参数是一种常量,通常出现在module内部。它常常被用作定义状态机的状态、数据位宽和延时大小等。
例如:
参数的值可以在编译时改变,因此它经常被用于一些参数可调的模块当中,让用户在实例化模块时,根据需要配置参数。
parameter比`define编译指令更加灵活。

Verilog中的并发与顺序

为了描述硬件的并发性,Verilog语言的module中,所有的描述语句之间都是并行发生的。任何功能描述语言,在Verilog的module中的顺序都不重要。
但是,在语句块(always 和 initial)内部,则可以存在两种语句组:
  • begin…end: 顺序语句组;
  • fork…join: 并行语句组;

操作数、操作符和表达式

操作符

notion image

操作符的优先级

notion image

连接、复制运算符

 

操作数

在verilog语言中,操作数可以是如下几种:
  • 常数
  • 参数
  • 线网
  • 寄存器
  • 向量的位选择
  • 向量的部分选择
  • 存储器单元
  • 系统函数或用户自定义函数调用的返回值。
在Verilog中,无符号数用以下3种形式存在:
  • 线网变量;
  • 一般寄存器变量;
  • 基数格式表示形式的整数常数。
而有符号:
  • 整型寄存器变量;
  • 十进制形式的整型常量。

系统任务和系统函数

在Verilog语言中,预先定义了一些任务和函数,用于完成一些特殊的功能,它们被称为系统任务和系统函数。Verilog能提供的系统任务和系统函数类型如下:
  • 显示任务(display task): $display
    • 文件输入/输出任务(file I/O task): $fopen用于打开一个文件,并返回一个整数的文件指针,然后$fdisplay就可以实用整个文件指针向文件中写入信息,写完后,实用$fclose关闭文件。
    • 时间标度任务(timescale task);
    • 模拟控制任务(simulation control task);
    • 时序验证任务(timing check task);
    • PLA建模任务(PLA modeling task);
    • 随机建模任务(stochastic modeling task);
    • 实数变换函数(conversion function for real);
    • 概率分布函数(probabilistic distribution function)。
    • ………

    描述方式

    Verilog语言中三种最基本的描述方式:
    • 数据流描述
    • 行为描述
    • 结构化描述

    数据流描述

    最基本的数据流描述语句: assign

    对延时进行建模

    例如:
    在一些电路模型中,延时分为最大、典型和最小三种情况,延时信号可以采用min:type:max来表示。

    多驱动源线网

    对wire进行多驱动会出现错误,导致wire变量变为x。

    三态总线功能

    实用tri。

    行为描述

    initial或always过程快(procedual block)

    initial和always语句都是在0仿真时间开始执行。
    举例:

    过程块中的语句

    • 非阻塞过程赋值;
    • 阻塞过程赋值;
    • 连续过程赋值;
    • 高级编程语句。

    时序控制

    在行为描述中的时序控制:
    • 时间语句(“@”): 多个条件语句可以用“,”或“or”隔开,表示任意一个发生皆可;
    • 延时语句(“#”);
    • 等待语句: 用法为wait (expression);//多数综合工具不支持

    过程赋值语句

    所谓过程赋值语句,就是在initial和always语句块中的赋值语句。赋值对象只能是寄存器变量类型。右边的表达式可以使任意操作符的表达式。
    • 阻塞赋值:=,建议在对组合逻辑建模时使用。
    • 非阻塞赋值:<=,通常利用非阻塞赋值的特点来对时序逻辑进行建模。

    过程连续赋值语句

    • assign & deassign: 在过程语句块中对寄存器变量强制赋值和放开;
    • force & release: 在过程语句块中对寄存器或线网进行强制赋值和放开。

    语句组

    • begin…end
    • fork…join

    语句组的标识符

    语句组可以有标识符,也可以没有。当一个语句组有标识符时,在语句组内部可以定义局部变量,而不会传递到语句组的外部。不过,整个变量时静态变量,它的值在整个仿真运行周期中时不变的,但是不会与其他语句组中同一个名称的变量发生冲突。

    高级编程语句

    编程语句只能出现在initial和always的过程块中,共分三大类:
    • if…else;
    • case;
    • 循环语句: forever、repeat、while、for
    if..else
    在进行组合逻辑建模时注意不要引入Latch电路:
    💡
    What is Latch?
    在描述时序逻辑建模时,通常利用if语句的隐式条件对带时钟使能的D触发器建模:
    case
    与if..else语句不同的是,在case语句中,所有被判断的粉质条件都具有一样的优先级。同时,也要考虑到Latch意外产生的情况,不需要break;
    派生语句: casez、casex
    格式如下:
    循环语句
    1. forever: 永远循环
      1. repeat: 执行固定次数
        1. while: 当表达式为真时执行
          1. for: 从初始值开始,如果表达式为真就执行

            结构化描述

            • 实例化门原语;
            • 实例化用户自定义原语(UDP);
            • 实例化模块(module)。

            模块实例化的端口连接规则

            模块内部端口属性:
            • input: 在模块内部默认是一个线网类型;
            • output: 在模块内部是一个寄存器或者线网类型;
            • inout: 在模块内部默认是一个线网类型,是双向信号,一般定义为tri;
            当整个模块被实例化时,与之相连的信号类型如下:
            • 与模块input端口相连: 线网或寄存器;
            • 与模块output端口相连:一定是驱动到一个线网;
            • 与模块inout端口相连:输入时从一个线网驱动来,输出时驱动到一个线网。
            举例:

            参数化模块

            参数的定义

            module中的参数一般是定义其中常量的工具。
            实际上,在Verilog语言中,在实例化模块时,用户可以修改模块中的参数,用来实现不同的特性。这个定制过程通过“新参数直接带入”或“参数重定义”完成。

            参数的定制

            参数的用户定制有两种方法:
            • 通过defparam关键字对模块中的参数重新定义;
            • 参数直接在实例化模块时带入。

            参数用法补充

            参数的声明既可以放到模块头上也可以放在模块内部
            一旦有模块参数被写在模块头部,则出现在模块内部的模块参数被视为本地参数(不能被重写)。
            模块参数重写方式
            本地参数重写关键字
            localparam

            参数疑问?

            • 参数能够用在数据长度表示吗?PARA’b1;
            • 参数能用在{}字符中吗?
            • 不同长度的数据能够相加吗?

            CRC计算与校验电路实例(行为级建模与RTL级建模对比)

            CRC10功能示意图:

            notion image

            CRC10校验,行为级

            当从行为建模的角度来考虑CRC10的实现方式,由于不同考虑代码的硬件实现面积和性能等参数,可以将12 * 32位的数据一次性移入CRC10寄存器中。
            以上实例中,不会考虑代码的硬件实现结果,而是采用最方便、最简洁的方式实现CR10的计算。

            CRC10计算电路,RTL级

            上述实例采用了两层索引方式,将12*32位数据通识一如了CRC10寄存器中,并不考虑实现该电路需要多少时钟周期。但是如果需要设计电路,也就是设计RTL代码,就需要考虑需要多少个时钟周期,实现的寄存器和寄存器之间有多少逻辑级数。
            如果将12*32位数据在一个时钟周期内一次移入CRC10寄存器,组合逻辑数显然过高,因此可以分为12个时钟周期移入CRC10寄存器,每个时钟周期处理32位,这样就可以保证CRC10电路的性能。

            RTL概念与常用RTL建模

            • RTL级语言的重要特性:可综合的表述层次;
              • 对时钟这一个概念的认识过于浅薄了———2023.12.1
            • 综合:指将HDL语言、原理图等设计输入翻译成由与、或、非门等基本逻辑单元组成的门级连接,输出门级网表文件;

            典型RTL设计的三个部分

            • 时钟域描述:描述设计所使用的所有时钟,时钟之间的主从与派生关系,时钟域之间的转换;
            • 时序逻辑描述(寄存器描述):根据时钟沿的变换,描述寄存器之间的数据传输方式;
            • 组合逻辑描述:描述电平敏感信号的逻辑组合方式与逻辑功能;
            RTL描述中 时序逻辑 组合逻辑 的连接关系和拓扑结构决定了设计的性能。

            RTL级代码的设计步骤

            • 功能定义与模块划分;
            • 定义所有模块的接口;
            • 设计时钟域;(这一块十分陌生)
            • 考虑设计的关键路径:关键路径是指设计中时序要求最难以满足的路径。设计的时序要求主要体现在频率、建立时间、保持时间等时序指标上;
            • 顶层设计;
            • FSM设计;
            • 时序逻辑设计:首先根据时钟域规划好寄存器组,然后描述各个寄存器组之间的数据传输方式;
            • 组合逻辑设计;

            常用RTL级建模

            • 非阻塞赋值、阻塞赋值、连续赋值;
            • 寄存器电路建模;
            • 组合逻辑建模;
            • 组合逻辑建模;
            • 存储器建模;
            • 简单的时钟分频电路;
            • 串并转换建模;

            同步复位的优缺点:

            优点:
            • 同步复位利于基于周期机制的仿真器进行仿真;
            • 使用同步复位可以设计100%的同步时序电路,利于时序分析,其综合结果的频率往往较高;
            • 同步复位仅在适中的有效沿生效,可以有效避免因复位电路毛刺造成的亚稳态和错误。在进行复位和释放复位信号时,都是仅当时钟沿采到复位信号电平变化时才进行相关操作,如果复位信号树的组合逻辑出现了某种毛刺,此时时钟沿采样到毛刺的概率非常低,通过时钟沿采样,可以十分有效地过滤复位电路组合逻辑产生的毛刺,增强电路稳定性;
            缺点:
            • 同步复位的最大问题在于必须保证复位信号的有效时间足够长,从而才能保证所有触发器都能够有效地复位。

            异步复位的优缺点:

            优点:
            • 由于多数目标器件(如FPGA和CPLD)和ASIC库的触发器都包含异步复位端口,异步复位会节约逻辑资源;
            • 异步复位设计简单;
            • 度与大多数FPGA,都有专用的全局异步复位资源(GSR),使用GSR资源,异步复位到达所有寄存器的偏斜最小;
            缺点:
            • 异步复位的作用和释放与时钟沿没有直接关系,在异步复位生效时问题并不明显,但是当异步复位释放时,如果异步复位信号释放时间和时钟的有效沿到达时间几乎一致,则容易造成触发器输出为亚稳态,造成逻辑错误;
            • 如果异步复位树的组合逻辑产生了毛刺,则毛刺的有效沿会使触发器误复位,造成严重的逻辑错误;

            推荐使用的复位电路设计方式

            1. 推荐的复位电路设计方式是异步复位,同步释放。这种方式可以有效地继承异步复位设计简单的优势,并克服异步复位的上述风险与缺陷;
            1. 在FPGA/CPLD等可编程逻辑器件中,使用异步复位,同步释放可以节约器件资源,并获得稳定可靠地复位效果,是推荐的复位设计方式。
            举例:
            先利用clk对rst_进行一次取样,在利用reset_reg进行复位,实现了异步复位同步化;
             

            case & if…else建模

            • case语句是“平行的”结构,每个case分支的条件判断和执行都是并行的,没有“优先级”;
            • if…else if…else if…语句可以建模无优先级的判断结构,if…if…if…结构可以建模具有优先级的判断结构;
            • 建立优先级结构会消耗组合逻辑资源;

            可综合的Verilog语法子集

            常用RTL语法结构列举如下:

            1. 模块声明:module…endmodule
            1. 端口声明:input、output、inout
            1. 信号类型:wire、reg、tri等,integer通常用于for语句中的索引
            1. 参数定义:parameter
            1. 运算操作符
            1. 比较判断
            1. 连续赋值:assign、?:
            1. always模块
            1. 语法分隔符:begin…end
            1. 任务定义:tast…endtask
            1. 循环语句:for

            学习疑问

            1. 什么是毛刺现象?为什么同步逻辑能够避免毛刺现象的影响?
            1. 异步逻辑为什么与同步逻辑相比并不可靠?其设计为什么要比同步逻辑要简单?

            RTL设计与编码指导

            一般性指导原则

            面积和速度的平衡与互换原则

            • 从理论上来讲,如果一个设计的时间余量较大,所能跑的频率远远高于设计要求,那么就能通过功能模块复用减少整个设计消耗的芯片面积;
            • 反之,如果一个设计的时序要求很高,普通方法达不到设计频率,那么一般可以通过将数据流串/并转换,并行复制多个操作模块,对整个设计采取“乒乓操作”和“串/并转换”的思想进行处理,在芯片输出模块处在进行“并/串转换”处理。

            硬件原则

            HDL语言便于描述的3大硬件特性:
            • 互连;
            • 并发;
            • 时间;
            HDL语言设计与其他软件语言不同,其本质是为了描述真实的硬件电路,因此,在进行编码时,必须要对所涉及的硬件电路胸有成竹,再用适当的HDL语言进行表达。
            在系统上复用模块节省的面积远比在代码上小打小闹来的实惠多。

            系统原则

            系统原则要求设计者将目标器件看做一个系统,对系统中的每个单元进行有效地

            同步设计原则和多时钟处理

            异步时序设计与同步时序设计

            异步电路与同步电路的异同
            。。。

            同步时序设计

            同步时序设计的基本原则是使用时钟沿触发所有的操作。如果所有寄存器的时序要求(Setup、Hold时间等指标)都能够满足,则同步时序设计与异步时序设计相比,在不同的PVT(工艺、电压、温度)条件下能获得更佳的系统稳定性与可靠性。
            同步设计中,稳定可靠的数据采样必须遵从以下两个基本条件:
            • 在有效时钟沿到达前,数据输入至少已经稳定了采样寄存器的Setup时间之久,这条原则简称满足Setup时间原则;
            • 在有效时钟沿到达后,数据输入至少还将稳定保持采样寄存器的Hold时间之久,这条原则建成满足Hold时间原则;
            同步时序设计有以下几个注意事项:
            • 异步时钟域的数据转换;
            • 组合逻辑电路的设计方法;
            • 同步时序电路的时钟设计;
            • 同步时序电路的延迟。

            亚稳态

             
            Shellmake