※书目:Verilog数字系统设计教程(第四版)夏宇闻等编著
虚拟机:VMware -14.0.0.24051
环 境:ubuntu 18.04.1
脚 本:makefile(点击直达)
应用工具:vcs 和 verdi
文章目录
一、模块的结构
一个模块有两部分组成,一部分描述接口,另一部分描述逻辑功能,即定义输入是如何影响输出的。
(1)I/O声明的格式
(2)内部信号说明
在模块内用到的与端口有关的wire和reg类型变量的声明。
//如:
reg [width-1:0] R变量1,R变量2 ...;
wire [width-1:0] W变量1,W变量2 ...;
(3)功能定义
在模块内,最重要的部分是逻辑功能定义部分,一般有三种方法:
- 用“assign”声明语句,如:assign a = b & c ;
- 用实例元件,如:and #2 u1(q , a, b);
- 用“always”块,如:
always @ (posedge clk or posedge clr)begin
if(clr) q <= 0;
else if(en) q <= d;
end
二、数据类型、常量和变量
Verilog一共有19种数据类型,常用的有reg型、wire型、integer型、parameter型,其他类型为:
(1)数字
※ 整数在verilog中,整型常数有四种进制表达形式:
- 二进制整数(b或B)
- 十进制整数(d或D)
- 十六进制整数(h或H)
- 八进制整数(o或O)
※ 数字表达式有3种:
- <位宽>'<进制><数字>,一般都写成这个形式多一点,如:8’b00011010;
- '<进制><数字>,这种省略了位宽的,则采用默认位宽(这由具体的机器系统决定,但至少为32位);'b01
- <数字>,只有数字,则默认为十进制。如:3 = 32’b11
※ x和z值
在数字电路中,x代表不定态,z代表高阻态。一个x可以用来定义十六进制数的4位二进制数的状态,八进制数的3位,二进制数的1位。z的表示方式和x类似,z还有一种表达方式,写作“?”,常用在case语句中。
※ 负数
一个数字可以被定义为负数,只需要在位宽表达式前加负号即可
※ 下划线(underscore)
下划线可以用来分隔开数的表达以提高程序可读性,但它不能用于位宽和进制之间。
当常量不说明位数时,默认值为32位,每个字母用8位
ASCII值表示。
(2)参数(parameter)型
在verilog中,用parameter定义常量,被称为符号常量,可以提高代码的可读性和可维护性。
在定义符号常量时,表达式只能包含数字或先前已经定义过的参数。
【例 3.1】参数传递
module Decode(A,F);
parameter Width = 1,Polarity = 1;
...
endmodule
module Top;
wire [3:0] A4;
wire [4:0] A5;
wire [15:0] F16;
wire [31:0] F32;
Decode #(4,0) D1(A4,F16);
Decode #(5) D2(A5,F32);
endmodule
原来的Width和Polarity都是1,在Top模块实例化时,通过#(4,0),D1实际引用的参数分别为4和0;通过#(5),D2实际引用的参数为Width为5,Polarity保持不变,为1。
【例 3.2】多层次模块
`include "Top.v"
`include "Block.v"
`include "Annotate.v"
module Test;
wire W;
Tpp T();
endmodule
module Top;
wire W;
Block B1();
Block B2();
endmodule
module Block;
parameter P = 0;
endmodule
module Annotate;
defparam
Test.T.B1.P = 2;
Test.T.B2.P = 3;
endmodule
在一个模块中改变另外一个模块的参数时,需要使用defparam命令,在做布线后仿真是,就是利用这种方法把布线延迟通过布线工具生成的延迟参数文件反标注(Back-annotate)到门级Verilog网表上。
(3)wire型
在端口变量声明时,如果没指定类型,则默认为wire型。wire型信号可以做任何方程式的输入,也可以做“assign”语句或实例元件的输出。
(4)reg型
寄存器数数据存储单元的抽象,寄存器数据类型的关键字数reg,通过赋值语句可以改变存储器的值,其作用与改变触发器存储的值相当。reg型数据通常表示“always”模块内指定信号,常代表触发器。在“always”内,被赋值的每一个信号都必须定义为reg型。
对于reg型数据,器默认的初始值为不定值x,其赋值语句的作用就如同改变一组触发器的存储单元的值。reg型数据可以赋值正值,也可以赋值负值,但当一个reg型数据是一个表达式中的操作数时,它的值被当做无符号正值,例如当一个4bit的寄存器做表达式的操作数时,如果开始寄存器被赋值-1时,其实际值会被认为是-1的补码,即+15。
(5)memory型
Verilog HDL通过对reg型变量建立数组对存储器建模,可以描述RAM型存储器、ROM存储器和reg文件。数组中的每一个单元通过一个数组索引进行寻址。在Verilog语言中,不存在类似于C语言中的对维数组。memory型数据是通过扩展reg型数据的地址范围来生成的。格式如下:
上面例子,使用了前面讲到的parameter,实际上这里表示256个16位的寄存器。
在对memory赋值时,需要指定地址,比如:
三、运算符及表达式
- 单目运算符(unary operator):可以带一个操作数,操作数放在运算符的右边。
- 双目运算符(binary operator):可以带两个操作数,操作数放在运算符的两边。
- 三目运算符(ternary operator):可以带三个操作数,这三个操作数用三目运算符分隔开
(1)基本算术运算符
(2)位运算符
各个位运算符的真值表如下,其中,不同长度的数据进制位运算时,系统会自动将两者按右端对齐,位数少的操作数会在相应的高位用0填满。
四、思考题
- 模块由几个部分组成?
由描述接口和描述逻辑功能两部分组成。 - 端口分为几种?
三种:输出口,输入口,输入/输出口。 - 为什么端口要说明信号的位宽?
因为如果不说明信号的位宽可能会在信号发生改变时发生错误,不容易看出接收到的信号的数据宽度,就很难进行数据的处理。 - 能否说模块相当于电路图中的功能模块,端口相当于功能模块的引脚?
可以那样说,每个模块都有特定的功能,而功能的实现就必须依靠具体的电路得以实现,端口是信号传递的通道,可以说是功能模块的引脚。 - 模块中的功能描述可以由哪几类语句或语句块组成?它们出现的顺序会不会影响功能的描述?
用assign语句声明,用实例元件,用always块。它们出现的顺序不会影响到功能的描述。
- 这几类描述中的哪一种直接与电路结构有关?
用实例元件直接与电路结构有关。 - 最基本的Verilog变量有哪几种类型?
wire型、reg型、memory型。 - reg型和wire型变量的差别是什么?
reg型变量是寄存器变量,wire型变量是连线型变量。两者根本性的差别在于reg型变量有个寄存器来存放变量,这个值只有变量发生改变时才会改变,否则保证原来的值不变,wire型变量的值不是确定的值。 - 由连续赋值语句(assign)赋值的变量是否能是reg类型的?
可以是reg类型的变量。 - 在always模块中被赋值的变量能否是wire类型的?如果不能是wire类型的,那么必须是什么类型的?它们表示的一定是实际的寄存器吗?
不能。必须是reg类型的变量,它们表示的不一定是实际的寄存器。
- 参数类型的变量有什么用处?
参数类型的变量的好处是可以提高程序的可读性和可维护性。 - Verilog语法规定的参数传递和重新定义功能有什么直接的应用价值?
可以用于定义延迟时间和变量宽度。 - 逻辑比较运算符小于等于“<=”和非阻塞赋值大于等于“<=”的表示是完全一样的,为什么Verilog在语句解释和编译时不会搞错?
因为逻辑比较时“<=”两边是两个操作数,此时“<=”是双目运算符,而在非阻塞赋值时“<=”的右边是操作数,此时“<=”是单目运算符。 - 是否可以说实例引用的描述实际就是严格意义上的电路结构描述?
不能实例引用的描述是在门级电路上加以描述的,和严格意义上的电路结构描述还是有点差距的。
作者:xlinxdu
版权:本文是作者读书整理的笔记,部分图片来源于参考教材,侵权联系删。
转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。