我们所接触到的IO都是单纯的输入(input)或者输出(output)类型,而我们的一些总线协议如IIC等,要求信号为三态类型,也就是我们所说的输入输出(inout)类型。那么,本节大家一起来探讨三态门的用法。
项目需求
设计一个三态门电路,可以实现数据的输出和总线“挂起”。
系统架构
http://s12/mw690/003wCLthzy7agq0WkYPfb&690
三态门系统架构图
模块功能介绍
表模块功能描述表
模块名
|
功能描述
|
three_state
|
控制三态总线sda是否处于挂起状态
|
顶层模块端口描述
表 顶层模块端口描述表
端口名
|
端口说明
|
clk
|
系统时钟
|
rst_n
|
系统低电平复位
|
data_buf
|
外部待传输数据输入
|
sda
|
三态数据总线
|
代码解释
1.三态门模块代码
00
module
three_state(
01
//系统输入
02
clk,//系统50M输入
03
rst_n,//低电平复位信号
04
data_buf,
05
//系统输出
06
sda//三态总线
07
);
08
//-------------------系统输入-------------------
09
input
clk;//系统50M输入
10
input
rst_n;//低电平复位信号
11
input
data_buf;//待传输数据
12
//-------------------系统输出-------------------
13
inout
sda;//三态总线
14
//------------------寄存器定义------------------
15
reg
flag;//三态门开关定义
16
reg
[10:0]counter;//计数器定义
17
//------------------三态门赋值------------------
18
assign
sda=(flag==1)?data_buf:1'bz;
19
//----------------开关控制计数器----------------
20
always@(posedge
clk or negedge
rst_n)
21
begin
22
if(!rst_n)
23
begin
24
counter<=0;//计数器复位
25
end
26
else
27
begin
28
if(counter<</span>25)//计数器范围
29
counter<=counter+1;//计数器累加
30
else
31
counter<=0;//计数器清零
32
end
33
end
34
//----------------开关/数据控制-----------------
35
always@(posedge
clk or negedge
rst_n)
36
begin
37
if(!rst_n)
38
begin
39
flag<=0;//开关关闭
40
end
41
else
42
begin
43
if(counter==25)
44
flag<=~flag;//开关信号翻转
45
end
46
end
47
endmodule
|
第18行代码就是三态门的赋值方式,三态门什么时候作为输出、什么时候作为输入是由开关信号flag控制的。当开关信号flag==1,sda的值等于待发送的数据data_buf(此时,sda相当于是output类型),当开关信号flag==0,sda的值变成高阻态(此时,sda相当于是input类型)。
20~33行代码为我们设计的一个定时器,用来控制开关信号的翻转。
43~44行代码表示当定时器到达预定值,开关电平开始翻转。
2.三态门模块测试代码
00
`timescale
1ns/1ns
01
module tb;
02
//-------------------系统输入-------------------
03
reg
clk;//系统50M输入
04
reg
rst_n;//低电平复位信号
05
reg
data_buf;//待传输数据
06
//-------------------系统输出-------------------
07
wire
sda;//三态总线
08
//-------------------测试激励-------------------
09
initial
10
begin
11
clk=0;//时钟赋初值
12
rst_n=0;//系统上电复位
13
data_buf=0;//data_buf赋初值
14
#1000
rst_n=1;//复位结束
15
#1000
data_buf=1;
16
#1000
data_buf=0;
17
#1000
data_buf=1;
18
#1000
data_buf=0;
19
end
20
21
always #10
clk=~clk;//产生50MHZ时钟
22
//-------------------模块实例化-------------------
23 three_state
three_state(
24
//系统输入
25
.clk(clk),//系统50M输入
26
.rst_n(rst_n),//低电平复位信号
27
.data_buf(data_buf),
28
//系统输出
29
.sda(sda)//三态总线
30
);
31
endmodule
|
14~18行代码,模拟的是待传输数据的变化。
仿真结果分析
http://s5/mw690/003wCLthzy7agq4gslu24&690
三态门仿真结果
由仿真波形可以看出,当开关关闭(flag==0),sda总线放开,处于高阻状态,此时外部数据可以输入,相当于我们模块的输入。
当开关打开(flag==1),sda等于data_buf的值,说明此时,sda相当于我们模块的输出。
加载中,请稍候......