FPGA之串口收发字符串控制HMI串口屏之(一)——发送模块

1、总体概述

串口通信是一种常见的通信方式。在FPGA中也是比不可少,本专题实现FPGA的串口收发字符串,属于Uart通信,通信方式:串行、异步、全双工的。用verilog实现,包括以下几个模块:串口发送模块、串口接收模块、波特率发生器模块、字符串接收与发送调度模块(可以独立于串口接收模块,这里的输入数据位并行的,主要是为了将要待发送字符串(来自其他模块)进行数据重组(本次的通信外部设备为HMI,其字符串控制指令具有特定的字符串格式))、按键发送字符模块(包含按键消抖模块),以下从各模块及书写和调试中遇到的问题进行详细说明。本次实例实现FPGA控制HMI屏(串口屏),在屏幕上显示相应的字符串数据。

NOTE:异步通信指的是通信的发送与接收方使用各自的时钟控制数据的发送和接收过程,具体就是:以字符(一帧数据)为单位进行传输,字符与字符见的间隙是任意的,但字符内部各bit位是一固定时间传送的(即在固定波特率的控制下进行)。通信的传输方向为全双工,指的时数据可以同时双向传输(实际上感觉这一点的作用并不是太大,因为很多时候不需要同时双向,一般是当接收到某个特定数据时,再向外发送某个数据,这已经暗含了非同时的特点,但它一定有特殊的应用场合)。

2 USART_Send模块

本次收发模块采用的是10bit为一帧数据的传输方式,串口发送模块的数据输入为8位并行数据(数据收入一个时钟周期就完成,速度很快),故需要将接收到的数据进行重组(即加上起始位0和停止位1),随后在波特率的控制下调度数据移位串行输出。发送模块的输入需要一个发送请求脉冲,用于作为启动波特率发生器的标志(控制移位输出)。

代码如下:
主要包括:请求信号到来写入数据、数据移位操作和数据位数计数模块
<请求信号到来写入数据>

/*************请求信号到来写入数据****************/
//请求信号到来,写入数据并置位波特率启动位
always @ (posedge clk, negedge rst_n)
begin
	if (!rst_n)
		tx_bps_start <= 1'b0;
	else if (req_send) 	 	 		  	  	 	    	  	 	 //请求信号有效,将输入写入到datain_buf1中
		tx_bps_start <= 1'b1;                      	 	 //波特率启动标志,直到停止位变为0
	else if (bit_cnt == 4'd10)
		tx_bps_start <= 1'b0;
end

always @ (posedge clk, negedge rst_n)
begin
	if (!rst_n)
		datain_buf1 <= {(PORT_WID + 1){1'b0}};
	else if (req_send)
		datain_buf1 <= {1'b1, datain[7 : 0], 1'b0}; 	 	 //10位数据帧格式,0位起始位,9位停止位;
end

<数据移位操作>

reg 	 	 	 	 	 	 	 dat_flag;
/*************数据移位操作****************/
always @ (posedge clk, negedge rst_n)
begin
	if (!rst_n)
	begin
		datain_buf2 <= {(PORT_WID + 1){1'b0}};
		dat_flag <= 1'b0;
	end
	else if (tx_bps_flag)
	begin
		datain_buf2 <= datain_buf1 >> bit_cnt;
		dat_flag <= 1'b1; 	 	 	 	  	 	 	 	  	 	
	end
	else
		dat_flag <= 1'b0;
end

assign TXD = tx_buf; 
 
assign TI = ti_buf;
always @ (posedge clk, negedge rst_n)
begin
	if (!rst_n)
		ti_buf <= 1'b0;
	else if (bit_cnt == 4'd10)
		ti_buf <= 1'b1;
	else
		ti_buf <= 1'b0;
end

always @ (posedge clk, negedge rst_n)
begin
	if (!rst_n)
		tx_buf <= 1'b1;
	else if (dat_flag) 	  	   	 	 	 		 	 //不是tx_bps_flag一到就赋值给tx_buf,顺延一个周期
		tx_buf <= datain_buf2[0]; 	 		 	 	    //为了避免datain_buf2初始赋值的影响
	else if (!tx_bps_start)
		tx_buf <= 1'b1;
end

<数据位数计数>

/*************数据位数计数****************/
always @ (posedge clk, negedge rst_n)
begin
	if (!rst_n)
		bit_cnt <= {DATA_WID{1'b0}};
	else if (tx_bps_flag)
		bit_cnt <= bit_cnt + 1'b1;
	else if (bit_cnt >= 4'd10)
		bit_cnt <= {DATA_WID{1'b0}};
end

在这里,先附上整个串口和发送程序的时序图,以方便理解。

FPGA之串口收发字符串控制HMI串口屏之(一)——发送模块_第1张图片
这一节先写到这,主要是串口的发送模块,下一节更新接收模块。
NOTE:完整代码连接
https://download.csdn.net/download/huigeyu/11156523
如有需要,请自行下载!

你可能感兴趣的:(FPGA设计开发)