赞
踩
UART(Universal Asynchronous Receiver/Transmitter)是一种通用异步收发器,是计算机与外设之间进行串行通信的一种常见方式。UART能够将数据以比特流的形式从一个设备发送到另一个设备,常用于串行通信接口,如串行通信口(RS-232)。
UART通过将数据分割成字节并在字节之间插入起始位、数据位、校验位和停止位的方式来进行数据传输。它使用异步通信模式,也就是说发送和接收设备的时钟不是同步的。发送方将数据按照固定的格式发送出去,接收方收到数据后,根据起始位和停止位来确定数据的边界,并通过校验位验证数据的准确性。
UART可以在不同的波特率下进行通信,波特率定义了数据传输的速度。常见的波特率有9600、19200、38400等,可以根据需求进行设置。
UART的优点是简单、可靠、灵活,可以适用于各种场景。缺点是通信速度相对较慢,并且需要占用较多的引脚。
加入环回的目的是为了防止在发送的时候同时有接受导致数据的缺失,缺失的主要原因是在发送与接受模块的时序图中最后的结束是半个计数时间。
- `timescale 1ns / 1ps
-
- module uart_rw(
- input sys_clk,
- input sys_rst_n,
- input uart_rxd,
-
- output reg [7:0] uart_data,
- output reg uart_done
- );
-
- parameter CLK_FREQ = 50_000_000;
- parameter UART_BPS = 115200;
-
- localparam BPS_CNT = CLK_FREQ/UART_BPS;
-
- wire start_flag;
-
- reg uart_rxd_d0;
- reg uart_rxd_d1;
- reg rx_flag;
- reg [ 7:0] uart_data_r;
-
- reg [ 3:0] rx_cnt;
- reg [11:0] clk_cnt;
-
- assign start_flag = uart_rxd_d0 & (~uart_rxd_d1);
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n) begin
- uart_rxd_d0 <= 1'b1;
- uart_rxd_d1 <= 1'b1;
- end
- else begin
- uart_rxd_d0 <= uart_rxd;
- uart_rxd_d1 <= uart_rxd_d0;
- end
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- rx_flag <= 1'b0;
- else if(start_flag)
- rx_flag <= 1'b1;
- else if((clk_cnt == BPS_CNT/2) && (rx_cnt == 4'd9))
- rx_flag <= 1'b0;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- clk_cnt <= 12'd0;
- else if(rx_flag) begin
- if(clk_cnt < BPS_CNT - 1)
- clk_cnt <= clk_cnt + 1'b1;
- else
- clk_cnt <= 12'd0;
- end
- else
- clk_cnt <= 12'd0;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- rx_cnt <= 4'd0;
- else if(rx_flag) begin
- if(clk_cnt == BPS_CNT - 1)
- rx_cnt <= rx_cnt + 1'b1;
- end
- else
- rx_cnt <= 4'd0;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- uart_data_r <= 8'd0;
- else if(rx_flag) begin
- if(clk_cnt == BPS_CNT/2) begin
- case(rx_cnt)
- 4'd1:uart_data_r[0] <= uart_rxd_d1;
-
- 4'd2:uart_data_r[1] <= uart_rxd_d1;
-
- 4'd3:uart_data_r[2] <= uart_rxd_d1;
-
- 4'd4:uart_data_r[3] <= uart_rxd_d1;
-
- 4'd5:uart_data_r[4] <= uart_rxd_d1;
-
- 4'd6:uart_data_r[5] <= uart_rxd_d1;
-
- 4'd7:uart_data_r[6] <= uart_rxd_d1;
-
- 4'd8:uart_data_r[7] <= uart_rxd_d1;
- endcase
- end
- end
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n) begin
- uart_data <= 8'd0;
- uart_done <= 1'b0;
- end
- else if(rx_cnt == 4'd9) begin
- uart_data <= uart_data_r;
- uart_done <= 1'b1;
- end
- else begin
- uart_data <= 8'd0;
- uart_done <= 1'b0;
- end
-
- endmodule

- `timescale 1ns / 1ps
-
- module uart_send(
- input sys_clk,
- input sys_rst_n,
- input [7:0] uart_din,
- input uart_en,
-
- output reg uart_txd,
- output uart_tx_busy
- );
-
- parameter CLK_FREQ = 50_000_000;
- parameter UART_BPS = 115200;
-
- localparam BPS_CNT = CLK_FREQ/UART_BPS;
-
- wire en_flag;
-
- reg uart_en_d0;
- reg uart_en_d1;
- reg tx_flag;
- reg [ 7:0] uart_data;
-
- reg [ 3:0] tx_cnt;
- reg [11:0] clk_cnt;
-
- assign en_flag = uart_en_d1 & (~uart_en_d0);
-
- assign uart_tx_busy = tx_flag;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n) begin
- uart_en_d0 <= 1'b0;
- uart_en_d1 <= 1'b0;
- end
- else begin
- uart_en_d0 <= uart_en;
- uart_en_d1 <= uart_en_d0;
- end
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n) begin
- tx_flag <= 1'b0;
- uart_data <= 8'd0;
- end
- else if(en_flag) begin
- tx_flag <= 1'b1;
- uart_data <= uart_din;
- end
- else if((clk_cnt == BPS_CNT - 1) && (tx_cnt == 4'd9)) begin
- tx_flag <= 1'b0;
- uart_data <= 8'd0;
- end
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- clk_cnt <= 12'd0;
- else if(tx_flag) begin
- if(clk_cnt < BPS_CNT - 1)
- clk_cnt <= clk_cnt + 1'b1;
- else
- clk_cnt <= 12'd0;
- end
- else
- clk_cnt <= 12'd0;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- tx_cnt <= 4'd0;
- else if(tx_flag) begin
- if(clk_cnt == BPS_CNT - 1)
- tx_cnt <= tx_cnt + 1'b1;
- end
- else
- tx_cnt <= 4'd0;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- uart_txd <= 1'b1;
- else if(tx_flag) begin
- case(tx_cnt)
- 4'd0:uart_txd <= 1'b0;
- 4'd1:uart_txd <= uart_data[0];
- 4'd2:uart_txd <= uart_data[1];
- 4'd3:uart_txd <= uart_data[2];
- 4'd4:uart_txd <= uart_data[3];
- 4'd5:uart_txd <= uart_data[4];
- 4'd6:uart_txd <= uart_data[5];
- 4'd7:uart_txd <= uart_data[6];
- 4'd8:uart_txd <= uart_data[7];
- 4'd9:uart_txd <= 1'b1;
- endcase
- end
- else
- uart_txd <= 1'b1;
-
- endmodule

- `timescale 1ns / 1ps
-
- module uart_loop(
- input sys_clk,
- input sys_rst_n,
- input tx_busy,
- input [7:0] recv_data,
- input recv_done,
-
- output reg [7:0] send_data,
- output reg send_en
- );
-
- reg uart_rxd_d0;
- reg uart_rxd_d1;
- reg uart_ready;
- wire start_flag;
-
-
- assign start_flag = uart_rxd_d0 & (~uart_rxd_d1);
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n) begin
- uart_rxd_d0 <= 1'b1;
- uart_rxd_d1 <= 1'b1;
- end
- else begin
- uart_rxd_d0 <= recv_done;
- uart_rxd_d1 <= uart_rxd_d0;
- end
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n) begin
- send_data <= 8'd0;
- send_en <= 1'b0;
- uart_ready <= 1'b0;
- end
- else begin
- if(start_flag) begin
- send_data <= recv_data;
- send_en <= 1'b0;
- uart_ready <= 1'b1;
- end
- else if((~tx_busy) && uart_ready)begin
- send_en <= 1'b1;
- uart_ready <= 1'b0;
- end
- end
-
- endmodule

- `timescale 1ns / 1ps
-
- module uart(
- input sys_clk, //系统时钟
- input sys_rst_n, //系统复位,低电平有效
-
- input uart_rxd, //UART接收端口
- output uart_txd
- );
-
- wire [7:0] uart_data;
- wire uart_done;
- wire uart_tx_busy;
- wire [7:0] send_data;
- wire send_en;
-
- uart_rw uart_rw(
- .sys_clk (sys_clk ),
- .sys_rst_n (sys_rst_n ),
- .uart_rxd (uart_rxd ),
-
- .uart_data (uart_data ),
- .uart_done (uart_done )
- );
-
-
- uart_send uart_send(
- .sys_clk (sys_clk ),
- .sys_rst_n (sys_rst_n ),
- .uart_din (send_data ),
- .uart_en (send_en ),
-
- .uart_txd (uart_txd ),
- .uart_tx_busy(uart_tx_busy)
- );
-
- uart_loop uart_loop(
- .sys_clk (sys_clk ),
- .sys_rst_n (sys_rst_n ),
- .tx_busy (uart_tx_busy ),
- .recv_data (uart_data ),
- .recv_done (uart_done ),
-
- .send_data (send_data ),
- .send_en (send_en )
- );
-
-
- endmodule

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。