• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
dzw9
博客园    首页    新随笔    联系   管理    订阅  订阅
SV

1. SV内建数据类型

  • logic 逻辑值分别为 0/1/x/z,默认x无符号数
  • bit 2值逻辑,分别为0/1,bit类型为无符号数
  • byte shortint int longint
    • 数据类型都为双状态,2值逻辑,分别为0/1
    • 位宽分别为 8/16/32/64
    • 都是有符号数

2. SV定宽数组

一维数组: int array[16]
二维数组: int array[8][4] 8行4列

int ascend[4] = ‘{0,1,2,3};       // 对4个元素进行初始化
int descend[5];
descend = ‘{4,3,2,1,0};            // 为5个元素赋值
descend[0:2] = ‘{5,6,7};          // 为前3个元素赋值 
ascend = ‘{4{8}};                 // 4个值全部为8 {8,8,8,8}
descend = ‘{9, 8, default:-1};   // {9,8, -1, -1, -1} 

//常用for循环遍历数组
initial begin
  bit [31:0] src[5],dst[5];
  for (int i=0; i<$size(src); i++)	//i为局部变量,$size函数返回数组的宽度
    src[i] = i;
end


initial begin
  bit [31:0] src[5],dst[5];
  foreach (dst[j])
    dst[j] = src[j]* 2;   //二维数组亦为SV常用数组
end			//使用foreach方便快捷的遍历数组

3. SV动态数组与关联数组

动态数组,可以在仿真时分配空间或者调整宽度
声明使用空的[],在使用数组之前一定要调用new[]操作符来分配空间

int dyn[], d2[];// Declare dynamic arrays
initial begin
  dyn = new[5]; //A: Allocate 5 elements
  foreach (dyn[j]) dyn[j]= j; // B: Initialize the elements
  d2 = dyn; // C: Copy a dynamicarray
  d2[0] = 5; //D: Modify the copy
  $display(dyn[0],d2[0]); // E: See both values(0 & 5)
  dyn = new[20](dyn); // F: Allocate 20 ints& copy
  dyn = new[100]; //G: Allocate 100 new ints
  // Old values are lost
  dyn.delete(); // H: Delete allelements
end

动态数组提供了一些内建的方法:delete和 size

int test[];
test=new[4];  //用new来创建数组
num=test.size();  //用size获取数组大小
test.delete();  //用delete删除数组

关联数组类型,用来保存稀疏型的数据,有利于使用零散的存储空间

  • 关联数组的索引
  1. 通配符索引:任意数据类型进行索引:int array_name [*];

  2. 字符串索引:int array_name[string];

  3. 类索引:int array_name [some_Class];

  4. integer(或int)索引:int array_name[integer];

  5. 有符号的压缩数组索引:typedef bit signed [4:1] Nibble; int array_name[Nibble];

  6. 无符号的压缩数组索引:typedef bit [4:1] Nibble; int array_name [Nibble];

  7. 其它用户定义类型索引:typedef struct { real R; int I[*]; } Unpkt; int array_name [Unpkt];

num()  //返回数组长度
delete()  //删除指定元素或者所有元素
exists()  //检查是否元素存在,存在返回1,否则返回0
first()  //将指定的索引变量赋值为数组第一个索引的值
last()  //将指定的索引变量赋值为数组最后一个索引的值  
next()  //索引变量被赋值为下一个条目的索引
prev()  //索引变量被赋值为上一个条目的索引

简单的for循环不能遍历关联数组,需要使用foreach遍历数组,还可以使用内建的first()和next()函数。
读取不存在的关联数组元素,4值逻辑返回x,2值逻辑返回0。

4. SV结构体与枚举

//struct_name.a可以引用结构体内部的a变量
struct {
    int   a;
    int   b;
    bit   c;  
} struct_name

//定义结构体的同时给结构体赋值
typedef struct {
  int addr = 1 + constant;
  int crc;
  byte data [4] = '{4{1}};
} packet1;

如果没有特别说明,枚举数据默认的存储类型为int型,且数值从0开始递增

enum{INIT, DECODE, IDLE} state;		//INIT:0  DECODE:1  IDLE:2
enum{A=2, B=5, C, D=30, E, F} dic;		//A=2 B=5 C=6 D=30 E=31 F=32
  • 枚举类型方法
    first() //returns the first member of theenumeration.
    last() //returns the last member of theenumeration.
    next() //returns the next element of theenumeration.
    next(N) //returns the Nth next element.
    prev() //returns the previous element ofthe enumeration.
    prev(N) //returns the Nth previous element.

5. SV队列及数组方法

队列声明格式 int data [$],

queue_name.size           //返回queue的大小
queue_name.insert(index,item)    //在某个索引处插入某元素
queue_name.delete(index)           //刪掉某元素或整个queue
queue_name.pop_front()         //去除第一个元素
queue_name.pop_back()         //去除最后一个元素
queue_name.push_front()   //插入元素到queue(0)
queue_name.push_back()         //插入元素到queue($)

可以在队列的任意地方实现元素的增删改查,注意不要对队列使用构造函数new[]。

q = {e, q};          // 在队列的头部插入'e'
q = q[1:$];          // 删除第一个(最左边)元素
q = q[0:$-1];          // 删除最后一个(最右边)元素
q = q[1:$-1];          // 删除第一个和最后一个元素
q = {};          // 清除队列(删除所有的元素)
q = {q[0:pos-1], e, q[pos:$]};    // 在位置'pos'处插入'e'
  • SV数组方法
    • 1.数组缩减方法:sum(求和)、product(求积)、and(与)、or(或)、xor(异或)
    int count, total, d[] = ‘{9,1,8,3,4,4};
    count = d.sum with (item > 7); // 2: {9, 8}
    total = d.sum with ((item > 7) * item); // 17= 9+8
    
      byte b[] = ‘{ 1, 2, 3, 4};
      int y;
      y = b.sum ; // y becomes 10 => 1 + 2 +3 + 4
      y = b.product ; // y becomes 24 => 1 * 2 *3 * 4
      y = b.xor with ( item + 4 ); // y becomes12 => 5 ^ 6 ^ 7 ^ 8
    
    • 2.数组定位方法
      —min()
      —max()
      —unique()
      —find() //returns all the elements satisfying the givenexpression.
      —find_index() //returns the index of all the elements satisfying the given expression.
      —find_first() //returns the first element satisfying the givenexpression.
      —find_first_index() //returns the index of the first element satisfying thegiven expression.
      —find_last() //returns the last element satisfying the givenexpression.
      —find_last_index()
    • 3.数组排序方法:sort、rsort、reverse、shuffle
    
      int d[] = ‘{9,1,8,3,4,4};
      d.reverse();// ‘{4,4,3,8,1,9}
      d.sort();// ‘{1,3,4,4,8,9}
      d.rsort();// ‘{9,8,4,4,3,1}
      d.shuffle();// ‘{9,4,3,8,1,4}
    

6. SV过程语句

initial语句在仿真一开始就立刻开始执行(0时刻),每个initial语句只执行一次。

多个initial块并行执行,每个块的执行是独立的。

initial  //语句块内含2条或以上语句需要使用begin…end或
   begin
     statement1;//可以是过程赋值语句/分支语句
     statement2; //循环语句,等待语句,顺序执行语句/并行执行语句
         …..   ; 
     statementN;
   end
   

module example_initial;
	reg clk;
	reg a,b;
	initial begin
	  clk=1’b0;
	  #2 a=1;
	  #3 b=1;
	  #5 a=1;
	  b=1
	end
endmodule

SV对Verilog 的always语句做了扩展,除了always外还有:

  1. always_comb //组合逻辑建模

  2. always_latch //为latch建模

  3. always_ff //为时序逻辑建模

final语句

  1. 当一个显式或隐式的$finish调用引起仿真结束的时候会执行final块。

  2. final块只能在一次仿真中触发一次。

final
   begin
        $display("Number of cyclesexecuted %d",$time/period);
        $display("Final PC = %h",PC);
   end
initial begin
   …
   $finish();
end

7. SV控制流

unique if指示在一系列if...else...if条件中不应该有任何交迭,也就是说,这些条件是互斥的.如果有多于一个条件为“真”,则会报错。
priority if指示一系列if...else...if条件应该按列出的顺序计算。如果多个条件同时满足,那么选择第一个满足条件的分支,即具有优先级逻辑。
priority case仅仅作用于第一个匹配。
unique case应该检查case条目的交迭。如果多于一个case条目匹配于case表达式,那么unique case应该发布一条警告信息。


Verilog提供了for、while、repeat以及forever循环。
SystemVerilog增强了Verilog的for循环,加入了一个do...while循环和一个foreach循环

initial
begin:example
integer array[10], sum, j;
// Declare i in for statement
for (int i=0; i<10; i++)        // Increment i
  array[i] = i;
// Add up values in the array
sum = array[9];
j=8;
do                             // do...whileloop
  sum += array[j];             // Accumulate
while(j--);                   // Test ifj=0
$display("Sum=%4d", sum);     // %4d - specify width
end : example


string words[2] ={"hello", "world"};
int prod[1:8][1:3];

foreach (words[j])
   $display(j, words[j]); // 打印每一个索引和值

foreach (prod[k,m])
   prod[k][m] = k * m;    // 初始化
   
repeat(5) @(posedge clk)

break

像C语言一样跳出循环,结束循环体。

continue

像C语言一样跳转到循环的尾部,结束本次循环,继续下一次循环。

return expression

退出一个函数且具有返回值,expression必须具有正确的类型,否则会报错。

return

退出一个任务或void函数

disable语句用于终止正在运行的代码块。可以分为diable fork以及disable lable

8. SV块语句

  1. 顺序块:语句置于关键字begin和end之间,块中的语句以顺序方式执行。
    命名块:可以为块语句定义一个标识名称,将块名加在begin或fork后面
  2. 并行块:关键字fork和join父进程会阻塞直到这个分支产生的所有进程结束
    join_any父进程会阻塞直到这个分支产生的任意一个进程结束。
    join_none父进程会继续与这个分支产生的所有进程并发执行。在父线程执行一条阻塞语句或者结束之前,产生的进程不会启动执行。
    之间的是并行块语句,块中的语句并行执行。

在定义一个fork...join块的时候,将整个分支封装在一个begin...end块中会引起整个块作为单个进程执行,其中每条语句顺序地执行。

// wait fork; 指定waitfork会引起调用进程阻塞直到它的所有子进程结束
task do_test;
   fork
        exec1();
        exec2();
   join_any
   fork
        exec3();
        exec4();
   join_none
   wait fork;   // 阻塞直到exec1... exec4完成
   disable fork;  //中止调用进程的所有活跃的子进程。
endtask

9. SV task与function

SystemVerilog加入了在静态任务和函数中声明自动变量的功能。
在自动任务和函数中声明静态变量的功能。
无需一个begin...end块或fork...jion块就可以在一个任务或函数中使用多条语句的能力。
在到达任务或函数的结尾之前从任务或函数返回的能力。

posted on 2023-06-02 15:08  dzw9  阅读(685)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3