IEEE Standard(1)--Conventions

本文最后更新于:Wednesday, September 30th 2020, 8:01 pm

1、Overview

1.1 Convention

shall: 用于法定的要求(mandatory requirement)

may: 用于可选的特性(optional feature)

1.2 Syntactic description

BNF描述方法(Backus-Naur Form):

基本结构为:::=

  • ::=:被定义为的意思
  • “ ”: 双引号表示字符串,也就是终结符,不能再被定义。
  • 在双引号外的字代表着语法部分;基本类型 ::= 字符串 | 数字 | 布尔,其中字符串、数字、布尔具体是什么,由下面的规则定义(递归)
  • <>:尖括号里的内容表示必选内容;
  • [...]: 表示可选。
  • {...}:表示重复;实例:AB ::= "a" {"b"}表示:AB由一个a加上任意数量(包括0个)个b组成
  • (...): 表示分组,用来控制优先级;AX ::= "a" ("m"|"n")表示:AX由一个a加上m或者n组成
  • (*...*) : 注释,说明性文本,不表示任何语法。
  1. 小写单词,一些包含下划线的:语法目录(syntactic categories)

    module_declaration

  2. 粗体:保留字、操作符、标点符号

    module => ;

  3. 竖条|分割可选单元。如果它以粗体形式出现,它才表示自己。

    ​ unary_operator ::= + | - | ! | ~ | & | ~& | |(或) | ~|(或非) | ^ | ~^ | ^~(都表示同或)

  4. 方括号[…]包含可选项。

    input_declaration ::= input [range] list_of_variables;

  5. 花括号{}除非以粗体出现,它才表示自己,否则表示重复。重复从左到右进行,和左递归等效。

    • list_of_param_assignments ::= param_assignment { , param_assignment }

    • list_of_param_assignments ::=
      param_assignment| list_of_param_assignment , param_assignment

  6. 任何目录的名字以斜体开头,等效于没有斜体部分的目录名。斜体部分只是为了传达semantic information

    mark

  7. 正文中当一个term被定义时使用斜体;在例子,文件名,常量特别时0,1,x和z的值时使用constant-width字体(等宽字体)

2、Lexical convention

2.1、Lexical tokens

Verilog HDL source file shall be a stream of lexical tokens. A lexical tokens shall consist of one or more characters.
verilog源文件应该是一连串语法标记,一个语法标记由一个或多个字符组成。

源文件中tokens的位置是随意的,也就是说:除了token分隔符,空格和换行不应该有特殊意义,转义字符除外。

有如下几种语法标记

  • White space
  • Comment
  • Operator
  • Number
  • String
  • Identifier
  • Keyword

2.2、White space

white space应该包含:用于空格、制表符、换行符和格式提要的字符。这些字符应该被忽略除了当它们用于分割其他语法标记(tokens)。但是blanks和tabs被认为是有意义的字符在字符串中。

2.3、Comments

  • 单行注释 //
  • 块注释:/* …. */

2.4、Operators

操作符可以是单个,双个或三个字符的序列,并被用在表达式中。Clause5将讨论表达式中操作符的使用。

单目运算符(Unary operators):在操作数(operand)的左边

双目运算符(Binary operators):在两个操作数中间

三木运算符(Triple operator or conditional operator): 有两个操作符字符分割三个操作数(a? x: y)

2.5、Numbers

Constant numbers可以被指定为integer constant或者real constant

2.5.1、Integer constant

有两种表达方式:

  1. 简单的十进制数:a sequence of digits of 0 through 9。开头可以加上+或者-(被视为有符号的整数)
  2. 指定基码(d,h,o,b):可选的位宽+'(ASCII 0x27)+基码+digits
    • 位宽:非零无符号十进制数
    • 基码:大小写不敏感;前面可选s指示是否为有符号数(没有s时默认为unsigned integers)
    • '基码中间不能有空格。
    • digits: 应该紧跟着基码,前面也可以有空格。a-f不区分大小写
    • s不影响指定的位模式,只改变解释方式。❓
  • 负数用补码表示
  • x代表unknown value;z代表high-impedance value(x应该设为4bit对于h的基码,3bit对于o的基码;z同理)
  • 如果无符号数位宽小于指定位宽,那么用0填充;如果无符号数最左边的位是x或z;那么用x或z填充。如果无符号位宽大于指定,那么应该从左边截断到指定位宽。
  • 没有指定位宽的数字至少为32位;对于高位是x或者z的没有位宽无符号常数应位扩展到包含该常数的表达式的大小。❓
  • ?z的替代字符。在高阻值不需要注意时,可用?来增加可读性。
  • 在十进制常数中,无符号数不能包含任何x,z,?;除非只有一个digit,指示其中每一位都是x或者z。
  • _下划线在数字的任何位置都是合法的,除了第一个字符。下划线是没有意义的 ,只是为了分割长的数字提高可读性。

无符号数:

1
2
3
4
5
6
7
8
9
10
11
12
/************* Example 1--Unsized constant numbers *****************/
659 // is a decimal number
'h 837FF // is a hexadecimal number
'o7460 // is an octal number
4af // is illegal (hexadecimal format requires 'h)

/************* Example 2--Sized constant numbers *****************/
4'b1001 // is a 4-bit binary number
5 'D 3 // is a 5-bit decimal number
3'b01x // is a 3-bit number with the least significant bit unknown
12'hx // is a 12-bit unknown number
16'hz // is a 16-bit high-impedance number

有符号数的表示意义:

1
2
3
4
5
6
7
/************* Example 3—Using sign with constant numbers *****************/
8 'd -6 // this is illegal syntax
-8 'd 6 // this defines the two's complement of 6, held in 8 bits—equivalent to -(8'd 6)
4 'shf // this denotes the 4-bit number '1111', to be interpreted as a 2's complement number,
// or '-1'. This is equivalent to -4'h 1
-4 'sd15 // this is equivalent to -(-4'd 1), or '0001'
16'sd? // the same as 16'sbz

自动左填充:

1
2
3
4
5
6
7
8
9
10
11
12
/************* Example 4—Automatic left padding **************************/
reg [11:0] a, b, c, d;
initial begin
a = 'h x; // yields xxx
b = 'h 3x; // yields 03x
c = 'h z3; // yields zz3
d = 'h 0z3; // yields 0z3
end
reg [84:0] e, f, g;
e = 'h5; // yields {82{1'b0},3'b101}
f = 'hx; // yields {85{1'hx}}
g = 'hz; // yields {85{1'hz}}

使用下划线:

1
2
3
4
/************* Using underscore character in numbers *******************/
27_195_000
16'b0011_0101_0001_1111
32 'h 12ab_f001

2.5.2、Real constants

real constantsIEEE Std 754-1985,双精度浮点数表示

有两种表示方法:

  1. 十进制表示:14.72
  2. 科学计数法:39e8(表示39乘以10的8次方)

注意:带有小数点的实数至少在小数点两边各有一位。

.12  9.   4.E3   .2e-7 都是不合法的

2.5.3、Convertion

实数向整数转化:四舍五入到最近的整数,而不是截断。

当一个实数被赋值给整数时:进行隐士转化(implicit conversion)

四舍五入规则:away from zero

  • -1.5 转化为-2;1.5转化为2

2.6、Strings

字符串是一个字符序列,用(“ “)括起来,包含在一行中。字符串可以用作表达式的操作数;赋值时被当成无符号整数常数,一个8-bit的ASCII值对应一个字符。

2.6.1、String variable declaration

字符串变量是reg类型,宽度=字符个数*8

1
2
3
4
5
/********* "Hello world!"一共12个字符 ********/
reg [8*12:1] stringvar;
initial begin
stringvar = "Hello world!";
end

2.6.2、String manipulation

字符串可以用Verilog的操作符进行操纵。被操纵的值是8bit ASCII值序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module  string_test;
reg [8*14:1] stringvar;
initial begin
stringvar = "Hello world";
$display ("%s is stored as %h", stringvar,stringvar);
stringvar = {stringvar,"!!!"};
$display ("%s is stored as %h", stringvar,stringvar);
end
endmodule


/************** outputs ****************/
Hello world is stored as 00000048656c6c6f20776f726c64
Hello world!!! is stored as 48656c6c6f20776f726c64212121
  • 当变量占用空间大于所分配的空间时,值向右调整,最左边用0填充,与处理非字符串的值一样。
  • 当占用空间大于分配空间时,字符串还是向右调整,最左边的截断。

2.6.3 Special characters in strings

有些字符只有前面加上escape character它们才能在字符串里面使用

mark

2.7、Identifiers,keywords,and system names

标识符用于给一个对象独一无二的名字,使得它们能呗引用。

简单的标识符:字母,数字,$,  _组成。开头只能是字母或者下划线。(_bus, wan$li)

实现的时候标识符有最大长度,它的限制应该至少为1024个字符。如果一个标识符长度超过这个,系统应该报错。

2.7.1 Escaped identifiers

转义标识符以反斜杠\开始,以white space(space, tab,newline)结束。它们提供了在标识符中包含任何可打印字符的方法(33(!)-126(~);$21_h$-$7E_h$)。

前导反斜杠和结尾的空白字符都不算标识符的一部分,因此,\cpu3被认为和cpu3一样。

1
2
3
4
5
6
\busa+index
\-clock
\***error-condition***
\net1/\net2
\{a,b}
\a*(b+c)

2.7.2 Keywords

关键字是先前定义好的非转义标识符,它们被用来定义语言结构。关键字前面加上转义字符不被解释为关键字

mark

2.7.3 System tasks and functions❓

美元符号()开头的名字被解释为系统任务或者系统函数。

1
2
3
/*********** for example **********/
$display ("display a message");
$finish ;

2.7.4 Compiler directives

`(ASICC value 0x60)字符引导用于实现编译器指令的语言结构;,一个描述文件中的编译器指令可以控制多个描述文件中的编译行为。

`identifier 编译器指令结构在以下两种地方定义

  • 标准标识符编译器指令
  • 由软件实现定义的附加’标识符编译器指令。

任何有效的标识符,包括已经在除此构造之外的上下文中使用的关键字,都可以用作编译器指令名

1
2
/*********** for example **********/
`define wordsize 8

2.8、Attributes

随着使用Verilog HDL作为源代码的仿真器以外的工具的激增(proliferation); Verilog引入一种机制:用于指定关于HDL源代码中对象、语句和语句组的属性,这些属性可被各种工具(包括模拟器)使用,以控制工具的操作或行为。这些属性被称作attribute. 本小节将介绍: 可以用于指定属性的语法机制。

1
2
3
4
5
attribute_instance ::= (* attr_spec { , attr_spec } *)  
attr_spec ::=
attr_name [ = constant_expression ]
attr_name ::=
identifier

attribute_instance:1、作为声明,模块项目,语句或者端口连接的前缀。2、运算符或在一个表达式中Verilog函数名的后缀

如果没有给属性指派值,那么值默认为1;如果对相同的language element定义多个相同的属性名字,那么最后一个属性值将被使用;工具可以在这种情况下给个warning。

nesting of attribute instances 不被允许;用包含属性实例的常量表达式(constant expression that contains an attribute instance)去给属性赋值是不合法的。

2.8.1 Examples

  • 范例1:给case语句贴上属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    (* full_case, parallel_case *)
    case (foo)
    <rest_of_case_statement>

    or

    (* full_case=1 *)
    (* parallel_case=1 *) // Multiple attribute instances also OK
    case (foo)
    <rest_of_case_statement>

    or

    (* full_case, // no value assigned;默认为1
    parallel_case=1 *)
    case (foo)
    <rest_of_case_statement>
  • 范例2:给模块定义加属性

    1
    2
    (* optimize_power *)
    module mod1 (<port_list>);
  • 范例3:给模块实例加属性

    1
    2
    (* optimize_power=0 *)
    mod1 synth1 (<port_list>);
  • 范例4:给reg声明加属性

    1
    2
    3
    4
    (* fsm_state *)  reg  [7:0] state1;
    (* fsm_state=1 *) reg [3:0] state2, state3;
    reg [3:0] reg1; // this reg does NOT have fsm_state set
    (* fsm_state=0 *) reg [3:0] reg2; // nor does this one
  • 范例5:给操作符加属性

    1
    2
    a = b ? (* no_glitch *) c : d;
    a = b + (* mode = "cla" *) c;

    2.8.2 Syntax(省略)


本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!