数据类型
动态数组
int dyn[],d2[];// 声明动态数组
initial begin
dyn = new[5]; //分配5个元素
foreach(dyn[j]) dyn[j]=j;//对元素初始化 dyn{0,1,2,3,4}
d2 =dyn; // 复制一个动态数组 d2{0,1,2,3,4}
d2[0] = 5; // 修改复制值 d2{5,1,2,3,4}
$display(dyn[0],d2[0]);// 显示数值0和5
dyn = new[20](dyn); // 分配20个数值并进行复制。{0,1,2,3,4,0,0,0....};括号内总共有20个数值
dyn = new[100]; //重新分配100个数值,而旧值不复存在
dyn.delete(); //删除所有元素 // 等效于dyn=new[0]和dyn=`{};
end
队列
- 【队列】结合了链表和数组的优点,可以在它的任何地方添加或删除元素,并且通过索引实现对任一元素的访问
- 队列的声明是使用带有美元符号的下标:
[$]
,队列元素的标号是从0
到$
. - 队列不需要
new[]
去创建空间,你只需要使用队列的方法为其增减元素,一开始其空间为0。new[]
只对动态数组有用。 - 队列的一个简单使用即是通过其自带的简单方法push_back()和pop_front()的结合来实现FIFO的用法。
int j = 1, q2[$] = {3,4},q[$] = {0,2,5};// 队列赋值不使用'`'
initial begin
q.insert(1,j);//{0,1,2,5}在2前插入1
q.insert(3,q2); // {0,1,2,3,4,5} 在q中插入队列q2
q.delete(1); // {0,2,3,4,5} 删除索引为1的元素。如果直接使用q.delete默认删除所有元素
// 下列操作运行速度更快(自有方法)
q.push_front(6) ; {6,0,2,3,4,5} 在队列头部插入
j= q.pop_back(); // {6,0,2,3,4} 从队列尾部取出
q.push_back(8);// {6,0,2,3,4,8} 从队列尾部插入
j =q.pop_front(); //{0,2,3,4,8} 从队列头部取出
foreach(q[i])
$display(q[i]); //打印整个队列
q.delete();// {}删除整个队列
end
关联数组
[图片上传失败...(image-a9c356-1651413432498)]
- 【关联数组】可以用来保存稀疏矩阵的元素,当你对一个非常大的地址空间寻址时,该数组只为实际写入的元素分配空间,这种实现方法所需要的空间比定宽或动态数组所占用的空间要小得多。
- 此外,关联数组有其它灵活的应用,在其他软件语言也有类似的数据存储结构,被称之为哈希(Hash)或者字典(Dictionary),可以灵活赋予键值(key)和数值(value)。
bit [63:0] assoc[int] ,idx=1;
repeat(64) begin //对稀疏分布的元素进行初始化
assoc[idx] = idx;
idx = idx <=1;
end
foreach (assoc[i]) // 使用foreach遍历数组
$display("assoc[%h]= %h", i , assoc[i]);
// 使用函数遍历数组
if(assoc.first(idx)) begin // 得到第一个索引
do
$display("assoc[%h]=%h",idx,assoc[idx]);
while (assoc.next(idx));// Get next index
end
//找到并删除第一个元素
assoc.first(idx);
assoc.delete(idx);
结构体
- Verilog的最大缺陷之一是没有数据结构,在SV中可以使用struct语句创建结构,跟C语言类似。
- 不过struct的功能少,它只是一个数据的集合,其通常使用的方式是将若干相关的变量组个到一个struct结构的定义中
- 伴随typedef可以用来创建新的类型,并利用新类型来声明更多变量。
struct {bit [7:0] r,g,b;} pixel; // 创建一个pixel结构体
// 为了共享该类型,通过typedef来创建新类型
typedef struct {bit[7:0] r,g,b;} pixel_s;
pixel_s my_pixel ; // 声明变量
my_pixel = '{'h10,'h10,'h10}; // 结构体类型的赋值
枚举类型
- 规范的操作码和指令如ADD,WRITE、IDLE等有利于代码的编写和维护,它比直接使用'h01这样的常量使用起来可读性和可维护性更好。
- 枚举类型enum经常和typedef搭配使用,由此便于用户自定义枚举类型的共享使用。
- 枚举类型的出现保证了一些非期望值的出现,降低设计风险
typedef enum{INIT,DECODE,IDLE} fsmstate_e;
fsmstate_e pstate,nstate;// 声明自定义类型变量
case(pstate)
IDLE: nstate = INIT;// 数值赋值
INIT: nstate = DECODE;
default: nstate = IDLE;
endcase
$display("Next state is %s",nstate.name());//显示状态名
- 如果直接给nstate直接用整数赋值,那么该赋值本身不合法,需要进行转化才可以,枚举类型可以赋值给整型。
字符串
- 所有与字符串相关的处理,都请使用string来保存和处理
- 与字符串处理相关的还包括字符串的格式化函数即如何形成一个你想要的字符串句子呢?可以使用SV系统方法
$sformatf()
,如果只需要将它打印输出,那么就使用$dispaly
.
string s;
initial begin
s = "IEEE ";
$display(s.getc(0)); // 显示'I' getc返回字符
$display(s.tolower()); // 显示ieee
s.putc(s.len()-1,"-") ; // 替换操作,将空格变为‘-’
s = {s,"P1800"}; // 字符串拼接操作,得到“IEEE-P1800”
$display(s.substr(2,5)) ; // 显示EE-P;得到一个子字符串
// 创建一个临时字符串并将其打印
my_log($sformatf("%s %d",s,42));
end
task my_log(string message); // 打印消息
$display("@%ot: %s",$time,message);
endtask
- 数组的大小,用
.size()
去查看 - 字符串的大小,用
.len()
去表示它的长度