串口发送接收程序源码

串口接收程序源码:

/***************************************************
*	Module Name		:	uart_rx_logic	   
*	Engineer		:	Huangruigui
*	Target Device	:	
*	Tool versions	:	
*	Create Date		:
*	Revision		:	v1.0
*	Description		:  
**************************************************/
module	uart_rx_logic #(
	parameter	BAUD_SET	= 16'd10416
)(
	input	wire		sys_clk,
	input	wire		sys_rst_n,
	output	reg [7:0]	rx_data,
	output	reg			rx_done,
	input	wire		uart_rx
);

	//	parameter define
	localparam	CLK_DIV_NUM = (100_000_000/BAUD_SET) >> 4;		//	对每一位数据进行16次采样,采中间6位数据进行平均运算

	//	reg define
	reg	[1:0]		uart_rx_r;		//	uart_rx消除亚稳态寄存器
	reg	[1:0]		uart_rx_t;		//	uart_rx寄存器
	reg				en_div_cnt;		//	分频时钟计数器使能信号
	reg	[15:0]		div_cnt;		//	分频时钟计数器
	reg	[8:0]		bps_clk_cnt;	//	波特率时钟计数器
	reg	[2:0]		r_rx_data[7:0];	
	reg [2:0] 		START_BIT,STOP_BIT;

	//	wire define
	wire 			uart_rx_nege;	//	uart_rx下降沿
	wire			bps_clk;		

	//****************************************************
	//	对uart_rx进行消除亚稳态,寄存
	always@(posedge	sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
		begin
			uart_rx_r <= 2'b00;
			uart_rx_t <= 2'b00;
		end 
		else
		begin
			uart_rx_r <= {uart_rx_r[0],uart_rx};
			uart_rx_t <= {uart_rx_t[0],uart_rx_r[1]};
		end 
	end 
	
	assign	uart_rx_nege = uart_rx_t[1] & ~uart_rx_t[0];
	//****************************************************
	
	//	gen baud clk
	always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			div_cnt <= 16'd0;
		else if(en_div_cnt)
		begin
			if(div_cnt >= CLK_DIV_NUM)
				div_cnt <= 16'd0;
			else 
				div_cnt <= div_cnt + 1'b1;
		end 
		else 
			div_cnt <= 16'd0;
	end 
	
	assign	bps_clk = (div_cnt == 16'd1);
	
	always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			bps_clk_cnt <= 9'd0;
		else if((bps_clk_cnt == 9'd159) | (bps_clk_cnt == 9'd12 && (START_BIT>2)))
			bps_clk_cnt <= 9'd0;
		else if(bps_clk)
			bps_clk_cnt <= bps_clk_cnt + 1'b1;
	end 
	
	always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			en_div_cnt <= 0;
		else if((bps_clk_cnt == 9'd159) | (bps_clk_cnt == 9'd12 && (START_BIT>2)))
			en_div_cnt <= 0;
		else if(uart_rx_nege)
			en_div_cnt <= 1;
	end 
	//***********************************************
	
	//	rx_data porcess
	always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			rx_done <= 0;
		else 
			rx_done <= (bps_clk_cnt == 9'd159);
	end 
	//assign	rx_done = (bps_clk_cnt == 9'd159);
	
	always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			rx_data <= 8'd0;
		else if(bps_clk_cnt == 9'd159)
			rx_data[0] <= r_rx_data[0][2];
			rx_data[1] <= r_rx_data[1][2];
			rx_data[2] <= r_rx_data[2][2];
			rx_data[3] <= r_rx_data[3][2];
			rx_data[4] <= r_rx_data[4][2];
			rx_data[5] <= r_rx_data[5][2];
			rx_data[6] <= r_rx_data[6][2];
			rx_data[7] <= r_rx_data[7][2];
	end 
	
	always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)begin
		START_BIT <= 3'd0;
		r_rx_data[0] <= 3'd0;
		r_rx_data[1] <= 3'd0;
		r_rx_data[2] <= 3'd0;
		r_rx_data[3] <= 3'd0;
		r_rx_data[4] <= 3'd0;
		r_rx_data[5] <= 3'd0;
		r_rx_data[6] <= 3'd0;
		r_rx_data[7] <= 3'd0;
		STOP_BIT <= 3'd0;
	end
	else if(bps_clk)begin
		case(bps_clk_cnt)
			0:begin
					START_BIT <= 3'd0;
					r_rx_data[0] <= 3'd0;
					r_rx_data[1] <= 3'd0;
					r_rx_data[2] <= 3'd0;
					r_rx_data[3] <= 3'd0;
					r_rx_data[4] <= 3'd0;
					r_rx_data[5] <= 3'd0;
					r_rx_data[6] <= 3'd0;
					r_rx_data[7] <= 3'd0;
					STOP_BIT <= 3'd0;			
				end
			6,7,8,9,10,11:			START_BIT <= START_BIT + uart_rx_r[1];
			22,23,24,25,26,27:		r_rx_data[0] <= r_rx_data[0] + uart_rx_r[1];
			38,39,40,41,42,43:		r_rx_data[1] <= r_rx_data[1] + uart_rx_r[1];
			54,55,56,57,58,59:		r_rx_data[2] <= r_rx_data[2] + uart_rx_r[1];
			70,71,72,73,74,75:		r_rx_data[3] <= r_rx_data[3] + uart_rx_r[1];
			86,87,88,89,90,91:		r_rx_data[4] <= r_rx_data[4] + uart_rx_r[1];
			102,103,104,105,106,107:r_rx_data[5] <= r_rx_data[5] + uart_rx_r[1];
			118,119,120,121,122,123:r_rx_data[6] <= r_rx_data[6] + uart_rx_r[1];
			134,135,136,137,138,139:r_rx_data[7] <= r_rx_data[7] + uart_rx_r[1];
			150,151,152,153,154,155:STOP_BIT <= STOP_BIT + uart_rx_r[1];
			default:
				begin
					START_BIT <= START_BIT;
					r_rx_data[0] <= r_rx_data[0];
					r_rx_data[1] <= r_rx_data[1];
					r_rx_data[2] <= r_rx_data[2];
					r_rx_data[3] <= r_rx_data[3];
					r_rx_data[4] <= r_rx_data[4];
					r_rx_data[5] <= r_rx_data[5];
					r_rx_data[6] <= r_rx_data[6];
					r_rx_data[7] <= r_rx_data[7];
					STOP_BIT <= STOP_BIT;						
				end
		endcase
	end
	//*********************************************

endmodule
//***************文件结束************************

串口发送程序源码:

/***************************************************
*	Module Name		:	uart_tx_logic	   
*	Engineer		:	Huangruigui
*	Target Device	:	
*	Tool versions	:	
*	Create Date		:
*	Revision		:	v1.0
*	Description		:  
**************************************************/
module	uart_tx_logic #(
	parameter	BAUD_SET		 		= 16'd10416
)(
	input	wire						sys_clk,
	input	wire						sys_rst_n,
	input	wire						tx_en,
	input	wire [7:0]					tx_data,
	output	reg							tx_done,
	output	reg							uart_tx
);

	//	parameter define
	localparam	CLK_DIV_NUM = 100_000_000/BAUD_SET;
	localparam	START_BIT	= 1'b0,
				STOP_BIT	= 1'b1;
	
	//	reg define
	reg				en_div_cnt;
	reg	[15:0]		div_cnt;
	reg	[6:0]		bps_clk_cnt;
	reg	[7:0]		tx_data_t;
	
	//	wire define
	wire			bps_clk;
	
	always@(posedge	sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			tx_data_t <= 0;
		else if(tx_en)
			tx_data_t <= tx_data;			
	end 
	
	always@(posedge	sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			en_div_cnt <= 0;
		else if(tx_en)
			en_div_cnt <= 1;
		else if(tx_done)
			en_div_cnt <= 0;
	end 	
	
	always@(posedge	sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			div_cnt <= 0;
		else if(en_div_cnt)
		begin
			if(div_cnt >= CLK_DIV_NUM)
				div_cnt <= 0;
			else 
				div_cnt <= div_cnt + 1'b1;
		end 
		else 
			div_cnt <= 0;
	end 
	
	assign	bps_clk = (div_cnt == 16'd1);
	
	always@(posedge	sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			bps_clk_cnt <= 0;
		else if(tx_done)
			bps_clk_cnt <= 0;
		else if(bps_clk)
			bps_clk_cnt <= bps_clk_cnt + 1'b1;
	end 
	
	always@(posedge	sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			tx_done <= 0;
		else if(bps_clk_cnt == 4'd11)
			tx_done <= 1'b1;
		else 
			tx_done <= 0;
	end 
	
	always@(posedge	sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			uart_tx <= 1;
		else 
		begin
			case(bps_clk_cnt)
				0: uart_tx <= 1'b1;
				1: uart_tx <= START_BIT;
				2: uart_tx <= tx_data_t[0];
				3: uart_tx <= tx_data_t[1];
				4: uart_tx <= tx_data_t[2];
				5: uart_tx <= tx_data_t[3];
				6: uart_tx <= tx_data_t[4];
				7: uart_tx <= tx_data_t[5];
				8: uart_tx <= tx_data_t[6];
				9: uart_tx <= tx_data_t[7];
				10:uart_tx <= STOP_BIT;
				default:uart_tx <= 1'b1;
			endcase
		end 
	end 
	
endmodule
//**********文件结束****************************

串口发送接收测试程序:

//	串口发送接收模块仿真测试
`timescale	1ns/1ns
module	uart_tx_rx_tb;

	//	parameter define
	localparam	BAUD_SET = 16'd10416;

	reg			sys_clk;
	reg			sys_rst_n;
	reg			tx_en;
	reg	[7:0]	tx_data;
	
	wire		uart_tx;
	wire		rx_done;
	wire [7:0]	rx_data;
	wire		tx_done;

	initial sys_clk = 1;
	always #5 sys_clk = ~sys_clk;
		
	initial begin
		sys_rst_n = 0;
		tx_en = 0;
		tx_data = 0;
		#201;
		sys_rst_n = 1;
		#20;
		@(posedge sys_clk)
		#100;
		repeat(10)
		begin
			tx_en = 1;
			tx_data = tx_data + 1;
			#10;
			tx_en = 0;
			wait(tx_done);
			#100;
		end 
		#1000;
		$stop;
	end 

	uart_rx_logic #(
		.BAUD_SET			(	BAUD_SET		)
	)uart_rx_logic(
		.sys_clk			(	sys_clk			),
		.sys_rst_n			(	sys_rst_n		),
		.rx_done			(	rx_done			),
		.rx_data			(	rx_data			),
		.uart_rx			(	uart_tx			)
	);
	
	uart_tx_logic #(
		.BAUD_SET			(	BAUD_SET		)
	)uart_tx_logic(	
		.sys_clk			(	sys_clk			),
		.sys_rst_n			(	sys_rst_n		),
		.tx_en				(	tx_en			),
		.tx_data			(	tx_data			),
		.tx_done			(	tx_done			),
			
		.uart_tx			(	uart_tx			)
	);
	
endmodule

这两个模块已经验证过了,没什么大问题,各位亲可以放心使用。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值