相关阅读
Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482
Verilog中的端口定义有两种风格,一种是Verilog Standard 1995风格,一种是Verilog Standard 2001风格,本文将对Verilog Standard 1995风格进行详细阐述。
图1 模块定义的BNF范式
从上图可以看出,module_declaration有两种形式,由符号|分隔:前一种使用list_of_ports形式的是Verilog Standard 1995风格;后一种使用list_of_port_declarations形式的是Verilog Standard 2001风格,这是一种ANSI C风格的形式。
图2将图1中与端口定义有关的语法单独列出来了。
图2 端口定义的BNF范式
下面将对Verilog Standard 1995风格端口定义的格式进行逐步分析。
list_of_ports
list_of_ports是用小括号包围的一个或多个port(如有多个,用逗号分隔)。
port是一个可选的port_expression或者是.port_identifier加上可选的port_expression(这有些奇怪,一般这个形式是在模块例化时用于命令端口连接的,但事实上,他也可以在模块端口定义时使用)。
port_expression是一个port_reference或port_expression的拼接(使用拼接运算符{})。
而最底层的port_reference,其实就是一个port_identifier,如果其为一个向量,还可以使用向量的常量位选或常量域选(见图中的constant_range_expression)。
下面列出了一些合法的list_of_ports,但其实只有第一种情况是最常用的(说实话,在看标准前,我没遇见过其他情况)。
module test1(a, b, c, d); // most common used
module test2(a, , b, c, d);
module test3(a[1:0], {b, c}, a[2], d);
module test4(.aa(a[1:0]), .bb({b, c}), .cc(a[2]), d, .ee());
上面的test4模块中,使用了一种特殊的port形式,即.port_identifier加上可选的port_expression,可以将其称呼为显式端口。而一般情况下的port_expression,可以将其称呼为隐式端口。
使用显式端口的目的,是为了方便进行命名端口连接,我们首先来隐式端口的命名端口连接。
test1 test1_i(.a(a1), .b(b1), .c(c1), .d(d1))
这很自然,因为a, b, c, d是简单标识符,但如果出现port_expression不是一个简单的标识符的情况,这时应该如何命名端口连接呢?下面的形式合法吗?
test3 test3_i(.a[1:0](a1), .{b, c}(b1), .a[2](c1), .d(d1)); // error
很不幸,这是不合法的,至少对于前三个端口,这是不合法的。那我是否能前三个端口使用位置端口连接,最后一个端口使用命名端口连接呢?这也是不合法的,因为不能混合使用命名端口连接和位置端口连接。
test3 test3_i(a1, b1, c1, .d(d1)); // error
可以解决这个问题,如果使用了显式端口,则可以使用port_identifier作为命名端口连接的替换,如下所示。
test4 test4_i(.aa(aa1), .bb(bb1), .cc(cc1), .d(d1), .ee(ee1)); // no error
以上,我们已经学习了端口列表相关的内容,但其实我们还未描述端口的详细信息:输入or输出or双向?向量or标量?有符号or无符号?类型?这些由模块体中的port_declaration完成。也就是说,如果使用了Verilog Standard 1995风格,则模块体中必须存在相应的port_declaration。
port_declaration
有三个类型的port declaration:输入端口声明、输出端口声明和双向端口声明,它们的BNF范式如图3所示。
图3 端口声明的BNF范式
port declaration用于描述port_expression中的port_identifier的详细信息(注意,显式声明.port_identifier中的port_identifier并不需要声明,它只是为了方便命名连接而存在的)。
从图3中我们可以看出,输入端口和输出端口有可选的net_type,这是因为输入端口的连接就像是一个assign连续赋值,作为等号左边的信号自然得是net大类(图4所示),其中wire类型最常用。
图4 net大类
输出端口则没有这些限制,所以它可以是net大类,也可以是variable大类中的reg,integer和time类型。
即使在port declaration时,可以用net_type,reg,signed,range,描述一个信号的信息,但仍然可以使用net declaration或variable declaration对其再次进行声明(可以用于补充更多信息,但需注意如果是向量,则位宽需要一致),后面我们统称为additional declaration。如果在port declaration时,指定了net_type,reg,integer或time,则这个端口声明视为一个对信号的完整描述,则不可以再使用additional declaration对其再次进行声明。
module test1(a, b, c, d);
// port declaration
output signed [2:0]a;
output b;
input wire [2:0]c; // unable to use additional declaration
input [2:0]d;
// additional declaration
reg [2:0]a;
wire signed b;
// wire [1:0]d; error
.....
endmodule
注意:如果在port declaration时一个信号不存在类型信息,且其没有使用additional declaration补充说明其类型,则其默认为wire类型,如上例中的信号d。一个信号如果在port declaration或additional declaration中的任意一个指定了signed,则其为有符号,否则为无符号。
根据这个规则,信号a是输出的,reg类型的,有符号的3位向量信号;信号b是输出的,wire类型的,有符号的标量信号;信号c是输入的,wire类型的,无符号的3位向量信号;信号d是输入的,wire类型的,无符号的3位向量信号。
标签:1995,端口,Verilog,declaration,net,expression,port From: https://blog.csdn.net/weixin_45791458/article/details/141254289