FPGA零基础学习之UART驱动教程

时间:2025-11-01  作者:Diven  阅读:0

UART即通用异步收发器,是通用串行数据总线,用于异步通信。该总线为双向通信,可以实现数据的接收与发送。

FPGA零基础学习之UART驱动教程

在数据传输过程中,我们需要解释一下串行通信。假设现在我们传输数据的双方为A和B,每次传输8bit数据,这8bit的数据在传输时按照A与B之间的连线分为串行通信和并行通信。串行通信即A与B之间仅有一根数据线,在传输数据时需要一次发送1bit,总共发送8次。并行通信即A与B之间有8根线,传输数据时,将8bit数据通过8根线一起传输,这样一次就可以全部传输完成。

数据传输时,接收方和发送方使用的时钟不是同一个时钟域,这也就是异步传输。

在通信双方传输数据之前,需要通过串口线进行连接,然后再传输数据,常用的串口线为DB9接口,但是由于这种接口体积大,不易携带等缺点而慢慢淘汰。我们在B04的开发板上使用到的是一个USB转串口的芯片,这样我们的MINI USB接口不仅可以给开发板供电,还可以进行串口数据传输。芯片为CP2102(USB <-->UART(LVCMOS/LVTTL)),对于开发者来说,就不需要关注电平标准了。

芯片电路图如图所示:

在电路图中我们可以发现,串口接口只有两根数据线,分别为RXD和TXD。那么在进行通信之前,我们需要先了解一下串口的传输规则。

在发送者没有发送数据时,接收方如果一直接收数据,那就会导致数据出错,所以,接收方在接收数据时需要有标志信号,然后启动接收。在我们的串口协议中是这样规定的:

1、空闲态数据线上为高电平。

2、发送数据时,先发送起始位,逻辑电平为低。

3、起始位结束之后,发送8bit数据,从低位开始传输。

4、数据传输完毕,是1bit的校验位,采用奇偶校验法。(可不使用)

5、停止位,为高电平,可以是1bit、1.5bit或者2bit。

那么我们清楚了数据传输规则之后,我们还需要明白一个内容,那就是1bit数据的时间长度。在算这个时间之前,我们需要了解一下波特率。波特率的单位是bit/s,也就是1秒时间内,传输的bit数。我们串口常用的波特率有9600、14400、19200等等。这个波特率是传输数据的双方,提前规定好的。那么在同一速度下传输数据,就会简单很多。那么根据波特率我们可以计算出来1bit数据的时长为104166ns。在清楚这些之后,接下来我们做一个回环测试。

首先我们先新建一个工程:

选好代码存放位置,修改工程名字为uart。

选择我们的芯片型号:XC7A35TFGG484-2。

新建好工程后,开始新建文件写代码。

点击OK,顶层文件新建完成,后续各个模块新建方式相同。接收代码如下:

 

1 Module uart_rx(2 3 input wire clk,4 input wire rst_n,5 input wire RXD,6 output reg [7:0] data,7 output reg wr_en8 );9 10 parameter t = 5208;1112 reg [14:0] cnt;13 reg flag;14 reg rxd_r, rxd_rr;15 wire rx_en;16 reg [3:0] num;17 reg [7:0] data_r;18 19 always @ (posedge clk) rxd_r <= RXD;20 always @ (posedge clk) rxd_rr <= rxd_r;21 22 assign rx_en = (~rxd_r) & rxd_rr;23 24 always @ (posedge clk, negedge rst_n)25 begin26 if(rst_n == 1'b0)27 cnt <= 15'd0;28 else if(flag)29 begin30 if(cnt == t - 1)31 cnt <= 15'd0;32 else33 cnt <= cnt + 1'b1;34 end35 else36 cnt <= 15'd0;37 end38 39 always @ (posedge clk, negedge rst_n)40 begin41 if(rst_n == 1'b0)42 flag <= 1'b0;43 else if(rx_en)44 flag <= 1'b1;45 else if(num == 4'd10)46 flag <= 1'b0;47 else48 flag <= flag;49 end50 51 always @ (posedge clk, negedge rst_n)52 begin53 if(rst_n == 1'b0)54 num <= 4'd0;55 else if(cnt == t / 2 - 1)56 num <= num + 1'b1;57 else if(num == 4'd10)58 num <= 4'd0;59 else60 num <= num;61 end62 63 always @ (posedge clk, negedge rst_n)64 begin65 if(rst_n == 1'b0)66 begin67 data_r <= 8'd0;68 data <= 8'd0;69 end70 else if(cnt == t / 2 - 1)71 case(num)72 4'd0 : ;73 4'd1 : data_r[0] <= rxd_rr;74 4'd2 : data_r[1] <= rxd_rr;75 4'd3 : data_r[2] <= rxd_rr;76 4'd4 : data_r[3] <= rxd_rr;77 4'd5 : data_r[4] <= rxd_rr;78 4'd6 : data_r[5] <= rxd_rr;79 4'd7 : data_r[6] <= rxd_rr;80 4'd8 : data_r[7] <= rxd_rr;81 4'd9 : data <= data_r;82 default : data <= data;83 endcase84 end85 86 always @ (posedge clk, negedge rst_n)87 begin88 if(rst_n == 1'b0)89 wr_en <= 1'b0;90 else if(num == 4'd10)91 wr_en <= 1'b1;92 else93 wr_en <= 1'b0;94 end9596 endModule

 

发送数据时,跟接收基本类似,按照数据格式发送数据,代码如下:

 

1 module uart_tx(2 3 input wire clk,4 input wire rst_n,5 input wire empty,6 input wire [7:0] data,7 output wire rd_en,8 output reg TXD9 );10 11 parameter t = 5208;1213 reg [14:0] cnt;14 reg flag;15 reg [3:0] num;16 17 18 always @ (posedge clk, negedge rst_n)19 begin20 if(rst_n == 1'b0)21 cnt <= 15'd0;22 else if(flag)23 begin24 if(cnt == t - 1)25 cnt <= 15'd0;26 else27 cnt <= cnt + 1'b1;28 end29 else30 cnt <= 15'd0;31 end32 33 always @ (posedge clk, negedge rst_n)34 begin35 if(rst_n == 1'b0)36 flag <= 1'b0;37 else if(empty == 1'b0)38 flag <= 1'b1;39 else if(num == 4'd10)40 flag <= 1'b0;41 else42 flag <= flag;43 end44 45 always @ (posedge clk, negedge rst_n)46 begin47 if(rst_n == 1'b0)48 num <= 4'd0;49 else if(cnt == t / 2 - 1)50 num <= num + 1'b1;51 else if(num == 4'd10)52 num <= 4'd0;53 else54 num <= num;55 end56 57 assign rd_en = (num == 4'd0 && cnt == 15'd1) ? 1'b1 : 1'b0;58 59 always @ (posedge clk, negedge rst_n)60 begin61 if(rst_n == 1'b0)62 TXD <= 1'b1;63 else if(cnt == t / 2 - 1)64 case(num)65 4'd0 : TXD <= 1'b0;66 4'd1 : TXD <= data[0];67 4'd2 : TXD <= data[1];68 4'd3 : TXD <= data[2];69 4'd4 : TXD <= data[3];70 4'd5 : TXD <= data[4];71 4'd6 : TXD <= data[5];72 4'd7 : TXD <= data[6];73 4'd8 : TXD <= data[7];74 4'd9 : TXD <= 1'b1;75 default : TXD <= 1'b1;76 endcase77 end7879 endmodule

 

其中读使能我们只需在数据发送前将数据读出即可。

在做完两个模块之后,我们还需要使用一个FIFO来做数据缓存,FIFO配置参数如下:

我们使用异步FIFO,深度选择2048,位宽为8,复位信号暂时不使用。

生成FIFO后,将各个模块例化到顶层当中,代码如下:

 

1 module uart(2 3 input wire clk,4 input wire rst_n,5 input wire RXD,6 output wire TXD7 );8 9 wire [7:0] rx_data;10 wire wr_en;11 wire rd_en;12 wire [7:0] tx_data;13 wire empty;14 15 uart_rx uart_rx_inst(16 17 .clk (clk ),18 .rst_n (rst_n),19 .RXD (RXD ),20 .data (rx_data),21 .wr_en (wr_en)22 );23 24 fifo fifo_inst (25 .wr_clk(clk), // input wire wr_clk26 .rd_clk(clk), // input wire rd_clk27 .din(rx_data), // input wire [7 : 0] din28 .wr_en(wr_en), // input wire wr_en29 .rd_en(rd_en), // input wire rd_en30 .dout(tx_data), // output wire [7 : 0] dout31 .full(), // output wire full32 .empty(empty) // output wire empty33 );34 35 uart_tx uart_tx_inst(36 37 .clk (clk ),38 .rst_n (rst_n ),39 .empty (empty ),40 .data (tx_data),41 .rd_en (rd_en ),42 .TXD (TXD )43 );4445 endmodule

 

功能部分写完之后,我们写一个仿真进行逻辑验证,写仿真时,我们按照数据顺序模拟给值,每1bit持续104166ns的时间。代码如下:

 

1 `timescale 1ns / 1ps2 3 module uart_tb;4 5 reg clk;6 reg rst_n;7 reg RXD;8 wire TXD;9 10 initial begin11 clk = 0;12 rst_n = 0;13 RXD = 1;14 #105;15 rst_n = 1;16 17 #1000;18 RXD = 0;19 #104166;20 21 RXD = 1;22 #104166;23 RXD = 0;24 #104166;25 RXD = 1;26 #104166;27 RXD = 0;28 #104166;29 RXD = 1;30 #104166;31 RXD = 0;32 #104166;33 RXD = 0;34 #104166;35 RXD = 1;36 #104166;37 38 RXD = 1;39 #104166;40 41 #5000;42 $stop;43 end44 45 always #10 clk = ~clk;46 47 uart uart_inst(48 49 .clk (clk ),50 .rst_n (rst_n ),51 .RXD (RXD ),52 .TXD (TXD )53 );54 55 endmodule

 

打开仿真波形:

如图,我们可以看到,当我们的接收模块接收到数据时,会将数据写入FIFO,FIFO中有数据时,发送模块就会将数据读出并发送,仿真现象正确。

下板现象:

我们随便写入几个数据,会发现我们的发送模块和接收模块的数据完全一致,即接收和发送正常。


审核编辑:刘清

猜您喜欢

电阻器作为基本且关键的元件,其性能直接关系到整个电路的稳定性和可靠性。Walsin(华新)作为知名的电子元器件制造商,其金属膜电阻系列凭借高精度、高稳定性和优异...
2016-12-26 06:21:30

合金电阻因其优异的性能被应用于各种电子设备中。肇庆英达作为国内知名的合金电阻制造商,其产品以稳定的电压参数和高品质,受到众多客户的青睐。本文将围绕“肇庆英达合金...
2022-08-16 17:44:40

防浪涌电阻作为保护电子设备免受电压波动损害的关键元件,其重要性不言而喻。而“富之光”(FUJICON)作为该领域的佼佼者,其品牌归属地自然成为业界关注的焦点。本...
2015-01-26 18:59:41

音频接口芯片是音频设备中的核心组件,负责将音频信号转换为数字信号,或将数字信号转换为音频信号。根据应用和功能,音频接口芯片可以分为几种主要类型。模拟音频接口芯片...
2009-05-27 00:00:00

电子设备和电气工程中,接触电阻和结壳热阻是两个重要的概念。直接影响着设备的性能和可靠性。了解这两者之间的关系,有助于优化设备的设计和提高其工作效率。本文将详细探...
2025-03-18 00:01:07

电子设备维修和DIY领域,经常需要对电路元件进行替换,而MOS管作为一种常见的功率半导体器件,其替换也有一定的讲究,尤其是同步整流MOS管。本文将为您提供一个快...
2024-05-11 00:00:00

手机配件是提升手机使用体验的重要组成部分,种类繁多,主要可以分为以下几类。首先是保护类配件,包括手机壳、保护膜等。这些配件可以有效防止手机在日常使用中受到刮擦和...
2009-10-28 00:00:00

PLC是一种工业电脑,因此,它的结构和电脑类似。PLC硬件主要由中央处理单元、存储器、输入单元、输出单元、电源单元、编程器、扩展接口、编程器接口和存储器接口组成...
2019-07-29 17:47:00

在选择电流传感器或磁传感器时,规格尺寸是一个关键因素。不同类型的传感器在应用领域和安装方式上存在差异,因此了解尺寸规格非常重要。电流传感器通常有多种尺寸可供选择...
2010-02-10 00:00:00

创业是什么?创新是什么?8月,四方光电股份有限公司(以下简称“四方光电”)董事长熊友辉博士坦言,是冒险、是承担责任,是继往圣开来学,是永远要有假想敌。21世纪...
2023-08-28 10:45:00