1. 程式人生 > >FPGA UART RX,FPGA設計一個簡單的串列埠接收模組

FPGA UART RX,FPGA設計一個簡單的串列埠接收模組




//UART序列口模組,波特率9600bps
//陳鵬
//20110118

module UART	(
					sys_clk,//系統時鐘輸入
					reset_n,//非同步復位輸入
					Rx,//資料輸入引腳
					NewRxData,//接收到新資料
					RxDATA//RxDATA當前接收的資料
				);
				
	input		sys_clk,reset_n,Rx;
	output	NewRxData;
	output [7 : 0] RxDATA;
	reg [7 : 0] RxDATA;
	
	parameter SYS_CLK = 20000000;//系統時鐘
	parameter Rx_CLK = 9600;//9600bps
	parameter RxDATA_W = 12;//波特率時鐘發生器分頻暫存器位寬
	parameter RXCLK_DATA = SYS_CLK / Rx_CLK - 1;//波特率分頻器時鐘分頻值 (2083)
	
	
	//波特率時鐘發生器
	reg	[RxDATA_W-1 : 0] clk_cnt;
	reg	EN_RXCLK;//使能接收時鐘
	wire	RX_CLK;//接收波特率時鐘
	always @ (posedge sys_clk or negedge reset_n)
		if(!reset_n)
			clk_cnt <= 12'd0;	
		else if(!EN_RXCLK)//不需要使能時鐘
			clk_cnt <= 12'd0;	
		else if(clk_cnt == RXCLK_DATA)
			clk_cnt <= 12'd0;
		else
			clk_cnt <= clk_cnt + 1'b1;
			
	assign RX_CLK = (clk_cnt == RXCLK_DATA/2);//產生接收時鐘
	
	
	//接收資料線下降沿檢測,用來啟動資料接收
	//採用邊沿檢測法,因為資料線空閒位高,起始位位低,因此1幀資料開始有一個下降沿
	reg 	RxThis,RxLast;
	wire	RxStart;
	always @ (posedge sys_clk or negedge reset_n)
		if(!reset_n) begin
			RxThis = 1'b0;
			RxLast = 1'b0;
			end
		else begin
			RxLast <= RxThis;
			RxThis <= Rx;
			end
	
	assign RxStart = RxLast&&(!RxThis);//產生起始訊號 
	
	
	//資料接收控制邏輯
	reg [10 : 0] RxTemp;
	reg [4 : 0]  RxState;
	reg NewRxData;
	always @ (posedge sys_clk or negedge reset_n)
		if(!reset_n) begin
			RxDATA = 8'd0;
			RxTemp = 11'd0;
			RxState = 5'd0;
			EN_RXCLK = 1'b0;//停止接收時鐘
			NewRxData = 1'b0;//去除新資料標誌
			end
		else if((RxState==5'd0) && RxStart)begin//有起始訊號,並且接收器空閒,則再次檢測起始訊號
				EN_RXCLK <= 1'd1;//啟動接收時鐘
				RxState <= 5'b1; //進入接收狀態機
				end
		else if(RX_CLK) begin //每個接收時鐘啟動一次
				case (RxState) //synthesis full_case
					5'd1	:	begin
								RxTemp[0] = Rx;//接收起始位
								RxState <= 5'd2;
								end
					5'd2	:	begin
								RxTemp[1] = Rx;//bit0
								RxState <= 5'd3;
								end
					5'd3	:	begin
								RxTemp[2] = Rx;//bit1
								RxState <= 5'd4;
								end
					5'd4	:	begin
								RxTemp[3] = Rx;//bit2
								RxState <= 5'd5;
								end
					5'd5	:	begin
								RxTemp[4] = Rx;//bit3
								RxState <= 5'd6;
								end
					5'd6	:	begin
								RxTemp[5] = Rx;//bit4
								RxState <= 5'd7;
								end
					5'd7	:	begin
								RxTemp[6] = Rx;//bit5
								RxState <= 5'd8;
								end
					5'd8	:	begin
								RxTemp[7] = Rx;//bit6
								RxState <= 5'd9;
								end
					5'd9	:	begin
								RxTemp[8] = Rx;//bit7
								RxState <= 5'd10;
								end
					5'd10	:	begin
								RxTemp[9] = Rx;//校驗位
								RxState <= 5'd11;
								end
					5'd11	:	begin
								RxTemp[10] = Rx;//結束位,接收完成
								EN_RXCLK <= 1'b0;//停止接收時鐘
								RxState <= 5'd0;//接收進入空閒狀態
								if(!RxTemp[0] && RxTemp[10]) begin//有正確的起始和停止位
									RxDATA <= RxTemp[8 : 1];//儲存接收的資料
									NewRxData = 1'b1;//新資料標誌置位
									end
								end
					endcase
			end //end else if
		else
			NewRxData = 1'b0;//去除新資料標誌
		
endmodule

	
			

串列埠資料大家網上找找,我也是個新手,歡迎交流.