FPGA 串口通信(uart)初探篇(含源代码)

您所在的位置:网站首页 串口通信的程序设计流程 FPGA 串口通信(uart)初探篇(含源代码)

FPGA 串口通信(uart)初探篇(含源代码)

2024-06-29 01:26| 来源: 网络整理| 查看: 265

一、UART

串口通信,说实话是日常生活中很常见的一种9针型的主机和显示屏之间的通信模式。本次博客,只为自己复盘相关知识,初学者,错误较多,请多指教。所以本文参考(一)FPGA之串口通信(UART)_fpga uart-CSDN博客

而编著的。

FPGA是一种可编程的逻辑器件,用于各种数字电路设计与实现,是一种可重复利用的芯片盒。今天所介绍的是利用赛灵思xc7a35tftg256-1系列的FPGA实现串口通信(UART)。

一个状态机,我们有发送模块(uart_tx)和接收模块((uart_tx)。模块首先得有一个时钟信号CLK,复位信号RESET.

波特率解释:

        串口协议中baud_rate波特率是很重要的知识点,字面意思就是一秒钟传输的码元(即一个0-1状态)的个数,就是指的是一秒钟传输的二进制位数,常见单位是bit/s和bps两种,常见的串口速度有115200bps(RS232串口)和9600bps and so on,

波特率和字节转换:

        1GB=1024MB   1MB=1024KB   1KB=1024B字节  ,倘若我们串口数据位每秒钟512字节,串口的波特率就是115200位/秒   (没搞懂换算?)

如果我们校验位置零,则位/10=字节 ,如波特率115200,即是115200(位/秒)=11520(b/s) ;除以1024 就可以从位换算到KB:波特率115200=115200((位/秒))=11.25KB/S

今天我们要在FPGA上实现异步串口通信,假设我们FPGA的clk时钟是50Mhz的系统时钟,波特率是9600bps,那么传输一个bit需要的时钟周期个数是50_000_000/9600个个数。得到这个个数,再乘以周期时间,就可以得到这个1bit所需要的时间。

状态机工作原理解释:

1.串口通信的信号线只需要两条线就可以完成。tx和rx, tx是状态机信号发送端,rx是状态机的信号接收端。

2.起始位STATE_START,数据线由高变低,低有效触发,即0开始,数据开始传输。

3.数据位,起始位低有效之后,数据位开始传输,如下图是8为数据,从左向右开始传输低位向着高位前进。

4.校验位PARITY,我们可以将校验位当成一个特殊的空位。通常使用的是奇偶校验位,通常在代码中有说明是否有校验, PARITY_ON=0,   //校验位,1为有校验位,0为无校验位,缺省为0。(即在串口通信中,校验位通常不适用)

5.停止位end,高有效=1,它表是一个个字节传输的结束

6.空闲位,是持续的高有效,由于当start=0低电平以后开始数据传输,所以高有效就能够使得状态机处于空闲状态。

7.帧:我们将一个个字节传输从起始位到停止位经历的全部时间称之为一帧。

状态机模型解释:

        如下图,我们定义了一个state状态机,用于控制串口通信的不同状态。我们还定义了一个bit_counter计数器用于计算每个位的延迟时间,在串口通信实例中,假设每个位延迟时间为bit_delay。然后定义一个数据寄存器serial_data,用于存储接收到的数据,开始时置位为0

在状态机的always块中,我们根据不同的状态开始发送以及接收。在空闲状态IDLE下,如果检测到起始位,则将状态切换到‘START_BIT’,同时重置计数器和数据寄存器。

在‘start_bit’状态下,通过计数器进行延迟,等待计数器进行延迟,等待起始位结束,然后将状态位切换到data_bits

在‘data_bits’状态下,通过计数器位逐位接收数据,并将存储在数据寄存器‘serial_data’中。当接收完所有数据后,应该切换到parity_bit位

然后根据parity_bit数据校验位的是否需要,进行逻辑处理

在stop位置等待结束后,切换☞IDLE空闲状态,并将发送状态的‘uart_tx’设置为停止位。

下列给出具体实现代码:

发送端uart_tx实现原理:发送思路原理:我们可以通过定义一个计数器,来记录每次发送所需要的的时间,然后用一个状态机来记录发送的状态。

`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 03/10/2024 08:46:28 PM // Design Name: // Module Name: uart_tx // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module uart_tx #( //搜素一下 这里为什么要加井号才能成功 parameter CLK_FRE=50, //默认时钟频率为50Mhz parameter DATA_WIDTH=8, //有效数据位,缺省为8位 parameter PARITY_TYPE=0, //校验类型,1为奇校验,0为偶校验,缺省为偶校验 parameter PARITY_ON=0, //校验位,1为有校验位,0为无校验位,缺省为0 parameter BAUD_RATE=9600 //波特率,缺省为9600 ) ( input i_clk_sys,//系统时钟 input i_rst_n,//全局异步复位 input[DATA_WIDTH-1:0] i_data_tx,//传输数据输入 input i_data_valid,//传输数据有效 output reg o_uart_tx//UART输出 ); //状态机定义 reg[2:0] r_current_state;//当前状态 reg[2:0] r_next_state;//次态 localparam STATE_IDLE=3'b000; //空闲状态 localparam STATE_START=3'b001; //开始状态 localparam STATE_DATA=3'b011; //数据发送状态 localparam STATE_PARITY=3'b100; //数据校验计算和发送 localparam STATE_END=3'b101; //结束状态 localparam CYCLE=CLK_FRE*1000000/BAUD_RATE; //波特率计数周期 reg baud_valid;//波特计数有效位 reg[15:0] baud_cnt; //波特率计数器 reg baud_pulse; //波特率采样脉冲 reg[3:0] r_tx_cnt; //接收数据位计数 //波特率计数器 always @(posedge i_clk_sys or negedge i_rst_n ) begin if(!i_rst_n) //如果是低电平 则成立 baud_cnt


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3