串口发送模块与验证

在当今的电子系统中,需要板内、板间或下位机与上位机之间进行数据的发送与接收,需要双方共同遵循一定的通信协议来保证数据传输的正确性。常见的协议有UART(Universal Asynchronous Receiver/Transmitter,通用异步收发传输器)、IIC(继承电路总线)、SPI(串行外围总线)、USB2.0/3.0(通用串行总线)以及Ethernet(以太网)等。最为基础的是UART。

UART在数据发送时将并行数据转换成串行数据来传输,在数据接收时将接收到的串行数据转换成并行数据,可以实现全双工传输和接收。UART是异步串行通信的总称。RS232、RS449、RS423、RS422和RS485等,是对应各种异步串行通信口的接口标准和总线标准,他们规定了通信口的电器特性、传输速率、连接特性和接口的机械特性等内容。

在RS-232标准中,一个完整的字节包括一位起始位、8位数据位、一位停止位总共十位数据来算,要想完整的实现这十位数据的发送,需要11个波特率时钟脉冲,第1个脉冲标记一次传输的起始,第11个脉冲标记一次传输的结束。

串口发送模块与验证

 BPS_CLK信号的第一个上升沿到来时,字节发送模块开始发送起始位,接下来的2到9个上升沿,发送8个数据位,第10个上升沿到第11个上升沿为停止位的发送。

本节要学习UART通信的原理及硬件电路设计,使用FPGA实现UART通信中的数据发送部分设计。在仿真验证时除进行正常的功能仿真以外,使用ISSP进行板级验证,具体方法是:输入需要通过串口发送出去的数据,通过按下AC620开发板上的按键来控制FPGA将待发送的数据发送出去,在串口助手中查看PC端接收到的数据。

串口发送模块包含两个主要组件:发送波特率生成模块;数据发送模块。将BPS_CLK信号与对应位对应起来。
 

串口发送模块与验证

下图中的逻辑电路图相对应的代码,这个电路结构是有优先级的,若Send_En为1,就不会执行else if和else语句了。

串口发送模块与验证

(1)这个模块的设计是为了模块的复用性。当需要不同的波特率时,只需设置不同的波特率时钟计数器的计数值,使用查找表即可实现。

 

串口发送模块与验证

串口发送模块与验证

	reg [15:0]bps_DR;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		bps_DR <= 16'd5207;
	else begin
		case(baud_set)
			0:bps_DR <= 16'd5207;
			1:bps_DR <= 16'd2603;
			2:bps_DR <= 16'd1301;
			3:bps_DR <= 16'd867;
			4:bps_DR <= 16'd433;
			default:bps_DR <= 16'd5207;
		endcase
	end

 

 

(2)计数器模块,注意有个使能端

串口发送模块与验证

	reg [15:0]div_cnt;
	reg en_cnt;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		div_cnt <= 16'd0;
	else if(en_cnt)
		begin
			if(div_cnt == bps_DR)
				div_cnt <= 16'd0;
			else
				div_cnt <= div_cnt + 1'b1;
		end
	else
		div_cnt <= 16'd0;

(3)产生bps_clk

 

串口发送模块与验证

	reg bps_clk;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		bps_clk <= 1'b0;
	else if(div_cnt == 16'd1)
		bps_clk <= 1'b1;
	else
		bps_clk <= 1'b0

(4)计数到11

串口发送模块与验证

	reg [3:0]bps_cnt;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		bps_cnt <= 4'd0;
	else if(clr)
		bps_cnt <= 4'd0;
	else if(bps_clk)
		bps_cnt <= bps_cnt + 1'b1;
	else
		bps_cnt <= bps_cnt;

(4)tx_done信号的生成

串口发送模块与验证

	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		Tx_done <= 1'b0;
	else if(bps_cnt == 4'd11)
		Tx_done <= 1'b1;
	else
		Tx_done <= 1'b0;

(5)数据传输

串口发送模块与验证

//在发送数据的过程中,必须保证数据是稳定的
//一旦检测到发送使能信号,将待发送数据寄存起来,使用一个寄存器寄存daya_byte信号
	reg [7:0]r_data_byte;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		r_data_byte <= 8'd0;
	else if(Send_en)
		r_data_byte <= data_byte;
	else
		r_data_byte <= 8'd0
	
	localparam START_BITE = 1'b0;
	localparam STOP_BIT = 1'b1;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		Rs232_Tx <= 1'b1;
	else 
		begin
			case(bps_cnt)
				0:Rs232_Tx <= 1'b1;
				1:Rs232_Tx <= START_BITE;
				2:Rs232_Tx <= r_data_byte[0];
				3:Rs232_Tx <= r_data_byte[1];
				4:Rs232_Tx <= r_data_byte[2];
				5:Rs232_Tx <= r_data_byte[3];
				6:Rs232_Tx <= r_data_byte[4];
				7:Rs232_Tx <= r_data_byte[5];
				8:Rs232_Tx <= r_data_byte[6];
				9:Rs232_Tx <= r_data_byte[7];
				10:Rs232_Tx <= STOP_BIT;
				default: Rs232_Tx <= 1'b1;
			endcase
		end

(6)

串口发送模块与验证

	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		uart_state <= 1'b0;
	else if(send_en)
		uart_state <= 1'b1;
	else if(Tx_done)
		uart_state <= 1'b0;
	else
		uart_state <= uart_state;

 

 

 

 

 

 

 

 

 

 

 

 

 

上一篇:ZYNQ PL系列(二)vivado与modelsim的联合仿真


下一篇:异步bus交互(二)— 握手协议(1)