标签:合并数组 gic 2.4 模块 处理 命令 格式 test ext
初学SystemVerilog我们在Verilog的基础之上提供了很多改进的数据结构。本章将分为几篇文章来讲述一下对验证很有用的数据结构。
通常,在Verilog中我们有两种常见的数据类型:变量和线网。他们各自有0、1、Z、X这四种状态。其中最为常见的应用也就是reg型和wire型。
变量
wire
线网通常用来连接设计中的不同部分。通常是连接设计模块的端口。
相对于通常的Verilog的reg类型,logic类型在其基础之上对其做了改进,使得它不仅可以作为一个变量,还可以被连续赋值、门单元和模块所驱动。任何使用线网类型的数据均可使用logic。logic不能有多个结构性的驱动,在定义双向总线的时候,就只能使用wire而不能使用logic。
real r,双状态,双精度浮点数
SystemVerilog提供了多个数据类型,功能上也大大增强。
所有的数组都是以0作为索引的起始点,所以SystemVerilog允许只给出数组宽度的便捷声明方式。
int i[0:15]; //16个整数[0] [1] ......[15]
int i_1[16]; //16个整数[0][1].......[15]
多维数组的定义:大小为8行4列
int array2[0:7][0:3]; //完整定义
int array3[8][4]; //紧凑的声明
array2[7][3]=1;//对最后一个元素设置为1
一个单引号加大括号来初始化数组,注意这里的单引号不同于编译器指引或宏定义中的单引号。
int ascend [4]=‘{0,1,2,3}; //对4个元素进行初始化
int descend [5];
descend=‘{4,3,2,1,0}; //对5个元素进行初始化
descend[0:2]=‘{5,6,7};//对前三个元素赋值
ascend=‘’{4{8}};//四个值全部为8
descend =‘{9,8,default:1};//{9,8,1,1,1}
对数组进行操作的最常见的方式就是使用for或foreach循环。$size函数会自动返回数组的宽度。foreach循环只需要指定数组名称并在其后面的方括号中给出索引量,SystemVerilog便会自动遍历数组中的元素。
对一维数组的操作代码如下:
     module test_enum();
      initial
        begin
        bit[31:0] src[5],dst[5];
          int i,j;
         for(int i=0;i<$size(src);i++)
          begin
          src[i]=i;
            $display("src[%0d]=%0d",i,src[i]);
              end
             foreach(dst[j])
                   begin
                     dst[j]=src[j]*2;
                $display("dst[%0d]=%0d",j,dst[j]);
             end
             endmodule
其结果如下:
# src[0]=0          
# src[1]=1          
# src[2]=2          
# src[3]=3          
# src[4]=4          
# dst[0]=0
# dst[1]=2
# dst[2]=4
# dst[3]=6
# dst[4]=8
对多维数组foreach循环方括号的下标并不是我们想象的[i][j],而是[i,j]。下面以两个例子来进行说明。
      module test_enum();
       int md[2][3]=‘{‘{0,1,2},‘{3,4,5}}; //对多维数组的赋初始值是在initial之外
        initial
            begin     
       // int i,j; //并不需要对i,j进行类型定义
         foreach(md[i,j])
        $display("md[%0d][%0d]=%0d",i,j,md[i][j]);      
         end             
         endmodule结果为:
   # md[0][0]=0
   # md[0][1]=1
   # md[0][2]=2
   # md[1][0]=3
   # md[1][1]=4
   # md[1][2]=5
另一个例子:
       module test_enum();
         initial
          begin
         byte two[4][6];
         foreach(two[i,j])
          two[i][j]=i*10+j;
     
          foreach(two[i])
           begin
            $write("%0d:",i);
            foreach(two[,j])
                $write("%3d",two[i][j]);  //利用位宽来表示空格
              $display;
            end
                end     
      
               endmodule
结果是:
  # 0:  0  1  2  3  4  5
  # 1: 10 11 12 13 14 15
   # 2: 20 21 22 23 24 25
   # 3: 30 31 32 33 34 35
能够对上述两个例子有一个深入的了解就能够掌握for和foreach的用法。
数组的复制和比较其实很简单,下面我就用一段代码来给大家讲述一下。
     module test_enum();
      bit[31:0] src[5]=‘{0,1,2,3,4},
              dst[5]=‘{5,4,3,2,1};   //赋初始值放在外面
     initial
     begin
     if(src==dst)
      $display("src==dst");
     else
      $display("src!=dst");
      dst=src;//将src赋给dst
      src[0]=5;//将src的第一个元素赋值为5
      $display("src %s dst",(src==dst)? "==":"!="); //以这种方式来比较
      $display("src[1:4] %s dst[1:4]",(src[1:4]==dst[1:4])? "==":"!=");
     end     
       endmodule
同时使用位下标和数组下标
bit[31:0] src[5]=‘{5{5}};
src[0]=5;src[0][0]=1;src[0][2:1]=‘b10合并数组
声明合并数组时,合并的位和数组大小作为数据类型的一部分必须在变量名前面指出。数组大小定义的格式必须是[msb:lsb],而不是[size]。
bit [3:0][7:0] bytes; //四个字节合并的数组,使用单独的32比特的字来存放。
bytes//32比特
bytes[3]//最高位字节
bytes[3][7]//最高字节的最高位
bit [3:0][7:0] barray[3];//3*32比特
barray[2]//32比特的数据
barray[2][3]//8比特的数据
barray[2][3][7]//单比特的数据
我们知道Verilog数组类型中,都是定宽度的数组,其宽度在编译时就确定了。但是如果我们事先并不知道数组的宽度,那么我们又该如何分配数组的宽度呢?下面我们就来介绍一下动态数组。
动态数组在声明时使用空下标[],数组在最开始时是空的,必须使用new[]操作符来分配空间,同时在方括号中传递数组宽度。
下面我们通过一个例子来深入了解一下动态数组。
   module test_enum();
   int dyn[],d2[];  //声明动态数组
   initial
     begin
     dyn=new[5];//dyn的宽度为5
     foreach(dyn[j])
     dyn[j]=j;
    d2=dyn;    //复制动态数组
    d2[0]=5;   
    $display("%d %d",dyn[0],d2[0]); // 0,5
    dyn=new[20](dyn);  //给dyn分配20个整数值并将前五个值进行复制
    $display("%d %d",dyn[3],dyn[19]);//3,0
    dyn=new[100];//分配100个整数值给dyn
    dyn.delete(); //删除所有元素
    end     
   endmodule
SystemVerilog引进了一种新的数据类型队列。在一个队列中的任何一个地方增加或删除元素,这类操作在性能上的损失要比动态数组小的多,因为动态数组需要分配新的数组并复制所有元素。
队列的声明是使用的带有美元符号的下标[$],队列元素的编号从0到$。
 module test_enum();
 int j,
     q2[$]={3,4},
     q[$]={0,2,5};
   initial
      begin
        j=q2[$];     //j=4     
        j=q2[0];    //j=3
  q.insert(1,1); //在第1位插入1{0,1,2,5}
  q.insert(2,3);//在第2位插入3{0,1,3,2,5}
  q.delete(1);//删除第一位{0,3,2,5}
  q.push_front(6);  //最前面插入6{6,0,3,2,5}       
  j=q.pop_back; //j=5 {6,0,3,2}
  q.push_back(8);//在最后插入8{6,0,3,2,8}
  j=q.pop_front;//j=6{0,3,2,8}
  foreach(q[i])
  $display("%0d",q[i]);
  q.delete();//等价于命令q={};
 end     
  endmodule
注意:把$放在一个范围表达式的左边,那么$将代表最小值[$:2]等价于[0:2],将$放在一个范围表达式的右边,那么$将代表最小值[1:$]等价于[1:2]
如果你只是需要对一个有着几个G字节寻址范围的处理器进行建模。在典型的测试中,这个处理器可能只访问了用来存放可执行代码和数据的几百或几千个字节,这种情况下对几个G字节的存储空间进行分配和初始化显然是浪费的。
仿真器一般采用32位地址线或者64位数据作为索引的数据包,显然这是有一定的额外开销的。
关联数组采用在方括号中放置数据类型的形式来进行声明
 module test_enum();
 bit[63:0] assoc[bit[63:0]],   //64个bit[63:0]
              idx=1;
  initial
 begin                 
   repeat(64)   //对1,2,4,8,16等等的稀疏元素进行初始化。
    begin
      assoc[idx]=idx;
      idx=idx<<1;
    end
    foreach(assoc[i])   //foreach遍历数组
    $display("assoc[%0d]=%0d",i,assoc[i]);
    if(assoc.first(idx))   //遍历数组的另一种形式
       begin
         do
         $display("assoc[%h]=%h",idx,assoc[idx]);
         while(assoc.next(idx));
       end
      assoc.first(idx);   //找到并删除第一个元素
      assoc.delete(idx);
      $display("the array now has %0d elements",assoc.num);
 end     
 endmodule标签:合并数组 gic 2.4 模块 处理 命令 格式 test ext
原文地址:https://www.cnblogs.com/xuqing125/p/9017823.html