FPGA串口模块

一、串口接收模块

module uart_rx #(
	parameter			CLK_PERIOD = 0,
	parameter			BAUD_RATE = 0,
	parameter			CHECK_MODE = "NONE"
	)(
	input				clk,
	input				rst_n,
	input				rxd,
	output	reg			rx_finish,
	output		[7:0]	data_r
	);
	parameter	BAUD_COUNTER	= 1000_000_000 / CLK_PERIOD / BAUD_RATE;
	parameter	BAUD_COUNTER_HALF	= BAUD_COUNTER / 2;
	reg	[3:0]	rx_num;
	reg			rx_start;
	
	reg	[7:0]	data_temp;
	reg	[7:0]	data_rr;
	
	reg	[7:0]	counter;
	reg			rx_clk_bps;
	
	reg			rxd_r;
	reg			rxd_rr;
	wire		rxd_neg;
	
	reg			check;
	
	assign rxd_neg = !rxd_r && rxd_rr;
	assign data_r = data_rr;
	
	always @(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			rxd_r <= 1'b0;
			rxd_rr <= 1'b0;
		end
		else
		begin
			rxd_r <= rxd;
			rxd_rr <= rxd_r;
		end
	end
	
	always @(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			rx_finish <= 1'b0;
			rx_start <= 1'b0;
		end
		else if(rxd_neg)
		begin
			rx_finish <= 1'b0;
			rx_start <= 1'b1;
		end
		else if((rx_num == 4'd10 && CHECK_MODE == "NONE") || (rx_num == 4'd11 && (CHECK_MODE == "ODD" || CHECK_MODE == "EVEN")))
		begin
			rx_finish <= 1'b1;
			rx_start <= 1'b0;
		end
		else
		begin
			rx_finish <= 1'b0;
			rx_start <= rx_start;
		end
	end
	
	always @(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			counter <= 8'd0;
		end
		else if(counter == BAUD_COUNTER || !rx_start)
		begin
			counter <= 8'd0;
		end
		else
		begin
			counter <= counter + 1'd1;
		end
	end
	
	always @(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			rx_clk_bps <= 1'b0;
		end
		else if(counter == BAUD_COUNTER_HALF)
		begin
			rx_clk_bps <= 1'b1;
		end
		else
		begin
			rx_clk_bps <= 1'b0;
		end
	end
	
	always @(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			rx_num <= 4'd0;
			data_temp <= 8'd0;
			data_rr <= 8'd0;
			//check <= 1'b0;
		end
		else if(rx_start)
		begin
			if(rx_clk_bps)
			begin
				rx_num <= rx_num + 1'd1;
				case(rx_num)
					4'd1:	data_temp[0] <= rxd;
					4'd2:	data_temp[1] <= rxd;
					4'd3:	data_temp[2] <= rxd;
					4'd4:	data_temp[3] <= rxd;
					4'd5:	data_temp[4] <= rxd;
					4'd6:	data_temp[5] <= rxd;
					4'd7:	data_temp[6] <= rxd;
					4'd8:	data_temp[7] <= rxd;
					4'd9:	/*check <= (CHECK_MODE == "ODD" || CHECK_MODE == "EVEN") ? rxd : 1'b0*/;
					default:;
				endcase
			end
			else if((rx_num == 'd10 && CHECK_MODE == "NONE") || (rx_num == 'd11 && (CHECK_MODE == "ODD" || CHECK_MODE == "EVEN")))
			begin
				rx_num <= 4'd0;
				data_rr <= data_temp;
			end
		end
	end

endmodule

二、串口发送模块

module uart_tx #(
	parameter			CLK_PERIOD = 0,
	parameter			BAUD_RATE  = 0,
	parameter			CHECK_MODE = "NONE"
	)(
	input				clk,
	input				rst_n,
	output				txd,
	input				tx_en,
	output				tx_finish,
	input		[7:0]	data_t
    );
	
	parameter	BAUD_COUNTER = 1000_000_000 / CLK_PERIOD / BAUD_RATE;
	
	reg [7:0] 	counter;
	reg	[3:0]	tx_num;
	
	reg			tx_start;
	reg			txd_r;
	reg			tx_finish_r;
	
	reg			tx_en_r;
	reg			tx_en_rr;
	wire		tx_en_pos;
	
	wire		check_odd;
	wire		check_even;
	
	assign txd = txd_r;
	assign tx_finish = tx_finish_r;
	
	assign check_even = data_t[7] + data_t[6] + data_t[5] + data_t[4] + data_t[3] + data_t[2] + data_t[1] + data_t[0];
	assign check_odd = check_even + 1'b1;
	
	assign tx_en_pos = tx_en_r && !tx_en_rr;
	
	always @(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			tx_en_r	<= 1'b0;
			tx_en_rr <= 1'b0;
		end
		else
		begin
			tx_en_r	<= tx_en;
			tx_en_rr <= tx_en_r;
		end
	end
	
	always @(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			tx_start <= 1'b0;
			tx_finish_r	<= 1'b0;
		end
		else if(tx_en_pos)
		begin
			tx_start <= 1'b1;
			tx_finish_r	<= tx_finish_r;
		end
		else if((CHECK_MODE == "ODD" || CHECK_MODE == "EVEN") && tx_num == 'd10 && counter == BAUD_COUNTER - 'd1)
		begin
			tx_start <= 1'b0;
			tx_finish_r <= 1'b1;
		end
		else if((CHECK_MODE == "NONE") && tx_num == 'd9 && counter == BAUD_COUNTER - 'd1)
		begin
			tx_start <= 1'b0;
			tx_finish_r <= 1'b1;
		end
		else
		begin
			tx_start <= tx_start;
			tx_finish_r <= 1'b0;
		end
	end
	
	always @(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			counter	<= 8'd0;
			tx_num <= 4'd0;
		end
		else if(tx_start)
		begin
			if(counter == BAUD_COUNTER - 1'd1)
			begin
				counter <= 8'd0;
				if(CHECK_MODE == "NONE" && tx_num == 4'd9)
				begin
					tx_num <= 4'd0;
				end
				else if((CHECK_MODE == "ODD" || CHECK_MODE == "EVEN") && tx_num == 4'd10)
				begin
					tx_num <= 4'd0;
				end
				else
				begin
					tx_num <= tx_num + 1'd1;
				end
			end
			else
			begin
				counter <= counter + 1'd1;
				tx_num <= tx_num;
			end
		end
		else
		begin
			counter <= 8'd0;
			tx_num <= 4'd0;
		end
	end
	
	always @(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			txd_r <= 1'b1;
		end
		else if(tx_start)
		begin
			if(CHECK_MODE == "ODD" || CHECK_MODE == "EVEN")
			begin
				case(tx_num)
					4'd0:	txd_r <= 1'b0;
					4'd1:	txd_r <= data_t[0];
					4'd2:	txd_r <= data_t[1];
					4'd3:	txd_r <= data_t[2];
					4'd4:	txd_r <= data_t[3];
					4'd5:	txd_r <= data_t[4];
					4'd6:	txd_r <= data_t[5];
					4'd7:	txd_r <= data_t[6];
					4'd8:	txd_r <= data_t[7];
					4'd9:
					begin
						if(CHECK_MODE == "ODD")
							txd_r <= check_odd;
						else
							txd_r <= check_even;
					end
					4'd10:	txd_r <= 1'b1;
					default:txd_r <= 1'b1;
				endcase
			end
			else if(CHECK_MODE == "NONE")
			begin
				case(tx_num)
					4'd0:	txd_r <= 1'b0;
					4'd1:	txd_r <= data_t[0];
					4'd2:	txd_r <= data_t[1];
					4'd3:	txd_r <= data_t[2];
					4'd4:	txd_r <= data_t[3];
					4'd5:	txd_r <= data_t[4];
					4'd6:	txd_r <= data_t[5];
					4'd7:	txd_r <= data_t[6];
					4'd8:	txd_r <= data_t[7];
					4'd9:	txd_r <= 1'b1;
					default:txd_r <= 1'b1;
				endcase
			end
			else
			begin
				txd_r <= 1'b1;
			end
		end
		else
		begin
			txd_r <= 1'b1;
		end
	end
	
endmodule

三、串口顶层模块

module uart_top(
	input			clk,
	input			rst_n,
	
	input			rxd,
	output			txd,
	
	input			tx_en,
	input	[7:0]	data_t,
	output			tx_finish,
	output			rx_finish,
	output	[7:0]	data_r
    );
	
	parameter	CLK_PERIOD	= 20;
	parameter	BAUD_RATE	= 115200;
	parameter	CHECK_MODE	= "ODD";		//校验位及其校验方式("NONE"无校验位,"ODD"奇校验,"EVEN"偶校验)
	
	uart_rx #(
	.CLK_PERIOD		(CLK_PERIOD),
	.BAUD_RATE		(BAUD_RATE),
	.CHECK_MODE		(CHECK_MODE)
	)
	uart_r(
	.clk			(clk),
	.rst_n			(rst_n),
	.rxd			(rxd),
	.rx_finish		(rx_finish),
	.data_r			(data_r)
	);
	
	uart_tx #(
	.CLK_PERIOD		(CLK_PERIOD),
	.BAUD_RATE		(BAUD_RATE),
	.CHECK_MODE		(CHECK_MODE)
	)
	uart_t(
	.clk			(clk),
	.rst_n			(rst_n),
	.txd			(txd),
	.tx_en			(tx_en),
	.tx_finish		(tx_finish),
	.data_t			(data_t)
	);
	
endmodule
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值