[X]关闭
0

S01-CH10 UART串口通信FPGA程序设计

摘要: 软件版本:VIVADO2017.4 操作系统:WIN10 64bit硬件平台:适用XILINX 7系列FPGA(包括A7/K7/Z7/ZU/KU等)米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!10.1 概述 串口自诞生以来由于其简单 ...

软件版本:VIVADO2017.4

操作系统:WIN10 64bit

硬件平台:适用XILINX 7系列FPGA(包括A7/K7/Z7/ZU/KU等)

米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!

10.1 概述

      串口自诞生以来由于其简单可靠的传输方式,被大量使用,对于现在这个充满高速通信设备的时代来说,串口依然不过时。老早以前的台式机和笔记本可都是有串口的,虽然现在很多台式机串口没有了,笔记本也没有串口了,但是串口从来没有被丢弃,只是以另外一种形式存在,这就是USB转串口芯片。串口只需要2根线就可以实现一收一发,使用简单,可靠方便,在低速场合大量使用。比如一些工控的人机界面、我们用的一些单片机的USB下载器都是用USB转串口来实现的。


10.2 时序设计 


      在进行具体的串口设计之前,先了解串口通信协议。通常串口的一次发送或接收由四个部分组成:起始位S(“一般为逻辑‘0’)、数据位D0~D7(一般为6位~8位之间可变,数据低位在前)、校验位(奇校验、偶检验或不需要校验位)、停止位(通常为1位、1.5位、2位)。停止位必须为逻辑1。在一次串口通信过程中,数据接收与发送双方没有共享时钟,因此,双方必须协商好数据传输波特率。波特率即数据传输速率。根据双方协议好的传输速率,接收端即可对发送端的数据进行采样。常见的波特率标准为300bps,600bps,800bps,9600bps,19200bps等。当然更块的速度意味着对采样的要求更高,有可能误码率会逐渐提高。

通常对串口进行数据采样,采用更高频的时钟。这样做的目的是采用高频时钟来锁存低频时钟,减少数据的误码率,增加接收模块的自纠错能力。


具体的工作流程为:

      发送端按照预先设定好的波特率,发送起始位(Start)+数据位(data)+奇偶校验位+结束位。其中,起始位为逻辑0,结束位为逻辑1,发送端在空闲状态为1。发送数据包格式如下图所示。

       数据的奇偶校验位是可以选择的,如果不使用奇偶,那么就没有这个数据位,我们本课程中没有用到奇偶校验位。

       接收端通过检测电平‘1’到‘0’的跳变来确定一个数据包的开始。确定开始位接收完成之后,依次接收数据,使用更高的采样时钟,完成数据采集。接收完数据位后,继续接收奇偶校验位和停止位。

串口的接收与发送,其主要时序设计包括两个部分:1、波特率的产生时序;2、数据传输时序,包括接收与发送。

波特率产生时序设计:假设FPGA输入时钟100Mhz,为得到常用的波特率,仍然采用计数分频来得到。BAUD_DIV=100_000000/波特率。其中采样中心点为发送或接收时钟的中心点,即BAUD_DIV_CAP=100_000000/(2*波特率)。该部分在数据接收和发送部分均单独完成。

      数据接收模块:在设置好传输波特率的情况下,根据串口传输时序,进行解串。空闲状态时,接收 数据为逻辑高电平,等待起始位逻辑低电平的到来。当起始位到达后,由低位到高位,依次采集8位数据,并进行相应的解串,存入临时寄存器。接收有效数据完成后,判断结束位,接收完毕。

数据发送模块:设置发送使能信号和待发送的数据。通过计数器,表示10个数据发送的周期。这10个数据,依次为起始位+8位数据位+1位结束位,实现数据位的逐个发送。

      本设计中,采用PC机的串口调试助手,发送数据位至FPGA,FPGA接收到数据位之后,立即回传至PC机。具体的设计原理和代码思路,在后续章节逐一介绍。

10.3 程序分析

接收端和发送端分别通过波特率启动信号和数据发送标志信号启动波特率时钟。

10.3.1 uart_rx_path.v

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////

// Company:

// Engineer:

//

// Create Date: 2017/07/25 13:35:17

// Design Name:

// Module Name: uart_rx_path

// Project Name:

// Target Devices:

// Tool Versions:

// Description:

//

// Dependencies:

//

// Revision:

// Revision 0.01 - File Created

// Additional Comments:

//

//////////////////////////////////////////////////////////////////////////////////



module uart_rx_path(

input clk_i,

input uart_rx_i,


output [7:0] uart_rx_data_o,

output uart_rx_done,

output baud_bps_tb //for simulation

 );

  

parameter [13:0] BAUD_DIV     = 14'd10416;//波特率时钟,9600bps,100Mhz/9600=5208

parameter [13:0] BAUD_DIV_CAP = 14'd5208;//波特率时钟中间采样点,100Mhz/9600/2=2604


reg [13:0] baud_div=0; //波特率设置计数器

reg baud_bps=0; //数据采样点信号

reg bps_start=0; //波特率启动标志

always@(posedge clk_i)

begin

if(baud_div==BAUD_DIV_CAP) //当波特率计数器计数到采样点时,产生采样信号baud_bps

begin

baud_bps<=1'b1;

baud_div<=baud_div+1'b1;

end

else if(baud_div

begin

baud_div<=baud_div+1'b1;

baud_bps<=0;

end

else

begin

baud_bps<=0;

baud_div<=0;

end

end


reg [4:0] uart_rx_i_r=5'b11111; //数据接收缓存器

always@(posedge clk_i)

begin

uart_rx_i_r<={uart_rx_i_r[3:0],uart_rx_i};

end

//数据接收缓存器,当连续接收到五个低电平时,即uart_rx_int=0时,作为接收到起始信号

wire uart_rx_int=uart_rx_i_r[4] | uart_rx_i_r[3] | uart_rx_i_r[2] | uart_rx_i_r[1] | uart_rx_i_r[0];


reg [3:0] bit_num=0; //接收数据个数计数器

reg uart_rx_done_r=0; //数据接收完成寄存器

reg state=1'b0;


reg [7:0] uart_rx_data_o_r0=0;//数据接收过程中,数据缓存器

reg [7:0] uart_rx_data_o_r1=0;//数据接收完成,数据寄存器


always@(posedge clk_i)

begin

uart_rx_done_r<=1'b0;

case(state)

1'b0 :

if(!uart_rx_int)//当连续接收到五个低电平时,即uart_rx_int=0时,作为接收到起始信号,启动波特率时钟

begin

bps_start<=1'b1;

1

路过

雷人

握手

鲜花

鸡蛋

刚表态过的朋友 (1 人)

本文作者
2019-10-15 11:11
  • 1
    粉丝
  • 3104
    阅读
  • 0
    回复

关注米联客

扫描关注,了解最新资讯

联系人:汤经理
电话:0519-80699907
EMAIL:270682667@qq.com
地址:常州溧阳市天目云谷3号楼北楼201B
热门评论
排行榜