FPGA之旅设计99例之第三例-----UART串口通信

简介: 笔记

一. 简介


这是FPGA之旅的第三个设计实例了,通过串口协议,就可以和电脑上的串口调试助手进行通信啦。串口一般用来输出程序中的一些信息,用来调试,也可以用来进行信息交互。在stm32中是可以通过串口下载程序的,是不是很nice。本例将实现一个基本的串口模块。


感兴趣的话,欢迎关注微信公众号 FPGA之旅。


二. 串口电路


串口电路一般使用的是CH340芯片,将串口协议中的RX和TX数据线,转换成电脑上可以识别的COM口,让电脑知道这个外部设备是串口设备。当然不弄硬件哈,只简单了解一下即可,还是重点学习下面的串口协议。

5.png

三. 串口协议


串口协议的全程为串行异步通信协议,UART。


异步,就说明通信双方需要提前约定好数据传输的速率,即波特率,每秒传输bit的数量。串行,就说明数据是按bit一个一个发送出去的(其他的有可能是2bit,3bit,或者更多)。


串口协议只需要两个数据线,一个用来发送,一个用来接收。具体协议规定如下


空闲位 :数据线都为高电平。

起始位:数据线拉低1bit,也就是拉低1bit所占用的时间。

数据位: 一比特一比特的将数据发送出去,先发送低位,后发送高位,数据位宽可以为5,6,7,8。一般为8bit。

校验位: 可以设置为奇校验,偶校验和无校验位。一般设置为无校验位,即去掉。

停止位: 数据线拉高0.5、1、1.5bit。一般设置为1bit。


7.png

以上就是串口协议的全部。


四. 实现思路


按照协议的规定,可以非常轻松得到状态机一共用那几个状态


空闲态

起始态

数据态

停止态

一共四个状态,每个状态所需要做的事情,在协议中已经明确指出来了。


还有一个问题就波特率怎么计算。FPGA的时钟一般为50Mhz,也就是一个时钟周期为20ns。可以先把波特率换成发送一个bit需要多少ns。最后再除以20,得到发送一个bit需要多少个时钟周期。例如波特率为115200,则时钟周期数计算方法如下


K = ((1 / 115200)* 1000 * 1000 * 1000) /20


这样就可以开始安心写代码啦!!代码一共分为两个部分,分别为TX和RX两个。

五. TX发送模块编写

先来定义端口信号.


请求信号来了之后,就开始发送idat数据


module  UART_TX(
    input       sys_clk,       /*系统时钟 50M*/
    input       rst_n,         /*系统复位 低电平有效*/
    input       uart_tx_req,   /*串口发送请求*/
    output      uart_tx_done,  /*串口发送完成*/
    input[7:0]  idat,          /*发送数据*/
    output      uarttx         /*uart tx数据线*/
);


再来定义波特率以及各个状态


时钟周期这里有一点点小改动,避免出现小数,而产生数值错误。


parameter   UARTBaud   = 'd115200;     /*波特率*/
localparam  UARTCLKPer =  (('d1000_000_000 / UARTBaud) /20) -1;   /*每Bit所占的时钟周期*/
localparam  UART_Idle       =   4'b0001;    /*空闲态*/
localparam  UART_Start      =   4'b0010;    /*起始态*/
localparam  UART_Data       =   4'b0100;    /*数据态*/
localparam  UART_Stop       =   4'b1000;    /*停止态*/


六. RX接收模块编写


定义端口信号。

module UART_RX(
    input          sys_clk,        /*系统时钟 50M*/
    input          rst_n,          /*系统复位*/
    output         uart_rx_done,   /*串口接收完成*/
    output[7:0]    odat,           /*接收数据*/
    input          uartrx         /*uart rx数据线*/
);


边沿检测。在接收数据的时候,需要判断数据的边沿,用来确定起始信号。通过缓存前两个时钟周期获取到的数据信号。然后通过取反再与的操作,是否发生了跳变,也就是上升沿和下降沿。

/*缓存rx数据*/
reg uartrxd0,uartrxd1,uartrxd2;
/*检测rx 上下边沿*/
wire  uartrxPosedge , uartrxNegedge;
assign uartrxPosedge = (uartrxd1) & ( ~uartrxd2);
assign uartrxNegedge = (~uartrxd1) & ( uartrxd2);


由于两个模块的总代码量一共有300行左右,就不全部粘贴出来了,需要的自行在微信公众号中获取,私聊即可。


七. testbeach编写


代码编写好了,怎么能不去仿真,验一验呢!万一有bug呢?


`timescale 1ns/1ps
/*仿真文件编写*/
module testbeach();
    reg clk;
    reg rst_n;
    wire       uart_rx_done;
    wire[7:0]  uart_rx_data;
    wire       uart;
    reg[7:0]    data;
    reg         uart_tx_req;
    wire        uart_tx_done;
    always #50 clk <= ~clk;
    initial begin
        clk = 1'b0;
        rst_n = 1'b1;
        data = 'd23;
        uart_tx_req = 1'b0;
        #100     /*手动复位一下,不然仿真会有高阻态*/
        rst_n = 1'b0;
        #100
        rst_n = 1'b1;
        #100 
        uart_tx_req = 1'b1;
    end
    /*数据发送完成后,左一位,进行发送*/
    always@(posedge clk)
    begin
        if(uart_rx_done == 1'b1)
            data <= data << 1;
    end
UART_RX UART_RX_HP(
    .sys_clk        (clk),        /*系统时钟 50M*/
    .rst_n          (rst_n),          /*系统复位*/
    .uart_rx_done   (uart_rx_done),   /*串口接收完成*/
    .odat           (uart_rx_data),             /*接收数据*/
    .uartrx         (uart)         /*uart rx数据线*/
);
UART_TX UART_TX_HP(
    .sys_clk        (clk),        /*系统时钟 50M*/
    .rst_n          (rst_n),          /*系统复位*/
    .uart_tx_req    (uart_tx_req),   /*串口发送请求*/
    .uart_tx_done   (uart_tx_done),  /*串口发送完成*/
    .idat           (data),          /*发送数据*/
    .uarttx         (uart)       /*uart tx数据线*/
);
endmodule


通过仿真可以看到,代码正确的运行了,下面就是上板测试了,如果有条件的话。


8.png

不会以为串口就这样完了吧,怎么可能,这才仅仅实现了最基本的功能。更多高级东西还在后头呢!


公众号:FPGA之旅

目录
相关文章
|
7月前
|
数据格式 异构计算
|
异构计算
FPGA项目四:串口通信(下)
FPGA项目四:串口通信
131 2
FPGA项目四:串口通信(下)
|
程序员 异构计算
FPGA项目四:串口通信(中)
FPGA项目四:串口通信
301 0
FPGA项目四:串口通信(中)
|
芯片 异构计算
FPGA项目四:串口通信(上)
FPGA项目四:串口通信
384 0
FPGA项目四:串口通信(上)
|
异构计算
FPGA-基于UART的QVGA显示(二)(实现PC端发送字母数字汉字的分别显示通过按键可以删除字符)
FPGA-基于UART的QVGA显示(二)(实现PC端发送字母数字汉字的分别显示通过按键可以删除字符)
125 0
FPGA-基于UART的QVGA显示(二)(实现PC端发送字母数字汉字的分别显示通过按键可以删除字符)
|
存储 异构计算
FPGA-基于UART的QVGA显示(一)(实现PC端发送字母数字汉字的分别显示)
FPGA-基于UART的QVGA显示(一)(实现PC端发送字母数字汉字的分别显示)
177 0
FPGA-基于UART的QVGA显示(一)(实现PC端发送字母数字汉字的分别显示)
FPGA-串口通信的原理和发送模块
FPGA-串口通信的原理和发送模块
267 0
FPGA-串口通信的原理和发送模块
|
数据采集 异构计算
FPGA-串口通信的接收模块(发送接收模块)
FPGA-串口通信的接收模块(发送接收模块)
226 0
|
异构计算
FPGA与STM32串口通信
FPGA与STM32串口通信

热门文章

最新文章