---------------------------------------------------------------------------
Net 线路连接
Net 是结构描述中为线路连接(连线和总线)建立的模型。net的值是由net的驱动器所决定的。驱动器可以是门、UDP、实例模块或者连续赋值语句的输出。
语法:
{either}
NetType [ Expansion] [ Range] [ Delay] NetName,...;
trireg [ Expansion] [ Strength] [ Range] [ Delay]
NetName,...;
{Net declaration with continuous assignment}
用连续声明语句对 net 进行声明
NetType [ Expansion] [ Strength] [ Range] [ Delay]
NetAssign,...;
NetAssign = NetName = Expression
NetType = {either}
wire tri {equivalent}
wor trior {equivalent}
wand triand {equivalent}
tri0
tri1
supply0
supply1
Expansion = {either}
vectored scalared
Range = [ ConstantExpression: ConstantExpression]
在程序中位于何处:
module-
-endmodule
规则
编码规则下载淘宝规则下载天猫规则下载麻将竞赛规则pdf麻将竞赛规则pdf
:
· supply0 和 supply1 类型的 net 分别具有逻辑值0和1,并可以为它定义驱动能力(Supply strength)。
· tri0 和 tri1 类型的nets,当没有驱动时,分别具有逻辑值0和1,并可以为它定义驱动能力(Pull strength)。
· 如果net的扩展(Expansion)选项选用了关键词 vectored,则不允许对它进行某位和某些位的选择,也不允许对它定义强度,PLI会认为该 net 是不可扩展的;如果扩展(Expansion)选项选用了关键词scalared,则允许对它进行某位和某些位的选择,也允许对它定义强度,PLI将会认为该 net 是可扩展的,这些关键词是有参考价值的。
· 除了结构描述中的端口和标量连线不用声明其 net 类型外,其他类型的net变量在应用之前必须声明。
Truth Table 真值
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
当Net具有两个或两个以上驱动时,同时假定其驱动器强度值均相等,这些真值表则告诉我们输出的结果。如果不相等,则驱动强度大者,驱动该 Net。
注意!
· 当net未被驱动时,对tri0 或 tri1 类型的net 的连续赋值不影响其值和强度,经常为强度(strength)保持为Pull,和逻辑值保持为 0(对tri0)或 1(对tri1)。
· 在IEEE 标准和已成事实的Cadence公司标准中,扩展可选项的保留字scalared 或 vectored的位置有所不同,在Cadence标准中,保留字位于范围(range)选项的跟前。
可综合性问
题
快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题
:
· Net类型的变量被综合成线路连接,但是某些线路连接经优化后有可能被删去。
· 综合工具只支持 Net类型中wire型的综合,其它的 Net类型均不支持。
提示:
· 在每个模块的块首明确地声明所有的 nets,即使是缺省的类型也应该明确地加以说明。通过清楚地说明设计意图,可以提高 Verilog 程序的可读性和可维护性。
· 只能用supply0 和 supply1来声明地和电源。
举例说明:
wire Clock;
wire [7:0] Address;
tri1 [31:0] Data, Bus;
trireg (large) C1, C2;
wire f = a && b,
g = a || b; // 连续赋值
还请参照:
连续赋值,寄存器类型说明
--------------------------------------------------
Number 数
整数或者实数。在Verilog中整数是通过若干位来表示的,其中某些位可以是不定值(X)或高阻态(Z)。
语法:
{either}
BinaryNumber
(二进制数)
OctalNumber
(八进制数)
DecimalNumber
(十进制数)
HexNumber
(十六进制数)
RealNumber
(实数)
BinaryNumber = [ Size] BinaryBase BinaryDigit...
OctalNumber = [ Size] OctalBase OctalDigit...
DecimalNumber = {either}
[ Sign] Digit... {signed number}
[ Size] DecimalBase Digit...
HexNumber = [ Size] HexBase HexDigit...
RealNumber = {either}
[ Sign] Digit... .Digit...
[ Sign] Digit...[. Digit...]e[ Sign] Digit...
[ Sign] Digit...[. Digit...]E[ Sign] Digit...
BinaryBase = {either} 'b 'B
OctalBase = {either} 'o 'O
DecimalBase = {either} 'd 'D
HexBase = {either} 'h 'H
Size = Digit...
Sign = {either} +
-Digit = {either} _ 0 1 2 3 4 5 6 7 8 9
BinaryDigit = {either} _ x X z Z ? 0 1
OctalDigit = {either} _ x X z Z ? 0 1 2 3 4 5 6 7
HexDigit = {either} _ x X z Z ? 0 1 2 3 4 5 6 7 8 9 a A
b B c C d D e E f F
UnsignedNumber = Digit...
在程序中位于何处:
请参阅表达式。
规则:
· 表示进制的字母、十六进制数、X和Z在数的表示中是不区分大小写的,字符Z和?在数的表示中是等价的。
· 数字中不能有空格,但是在表示进制的字母两侧可以出现空格。
· 负数表示为其二进制的补数。
· 数字的第一个字符不允许出现下划线’_’,但标识符可以。为了提高数字的可读性可用下划线把长的数字分段,在处理数字时下划线将被忽略。
· 位宽指明了数字的准确位数。
· 不指明位宽的数字,它的位宽应为32位或32位以上,取决于主机字长。
· 如果位宽大于实际的二进制位数时,高位部分补0,但除非左边最高位是X或Z,在这种情况下,则补X或Z。
· 如果位宽小于实际的二进制数位时,超过位宽的高位(左边)被舍去。
注意!
· 定义了位宽的负数被赋值到寄存器后,它将被认为是无符号的数。
reg [7:0] byte;
reg [3:0] nibble;
initial
begin
nibble = -1;
//例如 4'b1111
byte = nibble;
// 变为 8'b0000_1111
end
当寄存器类型的数或者定义了位宽的数被用在表达式中时,其值通常被当作一个无符号数。
integer i;
initial
i = -8'd12 / 3; // i变成 81 (即 8'b11110100 / 3)
可综合性问题:
· 0和1分别被综合成接地和接电源的连线,赋值为X的则被认为是无关项。 除了使用 casex 语句,如用其它的条件语句,与X的比较都认为是假的。 (case 等式运算符=== 和!== 一般情况下都是不可综合的)
· 除了在casex 和 casez语句中Z被认为是无关项,在其它情况下 Z 则被用来表示三态驱动器。
提示:
· 在 case 语句的标号中,通常用 ?要比用Z好。在程序的其它地方不要使用 ?号,否则会产生混淆。
· 用下划线来分隔较长的数字,从而提高可读性。
举例说明:
-253
// 有符号的十进制数
'Haf
// 未定义位宽的十六进制数
6'o67
// 位宽为六的八进制数
8'bx
// 位宽为8的二进制数,其值为不定值
4'bz1
// 位宽为四的二进制数,最低位为1其余高三位均为高阻值(4'bzzz1)。
下面所列的数为不合法的数并解释其原因:
_23
// 以_开头
8' HF F
// 包含两个非法空格
0ae
// 十进制数中出现十六进制数字
x
// 是名字,不是数字(应用1'bx)
.17
//
应该是0.17
还请参照:
表达式,字符串说明
-----------------------------------------------------------------------
Operators 运算符
在表达式中,使用运算符便可根据操作数(诸如数字、参量以及其它子表示式)计算出表达式的值。Verilog语言中的运算符和C语言中的很相似。
单目运算符:
+ -
正负号
!
逻辑非
~
按位取反
& ~& | ~| ^ ~^ ^~
缩位运算符 (~^ 和 ^~ 等价)
二目运算符:
+ - * /
算术运算符
%
取模运算符
> >= < <=
关系运算符
&& ||
逻辑运算符
== !=
逻辑等式运算符
=== !==
case等式运算符
& | ^ ^~ ~^
逐位运算符 (^~ 和 ~^ 等价)
<<
>>
移位运算符
其它运算符:
A ? B : C
条件运算符
{ A, B, C }
位拼接运算符
{ N{A} }
重复运算符
在程序中位于何处:
参阅表达式说明。
规则:
· 逻辑运算符把它的操作数当作布尔变量。例如,非零的操作数被认为是真(1'b1);零被认为是假(1'b0);不确定的值,例如4'bXX00,因不能判断其值为真还是假,就被认为是不确定的(1'bX)。
· 位运算符(~ & | ^ ^~ ~^)和全等运算符( = = = != = )把它们操作数的逐位分别进行处理。
· 在包含 = = 或 != 的逻辑比较式中,如果有任何一个操作数为X或Z,其结果便是不确定的(1'bX)。(请仔细看注意事项)
· 在包含(< > <= >= )的比较式中,如果操作数不确定,其结果为不定值。(1'bX)例如:
2'b10 > 1'b0X
// 结果为真
2'b11 > 1'b1X
// 结果不定(1'bX)
(请看注意事项)
· 缩位运算符( & ~& | ~| ^ ~^ ^~ )将一个矢量缩减为一个标量。
· 位宽确定的表达式的运算采用溢出的位不计的办法, 例如:4'b1111 + 4'b0001 = 4'b0000.
· 整数作除法运算时,小数部分被截掉。
· 取模运算(%)的结果是第一个操作数被第二个操作数除的余数,符号与第一个操作数一致。
· 只有某些特定的运算符允许出现在实数表达式中,例如单目运算符+和-、算术运算符、关系运算符、逻辑运算符以及条件运算符。实数逻辑或关系运算符的结果是一个只有一位的值。
运算符的优先级:
+ - ! ~
单目(unary) -
最高优先级
* / %
+ -
双目(binary)
<< >>
< <= > >=
== != === !==
& ~&
^ ^~
| ~|
&&
||
?:
最低优先级
注意:
· 应用 ==、 !=、 <、 > 、 <= 和 >= 对某些位不确定的值进行比较的规则并不适用于所有的仿真器,这点请特别注意!
· 注意单目缩位运算符与逐位逻辑运算符之间的区别,运算符本身是相同的,可根据上下文的关系来判断是哪一种,有时必须要用括号才能表达清楚。
可综合性问题:
· 逻辑运算符、逐位运算符、移位运算符是可综合的,都被综合成逻辑运算。
· 条件运算符是可综合的,被综合成多路器或带使能端的三态门。
· 运算符+、 -、 * 、< 、<= 、>、 >=、 == 和 != 都是可综合的,被分别综合成加法器、减法器、乘法器和比较器。
· 运算符 / 和 % 一般是不可综合的,只有当能用移位寄存器来表示运算时才是可综合的。而常量的 / 和 %运算是可综合,但结果只能用二进制数表示。
· 其它运算符均不能被任何工具所综合。
提示:
在写表达式的时候,运用括号要比依靠运算符的优先级要好,这样可预防错误产生,并且使那些不太了解 Verilog 语言的人更容易理解你的意思。
举例说明:
-16'd10
// 这是表达式,是负运算,不是有符号数!
a + b
x % y
Reset && !Enable
// 与 Reset && (!Enable)相同
a && b || c && d
// 与 (a && b) || (c && d)相同
~4'b1101
// 结果为 4'b0010
&8'hff
// 结果为 1’b1,即一位的逻辑值1
还请参照:
Expression 的说明
-----------------------------------------------------------------------------
Parameter 参数
参数是为常数命名的一种手段。在 Verilog 代码模块编译时(而不是在仿真期间),可以改写参数的值。使用参数就有可能重新定义 Verilog 代码中的常数,如数组的宽度等。
语法:
parameter Name = ConstantExpression,
Name = ConstantExpression,
... ;
有些工具支持下列非标准的语法:
parameter [ Range] Name = ConstantExpression,
Name = ConstantExpression,
... ;
Range = [ ConstantExpression: ConstantExpression]
在程序中位于何处:
module--endmodule
begin : Label--end
fork : Label--join
task--endtask
function--endfunction
规则:
· 参数是常量,在仿真期间更改参数的值是非法的。
· 在编译期间用 defparam 或者当包含参数的模块被引用时, 可以改写其参数的值。
可综合性问题:
有些综合工具能把含有参数的模块当作模板,一旦读入模板,便能够用不同的参数值多次对该模板进行综合。所有的综合工具都支持不带改动参数的模块实例的综合。
提示:
尽可能用参数给常数起一个有含义的名字。
举例说明:
下面的例子是一个 N 位宽的(可通过参数改变位宽的)移位寄存器。实例引用该参数化移位寄存器时可重新定义不同的位宽。
module Shifter (Clock, In, Out, Load, Data);
parameter NBits = 8;
input Clock, In, Load;
input [NBits-1:0] Data;
output Out;
always @(posedge Clock)
if (Load)
ShiftReg <= Data;
else
ShiftReg <= {ShiftReg[NBits-2:0], In}
assign Out = ShiftReg[NBits-1];
endmodule
module TestShifter;
...
defparam U2.NBits = 10;
Shifter #(16) U1 (...);
//
6位移位寄存器
Shifter U2 (...)
// 10位移位寄存器
Endmodule
还请参阅:
`define, Defparam, Instantiation, Specparam语句的说明。
------------------------------------------------------------------------
PATHPULSE$ 路径脉冲参数
· 在指定块中用指定参数 (即用specparam)对PATHPULSE$参数赋值可控制脉冲的传输。这里所谓的脉冲是指在模块输出端出现的两个跳变沿和它们之间的一段持续时间,其持续时间必须小于信号从模块的输入端直到输出端的延时。
· 如果使用缺省的PATHPULSE$参数值,仿真器将不考虑脉冲,这就是指因为路径脉冲的持续时间比模块传输延时短,故脉冲不能传过该模块,这种效应被称为“时延惯性”。用指定参数 (即用specparam)可给PATHPULSE$参数赋新的值。
语法:
{either}
PATHPULSE$ = ( Limit[, Limit]); {(Reject, Error)}
PATHPULSE$Input$Output = ( Limit[, Limit]);
Limit = ConstantMinTypMaxExpression
在程序中位于何处:
specify--endspecify
规则:
· 如果PATHPULSE$的第二个极限参数(即 Error)没有给定,它就应该与第一个极限参数(即 reject)相同。
· 维持时间比第一个极限参数(即 reject)短的脉冲不会输出。
· 维持时间比第一个极限参数(即 reject)长而比第二个极限参数(即 Error)短的脉冲将输出一位的不确定值(即 1'bX)。
· 维持时间比第二个极限参数长的脉冲将正常地输送出去。
· 用specparam对PATHPULSE$input$output参数重新赋值将改写常规值。
· 在同一个模块中可通过使用specparam对PATHPULSE$赋值来描述从输入到输出的延时。
可综合性问题:
综合工具不考虑延时结构,包括指定块的定义。
举例说明:
specify
(clk => q) = 1.2;
(rst => q) = 0.8;
specparam PATHPULSE$clk$q = (0.5,1),
PATHPULSE = (0.5);
Endspecify
还请参阅:
Specify, Specparam 说明
-------------------------------------------
Port 端口
模块的端口是硬件器件的引脚或接口的模型。
语法:
{definition}
{either}
PortExpression {ordered list}
.PortName([ PortExpression]) {named list}
PortExpression = {either}
PortReference
{ PortReference,...}
PortReference = {either}
Name
Name[ ConstantExpression]
Name[ ConstantExpression: ConstantExpression]
{declaration}
{either}
input [ Range] Name,...; {of port reference}
output [ Range] Name,...; {of port reference}
inout [ Range] Name,...; {of port reference}
Range = [ ConstantExpression: ConstantExpression]
{在上述部分位选择(即 Range)选项内,冒号左侧常量表达式表示最高位(即 MSB),冒号右侧常量表达式表示最底位(即LSB)}
在程序中位于何处:
module (); {definition}
{declaration}
...
endmodule
规则:
· 在端口列表中列出的所有端口必须按次序排列或按端口名称排列,这两种排列方式是不同的,不能混合使用。
· 有端口的名称但没有端口表达式,如 .A( ),则表示在本模块中定义了不与任何东西相连的端口。
· 每个端口除了必须在端口列表中列出外, 还必须声明该端口是输出(output)、输入(input)、还是双向端口(inout)。
· 每个端口不但要声明是输出、输入、还是双向端口,而且还要声明是连线(wire)还是寄存器(reg)类型,如果没声明,则会隐含地认为该端口是连线(wire)类型,且其位宽与相应的端口一致。如果某端口已被声明为一矢量,则其端口的方向和类型两个声明中的位宽必须一致。
· 输入和双向端口不能声明为寄存器类型。
· 输出端口的类型不能声明为实型(Real)或实时型(realtime)。
提示:
· 在测试模块中不要定义端口。
· 在模块定义时不建议使用命名的端口的列表,因为很少有人这样来定义模块端口,大家都不了解这种端口的定义形式。
举例说明:
module (A, B[1], C[1:2]);
input A;
input [1:1] B;
output [1:2] C;
module (.A(X), .B(Y[1]), .C(Z[1:2]);
input X;
input [1:1] Y;
output [1:2] Z;
还请参照:
Module, User Defined Primitive, Instantiation 的说明。
---------------------------------------------------------
Procedural Assignment 过程赋值语句
改变寄存器的值,或者安排以后的变化。
语法:
{Blocking assignment}
阻塞赋值
RegisterLValue = [ TimingControl] Expression ;
{Non-blocking assignment}
非阻塞赋值
RegisterLValue <= [ TimingControl] Expression ;
RegisterLValue = {either}
RegisterName
RegisterName[ Expression]
RegisterName[ ConstantExpression: ConstantExpression]
Memory[ Expression]
{ RegisterLValue,...}
在程序中位于何处:
请参阅statement语句的说明。
规则:
· 对寄存器的赋值(不包括正负号)
· 对于实型和实时数据类型的寄存器不允许选择某位和某几位的。
· 当赋值语句执行时,右侧的表达式被计算出值,但是直到定时控制事件或延时(也被称为‘内部指定的延时’)发生后,左侧的表达式才更新。
· 直到左侧的表达式更新后(例如内部定义的延时过后)阻塞赋值语句才算完成。在begin-end模块中,只有当前一条语句执行完后,才能执行其后面的一条语句。在fork-join模块中,只有当块中所有的阻塞赋值语句结束后,整个块才算结束。
· 如果仿真时刻相同,要待所有的阻塞赋值语句执行后,非阻塞赋值语句才执行。
A <= #5 0;
A = #5 1; //5个时间单位后,A将变为0,而不是变为1
注意!
寄存器变量可以在一个或几个initial 或 always 语句中赋值。无论何时,寄存器变量的值都是由最近的赋值所决定,与事件的来源无关。这一点与 net 类型的变量不同。net可以由两个或更多的源驱动,其结果值则取决于net变量的类型(wire型,wand型等)。
可综合性问题:
· 综合工具不考虑延时。
· 定时控制或延时是不可综合的。
· 同一个寄存器类型变量虽然可以在几个always语句中赋值,但只有在一个 always语句中赋值的才有可能被综合。
· 同一个寄存器类型变量不能既用阻塞赋值和非阻塞赋值。
· 在描述组合逻辑的always块中,右侧表达式被综合成组合逻辑,左侧的表达式被综合成连线,如有不完整的赋值则综合成锁存器。在描述时序逻辑的用时钟沿触发的always块中,非阻塞赋值符的左侧被综合成触发器,阻塞赋值符的左侧则被综合成一个连接,除非它被用在该always块之外,或者在赋值之前它的值已被读取。
提示:
· 通常采用非阻塞赋值语句来生成触发器组成的时序逻辑,而阻塞赋值常用于其它方面,这样做可以防止时钟沿触发的 always 块中发生竞争冒险。这样做也可使设计意图更加清晰,又能避免生成不需要的触发器。
· 在时钟树的模型已确定的情况下,可用一个简单的内部指定的延时来避免RTL时钟沿对不齐的问题。
举例说明:
always @(Inputs)
begin : CountOnes
integer I;
f = 0;
for (I=0; I<8; I=I+1)
if (Inputs[I])
f = f + 1;
end
always @Swap
fork // 交换a和b的值
a = #5 b;
b = #5 a;
join // 延时5秒后完成
always @(posedge Clock)
begin
c <= b; // 用旧的b值
b <= a; // b被a值替换
end
用非阻塞赋值语句时加一个延时来做输出与时钟沿有些偏移的仿真:
always @(posedge Clock)
Count <= #1 Count + 1;
在时钟周期的第五个下降沿插入复位信号:
initial
begin
Reset = repeat(5) @(negedge Clock) 1;
Reset = @(negedge Clock) 0;
End
还请参照:
Timing Control, Continuous Assignment 的说明。
--------------------------------------------------------------------------
Procedural Continuous Assignment 过程连续赋值语句
启动过程连续赋值语句,将给一个或多个寄存器赋值,并同时防止一般的过程赋值语句影响已赋值的寄存器。
语法:
assign RegisterLValue = Expression ;
deassign RegisterLValue ;
RegisterLValue = {either}
RegisterName
RegisterName[ Expression]
RegisterName[ ConstantExpression: ConstantExpression]
MemoryName[ Expression]
{ RegisterLValue,...}
在程序中位于何处:
请参阅 Statement的说明。
规则:
· 过程连续赋值语句执行后,它会对指定的寄存器(组)强制地维持过程连续赋值直到解除赋值(deassign)语句的执行,或直到另一个过程连续赋值语句又对该寄存器(组)赋值。
· 用force(强制)语句可以改写已由过程连续赋值语句赋值的寄存器类型变量,直到 release 语句的执行,此时强制赋值被解除而原过程连续赋值对该寄存器类型变量的作用又重新恢复。
注意!
连续赋值语句与过程连续赋值语句尽管很相似,但并不是完全一致。在编写程序时,确认将assign写在正确的位置。 过程连续赋值语句可以写在声明语句允许出现的位置(在initial, always, task, function等内部),而连续赋值语句则必须写在任何initial 或 always块之外。
可综合性问题:
无论用什么综合工具,过程连续赋值语句是都不能综合的。
提示:
过程连续赋值语句可以用来为异步复位和中断建立仿真模型。
举例说明:
always @(posedge Clock)
Count = Count + 1; //受下面always块控制的计时钟个数的计数器
always @(Reset) // 异步复位
if (Reset)
assign Count = 0; // 当 Reset为高时,使Count为0,不计数
else
deassign Count; // 当 Reset为低时,解除Count为0,
//于是下一个时钟的上升沿又重新开始计数。
还请参阅:
Continuous Assignment, Force 的说明
--------------------------------------------------------------------------
Programming Language Interface 编程语言接口
Verilog编程语言接口 (PLI)为用户提供了在Verilog模块中调用用C语言编写的
函数
excel方差函数excelsd函数已知函数 2 f x m x mx m 2 1 4 2拉格朗日函数pdf函数公式下载
的手段。这些函数可以动态地访问和修改被引用的Verilog数据结构中的数据,用PLI编写的系统任务使上述功能变得容易使用。通过调用用户定义的系统任务和函数的可以来启动PLI,用户编写自己的PLI 模块的目的是扩大系统任务和函数的内容。用户自定义的系统任务和函数在调用时都用以$字符开头的任务和函数名。这与Verilog语言提供的系统任务和函数库名一致。如用户自定义的系统任务和函数名与原系统任务或函数名相同时,则执行用户自定义的系统任务和函数。
下面列举的是PLI在某些方面的应用:
· 延迟计数
· 测试矢量读入
· 波形演示
· 源代码调试
接口模型可用C语言或其他语言(例如VHDL或硬件建模工具)编写或生成。
对于PLI的全面讨论超出了本参考指南的范围。
-----------------------------------------------------------------------------
Register 寄存器
寄存器可存储在initial、 always、task 和 function 块中所赋的值,广泛地应用在行为建模中。
语法:
{either}
reg [ Range] RegisterOrMemory,...;
integer RegisterOrMemory,...;
time RegisterOrMemory,...;
real RegisterName,...;
realtime RegisterName,...;
RegisterOrMemory = {either}
RegisterName
MemoryName Range
Range = [ ConstantExpression: ConstantExpression]
在程序中位于何处:
module--endmodule
begin : Label--end
fork : Label--join
task--endtask
function--endfunction
规则:
· 寄存器类型变量只能用过程赋值语句赋值。
· 在具体实现时,整数(integer)类型的变量至小用32位,时间(time)类型的变量至小用64位寄存器。
· integer 或 time类型的寄存器变量与位数相同的reg类型的寄存器变量行为是相同的。Integer 和 time 型的寄存器变量也可像reg类型的寄存器变量一样对某位或某些位操作。而在表达式中,整数类型的值被当作有符号值,而reg、time类型的值被当作无符号值。
· 存储器类型数组中的每个元素作为整体可以进行读或写操作,如果要单独访问数组中某个元素的个别位,则必须先把这个元素的内容复制到某个位数相同的寄存器变量中才能进行。
注意!
· 虽然 register 这个词指的是硬件寄存器(例如触发器),而寄存器(register)这个名字,在这里是指软件寄存器(即变量)。Verilog寄存器常用于组合逻辑电路、锁存器、触发器和接口电路的描述和综合。
· realtime 类型寄存器变量是Verilog语言新增加的变量类型,目前还没有任何工具支持这种类型的变量。
· 有符号和无符号值的概念,不同版本的Verilog和用不同厂家的仿真器时,并不是完全一致的。因此,当使用位宽大于32位的有符号数或矢量时要特别注意。
可综合性问题: .
· Real, time 和 realtime类型的寄存器变量是不可综合的。
· 在描述组合逻辑的always块中,寄存器被综合成 wire型;如果存在不完整赋值的情况,则被综合成锁存器。在描述时序逻辑的always块中,寄存器根据块内语句的内容被综合成连线(wire)或者触发器。
· 运用目前的综合工具,整数被综合成32位,其值用二进制数表示,负数则用其二进制补码表示。
· 根据所用语句,存储器数组会被综合成触发器或连线,而不会被综合成RAM 或 ROM的器件。
提示:
运用reg类型变量来描述寄存器逻辑,integer类型变量用于循环变量和计数,real类型变量用于系统模块,time 和 realtime类型变量用于测试模块中记录仿真时刻。
举例说明:
reg a, b, c;
reg [7:0] mem[1:1024], byte; // byte 不是数组只是一个8位的reg类型矢量
integer i, j, k;
time now;
real r;
realtime t;
下面的部分显示了reg 类型 和integer 类型变量的一般用法
integer i;
reg [15:0] V;
reg Parity;
always @(V)
for ( i = 0; i <= 15; i = i + 1 )
Parity = Parity ^ V[i];
还请参阅:
Net的说明。
-------------------------------------------------------------------------
Repeat
重复执行语句
把一个或多个声明语句重复地执行指定的次数。
语法 :
repeat ( Expression)
Statement
在程序中位于何处:
参见 Statement 的说明
规则:
重复执行的次数是由表达式的数值所决定的,如果该值为0, X 或 Z,则不会有重复。
可综合性问题:
只有部分综合工具可以综合repeat语句,而且只有当该循环中的每个循环的分支都被时钟事件,如被 @(posedge Clock),所中断时才有可能被综合成电路。
举例说明:
initial
begin
Clock = 0;
repeat (MaxClockCycles)
begin
#10 Clock = 1;
#10 Clock = 0;
end
end
还请参阅:
For, Forever, While, Timing Control的说明。
--------------------------------------------------------------------------
Reserved Words
关键词
下列词汇是Verilog语言规定的所有的关键词,请注意,千万不要把这些标识符用作自定义的标识符,除非把他们改写为大写的字符或扩展字符。
And for output strong1
Always force parameter supply0
Assign forever pmos supply1
Begin fork posedge table
Buf function primitive task
bufif0 highz0 pulldown tran
bufif1 highz1 pullup tranif0
case if pull0 tranif1
casex ifnone pull1 time
casez initial rcmos tri
cmos inout real triand
deassign input realtime trior
default integer reg trireg
defparam join release tri0
disable large repeat tri1
edge macromokule mmos vectored
else medium rpmos wait
end module rtran wand
endcase nand rtranif0 weak0
endfunction negedge rtranif1 weak1
endprimitive nor scalared while
endmodule not small wire
endspecify notif0 specify wor
endtable notif1 specparam xnor
endtask nmos strength xor
event or strong0
----------------------------------------------------------------------
Specify
指定的块延时
Specify块(指定延时块)用于描述从模块的输入到输出的路径延时以及定时约束,例如信号的建立和保持时间。用指定延时块可以在设计时把模块的信号传输延时与行为或结构分开来进行描述。
语法:
specify
SpecifyItems...
endspecify
SpecifyItem = {either}
Specparam
PathDeclaration
TaskEnable {Timing checks only}
PathDeclaration = {either}
SimplePath = PathDelay;
EdgeSensitivePath = PathDelay;
StateDependentPath = PathDelay;
SimplePath = {either}
( Input,... [ Polarity] *> Output,...) {full}
( Input [ Polarity] => Output) {parallel}
EdgeSensitivePath = {either}
([ Edge] Input,... *> Output,... [ Polarity]: Expression)
([ Edge] Input => Output [ Polarity]: Expression)
StateDependentPath = {either}
if ( Expression) SimplePath = PathDelay;
if ( Expression) EdgeSensitivePath = PathDelay;
ifnone SimplePath = PathDelay;
Input = {either}
InputName
InputName[ ConstantExpression]
InputName[ ConstantExpression: ConstantExpression]
Output = {either}
OutputName
OutputName[ ConstantExpression]
OutputName[ ConstantExpression: ConstantExpression]
Edge = {either} posedge negedge
Polarity = {either}
+
-
PathDelay = {either}
ListOfPathDelays
( ListOfPathDelays)
ListOfPathDelays = {either}
t
t,t
{Rise,Fall}
t,t,t
{Rise,Fall,Turn-Off}
t,t,t,t,t,t {01,10,0Z,Z1,1Z,Z0}
t,t,t,t,t,t,t,t,t,t,t,t {01,10,0Z,Z1,1Z,Z0,0X,X1,1X,X0,XZ,ZX}
t = MinTypMaxExpression
在程序中位于何处:
module--endmodule
规则:
· 路径必须从模块的输入端开始,在该模块的输出端结束,而且在模块内部只能有一个驱动器。
· 在路径声明中可使用全连接符( *> )或者并行连接符( => )来描述。全连接符指所有从输入端到输出端可能的路径,并行连接符指命名的输入端的某些位到命名的输出端的某些位的路径。
· 模块路径的极性可选是指着路径可以选择正极性或者负极性,分别指路径是同相的或是反相的(即路径的输入端若是正跳沿,输出端也是正跳沿,则路径是同相的。反之是反相的)。无论选哪一个都不影响仿真,但路径的相位可改变的选项便于时序
分析
定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析
等工具使用。
· 跳变沿敏感的路径数据表达式同样也不影响仿真。
· 与状态有关的路径延时(SDPD)表达式只跟端口、常量、局部定义的寄存器或者net类型变量有关。只有部分运算符在SDPD表达式中是有效的:如逐位计算符( ~ & | ^ ^~ ~^ )、逻辑运算和逻辑等式运算符(== != && || ! )、 缩位运算符( & | ^ ~& ~| ^~ ~^ )、位拼接运算符、重复拼接运算符和条件运算符( {} {{}} ?: )。如果条件表达式的值为真(在SDPD 表达式中 1,X,Z 均被认为是真),路径延时只影响路径。
· 如果没有一个if 条件为真,则用Ifnone来定义缺省的SDPD。如果同一条路径既定义为ifnone 与状态有关的路径延时(SDPD)又定义为一般简单的路径延时,则是非法的。
· 无条件的路径优先于SDPD路径。
· 对于同一条路径,跳变沿敏感的SDPD路径声明必须是唯一的,必须用不同的电平或不同的沿(或者两者)。在每条语句中,必须以同样的方式(整个端口、某一位、某些位)来引用输出端的信号。
· 如果模块的延时既包括指定的块延时(specify delays)又包括分布的延时(即由门、UDP、Net引起的延时),应选用最长的延时作为每条路径的延时。
可综合性问题:
综合工具不能综合指定延时块。指定延时块只用于模块的时延仿真建模。
注意!
· 目前还没有一个仿真工具支持上面语法中列出的那种可用12种不同跳变参数表示某条路径延时的方法。
· 有关路径目的地的规则比当前许多仿真工具所能支持的灵活。
提示:
· 运用指定延时块来描述库中的单元(cell)延时。请注意建立库模型时延时是怎样计算的。以PLI(编程语言接口)为基础的延时计算,需要依据并访问设计中所有单元的指定延时块中的信息。
· 可运用指定延时块来描述“黑匣子”元件的定时特性, 但这时还需要借助于支持指定延时块特性的时序验证工具或综合工具。
举例说明:
module M (F, G, Q, Qb, W, A, B, D, V, Clk, Rst, X, Z);
input A, B, D, Clk, Rst, X;
input [7:0] V;
output F, G, Q, Qb, Z;
output [7:0] W;
reg C;
// Functional Description ...功能描述
specify
specparam TLH$Clk$Q = 3,
THL$Clk$Q = 4,
TLH$Clk$Qb = 4,
THL$Clk$Qb = 5,
Tsetup$Clk$D = 2.0,
Thold$Clk$D = 1.0;
// 单一路径,全连接
(A, B *> F) = (1.2:2.3:3.1, 1.4:2.0:3.2);
// 单一路径,并行连接,正极性
(V + => W) = 3,4,5;
// 沿敏感路径,带极性
(posedge Clk *> Q +: D) = (TLH$Clk$Q,THL$Clk$Q);
(posedge Clk *> Qb -: D) = (TLH$Clk$Qb,THL$Clk$Qb);
// 电平敏感路径
if (C) (X *> Z) = 5;
if (!C && V == 8'hff) (X *> Z) = 4;
ifnone (X *> Z) = 6; // 缺省为SDPD,从 X(不定值)到 Z(高阻值)
// 时序检测
$setuphold(posedge Clk, D,Tsetup$Clk$D, Thold$Clk$D, Err);
endspecify
endmodule
还请参阅:
Specparam, PATHPULSE$, $setup 的说明。
---------------------------------------------------------------------------
Specparam
延时参数
类似于parameter(参数),但只能用在指定延时块中。
语法:
specparam Name = ConstantExpression,
Name = ConstantExpression,
... ;
在程序中位于何处:
specify -- endspecify
规则:
· Specify块中的常量表达式可以用数字和 specparam 来定义,但不能用参数(parameter)来定义,specparam 不能用在 Specify块(即指定延时模块)外。
· 利用 defparam 或在模块的实例引用时使用#,可以改写用 specparam 定义的延时参数值,用编程语言接口(PLI)也可以修改其值。
提示
· 在Specify块中,用specparam来定义命名的延时参数比直接用数字要好。
· 这些延时参数应有一个命名的规则,这样便于对它们进行修改,如果有必要的话,也可以采用PLI的延时计数来进行修改。
举例说明:
specify
specparam
tRise$a$f = 1.0,
tFall$a$f = 1.0,
tRise$b$f = 1.0,
tFall$b$f = 1.0;
(a *> f) = (tRise$a$f, tFall$a$f);
(b *> f) = (tRise$b$f, tFall$b$f);
endspecify
还请参阅:
PATHPULSE$, Specify的说明。
-------------------------------------------------------------------------
Statement
声明语句
运用声明语句可以描述硬件模块的行为。声明语句在定时控制的(延时、控制程序、等待)时刻执行。若两个或两个以上的语句是一起的,必须把它们写在 begin-end 或 fork-join块中。在 begin-end 块中每条语句是顺序执行的,在fork-join块中,它们是并行执行的。initial 或 always块中的语句是同其它initial 或 always块中的语句是同时执行的。
语法:
{either}
;
{Null statement}
TimingControl Statement {Statement may be Null}
Begin
Fork
ProceduralAssignment
ProceduralContinuousAssignment
Force
If
Case
For
Forever
Repeat
While
Disable
-> EventName; {Event trigger}
TaskEnable
在程序中位于何处:
initial-
always-
begin--end
fork--join
task--endtask {Null allowed}
function--endfunction
if()--else- {Null allowed}
case- label:--endcase {Null allowed}
for()-
forever-
repeat()-
while()-
还请参阅:
Timing Control的说明。
1
44