发 帖  
原厂入驻New
发烧友10周年庆典,全网超值优惠来袭!千元现金券,下单抽奖赶紧参与》》

[经验] 简析UART在FPGA中的原理与实现

2019-9-6 20:22:09  260 UART FPGA
分享
0
到底什么是UART
Introduction:

      UART中文名:通用异步收发器,是Universal Asynchronous Receiver/Transmitter的简称,之所以称为异步(Asynchronous)是因为其将并行数据转换成串行数据进行发送。
     举个栗子,小明一个月的零花钱是30元,并行通信就是小明的爸爸在月初直接给30元,串行通信就是把30元拆开,每天给小明1元。由此可见,串行通信的效率较并行通信效率低,这也是串行通信的主要缺点。可是,加入小明的爸爸每天给小明1块钱,剩余的钱就可以用在别的地方(比如买烟....),所以串行通信节省传输线,这也是串行通信的主要优点。除此之外,串行通信适合于远距离传输,几米到几千公里。并行通信的传输距离一般小于30米。
       由于UART总线的数据接收与发送口是独立的,所以数据接收与发送可以同时进行,专业一点叫做全双工传输与接收,这一点主要是区别IIC,iic属于半双工的传输,内部通过上拉电阻的配置进行双向传输。


      为了更好的理解,我们分别写UART中的RS232类型的数据接收与发送,最后在一个统一的顶层文件中调用两个子模块理解这种通用异步收发方式。

            引脚            简写            意义            说明
              2         RXD         Receiver         接收数据
              3         TXD         Transmit          发送数据
          else(略)                               
补充说明:
  (一)、一些关键参数
(1)、UART通信在使用时需要设置一些参数,主要有数据位数(此处指的是有效数据位)、波特率(baudrate)、奇偶检验位和起始停止位。
  (2)、数据位:指的是单词UART数据传输期间的数据有效位数。
  (3)、波特率:英文名baudrate,单位是bps(就是bit per second),典型的波特率有9600,19200,115200。一般通信两端设备都设置相同的波特率。
  (4)、奇偶检验类型:是一种保证数据传输准确性的一种方式,比CRC(循环冗余校验)简单一些,类似于求和校验,分为奇(Odd)校验与偶(Even)校验,校验位一般加载有效数据位的左侧或者右侧。以偶校验为例,通过使检验位置1或0使得传输的数据中1的个数为偶(even)数,

如: 1(校验位) 0100,0101(有效数据位),1的个数为偶数。
(5)、停止位:每个字节发送完毕后发送停止位,标志着一次数据传输的结束,默认为1位,也可设置为1.5,2位,这个几位按照发送的时间来理解,所谓的1.5位就是说发送停止位的时间是1位的1.5倍,1.5个时间单位的bps,比如接下来的例程中设置波特率为9600bps,每1/9600秒发送一个bit,1.5停止位就是1.5/9600s发送一个bit。

UART_RX(数据接收模块设计)
1、接收端通过检测电平“1”到“0”的下降沿来确定一个数据包的开始,确定开始接受之后,依次接收数据,完成数据采集,数据的接收是先接受数据的低位,依次到最高位,接收完数据位后,继续接受奇偶校验位和停止位。


2、模块构成
(1)、波特率生成时序:以本实验为例,系统时钟为100Mhz(根据个人系统时钟确定),拟采用的baudrate=9600bps,也就是1s传输9600个bit。波特率时钟通过计数分频方式来得到,100_000_000/9600=10416,即分频系数=系统时钟/波特率。目前常用的数据采集有两种方式,一种是通过中心点采样,另一种的多个点概率采样的方式,核心语句是assgin uart_rx[x]=(a+b+c+d+e)>3;



(2)、串口传输时序:在波特率设置完毕的情况下,根据串口传输时序进行解调,空闲状态时,数据接收端口为逻辑高电平,等待起始位逻辑低电平的到来,确定起始位后,依次接收起始位、数据低位....数据高位、停止位。
  1. `timescale 1ns / 1ps  
  2. // Engineer:  Lu  
  3. // Module Name: uart_rx_path  
  4. // Tool : Vivado2017
  5. //date:2019/09/06
  6. /*
  7. 宜:嫁娶、祭祀、祈福、求嗣、出行
  8. 忌:入宅、作梁、安门、伐木、修造
  9. */
  10. ////////////////////////////////////////////////////
  11. module uart_rx_path(
  12. input clk_i,
  13. input uart_rx_i,
  14. output[7:0] uart_rx_data_o,
  15. output uart_rx_done
  16.     );
  17. //传输波特率设置为9600bit per second
  18. parameter[13:0]BAUD_DIV=14'd10416;
  19. parameter[13:0]BAUD_DIV_CAP=14'd5208;

  20. reg[13:0]baud_div;  //分频计数寄存器
  21. reg baud_bps;   //接收时钟
  22. reg bps_start=0;   //接收数据开始控制寄存器
  23. //产生接收时钟baud_bps模块
  24. always@(posedge clk_i)begin
  25. IF(baud_div==BAUD_DIV)
  26. begin
  27.   baud_bps<=1'b1;
  28. end
  29. else if(bit_num<9)
  30.   uart_rx_data_o_r0[bit_num-1]<=uart_rx_i;
  31.   else if(bit_num==10)   //接收完成,丢弃停止位
  32.   begin
  33.    bit_num<=0;
  34.    uart_rx_done_r<=1'b1;
  35.    uart_rx_data_o_r1<=uart_rx_data_o_r0;
  36.    state<=0;   //再次进入循环检测
  37.    bps_start<=0;  //停止生成波特率时钟
  38.   end
  39. end

  40. end
  41. default:;
  42. endcase
  43. end  
  44. assign baud_rx_data_o=uart_rx_data_o_r1;
  45. assign uart_rx_done=uart_rx_done_r;

  46. endmodule
复制代码
UART_TX(数据发送模块设计)

1、数据发送模块:输入发送使能信号和发送数据,通过计数器设置10个数据发送的周期,依次发送起始位+8位数据+1位结束位
  1. <blockquote><font face="微软雅黑"><span style="font-size: 18px;">
  2. </span></font>
复制代码

module uart_top(
  input clk_i,
  input rst_n_i,
  
  input uart_rx_i,
  
  output uart_tx_o
    );
   
wire[7:0]uart_rx_data_o;   //接收数据
wire uart_rx_done;

uart_rx_path rx(
  .clk_i(clk_i),
  .uart_rx_i(uart_rx_i),
  .uart_rx_data_o(uart_rx_data_o),
  .uart_rx_done(uart_rx_done)
);
uart_tx_path tx(
  .clk_i(clk_i),
  .uart_tx_data_i(uart_tx_data_i),
  .uart_tx_en_i(uart_rx_done),
  .uart_tx_o(uart_tx_o)
);

endmodule

相关经验

评论

高级模式
您需要登录后才可以回帖 登录 | 注册

发经验
课程
    关闭

    站长推荐 上一条 /10 下一条

    快速回复 返回顶部 返回列表