Verilog Inout双向数据传输接口设计及仿真

一般博客会这样介绍三态控制写法:

	inout 				sda_1,
	
	wire          		inout_control_1;
	wire				sda_in_1;
	wire	        	sda_out_1;
	assign sda_1 = (inout_control_1)?sda_out_1:1'bz;
	assign sda_in_1 = sda_1;

插叙:悬空和高阻的区别

高阻,即可以认为是没有输出,作为输出端口而言,对下级电路没有任何影响。悬空是针对输入端口来说的,也就是说没有接输入。这也就意味着,实际上高阻和悬空是一个状态,在HDL语言里都表示为Z。

这里不谈inout接口是什么,只描述设计和仿真文件的写法。

经验:
设计中,顶层再做三态控制 方便插逻辑分析仪 而且inout需要和inout进行握手 用wire和reg分别模拟输入输出行为方便 控制信号在顶层出现
具体就是在ad驱动小模块里露出输入输出接口和输出信号 分别使用 在顶层再三态控制

驱动模块:

	output  reg     inout_control,//
	input			sda_in,
	output	reg     sda_out,//data_inout 

顶层:

	assign sda_1 = (inout_control_1)?sda_out_1:1'bz;
	assign sda_in_1 = sda_1;

inout端口不能独立存在,连接到inout的另一个模块也应该是inout端口如前所述,inout 端口不能独立存在。为了进一步考虑,当一个模块的inout端口作为输出时,那么另一个模块的inout端口必须作为输入;

反之,当一个模块的inout口用作输入时,那么另一个模块的inout口一定是输出口。因此,两个inout端口的控制信号实际上是由一对信号控制的。(控制信号在仿真时也作为端口传递 比如用读写信号分别控制行为)

以下借鉴两篇博客:

通俗易懂的带你解读inout双向端口【Verilog高级教程】_verilog inout-CSDN博客

双向端口inout端口-CSDN博客

设计文件写法

data_inout是双向接口 对于输入和输出的行为,定义reg型变量data_out来描述输出结果,wire型变量data_in来观察输出结果(注意data_in的条件限制了!data_out_control),控制信号为1时,data_in为0.

module inout_def(clk,data_inout)
input clk;
inout data_inout;
reg data_out;
reg data_out_control;
//define data_out

//define data_out_control

//assign data_inout
assign data_inout=data_out_control?data_out:1'bz;

//assign data_in
wire data_in;
assign data_in=(!data_out_control)&data_inout;

endmodule

inout接口仿真

编写测试模块时,对于inout类型的端口,需要定义成wire型变量

当上面的例子中的data_inout用作输入时,需要赋值给data_inout,其余情况可以断开。此时可以用assign语句实现:

assign data_inout = link ? data_in_t : 1'bz;

其中的link,data_in_t是reg型变量,在tb文件中赋值(可以是自己在仿真之中实现)。另外,可以设置一个输出端口观察data_inout用作输出的情况:

经测试有一些问题,修改如下:

  1. 数据位宽不为1位时,比如8bit,也要相应写成8’bz

  2. assign data_in=(!data_out_control)&data_inout;这个写法只适用于1bit情况(这个输出的相当于是一个逻辑值而不是data_inout向量 只会是1bit),用以下代码:

    assign w_data_in= (!i_data_out_control) ? io_data_inout : 8'bz;//有问题 只出现0 1 0 1
    

仿真中对输出信号进行观察的写法:

wire data_out_t;
assign data_out_t = (!link) ? data_inout : 1'bz;

需要注意的是:当给data_inout赋值的时候(它作输入端口时),只能在原INOUT数据为高阻态时才可以赋值,所以link信号即该INOUT数据为高阻态时的控制信号,也就是说

link = !data_out_control;

仿真的三态门控制信号和设计文件相反。因为仿真时,需要对inout进行赋值的时候是产生激励的时候,对reg型赋值,对应设计文件中的(data_out也相应赋值成reg类型)

不需要测试文件给data_inout数据赋值的时候,测试文件的data_inout接口因为高阻态,从而不影响源文件data_inout接口的其它操作。

自己写的版本:

src

module inout_interface(
input                   i_clk                ,
input                   i_rst              ,
input                   i_data_out_control   ,
inout      [7:0]        io_data_inout
);


//define data_out
reg [7:0] r_data_out;
//define i_data_out_control

always @(posedge i_clk or posedge i_rst)
if (i_rst)
    begin
        r_data_out <= 0;
    end
else if(i_data_out_control)
    begin
        r_data_out <= r_data_out + 1;
    end
else
    r_data_out <= r_data_out;

//assign io_data_inout

assign io_data_inout = i_data_out_control ? r_data_out : 8'bz; 

//assign data_in
wire [7:0] w_data_in;
// assign data_in= (!i_data_out_control) & io_data_inout ;//有问题 只出现0 1 0 1
assign w_data_in= (!i_data_out_control) ? io_data_inout : 8'bz;//有问题 只出现0 1 0 1
endmodule

tb

`timescale 1ns / 1ps
`define P_CLK_PERIOD 10 //100Mhz SYS_CLK
module tb_inout_interface();

reg                  r_clk;
reg                  r_rst;
reg                  r_link;
wire     [7:0]       w_data_inout;
reg      [7:0]       r_data_in_t;
wire     [7:0]       w_data_out_t;


inout_interface inout_interface_inst0(
.i_clk                  (r_clk)             ,
.i_rst                  (r_rst)             ,
.i_data_out_control     (!r_link)           ,
.io_data_inout          (w_data_inout)
);

assign w_data_inout = r_link ? r_data_in_t : 8'bz;     //写
assign w_data_out_t = (!r_link) ? w_data_inout : 8'bz; //读

initial
r_clk = 1;
always #(`P_CLK_PERIOD/2) r_clk = ~r_clk;

initial
begin
    r_rst = 1;
    r_link = 0;
    #20;
    r_rst = 0;
    #200;
    r_link = 1;
    #2000;
    r_link = 0;
    #2000;
    $stop;
end

always @(posedge r_clk or posedge r_rst)
if (r_rst)
    begin
        r_data_in_t <= 0;
    end
else if(r_link)
    begin
        r_data_in_t <= r_data_in_t + 1;
    end
else
    begin
        r_data_in_t <= r_data_in_t;
    end

endmodule

读信号拉高时(即这里的i_data_out_control为低,r_link为高时) inout端口作输入用 读取sim的激励信号r_data_in_t

在这里插入图片描述

写信号拉高(即这里的i_data_out_control为高,r_link为低时) inout端口作输出用 此时用于将设计文件中的输出量r_data_out输出

在这里插入图片描述

读信号有效时,w_data_out_t为z,但对应设计文件的输出还是有一个值(20),但对于w_data_out_t我们把它写死

assign w_data_out_t = (!r_link) ? w_data_inout : 8'bz; //观察输出

同理写信号有效时的r_data_in有值,但是设计文件中观察到的是8’bz,注意这个z必须要对应他们正确的位宽,是8位就是8’bz.

assign w_data_in= (!i_data_out_control) ? io_data_inout : 8'bz;
  • 29
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值