【FPGA】UART串口通信
文章目录
- 一、通信方式
- 1.串行通信
- 2.并行通信
- 二、UART串口通信
- 1.模块设计与时序图
- 2.代码实现
- 三、测试结果
- 1.仿真结果
- 2.上板验证
一、通信方式
1.串行通信
串行通信是指利用一条传输线将数据一位位地顺序传送。(也就是说串行通信传输的数据是1比特1比特的传送的)
常见串行通信接口
串行通信优点是传输距离远、占用资源少。
串行通信缺点是发送速度慢。
2.并行通信
并行是指多比特数据同时通过并行线进行传送,这样数据传送速度大大提高。
但并行传送的线路长度受到限制,因为长度增加,干扰就会增加,数据也就容易出错。
并行通信优点是发送速度快。
并行通信缺点是传输距离短、资源占用多。
二、UART串口通信
UART是一种异步全双工通信方式
1.模块设计与时序图
uart_tx模块时序图
uart_rx模块时序图
2.代码实现
uart.v(顶层模块)
module uart
(input clk ,input rst_n ,input u_rx ,output u_tx
);wire [7:0] data ;
wire start ;uart_rx uart_rx(.clk (clk) ,.rst_n (rst_n) ,.data (data) ,.start (start) ,.u_rx (u_rx)
);uart_tx uart_tx(.clk (clk) ,.rst_n (rst_n) ,.data (data) ,.start (start) ,.u_tx (u_tx)
);endmodule
uart_tx
module uart_tx
#(parameter BAUD_MAX = 5208,parameter BAUD_FLAG = 1
)
(input clk ,input rst_n ,input [7:0] data ,input start ,output reg u_tx
);reg [14:0] baud_cnt ;
reg [4:0] bit_cnt ;reg data_state ;
reg bit_flag ;
reg done ;always @(posedge clk or negedge rst_n) beginif(!rst_n)data_state <= 1'b0 ;else if(start)data_state <= 1'b1 ;else if(done)data_state <= 1'b0 ;elsedata_state <= data_state ;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)baud_cnt <= 1'b0 ;else if(data_state)beginif(baud_cnt == BAUD_MAX - 1)baud_cnt <= 1'b0 ;elsebaud_cnt <= baud_cnt + 1'b1 ;endelsebaud_cnt <= 1'b0 ;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)bit_flag <= 1'b0 ;else if(baud_cnt == BAUD_FLAG)bit_flag <= 1'b1 ;elsebit_flag <= 1'b0 ;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)bit_cnt <= 1'b0 ;else if(bit_flag)beginif(bit_cnt == 9)bit_cnt <= 1'b0 ;elsebit_cnt <= bit_cnt + 1'b1 ;endelsebit_cnt <= bit_cnt ;
endalways @(posedge clk or negedge rst_n) begin if(!rst_n)u_tx <= 1'b1 ; else if(bit_flag)begincase(bit_cnt)0 : u_tx <= 1'b0 ;1 : u_tx <= data[0] ;2 : u_tx <= data[1] ;3 : u_tx <= data[2] ;4 : u_tx <= data[3] ;5 : u_tx <= data[4] ;6 : u_tx <= data[5] ;7 : u_tx <= data[6] ;8 : u_tx <= data[7] ;9 : u_tx <= 1'b1 ;default : u_tx <= 1'b1 ;endcaseendelseu_tx <= u_tx ;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)done <= 1'b0 ;else if(bit_cnt == 9 && bit_flag)done <= 1'b1 ;elsedone <= 1'b0 ;
endendmodule
uart_rx
module uart_rx
#(parameter BAUD_MAX = 5208,parameter BAUD_FLAG = 2604
)
(input clk ,input rst_n ,input u_rx ,output reg start ,output reg [7:0] data
);reg u_rx0 ;
reg u_rx1 ;
reg u_rx2 ;reg [14:0] baud_cnt ;
reg [4:0] bit_cnt ;reg data_state ;
reg bit_flag ;
reg done ;always @(posedge clk or negedge rst_n) beginif(!rst_n)beginu_rx0 <= 1'b1 ;u_rx1 <= 1'b1 ;u_rx2 <= 1'b1 ;endelse beginu_rx0 <= u_rx ;u_rx1 <= u_rx0 ;u_rx2 <= u_rx1 ;end
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)data_state <= 1'b0 ;else if((!u_rx1) && (u_rx2))data_state <= 1'b1 ;else if(done)data_state <= 1'b0 ;elsedata_state <= data_state ;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)baud_cnt <= 1'b0 ;else if(data_state)beginif(baud_cnt == BAUD_MAX - 1)baud_cnt <= 1'b0 ;elsebaud_cnt <= baud_cnt + 1'b1 ;endelsebaud_cnt <= 1'b0 ;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)bit_flag <= 1'b0 ;else if(baud_cnt == BAUD_FLAG)bit_flag <= 1'b1 ;elsebit_flag <= 1'b0 ;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)bit_cnt <= 1'b0 ;else if(bit_flag)beginif(bit_cnt == 9)bit_cnt <= 1'b0 ;elsebit_cnt <= bit_cnt + 1'b1 ;endelsebit_cnt <= bit_cnt ;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)data <= 8'b00000000 ;else if(bit_flag)begin case(bit_cnt)0 : data <= data ;1 : data[0] <= u_rx2 ;2 : data[1] <= u_rx2 ;3 : data[2] <= u_rx2 ;4 : data[3] <= u_rx2 ;5 : data[4] <= u_rx2 ;6 : data[5] <= u_rx2 ;7 : data[6] <= u_rx2 ;8 : data[7] <= u_rx2 ;9 : data <= data ;default : data <= data ;endcaseendelsedata <= data ;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)done <= 1'b0 ;else if(bit_cnt == 9 && bit_flag)done <= 1'b1 ;elsedone <= 1'b0 ;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)start <= 1'b0 ;elsestart <= done ;
endendmodule
uart_tb
`timescale 1ps/1psmodule uart_tb();reg clk ;
reg rst_n ;reg u_rx ;
wire u_tx ;uart u_uart
(.clk (clk) ,.rst_n (rst_n) ,.u_rx (u_rx) ,.u_tx (u_tx)
);initial beginclk = 1;forever#10clk=~clk;
endinitial beginrst_n = 1;#10;rst_n = 0;#20;rst_n = 1;
endparameter TIMEPERIOD = 20;initial beginu_rx = 1'b1;#200//发送起始位u_rx = 1'd0;#(5027*TIMEPERIOD);//发送数据0u_rx = 1'd1;#(5027*TIMEPERIOD);//发送数据1u_rx = 1'd0;#(5027*TIMEPERIOD);//发送数据2u_rx = 1'd0;#(5027*TIMEPERIOD);//发送数据3u_rx = 1'd0;#(5027*TIMEPERIOD);//发送数据4u_rx = 1'd0;#(5027*TIMEPERIOD);//发送数据5u_rx = 1'd1;#(5027*TIMEPERIOD);//发送数据6u_rx = 1'd0;#(5027*TIMEPERIOD);//发送数据7u_rx = 1'd0;#(5027*TIMEPERIOD);//发送结束位u_rx = 1'd1;#(100000*TIMEPERIOD);$stop ;
endendmodule