Verilog学习:门级建模与开关建模
Verilog学习:门级建模与开关建模
Verilog学习——门/开关建模
一、门级建模
门级建模涉及门,并且硬件原理图和Verilog代码之间具有一对一的关系。Verilog支持一些被称为原语的基本逻辑门,可以像模块一样实例化,因为它们已经预定义了。
1. AND/OR/XOR门
这些原语的参数列表中的第一个终端是输出,每当任何输入更改时,它就会更新。
2. NAND/NOR/XNOR门
这些门可以有两个或两个以上的输入。
3. BUF/NOT门
这些门只有一个标量输入和一个或多个输出。端口列表总最后一个端口是input;
BUF 代表缓冲器,只需将值从输入传输到输出,而不会改变极性。
NOT 代表逆变器,在其输入端反转信号的极性。因此,输入端的 0 将产生 1,反之亦然。
4. BUFIF/NOTIF
缓冲器和逆变器具有额外的控制信号,以使能输出,可通过 BUFIF 和 NOTIF 基元使用
只有当控制信号使能时,这些门才具有有效的输出,否则输出将处于高阻抗状态。
二、Verilog的门延迟
数字元件是二进制实体,只能包含两个值中的任何一个:0或1;从0-1或从1-0的转换过程有一个延迟。门元件中将值从输入传到输出也有延迟。
1. 上升、下降和关闭延迟
有三种方法表示门级延迟:
// 单一延迟指定 - 用于所有三种类型的转换延迟
or #(<delay>) o1 (out, a, b);
// 两个延迟指定 - 用于上升和下降转换
or #(<rise>, <fall>) o1 (out, a, b);
// 三种延迟指定 - 用于上升、下降和关断转换
or #(<rise>, <fall>, <turn_off>) o1 (out, a, b);
2. 延迟规范格式
3. 最小/典型/最大延迟
每个数字门和晶体管单元都具有基于工艺节点指定的最小、典型和最大延迟,通常由制造代工厂的库提供。对于每种类型的延迟(上升、下降和关断),可以指定三个值 min、typ 和 max,分别代表最小、典型和最大延迟。
module des ( input a, b,
output out1, out2);
and #(2:3:4, 3:4:5) o1 (out1, a, b);
bufif0 #(5:6:7, 6:7:8, 7:8:9) b1 (out2, a, b);
endmodule
三、开关建模
- NMOS/PMOS
module des (input d, ctrl,
output outn, outp);
nmos (outn, d, ctrl);
pmos (outp, d, ctrl);
endmodule
- CMOS 开关
module des (input d, nctrl, pctrl,
output out);
cmos (out, d, nctrl, pctrl);
endmodule
- 双向开关
Tran:
module des (input io1, ctrl,
output io2);
tran (io1, io2);
endmodule
$monitor ("T=%0t io1=%0b ctrl=%0b io2=%0b", $time, io1, ctrl, io2);
T=0 io1=0 ctrl=0 io2=0
T=10 io1=1 ctrl=0 io2=1
T=20 io1=1 ctrl=1 io2=1
T=30 io1=1 ctrl=0 io2=1
T=40 io1=0 ctrl=0 io2=0
Tranif0:
module des (input io1, ctrl,
output io2);
tranif0 (io1, io2, ctrl);
endmodule
T=0 io1=0 ctrl=0 io2=0
T=10 io1=1 ctrl=0 io2=1
T=20 io1=1 ctrl=1 io2=z
T=30 io1=1 ctrl=0 io2=1
T=40 io1=0 ctrl=0 io2=0
Tranif1
module des (input io1, ctrl,
output io2);
tranif1 (io1, io2, ctrl);
endmodule
T=0 io1=0 ctrl=0 io2=z
T=10 io1=1 ctrl=0 io2=z
T=20 io1=1 ctrl=1 io2=1
T=30 io1=1 ctrl=0 io2=z
T=40 io1=0 ctrl=0 io2=z
- 电源和接地
module des (output vdd,
output gnd);
supply1 _vdd;
supply0 _gnd;
assign vdd = _vdd;
assign gnd = _gnd;
endmodule
module tb;
wire vdd, gnd;
des u0 (.vdd(vdd), .gnd(gnd));
initial begin
#10;
$display ("T=%0t vdd=%0d gnd=%0d", $time, vdd, gnd);
end
endmodule
T=10 vdd=1 gnd=0
四、Verilog用户定义的原语
标准的Verilog的原语,可能并不能容易的或并不足以表示复杂的逻辑。称为UDP的、或自定义的原语能够对组合逻辑或顺序逻辑建模。所有的UDP只有一个输出,可以是0、1、x。但不能是z,任何值为z的输入都将被视为x。
1. Verilog UDP符号
Verilog自定义原语可以与module定义相同的级别,但不能在endmodule和module之间。可以有多个输入端口,但始终只有一个输出端口,双向端口无效。所有的端口信号都必须是标量,即必须是1位宽。硬件行为被描述为一个原始状态表,在table和endtable之间列出了不同的可能输入组合及其相应的输出。输入和输出信号的值可以使用以下符号表示。
2. 组合UDP
输出应始终在端口列表的第一位;
primitive mux (out, sel, a, b);
output out;
input sel, a, b;
table
// sel a b out
0 1 ? : 1;
0 0 ? : 0;
1 ? 0 : 0;
1 ? 1 : 1;
x 0 0 : 0;
x 1 1 : 1;
endtable
endprimitive
- 顺序UDP
输出端口应在 UDP 定义中声明为 reg 类型,并且可以选择在 initial 语句中初始化。顺序 UDP 在输入和输出字段之间有一个附加字段,该字段由表示当前状态的:分割;
① Level-sensitive UDP
primitive d_latch (q, clk, d);
output q;
input clk, d;
reg q;
table
// clk d q q+
1 1 : ? : 1;
1 0 : ? : 0;
0 ? : ? : -;
endtable
endprimitive
② Edge-sensitive UDP
primitive d_flop (q, clk, d);
output q;
input clk, d;
reg q;
table
// clk d q q+
// obtain output on rising edge of clk
(01) 0 : ? : 0;
(01) 1 : ? : 1;
(0?) 1 : 1 : 1;
(0?) 0 : 0 : 0;
// ignore negative edge of clk
(?0) ? : ? : -;
// ignore data changes on steady clk
? (??): ? : -;
endtable
endprimitive
时钟的上升沿由 01 或 0? 指定。