Verilog 是一种用于数字逻辑电路设计的硬件描述语言,可以用来进行数字电路的仿真验证、时序分析、逻辑综合。
既是一种行为级(可用于电路的功能描述)描述语言又是一种结构性(可用于元器件及其之间的连接)描述语言。
Verilog 模块的基本概念
模块是Verilog的基本单位,除了编译指令,其他的所有的设计代码都必须放在一个或多个模块中。
一个模块内部可以使用其他模块,称为实例。上层模块可以引用底层任意层次模块的变量
模块内部可以包含若干个“块”。
Verilog模块总结:
Verilog 中的标示符可以是任意一组字母、数字、$符号和下划线符号的组合,但标示符的第一个字符必须是字母或者下划线。标示符区分大小写。
verilog 程序是有模块组成的,每个模块嵌套在module和endmodule声明语句中。模块是可以进行层次嵌套的
每个Verilog源文件中只准有一个顶层模块,其他为子模块。
每个模块要进行端口定义,并说明输入输出端口,然后对模块的功能进行行为逻辑描述
程序书写格式自由,一行可以写几个语句,一个语句可以分几行写,除了endmodule语句,begin…end语句,fork…join语句外,每个语句和数据定义的最后必须有分号。可用/…/和//…对程序的任何部分做注释,加上必要的注释,以增强程序的可度性和可维护性。
Verilog用于模块的测试
检查程序的功能是否正确要求:
需要有测试激励信号输入到被测模块
需要记录被测模块的输出信号
需要把用功能和行为描述的Verilog模块转换为门级电路互连的电路结构(综合);
需要对已经转换为门级电路结构的逻辑进行测试(门级电路仿真)
需要对布局布线后的电路结构进行测试(布局布线后仿真)
何为仿真?为何要仿真?
仿真是对电路模块进行动态的全面测试,通过观测被测试模块的输出信号是否符合要求可以调试和验证逻辑系统的设计和结构是否准确,并发现问题及时修改。
仿真可以在几个层面上进行?每个层面的仿真有什么意义?
仿真有:前(RTL)仿真,逻辑网表仿真,门级仿真和布线后仿真;
前仿真:前(RTL)仿真,逻辑网表仿真,门级仿真;可以调试和验证逻辑系统的设计和结构准确与否,并发现问题及时修改。
布线后仿真:分析设计模块运行是否正常;
模块的结构
Verilog 的基本设计单元是"模块(block)"
verilog 模块的结构由在module和endmodule关键字之间的4个主要部分组成:
逻辑功能的定义:
在Verilog中有3种方法可以描述电路的逻辑功能:
用assign语句(连续赋值语句,常用于描述组合逻辑)
assign x = (b &~c);
用元件例化(instance 门元件例化)
and(门元件关键字) u_and3(例化原件名)(f,a,b,c);
注1:元件例化即是调用Verilog提供的元件;
注2:元件例化包括门元件例化和模块元件例化;
注3:每个实例元件的名字必须唯一,以避免与其他调用元件的实例相混淆;
注4:例化元件名也可以省略。
用”always“块语句
注1:”always“块语句常用于描述时序逻辑,也可描述组合逻辑;
注2:”always“块可用多种手段来表达逻辑关系,如用if…else语句或case语句;
注3:”always“块语句与assign语句是并发执行的,assign语句一定要放在”always“块语句之外。
模块结构模板:
标示符:
任何用Verilog语言描述的东西都可以通过其名字来识别,这个名字被称为标示符;
如源文件名,模块名,端口名,变量名,常量名,实例名等
标示符可由字母,数字,
和下划线组成,但第一个字符必须是字母或下划线,不能是
和下划线组成,但第一个字符必须是字母或下划线,不能是
和下划线组成,但第一个字符必须是字母或下划线,不能是和数字
在Verilog中标示符是区分大小写的,且不能与关键字同名。
关键字:
语汇代码编写标准:
(1)每个Verilog HDL源文件中只准编写一个顶层模块,也不能把一个顶层模块分成几部分写在几个源文件中。 (2)源文件名字应与文件内容有关,最好与顶层模块同名!源文件名字的第一个字符必须是字母或下划线,不能是数字或$符号! (3)每行只写一个声明语句或说明。 (4)源代码用层层缩进的格式来写。
(5)定义变量名的大小写应自始至终保持一致 (如变量名第一个字母均大写)。
(6)变量名应该有意义,而且含有一定的有关信息。局部变量名(如循环变量)应简单扼要。
(7)通过注释对源代码做必要的说明,尤其对接口(如模块参数端口、任务、函数变量) 做必要的注释很重要。
(8)常量尽可能多地使用参数定义和宏定义,而不要在语句中直接使用字母、数字和字符串。
·参数定义(用一个标识符来代表一个常量)的格式:parameter 参数名1=表达式,参数名2=表达式,…宏定义 (用一个简单的宏名来代替一个复杂的表达式)的格式:define 标志符(即宏名) 字符串(即宏内容)
综合代码编写标准:
(1)把设计分割成较小的功能块,每块用行为风格设计。除设计中对速度响应要求比较临界的部分外,都应避免门级描述。 (2) 建立一个好的时钟策略(如单时钟、多相位时钟,经过门产生的时钟、多时钟域等)。保证源代码中时钟和复位信号是干净的(即不是由组合逻辑或没有考虑到的门产生的)。C (3)建立一个好的测试策略,使所有触发器都是可复位的,使测试能通过外部管脚进行,又没有冗余的功能。(4)所有源代码都必须遵守并符合在always块语句的4种可综合标准模板之一。 (5)描述组合和锁存逻辑的always块,必须在always块开头的控制事件列表中列出所有的输入信号。
(6) 描述组合逻辑的always块,一定不能有不完全赋值,即所有输出变量必须被各输入值的组合值赋值,不能有例外。
(7)描述组合和锁存逻辑的always块一定不能包含反馈,即在always块中已被定义为输出的寄存器变量绝对不能再在该always块中读进来作为输入信号。
(8)时钟沿触发的always块必须是单时钟的,且任何异步控制输入(通常是复位或置位信号) 必须在控制事件列表中列出。例: always @(posedge clk or negedge set or negedge reset)
(9)避免生成不想要的锁存器。在无时钟的always块中,若有的输出变量被赋了某个信号变量值,而该信号变量并未在该always块的电平敏感控制事件中列出,则会在综合中生成不想要的锁存器。
(10)避免生成不想要的触发器。
在时钟沿触发的always块中,如果用非阻塞赋值语句对reg型变量赋值;或者当reg型变量经过多次循环其值仍保持不变,则会在综合中生成触发器。
用reg型变量生成触发器举例:module rw2( clk, d, outl);
input clk, d;output outl;reg outl ;
always @(posedge clk) //沿触发out1 <= d :
endmodule
若不想生成触发器,而是希望用reg型变量生成组合逻辑,则应使用电平触发:
module rw2( clk, d, outl);
input clk, d;
output outl;
reg out1 ;
always @(d) //电平触发out1 <= d ;endmodule
(11)所有内部状态寄存器必须是可复位的,这是为了使RTL级和门级描述能够被复位成同一个已知的状态,以便进行门级逻辑验证。
(12)对存在无效状态的有限状态机和其他时序电路(如4位十进制计数器有6个无效状态),必须明确描述所有的2的N次幂种状态下的行为(包括无效状态),才能综合出安全可靠的状态机。
(13)一般地,在赋值语句中不能使用延迟,否则是不可综合的。
(14)仔细检查代码中使用动态指针(如用指针或地址变量检索的位选择或存储单元)、循环声明或算术运算部分,因为这类代码在综合后会生成大量的门,且难以优化。
想要了解更多,就关注IC修真院吧,后续为大家持续更新,如果想要获取全文档,也可直接领哦~
这里放个口:Verilog概述全文