• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > 基于STEP FPGA的UART串口通信模塊驅動

    基于STEP FPGA的UART串口通信模塊驅動

    作者: 時間:2023-11-29 來源:電子森林 收藏

    硬件說明

    通用異步收發傳輸器(Universal Asynchronous Receiver/Transmitter),通常稱作UART,是一種通用串行數據總線,用于異步通信。該總線雙向通信,可以實現全雙工傳輸和接收。
    異步通信以一個字符為傳輸單位,通信中兩個字符間的時間間隔多少是不固定的,然而在同一個字符中的兩個相鄰位間的時間間隔是固定的。兩個相鄰位間的時間間隔與UART通信的波特率有關,波特率用來表征UART通信中數據傳輸的速率,即每秒鐘傳送的二進制位數。例如數據傳送速率為120字符/秒,而每一個字符為10位(1個起始位,7個數據位,1個校驗位,1個結束位),則其傳送的波特率為10×120=1200字符/秒=1200波特。

    本文引用地址:http://www.czjhyjcfj.com/article/202311/453398.htm

    • 起始位:先發出一個邏輯”0”信號,表示傳輸字符的開始。
    • 數據位:可以是5~8位邏輯”0”或”1”。如ASCII碼(7位),擴展BCD碼(8位)。小端傳輸
    • 校驗位:數據位加上這一位后,使得“1”的位數應為偶數(偶校驗)或奇數(奇校驗)
    • 停止位:它是一個字符數據的結束標志。可以是1位、1.5位、2位的高電平。
    • 空閑位:處于邏輯“1”狀態,表示當前線路上沒有資料傳送。


    我們這里使用的時序為去掉校驗位的時序

    本設計共有四個模塊,一個top模塊,一個baud模塊,一個接收模塊和一個發送模塊,大家可以根據自己的需求進行調整。


    Verilog代碼

    // --------------------------------------------------------------------
    // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
    // --------------------------------------------------------------------
    // Module: Uart_bus
    // 
    // Author: Step
    // 
    // Description: The module for uart communication
    // 
    // 
    // --------------------------------------------------------------------
    // Code Revision History :
    // --------------------------------------------------------------------
    // Version: |Mod. Date:   |Changes Made:
    // V1.0     |2016/04/20   |Initial ver
    // --------------------------------------------------------------------
    module Uart_Bus #
    (
    parameter				BPS_PARA = 1250 //當使用12MHz時鐘時波特率參數選擇1250對應9600的波特率
    )
    (
    input					clk_in,			//系統時鐘
    input					rst_n_in,		//系統復位,低有效
    input					rs232_rx,		//FPGA中UART接收端,分配給UART模塊中的發送端TXD
    output					rs232_tx		//FPGA中UART發送端,分配給UART模塊中的接收端RXD
    );		 /////////////////////////////////UART接收功能模塊例化////////////////////////////////////
    wire					bps_en_rx,bps_clk_rx;
    wire			[7:0]	rx_data; //UART接收波特率時鐘控制模塊 例化
    Baud #
    (
    .BPS_PARA				(BPS_PARA		)
    )
    Baud_rx
    (	
    .clk_in					(clk_in			),	//系統時鐘
    .rst_n_in				(rst_n_in		),	//系統復位,低有效
    .bps_en					(bps_en_rx		),	//接收時鐘使能
    .bps_clk				(bps_clk_rx		)	//接收時鐘輸出
    ); 
    //UART接收數據模塊 例化
    Uart_Rx Uart_Rx_uut
    (
    .clk_in					(clk_in			),	//系統時鐘
    .rst_n_in				(rst_n_in		),	//系統復位,低有效
    .bps_en					(bps_en_rx		),	//接收時鐘使能
    .bps_clk				(bps_clk_rx		),	//接收時鐘輸入
    .rs232_rx				(rs232_rx		),	//UART接收輸入
    .rx_data				(rx_data		)	//接收到的數據
    ); 
     /////////////////////////////////UART發送功能模塊例化////////////////////////////////////
     wire					bps_en_tx,bps_clk_tx; 
     //UART發送波特率時鐘控制模塊 例化
     Baud #
     (
     .BPS_PARA				(BPS_PARA		)
     )
     Baud_tx
     (
     .clk_in					(clk_in			),	//系統時鐘
     .rst_n_in				(rst_n_in		),	//系統復位,低有效
     .bps_en					(bps_en_tx		),	//發送時鐘使能
     .bps_clk				(bps_clk_tx		)	//發送時鐘輸出
     ); 
     //UART發送數據模塊 例化
     Uart_Tx Uart_Tx_uut(.clk_in					(clk_in			),	//系統時鐘
     .rst_n_in				(rst_n_in		),	//系統復位,低有效
     .bps_en					(bps_en_tx		),	//發送時鐘使能
     .bps_clk				(bps_clk_tx		),	//發送時鐘輸入
     .rx_bps_en				(bps_en_rx		),	//因需要自收自發,使用接收時鐘使能判定:接收到新的數據,需要發送
     .tx_data				(rx_data		),	//需要發出的數據
     .rs232_tx				(rs232_tx		)	//UART發送輸出
     ); 
     endmodule
    // --------------------------------------------------------------------
    // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
    // --------------------------------------------------------------------
    // Module: Baud
    // 
    // Author: Step
    // 
    // Description: Beat for uart transfer and receive baud rate
    // 
    // --------------------------------------------------------------------
    // Code Revision History :
    // --------------------------------------------------------------------
    // Version: |Mod. Date:   |Changes Made:
    // V1.0     |2016/04/20   |Initial ver
    // --------------------------------------------------------------------
    module Baud #
    (
    parameter				BPS_PARA = 1250 //當使用12MHz時鐘時波特率參數選擇1250對應9600的波特率
    )
    (
    input					clk_in,		//系統時鐘
    input					rst_n_in,	//系統復位,低有效
    input					bps_en,		//接收或發送時鐘使能
    output	reg				bps_clk		//接收或發送時鐘輸出
    );	 
    reg				[12:0]	cnt;//計數器計數滿足波特率時鐘要求
    always @ (posedge clk_in or negedge rst_n_in) begin
    	if(!rst_n_in) 
    		cnt <= 1'b0;
    	else if((cnt >= BPS_PARA-1)||(!bps_en)) //當時鐘信號不使能(bps_en為低電平)時,計數器清零并停止計數
    		cnt <= 1'b0;						
    		//當時鐘信號使能時,計數器對系統時鐘計數,周期為BPS_PARA個系統時鐘周期
    	else 
    		cnt <= cnt + 1'b1;end //產生相應波特率的時鐘節拍,接收模塊將以此節拍進行UART數據接收
    		always @ (posedge clk_in or negedge rst_n_in)
    	begin
    		if(!rst_n_in) 
    			bps_clk <= 1'b0;
    		else if(cnt == (BPS_PARA>>1)) 	
    		//BPS_PARA右移一位等于除2,因計數器終值BPS_PARA為數據更替時間點,所以計數器中值時為數據最穩定時間點
    			bps_clk <= 1'b1;	
    		else 
    			bps_clk <= 1'b0;
    	end 
    	endmodule
    // --------------------------------------------------------------------
    // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
    // --------------------------------------------------------------------
    // Module: Uart_Rx
    // 
    // Author: Step
    // 
    // Description: The receive module of uart interface
    // 
    // --------------------------------------------------------------------
    // Code Revision History :
    // --------------------------------------------------------------------
    // Version: |Mod. Date:   |Changes Made:
    // V1.0     |2016/04/20   |Initial ver
    // --------------------------------------------------------------------
    module Uart_Rx(input					clk_in,			//系統時鐘
    input					rst_n_in,		//系統復位,低有效 
    output	reg				bps_en,			//接收時鐘使能
    input					bps_clk,		//接收時鐘輸入 
    input					rs232_rx,		//UART接收輸入
    output	reg		[7:0]	rx_data			//接收到的數據
    );	 
    reg	rs232_rx0,rs232_rx1,rs232_rx2;	//多級延時鎖存去除亞穩態
    always @ (posedge clk_in or negedge rst_n_in) begin
    	if(!rst_n_in) begin
    		rs232_rx0 <= 1'b0;
    		rs232_rx1 <= 1'b0;
    		rs232_rx2 <= 1'b0;
    	end else begin
    		rs232_rx0 <= rs232_rx;
    		rs232_rx1 <= rs232_rx0;
    		rs232_rx2 <= rs232_rx1;
    	endend //檢測UART接收輸入信號的下降沿
    	wire	neg_rs232_rx = rs232_rx2 & rs232_rx1 & (~rs232_rx0) & (~rs232_rx);	 
    	reg				[3:0]	num;			//接收時鐘使能信號的控制
    	always @ (posedge clk_in or negedge rst_n_in) begin
    	if(!rst_n_in)
    		bps_en <= 1'b0;
    	else if(neg_rs232_rx && (!bps_en))	
    	//當空閑狀態(bps_en為低電平)時檢測到UART接收信號下降沿,進入工作狀態(bps_en為高電平),控制時鐘模塊產生接收時鐘
    		bps_en <= 1'b1;		
    	else if(num==4'd9)		      		//當完成一次UART接收操作后,退出工作狀態,恢復空閑狀態
    		bps_en <= 1'b0;			
    		end 
    		reg				[7:0]	rx_data_r;//當處于工作狀態中時,按照接收時鐘的節拍獲取數據
    		always @ (posedge clk_in or negedge rst_n_in) begin
    	if(!rst_n_in) begin
    		num <= 4'd0;
    		rx_data <= 8'd0;
    		rx_data_r <= 8'd0;
    	end else if(bps_en) begin	
    		if(bps_clk) begin			
    			num <= num+1'b1;
    			if(num<=4'd8)
    			rx_data_r[num-1]<=rs232_rx;	//先接受低位再接收高位,8位有效數據
    		end else if(num == 4'd9) begin	//完成一次UART接收操作后,將獲取的數據輸出
    			num <= 4'd0;			
    			rx_data <= rx_data_r;	
    		end
    	end
    	end 
    	endmodule
    // --------------------------------------------------------------------
    // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
    // --------------------------------------------------------------------
    // Module: Uart_Tx
    // 
    // Author: Step
    // 
    // Description: The transfer module of uart interface
    // 
    // --------------------------------------------------------------------
    // Code Revision History :
    // --------------------------------------------------------------------
    // Version: |Mod. Date:   |Changes Made:
    // V1.0     |2016/04/20   |Initial ver
    // --------------------------------------------------------------------
    module Uart_Tx
    (
    input					clk_in,			//系統時鐘
    input					rst_n_in,		//系統復位,低有效
    output	reg				bps_en,			//發送時鐘使能
    input					bps_clk,		//發送時鐘輸入
    input					rx_bps_en,		
    //因需要自收自發,使用接收時鐘使能判定:接收到新的數據,需要發送
    input			[7:0]	tx_data,		//需要發出的數據
    output	reg				rs232_tx		//UART發送輸出
    ); 
    reg						rx_bps_en_r;//延時鎖存接收時鐘使能信號
    always @ (posedge clk_in or negedge rst_n_in) begin
    	if(!rst_n_in) rx_bps_en_r <= 1'b0;
    	else rx_bps_en_r <= rx_bps_en;end //檢測接收時鐘使能信號的下降沿,因為下降沿代表接收數據的完成,以此作為發送信號的激勵
    	wire	neg_rx_bps_en = rx_bps_en_r & (~rx_bps_en); 
    	reg				[3:0]	num;
    	reg				[9:0]	tx_data_r;	//根據接收數據的完成,驅動發送數據操作
    	always @ (posedge clk_in or negedge rst_n_in) begin
    	if(!rst_n_in) begin
    		bps_en <= 1'b0;
    		tx_data_r <= 8'd0;
    	end else if(neg_rx_bps_en)begin	
    		bps_en <= 1'b1;						
    		//當檢測到接收時鐘使能信號的下降沿,表明接收完成,需要發送數據,使能發送時鐘使能信號
    		tx_data_r <= {1'b1,tx_data,1'b0};	
    	end else if(num==4'd10) begin	
    		bps_en <= 1'b0;	//一次UART發送需要10個時鐘信號,然后結束
    	endend //當處于工作狀態中時,按照發送時鐘的節拍發送數據
    	always @ (posedge clk_in or negedge rst_n_in) begin
    	if(!rst_n_in) begin
    		num <= 1'b0;
    		rs232_tx <= 1'b1;
    	end else if(bps_en) begin
    		if(bps_clk) begin
    			num <= num + 1'b1;
    			rs232_tx <= tx_data_r[num];
    		end else if(num>=4'd10) 
    			num <= 4'd0;	
    	end
    	end 
    	endmodule

    小結

    本節主要為大家講解了UART通信的原理及軟件設計,需要大家掌握的同時自己創建工程,通過整個設計流程,生成FPGA配置文件加載測試。



    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 边坝县| 诸暨市| 丹东市| 沙坪坝区| 永宁县| 琼结县| 江门市| 西藏| 永顺县| 广灵县| 孟津县| 抚顺县| 宜兰市| 宁国市| 什邡市| 揭东县| 上思县| 泌阳县| 客服| 夹江县| 长葛市| 峨眉山市| 常山县| 乌审旗| 常宁市| 静安区| 建水县| 东安县| 万山特区| 舒城县| 桃江县| 云安县| 哈巴河县| 乌鲁木齐县| 德化县| 永年县| 宿州市| 门头沟区| 长寿区| 南京市| 灵川县|