当前位置: 首页 > news >正文

集成电路流片随笔10:UART模块tinyriscv 通信协议和RIB接口总线区别

UART(通用异步收发传输)Universal Asynchronous Receiver-Transmitter模块,用于支持数据的串行通信。模块包括接收和发送数据的逻辑。

模块端口说明:

module uart(input wire clk,           // 时钟信号input wire rst,           // 复位信号input wire we_i,          // 写使能信号input wire[31:0] addr_i, // 地址信号input wire[31:0] data_i, // 写入数据output reg[31:0] data_o, // 读取数据output wire tx_pin,       // UART 发送数据引脚input wire rx_pin         // UART 接收数据引脚
);
  • we_i:写使能信号,控制是否可以向寄存器写数据。
  • addr_i:寄存器的地址信号,表示要访问哪个寄存器。
  • data_i:写入的数据,给 UART 寄存器。
  • data_o:读取的数据输出,来自 UART 寄存器。
  • tx_pin:UART 发送引脚,用于将数据发送到外部设备。
  • rx_pin:UART 接收引脚,用于接收外部设备发送的数据。

寄存器和常量定义:

localparam BAUD_115200 = 32'h1B8; // 50MHz时钟,波特率115200bps对应的分频系数
localparam S_IDLE = 4'b0001; // 状态机的空闲状态
localparam S_START = 4'b0010; // 启动状态
localparam S_SEND_BYTE = 4'b0100; // 发送字节状态
localparam S_STOP = 4'b1000; // 停止状态reg tx_data_valid;  // 发送数据有效
reg tx_data_ready;  // 发送数据准备好reg[3:0] state;     // 当前状态
reg[15:0] cycle_cnt; // 计数周期,用于波特率控制
reg[3:0] bit_cnt;    // 发送的位计数
reg[7:0] tx_data;    // 发送数据
reg tx_reg;           // 发送寄存器reg rx_q0;           // RX 引脚的延迟信号
reg rx_q1;           // RX 引脚的另一个延迟信号
wire rx_negedge;   
reg rx_start;         // RX使能
reg[3:0] rx_clk_edge_cnt; // RX 时钟边缘计数
reg rx_clk_edge_level;    // RX 时钟边缘电平
reg rx_done;          // RX 完成标志
reg[15:0] rx_clk_cnt; // RX 时钟计数
reg[15:0] rx_div_cnt; // RX 分频计数
reg[7:0] rx_data;    // 接收到的 RX 数据
reg rx_over;          // RX 超过标志// 寄存器地址
localparam UART_CTRL = 8'h0;
localparam UART_STATUS = 8'h4;
localparam UART_BAUD = 8'h8;
localparam UART_TXDATA = 8'hc;
localparam UART_RXDATA = 8'h10;

波特率和分频器:

波特率(Baud Rate)表示每秒钟传输的数据位数。在通信系统中,设置合适的波特率非常重要,因为它决定了数据传输的速度。

在此代码中,BAUD_115200 = 32'h1B8 用于设置 UART 模块的波特率为 115200。这是通过分频器来实现的。波特率分频器的作用是根据时钟频率(这里假设时钟频率是 50MHz)生成一个适合于 UART 数据传输的时钟信号。

如何计算波特率:

  1. 假设系统时钟是 50MHz(50,000,000 Hz),表示每秒钟有 5000 万个时钟周期。
  2. UART 波特率(115200)意味着每秒钟发送 115200 个数据位(包括起始位、数据位、停止位等)。
  3. 为了实现这一目标,我们需要将系统时钟频率分频,得到每个数据位传输所需要的时间。

通过公式:
波特率分频器 = 系统时钟频率 波特率 = 50000000 115200 ≈ 434.027 \text{波特率分频器} = \frac{\text{系统时钟频率}}{\text{波特率}} = \frac{50000000}{115200} \approx 434.027 波特率分频器=波特率系统时钟频率=11520050000000434.027

这个结果表示我们需要将系统时钟频率分频到 115200 波特率,通常会进行四舍五入,得到分频器值 0x1B8

32'h1B8 的含义

  • 32'h1B8 是一个 32 位十六进制数,它的值等于十进制的 440,这个数字就是分频器的值,表示将时钟频率除以 440 后,得到的时钟信号会有 115200 Hz 的频率,这样就达到了设置 115200 波特率的目的。

总结:

BAUD_115200 = 32'h1B8 表示将时钟分频到 115200 波特率所需的分频器值。在实际操作中,这个分频器值会用在生成 UART 波特率时钟的电路中,从而确保数据的正确传输速度。


寄存器控制和状态操作:

always @ (posedge clk) beginif (rst == 1'b0) beginuart_ctrl <= 32'h0;uart_status <= 32'h0;uart_rx <= 32'h0;uart_baud <= BAUD_115200;tx_data_valid <= 1'b0;end else beginif (we_i == 1'b1) begincase (addr_i[7:0])UART_CTRL: beginuart_ctrl <= data_i;endUART_BAUD: beginuart_baud <= data_i;endUART_STATUS: beginuart_status[1] <= data_i[1];endUART_TXDATA: beginif (uart_ctrl[0] == 1'b1 && uart_status[0] == 1'b0) begintx_data <= data_i[7:0];uart_status[0] <= 1'b1;tx_data_valid <= 1'b1;endendendcaseend else begintx_data_valid <= 1'b0;if (tx_data_ready == 1'b1) beginuart_status[0] <= 1'b0;endif (uart_ctrl[1] == 1'b1) beginif (rx_over == 1'b1) beginuart_status[1] <= 1'b1;uart_rx <= {24'h0, rx_data};endendendend
end
  • 在时钟上升沿触发时,模块根据复位信号初始化或更新各个寄存器。
  • 如果 we_i == 1 且地址匹配相应寄存器,则更新相应寄存器。
  • UART_TXDATA:当数据写入 UART_TXDATA 寄存器时,如果 uart_ctrl[0] 为 1(发送使能),且 uart_status[0] 为 0(发送空闲),则将数据写入 tx_data 并开始发送。

读取寄存器操作:

always @ (*) beginif (rst == 1'b0) begindata_o = 32'h0;end else begincase (addr_i[7:0])UART_CTRL: begindata_o = uart_ctrl;endUART_STATUS: begindata_o = uart_status;endUART_BAUD: begindata_o = uart_baud;endUART_RXDATA: begindata_o = uart_rx;enddefault: begindata_o = 32'h0;endendcaseend
end
  • 这是一个组合逻辑块,用于根据 addr_i 地址读取 UART 寄存器的值并输出到 data_o

发送数据(TX):

always @ (posedge clk) beginif (rst == 1'b0) beginstate <= S_IDLE;cycle_cnt <= 16'd0;tx_reg <= 1'b0;bit_cnt <= 4'd0;tx_data_ready <= 1'b0;end else beginif (state == S_IDLE) begintx_reg <= 1'b1;tx_data_ready <= 1'b0;if (tx_data_valid == 1'b1) beginstate <= S_START;cycle_cnt <= 16'd0;bit_cnt <= 4'd0;tx_reg <= 1'b0;endend else begincycle_cnt <= cycle_cnt + 16'd1;if (cycle_cnt == uart_baud[15:0]) begincycle_cnt <= 16'd0;case (state)S_START: begintx_reg <= tx_data[bit_cnt];state <= S_SEND_BYTE;bit_cnt <= bit_cnt + 4'd1;endS_SEND_BYTE: beginbit_cnt <= bit_cnt + 4'd1;if (bit_cnt == 4'd8) beginstate <= S_STOP;tx_reg <= 1'b1;end else begin                tx_reg <= tx_data[bit_cnt];endendS_STOP: begintx_reg <= 1'b1;state <= S_IDLE;tx_data_ready <= 1'b1;endendcaseendendend
end
  • 这是 UART 发送模块,使用状态机来控制数据的发送过程。
  • 状态机:包括空闲状态(S_IDLE)、起始状态(S_START)、发送数据状态(S_SEND_BYTE)和停止状态(S_STOP)。
  • cycle_cnt:计数器用于生成波特率。
  • 根据状态机的状态,数据位被依次发送到 tx_reg,并通过 tx_pin 引脚发送出去。

接收数据(RX):

assign rx_negedge = rx_q1 && ~rx_q0;
  • rx_negedge:表示接收引脚的下降沿。当 rx_q1 为 1 而 rx_q0 为 0 时,意味着接收到数据的下降沿。rx_q0 是当前时钟周期的接收数据。rx_q1 是前一个时钟周期的接收数据。

接收数据的处理逻辑相对复杂,涉及对 RX 数据的采样、计时、数据转换等操作,通过这些操作来正确接收数据并最终将数据写入 uart_rx 寄存器。


总结:

这个 UART 模块 实现了一个 115200 波特率的串口通信模块。它包括:

  • 数据发送和接收的功能。
  • 通过控制寄存器设置波特率、使能接收发送等。
  • 使用状态机控制数据的发送过程,确保每一位数据都在正确的时钟周期被发送。

广泛应用于串行设备的通信,如计算机与外部设备、嵌入式系统之间的通信等。


其他常见的通信接口,应用场景和通信特性

1. SPI (Serial Peripheral Interface)

  • 用途:SPI 是一种同步串行通信协议,通常用于微控制器与外部外设(如传感器、存储设备、显示屏等)之间的数据交换。
  • 特点:支持全双工通信,使用多个信号线(如:MOSI、MISO、SCK、CS),速度较快。
  • 信号线
    • MOSI (Master Out Slave In):主设备发送数据到从设备。
    • MISO (Master In Slave Out):从设备发送数据到主设备。
    • SCK (Serial Clock):时钟信号,由主设备提供。
    • CS (Chip Select):选择要与主设备通信的从设备。

2. I2C (Inter-Integrated Circuit)

  • 用途:I2C 是一种同步串行通信协议,广泛应用于低速设备(如传感器、EEPROM、ADC等)之间的通信。
  • 特点:支持多主机和多从机的配置,只需要两条信号线:数据线和时钟线。它是一个半双工通信协议,即数据传输和时钟信号共享。
  • 信号线
    • SCL (Serial Clock):时钟信号。
    • SDA (Serial Data):数据传输线。

3. CAN (Controller Area Network)

  • 用途:CAN 是一种多主机的串行通信协议,常用于汽车电子和工业自动化系统中。它用于设备和控制器之间的通信,尤其在噪声环境下表现良好。
  • 特点:支持高速的数据传输,具备错误检测和故障保护机制,可以在多个节点之间传输信息。
  • 信号线
    • CAN_HCAN_L:用于差分信号传输。

4. RS-232 (Recommended Standard 232)

  • 用途:RS-232 是一种标准的串行通信协议,常用于计算机和外设(如调制解调器、打印机等)之间的连接。
  • 特点:使用的信号电平与 TTL 和 CMOS 不同,通常通过 DB9 或 DB25 连接器实现。它的传输速度较低,传输距离有限。
  • 信号线
    • TX(Transmitter):数据输出。
    • RX(Receiver):数据输入。
    • GND(Ground):地线。

5. USB (Universal Serial Bus)

  • 用途:USB 是一种广泛使用的串行通信协议,主要用于计算机和外部设备(如键盘、鼠标、打印机、存储设备等)之间的通信。
  • 特点:支持即插即用,能够提供电力给外设,数据传输速率较高。
  • 信号线
    • D+D-:数据传输线。
    • Vcc:电源线。
    • GND:地线。

6. Ethernet (以太网)

  • 用途:Ethernet 是一种用于局域网(LAN)通信的标准协议,广泛应用于计算机、路由器、交换机等设备之间的网络通信。
  • 特点:支持高速数据传输,广泛应用于家庭、办公和企业网络。
  • 信号线
    • Tx+Tx-:发送数据。
    • Rx+Rx-:接收数据。

7. Bluetooth

  • 用途:蓝牙是一种短距离无线通信协议,广泛用于无线设备之间的通信,如耳机、鼠标、手机等。
  • 特点:低功耗,适合短距离通信,支持点对点或点对多点通信。
  • 信号:无线信号。

8. Wi-Fi

  • 用途:Wi-Fi 是一种无线局域网通信协议,广泛用于无线互联网连接,常见于智能手机、笔记本电脑、路由器等设备中。
  • 特点:支持高速无线网络通信,适合家庭、办公室等环境。
  • 信号:无线信号。

9. MIPI (Mobile Industry Processor Interface)

  • 用途:MIPI 是一种高带宽的串行通信接口,广泛应用于移动设备(如智能手机、平板电脑等)中的图像传输、显示、摄像头接口等。
  • 特点:支持高数据速率和低功耗,常用于连接图像传感器、显示屏等设备。
  • 信号线
    • D-PHY:用于高速数据传输。
    • C-PHY:用于低功耗模式下的数据传输。

10. LVDS (Low-Voltage Differential Signaling)

  • 用途:LVDS 是一种低电压差分信号传输协议,常用于高速数据传输,例如在显示器、通信设备中。
  • 特点:适用于高速信号传输,具有较低的功耗和噪声免疫能力。
  • 信号线
    • LVDS+LVDS-:用于差分信号传输。

他们和RIB-接口总线的区别:

RIB (Request/Response Interface Bus)

1. RIB (Request/Response Interface Bus)

RIB 是一个 请求/响应总线接口,通常在复杂的系统设计中用于 主从结构 的通信。它通常用于在处理器和不同外设、模块之间进行通信。这种接口设计允许主设备(如 CPU 或其他控制器)向从设备发送请求,并等待从设备的响应。RIB 接口通常用于不同模块之间的低级别通信,例如 处理器与外设、内存、IO 设备之间的通信

RIB 接口的特点
  • 主从通信:一个或多个主设备通过请求/响应的方式与从设备进行通信。
  • 简单的请求-响应机制:主设备发出请求,从设备处理并返回响应。
  • 支持不同的数据传输模式:可以使用简单的读/写操作进行通信,通常不涉及复杂的协议。
  • 灵活性:RIB 可以与多种外设连接,如存储器、外部设备等。
  • 接口信号:通常包括地址线、数据线和控制信号(如读写使能)。
RIB 用途示例
  • 内存接口:CPU 通过 RIB 向 RAM 发送读/写请求。
  • 外设接口:CPU 向外设发出控制命令,并等待响应数据。

2. 与 UART, SPI, I2C 等接口的区别

  • UART:是一个 异步串行通信协议,常用于计算机与外设之间的数据通信,支持点对点的全双工传输。UART 是标准的串行接口,通常用于通信距离较远的设备(如计算机与调制解调器、传感器等)。

  • SPI:是一种 同步串行接口,用于主设备与多个从设备之间的高速数据传输。SPI 支持全双工通信,但它通常需要更多的信号线(如 MOSI、MISO、SCK 和 CS)。

  • I2C:是一种 同步串行接口,通常用于低速设备之间的通信。I2C 使用两条信号线(SDA 和 SCL)支持多主机和多从机的通信,适合低速设备。

关键区别
  • 协议类型:UART、SPI 和 I2C 都是标准的通信协议(通常涉及数据传输的格式、时序、错误处理等),而 RIB 主要是一个 硬件总线接口,用于简单的请求/响应通信。它通常不涉及复杂的协议。
  • 数据传输模式
    • UART 是异步通信,而 SPII2C 是同步通信。
    • RIB 则通常用于较低级别的控制信号和响应,没有复杂的数据协议,主要关注传输控制信号。
  • 用途
    • UARTSPII2C 通常用于外设之间的数据交换,具有明确的协议和数据格式。
    • RIB 更多用于 内部模块之间 的简单通信,如处理器与内存、外设之间的低级控制信号传递。

总结:

  • RIB 通常用于模块间的低级请求/响应式通信,通常不涉及复杂的协议。它是硬件设计中常见的总线接口,用于控制信号和基本数据的传输。
  • UART, SPI, 和 I2C 是不同的通信协议,涉及到更高层次的数据传输,并且通常用于 计算机与外设外设与外设 之间的通信,且每种协议都有明确的通信规范。

相关文章:

  • 【day5】调用AI接口,生成自动化测试用例
  • JVM 垃圾回收
  • 一个简单的Python文件MCP服务器
  • OpenAI 最新发布的 GPT-4.1 系列在 API 中正式上线
  • Google-Tensorflow-NLP
  • NLP高频面试题(四十三)——什么是人类偏好对齐中的「对齐税」(Alignment Tax)?如何缓解?
  • 什么样的游戏需要用到游戏盾SDK呢?
  • vue 表格某列超出显示...,悬浮tip
  • 【HarmonyOS 5】AttributeModifier和AttributeUpdater详解
  • 【C#】Html转Pdf,Spire和iTextSharp结合,.net framework 4.8
  • MAC-​​需求​​:10万订单异步执行库存扣减、短信通知。
  • #include<bits/stdc++.h>
  • macos下 ~/.zshrc~ 和 ~/.zshrc
  • WEB安全--蓝队日志--RCE数据包分析
  • 系统架构设计师:系统架构概述知识体系、考点详解、高效记忆要点、练习题并提供答案与解析
  • LeetCode面试热题150中12-18题学习笔记(用Java语言描述)
  • Java项目之基于ssm的QQ村旅游网站的设计(源码+文档)
  • Redis 适合作为微服务架构中的哪些组件?
  • 树莓派_利用Ubuntu搭建gitlab
  • 深入理解 Nacos 服务发现机制
  • 习近平同俄罗斯总统普京举行会谈
  • 商务部再回应中美经贸高层会谈:美方要拿出诚意、拿出行动
  • 李云泽:将尽快推出支持小微企业民营企业融资一揽子政策
  • 潘功胜:将创设科技创新债券风险分担工具
  • 一周人物|何子彦任职光州双年展,陈意心讲述五原路往事
  • 抗战回望19︱《中国工程师学会四川考察团报告》:“将来重工业所在,以四川为最适宜之地点”