在上节课中我们介绍了在Verilog 中,逻辑电路的入口及行为描述。语法规则非常简单,说穿了就是数字电路的文字描述。也就在数字电路中的单一电路都可以用这种方法进行描述。但是在数字电路设计中,复杂电路往往是由多个子电路或器件实现的,在Verilog中是如何对应的呢?
在Verilog 结构中可以通过例化的方式实现设计的层次结构。本节课程中我们将以1位全加器的设计,例化(instance), 然后在4位全加器中引用为例介绍如何通过这种方式,实现层次电路的设计。 例化的目的是为将已经完成的设计作为一个子设计或子模块使用,可以充分利用已设计的成果进行设计积累。
在verilog设计中,虽然有多个module存在,但只有一个module的端口负责整个设计架构的输入、输出。内部module端口如果有输入、输出通过例化后端口映射的方式与外部电路打交道。
在正式设计之前先介绍几个逻辑运算符。
- 与运算 “and”, “&”;
A and B, 或 A& B ;可以直接使用 “and “,也可以使用 “&” 符号
在多位运算中 & 是按对应位进行运算的。
- 或运算 “or” , “|”;
- 异或运算 “xor”, “^”;
- 非运算 !;
- 取反运算符 ~;
- 并位运算符 {}
也就是将多个位合并级联形成新的变量。如 a ,b 为单变量 ,y[1:0] 为向量
Assign y={a,b}; 结果为 y[0]=b, y[1]=a;
这里引用的运算符主要目的是帮助本节设计中用到的运算符的理解,详细内容请参照 verilog 运算符
1位全加器的设计:
输入: a, b ,ci; 其中 ci是进位输入
| 输入变量 | 输出变量 | |||
| a | b | ci | y | co |
| 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 1 | 1 |
根据真值表可以得到如下逻辑表达式:
y=a xor b xor c;
co=(~a&b & ci) | (a &~b& ci) | ( a & b&~ci) | ( a & b & ci) = ci & (a xor b) | (a & b);

一位全加器Verilog 描述。文件存储时,要以 .v为扩展名存储,如 fadder1.v,及存储的文件名要与 模块名(这里模块名为fadder1)一致。
module fadder1
(
input ci,
input a,
input b,
output y,
output co
);
assign y=a ^ b ^ ci;
assign co=ci&(a ^ b) | a&b;
endmodule
2.四位全加器的设计:
在一个新的文件中,四位全加器的verilog代码如下:
module fadder4
(
input ci,
input [3:0] a,
input [3:0] b,
output [3:0] y,
output co
);
wire co1,co2,co3;
// 例化 一位全加器,并重复使用4次
fadder1 fadder1_inst1
(
.ci (ci),
.a (a[0]),
.b (b[0]),
.y (y[0]),
.co (co1)
);
fadder1 fadder1_inst2
(
.ci (co1),
.a (a[1]),
.b (b[1]),
.y (y[1]),
.co (co2)
);
fadder1 fadder1_inst3
(
.ci (co2),
.a (a[2]),
.b (b[2]),
.y (y[2]),
.co (co3)
);
fadder1 fadder1_inst4
(
.ci (co3),
.a (a[3]),
.b (b[3]),
.y (y[3]),
.co (co) //可以将本级模块中定义的端口直接映射到下级模块中。而且可以使用同样的名称。
);
endmodule
模块例化的格式如下:
模块名 例化名
(
);
例化名可以随意命名,不一定要和模块名一致,但在使用时往往给比较有意义的名称,增加代码的可读性。
( …);包含端口映射;如在fadder1_inst4 中将 co3 与原1位全加器的ci相连,通过 .ci(co3)方式相关联,这种关联方式称为名称关联方式。也就时本设计模块与例化模块以名称的方式相关联。名称关联方式,在例化模块中的端口不要求按照例化模块的端口排列顺序进行。
fadder1 fadder1_inst4
(
.ci (c03),
.a (a[3]),
.b (b[3]),
.y (y[3]),
.co (co)
);
名称关联方式,在例化模块中的端口不要求按照例化模块的端口排列顺序进行。如:下面的例化用法和上面的例化效果是相同的。
fadder1 fadder1_inst4
(
.ci (c03),
.b (b[3]),
.a (a[3]),
.co (co),
.y (y[3])
);
还有一种例化方式是位置对应,如:
fadder1 fadder1_inst4
(
c03,
a[3],
b[3],
y[3],
co
);
引用时,严格按照模块定义的端口顺序来连接,不用标明原模块定义时规定的端口名。由于模块fadder1在定义时端口的顺序为ci,a,b,y,co 因此上面的位置对应的关系为,co3<–>ci, a[3]<–>a,b[3]<–>b, y[3]<–>y, co<–>co;
一般在情况下,以名称关联的方式使用最多。
对应视频:
学习本篇文章有几点收获,1、通过例化实现层次电路;2、只有一个module的端口负责整个设计架构的输入、输出;3、运算符(and[&],or[|],xor[^],!,~,{});4、例化名可以随意命名,但要有意义;5、端口映射方式包含名称关联方式与位置对应方式;
本篇文章借助一位和四位全加器,展示了如何实现模块内部的例化,进而实现层次电路的设计,文章内容主线明确,同时附带串讲了需要用到的相关知识点,很棒!
在学习中有一点疑问,向老师请教:
1、assign co=ci&(a xor b)+ a&b;这句语句中的”+“号是否应该换成符号”|“,更改为 assign co=ci&(a xor b)| (a&b)?
2、assign co=ci & (a xor b) + a & b;这句语句中的符号”&“可以替换为”and“吗?更改为 assign co =ci and(a xor b)+a and b;
你说的是对的,这里不应该用 + ,而是应该用 | 。
并且,注意一下,这里的XOR,AND等都是VHDL的语法,Verilog中应该使用 ^ , & ,文章已经修改,谢谢你的反馈。
谢谢老师!