在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
楼主: nemo2009

SystemVerilog设计读书笔记

[复制链接]
发表于 2009-7-8 16:32:14 | 显示全部楼层
Thanks
发表于 2009-7-9 08:50:50 | 显示全部楼层
主要讲啥的,money不多,不敢随便下:)
发表于 2009-7-11 13:21:33 | 显示全部楼层
wa!这可是好东西!
发表于 2009-7-16 20:36:56 | 显示全部楼层
xiexie!!!!
发表于 2009-9-3 10:47:56 | 显示全部楼层
发表于 2009-9-30 11:10:22 | 显示全部楼层
sv设计先行者!
发表于 2009-10-5 22:18:27 | 显示全部楼层
Good! Thanks for the sharing!
发表于 2009-10-6 01:11:07 | 显示全部楼层
太扯淡了
就是把书给打成文档了
这也拿来赚钱
我给你全贴出来

第二章 SystemVerilog声明的位置内容主要包括以下四个方面:
1.
包定义及引用包的内容
2.
$unit
编辑单元声明
3.
未命名块的声明
4.
增强时间单元的定义

新增数据类型集锦:
1.
logic ——
代表1-bit 4-state变量,类似于Verilog中的reg类型,可用来定义任意长度的变量。
2.
enum ——
代表可计数的net或变量(veriable,类似于C语言中的枚举类型,但是附加了用于硬件模型的语法和语义。
3.
typedef ——
用户自定义类型。
4.
struct ——
结构体类型。

2.1 2.1.1
包定义SystemVerilogVerilog增添了包定义,关键字为packageendpackage
可综合的包中可以包括:
1.
parameter
localparam常量定义
2.
const
变量定义
3.
typedef
用户自定义类型
4.
全自动化taskfunction定义
5.
从其他包中引入状态
6.
操作符重载定义
其中在包中,parameter参数是不能进行重定义的。Parameterlocalparam可综合。
2-1所示,为包定义。
package definitions;
parameter VERSION = "1.1";
typedef enum {ADD, SUB, MUL} opcodes_t;
typedef struct {
logic [31:0] a, b;
opcodes_t opcode;
} instruction_t;
function automatic [31:0] multiplier (input [31:0] a, b);
// code for a custom 32-bit multiplier goes here
return a * b; // abstract multiplier (no error detection)
endfunction
endpackage

2.1.2
引用包的内容中模块和接口处涉及到的定义和声明常用的四种方式:
1.
直接应用“::”scope resolution operator操作符
2.
从特别中导出应用于模块或接口
3.
从特别中导出通配符(Wildcard)应用于模块或接口
4.
中导出用于$unit声明中

1.
直接应用“::”scope resolution operator操作符

“::”
操作符将包中项相连,包名和包中项名由操作符“::”隔开。举例:module中端口定义为instruction_t类型,instruction_t是在definitions包中进行的定义。如下所示2-2
module ALU
(input definitions::instruction_t IW,
input logic clock,
output logic [31:0] result
);
always_ff @(posedge clock) begin
case (IW.opcode)
definitions::ADD : result = IW.a + IW.b;
definitions::SUB : result = IW.a - IW.b;
definitions::MUL : result = definitions::
multiplier(IW.a, IW.b);
endcase
end
endmodule
2.
从特别中导出应用于模块或接口
通过该种方式,2-2可改写为2-3,如下所示:
module ALU
(input definitions::instruction_t IW,
input logic clock,
output logic [31:0] result
);
import definitions::ADD;
import definitions::SUB;
import definitions::MUL;
import definitions::multiplier;
always_comb begin
case (IW.opcode)
ADD : result = IW.a + IW.b;
SUB : result = IW.a - IW.b;
MUL : result = multiplier(IW.a, IW.b);
endcase
end
endmodule
注意:importing即只能导引出可枚举的类型,而不能导出定义中用到的标号。如下:
import definitions:pcode_t;
是错误的。它不能起作用。这样导出使得opcode_tmodule中是可见得,但是,opcode_t则不能应用definitions中的枚举项。
3.
中导出通配符(Wildcard)应用于模块或接口
包中所有项可以通过通配符(wildcard)变成可视状态。用“*”表示。
举例: import definitions :: *;
但是通配符不会自动导引出包中的所有内容,而只是导引出模块或是接口中所用到的项。注意,模块或接口中本地的定义和声明的优先级要高于通配符,具体引用的包中项优先级也高于通配符。
如下2-4所示,应用通配符“*”引出该模块中所用到的包中项,在case语句中应用ADDSUBMULmultiplier时,将会在definitions包中找到。
Example 2-4: Using a package wildcard import
module ALU
(input definitions::instruction_t IW,
input logic clock,
output logic [31:0] result
);
import definitions::*; // wildcard import
always_comb begin
case (IW.opcode)
ADD : result = IW.a + IW.b;
SUB : result = IW.a - IW.b;
MUL : result = multiplier(IW.a, IW.b);
endcase
end
endmodule
2.1.3
综合指导为了便于综合,包中的任务(tasks)和功能(functions)必须是定义为自动形式,并不包括静态变量。
2.2 $unit 编译单元声明这是SystemVerilogVerilog多加的一个概念。
编译单元中的所有内容在同一时间进行编译。编译单元提供的一个概念,就是说软件可以分别对子块进行编译。其中子块可能是由单一模块或多重模块组成,并且模块可能包块单一的文件或是多重文件,也可以包含接口模块和测试模块。
同时,编译单元的范畴还包块外部声明。
编译单元的范畴包括以下几个方面:
1.
时间单位和精度的声明。
2.
变量(variable)声明
3.
网表(net)声明
4.
常量(constant)声明
5.
用户自定义类型(typedefenumclass
6.
任务和功能定义
如下2-5所示为外部声明,其中包括常量,变量,用户自定义类型以及功能。
Example 2-5: External declarations in the compilation-unit scope (not synthesizable)
/******************* External declarations *******************/
parameter VERSION = "1.2a"; // external constant
reg resetN = 1; // external variable (active low)
typedef struct packed { // external user-defined type
reg [31:0] address;
reg [31:0] data;
reg [ 7:0] opcode;
} instruction_word_t;
function automatic int log2 (input int n); // external function
if (n <=1) return(1);
log2 = 0;
while (n > 1) begin
n = n/2;
log2++;
end
return(log2);
endfunction
/********************* module definition *********************/
// external declaration is used to define port types
module register (
output instruction_word_t q,
input instruction_word_t d,
input wire clock );
always @(posedge clock, negedge resetN)
if (!resetN) q <= 0; // use external reset
else q <= d;
endmodule

注意: 外部编译单元的声明不是全局的
所谓全局声明定义的参数,设计建立的所有模块都可以应用,不管所有的文件是否分别编译或是同时编译。SystemVerilog中一个编译单元只用于需要同时编译的文件。
举例来说,有两个模块分别为CPU模块和Controller模块,两个模块同时引用同一个外部声明变量reset,则可能有以下两种情况存在:
1.
如果两个模块在同一时间进行编译,则会产生一个编译单元,则外部声明变量reset则为两个模块共用。
2.
如果每个模块分别进行编译,则会产生两个编译单元空间,分别应用两个不同的reset变量。
2.2.1
编码指导
$unit
只能用于导出包。
1.
不可在编译单元空间进行声明。所有的声明应在包中命名。
2.
必要的话,可以将包导出到$unit单元中。这对于模块或是接口包含多个由用户自定义端口类型的情况是非常有用的,类型定义可以在包中定义。
当文件分别进行编译时,直接在$unit编译单元中进行对象声明会导致设计的错误。
2.2.2
SystemVerilog
标识符搜索规则SystemVerilog定义了简单并直接的标识搜索规则,如下:
1.
首先,搜索本地声明,似Verilog标准
2.
其次,搜索包中声明
3.
第三,搜索编译单元范畴的声明
4.
第四,搜索设计层次的声明
2.2.3
源码顺序注意:数据标识符和类型定义一定要在应用前进行声明。
编译单元中的变量和线网类型
未定义类型的标识符默认为线网类型(wire)。
外部声明定义必须在使用之前。
如下例所示,说明了编码顺序对声明使用的影响。
module parity_gen (input wire [63:0] data );
assign parity = ^data; // parity is an implicit local net
endmodule

reg parity; // external declaration is not used by module parity_gen. because the declaration comes after it has been referenced
module parity_check (input wire [63:0] data,output logic err);
assign err = (^data != parity); // parity is the $unit
endmodule // variable
2.2.4
将包导入$unit的编码规则1. 直接引用用户自定义变量
module ALU
(input definitions::instruction_t IW,
input logic clock,
output logic [31:0] result
);
2. 从包中引用用户自定义变量
// import specific package items into $unit
import definitions::instruction_t;
module ALU
(input instruction_t IW,
input logic clock,
output logic [31:0] result
);
3. 从包中引出所有该模块需要的变量
// wildcard import package items into $unit
import definitions::*;
module ALU
(input instruction_t IW,
input logic clock,
output logic [31:0] result
);
若将包的内容陈述于文件definitions.pkg文件中,则若在设计文件或是testbench文件中要用到该包,则在程序开头加上`include “definitions.pkg”一句,即可对包进行编译。
2.2.5
综合规则可综合定义包括以下:
1.
typedef
用户自定义类型
2.
Automatic
功能
3.
Automatic
任务
4.
parameter
localparam静态变量
5.
包导出
应用代替$unit是一种较好的编码方式。

2.3
未命名语句块中的声明2.3.1
未命名块中的局部变量如下例所示:
module chip (input clock);
integer i; // declaration at module level
always @(posedge clock)
begin // unnamed block
integer i; // local variable
for (i=0; i<=127; i=i+1) begin
...
end
end
endmodule
2.4
仿真时间单位及精度2.4.1
Verilog
编译指令timescaleVerilog中用该语句来定义,`timescale 1ns / 10ps1ns表示单位时间长度,10ps表示精度。若遇到以下情况,连续三个模块,若如图1所示,其中A文件和C文件对时间单位及精度进行了定义,但是B没有定义,则B的时间单位将延续它前面的文件中的时间定义,即A的,所以,#5表示的是延时5ns。所示,则#5表示的是延时5ms



1
2
2.4.2
包含时间单位的时间值forever #5ns clock = ~clock;
//
时间值与时间单位之间没有空格

2.4.3
范围级(Scope-level)时间单位和精度SystemVerilog中,时间单位和精度可以通过关键字timeunittimeprecision来定义。举例如下:
module chip (...);
timeunit 1ns;
timeprecision 10ps;
...
endmodule
关键字timeunittimeprecision必须紧接着moduleinterfaceprogram声明就立刻定义,在其他声明和陈述之前。
module adder (input wire [63:0] a, b,
output reg [63:0] sum,
output reg carry);
timeunit 1ns;
timeprecision 10ps;
...
Endmodule
2.4.4
编译单位时间单元和精度2-9如下:
Example 2-9: Mixed declarations of time units and precision (not synthesizable)
timeunit 1ns; // external time unit and precision
timeprecision 1ns;
module my_chip ( ... );
timeprecision 1ps; // local precision (priority over external)
always @(posedge data_request) begin
#2.5 send_packet; // uses external units & local precision
#3.75ns
check_crc; // specific units take precedence
end
task send_packet();
...
endtask
task check_crc();
...
endtask
endmodule
`timescale 1ps/1ps // directive takes precedence over external(直接定义的优先于外部定义)
module FSM ( ... );
timeunit 1ns; // local units take priority over directive
always @(State) begin
#1.2 case (State) // uses local units & timescale precision
WAITE: #20ps...; // specific units take precedence
...
end
endmodule



第三章 SystemVerilog文本值和数据类型SystemVerilog增加的类型在本章中包括以下:
1.
增强型文字值(literal values 直接赋值)
2.
`define text
代替 enhancements
3.
时间值(time values
4.
新变量类型
5.
有符号和无符号类型(signed and unsigned)
6.
变量初始化
7.
静态和自动变量(static and automatic
8.
Casting
(计算合计)
9.
常数常量(Constants
3.1
加强的文本值赋值(Enhanced Literal Value assignments如下例所示,Verilog中对向量直接赋值
parameter SIZE = 64;
reg [SIZE-1:0] data;
data = 0; // fills all bits of data with zero
data = 'bz; // fills all bits of data with Z
data = 'bx; // fills all bits of data with X
但是,当要将数值所有位赋值为‘1’时就不太方便,即为data=64'hFFFFFFFFFFFFFFFF;,若将SIZE改为128,则须查找data变量位置,将其值进行修改,而不能灵活改变。可以操作符的方式进行修改,如下所示:
data = ~0; // one's complement operation
data = -1; // two's complement operation
SystemVerilog中,增加了两种直接赋值的方式。
1.
增加了一种简单语法,无需指定进制类型(二进制、十进制、十六进制等)。直接在之前加一个( ‘ )
l
‘0 将所有位置0
l
‘1 将所有位置1
l
‘z ‘Z 表示所有位置Z
l
‘x ‘X 表示所有位置Z
注意:()区别于( ` ),是不同的。
举例:data = ‘1; // data所有位置1
2.
赋的值可以使logic 1
3.2
`define增强SystemVerilog中扩展了`define的功能,代替了宏定义的功能。
3.2.1
字符串中的宏变元替换(Macro argument substitution within stringsVerilog
`define
宏定义中可以用(),则引号中的文字变成了文字型字符串。
这就意味着,Verilog不能建立含有宏变元的字符串。
如下例所示,不能按原本意愿展开。
`define print(v) \
$display("variable v = %h", v)
`print(data);
该例中,将`print(data);展开,则为,$display(“variable v = %h”, data);。原本的意愿是,将宏定义中所有的‘v’都变成‘data’,但是,包含在双引号里的v并没有发生变化,所以在Verilog语言中不能实现以上的功能。
SystemVerilog中能够实现宏变元的替换。应用重音符( ` )。
举例:
`define print(v) \
$display(`"variable v = %h`", v)
`print(data);
$display(“variable data = %h”, data);
Verilog中,若要在字符串中加入引号(单引号或双引号),则需在引号前加上字符“\”。举例:$display("variable \"data\" = %h", data);
当字符串中含宏变元时,只用\"是不够的,则需要用`\`"。举例如下:
`define print(v) \
$display(‘"variable ‘\‘"v‘\‘" = %h‘", v)
`print(data);
则宏展开为:
$display("variable \"data\" = %h", data);
3.2.2
通过宏建立标识符名(Constructing identifier names from macrosSystemVerilog中可以通过( `` )将两个或更多的名字连接在一起形成新的名字。注意,重音符间无空格。
举例:
Verilog
bit d00_bit; wand d00_net = d00_bit;
bit d01_bit; wand d01_net = d01_bit;
... // repeat 60 more times, for each bit
bit d62_bit; wand d62_net = d62_bit;
bit d63_bit; wand d63_net = d63_bit;
SystemVerilog中用`define
`define TWO_STATE_NET(name) bit name``_bit; \
//宏定义
wand name_``net = name``_bit;

//执行的操作
`TWO_STATE_NET(d00)
`TWO_STATE_NET(d01)
...
`TWO_STATE_NET(d62)
`TWO_STATE_NET(d63)


3.3
SystemVerilog变量 3.3.1
对象类型(目标类型)和数据类型Verilog数据类型:
1.
reg
integertime变量中的每个bit都有4中逻辑值:01ZX
2.
wire
worwandnet变量中的每个bit120个值等。
SystemVerilog数据类型
数据的声明包括类型数据类型
1.
当信号是net型或variable变量型时,需要定义类型。SystemVerilog承接了Verilog中的所有类型,并添加一些变量类型byteint型。Net型没有添加。
2.
当信号是两态(2-state01)或四态(4-state01ZX)时,需要定义数据类型。用关键字bit定义两态,关键字logic定义四态。其中变量类型的数据类型可以是2-state4-state,,但是net类型只能是4-state
3.3.2
SystemVerilog
四态变量(4-state variable4-state logic type
举例:logic变量类型类型代替reg
logic resetN; // a 1-bit wide 4-state variable
logic [63:0] data; // a 64-bit wide variable
logic [0:7] array [0:255]; // an array of 8-bit variables
关键字logic实际上不是变量类型,而是数据类型,且信号可以有四个状态值。但是,logic自用则默认为variable变量型。或者可以明确的指出类型应用关键字var logic,如下:
var logic [63:0] addr; // a 64-bit wide variable
Verilog中的net型默认为四态的数据类型,用logic来表示,则为:
wire logic [63:0] data; // a 64-bit wide net
从语义上来说,logicreg类型是可以等同的(除了reg不能代表net类型)。
3.3.3
SystemVerilog
两态变量(2-state variableSystemVerilog增加了几种新的两态类型,适用于比RTL级设计更为抽象的系统级和传输级设计。包括以下:
1.
bit
—— 1-bit 2-state整型
2.
byte
—— 8-bit 2-state 整型,类似于C char类型
3.
shortint
—— 16-bit 2-state整型,类似于C short类型
4.
int
—— 32-bit 2-state整型,类似于C int
5.
longint
—— 64-bit 2-state 整型,类似于C longlong
抽象建模级(系统级和传输级)不需要4-state,其中ZX状态是不需要的。
bit可以与reglogic同样对变量进行定义,但是它只能定义2-state的变量。例如下:
bit resetN; // a 1-bit wide 2-state variable
bit [63:0] data; // a 64-bit 2-state variable
bit [0:7] array [0:255]; // an array of 8-bit 2-state variables
4-state类型仿真起始的默认值为logic X2-state类型仿真起始默认值为0
其他抽象类型:
Void型:无返回值;
Shortreal型:32-bit 单精度浮点型,类似于C float。(不可综合)
Real型:双精度,类似于C double。(不可综合)
SystemVerilog在验证中,天价了classes和其他自动类型。(见SystemVerilog for verification
3.3.4
显式和隐式变量及线网数据类型(Explicit and implicit variable and net data typesSystemVerilog有线网和变量类型,还包括2-state4-state的数据类型。
logic [7:0] busA; // infers a variable that is a 4-state data type
bit [31:0] busB; // infers a variable that is a 2-state data type
SystemVerilog中可以应用关键字“var”对变量进行定义。举例:
typedef enum bit {FALSE, TRUE} bool_t;
var bool_t c; // variable of user-defined type
3.3.5
综合规则4-state logic类型和2-statebitbyteshortintintlongint类型都是可综合的。
3.4
RTL级模块中2-state类型应用3.4.1
2-state
类型特征1.
SystemVerilog
增加了一些2-state类型:bitbyteshortintintlongint。可应用于抽象级系统设计。
2.
4-state
2-state之间的映射关系,可以将4-state值赋给2-state,映射关系如下表:

3.4.2
2-state type
2-state simulation 的对比3.4.3
Case语句中使用两态类型3.5
数据类型规则放宽Verilog的规则具有较大的约束性。
SystemVerilog做了较大的改进,更加简单化。变量可以通过以下几种情况下使用,而不局限于一种:
1.
initialalways进程块中进行赋值(同于Verilog);
2.
always_combalways_ffalways_latch进程块中进行赋值。具体进程块将在第六章进行介绍;
3.
通过简单的连续赋值语句进行赋值;
4.
从简单模块或原始端口中得到值等等。
大部分的信号定义为logicbit类型。
变量宽松应用举例:3-1
module compare (output logic lt, eq, gt,
input logic [63:0] a, b );
always @(a, b)
if (a < b) lt = 1'b1; // procedural assignments
else lt = 1'b0;
assign gt = (a > b); // continuous assignments
comparator u1 (eq, a, b); // module instance
endmodule
module comparator (output logic eq,
input [63:0] a, b);
always @(a, b)
eq = (a==b);
endmodule
注意:同一变量不可以被多个资源驱动。
举例:
module add_and_increment (output logic [63:0] sum,
output logic carry,
input logic [63:0] a, b );
always @(a, b)
sum = a + b; // procedural assignment to sum
assign sum = sum + 1; // ERROR! sum is already being assigned a value
look_ahead i1 (carry, a, b); // module instance drives carry
overflow_check i2 (carry, a, b); // ERROR! 2nd driver of carry
endmodule
module look_ahead (output wire carry, input logic [63:0] a, b);
...
endmodule
module overflow_check (output wire carry,
input logic [63:0] a, b);
...
endmodule
TIP变量型(variables)用于单一驱动(single-drive)逻辑,网络型(nets)用于多驱动(multi-driver)逻辑。

3.6
有符号和无符号修饰符Verilog举例:
reg [63:0] u; // unsigned 64-bit variable
reg signed [63:0] s; // signed 64-bit variable
SystemVerilog举例:
int s_int; // signed 32-bit variable
int unsigned u_int; // unsigned 32-bit variable
注意:SystemVerilogC语言的有符号型声明有所不同
unsigned int u1; /* legal C declaration */
int unsigned u2; /* legal C declaration */
Verilog中(Verilog中无unsigned类型)
reg signed [31:0] s; // Verilog declaration
Systemverilog
int unsigned u; // SystemVerilog declaration
3.7
静态和自动变量( Static and automatic variablesSystemVerilog增加了staticautomatic关键字,对静态自动变量进行声明。可定义在tasksfunctionsbegin…endfork…join模块中。注意,在模块级上,所有的变量都是静态的。
3.7.1
静态和自动变量的初始化静态变量只能初始化一次;举例:
function int count_ones (input [31:0] data);
logic [31:0] count = 0; // initialized once(默认为静态变量)
logic [31:0] temp = data; // initialized once
for (int i=0; i<=32; i++) begin
if (temp[0]) count++;
temp >>= 1;
end
return(count);
endfunction
自动变量可以在每次调用的时候进行初始化;举例:
function int count_ones (input [31:0] data);
automatic logic [31:0] count = 0;
automatic logic [31:0] temp = data;
for (int i=0; i<=32; i++) begin
if (temp[0]) count++;
temp >>= 1;
end
return(count);
endfunction
3.7.2
自动变量综合规则注意:静态变量初始化是不可综合的,自动变量初始化是可综合的。
3.7.3
静态和自动变量使用规则以下规则有助于决定何时用静态变量何时用自动变量:
1.
alwaysinitial块中,如果无in-line初始化使用静态变量,如果有in-line初始化使用自动变量。
2.
If a task or function is to be re-entrant, it should be automatic.

3.
If a task or function represents the behavior of a single piece of hardware, and therefore is not re-entrant, then it should be declared as static, and all variables within the task or function should be static.

3.8
变量初始化的确定性(Deterministic variable initialization3.8.1
初始化确定机制(Initialization determinismSystemVerilog中定义,所有in-line变量初始化会在仿真时间0之前进行计算。
3.8.2
时序逻辑异步输入初始化(Initializing sequential logic asynchronous inputs3-3所示,resetN异步复位,即计数器counterresetN变为0时,立即复位,与时钟信号无关。
module counter (input wire clock, resetN,
output logic [15:0] count);
always @(posedge clock, negedge resetN)
if (!resetN) count <= 0; // active low reset
else count <= count + 1;
endmodule
测试程序:
module test;
wire [15:0] count;
bit clock;
bit resetN = 1; // initialize reset to inactive value
counter dut (clock, resetN, count);
always #10 clock = ~clock;
initial begin
resetN = 0; // assert active-low reset at time 0
#2 resetN = 1; // de-assert reset before posedge of clock
$display("\n count=%0d (expect 0)\n", count);
#1 $finish;
end
endmodule
注意:写Testbench时要对未确定状态的变量进行初始化。
在仿真时间“0”时就确定事件状态。
发表于 2009-10-6 22:00:47 | 显示全部楼层
very good! thanks!
发表于 2009-10-8 16:41:08 | 显示全部楼层
谢谢共享。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

×

小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-22 14:21 , Processed in 0.029897 second(s), 6 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表