System Verilog我的学习之路(一)

Data types

System Verilog引进了几种新的数据类型。C语言程序员会熟悉其中的大多数。引进新的数据类型构思是这样的,如果C语言和System Verilog有相同的数据类型可以使C语言算法模型更容易的转化为System Verilog模型。
Verilog的变量类型有四态:既是0,1,X,Z。SystemVerilog引进了新的两态数据类型,每一位只可以是0或是1。当你不需要使用的X和Z值时,譬如在写Testbench和做为for语句的循环变量。使用两态变量的RTL级模型,可以使模拟器更有效率。并且使用得当的话将不会对综合结果产生影响。

常量

在变量前面加const,如果用户把这个变量改变了,那么仿真器会报错。按照C语言中的const来理解。

整型常量

8‘b0  32’d0  '0  '1  'x  'z

省略位宽则意味着全位宽都被赋值。

实型常量

支持小数或者科学型表示,例如:3.14  2.0e3
real a = 3.14;

字符串常量

和c++类似,但是字符串末尾不是“\n”
string s=“123”
bit [7:0] d = “sv”; //也可以赋值给整型

数组常量

和c++类似
int array[1:2] = {5,6};

结构体常量

typedef struct{
     int     a;
     string b;
     real    c;      
}  name_1;

name_1 var;

var = {10, "sv", 1.24};

时间文本值

和verilog类似

`timescale 1ns/100ps    //时间单位是1ns,时间精度是100ps
module test;
initial begin
    #20;        //相当于20ns
    #20ns;
    #5.18ns;  //相当于5.2ns,因为时间精度是100ps,即0.1ns,自动进位了
    #1step;   //相当于100ps
end
endmodule

`timescale必须定义在模块的外面,使用关键字timeunit和timeprecision只能定义在模块内部,只会影响单个模块。

整型

类型描述符号
bit2态,自定义位宽无符号
byte2态,8bit有符号
int2态,32bit有符号
shortint2态,16bit有符号
longint2态,32bit有符号
logic4态,自定义位宽有符号
reg4态,自定义位宽有符号
integer4态,32bit有符号
time4态,64bit无符号

2态只有1和0;4态是0,1,Z,X。2态数据类型不初始化,则默认是0;4态数据类型不初始化,则默认是X。不要用2态的数据类型去做ADC数据采集。在对4态数据类型做比较的时候,使用三个等号(a===b)。2态和4态数据类型是可以相互转化的。从4态转化倒2态,那么4态中的Z和X会默认为2态的0。注意time类型是整数类型,64bit位宽。

logic类型

在SV中增加了logic类型,是reg类型的增强。在verilog中,一般输入会定义成wire类型,但是在SV中,输出和输入都定义成logic就行。 在verilog中,reg类型只能在always块中被赋值,不能用assign来赋值,但是logic类型可以在always块中和assign中被赋值。

module(
    output    reg    a,
    input      wire   b
);
endmodule

SV:
module(
    output    logic    a,
    input      logic    b
);
endmodule

实数

类型描述符号
real2态,64bit有符号
shotreal2态,32bit有符号

分为real data和shortreal data。real data相当于C语言中的double类型,64bit位宽,2态;shortreal data相当于C语言中的float类型,32bit位宽,2态。

字符串

初始值是空字符。字符串的比较按照ASIC码来比较。使用[]来索引,随意改变和取值。SystemVerilog字符串类型支持很多操作和函数。

操作描述
{strA,strB}连接——扩展指定的字符串。操作符可以是字符串类型,也可以是字符串文字。当所有的操作符都是字符串文字时,此操作完成整体的连接,结果也是一个字符串文字。
str.len长度——返回代表字符串的长度的整数
str.putc(i, c)字符输入——将字符串str中的第i个字符替换成字符c。i必须是一个整数,c必须是一个字节类型的字符
str.getc(i)获取字符——返回字符串str的第i个字符。i必须是整数,返回的字符表示为一个字节。
str.toupper()转成大写——返回str中所有字符变成大写的字符串
str.tolower()转成小写——返回str中所有字符变成小写的字符串
strA.compare(strB)比较——比较strA和strB.从第一个字符开始比较。如果相等,则继续后续字符,知道两者有不同或者到达某个字符串的结尾。如果相等,返回’0‘;如果strA在strB之后,则返回整数;如果strA在strB之前,则返回负数.
strA.icompare(strB)比较——和compare方法类似,但是不关心大小写。
str.substr(i, j)子串——i和j都是整数,返回一个新的字符串,由str的第i和和第j个中间的所有字符组成
str.atoi()字符串转整数——返回一个32bit整数(不考虑此字符串表示的数字的长度),对于atoi, 字符串将被看作十进制;对于atoh,十六进制;对于atooct,八进制;对于atob,二进制。对于比较大的数字,使用系统任务$sscanf更加合适.
str.atoreal()字符串转实数——此方法返回字符串str表示的实数
str.itoa(i)整数转字符串——atoi,atohex,atooct,atobin的反运算。此系列方法输入一个整数i,将其对应的表示方式存在字符串str中。
str.realtoa®实数转字符串——atoreal的反运算。此方法输入一个实数r,将其对应的表示方式存在字符串str中。

空类型

SV中定义function也是可以有返回值的,如果不想有返回值,那么在定义function后面添加void。调用有返回值的函数,但是不想用返回值,这个时候在调用函数的前面加void’(fun1());就可以了。不然会有warning,在验证中最好不要有警告。

动态数组

在run-time才知道元素个数,在compile-time不知道,可以使用动态数组,在仿真的时候再确定元素个数。也可将固定数组赋值给动态数组,要求是元素个数相同。
data_type name_of_dynamic_array[];
name_of_ dynamic_array = new[number of elements];

实例:int dyn[]; dyn = new[5];dyn.delete();

队列

和C++的类似,可插入,删除,sort,search,push,pop等
  data_type queue_name[$] = {…} //队列赋值时大括号前面不加单引号

实例:
int b[$] = {3,4}; //{3,4}
b.insert(1,1); //{3,1,4} 在第一个元素后面添加1
b.delete(1); //{3,4} 删除元素1
b.push_front(6) ; //{6,3,4}
j = b.pop.back; //{6,3}, j = 4

联合数组

充分利用内存里的离散空间,不连续空间;索引值可以为整型,字符型,一维数组。有如下的操作,遍历(foreach),first,next,prev,delete,exits
data_type associative_array_name[*/string]
实例:
logic [63:0] assoc [*],idx=1;
repeat(64) begin
assoc[idx]=dix;
idx=idx<<1;
end
说明:标准数组存储时,所有的存储器都用到了;联合数组使用内存时,稀疏。

数组的操作

   /*    
      Exercsise platform :     Questa Sim 10.1b
    */
    class Array;
      int array[9:0] ;
      
      function new();
         for( int i = 0 ; i < 10 ; i++ )
             array[i] = i ;
          /*
              array = '{'{1,2,3},'{5{5}},default:0};
              无法使用这种基本的赋值方式,可能是编译器的版本过低了
          */
      endfunction:new
      
       function void print();
        foreach(array[i]) begin
          $display(" array[%d] = %d ",i,array[i]);
        end
        for ( int i = 0 ; i < 10 ; i++ )begin
          $write(" ** ");
        end
        $display();
      endfunction:print
      
      function void funcs();
          int pos[$] ;
        //   缩减操作 xor , or , and ,  xnor  , sum , product 等
        $display("the sum is %d ",array.sum());
        $display("the and is %d ",array.and());
        $display("the  or is %d ",array.or() );
        $display("the xor is %d ",array.xor());
        $display("the product is %d ",array.product());
        
        //   索引操作:取得相应的所需要的数组原素位置
        $display(" max value is %d ",array.max()[0]);
        $display(" min value is %d ",array.min()[0]);
        array = array.unique();
        print();       //  在类中时,调用自己类的函数,可以直接调用。这点与cpp相同
        pos = array.find with ( item == 7 ) ; 
        //  find 有多种变体: find_first   find_last  find_first_index   find_last_index
        $display(" pos : %d ? value: %d ",pos[0],array[pos[0]]);
        
        //  排序操作: sort ,  rsort  , reverse , shuffle , 
        // 其中 sort ,rsort  可以与with相结合,根据with后的条件排序
        array.shuffle();
        $display("shuffled:");
        print();
        array.sort();
        $display("Sorted:");
        print();
        array.rsort();
        $display("Resorted:");
        print();
        array.reverse();
        $display("Reversed:");
        print();  
      endfunction:funcs
    endclass:Array
    module top;
      Array array;
      int arr[] ;     //   动态数组的声明
      
      initial begin
        //  initial process
        array=new();
        array.print();
        array.funcs();
        arr = new[20];   //   分配内存大小
        foreach(arr[i]) $display(" arr[%2d] = %d ",i,arr[i]); 
        $display("***************");
        arr.delete();
      end
    endmodule
    //   所有关于定长数组的操作都可以用在动态数组上

仿真结果:

# ** Note: (vsim-3812) Design is being optimized...
# 
# Loading sv_std.std
# Loading work.array_sv_unit(fast)
# Loading work.top(fast)
>>>run
#  array[          9] =           9 
#  array[          8] =           8 
#  array[          7] =           7 
#  array[          6] =           6 
#  array[          5] =           5 
#  array[          4] =           4 
#  array[          3] =           3 
#  array[          2] =           2 
#  array[          1] =           1 
#  array[          0] =           0 
#  **  **  **  **  **  **  **  **  **  **  
# the sum is          45 
# the and is           0 
# the  or is          15 
# the xor is           1 
# the product is           0 
#  max value is           9 
#  min value is           0 
#  array[          9] =           0 
#  array[          8] =           1 
#  array[          7] =           2 
#  array[          6] =           3 
#  array[          5] =           4 
#  array[          4] =           5 
#  array[          3] =           6 
#  array[          2] =           7 
#  array[          1] =           8 
#  array[          0] =           9 
#  **  **  **  **  **  **  **  **  **  **  
#  pos :           7 ? value:           2 
# shuffled:
#  array[          9] =           2 
#  array[          8] =           8 
#  array[          7] =           0 
#  array[          6] =           4 
#  array[          5] =           7 
#  array[          4] =           1 
#  array[          3] =           9 
#  array[          2] =           5 
#  array[          1] =           6 
#  array[          0] =           3 
#  **  **  **  **  **  **  **  **  **  **  
# Sorted:
#  array[          9] =           0 
#  array[          8] =           1 
#  array[          7] =           2 
#  array[          6] =           3 
#  array[          5] =           4 
#  array[          4] =           5 
#  array[          3] =           6 
#  array[          2] =           7 
#  array[          1] =           8 
#  array[          0] =           9 
#  **  **  **  **  **  **  **  **  **  **  
# Resorted:
#  array[          9] =           9 
#  array[          8] =           8 
#  array[          7] =           7 
#  array[          6] =           6 
#  array[          5] =           5 
#  array[          4] =           4 
#  array[          3] =           3 
#  array[          2] =           2 
#  array[          1] =           1 
#  array[          0] =           0 
#  **  **  **  **  **  **  **  **  **  **  
# Reversed:
#  array[          9] =           0 
#  array[          8] =           1 
#  array[          7] =           2 
#  array[          6] =           3 
#  array[          5] =           4 
#  array[          4] =           5 
#  array[          3] =           6 
#  array[          2] =           7 
#  array[          1] =           8 
#  array[          0] =           9 
#  **  **  **  **  **  **  **  **  **  **  
#  arr[ 0] =           0 
#  arr[ 1] =           0 
#  arr[ 2] =           0 
#  arr[ 3] =           0 
#  arr[ 4] =           0 
#  arr[ 5] =           0 
#  arr[ 6] =           0 
#  arr[ 7] =           0 
#  arr[ 8] =           0 
#  arr[ 9] =           0 
#  arr[10] =           0 
#  arr[11] =           0 
#  arr[12] =           0 
#  arr[13] =           0 
#  arr[14] =           0 
#  arr[15] =           0 
#  arr[16] =           0 
#  arr[17] =           0 
#  arr[18] =           0 
#  arr[19] =           0 
# ***************

语法

procedural statement

新操作符

  • i++,++i,i–,--i 同c语言,但易出现race现象。
  • ==?,!=? 如:a==?b ,x与z只能出现在右侧,即b的值有x或者z
  • inside 用于值的范围,类似python的 in

强制转换

1、数据类型强制转换
通过赋值的方式,例如
longint a,y;
real r;
y=a+longint(r);

2、位宽强制转换

logic [15:0] a,b,c,sum;
logic carry
sum=a+16'(5)
{carry,sum}=17'(a+3)
sum=a+16'(b-2)/c;

3、符号位强制转换
将无符号数转化为有符号数,将有符号数转化为无符号数
例子:signed’(expression) unsigned’(expression)

循环

1、 for循环
verilog中,循环体内的变量需要在循环体外声明。sv里和c++一样,可在循环体内声明变量,这种变量是local的,在循环体外看不见。若在循环体内外同时声明同一变量,则互不干扰。
2、do while sv里增加的循环,verilog里没有。
3、增加unique,priority(优先级)选项;

function

不消耗时间;不带时序,function里不能包含延时信息,@,wait等时间信息关键字;由于task可以带时序,所以规定function不能调用task;
void function中,不返回值;在verilog里,function一定返回值,且返回的值是function的名字。

task

消耗时间,含有输入输出双向端口;可含delay,timing,event;

sv里task与function增加点

  1. 不需要加begin…end
  2. 添加return,直接退出函数
  3. function增加了void function
  4. 在verilog里function只有input,没有output,返回值就是函数值;但在sv里,function增加了output,inout变量
  5. 参数方向类型缺省时,类型默认为logic,方向默认为input
  6. 引用ref。所谓引用传递,就如c++里面的指针,也就是变量的入口地址;只有automatic型task,function可以使用ref;传值方式来传递参数,那么参数会被整体复制到其他地址,这样消耗一定的内存和操作时间;而用ref传值方式来传递参数,只是获得参数的入口地址,操作速度快,减少内存使用

automatic

一般硬件里的所有对象都是静态的;在verilog-1995,如果在多个地方调用同一个任务,本地变量是共同而且静态分配的,为此,不同的进程相互访问同一个值。在verilog-2001中,可以通过使用automatic关键字,将任务,函数和模块声明为自动存储模式,这样,仿真器就能够对所有形式的参数和内部变量使用堆栈的形式来存储。

  • 3
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值