双向端口(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驱动,模块接线得到此时的值。