SV-grammar1
组合型(packed)数组
组合型(packed)数组初始化时,同向量初始化一致
非组合型(unpacked)数组
- 非组合型(unpacked)数组初始化时,则需要通过’{ }来对数组的每一个维度进行赋值。
- 对于非组合型数组,在发生数组间拷贝时,则要求左右两侧操作数的维度和大小必须严格一致。
数组系统函数
$dimensions(array_name)//用来返回数组的维度。
$left(array_name,dimension)//返回指定维度的最左索引值(msb)
$right(array_name,dimension)
$low(array_name,dimension)
$high(array_name,dimension)
$size(array_name,dimension)//可以返回指定维度的尺寸大小。
$increment(array_name,dimension)//如果指定维度的最左索引值大于或等于最右索引值,那么返回1,否则返回-1。
$bits(expression)//可以用来返回数组存储的比特数目。
foreach循环结构特点:
-
- foreach循环结构中的变量无需声明。
- foreach循环结构中的变量是只读的,其作用域只在此循环结构中。
————————————————
队列
- SV引入了队列类型,它结合了数组和链表。
- 可以在队列的任何位置添加或者删除数据成员。
- 可以通过索引来访问队列的任何一个成员。
通过[$]来声明队列,队列的索引值从0到$。
//添加或者移除并且获得数据成员
push_back(val)//在队列后面插入
push_front(val)//在队列前面插入
pop_back()//删除后面的元素
pop_front()//删除前面的元素
insert (val, pos)//在指定位置插入数据成员。
delete()//删除所有数据成员。
关联数组:可以用来存放散列的数据成员
三种数组的公共方法
缩减方法
基本的数组缩减方法是把一个数组缩减成一个值。
最常用的缩减方法是sum,它对数组中的所有元素求和。
byte b [$]={2,3,4,5};
int w;
w=b.sum () ; //14=2+3+4+5
w=b.product() ; //120=2*3*4*5
w=b.and() ; //0000_0000=2 & 3 & 4 & 5
product(积)
and(与)
or(或)
xor(异或)。
定位方法
int f[6]='{1,6,2,6,8,6}; //定长数组
int d[]='{2,4,6,8,10}; //动态数组
int q[$}={1,3,5,7}, //队列
tq[$]; //保存结果的临时队列
tq=q.min() ; //{1}
tq=d.max (); //{10}
tq=f.unique(); //{1,6,2,8}
int d[]=’{9,1,8,3,4,4} , tq[$];//找出所有大于3的元素
tq = d.find with (item >3) ;// {9,8,4,4}
//等效代码
ta.delete() ;
foreach (d[i])
if(d[i]>3)
tq. push_back(d[i]);
tq = d.find_index with (item > 3);// {0,2,4,5}
tq = d.find_first with (item > 99);//{}–没有找到
tq = d.find_first_index with (item==8);//{2} d[2]=8
ta = d.find_last with (item==4);//{4]
tq = d.find_last_index with (item==4); // {5} d[5]=4
排序方法
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}乱序排列
————————————————
接口与模块的定义有许多相似之处 :
- 接口的定义同模块定义类似。
- 接口也可以有端口,例如外部接入的时钟或者复位信号。
- 接口内部可以声明所有的变量或者线网类型。
接口和模块的区别:
- 接口不同于模块的地方在于,接口不允许包含设计层次,即接口无法例化模块,但是接口可以例化接口。
- 可以在接口声明modport来约束不同模块连接时的信号方向。
- 模块的端口如果声明为input、output或者inout,那么在例化时可以不连接。
接口特点:
- 接口提高了建模级别,接口对于设计复用非常有利。
- 接口减少了模块之间错误连接的可能性。
- 如果要添加新的信号,只需要在接口中声明,而不必在模块中声明。
- 由于接口将有关信号都集合在一起,因此在使用这些信号时需要添加接口实例名。
- 一种接口往往会将有关的信号集合在一起,对于拥有多组不相关信号的设计而言,它需要有多个接口才能完成与其它模块的连接。
————————————————
modport
- 接口中的变量或者线网信号,对于连接到该接口的不同模块则可能具备着不同的连接方向。
- 接口引入了modport来作为moduleport的缩写,表示不同的模块看到同一组信号时的视角(连接方向)。
- 在接口中声明modport,需要指明modport中各个信号的方向。
当一个模块在例化时,可以选择连接到interface端口中具体的某一个modport。 这种方式可以降低方向连接错误的可能,进而避免信号多驱动的情况。
————————————————
SV中字符串的特点:
- 字符串类型变量的存储单元为byte类型( 8位二值逻辑)。
- 字符串类型变量长度为N时,其字符成员索引值为从0到N-1
- 不同于C语言,字符串结尾没有空字符“\0”
- 字符串的内存是动态分配的,用户无需担心内存空间管理。
————————————————
字符串内建方法:
str.len()//返回字符串的长度。
str.putc(i, c)//将第i个字符替换为字符c,等同于str[i]=c。
str.getc(i)//返回第i个字符。
str.substr(i,j)//将从第i个字符到第j个字符的字符串返回。
str. {atoi(), atohex(), atooct, atobin}//将字符串转变为十进制、十六进制、八进制或者二进制数据。
module data_type; // TODO-2: distinguish bit and logic initial begin: bit_vs_logic bit v1; logic v2; wait(b_bit_vs_logic == 1); $display("bit_vs_logic process block started"); v2 = 'bx; $display("logic variable v2 = %d", v2); v1 = v2; $display("bit variable v1 = %b", v1); v2 = 'bz; $display("logic variable v2 = %b", v2); v1 = v2; $display("bit variable v1 = %b", v1);
//不管z和x,bit都是0 end // TODO-3: enum type initial begin: enum_type typedef enum {IDLE, START, PROC, END} state_t; state_t st1, st2; wait(b_enum_type == 1); $display("enum_type process block started"); st1 = IDLE; $display("st1 value = %0d (int)", st1); $display("st1 value = %s (string)", st1); // implicit conversion $display("st1 value = %s (string)", st1.name()); st2 = state_t'(1); //注意此处赋值 $display("st1 value = %0d (int)", st2); $display("st1 value = %s (string)", st2.name()); end // TODO-4: struct type initial begin: struct_type typedef struct { //要试一下packet bit[7:0] addr; bit[31:0] data; bit is_write; int id; } trans_t; trans_t t1, t2, t3; wait(b_struct_type == 1); $display("struct_type process block started"); t1 = '{'h10, 'h1122_3344, 'b1, 'h1000}; //赋值 $display("t1 data content is %p", t1); // 结构体的输出%p,输出的是整形 t2.addr = 'h20; t2.data = 'h5566_7788; t2.is_write = 'b0; t2.id = 'h2000; $display("t2 data content is %p", t2); t3 = t2; t3.data = 'h99AA_BBCC; t3.id = 'h3000; $display("t3 data content is %p", t3); $display("t2 data content is %p", t2); end endmodule
// TODO-1 understand how to formulate a new string initial begin: string_format string s1, s2, s3, s4, s5; wait(b_string_format == 1);$display("string_format process block started"); s1 = "Welcome"; s2 = "www.rockeric.com"; s3 = {s1, " to ", s2}; // concatenation operator '{...}' $display("s3 content: %s", s3); s4 = $sformatf("%s to %s", s1, s2); // system format function $display("s4 content: %s", s4); s5 = $psprintf("%s to %s", s1, s2); // system format function 和{},sformatef一样的 $display("s5 content: %s", s5); end // TODO-2 understand how s3 is composed with s1 and s2 initial begin: string_builtin_function string s1, s2, s3; int i1; wait(b_string_builtin_function == 1); $display("string_builtin_function process block started"); s1 = "RockerIC is established in "; i1 = 2015; s2.itoa(i1); // integer converted to string “2015” $display("s2 = %s", s2); s3 = {s1.len()+s2.len(){" "}}; // 开辟空间,不开后面不能加入进来try to comment this line and check the result $display("s3 content: [%s]", s3); for(int i=0; i<s1.len()+s2.len(); i++) begin //拼接 s3[i] = i < s1.len() ? s1[i] : s2[i-s1.len()]; // s3[i] = i < s1.len() ? {s3,s1[i]} : {s3,s2[i-s1.len()]}; //如果不开辟空间,可以拼接 end $display("s3 content: %s", s3); end