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