串口收发模块设计

2021-04-15 10:47:19 浏览数 (2)

该串口收发模块有串口发送模块,串口接收模块,波特率生成模块,发送数据fifo模块,接收数据的fifo模块组成。

默认配置下,要求输入的参考时钟为50MHz,输入输出的波特率默认配置为115200.该设置体现在波特率生成模块中。

整体的设计框架如下:

端口定义如下:

端口名

方向

描述

Clk

Input

主时钟,默认频率为50MHz

Rst_n

Input

复位信号,低有效

RsRx

Input

串口接收端口

RSTx

Output

串口发送端口

Tx_data_in[7:0]

Input

tx端要发送的1字节数据

Rx_data_out[7:0]

output

rx端口接收到的1字节数据

Tx_wen

Input

发送数据的写入使能信号

Rx_ren

Input

接收数据的读取使能信号

Uart_irq

output

串口中断信号,为高时标志着rx接收到了有效的数据

该模块的使用:

发送数据

将要发送的数据放置到Tx_data_in[7:0]总线上,同时将Tx_wen置为高,下一个时钟时,该数据会写进tx_fifo中。如要发送多字节数据,则重复上述步骤,每个时钟向TX_FIFO中发送一个字节的数据,tx_fiof的默认深度为256,可以储存256个字节的数据,则一次最多可以发送256字节数据。

接收数据

接收到一个字节的有效数据时,该字节立即在Rx_data_out[7:0]端口输出,此时中断信号Uart_irq为高时,读取输出端口的数据,同时将Rx_ren置一个时钟的高电平即可 。 。

1,波特率计数模块

在波特率生成模块中,生成发送和接收数据的采样时钟,该采样时钟为波特率的16倍频时钟。count_reg 是分频计数器。27为波特率设置为115200时的时钟分频参数。

设置一个可配置参数 Baud_rate,便可以再顶层例化模块中通过该参数来改变串口的波特率。参数值和对应的波特率如下表所示。默认情况下,配置参数为6,对应的波特率设置为115200.

分频计数器的参数计算如下:

分频参数 = 主时钟频率/(波特率*16)。

设置为其他常用波特率时,该参数的值为下表:

波特率

计算的分频参数

实际的分频参数

配置参数

1200

2604.2

2604

1

2400

1302.1

1302

2

4800

651.0

651

3

9600

325.5

325

4

38400

81.4

81

5

115200

27.1

27

6

2,fifo模块

tx_fifo和rx_fifo 都是例化的自定义的fifo模块。该fifo模块预留有参数接口,可以通过改变该参数来改变fifo的深度和数据宽度。

fifo模块用于临时储存串口发送和接收的数据,进行跨时钟预的数据储存。若不使用fifo来暂存数据,由于串口发送数据相对缓慢,则要连续发送多个字节的数据时,必须等待上一个字节发送完成后才能发送下一个字节,则主模块便要不断等待。使用fifo后,便可以将连续多个字节的数据一次性发送到fifo中,发送模块便会自动读取fifo中的数据进行发送,主模块便可以空闲。

接收模块的fifo同理。将接收到的多个数据暂时储存在fifo中,在读取时便可以一次性连续读取多个字节的数据。

当往fifo中写入数据时,写入的第一个字节的数据就会在R_out[7:0]端口输出。将rd信号置高时,读指针指向下一个地址,在下一个时钟将输出下一个字节数据。

fifo模块的配置参数和端口定义如下:

定义了一个名为array_reg的内存阵列,该内存阵列的储存深度由参数AWIDTH决定,储存的深度等于 2^AWIDTH.fifo的数据宽度等于DWIDTH。

在串口模块例化该fifo模块时,将AWIDTH配置为8,DWIDTH也配置为8。即例化了一个数据宽度为8,储存深度为256的fifo模块。

发送数据fifo:

要通过tx端口向其他串口设备发送数据,首先将要发送的数据放置到Tx_data_in[7:0]总线上,同时将Tx_wen置为高,下一个时钟时,该数据会写进tx_fifo中。如要发送多字节数据,则重复上述步骤,每个时钟向TX_FIFO中发送一个字节的数据,tx_fiof的默认深度为64,可以储存64个字节的数据,则一次最多可以发送64字节数据。当数据储存到TX_FIFO中后,fifo的空标志位(empty)不等于零,令发送模块的开发发送标志位(tx_start)等于 ~empty,则当fifo内储存有要发送的数据时,tx_start信号为1,此时,发送模块从TX_FIFO中读取一字节的数据。待这一字节的数据发送完成后,继续读取fifo内储存的下一个发送数据。直至将fifo内储存的数据全部读取完后,empty等于1,tx_start等于0,发送模块不再发送数据。

接收数据fifo:

当接收到rx端口的有效数据时,接收到的数据会临时储存在rx_fifo中,第一个字节的数据就会在Rx_data_out[7:0]端口输出。中断信号 uart_irq 时rx_fifo的空标志位的取反,此时中断信号 uart_irq 为高,标志这接收到了有效的数据。此时将Rx_ren置为高,读指针指向下一个数据的地址,在下一个时钟将输出下一个字节数据。连续将Rx_ren置为高,则可读出储存在rx_fifo中的接收到的数据,并从Rx_data_out[7:0]端口输出,直到fifo中的数据被读完。

故当tx_fifo里每接收到一个数据时,中断信号为高即标志着接收到了数据,同时在接收到的数据就在Rx_data_out[7:0]端口输出。如果每接收到一个有效数据就立即读取,则必须同时发送一个周期的Rx_ren高信号,使得读地址指针指向下一个读地址,以便当接收到新的数据时,也能立即输出。

如果等待接收多个字节的数据才读取的话,此时输出端口直接输出第一个字节的地址,当将Rx_ren信号置高时,每一个时钟输出一个接收到的数据,直到fifo中的数据被读完。

3,发送模块

发送模块的端口如下:

当 信号 tx_start 为高时,该模块将此时端口 d_in[7:0]输入的数据按照预定的波特率将该字节的数据从端口tx发送出去, 波特率时钟 b_tick 指定了该模块的波特率。等到该字节数据发送完成后,tx_done信号被置为一个时钟的高电平。tx_done信号连接到tx_fifo的读端口,当tx_done为高时,fifo的读指针指向下一个地址,如果下一个地址还储存有数据,输出端口输出储存在下一个地址中的数据,同时empty信号为0,串口发送模块将继续发送数据。当下一个地址还没有数据时,empty输出为高,数据发送停止。

4,接收模块

接收模块的端口如下:

当该模块从rx端口接收到一个有效的字节数据后,rx_done会置高一个时钟,同时接收到的数据从端口dout[7:0]输出。rx_done连接到rx_fifo的写使能端口,接收到的数据将写入到rx_fifo中。

5,模块测试

通过电脑端串口向FPGA发送数据,FPGA端RX模块接收到数据后再将该数据通过串口在发送到电脑端。

我们连续发送了字符串“123”,在接收端也同样接收到了字符串“123”。

这是接收到的三个字符采样得到的时序图。

如下图,当接收到一个字节数据后,uart_irq信号会置高,同时接收到的数据就立刻在rx_data_out[7:0]端口输出。然后将rx_ren信号置高一个时钟,让读地址指针指向下一个地址,则当再次接收到一个新的数据时,该数据也能马上输出。

0 人点赞