FPGA_UART协议理解

FPAG需要与其他设备进行通信,如上位机、传感器、执行器或其他处理器。UART提供了一种简单而广泛支持的通信方式,使FPAG能够与各种外部设备进行数据交换。下面将对UART的特性进行介绍。

1.UART的相关概念

UART全称是通用异步收发器(Universal Asynchronous Receiver-Transmitter)

主要是将数据在串行通信和并行通信间传输转换。简单来说就是将多比特数据在发送端转化为单比特的数据进行传输,或者将多比特转化为单比特的数据进行传输。

串行:即同一时刻只能传输一个数据位的数据

并行:同一时刻可以传输多个数据位的数据

异步:无同步时钟,即UART通常使用异步通信,意味着发送端和接收端的时钟不同步


2.UART的基本工作原理:


串行数据传输:UART通过一个引脚发送和接收数据,这两个引脚分别是TX(发送)和RX(接收)。发送端将要发送的数据转换为串行格式,并将其发送到TX引脚。接收端从RX引脚接收串行数据,并将其转换回并行数据。


帧结构:UART使用一组位来表示每个数据帧。帧通常由起始位、数据位、可选的校验位和停止位组成。起始位指示数据帧的开始,停止位指示数据帧的结束。校验位用于检测数据传输中的错误。

波特率:UART通信的速率由波特率(即数据传输速率)决定。波特率表示每秒传输的位数。发送端和接收端必须以相同的波特率进行通信,以确保数据能够正确传输。常见的波特率有9600Bd,115200Bd。

3.UART的verilog代码实现

以RS232为例,它是UAR的一种,常用于计算机和外部设备之间的数据传输。假设系统时钟50Hz,波特率9600Bd。

50Hz时钟,周期是20ns,1bit计数cnt = 1/9600/20 = 5208,即5208个计数才能发送或接收下一比特数据。

rx端:

1.rx传到FPGA中需要打俩拍,一是为了降低亚稳态,二是获取下降沿,作为开始的标志。

2.rx端在中间时刻采数据最稳定。

module uart_rx(
	input	wire 				clk,
	input	wire 				rst_n,
	input	wire 				rx,
	output	reg 	[7:0]		po_data,
	output	reg 				po_flag
	);

parameter 	CNT_BAUD_MAX = 5207;
parameter	CNT_HALF_BAUD_MAX = 2603;
reg 			rx1,rx2,rx2_reg;
reg 			rx_flag;
reg 	[12:0]	cnt_baud;
reg 			bit_flag;
reg 	[3:0]	bit_cnt;

always @(posedge clk) begin
	{rx2_reg,rx2,rx1}<={rx2,rx1,rx};
end


always @(posedge clk or negedge  rst_n) begin
	if (rst_n == 1'b0) begin
		rx_flag <= 1'b0;
	end
	else if (bit_cnt == 4'd8 && bit_flag == 1'b1) begin
		rx_flag <= 1'b0;
	end
	else if (rx2_reg == 1'b1 && rx2 == 1'b0) begin
		rx_flag <= 1'b1;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		cnt_baud <= 'd0;
	end
	else if (rx_flag == 1'b0) begin
		cnt_baud <= 'd0;
	end
	else if (rx_flag == 1'b1 && cnt_baud == CNT_BAUD_MAX) begin
		cnt_baud <= 'd0;
	end
	else if (rx_flag == 1'b1) begin
		cnt_baud <= cnt_baud + 1'b1;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		bit_flag <= 1'b0;
	end
	else if (rx_flag == 1'b1 && cnt_baud == CNT_HALF_BAUD_MAX) begin
		bit_flag <= 1'b1;
	end
	else begin
		bit_flag <= 1'b0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		bit_cnt <= 'd0;
	end
	else if (bit_flag == 1'b1 && bit_cnt == 'd8) begin
		bit_cnt <= 'd0;
	end
	else if (bit_flag == 1'b1) begin
		bit_cnt <= bit_cnt + 1'b1;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		po_data <='d0;
	end
	else if (bit_cnt >= 4'd1 && bit_flag == 1'b1) begin
		po_data <= {rx2_reg,po_data[7:1]};
	end
end

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin	
		po_flag <= 1'b0;
	end
	else if (bit_cnt == 4'd8 && bit_flag == 1'b1) begin
		po_flag <= 1'b1;
	end
	else begin
		po_flag <= 1'b0;
	end
end
endmodule 

tx端:

module 	uart_tx(
	input	wire	clk,
	input	wire	rst_n,
	input	wire[7:0]	pi_data,
	input	wire		pi_flag,
	output	reg			tx
	);


reg			[7:0]	data_reg;
reg  				tx_flag;
reg 		[12:0]	cnt_baud;
reg 				bit_flag;
reg 		[3:0]	bit_cnt;
parameter  CNT_BAUD_MAX = 5207;
always @(posedge clk or negedge rst_n) begin
	if (rst_n ==1'b0 ) begin
		data_reg <= 'd0;
	end
	else if (pi_flag == 1'b1) begin
		data_reg <= pi_data;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		tx_flag <= 'd0;
	end
	else if (bit_cnt == 'd8 && bit_flag == 1'b1) begin
		tx_flag <= 'd0;
	end
	else if (pi_flag == 1'b1) begin
		tx_flag <= 'd1;
	end

end

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		cnt_baud <= 'd0;
	end
	else if(cnt_baud == CNT_BAUD_MAX&&tx_flag == 1'b1)begin
		cnt_baud <= 'd0;
	end
	else if (tx_flag == 1'b1) begin
		cnt_baud <= cnt_baud + 1'b1;
	end
end
always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		bit_flag <= 'd0;
	end
	else if (cnt_baud == CNT_BAUD_MAX-1&&tx_flag == 1'b1) begin
		bit_flag <= 1'b1;
	end
	else begin
		bit_flag <= 'd0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		bit_cnt <= 'd0;
	end
	else if(bit_cnt == 'd8 && bit_flag == 1'b1) begin
		bit_cnt <= 'd0;
	end
	else if (bit_flag ==1'b1) begin
		bit_cnt <= bit_cnt +1'b1;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		tx <= 'd1;
	end
	else if(pi_flag == 1'b1)begin
		tx <= 'd0;
	end
	else if (bit_flag == 1'b1 && bit_cnt<= 'd7) begin
		tx <= data_reg[bit_cnt];
	end
	else if(bit_flag == 1'b1 && bit_cnt== 'd8)begin
		tx <= 'd1;
	end
end

endmodule

顶层top:

module top_uart(
	input	wire	clk,
	input 	wire	rst_n,
	input	wire	rx,
	output	wire	tx
	);

wire	[7:0]	data;
wire			flag;
	uart_rx inst_uart_rx (
			.clk     (clk),
			.rst_n   (rst_n),
			.rx      (rx),
			.po_data (data),
			.po_flag (flag)
		);


		uart_tx  inst_uart_tx (
			.clk     (clk),
			.rst_n   (rst_n),
			.pi_data (data),
			.pi_flag (flag),
			.tx      (tx)
		);


endmodule

最后可通过modelsim仿真。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值