Augus

17.菜鸟初入FPGA之Uart发送数据

0
阅读(3328)

UART

Universal

Asynchronous

Receiver/Transmitter

)即

通用异

步收发传输器

工作于数据链路层

(协议层之一)

包含了

RS

232

RS

422

RS

485

串口通信和红外

(IrDA)

等等。

UART

协议作为一

种低速通信协议,

广泛应用于通信领域等各种场合。

UART

基本可分

为并口通信及串口通信两种

UART使用的是 异步,串行通信。
串行通信是指利用一条传输线将资料一位位地顺序传送。特点是通信线路简单,利用简单的线缆就可实现通信,降低成本,适用于远距离通信,但传输速度慢的应用场合。
异步通信以一个字符为传输单位,通信中两个字符间的时间间隔多少是不固定的,然而在同一个字符中的两个相邻位间的时间间隔是固定的。
数据传送速率用波特率来表示,即每秒钟传送的二进制位数。例如数据传送速率为120字符/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。

UART发送一个字节时序图:

2016-04-16_164624.jpg

串口发送模块包含两个主要组件:

1、发送波特率生成模块

2、数据发送模块

串口发送模块整体结构体

2016-04-16_164643.jpg

串口发送模块详细结构图

2016-04-16_164701.jpg


波特率计算:

系统时钟周期为System_clk_period

baud_set

波特率

波特率周期

波特率分频计数值

System_clk_period = 20计数值

0

9600

104167ns

104167/ System_clk_period

5208-1

1

19200

52083ns

52083/ System_clk_period

2604-1

2

38400

26041ns

26041/ System_clk_period

1302-1

3

57600

17361ns

17361/ System_clk_period

868-1

4

115200

8680ns

8680/ System_clk_period

434-1

代码:

module uart_tx( clk, rst_n, data_byte, send_en, baud_set, rs232_tx, tx_done, uart_state ); input clk,rst_n; input [7:0]data_byte; //发送字节 input send_en;//发送控制 input [3:0]baud_set;//波特率选择 output reg rs232_tx;//数据发送 output reg tx_done;//发送完成 output reg uart_state;//是否处于空闲状态 //查找表--比特率选择 reg [15:0]bps_max;//分频计数最大值 always @(posedge clk or negedge rst_n) if(!rst_n) bps_max <= 16'd5207; else begin case (baud_set) 0: bps_max <= 16'd5207; 1: bps_max <= 16'd2603; 2: bps_max <= 16'd1301; 3: bps_max <= 16'd867; 4: bps_max <= 16'd433; default:bps_max <= 16'd5207; endcase end reg [15:0]div_cnt; always @(posedge clk or negedge rst_n) if(!rst_n) div_cnt <= 16'd0; else if(uart_state)begin if(div_cnt == bps_max) div_cnt <= 16'd0; else div_cnt <= div_cnt +1'b1; end else div_cnt <= 16'd0; reg bps_clk;//波特率时钟 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; reg [3:0]bps_cnt; //计数到11,波特率时钟计数器 always @(posedge clk or negedge rst_n) if(!rst_n) bps_cnt <= 4'd0; else if(bps_clk) bps_cnt <= bps_cnt + 1'b1; else if(tx_done) bps_cnt <= 4'd0; 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) 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; reg [7:0]r_data_byte; 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; localparam START_BIT = 1'b0; localparam STOP_BIT = 1'b1; 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 `timescale 1ns/1ns `define clk_period 20 module uart_tx_tb; reg clk; reg rst_n; reg [7:0]data_byte; reg send_en; reg [3:0]baud_set; wire rs232_tx; wire tx_done; wire uart_state; uart_tx uart_tx( .clk(clk), .rst_n(rst_n), .data_byte(data_byte), .send_en(send_en), .baud_set(baud_set), .rs232_tx(rs232_tx), .tx_done(tx_done), .uart_state(uart_state) ); initial clk = 1; always#(`clk_period/2)clk = ~clk; initial begin rst_n = 1'b0; data_byte = 8'd0; send_en = 1'd0; baud_set = 3'd4; #(`clk_period*20 + 1 ) rst_n = 1'b1; #(`clk_period*50); data_byte = 8'haa; send_en = 1'd1; #`clk_period; send_en = 1'd0; @(posedge tx_done) #(`clk_period*5000); data_byte = 8'h55; send_en = 1'd1; #`clk_period; send_en = 1'd0; @(posedge tx_done) #(`clk_period*5000); $stop; end endmodule

2016-04-16_203055.jpg


2016-04-16_203621.jpg


更多资料请参考:

发烧友小梅哥视频教程


Baidu
map