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自动生成的通用模块定制采用

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

相关推荐:

Python新手入门基础英文笔记

Python新手入门重点:变量无需声明类型,靠缩进区分代码块,常用内置函数如print()、input()、len()等,条件用if/elif/else,循环用for配合enumerate可带序号。 Python新手入门,英文笔记不用怕——重点记清楚、用得上就行。 Variables&Dat...

python openpyxl笔记

from openpyxl import Workbook wb = Workbook() ws = wb.active ''' 指定sheet wb.create_sheet("myShe...

整理C知识点--变量作用范围

按照作用域分:(1).全局变量Globalvariabless在所有函数外部定义的变量叫全局变量作用范围:从定义位置开始到整个程序结束(换一种说法:函数调用全局变量,全局变量必须在被调用函数的上方)e.g:#include<stdio.h>voideg1(void){printf(&qu...

整理C知识点--数组

数组是为了解决大量同类型数据的存储和使用(e.g需要10000个同类型数据,定义这么多变量只是取变量名称就是一个浩大的工程) 数组的分类:一维数组,二维数组,多维数组 一维数组:(1).为N个变量连续分配存储空间(2).所有的变量数据类型必须相同(3).所有变量所占的字节大小必须相当e.ginta[...

整理C知识点--函数(重点)

函数:能够完成特定功能的独立的代码 函数的作用:避免重复性操作有利于程序的模块化 定于函数:函数的翻回值函数的名字{函数的执行体}(1).函数的定义的本质是详细描述函数之所以能实现某个特定功能的具体方法(2).return表达式;含义:(1).终止被调函数,向主函数返回表达式的值(2).若表达式为空...

lr连接数据笔记

globals.h #ifndef_GLOBALS_H #define_GLOBALS_H //-------------------------------------------------------------------- //IncludeFiles #include"lrun.h" #...

expect学习笔记及实例详解

expect学习笔记及实例详解引用自:http://wenku.baidu.com/view/b65e103610661ed9ad51f374.html1.expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示:1.1首行加上/usr/bin/expect1.2spawn:...

PHPexcel笔记

首选去下载phpexcel文件包 1.phpexcel把excel表格数据导入mysql‘数据库中规定的表中前端:<tr><td><tablewidth="100%"border="0"cellspacing="0&qu...