当前位置:网站首页>【数字IC验证快速入门】14、SystemVerilog学习之基本语法1(数组、队列、结构体、枚举、字符串...内含实践练习)
【数字IC验证快速入门】14、SystemVerilog学习之基本语法1(数组、队列、结构体、枚举、字符串...内含实践练习)
2022-07-07 04:43:00 【luoganttcc】
导读:作者有幸在中国电子信息领域的排头兵院校“电子科技大学”攻读研究生期间,接触到前沿的数字IC验证知识,旁听到诸如华为海思、清华紫光、联发科技等业界顶尖集成电路相关企业面授课程,对数字IC验证有了一些知识积累和学习心得。为帮助想入门前端IC验证的朋友,思忱一二后,特开此专栏,以期花最短的时间,走最少的弯路,学最多的IC验证技术知识。
文章目录
一、内容概述
- 数据类型:四值变量、二值变量
- 四值变量如果是1bit,那么四值是:0/1/x/z(x是不定态;z是高阻态,如果0是0V,1是0.8V,那么z便是0.5V/0.6V左右的样子)
- 固定数组:初始化(直接赋值、for、foreach)
- 固定数组:unpacked array & packed array
- 固定数组:赋值和比较
- 动态数组
- 队列
- 联合数组
- 数组方法(函数)
- 结构体
- 枚举类型
- 字符串
二、基本变量
2.1、SystemVerilog 语法规则
和Verilog一样
- 大小写敏感
- 空格不忽略,字符串中的除外
- 注释符号
- 行注释:
//
- 语句块注释:
/*...*/
- 行注释:
数制格式
<size>' <base> <number>
'b
(binary 二进制):01xXzZ
'd
(decimal 十进制):0123456789
'h
(hexadecimal 十六进制):0123456789abcdefABCDEFxXzZ
使用分隔符
“_”
,提高阅读性:16'b1100_1011_1010_0010
32'hbeef_cafe
2.2、SystemVerilog 新的数据类型
- 二值逻辑:性能更好,占内存少
- 队列,动态数组和联合数组:减少内存的使用量,支持搜索和排序
- 联合数组和填充结构体:相同数据具有不同的视图(View)
- 类和结构体:支持数据结构的抽象化
- 字符串:SV内建了操作函数
- 枚举类型:便于编码和理解(常用在TestBench中)
2.3、SystemVerilog 数据类型
Verilog 语言中的赋值
- 矢量(vector,即位宽大于1的变量)容易赋值为全
0/z/x
,但是赋值全1
的时候,需要把全部位都写出来!
SystemVerilog 的赋值
- 不需要指定进制数(二进制、八进制、十进制和十六进制数)就可以填充0/x/z
- 全部填充1
四值变量
Verilog
- reg:通用变量,用在
initial
和always
语句中,对硬件模块建模- 组合电路和时序电路
- wire:主要起到连接作用,类似金属线;在
assign
中赋值
- reg:通用变量,用在
SystemVerilog
- logic(logic取代了reg)
- 可被连续赋值语句,门电路或module驱动
- 不能多驱动,比如双向总线(需要使用wire进行建模)
- logic(logic取代了reg)
logic 有四种状态
- 0/1/x/z
- logic定义的变量是无符号数!
- 举例:
logic [31:0] data;
- 举例:
常见用法:
logic reset_n; //未指定位宽,默认为1bit
logic [63:0] data; //使用 [最高位:最低位] 表示数据位宽
logic [7:0] array [0:255]; //二维数组,常用memory的建模
- 1
- 2
- 3
二值变量:bit,byte,shortint,int,longint
- 只有两种状态0和1(x和z会转换成0)
- 提高仿真性能,减少内存使用量
- 不用于做RTL设计(因为x or z两种状态会被转换成0)
bit
的位宽是用户自定义的,并且是无符号数;byte/shortint/int/longint
的位宽是固定的,并且是有符号数!logic
的位宽也是用户自定义的,并且是无符号!
关于有符号数和无符号数的数据范围再做一点小回顾,eg:2位宽,即
00 / 01 / 10 / 11
四种形式,在无符号形式下依次代表:0 / 1 / 2 / 3
;在有符号形式下(最高位为符号位)依次代表:0 / 1 / -1 / -2
- 正数的补码是它本身,负数的补码是取反再加1
Q:
logic [7:0] x
和byte x
一样吗?- A:不一样,
logic
是四值变量,byte
是二值变量
- A:不一样,
逻辑仿真特性
- 四值状态变量的默认初始值是
x
;二值状态变量的默认初始值是0
- 二值状态的变量不能表示未初始化状态(
x
) - 四值状态的变量可以赋值为二值状态的变量。
x
和z
会转换成0 $isunknown(expression)
可以检查表达式中是否存在x或z
三、固定数组
- 支持多维数组(算法类矢量运算用的较多)
- 超出边界的写操作被忽略
- 超出边界的读操作返回值为
x
(四值状态变量),0
(二值状态变量) byte/shortint/int
存放在32位的存储空间中(显然byte
和shortint
有点浪费存储空间)longint
存放在64位的存储空间中
3.1、一维数组
int
等效于bit signed [31:0]
的声明[0:15]
、[16]
两种方式指定一维数组的深度,所以两种写法是等效。int lo_hi[0:15]
与int lo_hi[16]
写法的元素排列顺序一样(从0开始到最大15),但是int lo_hi[15:0]
写法的元素排列顺序与前面不一样(从15开始到最小0)!- 数组
f[5]
等同于f[0:4]
,而foreach(f[i])
等同于for(int i=0; i<=4; i++)
。 - 对于数组
rev[6:2]
来说,foreach(rev[i])
等同于for(int i=6; i>=2; i--)
。
int lo_hi[16]
相当于16行x32列
的矩阵大小- 取lo_hi中第1个数的第8bit:
lo_hi[1][8]
3.2、多维数组
3.3、固定数组的基本操作
3.3.1、固定数组初始化:'{} '{n{}}
- 全部或部分初始化
3.3.2、for
:利用for循环语句进行初始化
- 最常见的数组初始化方法
- 变量
i
为本地循环变量 - 系统函数
$size
返回数组大小(固定数组只能用$size
)
3.3.3、foreach
:利用foreach循环语句进行初始化
- 指定数组名称,方括号中是索引号,foreach会根据索引号遍历所有的数组元素
- 索引号可以自动声明为本地循环变量
3.3.4、固定数组的赋值和比较
- 不需要循环就可以进行数组的赋值和比较(只适用操作符等号
==
和不等号!=
)
3.3.5、数组元素、数组元素部分选取
3.4、非填充数组(unpacked array)
- 存放在32位的存储单元中
bit [7:0] up_array[3]
近似等效于byte up_array[3]
(但注意bit是无符号的,byte是有符号的)
简单的非填充数组声明
- 注意数组直接定义深度比如
1024
,那么就是从0-1023
;如果直接指定[64:83]
,那么就是64-83
3.5、填充数组(压缩数组,Packed Array)
相对于非压缩数组的区别,还是在存储上!
- 将一个数组当做一个值
- 连续存储数据
- 维度的书写格式为
[msb:lsb]
填充数组的初始化
- 声明时使用简单的赋值语句进行初始化
- 填充数组初始化赋值不需要加单引号!
3.6、混合数组(Mixed Arrays)
3.6.1、混合数组介绍
- p_array 是一个非填充数组,数组元素则为填充数组:
bit [3:0][7:0] p_array[0:2]
- 非填充数组回顾:
bit [7:0] up_array[3];
3.6.2、混合数组维度
- 混合数组中,非填充数组的维度是第一位的;从最左侧开始到最右侧
- 填充数组的维度是第二位的,从左侧开始到最右侧
3.7、填充数组和非填充数组比较
- 填充数组可以手动跟标量进行转换
bit [3:0][7:0] a;
与bit [31:0] b;
之间是可以相互转换的!即:a = b;
或b = a;
- 按照
byte
引用内存数据- 即一个字节,
8bit
- 即一个字节,
- 如果仿真中需要等待数组的变化,可以使用填充数组
- 用非填充也行,填充相比非填充存储空间更小,仿真速度更快!
- 只有固定数组可以被填充
- 固定数组分为填充和非填充两类!
- 动态数组、联合数组和队列是不能够被填充的
3.8、填充数组和常量数组初始化与内存存储比较
常量数组:int a[4] = '{0, 1, 2, 3};
- 常量数组初始化必须在前面加上单引号
- 内存存储:
a[0] = 0; a[1] = 1; a[2] = 2; a[3] = 3;
填充数组:bit [3:0] [7:0] b = {8'h3, 8'h2, 8'h1, 8'h0};
- 填充数组初始化不需要在前面加单引号
- 内存存储:
b[3] = 3; b[2]=2; b[1] = 1; b[0] = 0;
3.9、小测试
Q:变量logic和reg有根本性的不同吗?
- A:没有
Q:变量logic和bit有什么不同?
- A:logic有四种状态:0/1/x/z;bit只有两种状态:0/1
Q:两种状态的变量可以用于RTL设计吗?为什么?
- A:不可以,因为二值逻辑会把x/z两种电路状态转换成0
Q:
bit[31:0] src[5] = '{5,6,7,5,5}
,则src[1]
= 3‘b110’src[3][0]
= 1’b1src[2][3:1]
= 3’b011
Q:下列哪个不是2值数据类型?(B)
- A bit
- B logic
- C int
- D byte
Q:下列哪种不是Verilog语法?(D)
- A data = '0;
- B data = 'z;
- C data = 'x;
- D data = '1;
int md[2][3];
foreach(md[i,j])
md[i,j] = 2*i+j;
- 1
- 2
- 3
- Q:如上代码,那么
md[2,3]
(A)- A 0
- B 5
- C 7
- D X
解析:i
取值范围是:0-1
,j
取值范围是:0-2
。int是二值变量,md[2,3]
毫无疑问越界了,所以应该返回0,答案A。但是如果定义的是logic四值变量,那么返回的是x
- Q:logic[7:0] 和 byte的取值范围分别是?(A)
- A
0~255, -128~127
- B
-128~127, -128~127
- C
0~255, 0~255
- D
-128~127, 0~255
- A
logic是无符号的,byte是有符号的
四、动态数组
如果在仿真之前不知道数组的元素个数,那就用动态数组!
- 动态数组声明时使用方括号:
[]
,形式如下:
data_type name_of_dynamic_array[];
name_of_dynamic_array = new[number_of_elements];
- 1
- 2
- 在运行仿真时设置数组的元素个数,编译时不需要
- 在仿真过程中,可以分配内存空间和重新设置数组元素的个数
new[]
用于分配内存空间,传递数组元素的个数- 通过数组名称可以实现数组的赋值
- 当固定数组的数据类型相同时,可以将值赋给动态数组
$size
系统函数返回固定数组和动态数组的元素个数!(固定数组只能用$size
,动态数组可以用$size
和size()
)
dyn = new[20](dyn)
- 原来的元素值还保存dyn = new[100];
- 原来的元素值就丢了
当满足以下条件时,动态数组和固定数字可以相互赋值:
- 相同的数据类型
- 相同的元素数目
int a[10]; //固定数组
int b[]; //动态数组
b = new[10]; //这样之后,b和a可以相互赋值即:a=b或b=a都可以!
- 1
- 2
- 3
五、队列(用的多)
队列结合了数组和链表的特点。队列与链表相似,可以在一个队列中的任何地方增加或删除元素,这类操作在性能上的损失比动态数组小的多,因为动态数组需要分配新的数组并复制所有元素的值。队列与数组相似,可以通过索引实现对任一元素的访问,而不需要像链表那样去遍历目标元素之前的所有元素!
- 队列声明使用
$
在方括号中:data_type queue_name[$];
- 具有排序和搜索的功能
- 循序分配额外的空间和额外的元素
- 支持
push
和pop
操作 - 支持
add
和remove
元素操作 - 固定数组和动态数组的值赋值给队列
- 不需要
new[]
函数 - 队列元素编号是:
0
到$
- 如果把
$
放在一个范围表达式的左边,那么$
将代表最小值,例如[$:2]
就代表[0:2]
。同理,如果放在表达式的右边,则代表最大值。
- 如果把
- 队列常量的初始化同填充数组(合并数组)一样没有单引号!
b
和q
和j
共用变量类型int
,所以它们之间是逗号隔开!队列{3, 4}
左侧3是队头,右侧4是队尾!insert(x, y)
:在第x个位置元素之前插入值为y的元素push_front(x)
:在队头插入值为x的元素;push_back(x)
:在队尾插入值为x的元素;
pop_back
:队尾元素出队pop_front
:队头元素出队
push
和pop
只能操作队首或者队尾,相当于一个FIFO行为!delete(x)
:删除第x个位置元素
队列中的元素是连续存放的,所以队列的前面或者后面存取数据非常方便。无论队列有多大,这种操作(前后存取数据)所耗费的时间都是一样的。在队列中间增加或删除元素需要对已经存在的数据进行搬移以便腾出空间。相应操作所耗费的时间会随着队列的大小线性增加。
六、联合数组(关联数据)
SV提供了关联数组类型,用来保存稀疏矩阵的元素,这意味着当你对一个非常大的地址空间进行寻址时,SV只为实际写入的元素分配空间。关联数组可以采用树或哈希表的形式来存放关联数组,但有一定的额外开销。但当保存索引值比较分散的数组时,如32位地址或64位数据作为索引的数据包,这种额外开销显然是可以接受的!
- 关联数组声明采用在方括号中放置数据类型,
data_type associative_array_name[data_type]
- 使用稀疏的内存空间
- 动态分配,非连续元素(有点类似链表)
- 一维,可以利用整数和字符串作为索引。
注:联合数组声明也可以使用
*
在方括号中,但是不推荐,这里仅作为了解即可!
联合数组操作
- 联合数组可以使用
foreach
进行初始化 - 读取未分配的元素,4值逻辑变量返回x,2值逻辑变量返回0
- 支持函数:
first,next,prev,delete,exists
关联数组的更多使用,可参考:
七、数组方法(内置函数)
- 数组递减方法(用于非填充数组:固定数组、动态数组、队列和联合数组)
- 求和
sum
,求积product
、与and
、或or
、异或xor
a.sum
单比特数组的求和返回单比特的数值- 这个就能解释通为什么要把
data_in
定义成33bit
了!
- 这个就能解释通为什么要把
- 求最大值
max
,最小值min
,唯一化unique
(去重)【注意,它们的返回值是一个队列】
on.sum
中sum后面的括号可加可不加
数组排序操作
- 翻转:reverse
- 乱序:shuffle
- 升序排列:sort
- 降序排列:rsort
数组定位操作
- 查找元素:find
- 可以找某一类元素,定义这一类元素的范围,即特点
- 查找第一个元素:find_first
- 查找第一个元素的索引:find_first_with_index
- with 和 item都是关键字,item表示所有元素!
- 注意带index是返回索引!
- 注意动态数组的初始化,用的是固定数组的初始化方式,这种是可以的!new是当元素个数变化时用的!
d.sum(x) with(x > 7)
中x>7
返回的是一个逻辑结果,即结果只有0和1两种。
上述代码实操
- 可以看到第一个
count
应该打印出2,这里为什么是0呢?- 还是我们上面讲的:
with(x > 7)
返回的逻辑结果是单bit的,而单比特数组的求和返回单比特的数值,故这里就错误了!解决办法,强制转换在其后面乘上1,这个1是32bit的 - 总结:只有单纯逻辑运算的,都需要去做转换!
- 还是我们上面讲的:
八、数组使用推荐
固定数组
- 编译时,数组元素的个数是固定的
- 连续存放数据(相比联合数组)
- 多维数组
动态数组
- 编译时,不知道数组元素的个数
- 连续存放数据(相比联合数组)
队列
- FIFO/Stack
- 特殊的动态数组,相比动态数组优势可以实现元素的快速删减,不需要
new()
来重新更新!
联合数组
- 稀疏数据和内存(存储不连续)
- 索引号可以是整数或字符串
九、结构体
- 结构体的关键字是:struct
- 结构体是有一组变量或者常数组成的集合,可以作为一个整体进行操作,也可以操作其中的一部分
- 将逻辑上相关的信号放在一起,比如总线协议:
struct{
int a, b;
logic [7:0] opcode;
logic [23:0] address;
bit error;
}instruction_Word
- 使用结构体的名字来操作整个变量
<structure_name>.<variable_name>
instruction_Word.address =24'hF00000;
填充结构体
- 结构体默认情况下是非填充的
- 不同的EDA工具的排列是不一样
- 使用关键字
packed
可以将结构体声明成填充的结构体- 填充结构体将所有的数据元素存储在连续的单元内
- 结构体的第一个元素是适量的最左侧域(不同的EDA工具可能不一样!)
- 填充结构体可以通过变量名或者部分矢量选择来使用结构体中的变量
data_word tag = 8'hf0; data_word [39:32] = 8'hf0;
- 填充结构体操作
- 填充结构体的赋值
data_word = '{1'b1, 8'hff, 32'd1024};
- 1
十、枚举
- 抽象变量代表一个数值序列
- 用户可以定义每一个数值
- 增加了可阅读性
- 支持
first、last、next、prev
操作
enum {
RED,GREEN, BLUE} RGB
- 1
默认标号依次是:0 / 1 / 2
枚举类型默认的值为int
- 第一个值为
0
,第二个值为1
,依次递增
- 第一个值为
- SystemVerilog 支持显式指定每个数值
- 所有的数值必须唯一
- 对于没有指定数值的元素,其数值是按照前一个元素的数值加1
- 枚举变量的基础类型
- SystemVerilog 允许显式指定基础类型
- 枚举变量数值
- 赋值的变量的值必须匹配基础类型
- 枚举类型的数值大小
- 取值范围不能超多基础类型的有效范围(系统会自动根据已定义变量确定取值范围!)
- 给四值逻辑变量赋值X/Z是合法的
- 必须给x/z之后的变量显示赋值
十一、字符串
string variable_name [=initial_value];
中括号中的内容是可选的,也即初始值是可选的!- 在未赋值的情况下,string类型变量的值初始化为空字符
""
- 系统函数
$psprintf()
生成字符串 - 字符串变量类型具有内建的操作符和函数
==,!=,compare() 和 icompare();
itoa(), atoi(), atohex(), toupper(), tolower()
等len(), getc(), putc(), substr()
十二、实践练习
12.1、bit/logic练习
12.1.1、二值和四值变量初始值练习
sv_bit_logic.sv
module sv_bit_logic();
logic [7:0] sig_logic;
bit [7:0] sig_bit;
byte sig_byte;
shortint sig_sint;
int sig_int;
longint sig_lint;
initial begin
$display("********************************initial value test********************************");
$display("**********************************************************************************");
$display("*************************4 state varialbe initial value***************************");
$display("***************Initial value of logic type signal sig_logic = %0b*****************", sig_logic);
$display("**********************************************************************************");
$display("**********************************************************************************");
$display("*************************2 state varialbe initial value***************************");
$display("***************Initial value of logic type signal sig_bit = %0b*****************", sig_bit);
$display("***************Initial value of logic type signal sig_byte = %0b*****************", sig_byte);
$display("***************Initial value of logic type signal sig_sint = %0b*****************", sig_sint);
$display("***************Initial value of logic type signal sig_int = %0b*****************", sig_int);
$display("***************Initial value of logic type signal sig_lint = %0b*****************", sig_lint);
$display("**********************************************************************************");
end
endmodule
Makefile
comp_file = ;
all: comp run log open
comp:
vcs -full64 -sverilog -debug_all -timescale=1ns/1ps $(comp_file) -l comp.log
run:
./simv -l $(comp_file).log
log:
sed '/^[^*].*/d' $(comp_file).log > rslt.log
open:
gvim rslt.log
clean:
sed '/^[^*].*/d' $(comp_file).log > rst.log
:正则表达,作用是开头不是星号*
的行就把它删掉,删掉之后剩余有星号的行放到文件rslt.og
里
运行命令如下:
make comp_file=sv_bit_logic.sv
- 1
rslt.log
********************************initial value test********************************
**********************************************************************************
*************************4 state varialbe initial value***************************
***************Initial value of logic type signal sig_logic = xxxxxxxx*****************
**********************************************************************************
**********************************************************************************
*************************2 state varialbe initial value***************************
***************Initial value of logic type signal sig_bit = 0*****************
***************Initial value of logic type signal sig_byte = 0*****************
***************Initial value of logic type signal sig_sint = 0*****************
***************Initial value of logic type signal sig_int = 0*****************
***************Initial value of logic type signal sig_lint = 0*****************
**********************************************************************************
sig_logic
是个八位的四值变量,所以打印出来的是8个x
- 其他都是二值变量,默认初始值是
0
12.1.2、$isunknown
练习
在sv_bit_logic.sv
中添加相关代码:
...
$display("********************************$isunknown() test ********************************");
if($isunknown(sig_logic) == 1) begin
$display("***************Initial value of sig_logic is X*****************");
end
else begin
$display("***************Initial value of sig_logic is not X*****************");
end
if($isunknown(sig_bit) == 1) begin
$display("***************Initial value of sig_bit is X*****************");
end
else begin
$display("***************Initial value of sig_bit is not X*****************");
end
...
... ********************************$isunknown() test ******************************** ***************Initial value of sig_logic is X***************** ***************Initial value of sig_bit is not X*****************
12.1.3、无符号和有符号数练习
在
sv_bit_logic.sv
中添加相关代码:... $display("********************************signed & unsigned test ********************************"); sig_logic = 8'b1000_1010; sig_bit = 8'b1000_1010; sig_byte = 8'b1000_1010; $display("***************sig_logic(8'b1000_1010) = %0d*****************", sig_logic); $display("***************sig_bit (8'b1000_1010) = %0d*****************", sig_bit ); $display("***************sig_byte (8'b1000_1010) = %0d*****************", sig_byte ); ...
rslt.log
... ********************************signed & unsigned test ******************************** ***************sig_logic(8'b1000_1010) = 138***************** ***************sig_bit (8'b1000_1010) = 138***************** ***************sig_byte (8'b1000_1010) = -118*****************
bit/logic
的位宽是用户自定义的,并且是无符号数;byte/shortint/int/longint
的位宽是固定的,并且是有符号数!
12.1.4、全0/1/x/z
赋值练习
在sv_bit_logic.sv
中添加相关代码:
... $display("********************************all zeros, one test********************************"); sig_logic = '0; $display("***************sig_logic = '0 is %0b*****************", sig_logic); sig_logic = '1; $display("***************sig_logic = '1 is %0b*****************", sig_logic); sig_logic = 'x; $display("***************sig_logic = 'x is %0b*****************", sig_logic); sig_logic = 'z; $display("***************sig_logic = 'z is %0b*****************", sig_logic); ...
rslt.log
... ********************************all zeros, one test******************************** ***************sig_logic = '0 is 0***************** ***************sig_logic = '1 is 11111111***************** ***************sig_logic = 'x is xxxxxxxx***************** ***************sig_logic = 'z is zzzzzzzz*****************
- 0有几个无所谓,反正都是0,所以这里打印是正确的!
12.2、固定数组练习
12.2.1、unpacked array ininial demo(非填充数组初始化demo)
sv_fix_array.sv
module sv_fix_array();
int src[5];
int dst[5];
logic [31:0] src_logic[5] = '{
5{
2}};
bit [3:0][7:0] packed_src;
initial begin
$display("**************************************************");
$display("*************unpacked array ininial demo**********");
$display("****size of src[5] is : %0d*********************", $size(src));
$display("****size of dst[5] is : %0d*********************", $size(dst));
foreach(src[i]) begin
src[i] = i;
$display("****src[%0d] = %0d*********************", i, src[i]);
end
foreach(dst[i]) begin
dst[i] = 5-i;
$display("****dst[%0d] = %0d*********************", i, dst[i]);
end
if( src == dst ) begin
$display("*********src == dst********");
end
else begin
$display("*********src != dst********");
foreach(src[i]) begin
$display("***src[%0d] = %1d, dst[%0d] = %1d***", i, src[i], i, dst[i]);
end
end
$display("**************************************************");
end
endmodule
Makefile
文件同5.1
,直接拷贝过来。运行命令如下:make comp_file=sv_fix_array.sv
rslt.log
************************************************** *************unpacked array ininial demo********** ****size of src[5] is : 5********************* ****size of dst[5] is : 5********************* ****src[0] = 0********************* ****src[1] = 1********************* ****src[2] = 2********************* ****src[3] = 3********************* ****src[4] = 4********************* ****dst[0] = 5********************* ****dst[1] = 4********************* ****dst[2] = 3********************* ****dst[3] = 2********************* ****dst[4] = 1********************* *********src != dst******** ***src[0] = 0, dst[0] = 5*** ***src[1] = 1, dst[1] = 4*** ***src[2] = 2, dst[2] = 3*** ***src[3] = 3, dst[3] = 2*** ***src[4] = 4, dst[4] = 1*** **************************************************
12.2.2、unpacked array assignment demo(非填充数组赋值demo)
在
sv_fix_array.sv
中添加相关代码:... $display("*************unpacked array assignment demo**********"); dst = src; $display("*************after dst = src**********"); foreach(src[i]) begin $display("***src[%0d] = %1d, dst[%0d] = %1d***", i, src[i], i, dst[i]); end src[0] = 5; $display("*************after src[0] = 5**********"); foreach(src[i]) begin $display("***src[%0d] = %1d, dst[%0d] = %1d***", i, src[i], i, dst[i]); end if( src[1:4] == dst[1:4] ) begin $display("*********src == dst********"); end else begin $display("*********src != dst********"); foreach(src[i]) begin $display("***src[%0d] = %1d, dst[%0d] = %1d***", i, src[i], i, dst[i]); end ...
rslt.log
*************unpacked array assignment demo********** *************after dst = src********** ***src[0] = 0, dst[0] = 0*** ***src[1] = 1, dst[1] = 1*** ***src[2] = 2, dst[2] = 2*** ***src[3] = 3, dst[3] = 3*** ***src[4] = 4, dst[4] = 4*** *************after src[0] = 5********** ***src[0] = 5, dst[0] = 0*** ***src[1] = 1, dst[1] = 1*** ***src[2] = 2, dst[2] = 2*** ***src[3] = 3, dst[3] = 3*** ***src[4] = 4, dst[4] = 4*** *********src == dst********
12.2.3、unpacked array partial assign demo(非填充数组部分赋值demo)
在
sv_fix_array.sv
中添加相关代码:$display("**************************************************"); $display("*************unpacked array partial assign demo**********"); src = '{ 5{ 5}}; foreach(src[i]) begin $display("***src[%0d] = %1d ***", i, src[i]); end $display("***src[0] = %0b ***", src[0]); $display("***src[0][0] = %0b ***", src[0][0]); $display("***src[2][2:1] = %0b ***",src[2][2:1]);
rslt.log
************************************************** *************unpacked array partial assign demo********** ***src[0] = 5 *** ***src[1] = 5 *** ***src[2] = 5 *** ***src[3] = 5 *** ***src[4] = 5 *** ***src[0] = 101 *** ***src[0][0] = 1 *** ***src[2][2:1] = 10 ***
12.2.4、array over read demo(数组越界读demo)
在
sv_fix_array.sv
中添加相关代码:... logic [31:0] src_logic[5] = '{ 5{ 2}}; ... $display("*************array over read demo**********"); $display("***over read int type src[10] = %0b ***", src[10]); $display("***over read logic src_logic[10] = %0b ***", src_logic[10]); ...
rslt.log
*************array over read demo********** ***over read int type src[10] = 0 *** ***over read logic src_logic[10] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ***
- 1
- 2
- 3
- 二值变量越界是
0
态 - 注意四值变量越界是
x
态,并且是对应位数个x
。在此处src_logic是32位,所以是32个x
12.2.5、packed array assign demo(填充数组赋值demo)
在sv_fix_array.sv
中添加相关代码:
$display("*************packed array assign demo**********");
packed_src = {
8'h3, 8'h2, 8'h1, 8'h0};
foreach(packed_src[i]) begin
$display("***packed_src[%0d] = %1d ***", i, packed_src[i]);
end
rslt.log
*************packed array assign demo**********
***packed_src[3] = 3 ***
***packed_src[2] = 2 ***
***packed_src[1] = 1 ***
***packed_src[0] = 0 ***
- 填充数组赋值花括号前可以不用加
'
- 注意填充数组的索引是从右往左的,右边的是
0
。
12.3、动态数组练习
12.3.1、dynamic array initial demo(动态数组初始化demo)
sv_dyn_array.sv
module sv_dyn_array();
int dyn1[];
int dyn2[];
initial begin
$display("***dynamic array initial demo***");
$display("***Before dyn1=new[5], size of dyn1 is : %0d ***", $size(dyn1));
dyn1 = new[5];
$display("***After dyn1=new[5], size of dyn1 is : %0d ***", $size(dyn1));
foreach(dyn1[i]) begin
dyn1[i] = i;
$display("****** dyn1[%0d]=%0d", i, dyn1[i]);
end
end
endmodule
rslt.log
***dynamic array initial demo***
***Before dyn1=new[5], size of dyn1 is : 0 ***
***After dyn1=new[5], size of dyn1 is : 5 ***
****** dyn1[0]=0
****** dyn1[1]=1
****** dyn1[2]=2
****** dyn1[3]=3
****** dyn1[4]=4
- Makefile 同之前,不过是
comp_file
参数变了:make comp_file=sv_dyn_array.sv
12.3.2、dynamic array assignment demo(动态数组赋值demo)
sv_dyn_array.sv
$display("***dynamic array initial demo***");
dyn2 = dyn1;
dyn2[0] = 5;
$display("***After dyn2=dyn1 & dyn2[0]=5***");
foreach(dyn2[i]) begin
$display("****** dyn1[%0d]=%0d, dyn2[%0d]=%0d", i, dyn1[i], i, dyn1[i]);
end
dyn1=new[20](dyn1);
$display("******After dyn1=new[20](dyn1)******");
foreach(dyn1[i]) begin
$display("****** dyn1[%0d]=%0d", i, dyn1[i]);
end
dyn1=new[10];
$display("******After dyn1=new[10]******");
foreach(dyn1[i]) begin
$display("****** dyn1[%0d]=%0d", i, dyn1[i]);
end
rslt.log
***dynamic array initial demo***
***After dyn2=dyn1 & dyn2[0]=5***
****** dyn1[0]=0, dyn2[0]=0
****** dyn1[1]=1, dyn2[1]=1
****** dyn1[2]=2, dyn2[2]=2
****** dyn1[3]=3, dyn2[3]=3
****** dyn1[4]=4, dyn2[4]=4
******After dyn1=new[20](dyn1)******
****** dyn1[0]=0
****** dyn1[1]=1
****** dyn1[2]=2
****** dyn1[3]=3
****** dyn1[4]=4
****** dyn1[5]=0
****** dyn1[6]=0
****** dyn1[7]=0
****** dyn1[8]=0
****** dyn1[9]=0
****** dyn1[10]=0
****** dyn1[11]=0
****** dyn1[12]=0
****** dyn1[13]=0
****** dyn1[14]=0
****** dyn1[15]=0
****** dyn1[16]=0
****** dyn1[17]=0
****** dyn1[18]=0
****** dyn1[19]=0
******After dyn1=new[10]******
****** dyn1[0]=0
****** dyn1[1]=0
****** dyn1[2]=0
****** dyn1[3]=0
****** dyn1[4]=0
****** dyn1[5]=0
****** dyn1[6]=0
****** dyn1[7]=0
****** dyn1[8]=0
****** dyn1[9]=0
dyn1=new[20](dyn1)
不会覆盖已赋值的;而dyn1=new[10]
会覆盖已赋值的!
12.3.3、dynamic array delete demo(动态数组删除demo)
sv_dyn_array.sv
$display("***dynamic array delete demo***");
dyn1.delete();
$display("*******After dyn1.delete******");
d i s p l a y < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ( < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " ∗ ∗ ∗ ∗ A f t e r d e l e t i o n , d y n 1 s i z e i s : display</span><span class="token punctuation">(</span><span class="token string">"****After deletion, dyn1 size is : %0d"</span>, <span class="token variable"> display</span><spanclass="tokenpunctuation">(</span><spanclass="tokenstring">"∗∗∗∗Afterdeletion,dyn1sizeis:size(dyn1));
foreach(dyn1[i]) begin
$display(“****** dyn1[%0d]=%0d”, i, dyn1[i]);
end
rslt.log
***dynamic array delete demo*** *******After dyn1.delete****** ****After deletion, dyn1 size is : 0
12.4、队列练习
12.4.1、队列内建函数demo(有bug)
sv_queue.sv
module sv_queue(); int q[$] = { 1, 3, 5, 7}; int tq[$]; int d[$] = '{9, 1, 8, 3, 4, 4}; int f[$] = '{ 1, 6, 2, 6, 8, 6}; initial begin foreach(q[i]) begin $display("******q[%0d] = %0d******", i, q[i]); end $display("******summation of q{1, 3, 5, 7} = %0d, ******", q.sum); $display("******product of q{1, 3, 5, 7} = %0d, ******", q.product); $display("******minimum of q{1, 3, 5, 7} = %0d, ******", q.min); $display("******maximum of q{1, 3, 5, 7} = %0d, ******", q.max); tq = f.unique; foreach(tq[i]) begin $display("******unique of queue f{1,6,2,6,8,6}[%0d] = %0d******", i, tq[i]); end end endmodule
rslt.sv
******q[0] = 1****** ******q[1] = 3****** ******q[2] = 5****** ******q[3] = 7****** ******summation of q{ 1, 3, 5, 7} = 16, ****** ******product of q{ 1, 3, 5, 7} = 105, ****** ******minimum of q{ 1, 3, 5, 7} = -1207817664, ****** ******maximum of q{ 1, 3, 5, 7} = -1207816928, ****** ******unique of queue f{ 1,6,2,6,8,6}[0] = 1****** ******unique of queue f{ 1,6,2,6,8,6}[1] = 6****** ******unique of queue f{ 1,6,2,6,8,6}[2] = 2****** ******unique of queue f{ 1,6,2,6,8,6}[3] = 8******
疑问:为什么max和min打印的值不对呢?
- Makefile 同之前,不过是
comp_file
参数变了:make comp_file=sv_queue.sv
- 语法要求,对于队列,需要
'
初始化,但是现在工具比较强大,不加也没关系!
12.4.2、队列插入删除demo
sv_queue.sv
$display("******Queue operation demo******"); q.insert(1, 2); $display("***q{1,3,5,7} after q.insert(1,2) becomes : {%0d,%0d,%0d,%0d,%0d}******", q[0],q[1],q[2],q[3],q[4]); q.insert(3, 4); $display("***q{1,2,3,5,7} after q.insert(3,4) becomes : {%0d,%0d,%0d,%0d,%0d,%0d}******",q[0],q[1],q[2],q[3],q[4],q[5]); q.insert(5, 6); $display("***q{1,2,3,4,5,7} after q.insert(5,6) becomes : {%0d,%0d,%0d,%0d,%0d,%0d,%0d}******",q[0],q[1],q[2],q[3],q[4],q[5],q[6]); q.delete(5); $display("***q{1,2,3,4.5,6,7} after q.delete(5) becomes : {%0d,%0d,%0d,%0d,%0d,%0d}******",q[0],q[1],q[2],q[3],q[4],q[5]); q.delete(3); $display("***q{1,2,3,4,5,7} after q.delete(3) becomes : {%0d,%0d,%0d,%0d,%0d}******",q[0],q[1],q[2],q[3],q[4]); q.delete(1); $display("***q{1,2,3,5,7} after q.delete(1) becomes : {%0d,%0d,%0d,%0d}******",q[0],q[1],q[2],q[3]);
******Queue operation demo****** ***q{ 1,3,5,7} after q.insert(1,2) becomes : { 1,2,3,5,7}****** ***q{ 1,2,3,5,7} after q.insert(3,4) becomes : { 1,2,3,4,5,7}****** ***q{ 1,2,3,4,5,7} after q.insert(5,6) becomes : { 1,2,3,4,5,6,7}****** ***q{ 1,2,3,4.5,6,7} after q.delete(5) becomes : { 1,2,3,4,5,7}****** ***q{ 1,2,3,4,5,7} after q.delete(3) becomes : { 1,2,3,5,7}****** ***q{ 1,2,3,5,7} after q.delete(1) becomes : { 1,3,5,7}******
12.4.3、入队出队demo
sv_queue.sv
$display("*******************************"); for(int i=0; i<4; i=i+1) begin $display("***q{1,3,5,7} the %0d times q.pop_front value %0d***", i, q.pop_front); end $display("******* After 4 times pop_front for q{1,3,5,7}******"); $display("***q[0]=%0d,q[1]=%0d,q[2]=%0d,q[3]=%0d***",q[0],q[1],q[2],q[3]); for(int i=0; i<4; i=i+1) begin q.push_back(2*i+1); $display("*** the %0d times q.push_back value %0d***", i, 2*i+1); end $display("******* After 4 times push_back(2*i+1) for q{} ******"); $display("***q[0]=%0d,q[1]=%0d,q[2]=%0d,q[3]=%0d***",q[0],q[1],q[2],q[3]);
rslt.sv
******************************* ***q{ 1,3,5,7} the 0 times q.pop_front value 1*** ***q{ 1,3,5,7} the 1 times q.pop_front value 3*** ***q{ 1,3,5,7} the 2 times q.pop_front value 5*** ***q{ 1,3,5,7} the 3 times q.pop_front value 7*** ******* After 4 times pop_front for q{ 1,3,5,7}****** ***q[0]=0,q[1]=0,q[2]=0,q[3]=0*** *** the 0 times q.push_back value 1*** *** the 1 times q.push_back value 3*** *** the 2 times q.push_back value 5*** *** the 3 times q.push_back value 7*** ******* After 4 times push_back(2*i+1) for q{ } ****** ***q[0]=1,q[1]=3,q[2]=5,q[3]=7***
12.5、数组方法练习
12.5.1、求和、求积方法demo
sv_array_method.sv
module sv_array(); int on[6]; int td[6]; int dq[$]; int sum; int product; int x; initial begin $display("***array methods demo***"); foreach(on[i]) begin on[i] = i; $display("******on[%0d] = %0d", i, on[i]); end $display("*********on.sum=%0d*********", on.sum); $display("*********on.product=%0d*********", on.product); on.reverse(); $display("***on reverse : %0d, %0d, %0d, %0d, %0d, %0d***",on[0],on[1],on[2],on[3],on[4],on[5]); on.shuffle; $display("***on shuffle : %0d, %0d, %0d, %0d, %0d, %0d***",on[0],on[1],on[2],on[3],on[4],on[5]); on.sort; $display("***on sort : %0d, %0d, %0d, %0d, %0d, %0d***",on[0],on[1],on[2],on[3],on[4],on[5]); on.rsort; $display("***on rsort : %0d, %0d, %0d, %0d, %0d, %0d***",on[0],on[1],on[2],on[3],on[4],on[5]); end endmodule
- Makefile 同之前,不过是
comp_file
参数变了:make comp_file=sv_array_method.sv
rslt.log
***array methods demo*** ******on[0] = 0 ******on[1] = 1 ******on[2] = 2 ******on[3] = 3 ******on[4] = 4 ******on[5] = 5 *********on.sum=15********* *********on.product=0********* ***on reverse : 5, 4, 3, 2, 1, 0*** ***on shuffle : 3, 4, 2, 5, 0, 1*** ***on sort : 0, 1, 2, 3, 4, 5*** ***on rsort : 5, 4, 3, 2, 1, 0***
12.5.2、队列找某元素或索引方法,带条件的求和demo
sv_array_method.sv
$display("********************************"); dq=on.find(x) with (x>3); $display("***dp=on.find(x) with(x>3) dq: %0d, %0d, %0d, %0d, %0d, %0d***",dq[0],dq[1],dq[2],dq[3],dq[4],dq[5]); dq=on.find_index(x) with (x>3); $display("***dp=on.find_index(x) with(x>3) dq: %0d, %0d, %0d, %0d, %0d, %0d***",dq[0],dq[1],dq[2],dq[3],dq[4],dq[5]); sum=on.sum(x) with (x>3); $display("***sum=on.sum(x) with (x>3) sum : %0d", sum); sum=on.sum(x) with ((x>3) * 1); $display("***sum=on.sum(x) with ((x>3) * 1) sum : %0d", sum); sum=on.sum(x) with ((x>3) * x); $display("***sum=on.sum(x) with ((x>3) * x) sum : %0d", sum);
rslt.log
******************************** ***dp=on.find(x) with(x>3) dq: 5, 4, 0, 0, 0, 0*** ***dp=on.find_index(x) with(x>3) dq: 0, 1, 0, 0, 0, 0*** ***sum=on.sum(x) with (x>3) sum : 0 ***sum=on.sum(x) with ((x>3) * 1) sum : 2 ***sum=on.sum(x) with ((x>3) * x) sum : 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
sum=on.sum(x) with (x>3)
这种写法最后只会取结果的最低1个bit位;- 上面大于3的只有5和4,所以
x>3
比较后两个1。两个1求和是2,对应二进制是0010,因为只取最低1bit位,所以此处是0. - 要想把几个1的求和结果显示出来,那就
(x>3)*1
,1默认是32bit的,这样最终结果就是32bit的了 - 要想把
x>3
的数求和,那就(x>3)*x
- 上面大于3的只有5和4,所以
注意
find_index
是对应x>3
的索引值:0 1
后面的4个0是无效的0,可以对比find
结果来看!
12.6、结构体、枚举练习
12.6.1、结构体(unpacked struct)赋值demo
sv_struct_enum.sv
module
sv_struct_enum();
struct {
int height;
int weight;
logic [7:0] legs;
logic [7:0] hands;
logic [1:0] eyes;
logic noses;
} animal;
struct packed {
int height;
int weight;
logic [7:0] legs;
logic [7:0] hands;
logic [1:0] eyes;
logic noses;
} animal_packed;
enum {
IDLE, SFD, PREAMBLE, DATA, FCS, EFD} cur_st;
enum {
RED=1, GREEN, BULE} rgb;
initial begin
animal.height = 32'd132; animal.weight = 32'd200;
animal.legs = 8'd2; animal.hands = 2'd2;
animal.eyes = 2'd2; animal.noses = 1'd1;
$display("******@%0tns animal unpacked value *******", $time);
$display("******@%0tns height : %0d *******", $time, animal.height);
$display("******@%0tns weight : %0d *******", $time, animal.weight);
$display("******@%0tns legs : %0d *******", $time, animal.legs);
$display("******@%0tns hands : %0d *******", $time, animal.hands);
$display("******@%0tns eyes : %0d *******", $time, animal.eyes);
$display("******@%0tns noses : %0d *******", $time, animal.noses);
end
endmodule
rslt.log
******@0ns animal unpacked value *******
******@0ns height : 132 *******
******@0ns weight : 200 *******
******@0ns legs : 2 *******
******@0ns hands : 2 *******
******@0ns eyes : 2 *******
******@0ns noses : 1 *******
- Makefile 同之前,不过是
comp_file
参数变了:make comp_file=sv_struct_enum.sv
12.6.2、结构体(packed struct)赋值demo
sv_struct_enum.sv
animal_packed = '{32'd132,32'd200,8'd2,8'd2,8'd2,1'd1};
#1
$display("******@%0tns animal packed value *******", $time);
$display("******@%0tns height : %0d *******", $time, animal_packed.height);
$display("******@%0tns weight : %0d *******", $time, animal_packed.weight);
$display("******@%0tns legs : %0d *******", $time, animal_packed.legs);
$display("******@%0tns hands : %0d *******", $time, animal_packed.hands);
$display("******@%0tns eyes : %0d *******", $time, animal_packed.eyes);
$display("******@%0tns noses : %0d *******", $time, animal_packed.noses);
rslt.log
******@1000ns animal packed value *******
******@1000ns height : 132 *******
******@1000ns weight : 200 *******
******@1000ns legs : 2 *******
******@1000ns hands : 2 *******
******@1000ns eyes : 2 *******
******@1000ns noses : 1 *******
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 注意
packed struct
赋值方式是特有的,当然它也可以用unpacked struct
那种赋值方式! - 还需要注意
packed struct
的赋值花括号前需要加'
12.6.3、枚举的赋值demo
sv_struct_enum.sv
$display("******@%0tns Enumeration test *******", $time);
$display("******@%0tns cur_st Range {IDLE, SFD, PREAMBLE, DATA, FCS, EFD} *******", $time);
$display("******@%0tns Initial Value of cur_st : %s=%0d****", $time,cur_st,cur_st);
#5 cur_st = IDLE;
$display("******@%0tns Current Value of cur_st : %s=%0d****", $time,cur_st,cur_st);
#5 cur_st = SFD;
$display("******@%0tns Current Value of cur_st : %s=%0d****", $time,cur_st,cur_st);
#5 cur_st = 3;
$display("******@%0tns Current Value of cur_st : %s=%0d****", $time,cur_st,cur_st);
#5 rgb = RED;
d i s p l a y < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ( < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " ∗ ∗ ∗ ∗ ∗ ∗ @ display</span><span class="token punctuation">(</span><span class="token string">"******@%0tns rgb Value of rgb : %s=%0d****"</span>, <span class="token variable"> display</span><spanclass="tokenpunctuation">(</span><spanclass="tokenstring">"∗∗∗∗∗∗@time,rgb,rgb);
#5 rgb = GREEN;
d i s p l a y < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ( < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " ∗ ∗ ∗ ∗ ∗ ∗ @ display</span><span class="token punctuation">(</span><span class="token string">"******@%0tns rgb Value of rgb : %s=%0d****"</span>, <span class="token variable"> display</span><spanclass="tokenpunctuation">(</span><spanclass="tokenstring">"∗∗∗∗∗∗@time,rgb,rgb);
#5 rgb = 2;
d i s p l a y < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ( < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " ∗ ∗ ∗ ∗ ∗ ∗ @ display</span><span class="token punctuation">(</span><span class="token string">"******@%0tns rgb Value of rgb : %s=%0d****"</span>, <span class="token variable"> display</span><spanclass="tokenpunctuation">(</span><spanclass="tokenstring">"∗∗∗∗∗∗@time,rgb,rgb);
- 枚举元素的类型默认是字符串的,如果直接赋值整型编译可能会有warning:
Warning-[ENUMASSIGN] Illegal assignment to enum variable
。可以使用cast
进行强制转换,即:$cast(curs_st, 3)
rslt.log
******@1000ns Enumeration test *******
******@1000ns cur_st Range {
IDLE, SFD, PREAMBLE, DATA, FCS, EFD} *******
******@1000ns Initial Value of cur_st : IDLE=0****
******@6000ns Current Value of cur_st : IDLE=0****
******@11000ns Current Value of cur_st : SFD=1****
******@16000ns Current Value of cur_st : DATA=3****
******@21000ns rgb Value of rgb : RED=1****
******@26000ns rgb Value of rgb : GREEN=2****
******@31000ns rgb Value of rgb : GREEN=2****
12.7、字符串练习
12.7.1、字符串赋值demo
string.sv
module STRING();
string name;
string s =“now is the time”;
string old_s;
string a;
initial begin
for<span class="token punctuation">(</span>int <span class="token assign-left variable">i</span><span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> i<span class="token operator"><</span><span class="token number">4</span><span class="token punctuation">;</span> i++<span class="token punctuation">)</span> begin
name <span class="token operator">=</span> <span class="token variable">$psprintf</span><span class="token punctuation">(</span><span class="token string">"******string%0d"</span>, i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$display</span><span class="token punctuation">(</span><span class="token string">"******%s, upper:%s"</span>, name, name.toupper<span class="token punctuation">(</span><span class="token punctuation">))</span><span class="token punctuation">;</span>
end
end
endmodule
- Makefile 同之前,不过是
comp_file
参数变了:make comp_file=string.sv
rslt.log
************string0, upper:******STRING0
************string1, upper:******STRING1
************string2, upper:******STRING2
************string3, upper:******STRING3
- 1
- 2
- 3
- 4
- 注意module的名字不能是string,所以这里大写了
12.7.2、获取、写入字符串中的单个字符demo
string.sv
old_s = s; for(int i=0; i<s.len; i++) begin a = s.getc(i); $display("****** the %dth character in string (%s) is : %c", i, s, a); end
s.putc<span class="token punctuation">(</span>s.len<span class="token punctuation">(</span><span class="token punctuation">)</span>-1, s.getc<span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">))</span><span class="token punctuation">;</span> <span class="token variable">$display</span><span class="token punctuation">(</span><span class="token string">"******After s.putc(s.len()-1, s.getc(5))"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$display</span><span class="token punctuation">(</span><span class="token string">"******Old string : %s"</span>, old_s<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$display</span><span class="token punctuation">(</span><span class="token string">"******new string : %s"</span>, s<span class="token punctuation">)</span><span class="token punctuation">;</span>
rslt.log
****** the 0th character in string (now is the time) is : n
****** the 1th character in string (now is the time) is : o
****** the 2th character in string (now is the time) is : w
****** the 3th character in string (now is the time) is :
****** the 4th character in string (now is the time) is : i
****** the 5th character in string (now is the time) is : s
****** the 6th character in string (now is the time) is :
****** the 7th character in string (now is the time) is : t
****** the 8th character in string (now is the time) is : h
****** the 9th character in string (now is the time) is : e
****** the 10th character in string (now is the time) is :
****** the 11th character in string (now is the time) is : t
****** the 12th character in string (now is the time) is : i
****** the 13th character in string (now is the time) is : m
****** the 14th character in string (now is the time) is : e
******After s.putc(s.len()-1, s.getc(5))
******Old string : now is the time
******new string : now is the tims
12.7.3、截取字符串的某一部分
string.sv
old_s = s;
s = s.substr(s.len()-4, s.len()-1);
$display("******After substring s.substr(s.len()-4, s.len()-1)");
$display("******old string : %s", old_s);
$display("******new string : %s", s);
rslt.log
******After substring s.substr(s.len()-4, s.len()-1)
******old string : now is the tims
******new string : tims
substr
还可以直接填索引值,如s.substr(1, 3)
边栏推荐
- Value sequence (subsequence contribution problem)
- Leetcode 43 String multiplication (2022.02.12)
- [UVM practice] Chapter 2: a simple UVM verification platform (2) only driver verification platform
- Common method signatures and meanings of Iterable, collection and list
- Cnopendata list data of Chinese colleges and Universities
- 【webrtc】m98 screen和window采集
- padavan手动安装php
- [guess-ctf2019] fake compressed packets
- Yugu p1020 missile interception (binary search)
- C语言航班订票系统
猜你喜欢
Implementation of replacement function of shell script
mysql多列索引(组合索引)特点和使用场景
2022年全国最新消防设施操作员(初级消防设施操作员)模拟题及答案
有 Docker 谁还在自己本地安装 Mysql ?
Technology cloud report: from robot to Cobot, human-computer integration is creating an era
Figure out the working principle of gpt3
Operation suggestions for today's spot Silver
Thinkcmf6.0安装教程
Quickly use Jacobo code coverage statistics
Explore Cassandra's decentralized distributed architecture
随机推荐
Force buckle 145 Binary Tree Postorder Traversal
These five fishing artifacts are too hot! Programmer: I know, delete it quickly!
[webrtc] M98 screen and window acquisition
leanote私有云笔记搭建
C language flight booking system
大视频文件的缓冲播放原理以及实现
Main window in QT learning 27 application
C语言航班订票系统
Linux server development, MySQL cache strategy
What are the positions of communication equipment manufacturers?
Live broadcast platform source code, foldable menu bar
Codeforces Global Round 19
QT learning 28 toolbar in the main window
2022茶艺师(初级)考试题模拟考试题库及在线模拟考试
dash plotly
SQL优化的魅力!从 30248s 到 0.001s
Visualization Document Feb 12 16:42
Thinkcmf6.0安装教程
C language queue
[mathematical notes] radian