进阶项目(3)UART串口通信程序设计讲解

写在前面的话

UART串行接口简称串口,是我们各类芯片最常用的一种异步通信接口,通过串口我们就可以建立起计算机和我们实验板之间的通信和控制关系,也就是我们通常所说的上下位机通信。串口可以说是不同平台互相通信、控制的一个最基本的接口。

项目需求

设计一个UART控制器,当控制器从上位机接收到数据以后,马上将数据输出,发送回上位机,完成“回环测试”。

 UART的原理分析

要实现UART通信,首先我们需要用到一个外部的电平转换芯片MAX232,其具体配置电路如下:

注解:

MAX232芯片是美信(MAXIM)公司专为RS_232标准串口设计的单电源电平转换芯片,使用+5V单电源供电

主要特点:

符合所有的RS_232技术标准

只需要单一+5V电源供电

片载电荷泵具有升压、电源极性翻转能力,能够产生+10V和-10V电压

功耗低,典型供电电流5MA

内部集成2个RS_232驱动器

高集成度,片外最低只需四个电容即可工作

由原理图可以看出,最终我们FPGA需要控制的其实也就是两条信号线:

RXD和TXD,分别为数据接收线和数据发送线。

那么接下来,问题就变得简单了,既然只有两条线,那么我们只需要关注其数据收发时序即可,时序图如下:

UART数据格式:

说明:在此实验中,无奇偶校验位,则一帧数据为十位。(奇偶校验是一种校验代码传输正确性的方法。根据被传输的一组二进制代码的数位中“1”的个数是奇数或偶数来进行校验。采用奇数的称为奇校验,反之,称为偶校验。采用何种校验是事先规定好的。通常专门设置一个奇偶校验位,用它使这组代码中“1”的个数为奇数或偶数。若用奇校验,则当接收端收到这组代码时,校验“1”的个数是否为奇数,从而确定传输代码的正确性。)

在UART接收时,采集一帧数据的中间8位有效位,忽略开始位与停止位;在UART发送时,将发送的并行8位数据转为串行数据,并添加开始位与停止位。

UART中的一帧数据为10位,空闲时均为高电平,在检测到开始位(低电平)之后,开始采集8位有效数据位(低位在前),再将停止位置为高电平即可。

通过前面的学习,我们已经了解了UART的数据格式,那么,传输速率如何控制呢?这就涉及到了一个波特率的概念:

波特率是衡量数据传输速率的指针。表示为每秒钟传送的二进制位数(bit),例如资料传送速率为120字符/秒,而每一个字符为10位,则其传送的波特率为10*120=1200波特(bit)。此实验中设置波特率为9600bit/s。

系统架构

模块功能说明:bps_rx模块为串口接收数据的速率控制模块,当使能信号rx_en为高电平时,bps_rx模块内部计数器开始计数,按照设定好的波特率,输出控制数据采集的尖峰脉冲信号rx_sel_data和有效数据位的计数值rx_num。

模块功能说明:uart_rx为串口串行数据的接收模块,数据从端口rs232_rx输入,在采集控制信号rx_sel_data和有效位计数器rx_num的控制下,进行串并转换,从端口rx_d[7:0]输出。tx_en为发送控制模块的使能信号,当Uart_rx模块接收数据完毕以后,置高信号tx_en启动数据发送,将采集到的数据rx_d[7:0]发送到上位机。

模块功能说明:bps_tx模块为串口发送数据的速率控制模块,当使能信号tx_en为高电平时,bps_tx模块内部计数器开始计数,按照设定好的波特率,输出控制数据发送的尖峰脉冲信号tx_sel_data和有效数据位的计数值tx_num。

模块功能说明:uart_tx为串口串行数据的发送模块,并行数据从端口rx_d[7:0]输入,在采集控制信号tx_sel_data和有效位计数器tx_num的控制下,进行并串转换,从端口rs232_tx输出。

模块功能介绍


模块名


功能描述


bps_rx


控制串口接收数据的速率


uart_rx


接收串口串行数据


bps_tx


控制串口发送数据的速率


uart_tx


发送串口串行数据


uart


顶层连接

端口和内部连线描述

顶层模块端口介绍


端口名


端口说明


clk


系统时钟输入


rst_n


系统复位


rs232_tx


数据输出端口


rs232_rx


数据输入端口

内部连线


连线名


连线说明


rx_en


bps_rx开始计数的使能信号


rx_sel_data


控制数据采集的尖峰脉冲信号


rx_num


接收有效数据位的计数值


rx_d


接收到的数据


tx_en


发送控制模块的使能信号


tx_sel_data


控制数据发送的尖峰脉冲信号


tx_num


发送有效数据位的计数值

代码解释

数据接收模块波特率生成


/****************************************************

*   Engineer      :   梦翼师兄

*   QQ             :   761664056

*   The module function:控制串口接收数据的速率

*****************************************************/

00 module bps_rx(

01 clk,   //系统时钟50MHz

02 rst_n, //低电平复位

03 rx_en,    //使能信号:串口接收或发送开始

04 rx_sel_data,  //波特率计数的中心点(采集数据的使能信号)

05 rx_num   //一帧数据0-9

06 );

07 //模块输入

08 input    clk;   //系统时钟50MHz

09 input    rst_n; //低电平复位

10 input   rx_en;    //使能信号:串口接收开始

11 //模块输出

12 output reg   rx_sel_data;  //波特率计数的中心点(采集数据的使能信号)

13 output reg [3:0] rx_num;   //一帧数据0-9

14 //设置参数

15 parameter bps_div   = 13‘d5207,

16   bps_div_2 = 13‘d2603;

17

18 //接收标志位:接收到使能信号rx_en后,将标志位flag拉高,当信号rx_num计完一帧数据后拉低

19 reg       flag;

20 always@(posedge clk or negedge rst_n)

21 if(!rst_n)

22 flag <= 0;

23 else if(rx_en)

24 flag <= 1;

25 else if(rx_num == 4‘d10)

26 flag <= 0;

27

28 //波特率计数

29 reg [12:0] cnt;

30 always@(posedge clk or negedge rst_n)

31 if(!rst_n)

32 cnt  <= 13‘d0;

33   else if(flag && cnt < bps_div)

34 cnt <= cnt + 1‘b1;

35   else

36 cnt <= 13‘d0;

37

38 //规定接收数据的范围:即一帧数据(10位:1位开始位,8位数据位,1位结束位)

39 always@(posedge clk or negedge rst_n)

40 if(!rst_n)

41 rx_num <= 4‘d0;

42 else if(rx_sel_data && flag)

43 rx_num <= rx_num + 1‘b1;

44 else if(rx_num == 4‘d10)

45 rx_num <= 1‘d0;

46

47 //数据在波特率的中间部分采集:即接收数据的使能信号

48 always@(posedge clk or negedge rst_n)

49 if(!rst_n)

50 rx_sel_data <= 1‘b0;

51 else if(cnt == bps_div_2)//中间取数是为了产生尖峰脉冲,尖峰脉冲为采集数据的使能信号,用来把握速率

52 rx_sel_data <= 1‘b1;

53 else

54 rx_sel_data <= 1‘b0;

55

56 endmodule

本模块20~26行负责控制flag的值,flag为高电平代表一帧数据正在传输。29~36行为波特率计数器,当flag有效时计数器开始计数。48~54行负责在波特率计数值的中间部位生成尖峰脉冲rx_sel_data,两个尖峰脉冲之间的间隔为5207个系统时钟周期,满足9600bps波特率。39~45在尖峰脉冲作用下接收数据计数器开始标定有效帧比特位。

数据接收模块


/****************************************************

*   Engineer      :   梦翼师兄

*   QQ             :   761664056

*   The module function:接收串口串行数据

*****************************************************/

00  module uart_rx(

01                  clk,            //50MHZ时钟

02                  rst_n,          //低电平复位

03                  rs232_rx,      //输入串行数据

04                  rx_num,        //一帧数据控制位

05                  rx_sel_data,  //波特率计数的中心点(采集数据的使能信号)

06                  rx_en,         //使能信号:启动接收波特率计数

07                  tx_en,    //使能信号:在接收完数据后,开始启动发送数据模块

08                  rx_d      //将采集数据的有效8位串行数据转化为并行数据

09                );

10      //模块输入

11      input            clk;         //50MHZ时钟

12      input            rst_n;       //低电平复位

13      input            rs232_rx;   //输入串行数据

14      input [3:0]      rx_num;    //一帧数据控制位

15      input            rx_sel_data; //波特率计数的中心点(采集数据的使能信号)

16      //模块输出

17      output          rx_en;  //使能信号:启动接收波特率计数

18      output reg      tx_en;  //使能信号:在接收完数据后,开始启动发送数据模块

19      output reg [7:0] rx_d; //将采集数据的有效8位串行数据转化为并行数据

20  //检测低电平(开始位)

21  reg in_1,in_2;

22  always@(posedge clk or negedge rst_n)

23      if(!rst_n)

24          begin

25              in_1 <= 1‘b1;

26              in_2 <= 1‘b1;

27          end

28      else

29          begin

30              in_1 <= rs232_rx;

31              in_2 <= in_1;

32          end

33

34  assign  rx_en = in_2 &(~in_1); //当检测由高变低的过程后,使能信号拉高

35

36  //确保在一帧数据的中间8位进行数据的读取,读取完成后,使能信号tx_en控制串口发送模块

37  reg [7:0] rx_d_r;

38  always@(posedge clk or negedge rst_n)

39      if(!rst_n)

40          begin

41              rx_d_r <= 8‘d0;

42              rx_d  <= 8‘d0;

43          end

44      else if(rx_sel_data)

45          case(rx_num)

46              0:;                     //忽略开始位

47              1: rx_d_r[0] <= rs232_rx;//采集中间8位有效数据

48              2: rx_d_r[1] <= rs232_rx;

49              3: rx_d_r[2] <= rs232_rx;

50              4: rx_d_r[3] <= rs232_rx;

51              5: rx_d_r[4] <= rs232_rx;

52              6: rx_d_r[5] <= rs232_rx;

53              7: rx_d_r[6] <= rs232_rx;

54              8: rx_d_r[7] <= rs232_rx;

55              9: rx_d  <= rx_d_r;      //锁存采集的8位有效位(忽略停止位)

56              default:;

57          endcase

58  //使能信号:在完成接收以后立即拉高tx_en(启动发送模块)

59  always@(posedge clk or negedge rst_n)

60      if(!rst_n)

61          tx_en <= 0;

62      else if(rx_num == 9 && rx_sel_data) //在接收停止位之后拉高一个时钟

63          tx_en <= 1;

64      else

65          tx_en <= 0;

66  endmodule

22~34行的作用是下降沿检测,电路检测到rs232_rx有下降沿出现说明一帧数据开始传输。38~57行在波特率采样控制信号rx_sel_data的控制下,将串行数据进行串并转换,逐位存储到中间并行寄存器rx_d_r。59~65行当数据采集完毕以后,负责输出发送使能信号tx_en,触发数据发送模块启动,将采集到的数据发送到上位机。

数据发送模块波特率生成


/****************************************************

*   Engineer      :   梦翼师兄

*   QQ             :   761664056

*   The module function:控制串口发送数据的速率

*****************************************************/

00  module bps_tx(

01              clk,   //系统时钟50MHz

02              rst_n, //低电平复位

03              tx_en,    //使能信号:串口发送开始

04

05              tx_sel_data,  //波特率计数的中心点(采集数据的使能信号)

06              tx_num   //一帧数据0-9

07      );

08      //模块输入

09      input            clk;   //系统时钟50MHz

10      input            rst_n; //低电平复位

11      input            tx_en;    //使能信号:串口发送开始

12      //模块输出

13      output reg       tx_sel_data;  //波特率计数的中心点

14      output reg [3:0] tx_num;   //一帧数据0-9

15  //设置参数

16  parameter bps_div   = 13‘d5207,

17            bps_div_2 = 13‘d2603;

18

19  //发送标志位:接收到使能信号tx_en后,将标志位flag拉高,当信号tx_num计完一帧数据后拉低

20  reg       flag;

21  always@(posedge clk or negedge rst_n)

22      if(!rst_n)

23          flag <= 0;

24      else if(tx_en)

25          flag <= 1;

26      else if(tx_num == 4‘d10)

27          flag <= 0;

28

29  //波特率计数

30  reg [12:0] cnt;

31  always@(posedge clk or negedge rst_n)

32      if(!rst_n)

33          cnt  <= 13‘d0;

34    else if(flag && cnt < bps_div)

35          cnt <= cnt + 1‘b1;

36    else

37 cnt <= 13‘d0;

38

39 //规定发送数据的范围:即一帧数据(10位:1位开始位,8位数据位,1位结束位)

40 always@(posedge clk or negedge rst_n)

41 if(!rst_n)

42 tx_num <= 4‘d0;

43 else if(tx_sel_data && flag)

44 tx_num <= tx_num + 1‘b1;

45 else if(tx_num == 4‘d10)

46 tx_num <= 1‘d0;

47

48 //数据在波特率的中间部分采集:即发送数据的使能信号

49 always@(posedge clk or negedge rst_n)

50 if(!rst_n)

51 tx_sel_data <= 1‘b0;

52 else if(cnt == bps_div_2)//中间取数是为了产生尖峰脉冲,尖峰脉冲为采集数据的使能信号,用来把握速率

53 tx_sel_data <= 1‘b1;

54 else

55 tx_sel_data <= 1‘b0;

56

57 endmodule

本模块确定了发送数据与接收数据的有效范围并且进行分频计数(在此例中,使用的波特率为9600bps,时钟为50MHZ,则分频计数值为5207)。该模块功能和bps_rx模块功能类似。

数据发送模块


/****************************************************

*   Engineer      :   梦翼师兄

*   QQ             :   761664056

*   The module function:发送串口串行数据

*****************************************************/

00 module uart_tx(

01 clk,              //50MHZ时钟

02 rst_n,            //低电平复位

03 tx_num,           //一帧数据控制位

04 tx_sel_data,     //波特率计数的中心点(采集数据的使能信号)

05 rx_d,             //8位数据(即输入数据)

06 rs232_tx         //uart发送信号(一帧数据)

07 );

08 //模块输入

09 input        clk;              //50MHZ时钟

10 input       rst_n;            //低电平复位

11 input [3:0]  tx_num;              //一帧数据控制位

12 input        tx_sel_data;         //波特率计数的中心点(采集数据的使能信号)

13 input [7:0]  rx_d;             //8位数据(即输入数据)

14 //模块输出

15 output reg   rs232_tx;          //uart发送信号(一帧数据)

16 //在串口发送的过程中,确保发送1位开始位,8位有效数据位,1位结束位

17 always@(posedge clk or negedge rst_n)

18 if(!rst_n)

19 rs232_tx <= 1‘b1;

20 else if(tx_sel_data)

21 case(tx_num)

22 0: rs232_tx  <= 1‘b0;  //开始位为低电平

23 1: rs232_tx  <= rx_d[0];

24 2: rs232_tx  <= rx_d[1];

25 3: rs232_tx  <= rx_d[2];

26 4: rs232_tx  <= rx_d[3];

27 5: rs232_tx  <= rx_d[4];

28 6: rs232_tx  <= rx_d[5];

29 7: rs232_tx  <= rx_d[6];

30 8: rs232_tx  <= rx_d[7];

31 9: rs232_tx  <= 1‘b1;  //结束位为高电平

32   default: rs232_tx  <= 1‘b1;  //串口的其它空闲位均要拉至高电平

33   endcase

34

35 endmodule

20~31行在发送使能信号tx_sel_data作用下,rs232_tx首先发送启动信号,然后将并行数据逐位输出,完成并串转换,八位数据发送完毕以后发送停止信号,结束数据传输。

顶层模块


/****************************************************

*   Engineer      :   梦翼师兄

*   QQ             :   761664056

*   The module function:负责顶层连接

*****************************************************/

00 module uart(

01 clk,     //系统时钟50MHz

02 rst_n,   //低电平复位

03 rs232_rx, //uart发送信号

04 rs232_tx  //uart接收信号

05 );

06 //系统输入

07 input   clk;     //系统时钟50MHz

08 input   rst_n;   //低电平复位

09 input   rs232_rx; //uart发送信号

10 //系统输出

11 output  rs232_tx;  //uart接收信号

12

13 //内部信号:模块内部的接口信号,比如模块bps_rx的输入信号en,通过内部信号rx_en与模块uart_rx的输出信号en相连

14

15 wire  rx_en;

16 wire  tx_en;

17 wire [7:0] rx_d;

18 wire [3:0] rx_num,tx_num;

19

20 //模块例化

21 bps_rx bps_rx(                //串口接收波特率计数模块

22 .clk(clk),

23 .rst_n(rst_n),

24 .rx_en(rx_en),

25 .rx_num(rx_num),

26 .rx_sel_data(rx_sel_data)

27 );

28

29 uart_rx uart_rx(             //串口接收模块

30 .clk(clk),

31 .rx_d(rx_d),

32 .rst_n(rst_n),

33 .rs232_rx(rs232_rx),

34 .rx_en(rx_en),

35 .rx_num(rx_num),

36 .rx_sel_data(rx_sel_data),

37 .tx_en(tx_en)

38 );

39

40 bps_tx bps_tx(             //串口发送波特率计数模块

41 .clk(clk),

42 .rst_n(rst_n),

43 .tx_en(tx_en),

44 .tx_num(tx_num),

45 .tx_sel_data(tx_sel_data)

46 );

47 uart_tx uart_tx( //串口发送模块

48 .clk(clk),

49 .rst_n(rst_n),

50 .rx_d(rx_d),

51 .rs232_tx(rs232_tx),

52 .tx_num(tx_num),

53 .tx_sel_data(tx_sel_data)

54 );

55

56 endmodule

编写完可综合代码之后,查看RTL视图如下:

由RTL视图可以看出,代码综合以后得到的电路结构和我们设计的系统框图一致,说明顶层逻辑连接正确,接下来编写测试代码如下:


/****************************************************

*   Engineer      :   梦翼师兄

*   QQ             :   761664056

*   The module function:测试uart

*****************************************************/

00 `timescale 1ns/1ps   //设置仿真时间单位与精度分别为1ns/1ns

01

02 module  uart_tb;

03 //系统输入

04 reg  clk;   //系统时钟50MHz

05 reg  rst_n; //低电平复位

06 reg  rs232_rx; //uart发送信号

07 //系统输出

08 wire rs232_tx;//uart接收信号

09 //例化

10 uart  uart(

11 .clk(clk), //系统时钟50MHz

12 .rst_n(rst_n), //低电平复位

13 .rs232_rx(rs232_rx), //uart发送信号

14 .rs232_tx(rs232_tx) //uart发送信号

15 );

16

17 initial

18 begin

19 clk = 0; rst_n = 0; rs232_rx= 1;  //在复位阶段,将激励赋初值

20 #200.1  rst_n = 1;    //延时200ns后停止复位

21 //模拟发送一帧数据(发送时间的延时根据所设定的波特率计算)

22 #200    rs232_rx= 0;//开始位

23 #110000 rs232_rx= 0;//发送数据8‘ha4 (8‘b0110_0100)

24 #110000 rs232_rx= 1;

25 #110000 rs232_rx= 1;

26 #110000 rs232_rx= 0;

27 #110000 rs232_rx= 0;

28 #110000 rs232_rx= 1;

29 #110000 rs232_rx= 0;

30 #110000 rs232_rx= 0;

31 #110000 rs232_rx= 1;//结束位

32 #1500000 $stop;   //仿真1500000ns后停止仿真

33 end

34 always #10  clk = ~clk;   //时钟的表示,即每隔10ns翻转一次,一个周期的时间即为20ns,时钟为1/20ns = 50MHZ

35 endmodule

22~31行模拟了上位机数据的输入,用来测试我们设计的串口模块是否能够进行正常的数据收发。

 仿真分析

从波形上可以很清楚的看到,接收和发送的波形完全相同,说明我们的设计正确。

 

原文地址:https://www.cnblogs.com/mengyi1989/p/11517679.html

时间: 2024-11-09 02:17:32

进阶项目(3)UART串口通信程序设计讲解的相关文章

进阶项目(4)蜂鸣器程序设计讲解

写在前面的话 经过前面内容的学习,梦翼师兄相信大家的基础知识水平一定已经很扎实.那么本节,我们就一起来庆祝一下,用播放器奏响一曲<欢乐颂>,奏响我们凯旋的乐章. 什么是蜂鸣器? 蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机.打印机.电子玩具.定时器等电子产品中作为发声器件.蜂鸣器分为有源蜂鸣器和无源蜂鸣器两种,在电路中用字母“H”或“HA”(旧标准用“FM”.“ZZG”.“LB”.“JD”等)表示.那么,怎么区分有源蜂鸣器和无源蜂鸣器呢?有源蜂鸣器内部带震荡源,所以只

Win10 IoT C#开发 4 - UART 串口通信

原文:Win10 IoT C#开发 4 - UART 串口通信 Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,既可以开发设备UI与用户交互式操作,又可以控制GPIO等接口,使得原来嵌入式繁琐的开发变得简单.通过Remote Debug功能可以进行断点追踪调试.C#语言本身也有很好的用户基础,相信Win10 IoT 不远的将来会火起来.上个月帮朋友解决了关于Win10 IoT 的一些技术问题,当前也有很多公司在尝试采用Win10 IoT进行开发,可能也会遇到这些问题,

嵌入式Linux裸机开发(七)——UART串口通信

嵌入式Linux裸机开发(七)--UART串口通信 一.UART串口通信简介 通用异步收发器简称UART,即UNIVERSAL ASYNCHRONOUS RECEIVER AND TRANSMITTER, 它用来传输串行数据.发送数据时, CPU 将并行数据写入UART,UAR按照一定的格式在一根电线上串 行发出:接收数据时, UART检测另一根电线的信号,将串行收集在缓冲区中, CPU 即可读取 UART 获得这些数据. 在 S5PV210中, UART提供了 4 对独立的异步串口I/O端口,

【C51】UART串口通信

我们常需要单片机和其他模块进行通信,数据传输,常用的方式就是串口通信技术. 常用来 单片机<-->电脑,  单片机<-->单片机之间通信. 串行通信 versus 并行通信 并行传输:将字节的各个 bit 用多条传输线路同时发送出去.每个bit使用一条线路. 优点:速度相对快,控制简单. 缺点:控制线路多,耗费的硬件资源多. 串行传输:将一个字节的数据的各个 bit 在一条线路上 分时发送.一个字节8位,则至少需要分8次发送完. 优点:需要的线路少,成本低. 缺点:控制复杂,因为它

奶爸业余单片机学习之:UART串口通信学习笔记(一)

UART串口通信,全名:异步串口通信 UART的四种工作模式:(0,1,2,3) 模式1:SM0 = 0; SM1 = 1;REN = 1  //由SCON(串行口控制寄存器)控制,可位寻址.10位异步收发(8位数据),波特率可变(由定时器1的溢出率控制) 模式1功能:以TXD为例,平时没数据时,TXD为高电平,需要发送数据时,先发送一个起始位0,然后发送八位数据位(一个字节),最后发送一位停止位1: REN位为允许串行接收位:REN = 1:允许串行口接收数据:REN = 0:禁止串行口接收数

Win10 IoT C#开发 3 - UART 串口通信

Windows 10 IoT Core 是微软针对物联网上市场的一个重要产品,既可以开发设备UI与用户交互式操作,又可以控制GPIO等接口,使得原来嵌入式繁琐的开发变得简单.通过Remote Debug功能可以进行断点追踪调试.C#语言本身也有很好的用户基础,相信Win10 IoT 不远的将来会火起来.上个月帮朋友解决了关于Win10 IoT 的一些技术问题,当前也有很多公司在尝试采用Win10 IoT进行开发,可能也会遇到这些问题,相关文档现在还非常少,这里写出来供大家参考.因为要做一个Jav

奶爸业余单片机学习之:UART串口通信学习笔记(二)

/************************************** 串口通信实验* 晶振11.0592MHz* 波特率9600bps* 中断方式实现:单片机接收电脑数据,加1后发送回电脑***************************************/ #include<reg52.h> unsigned char dat; /**********串口通信配置*******************/void UART_CONFIG(unsigned long baud

51单片机IO口模拟UART串口通信

#include <reg52.h>#include "main.h"#include "smartcard.h"#include "stdio.h" typedef enum { false, true }bool; #if 0sbit PIN_RXD = P1^0; //接收发送同一个引脚定义sbit PIN_TXD = P1^0; //接收发送同一个发送引脚定义sbit PIN_CLK = P3^1; //智能卡时钟引脚定义sb

基础项目(3)三态门程序设计讲解

写在前面的话 我们所接触到的IO都是单纯的输入(input)或者输出(output)类型,而我们的一些总线协议如IIC等,要求信号为三态类型,也就是我们所说的输入输出(inout)类型.那么,本节梦翼师兄将和大家一起来探讨三态门的用法. 项目需求 设计一个三态门电路,可以实现数据的输出和总线“挂起”. 系统架构 模块功能介绍 模块名 功能描述 three_state 控制三态总线Sda是否处于挂起状态 顶层模块端口描述 端口名 端口说明 Clk 系统时钟 Rst_n 系统低电平复位 Data_b