zoukankan      html  css  js  c++  java
  • Verilog HDL笔记

    《设计与验证 Verilog HDL》

    设计与验证的发展历程

    早期:卡诺图设计,面包板验证

    中期:原理图设计,EDA工具仿真验证

    后期:硬件描述语言HDL设计,EDA工具仿真验证

    抽象层次不断提高

    HDL可以从算法/系统级>功能级>行为级>寄存器传输级(RTL)>门级和开关级不同的层次描述数字电路系统。

    通过EDA工具将高层次的电路描述解析到门级等低层次的电路描述(网表)的过程就叫做"综合"(Synthesize),或者称逻辑综合(综合时会根据"约束条件"优化)

    最成熟的综合是RTL级到门级的综合

     

    Verilog不仅定义了语法,还对每个语法结构都清晰定义了仿真语义,从而便于仿真调试

    Verilog集成了C语言的语法结构和操作符,易学易用,具有很强的扩展性

    VHDL(Very High Speed Integrated Circuit HDL,超高速集成电路描述语言)的特点是描述严谨

     

    几种设计方法:

    原理图直观,便于理解,但在大型设计中可维护性差,不利于提高模块重用性

    HDL输入:利于自顶向下设计,利于模块划分和重用,可移植性好,通用性好,设计不因芯片工艺和结构变化而变化,利于向ASIC移植

    波形输入和状态机输入:是最常用的辅助设计方法,EDA工具可自动根据两种输入生成HDL代码,应用受局限,维护性不高

    推荐初学者:首选HDL方式,在某些要求使用图形描述设计顶层的情况下才使用原理图,不要在设计顶层以外的其他层次使用原理图,不要依赖波形设计工具(因为复杂的测试激励无法用波形工具描述)

     

    Verilog和VHDL:

    两者都能胜任数字电路系统设计任务

    VHDL最初用作文档来描述数字硬件的行为,描述性和抽象性更强,更适合描述更高层次(行为级,系统级)

    Verilog最初为更简捷、有效的描述数字电路和仿真而设计,易学易懂

    在这两者基础上又发展处很多更抽象的硬件描述语言:SystemVerilog、Superlog、SystemC、CoWare C等

    Verilog寄存器和线网两种数据类型定义清楚,时序和组合电路描述简洁,能帮助快速了解硬件设计的基本概念。

    但VHDL和Verilog各有所长,并无优劣之分,最重要的是建模方法与思想

    推荐初学者:从Verilog学起

     

    Verilog和C语言:

    区别:

    互连(connectivity):wire型变量配合驱动结构可有效表示网线互连

    并发(concurrency):并行执行

    时间(time):Verilog定义了绝对和相对的时间度量,仿真时可描述信号之间的时间关系

    HDL语言与软件语言(C,C++等)有本质区别,评判HDL代码的最终标准是实现的硬件电路的性能(面积和速度)

    一个硬件设计的最终性能,很大程度上取决于设计工程师所构想的硬件实现方案的合理性

    从软件设计转行的初学者,片面追求代码的整洁、简短是错误的,是与评价HDL的标准背道而驰的

    正确的方法是,首先对所要实现的硬件电路有一个清楚的认识,对硬件结构与连接了解十分清楚,再用HDL语句描述出来

    验证时,常用C语言编写测试向量,与Verilog在仿真器中通信,用于验证

     

    描述分级

    系统级:对系统整体功能和性能指标进行衡量

    功能级:将系统功能划分为可实现的具体功能模块,大致确定模块间的接口,描述每个模块的时序约束

    行为级:明确每个模块所有的接口和边界,模块内部功能,外部接口和行为都已经清晰。常用于编写仿真测试激励(延时描述、监视描述)

    寄存器传输级:不关注寄存器和组合逻辑的细节,使用HDL语言描述寄存器到寄存器间的逻辑功能描述电路——一般对此设计仿真

    门级:目前要直接使用门级描述的情况一般是ASIC和FPGA设计中有面积或时序要求较高的模块

    布局规划与布局布线:门级描述映射到目标器件中

    时序仿真:将布局布线的延时信息反标注到设计网表中进行仿真,简称后仿真。包含门延时和线延时,能较好反映芯片实际工作情况。主要目的是发现时序违规的情况

     

    所有的电路单元是并行工作的,相互之间没有顺序关系,即使是最小的单元也是如此

    模块中只有定义了时钟边沿的行为是与跳变沿有关的,其余(例如+,-,×,÷,多路选择器,译码器等)如果没有定义边沿触发,就与边沿无关,其输出与输入之间的延时只有门延时和线延时,线路越长,此延时越大

     

    assign:连续赋值语句

    #3:模拟组合逻辑的延时,表示经过3个延时单位,再进行赋值

    timescale 1ns/100ps:定义时间单位/仿真时间精度

    {}:是Verilog的合并符号,将多个变量合并成一个组合变量,可用于批量赋值

    xor:是Verilog自带的逻辑门原语

    实例化:调用功能模块

    在模块中实例化其他模块的描述方式称为结构化描述

     

    Verilog的3种描述方法:

    数据流描述:assign语句——连续赋值语句

    行为描述:always或initial语句——其中包含的语句称为过程赋值语句

    结构化描述:实例化已有的模块(包括Module实例化、门实例化、用户定义原语UDP实例化)

     

    基本词法:

    Verilog对大小写敏感,书写时要格外注意

    Verilog中所有关键字都是小写

    Verilog中标识符(内部信号名,变量名)由字母、数字、$、和_组成,第一个字符必须是字母或_

    //和/* */表示注释,某些控制编译过程的指令也是以注释的形式出现,例如/* synthesis syn_black_box */

    间隔:空格、制表符、换行符

    转义字符:\n换行符;\t制表符;\\表示\本身

     

    模块和端口:

    Verilog中,module是基本的组成单元

    建议在一个Verilog文件中只放一个module定义,且使文件名与module名称一致

    module 模块名称 (端口列表)

    //变量声明

    input [1:0], output, inout,

    reg, wire, parameter,

    function, task, …

    //语句,以下语句在module中是并行的关系,无任何顺序关系,其文本上的顺序不改变module的功能

    initial

    always

    module实例化

    门实例化

    UDP实例化

    assign

    endmodule

    有些module不包含输入输出端口,一般用于内部已经实例化了激励的封闭系统,只用于仿真,不用于实际系统

    input默认为wire类型(貌似不可以声明为reg类型);output在always或initial中赋值时默认是reg,否则是wire;inout一般设为tri类型(表示有多个驱动源,如无驱动则为三态)

    建议将所有的声明放到所有语句之前,增加可读性

     

    always的用法

    1.always@后面内容是敏感变量,always@(*)里面的敏感变量为*,意思是说敏感变量由综合器根据always里面的输入变量自动添加,不用自己考虑。

    2.如果没有@,那就是不会满足特定条件才执行,而是执行完一次后立马执行下一次,一直重复执行

    3.通常情况下,使用方法是:always@(posedge clk_out_0, negedge reset_n)

     

    Error (10028): Can't resolve multiple constant drivers for net……

    上面的代码在quartusII里面就会出现题目的错误提示,其原因就是在两个always语句里面都对out1,out2信号赋值了,而两个always是并行快,所以提示出现多重驱动的情况

    解决办法:将两个always合并成一个

     

    结构化描述

    结构化描述就是在设计中实例化已有的功能模块,包括门原语、用户自定义原语UDP,和其他模块module

    需要将模块实例与外部信号相连接,模块实例的端口连接规则:

    Input:缺省为线网wire类型

    Output:寄存器(在过程赋值语句中被赋值),或者是线网类型

    Inout:缺省为线网类型,定义为tri双向

    与之相连的信号类型为:

    与input相连的,可以使一个线网或寄存器

    与output,相连的一定是驱动一个线网

    与inout先练,输入时从一个线网驱动而来,输出时驱动到一个线网(切记,只有线网类型可以驱动inout端口,否则编译出错)

     

    实例的端口对应方式有两种:

    (1)名称对应:外部信号与模块端口名称相对应,顺序可随意

    模块名 实例名称(

        .X(E_X),

        .Y(E_Y),    //没有可留空

        ……

        );

    (2)位置对应:按顺序对应(与函数传递参数类似),没有则留空

    模块名 实例名称(E_X, E_Y, E_SUM, E_C_out);

     

    参数化

    上面讲了实例化,这里讲参数化

    module中的参数一般用作定义常量

    当实例化某个模块时,可以修改参数的值,实现不同的特性,是通过"新参数直接代入""参数重定义"来完成的。

    方法:

    1、defparam关键字重新定义模块参数——Altera自动生成的通用模块定制采用

    此方法在某些综合器中失效(应采用第2种)

    defparam

        module.parameter = ,

        ……

    2、直接在实例化时代入参数——Xilinx自动生成的通用模块定制采用

    #(……,……,……)参数要按顺序列出,不能遗漏和颠倒

  • 相关阅读:
    Apache CXF实战之四 构建RESTful Web Service
    使用CXF开发RESTFul服务
    Java多线程中的异常处理
    Checked异常和Runtime异常体系
    hql 语法与详细解释<转>
    hibernate实现有两种配置,xml配置与注释配置。<转>
    Hibernate配置详细解释
    重构(Refactoring)技巧读书笔记(General Refactoring Tips)
    Hibernate(1)——数据访问层的架构模式<转>
    关于layer.photos即照片显示的问题。
  • 原文地址:https://www.cnblogs.com/PhiloSky/p/3093776.html
Copyright © 2011-2022 走看看