[color=darkred][size=medium]三态缓冲器也称三态门,其典型应用是双向端口,常用于双向数据总线的构建。
在Verilog HDL中,inout型双向端口信号不能被定义成reg型变量,因此在always块内不能被直接赋值使用。
由于现在FPGA设计和外部存储器或CPU数据交换的频繁运用,以及引脚资源有限,使用双向端口设计可以成倍地节省数据引脚线,所以利用Verilog HDL实现双向端口至关重要。在设计双向端口时应注意亮点:其一,要用三态门的控制来处理实现双向端口;其二,要分别指定双向端口作为输出口和输入口时,对外部对象的数据操作。[/size][/color]
下面是一个双向端口的Verilog HDL实例:
[color=red][size=small]注意:z为三态门选通信号,当z=1时,把三态门置为高阻态,这时dinout作为输入口;当z=0时,开通三态门,dinout作为输出端口。[/size][/color]
[color=darkred][size=medium]双向端口的仿真:
编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其他输入端口都定义成reg类型,这两者是有区别的。此外,对于双向端口本身,仿真其输出端口和输入端口的语法是不同的。[/size][/color]
[color=red][size=medium](1)输出端口特性仿真:当双向端口作为输出口时,不需要对其进行初始化,只要开通三态门即可。[/size][/color]
仿真图为:
[img]http://dl.iteye.com/upload/attachment/375098/643f8c2b-2ff9-312e-9226-5302b13d1595.bmp[/img]
[color=red][size=medium](2)输入端口特性仿真:当双向端口dinout作为输入口时,需要对它进行初始化赋值并关闭三态门。而如果把它跟一般的输入口一样直接进行初始化赋值,则会出错,这是因为在定义它的时候是wire型的数据变量,而不是reg型数据变量。因此,这里需要用到force命令,以强制给dinout赋值。[/size][/color]
不知道为何生不成仿真图,哥就是个杯具。。。
今晚P大又要搞镜湖之夜,哥看着喧闹的人群,却突然觉得好孤单啊~~
在Verilog HDL中,inout型双向端口信号不能被定义成reg型变量,因此在always块内不能被直接赋值使用。
由于现在FPGA设计和外部存储器或CPU数据交换的频繁运用,以及引脚资源有限,使用双向端口设计可以成倍地节省数据引脚线,所以利用Verilog HDL实现双向端口至关重要。在设计双向端口时应注意亮点:其一,要用三态门的控制来处理实现双向端口;其二,要分别指定双向端口作为输出口和输入口时,对外部对象的数据操作。[/size][/color]
下面是一个双向端口的Verilog HDL实例:
module InOut(din, clk, z, dout, dinout);
input [7:0] din;
input clk;
input z;
output [7:0] dout;
inout [7:0] dinout;
reg [7:0] dout, din_reg;
assign dinout = din_reg;
always @(posedge clk) begin
if(!z)
din_reg <= din; // inout型双向端口信号不能被定义成reg型变量,因此在always块内不能被直接赋值使用
else
dout <= dinout;
end
endmodule
[color=red][size=small]注意:z为三态门选通信号,当z=1时,把三态门置为高阻态,这时dinout作为输入口;当z=0时,开通三态门,dinout作为输出端口。[/size][/color]
[color=darkred][size=medium]双向端口的仿真:
编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其他输入端口都定义成reg类型,这两者是有区别的。此外,对于双向端口本身,仿真其输出端口和输入端口的语法是不同的。[/size][/color]
[color=red][size=medium](1)输出端口特性仿真:当双向端口作为输出口时,不需要对其进行初始化,只要开通三态门即可。[/size][/color]
`timescale 1ns/1ps
module tb_InOut;
reg [7:0] din;
reg z;
reg clk;
wire [7:0] dout;
wire [7:0] dinout;
integer i;
InOut uut(
.din(din),
.z(z),
.clk(clk),
.dout(dout),
.dinout(dinout)
);
always #5 clk = ~clk;
initial begin
din = 0;
z = 0;
clk = 0;
#100 din = 10;
for(i=0; i<10; i=i+1)
#10 din = din + 1;
end
endmodule
仿真图为:
[img]http://dl.iteye.com/upload/attachment/375098/643f8c2b-2ff9-312e-9226-5302b13d1595.bmp[/img]
[color=red][size=medium](2)输入端口特性仿真:当双向端口dinout作为输入口时,需要对它进行初始化赋值并关闭三态门。而如果把它跟一般的输入口一样直接进行初始化赋值,则会出错,这是因为在定义它的时候是wire型的数据变量,而不是reg型数据变量。因此,这里需要用到force命令,以强制给dinout赋值。[/size][/color]
`timescale 1ns/1ps
module tb_InOut_in;
reg [7:0] din;
reg z;
reg clk;
wire [7:0] dout;
wire [7:0] dinout;
integer i;
InOut uut(
.din(din),
.z(z),
.clk(clk),
.dout(dout),
.dinout(dinout)
);
always #5 clk = ~clk;
initial begin
z = 1;
clk = 0;
force dinout = 20;
#100;
for(i=0; i<10; i=i+1)
#10 force dinout = dinout - 1;
end
endmodule
不知道为何生不成仿真图,哥就是个杯具。。。
今晚P大又要搞镜湖之夜,哥看着喧闹的人群,却突然觉得好孤单啊~~