立即学习>>梦翼师兄FPGA培训(视频加板卡),手把手带你入门FPGA
写在前面的话 我们所接触到的IO都是单纯的输入(input)或者输出(output)类型,而我们的一些总线协议如IIC等,要求信号为三态类型,也就是我们所说的输入输出(inout)类型。那么,本节梦翼师兄将和大家一起来探讨三态门的用法。 项目需求 设计一个三态门电路,可以实现数据的输出和总线“挂起”。 系统架构
模块功能介绍 模块名
| 功能描述
| three_state
| 控制三态总线Sda是否处于挂起状态
|
顶层模块端口描述 端口名
| 端口说明
| Clk
| 系统时钟
| Rst_n
| 系统低电平复位
| Data_buf
| 外部待传输数据输入
| Sda
| 三态数据总线
|
代码解释 三态门模块代码 /****************************************************
* Engineer : 梦翼师兄
* QQ : 761664056
* The module function:三态门模块
*****************************************************/
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<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行代码表示当定时器到达预定值,开关电平开始翻转。 三态门模块测试代码 /****************************************************
* Engineer : 梦翼师兄
* QQ : 761664056
* The module function:三态门测试模块
*****************************************************/
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行代码,模拟的是待传输数据的变化
由仿真波形可以看出,当开关关闭(flag==0),Sda总线放开,处于高阻状态,此时外部数据可以输入,相当于我们模块的输入。 当开关打开(flag==1),Sda等于data_buf的值,说明此时,Sda相当于我们模块的输出。
|