anti-iliteracy02_uart发送与接收

在lab04中决定对其代码进行好好的复盘,这几天也将uart的传输原理搞的七七八八。
在此记录,积极输出是为了更多的输入。

UART 原理 principle

  • UART:universal asynachronous receiver/transmitter,通用异步收发传输器

  • 其在数据发送时将并行数据转换为串行数据来传输,在数据接收时将串行数据转换为并行数据来接受,实现全双工传输和接收。

  • 包括了RS232,RS449,RS423,RS422,RS485等接口标准规范和总线标准规范。换句话说,UART是通用异步串行通信的总称,而RS232等是对应各种异步串行通信口的借口标准和总线标准,他们规定了通信口的电气特性、传输速率、连接特性和接口的机械特性等内容。

  • UART 通信在使用前需要做多项设置,最常见的设置包括数据位数、波特率大小、奇偶校验类型和停止位数。

    按照一个完整的字节包括一位起始位、8位数据位、一位停止位即总共十位数据来算,要想完整的实现这十位数据的发送,就需要11个波特率时钟脉冲。

    第1个脉冲标记一次传输的起始,第11个脉冲标记一次传输的结束。
    在这里插入图片描述

UART模块 module

uart_tx 发送

  • 波特率时钟生成(系统时钟计数值= 1/(bps*sys_clk_period) -1)
  • 数据输出模块
    • 通过对波特率时钟进行计数,来确定数据发送的循环状态
    • 传输结束产生一个byte传送结束的信号
    • 对输入数据进行寄存(打两拍来同步数据)
  • 数据传输状态控制
    -根据bps_cnt传输共10位bit数
module uart_byte_tx(
 Clk,       //50M时钟输入
 Rst_n,     //模块复位
 data_byte, //待传输8bit数据
 send_en,   //发送使能
 baud_set, //波特率设置
 
 Rs232_Tx,  //Rs232输出信号
 Tx_Done,   //一次发送数据完成标志
 uart_state //发送数据状态
);

 input Clk;
 input Rst_n;
 input [7:0]data_byte;
 input send_en;
 input [2:0]baud_set;
 
 output reg Rs232_Tx;
 output reg Tx_Done;
 output reg uart_state;
 
 reg bps_clk; //波特率时钟
 reg [15:0]div_cnt;//分频计数
 reg [15:0]bps_DR;//分频计数最大值
 reg [3:0]bps_cnt;//波特率时钟计数器
 reg [7:0]r_data_byte;
 
 localparam START_BIT = 1'b0;
 localparam STOP_BIT = 1'b1;
  always@(posedge Clk or negedge Rst_n)
 if(!Rst_n)
  uart_state <= 1'b0;
 else if(send_en)
  uart_state <= 1'b1;
 else if(Tx_Done)
  uart_state <= 1'b0;
 else
  uart_state <= uart_state;
 
 always@(posedge Clk or negedge Rst_n)
 if(!Rst_n)
  r_data_byte <= 8'd0;
 else if(send_en)
  r_data_byte <= data_byte;
 else
  r_data_byte <= r_data_byte;
 
 always@(posedge Clk or negedge Rst_n)
 if(!Rst_n)
  bps_DR <= 16'd5207;
 else begin
  case(baud_set)
   0:bps_DR <= 16'd5207;
   1:bps_DR <= 16'd2603;
   2:bps_DR <= 16'd1301;
   3:bps_DR <= 16'd867;
   4:bps_DR <= 16'd433;
   default:bps_DR <= 16'd5207;   
  endcase
 end 
 
  //counter
 always@(posedge Clk or negedge Rst_n)
 if(!Rst_n)
  div_cnt <= 16'd0;
 else if(uart_state)begin
  if(div_cnt == bps_DR)
   div_cnt <= 16'd0;
  else
   div_cnt <= div_cnt + 1'b1;
 end
 else
  div_cnt <= 16'd0;
 
 // bps_clk gen
 always@(posedge Clk or negedge Rst_n)
 if(!Rst_n)
  bps_clk <= 1'b0;
 else if(div_cnt == 16'd1)
  bps_clk <= 1'b1;
 else
  bps_clk <= 1'b0;
 
 //bps counter
 always@(posedge Clk or negedge Rst_n)
 if(!Rst_n) 
  bps_cnt <= 4'd0;
 else if(Tx_Done)
  bps_cnt <= 4'd0;
 else if(bps_clk)
  bps_cnt <= bps_cnt + 1'b1;
 else
  bps_cnt <= bps_cnt;
  
 always@(posedge Clk or negedge Rst_n)
 if(!Rst_n)
  Tx_Done <= 1'b0;
 else if(bps_cnt == 4'd11)
  Tx_Done <= 1'b1;
 else
  Tx_Done <= 1'b0;
  
 always@(posedge Clk or negedge Rst_n)
 if(!Rst_n)
  Rs232_Tx <= 1'b1;
 else begin
  case(bps_cnt)
   0:Rs232_Tx <= 1'b1;
   1:Rs232_Tx <= START_BIT;
   2:Rs232_Tx <= r_data_byte[0];
   3:Rs232_Tx <= r_data_byte[1];
   4:Rs232_Tx <= r_data_byte[2];
   5:Rs232_Tx <= r_data_byte[3];
   6:Rs232_Tx <= r_data_byte[4];
   7:Rs232_Tx <= r_data_byte[5];
   8:Rs232_Tx <= r_data_byte[6];
   9:Rs232_Tx <= r_data_byte[7];
   10:Rs232_Tx <= STOP_BIT;
   default:Rs232_Tx <= 1'b1;
  endcase
 end 

endmodule

uart_rx 接收

  • 串行输入信号同步设计
    • 同步寄存器(消除亚稳态)
    • 数据寄存器(为了定义下降沿)
  • 采样时钟生成
    • 实际采样频率是波特率的16倍
    • 系统时钟计数值=1/(bpssys_clk_period16) -1
  • 采样数据接收模块设计
  • 数据状态判定模块设计

【注】:全文参考小梅哥FPGA自学笔记3.10/3.11

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值