《SystemVerilog硬件设计及建模—第34章》由会员分享,可在线阅读,更多相关《SystemVerilog硬件设计及建模—第34章(52页珍藏版)》请在金锄头文库上搜索。
1、SystemVerilogSystemVerilog硬件设计硬件设计及建模及建模第第3434章章HMECMicroElectronics 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呢? data = 0; /1的补码 data = -1; /2的补
2、码HMECMicroElectronics Center3.1 增强的文本赋值 SystemVerilog在向量赋值的增强: 1. 可以只指定要赋的值,不用指定进制 2. 赋值可以是逻辑1,该语法指定所有位所赋的值 parameter SIZE = 64; reg SIZE 1 : 0 data; data = 0; /将数据各位置0 data = 1; data = z; /将数据各位置z data = x; /将数据各位置xHMECMicroElectronics Center3.2 define增强 Verilog允许在define宏中使用双引号,但是双引号内的文本变成了文本串,即在ve
3、rilog中不能采用在字符串中嵌入宏变量的文本替换宏创建字符串 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);HMECMicroElectronics Center3.2 define增强 Syste
4、mVerilog允许在包含变量替换的宏文本字符串中使用隔离引号,SV中如何通过宏定义实现下面与Verilog相同功能的语句? $display(“variable ”data” = %h”, data); define print(v) $display(“variable ”v” = %h”, v) print(data); $display(“variable ”data” = %h”, data);HMECMicroElectronics Center3.2 define增强 SystemVerilog可以提供了一个不引入空格的方法,通过使用两个连续的重音符号,使两个或多个文本宏连接成一
5、个新名字 bit d00_bit; wand d00_net = d00_bit; bit d01_bit; 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);HMECMicroElectronics Center3.3 SystemVerilog变量 对象类型和数据类型Sys
6、temVerilog四态变量SystemVerilog两态变量显式及隐式变量和线网类型综合指导HMECMicroElectronics Center3.3.1 对象类型和数据类型 对象类型指明信号是变量还是线网;数据类型指明变量或线网的值系统:两态数据类型或四态数据类型 Verilog数据类型:变量:integer, reg, time线网:wire, wor, wand SystemVerilog数据类型:1.包含了所有的Verilog数据类型2.增加了一些新数据类型:byte, int, logicHMECMicroElectronics Center3.3.2 SystemVerilog
7、四态变量 SystemVerilog用logic关键字描述通用的针对硬件的数据类型,logic数据类型变量与Verilog中的reg类型是大多数情况下可以互换使用 logic类型变量声明: 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?HMECMicroElectronics Center3.3.3 Syste
8、mVerilog两态变量 适合于更高抽象层次建模,如系统级和交易级 bit1位两态整数 byte8位两态整数,与C语言的char类似 shortint16位两态整数,与C语言的short类似 int32位两态整数,与C语言的int类似 longint64位两态整数,与C语言的long类似 bit resetN; bit 63 : 0 data; bit 0 : 7 array 0 : 255; var bit 63 : 0 addr;HMECMicroElectronics Center3.3.3 SystemVerilog两态变量 类似C语言类型优点:1.类似C语言的两态类型如int和byt
9、e,主要用来描述更抽象的总线功能模型,不需要描述硬件细节,如三态总线及可能产生逻辑值X的硬件冲突2.易于使用SystemVerilog的直接编程接口(DPI),建立Verilog到C或C+的接口,因为数据类型相同,所以数据在两语言间的传递更简单有效3. for 语句中的循环变量,综合后就消失了,int类型是一个很好的选择HMECMicroElectronics Center3.3.4 显式及隐式变量和线网类型 声明语句中,数据类型前没有显式指定对象类型时,则推断为隐式变量 logic 7 : 0 busA; bit 31 : 0 busB; var logic 7 : 0 ; var bit
10、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;1. 两态线网问题2. wire reg 31 : 0 busD;HMECMicroElectronics Center3.4 RTL中使用两态类型 SystemVerilog新增加的两态类型可以用于设计抽象建模,这种情况下很少用到三态值,可能导致不确定值或不可预测值(X)的电路不会出现。 SystemVerilog允许给一个
11、两态类型赋四态值,其映射关系如下:四态值转换为0011Z0X0HMECMicroElectronics Center3.4.1 两态类型和四态类型仿真1. 两态模式仿真器:软件工具在设计模型不需要使用逻辑Z和X时提供的仿真模式,提高仿真速度2. 多数两态模式仿真器通常不能使用两态与四态混合仿真3. 不同两态模式仿真器将Z和X映射到两态类型时可能不同,导致仿真结果不同4. 两态仿真模式对casez和casex解释不同,从而导致仿真结果不同5. SystemVerilog中标准两态类型为所有软件工具提供相同的行为,同时,四态到两态的映射也是标准化的,因此所有软件工具仿真结果也是一致的HMECMic
12、roElectronics Center3.4.2 case语句中使用两态类型缺省赋值两个优点:其一是综合会将条件选择项的译码逻辑进行优化,不会考虑缺省分支条件表达的值如何译码;其二是缺省X赋值有助于检测RTL模型中的设计错误 case (state) RESET : next = WAIT; WAIT : next = LOAD; LOAD : next = DONE; DONE : next = WAIT; default : next = 4bx; /不定态 endcase但如果是两态变量呢?!给两态变量赋一个X值如何?HMECMicroElectronics Center3.5 数据类
13、型规则的放宽 SystemVerilog简化了模型中数据类型的使用,任何数据类型的变量都可以通过下列方式赋值: initial或always过程块中赋值 在单个always_comb,always_ff或always_latch过程块中赋值 通过单个模块或原语的output/inout端口驱动赋值大部分信号可以声明为变量类型!HMECMicroElectronics Center3.5 数据类型规则的放宽 module compare(output logic lt, eq, gt, input logic 63 : 0 a, b); always (a, b) if (a b); /连续赋值
14、 comparator u1(eq, a, b); /模块例化 endmodule module comparator(output logic eq, input logic 63 : 0 a, b); always (a, b) eq = (a = b); endmoduleHMECMicroElectronics Center3.5 数据类型规则的放宽 对变量使用的限制可以防止设计错误:多个输出端口驱动一个变量;对一个变量进行多次连续赋值;对同一个变量同时进行过程赋值和连续赋值 module add_and_increment(output logic 63 : 0 sum, outpu
15、t 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_check(output wi
16、re carry, . endmoduleHMECMicroElectronics Center3.6 有符号和无符号修饰符 integer j; /verilog-1995标准,32位有符号数 reg 63 : 0 u; /无符号64位数 reg signed 63 : 0 s; /有符号64位数,verilog-2001标准 SystemVerilog增加了缺省为有符号数的数据类型:byte, shortint, int和longint int s_int; /有符号32位变量 int unsigned u_int; /无符号32位变量与verilog相同,SystemVerilog只能在
17、类型关键字后面指定signed或unsigned关键字,与C语言不同!HMECMicroElectronics Center3.7 静态变量和自动变量 verilog-1995标准中,所有数据类型都是静态的 verilog-2001标准中在任务和函数中添加了自动变量 自动变量特点是其存储区在需要时由软件工具动态分配,不需要时被释放,因此也被称为动态变量。 自动变量用途: 1. 用于描述在测试程序、抽象系统级、交易级或总线功能模型中的验证程序 2. 用于编写可重入任务或递归函数 HMECMicroElectronics Center3.7 静态变量和自动变量平衡加法器:把数组的所有元素加在一起,
18、被加的数组元素高、低地址作为函数的输入。 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 HMECMicroElectronics Center3.7 静态变量和自动变量 SystemVerilog增加了关键字static,允许任何变量显式被声明为static或automatic,这个声明可以出现
19、在任务、函数、beginend块或forkjoin块中,但在module一级声明的变量不能显式地声明为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 HMECMicroElectronics Center3.7 静态变量和自动变量 检查程序
20、运行总错误数任务: typedef struct packed packet_t; task automatic check_results(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块以及非自动任务和函数中,缺省存储方式
21、为静态的,如果一个任务和函数被声明自动的,则缺省存储方式的自动的。HMECMicroElectronics Center3.7.1 静态变量和自动变量的初始化 SystemVerilog对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) coun
22、t +; end return count; endfunction 上述程序不能正确工作:第一次调用时, count初始为0,再次调用时,静态变量count保持上次调用时的值,从而导致计数错误 静态变量初始化是不可综合的,动态变量初始化是可综合的!HMECMicroElectronics Center3.7.2 静态变量和自动变量使用原则1. 在always和initial块中,如果无内嵌初始化则使用静态变量,而需要内嵌初始化则使用自动 变量2.如果一个任务或函数是可重入的,则应设成自动的,变量也应是自动的,除非要在两次调用之间保持变量的值3.如果一作任务或函数用来描述硬件的独立部分,并且不
23、是可重入的,则应声明为静态的,任务或函数中的变量也应是静态HMECMicroElectronics Center3.8 变量初始化的确定性1.Verilog初始化不确定2.SystemVerilog内嵌初始化在时间0之前3.Verilog内嵌初始化可能引起事件,SystemVerilog不引起事件4.SystemVerilog内嵌初始化是确定的 integer j = 5; integer k; /integer k = j; initial k = j; /initial / k = j; logic resetN = 0; always (posedge clk, negedge rese
24、tN) if (!resetN) count = 0; else count = count + 1;resetN初始与always过程谁先被仿真器激活,表现的结果是不同的!HMECMicroElectronics Center3.8.1 时序逻辑的异步输入初始化 module counter(input wire clk, resetN, output logic 15 : 0 count); always (posedge clk, negedge resetN) if(!resetN) count = 0; else count = count + 1; endmodule module
25、 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 endmodule 对Verilog来说,该程序执行具有不确定性,WHY?HMECMicroElectronics Center3.9 强制类型转换 verilog是弱类型语言,
26、允许一个数据类型的值赋给另一个 数据类型的变量或线网,新值按verilog标准中定义的规则转换,强制转换不同于赋值时转变数值,它可以在表达式内,将一个数值转换成一个新的类型!HMECMicroElectronics Center3.9.1 静态转换(编译时转换) SystemVerilog加入了一个强制转换操作符,用于将一个值强制转换为其它类型 数据类型强制转换: () 7 + int(2.0 * 3.0); 向量宽度强制转换: () logic 15 : 0 a, b, y; y = a + b * 16(2); 符号强制转换: () shortint a, b; int y; y = y
27、signed(a, b);HMECMicroElectronics 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_latch begin $cast(next_state,
28、state + 1); end1.$cast可以作为任务被调用2.$cast可以作为函数被调用3.$cast作为函数被调用时,会返回一个转换成功与否标志4.$cast不能和直接修改源表达式的操作符一块使用,如+,+=等5.$cast语句不可综合!HMECMicroElectronics Center3.10 常数 verilog提供三种类型常数:parameter,specparam和localparam paramter可以在确立时使用defparam或内嵌参数重定义修改的常数Specparam是一个可以在确立时从SDF文件中重定义的常数Localparam是确立期常数,可以基于其它常数,但
29、不能重定义 verilog限制这些常数不能在自动任务或函数、beginend、forkjoin中声明HMECMicroElectronics 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 in
30、t N = 5; endtaskHMECMicroElectronics Center SystemVerilog允许用户定义新的变量和线网类型,从而能够在更高的抽象线上进行复杂的设计,使用用户自定义数据类型,可以用更少的代码完成更多的设计功能,并且代码的自文档性和可读性更好。使用typedef建立用户自定义类型使用enum建立枚举类型枚举值的使用第4章 用户自定义和枚举数据类型HMECMicroElectronics Center4.1 用户自定义类型 Verilog没有提供用户自行扩展语言变量和线网类型机制,其数据类型主要用于RTL和门级建模,SystemVerilog除增加了许多新数据类
31、型外,还可以用typedef关键字来建立用户自定义类型,新类型定义后,可以声明这个类型的变量,如: typedef int unsigned uint; uint a, b; /uint类型的两个变量HMECMicroElectronics Center4.1.1 局部typedef声明 用户自定义类型可以在局部定义,也可以在编译单元域进行外部定义。当一个用户自定义类型只用于设计的特定部分时,typedef的定义可以在模块或设计的接口部分。 module alu(); typedef logic 3 : 0 nibble; nibble opA, opB; nibble 7 : 0 data;
32、 /由8个nibble类型组成的32位向量 endmodulenibble只有alu模块中可见,其它模块完全可以用nibble表示其它的意思HMECMicroElectronics Center4.1.2 共享typedef定义 如果一个用户自定义类型会在很多不同的模块或接口是使用,可以把typedef声明放在package或$unit中声明。 package chip_types; ifdef TWO_STATE typedef bit dtype_t; else typedef logic dtype_t; endif endpackageHMECMicroElectronics Cent
33、er4.1.2 共享typedef定义module counter(output chip_types : 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); al
34、ways (posedge clock, negedge resetN) if (! resetN) count = 0; else count = count + 1; endmoduleHMECMicroElectronics Center4. 2 枚举数据类型枚举数据类型提供了一种方式来声明一个具有特定允许值列表的抽象变量,每一个值都有一个确定的用户自定义名字,即标签(label)。Verilog语言没有枚举类型,为了给数值创建一个标签,必须定义parameter常数来表示每个值,并且将值赋给常数(标识符),define文本替换是另一种把标识符与值对应的方法HMECMicroElectr
35、onics Center4. 2 枚举数据类型define FETCH 3H0define WRITE 3H1define ADD 3H2define SUB 3H3define MULT 3H4define 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, ne
36、xtState;HMECMicroElectronics Center4. 2 枚举数据类型 always (posedge clk, negedge resetN) if (!resetN) state = WAIT; else state = nextState; always (state) begin case(state) WAIT : nextState = LOAD; LOAD : nextState = STORE; STORE : nextState = WAIT; endcase end always (state, instruction) begin read = 0;
37、 write = 0; if(state = LOAD & instruction = FETCH) read = 1; else if (state = STORE & instruction = WRITE) write = 1; endendmodulestate和nextState只取三个值吗?HMECMicroElectronics Center4. 2 枚举数据类型package chip_types; typedef enum FETCH, WRITE, ADD, SUB, MULT, DIV, SHIFT, NOP instr_t;endpackageimport chip_t
38、ypes : *;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 state = nextState; always_comb begin case (state) WAIT : nextState = LOAD; LOAD :
39、 nextState = STORE;HMECMicroElectronics 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,nextState只能有WAIT、LOAD、STORE三种值,
40、所有软件工具都使用相同的方式解释对于枚举类型变量合法值的约束!HMECMicroElectronics Center4. 2 枚举数据类型枚举类型标签作用域:枚举类型列表中的标签在其作用域内必须是唯一的,可以包含枚举类型声明的作用域包括编译单元、模块、接口,任务、函数、beginend块和forkjoin块module FSM(); enum GO, STOP fsm1_state; enum WAIT, GO, DONE fsm2_state;endmodule?HMECMicroElectronics Center4. 2 枚举数据类型枚举类型相标签代码的值:枚举类型标签缺省情况下代表的实
41、际数值是一个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;枚举列表中的各个标签必须具有唯一的值!HMECMicroElectronics Center4. 2 枚举数据类型枚举类型的基类:枚举类型是具有一系列标签值的变量或线网,其缺省的基类是int类型,
42、SystemVerilog允许对枚举类型的基类进行显式的声明。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 O
43、N = 1b0, OFF = 1bz switch;enum logic 1 : 0 WAIT, ERR = 2bxx, LOAD, READY state; /?HMECMicroElectronics Center4. 2 枚举数据类型枚举类型操作的强类型检验:枚举类型与其它的Verilog变量不同,它是强类型,一个枚举类型只可以进行下列赋值。枚举类型列表中的一个标签同类枚举类型的其它变量通过$cast转换成枚举类型变量的数值typedef enum WAIT, LOAD, READY states_t;states_t state, next_state;int foo;foo = st
44、ate + 1; state = next_state; state = WAIT;state = foo + 1;state = state +1; state +; next_state += state;HMECMicroElectronics 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
45、 +1);如果state = READY呢?会发生什么事?HMECMicroElectronics Center4. 2 枚举数据类型枚举类型的专用系统任务:SystemVerilog提供了一些内置函数,可以循环访问枚举类型列表中的值,这些方法能自动处理枚举类型的半强类型特性,简化操作。.first 返回枚举列表第一个成员的值.last 返回枚举列表最后一个成员的值.next() 返回枚举列表中下一个成员的值,可以用一个整数作为next的参数,这种情况返回后面第N个成员的值.prev() 返回枚举列表中前一个成员的值.num 返回枚举列表中元素个数.name 返回枚举变量值对应的字符串,如果这
46、个值不在枚举变量列表中,则返回一个空字符串HMECMicroElectronics Center4. 2 枚举数据类型module counter(input logic synced, compare, resetN, clk, output logic in_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) i
47、f ( !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均为假,计数器保持当前值;如果compare和synced均为真,计数器加1;如果compare为真而synced为假,计数器减2。HMECMicroElectronics Center4. 2 枚举数据类型 always_comb begin next_st = state; c
48、ase (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 = state.prev(2); default : begin if (compare & synced) next_st = state.next; if (compare &
49、!synced) next_st = state.prev(2); end endcase endendmoduleHMECMicroElectronics Center4. 2 枚举数据类型打印枚举类型:枚举类型值可以作为标签的内部值或标签名打印。module FSM(input logic clk, resetN, output logic 3 : 0 control); enum logic 2 : 0 WAIT = 3b001, LOAD = 3b010, READY = 3b100 state, next; always (posedge clk, negedit resetN) i
50、f (!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结束!结束!