(一)FPGA之串口通信(UART)

本文详细介绍了FPGA如何实现UART串口通信,包括波特率的计算、串口协议的各个组成部分,以及Verilog代码实现的接收和发送模块。通过实例展示了如何在50MHz系统时钟下,处理9600bps波特率的数据传输,包括起始位、数据位、校验位和停止位的识别与处理。同时,提供了仿真代码以验证设计的正确性。
该文章已生成可运行项目,

(一)FPGA之串口通信(UART)

回到梦开始的地方,如今回过头来看串口协议,确实清晰了很多,但是奈何好记性不如烂笔头,我还是要重新记录一下学习的知识点,方便查找和学习。
波特率(Band Rate):
串口协议中很重要的一点就是波特率,波特率的概念是每秒钟传送码元的个数,就是一秒钟传输了几个二进制的个数,他的单位是Bit/s和bps两种。常见的串口速度有115200bps 9600bps等等,串口(RS232)的最大传输速率是 115200bps,表示一秒钟传输了115200个二进制 。
波特率和字节的关系
1GB=1024MB
1MB=1024KB
1KB=1024B(字节)

我们需要串口接收的数据数每秒512字节,串口的波特率是115200位/秒

波特率115200=115200(位/秒)

如果没有校验位,就应该除以10,得到的是每秒字节数:波特率115200=115200(位/秒)=11520(字节/秒)

再除以1024,就是每秒KB数:波特率115200=115200(位/秒)=11.25(KB/秒)也就是满足每秒可以接收512字节。

**在Verilog代码中,我们只需要理解计算这两个值就可以完成串口代码的梳理,**假设我们FPGA使用的是50MHZ的系统时钟 波特率使用的是9600bps 传输一个bit需要的时钟周期个数是50_000_000/9600个个数,得到个数之后再用这个个数乘以周期的时间便是传输1bit需要的时间50_000_000/9600*20便是1bit需要的时间。

Uart通信协议

1.串口通信的信号线只需要两条线就可以完成,TX和RX TX发送端 RX为接收端。
2.起始位,数据线从高变低,低有效为0,数据传输开始。
3.数据位,起始位传输之后便是数据位开始,一般为8位,传输时低位(LSB)在前,高位(MSB)在后。
4.校验位,校验位可以认为是一个特殊的数据位,通常使用的是奇偶校验,使用串口协议时通常取消奇偶校验位。
5.停止位,停止位高有效为1,他表示这一个个字节传输结束。
6.位时间,起始位、数据位、校验位的位宽度是一致的,停止位有0.5位、1位、1.5位格式,一般为1位。
7.空闲位,持续的高电平。
7.帧:从起始位开始到停止位结束的时间间隔称之为一帧。
在这里插入图片描述

接受模块

首先约定波特率为9600(可变),无校验位
将数据线打两拍,防止亚稳态并捕获其的下降沿信号(起始位0)
检测到下降沿后拉高数据传输标志,意味着数据开始接收;并在传输第九个数据(终止位1)的正中(数据比较稳定)将数据传输标志拉低,意味着数据接收完成
对时钟进行计数,每一个周期(在设定波特率条件下传输一位所需要的时间)对数据线进行采样并将数据寄存,同时记录传输个数(记录当前共接收了多少个数据)
接收到第九个数据(终止位1)后,拉高接收完成标志位
————————————————

module uart_rx(
	input 			sys_clk,			//50M系统时钟
	input 			sys_rst_n,			//系统复位
	input 			uart_rxd,			//接收数据线
	output reg 		uart_rx_done,		//数据接收完成标志
	output reg [7:0]uart_rx_data		//接收到的数据
);
//常量化波特率,可更改
parameter	BPS=9600;					//波特率9600bps,可更改
parameter	SYS_CLK_FRE=50_000_000;		//50M系统时钟
localparam	BPS_CNT=SYS_CLK_FRE/BPS;	//传输一位数据所需要的时钟个数
 
reg 			uart_rx_d0;		//寄存1拍
reg 			uart_rx_d1;		//寄存2拍
reg [15:0]		clk_cnt;				//时钟计数器
reg [3:0]		rx_cnt;					//接收计数器
reg 			rx_flag;				//接收标志位
reg [7:0]		uart_rx_data_reg;		//数据寄存
	
wire 			neg_uart_rx_data;		//数据的下降沿
 
assign	neg_uart_rx_data=uart_rx_d1 & (~uart_rx_d0);  //捕获数据线的下降沿,用来标志数据传输开始
//将数据线打两拍,作用1:同步不同时钟域信号,防止亚稳态;作用2:用以捕获下降沿
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		uart_rx_d0<=1'b0;
		uart_rx_d1<=1'b0;
	end
	else begin
		uart_rx_d0<=uart_rxd;
		uart_rx_d1<=uart_rx_d0;
	end		
end
//捕获到数据下降沿(起始位0)后,拉高传输开始标志位,并在第9个数据(终止位)的传输过程正中(数据比较稳定)再将传输开始标志位拉低,标志传输结束
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)
		rx_flag<=1'b0;
	else begin 
		if(neg_uart_rx_data)
			rx_flag<=1'b1;
		else if((rx_cnt==4'd9)&&(clk_cnt==BPS_CNT/2))//在第9个数据(终止位)的传输过程正中(数据比较稳定)再将传输开始标志位拉低,标志传输结束
			rx_flag<=1'b0;
		else 
			rx_flag<=rx_flag;			
	end
end
//时钟每计数一个BPS_CNT(传输一位数据所需要的时钟个数),即将数据计数器加1,并清零时钟计数器
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		rx_cnt<=4'd0;
		clk_cnt<=16'd0;
	end
	else if(rx_flag)begin
		if(clk_cnt<BPS_CNT-1'b1)begin
			clk_cnt<=clk_cnt+1'b1;
			rx_cnt<=rx_cnt;
		end
		else begin
			clk_cnt<
本文章已经生成可运行项目
FPGA串口开发有其特定的流程。般性的FPGA开发流程可作为基础,包括设计输入(创建FPGA工程,添加如HDL文件等设计源文件)、设计综合(将HDL源文件转译为特定结构的设计网表)、约束输入(指定时序、布局布线等设计要求)、设计仿真(对FPGA工程进行功能或时序验证)、设计实现(将逻辑设计转译为可下载烧录到目标FPGA器件的特定物理文件格式)、分析实现结果(对设计性能进行分析)、设计优化(修改设计源文件等以达到设计最优化)、板级调试(生成比特流并下载到开发板上进行调试)等步骤,且存在很多迭代过程 [^1]。 在应用方面,FPGA在JESD204B高速串行接口协议中有应用。JESD204B协议在FPGA应用中的优点包括减少了PCB布板空间(通过高速串行接口减少了器件之间的走线数量)、降低了走线匹配要求(消除了建立与保持时序约束问题)、简化了高速转换器数据接口的实施(通过帧串行数据链路时钟和对齐字符简化了接口设计) [^2]。 ### FPGA串口开发代码示例(简单的串口发送示例,Verilog语言) ```verilog module uart_tx ( input wire clk, input wire rst_n, input wire [7:0] data_in, input wire send_en, output reg tx_out ); // 波特率计数器参数 parameter BAUD_RATE = 9600; parameter CLK_FREQ = 50000000; parameter BAUD_DIV = CLK_FREQ / BAUD_RATE; reg [12:0] baud_cnt; reg [3:0] bit_cnt; reg [9:0] tx_data; reg sending; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin baud_cnt <= 0; bit_cnt <= 0; tx_data <= 0; sending <= 0; tx_out <= 1; end else begin if (send_en && !sending) begin tx_data <= {1'b1, data_in, 1'b0}; sending <= 1; bit_cnt <= 0; baud_cnt <= 0; end if (sending) begin if (baud_cnt == BAUD_DIV - 1) begin baud_cnt <= 0; if (bit_cnt < 10) begin tx_out <= tx_data[bit_cnt]; bit_cnt <= bit_cnt + 1; end else begin sending <= 0; tx_out <= 1; end end else begin baud_cnt <= baud_cnt + 1; end end end end endmodule ```
评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGA资料库

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值