目录
- 3.1 增强的文本值赋值
- 3.2 `define 增强
- 3.2.1 字符串内的宏变量替换
- 3.2.2 通过宏建立标识符名
- 3.3 SystemVerilog变量
- 3.3.1 对象类型和数据类型
- 3.3.2 SystemVerilog 四态变量
- 3.3.3 SystemVerilog 两态变量
- 3.3.4 显式及隐式变量和线网类型
- 3.3.5 综合指导
- 3.5 数据类型规则的放宽
- 3.6 有符号和无符号修饰符
- 3.7 静态类型和自动变量
- 3.7.1 静态变量和动态变量的初始化
- 3.7.2 自动变量的综合指导
- 3.7.3 静态和自动变量的使用原则
- 3.8 变量初始化的确定性
- 3.8.1 初始化确定机制
- 3.8.2 时序逻辑的一部输入初始化
- 3.9 强制类型转换
- 3.10 常数
SystemVerilog拓展了Verilog的数据类型,增强了指定文本值的方法。
3.1 增强的文本值赋值
- 只指定要赋的值而不用指定位数和进制
data = '1;//左边所有的位赋为1
data = '0;//左边所有的位赋为0
data = 'z;//左边所有的位赋为z
data = 'x;//左边所有的位赋为x
3.2 `define 增强
SystemVerilog拓展:使宏文本可以包含特殊字符。
3.2.1 字符串内的宏变量替换
Verilog | SystemVerilog |
`define宏中 “” 内文本被判定为字符串 | 允许`" `"内文本进行宏变量替换 |
例子:
`define print(v) $display(`"variable v = %h`", v);
`print(data)
宏`define将替换为:
$display("variable data = %h", data)
如果同时需要输出引号,光转义是不够的,需要使用`\`",例子:
`define print(v) $display(`"variable `\`"v`\`" = %h`", v);
`print(data)
宏`define将替换为:
$display("variable \"data\" = %h", data)
3.2.2 通过宏建立标识符名
不引入空格实现宏定义内容拼接,例子:
`define TWO_STATE_NET(name) bit name``_bit;wand name``_net = name``_bit;
`TWO_STATE_NET(d00);
`TWO_STATE_NET(d01);
...
`TWO_STATE_NET(d62);
`TWO_STATE_NET(d63);
替换之后的结果是:
bit d00_bit;wand d00_net = d00_bit;
bit d01_bit;wand d01_net = d01_bit;
...
bit d62_bit;wand d62_net = d62_bit;
bit d63_bit;wand d63_net = d63_bit;
3.3 SystemVerilog变量
3.3.1 对象类型和数据类型
Verilog:
- 数据分为变量类型和线网类型
- 变量:
- reg、integer、time变量每一位都是四态逻辑:0,1,X,Z。
- 线网:
- wire、wor、wand等net类型每一位有120种值(四态加上多个强度级)及专用线逻辑决断函数。
SysteVerilog:
- 数据声明具有类型和数据类型.\
- 类型指示信号是线网(wore)还是变量(var)
- 数据类型指示线网或者变量的值系统
- 两态数据类型是0,1.
- 四态数据类型是0,1,x,z.
- logic是四态数据类型
- 变量可以是两态也可以是四态,线网类型只能是四态.
3.3.2 SystemVerilog 四态变量
Verilog:
- 使用reg类型作为initial和always块中硬件行为建模的通用变量.
注意:实际上,reg变量和推断出的硬件没有任何关系,只有根据reg使用的上下文才能确定它表示的硬件是组合逻辑还是时序逻辑.
SystemVerilog:
- 使用Logic数据类型代替reg,用来描述通用的针对硬件的数据类型.
- logic表示信号具有四态值,但是当logic关键字单独使用时表示这是一个变量.
因为关键字logic不会产生硬件类型的误解,所以在需要使用四态逻辑时,使用logic描述硬件更直观。
3.3.3 SystemVerilog 两态变量
SystemVerilog新增的两态类型:
- bit 1位
- byte 8位
- shortint 16位
- int 32位
- longint 64位
两态类型与四态类型比较?
- 在可综合RTL硬件模型中,更愿意使用的四态类型(reg、logic),z用于表示未连接或者三态逻辑,x有助于检测和隔离设计错误。而在更高级建模,如系统级和传输级中,几乎不需要逻辑值z和x,两态类型对更高抽象级的硬件建模非常有用。
- 两态类型可以用于到C和C++模型的接口。
- int类型可以用于循环控制变量,循环控制变量作为一个临时变量,在综合后的门级表示中就消失了,不需要四态值。
- 两态类型从逻辑0开始仿真,四态类型从逻辑X开始仿真,用四态类型才能描述未初始化状态。
- 给两态类型赋x和z会被指定为0。
*SystemVerilog其他抽象类型
- void:表示无存储
- real、shortreal:双精度变量,不可综合,用于抽象建模和测试程序。
- 类和其他用于高层次测试的动态类型。
3.3.4 显式及隐式变量和线网类型
var关键字:
用途:显示表示对象时变量(variable),便于代码维护。
说明:var关键字并不影响变量的仿真或综合行为。
SystemVerilog:
- 具有线网和变量类型和两态和四态数据类型。
- 所有线网类型都隐含为四态逻辑数据类型,没有两态线网类型。
- 不允许reg关键字直接和任何线网类型关键字成对使用,可以选择使用线网类型和logic类型进行声明。
wire logic[31:0] busA; //对
wire reg[31:0] busA; //错
3.3.5 综合指导
两态类型的使用主要影响仿真。
两态类型和四态类型同样综合,综合会忽略两态类型的默认初始值。
3.5 数据类型规则的放宽
verilog:
在initia和always过程块中使用变量(reg),在使用持续赋值语句、模块实例或Verilog原语实例建模时,使用线网类型(wire)。
SystemVerilog:
任何数据类型的变量都可以通过下列方式且只能采用其中一种赋值:
- 任意initial或always过程块。(与Verilog一致)
- 单个always_comb、always_ff或always_latch过程块中赋值。
- 单个持续赋值语句赋值。
- 单个模块或者原语的output/input端口驱动赋值。
说明:规则的放宽可以允许模型中的大部分信号声明为一个变量类型,如bit或logic。不用事先确定信号使用的上下文。
SystemVerilog变量的错误使用:
- 多个输出端口驱动一个变量。
- 对一个变量进行多次持续赋值。
- 对一个变量同时作用过程赋值和持续赋值。
单驱动逻辑使用变量,多驱动逻辑使用线网。
3.6 有符号和无符号修饰符
Verilog:
reg [63:0] u;//无符号64位变量
reg signed [63:0] s;//有符号64位变量
SystemVerilog:
int s_int;//有符号32位变量
int unsigned u_int;//无符号32位变量
注意:SystemVerilog只允许在类型关键字后面指定signed或unsigned关键字。
3.7 静态类型和自动变量
Verilog:
- Verilog-1995标准所有数据类型都是静态的,因为硬件模型的数据类型也是静态的。
- Verilog-2001标准任务或函数中的变量是自动的。所谓自动变量,也称动态变量。
- 含义:在存储区需要时由软件工具动态分配,在不需要时被释放。每次调用,都建立新的存储空间,访问结束后空间被释放。
- 作用:用来描述在测试程序、抽象系统级、传输级、或总线功能模型中的验证程序。
- Verilog通过声明整个任务或者函数来声明其中所有的变量位自动变量。
SystemVerilog:
- 加入通过static和automatic关键字作为声明变量的一部分声明静态和自动变量的能力。
注意:在模块级,所以变量都是静态的。
3.7.1 静态变量和动态变量的初始化
Verilog的内嵌(in-line)变量初始化:
- Verilog只允许在模块级声明的变量进行内嵌初始化,在任务、函数、begin…end及fork…join块中声明的变量不能在声明的时候初始化。
Systemverilog的内嵌初始化:
- 在任务、函数中声明的变量都可以内嵌初始化。
注意:
- 非自动函数和任务中声明的变量默认是静态的,只在开始仿真时赋值一次。
- 自动函数和任务每次调用都会通过内嵌初始化赋值。
3.7.2 自动变量的综合指导
静态变量初始化不可综合
动态变量初始化可综合。
3.7.3 静态和自动变量的使用原则
- always和initial块:无内嵌初始化则用静态,有则用动态,因为有内嵌初始化一般每次调用需要初始化值。
- 可重入的函数与任务中:每次调用需要初始化的变量用动态,需要保持的用静态,比如记录运行次数的变量。
- 不可重入的函数与任务:作为硬件的独立部分,需要用静态变量。
3.8 变量初始化的确定性
3.8.1 初始化确定机制
Verilog-1995:
- 多个initial过程块仿真次序不确定,所以块中的变量初始化顺序不确定。
Verilog-2001:
- 可以在声明时初始化,与initial块中初始化一样不确定顺序。
SystemVerilog:
- 所有内嵌初始化先于仿真0时刻,保证初始化值都正确。
例子:
logic resetN = 0;
always @(posedge clock,negedge resetN)
if (!resetN)
count <= 0;
else
count <= count + 1;
- Verilog可能的情况:
- always块可能先于resetN初始化,则always可以检测resetN从x到0,count被赋为0。
- resetN初始化先于always块,count在时钟上升沿加一,不会赋为0。
- SystemVerilog可能的情况:
- 确保初始化完成, 只有resetN初始化先于always块的情况。
3.8.2 时序逻辑的一部输入初始化
- Verilog变量初始化顺序的不确定性可能引起时序逻辑中的异步置位或者复位变成同步逻辑。
- SystemVerilog内嵌变量初始化的确定性可以保证0仿真时刻事件的发生顺序。
3.9 强制类型转换
项目 | Verilog | SystemVerilog |
比较 | 弱类型语言,允许一个数据类型的值赋给另一个数据类型的变量或者线网。(只要是个数就能赋给另一个) | 加入强制转换。(赋值前先转变数值类型) |
静态转换(编译时转换) | 直接赋值,无错误检测 | <type>’(<expression>),<size>’(<expression>),<sign>’(<expression>),无错误检查 |
动态强制类型转换 | 使用系统函数$cast(dest_var,source_exp),如果表达式的结果赋给目标变量无效,则会报告运行时错误且目标变量不变。 |
int'(2.0 * 3.0);
16'(2);
signed'(a);
注意:
- 系统函数$cast 不能和直接修改源表达式的操作符(如++,+=)一起使用。
- 静态的强制类型转换操作符可综合,动态系统函数$cast不可综合。
3.10 常数
项目 | Verilog | SystemVerilog |
类型 | parameter、specparam和localparam | 加入const关键字修饰常数 |
位置 | 不允许在自动任务和函数中 | const修饰的常量可以在自动任务和函数声明 |
值 | 确立(软件工具建立模块实例代表的设计层次的过程)时才能确定它们的最终值。对常数赋层次引用值非法。 | const修饰的常数可以被赋予一个线网或变量值而非常数表达式,可以被赋予一个在任何设计层次定义的对象值。 |
一个const常数实质是一个只能被初始化的变量。