双向端口(inout)可以通过引脚复用来节省引脚。
在控制信号控制下,inout既可作为输入input也可作为输出output,因此对其仿真描述不当可能会引起仿真错误。当然,不只在testbench中,在程序中对inout口一般也是要做特殊处理的。
testbench:
`timescale 1ns / 1ps
// Company:
// Engineer:
//
// Create Date: 12:01:57 07/11/2017
// Design Name: work
// Module Name: C:/Users/gao/Desktop/isetest/work/testbench.v
// Project Name: work
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: work
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
module testbench;
// Inputs
reg clk;
reg rst;
// Outputs
wire inout_vld;
// Bidirs
wire [3:0] inout_data;
reg [3:0] data_in;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
rst = 0;
#7 rst = 1;
#16 rst = 0;
end
always @(posedge clk or posedge rst) begin
if (rst) begin
// reset
data_in <= 0;
end
else begin
data_in <= data_in + 1;
end
end
assign inout_data = inout_vld ? 4'bzzzz : data_in;
// Instantiate the Unit Under Test (UUT)
work uut (
.clk(clk),
.rst(rst),
.inout_data(inout_data),
.inout_vld(inout_vld)
);
endmodule
其中wire [3:0]inout_data用来连接inout口,inout_vld为模块输出,用以标志当前模块数据为输入(inout_vld == 0)还是输出(inout == 1)。
当为输出时(inout == 1),inout_data强制为16'bzzzz,此时与模块输出线与得到值为模块的输出值;当为输入时(inout == 0),inout_data连接寄存器,驱动模块端口。
在模块中的inout口做相似处理。
work:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 11:42:10 07/11/2017
// Design Name:
// Module Name: work
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module work(
clk
,rst
,inout_data
,inout_vld
);
input clk, rst;
inout [3:0]inout_data;
output inout_vld;
reg [3:0]counter;
always @(posedge clk or posedge rst) begin
if (rst) begin
// reset
counter <= 0;
end
else begin
counter <= counter + 1;
end
end
reg inout_vld; //0->in 1->out
always @(posedge clk or posedge rst) begin
if (rst) begin
// reset
inout_vld <= 0;
end
else if (counter == 4'b1111) begin
inout_vld <= !inout_vld;
end
else begin
inout_vld <= inout_vld;
end
end
reg [3:0]data_out;
always @(posedge clk or posedge rst) begin
if (rst) begin
// reset
data_out <= 4;
end
else begin
data_out <= data_out - 1;
end
end
assign inout_data = inout_vld ? data_out : 4'bzzzz;
endmodule
最后得到波形如下:
绿色为testbench中信号,橘黄色为模块信号。
可以看到在inout_vld == 0即输入时,模块的inout_data被外部接线驱动;在inout_vld == 1即输出时,模块的inout_data被内部寄存器data_out驱动,模块接线得到此时的值。