1、MicroElectronics Center 增强的文本值 改进的define文本替换 时间值 新的变量类型 有符号和无符号类型 静态和动态变量 类型转换 常数第3章 SystemVerilog文本值和数据类型MicroElectronics Center3.1 增强的文本赋值 Verilog中的向量赋值:parameter SIZE=64;reg SIZE 1:0 data;data=0;/将数据各位置0 data=bz;/将数据各位置z data=bx;/将数据各位置x 但如何给data赋全1的值?data=64hFFFFFFFFFFFFFFFF;/不可扩展,如果 /SIZE改为128呢
2、?data=0;/1的补码 data=-1;/2的补码MicroElectronics Center3.1 增强的文本赋值 SystemVerilog在向量赋值的增强:1.可以只指定要赋的值,不用指定进制 2.赋值可以是逻辑1,该语法指定所有位所赋的值 parameter SIZE=64;reg SIZE 1:0 data;data=0;/将数据各位置0 data=1;data=z;/将数据各位置z data=x;/将数据各位置xMicroElectronics Center3.2 define增强 Verilog允许在define宏中使用双引号,但是双引号内的文本变成了文本串,即在veril
3、og中不能采用在字符串中嵌入宏变量的文本替换宏创建字符串 define print(v)$display(“variable v=%h”,v)print(data);/$display(“variable v=%h”,data);SystemVerilog允许字符串内的宏变量替换!define print(v)$display(“variable v=%h”,v)print(data);/$display(“variable data=%h”,data);MicroElectronics Center3.2 define增强 SystemVerilog允许在包含变量替换的宏文本字符串中使用隔离
4、引号,SV中如何通过宏定义实现下面与Verilog相同功能的语句?$display(“variable”data”=%h”,data);define print(v)$display(“variable”v”=%h”,v)print(data);$display(“variable”data”=%h”,data);MicroElectronics Center3.2 define增强 SystemVerilog可以提供了一个不引入空格的方法,通过使用两个连续的重音符号,使两个或多个文本宏连接成一个新名字 bit d00_bit;wand d00_net=d00_bit;bit d01_bit;
5、wand d01_net=d01_bit;.bit d62_bit;wand d62_net=d62_bit;bit d63_bit;wand d63_net=d63_bit;define TWO_STATE_NET(name)bit name_bit;wand name_net=name_bit;TWO_STATE_NET(d00);MicroElectronics Center3.3 SystemVerilog变量 对象类型和数据类型SystemVerilog四态变量SystemVerilog两态变量显式及隐式变量和线网类型综合指导MicroElectronics Center3.3.1
6、对象类型和数据类型 对象类型指明信号是变量还是线网;数据类型指明变量或线网的值系统:两态数据类型或四态数据类型 Verilog数据类型:变量:integer,reg,time线网:wire,wor,wand SystemVerilog数据类型:包含了所有的Verilog数据类型1.增加了一些新数据类型:byte,int,logicMicroElectronics Center3.3.2 SystemVerilog四态变量 SystemVerilog用logic关键字描述通用的针对硬件的数据类型,logic数据类型变量与Verilog中的reg类型是大多数情况下可以互换使用 logic类型变量声
7、明:logic resetN;/一位四态变量 logic 63:0 data;/64位宽变量 logic 0:7 array 0:255;/8位数组变量 显式变量或线网声明:var logic 63:0 addr;/64位宽变量 wire logic 63:0 addr;/64位宽线网Why logic?MicroElectronics Center3.3.3 SystemVerilog两态变量 适合于更高抽象层次建模,如系统级和交易级 bit1位两态整数 byte8位两态整数,与C语言的char类似 shortint16位两态整数,与C语言的short类似 int32位两态整数,与C语言的i
8、nt类似 longint64位两态整数,与C语言的long类似 bit resetN;bit 63:0 data;bit 0:7 array 0:255;var bit 63:0 addr;MicroElectronics Center3.3.3 SystemVerilog两态变量 类似C语言类型优点:类似C语言的两态类型如int和byte,主要用来描述更抽象的总线功能模型,不需要描述硬件细节,如三态总线及可能产生逻辑值X的硬件冲突 易于使用SystemVerilog的直接编程接口(DPI),建立Verilog到C或C+的接口,因为数据类型相同,所以数据在两语言间的传递更简单有效1.for 语
9、句中的循环变量,综合后就消失了,int类型是一个很好的选择MicroElectronics Center3.3.4 显式及隐式变量和线网类型 声明语句中,数据类型前没有显式指定对象类型时,则推断为隐式变量 logic 7:0 busA;bit 31:0 busB;var logic 7:0;var bit 31:0 b;typedef enum bit FALSE,TRUE bool_t;var bool_t c;var 7:0 d;/四态8位变量 wire 31:0 busB;/隐含为四态逻辑数据类型 wire logic 31:0 busC;两态线网问题 wire reg 31:0 bus
10、D;MicroElectronics Center3.4 RTL中使用两态类型 SystemVerilog新增加的两态类型可以用于设计抽象建模,这种情况下很少用到三态值,可能导致不确定值或不可预测值(X)的电路不会出现。SystemVerilog允许给一个两态类型赋四态值,其映射关系如下:四态值转换为0011Z0X0MicroElectronics Center3.4.1 两态类型和四态类型仿真1.两态模式仿真器:软件工具在设计模型不需要使用逻辑Z和X时提供的仿真模式,提高仿真速度2.多数两态模式仿真器通常不能使用两态与四态混合仿真3.不同两态模式仿真器将Z和X映射到两态类型时可能不同,导致仿
11、真结果不同4.两态仿真模式对casez和casex解释不同,从而导致仿真结果不同5.SystemVerilog中标准两态类型为所有软件工具提供相同的行为,同时,四态到两态的映射也是标准化的,因此所有软件工具仿真结果也是一致的MicroElectronics Center3.4.2 case语句中使用两态类型缺省赋值两个优点:其一是综合会将条件选择项的译码逻辑进行优化,不会考虑缺省分支条件表达的值如何译码;其二是缺省X赋值有助于检测RTL模型中的设计错误 case(state)RESET:next=WAIT;WAIT:next=LOAD;LOAD:next=DONE;DONE:next=WAIT
12、;default:next=4bx;/不定态 endcase但如果是两态变量呢?!给两态变量赋一个X值如何?MicroElectronics Center3.5 数据类型规则的放宽 SystemVerilog简化了模型中数据类型的使用,任何数据类型的变量都可以通过下列方式赋值:initial或always过程块中赋值 在单个always_comb,always_ff或always_latch过程块中赋值 通过单个模块或原语的output/inout端口驱动赋值大部分信号可以声明为变量类型!MicroElectronics Center3.5 数据类型规则的放宽 module compare(o
13、utput logic lt,eq,gt,input logic 63:0 a,b);always(a,b)if(a b);/连续赋值 comparator u1(eq,a,b);/模块例化 endmodule module comparator(output logic eq,input logic 63:0 a,b);always(a,b)eq=(a=b);endmoduleMicroElectronics Center3.5 数据类型规则的放宽 对变量使用的限制可以防止设计错误:多个输出端口驱动一个变量;对一个变量进行多次连续赋值;对同一个变量同时进行过程赋值和连续赋值 module a
14、dd_and_increment(output logic 63:0 sum,output logic carry,input logic 63:0 a,b);always(a,b)sum=a+b;/过程赋值 assign sum=sum+1;/error,sum已经被过程赋值一次 look_ahead i1(carry,a,b);/carry被驱动一次 overflow_check i2(carry,a,b);/error,carry再一次被驱动 endmodule module loock_ahead(output wire carry,.endmodule module overflow
15、_check(output wire carry,.endmoduleMicroElectronics Center3.6 有符号和无符号修饰符 integer j;/verilog-2019标准,32位有符号数 reg 63:0 u;/无符号64位数 reg signed 63:0 s;/有符号64位数,verilog-2019标准 SystemVerilog增加了缺省为有符号数的数据类型:byte,shortint,int和longint int s_int;/有符号32位变量 int unsigned u_int;/无符号32位变量与verilog相同,SystemVerilog只能在类
16、型关键字后面指定signed或unsigned关键字,与C语言不同!MicroElectronics Center3.7 静态变量和自动变量 verilog-2019标准中,所有数据类型都是静态的 verilog-2019标准中在任务和函数中添加了自动变量 自动变量特点是其存储区在需要时由软件工具动态分配,不需要时被释放,因此也被称为动态变量。自动变量用途:1.用于描述在测试程序、抽象系统级、交易级或总线功能模型中的验证程序 2.用于编写可重入任务或递归函数 MicroElectronics Center3.7 静态变量和自动变量平衡加法器:把数组的所有元素加在一起,被加的数组元素高、低地址作
17、为函数的输入。function automatic int b_add(int lo,hi);int mid=(lo+hi+1)1;if(lo+1!=hi)return(b_add(lo,(mid 1)+b_add(mid,hi);else return(arraylo+arrayhi);endfunction MicroElectronics Center3.7 静态变量和自动变量 SystemVerilog增加了关键字static,允许任何变量显式被声明为static或automatic,这个声明可以出现在任务、函数、beginend块或forkjoin块中,但在module一级声明的变量
18、不能显式地声明为static或automatic,在module级,所有变量都是静态的!function int count_ones(input 31:0 data);automatic logic 31:0 count=0;automatic logic 31:0 temp=data;for(int j=0;j =1;end return count;endfunction MicroElectronics Center3.7 静态变量和自动变量 检查程序运行总错误数任务:typedef struct packed packet_t;task automatic check_results
19、(input packet_t sent,received,output int total_errors);static int error_count=0;if(sent!=received)error_count+;total_errors=error_count;endtask SystemVerilog缺省存储方式与Verilog兼容,在模块、beginend块、forkjoin块以及非自动任务和函数中,缺省存储方式为静态的,如果一个任务和函数被声明自动的,则缺省存储方式的自动的。MicroElectronics Center3.7.1 静态变量和自动变量的初始化 SystemVer
20、ilog对Verilog进行了扩展,在模块、任务、函数中声明的变量可以有内嵌初始值,静态变量只初始化一次,自动变量每次调用时都初始化 function int count_ones(input 31:0 data);logic 31:0 count=0;logic 31:0 temp=data;for(int k=0;k=31;k+)begin if(temp0)count+;end return count;endfunction 上述程序不能正确工作:第一次调用时,count初始为0,再次调用时,静态变量count保持上次调用时的值,从而导致计数错误 静态变量初始化是不可综合的,动态变量初
21、始化是可综合的!MicroElectronics Center3.7.2 静态变量和自动变量使用原则 在always和initial块中,如果无内嵌初始化则使用静态变量,而需要内嵌初始化则使用自动 变量 如果一个任务或函数是可重入的,则应设成自动的,变量也应是自动的,除非要在两次调用之间保持变量的值 如果一作任务或函数用来描述硬件的独立部分,并且不是可重入的,则应声明为静态的,任务或函数中的变量也应是静态MicroElectronics Center3.8 变量初始化的确定性 Verilog初始化不确定 SystemVerilog内嵌初始化在时间0之前 Verilog内嵌初始化可能引起事件,S
22、ystemVerilog不引起事件 SystemVerilog内嵌初始化是确定的 integer j=5;integer k;/integer k=j;initial k=j;/initial/k=j;logic resetN=0;always(posedge clk,negedge resetN)if(!resetN)count=0;else count=count+1;resetN初始与always过程谁先被仿真器激活,表现的结果是不同的!MicroElectronics Center3.8.1 时序逻辑的异步输入初始化 module counter(input wire clk,rese
23、tN,output logic 15:0 count);always(posedge clk,negedge resetN)if(!resetN)count=0;else count=count+1;endmodule module counter_test;wire 15:0 count;bit clk;bit resetN=1;counter counter_1(clk,resetN,count);always#10 clk=clk;initial begin resetN=0;#2 resetN=1;$display(“n count=%0d(expect 0)n”,count);end
24、 endmodule 对Verilog来说,该程序执行具有不确定性,WHY?MicroElectronics Center3.9 强制类型转换 verilog是弱类型语言,允许一个数据类型的值赋给另一个 数据类型的变量或线网,新值按verilog标准中定义的规则转换,强制转换不同于赋值时转变数值,它可以在表达式内,将一个数值转换成一个新的类型!MicroElectronics Center3.9.1 静态转换(编译时转换)SystemVerilog加入了一个强制转换操作符,用于将一个值强制转换为其它类型 数据类型强制转换:()7+int(2.0*3.0);向量宽度强制转换:()logic 15
25、:0 a,b,y;y=a+b*16(2);符号强制转换:()shortint a,b;int y;y=y signed(a,b);MicroElectronics Center3.9.1 动态强制类型转换 SystemVerilog提供了一个系统函数$cast,在运行时能够进行待转换数值的检查$cast(dest_var,source_exp);int radius,area;always(posedge clk)$cast(area,3.154*radius*2);typedef enum s1,s2,s3 states_t;states_t state,next_state;always_
26、latch begin$cast(next_state,state+1);end$cast可以作为任务被调用$cast可以作为函数被调用$cast作为函数被调用时,会返回一个转换成功与否标志$cast不能和直接修改源表达式的操作符一块使用,如+,+=等$cast语句不可综合!MicroElectronics Center3.10 常数 verilog提供三种类型常数:parameter,specparam和localparam paramter可以在确立时使用defparam或内嵌参数重定义修改的常数Specparam是一个可以在确立时从SDF文件中重定义的常数Localparam是确立期常数
27、,可以基于其它常数,但不能重定义 verilog限制这些常数不能在自动任务或函数、beginend、forkjoin中声明MicroElectronics Center3.10 常数 SystemVerilog加入了一个类似C语言风格的const声明,可以将任何变量声明为常数,有确立完成之后才被赋值,并且可以在自动任务或函数、beginend、forkjoin中声明 const logic 23:0 c1=7;const int c2=15;const real c3=3.14;const c4=5;/error,无数据类型 task automatic C;const int N=5;end
28、taskMicroElectronics Center SystemVerilog允许用户定义新的变量和线网类型,从而能够在更高的抽象线上进行复杂的设计,使用用户自定义数据类型,可以用更少的代码完成更多的设计功能,并且代码的自文档性和可读性更好。使用typedef建立用户自定义类型使用enum建立枚举类型枚举值的使用第4章 用户自定义和枚举数据类型MicroElectronics Center4.1 用户自定义类型 Verilog没有提供用户自行扩展语言变量和线网类型机制,其数据类型主要用于RTL和门级建模,SystemVerilog除增加了许多新数据类型外,还可以用typedef关键字来建立
29、用户自定义类型,新类型定义后,可以声明这个类型的变量,如:typedef int unsigned uint;uint a,b;/uint类型的两个变量MicroElectronics Center4.1.1 局部typedef声明 用户自定义类型可以在局部定义,也可以在编译单元域进行外部定义。当一个用户自定义类型只用于设计的特定部分时,typedef的定义可以在模块或设计的接口部分。module alu();typedef logic 3:0 nibble;nibble opA,opB;nibble 7:0 data;/由8个nibble类型组成的32位向量 endmodulenibble只
30、有alu模块中可见,其它模块完全可以用nibble表示其它的意思MicroElectronics Center4.1.2 共享typedef定义 如果一个用户自定义类型会在很多不同的模块或接口是使用,可以把typedef声明放在package或$unit中声明。package chip_types;ifdef TWO_STATE typedef bit dtype_t;else typedef logic dtype_t;endif endpackageMicroElectronics Center4.1.2 共享typedef定义module counter(output chip_type
31、s:dtype_t 15:0 count,input chip_types:clock,resetN);always(posedge clock,negedge resetN)if(!resetN)count=0;else count=count+1;endmodule inport chip_types:*;module counter(output dtype_t 15:0 count,input clock,resetN);always(posedge clock,negedge resetN)if(!resetN)count=0;else count=count+1;endmodule
32、MicroElectronics Center4.2 枚举数据类型枚举数据类型提供了一种方式来声明一个具有特定允许值列表的抽象变量,每一个值都有一个确定的用户自定义名字,即标签(label)。Verilog语言没有枚举类型,为了给数值创建一个标签,必须定义parameter常数来表示每个值,并且将值赋给常数(标识符),define文本替换是另一种把标识符与值对应的方法MicroElectronics Center4.2 枚举数据类型define FETCH 3H0define WRITE 3H1define ADD 3H2define SUB 3H3define MULT 3H4define
33、DIV 3H5define SHIFT 3H6define NOP 3H7module controller(output reg read,write,input wire 2:0 instruction,input wire clk,resetN);parameter WAIT=0,LOAD=1,STORE=2;reg 1:0 state,nextState;MicroElectronics Center4.2 枚举数据类型 always(posedge clk,negedge resetN)if(!resetN)state=WAIT;else state=nextState;always
34、(state)begin case(state)WAIT:nextState=LOAD;LOAD:nextState=STORE;STORE:nextState=WAIT;endcase end always(state,instruction)begin read=0;write=0;if(state=LOAD&instruction=FETCH)read=1;else if(state=STORE&instruction=WRITE)write=1;endendmodulestate和nextState只取三个值吗?MicroElectronics Center4.2 枚举数据类型pack
35、age chip_types;typedef enum FETCH,WRITE,ADD,SUB,MULT,DIV,SHIFT,NOP instr_t;endpackageimport chip_types:*;module controller(output logic read,write,input instr_t instruction,input wire clk,resetN);enum WAIT,LOAD,STORE state,nextState;always_ff(posedge clk,negedge resetN)if(!resetN)state=WAIT;else sta
36、te=nextState;always_comb begin case(state)WAIT:nextState=LOAD;LOAD:nextState=STORE;MicroElectronics Center4.2 枚举数据类型 STORE:nextState=WAIT;endcase end always_comb begin read=0;write=0;if(state=LOAD&instruction=FETCH)read=1;if(state=STORE&instruction=WRITE)write=1;endendmodule枚举类型限制数值的合法集合,例子中state,ne
37、xtState只能有WAIT、LOAD、STORE三种值,所有软件工具都使用相同的方式解释对于枚举类型变量合法值的约束!MicroElectronics Center4.2 枚举数据类型枚举类型标签作用域:枚举类型列表中的标签在其作用域内必须是唯一的,可以包含枚举类型声明的作用域包括编译单元、模块、接口,任务、函数、beginend块和forkjoin块module FSM();enum GO,STOP fsm1_state;enum WAIT,GO,DONE fsm2_state;endmodule?MicroElectronics Center4.2 枚举数据类型枚举类型相标签代码的值:枚
38、举类型标签缺省情况下代表的实际数值是一个int类型的整数,第一个标签表示数值0,第二个为1,以此类推。SystemVerilog支持显式地说明标签表示的数值,如:enum ONE=1,FIVE=5,TEN=10 state;enum A=1,B,C,X=24,Y,Z list1;/B=?,C=?,Y=?,Z=?enum A=1,B,C,D=3;list2;枚举列表中的各个标签必须具有唯一的值!MicroElectronics Center4.2 枚举数据类型枚举类型的基类:枚举类型是具有一系列标签值的变量或线网,其缺省的基类是int类型,SystemVerilog允许对枚举类型的基类进行显式的
39、声明。enum bit FALSE,TRUE boolean;enum logic 1:0 WAIT,LOAD,READY state;enum logic 2:0 WAIT=3b001,LOAD=3b010,READY=3b100 state;/one-hot编码enum WAIT=3b001,LOAD=3b010,READY=3b100 state;/基类宽度与赋给标签的值宽度不同enum logic A,B,C list4;/标签数超过基类所能代表的宽度enum logic ON=1b0,OFF=1bz switch;enum logic 1:0 WAIT,ERR=2bxx,LOAD,R
40、EADY state;/?MicroElectronics Center4.2 枚举数据类型枚举类型操作的强类型检验:枚举类型与其它的Verilog变量不同,它是强类型,一个枚举类型只可以进行下列赋值。枚举类型列表中的一个标签同类枚举类型的其它变量通过$cast转换成枚举类型变量的数值typedef enum WAIT,LOAD,READY states_t;states_t state,next_state;int foo;foo=state+1;state=next_state;state=WAIT;state=foo+1;state=state+1;state+;next_state+=
41、state;MicroElectronics Center4.2 枚举数据类型将表达式强制转换为枚举类型:使用转换操作符和动态$cast系统函数。typedef enum WAIT,LOAD,READY states_t;states_t state,next_state;next_state=states_t(state+1);$cast(next_state,state+1);如果state=READY呢?会发生什么事?MicroElectronics Center4.2 枚举数据类型枚举类型的专用系统任务:SystemVerilog提供了一些内置函数,可以循环访问枚举类型列表中的值,这些
42、方法能自动处理枚举类型的半强类型特性,简化操作。.first 返回枚举列表第一个成员的值.last 返回枚举列表最后一个成员的值.next()返回枚举列表中下一个成员的值,可以用一个整数作为next的参数,这种情况返回后面第N个成员的值.prev()返回枚举列表中前一个成员的值.num 返回枚举列表中元素个数.name 返回枚举变量值对应的字符串,如果这个值不在枚举变量列表中,则返回一个空字符串MicroElectronics Center4.2 枚举数据类型module counter(input logic synced,compare,resetN,clk,output logic in
43、_sync);enum cnt0:15 state,next_st;always_ff(posedge clk,negedge resetN)if(!resetN)state=cnt0;else state=next_st;always_ff(posedge clk,negedge resetN)if(!resetN)in_sync=0;else begin if(state=cnt8)in_sync=1;if(state=cnt0)in_sync=0;end一个计数器的例子:输出in_sync初始为0,当计数器到8时置位,计数器到0清零;如果compare和synced均为假,计数器保持当前
44、值;如果compare和synced均为真,计数器加1;如果compare为真而synced为假,计数器减2。MicroElectronics Center4.2 枚举数据类型 always_comb begin next_st=state;case(state)cnt0:if(compare&synced)next_st=state.next;cnt1:begin if(compare&synced)next_st=state.next;if(compare&!synced)next_st=state.first;end cnt15:if(compare&!synced)next_st=st
45、ate.prev(2);default:begin if(compare&synced)next_st=state.next;if(compare&!synced)next_st=state.prev(2);end endcase endendmoduleMicroElectronics Center4.2 枚举数据类型打印枚举类型:枚举类型值可以作为标签的内部值或标签名打印。module FSM(input logic clk,resetN,output logic 3:0 control);enum logic 2:0 WAIT=3b001,LOAD=3b010,READY=3b100 s
46、tate,next;always(posedge clk,negedit resetN)if(!resetN)state=WAIT;else state=next;always_comb begin$display(“nCurrent state is%s(%b)”,state.name,state);case(state)WAIT:next=LOAD;LOAD:next=READY;READY:next=WAIT;endcase$display(“next state will be%s(%b)”,next.name,next);end assign control=state;endmodule