UART Verilog詳解

一、UART簡介

UART是通用非同步收發傳輸器(Universal Asynchronous Receiver/Transmitter)的縮寫,它是一種串列通訊介面標準。相比較其他串列通信方式,UART具有性能高、成本低的優點,在單片機、嵌入式系統、計算機外圍設備中被廣泛應用。

UART使用一種非同步方式,即發送數據和接收數據的時鐘不同步,通過指定數據位,停止位,奇偶校驗位等參數,可以保證數據正確無誤地傳輸。

下面我們來詳細了解一下UART的工作原理以及在Verilog中的實現。

二、UART的工作原理

UART的工作原理可以分為兩個階段:

1、發送數據

module uart_tx(
    input clk, //system clock
    input reset, //system reset
    input enable, //tx enable signal
    input [7:0] data_in, //data to be sent
    output tx //tx output signal
);
   ......
endmodule

2、接收數據

module uart_rx(
    input clk, //system clock
    input reset, //system reset
    input enable, //rx enable signal
    input rx, //rx input signal
    output reg [7:0] data_out, //received data
    output reg receive_done //receive done signal
);
   ......
endmodule

三、UART Verilog實現

1、發送數據實現

UART發送數據的核心是將發送的數據按照指定的協議進行封裝,然後通過TX引腳發送出去。

以下是一個基本的UART發送模塊:

module uart_tx(
    input clk, //system clock
    input reset, //system reset
    input enable, //tx enable signal
    input [7:0] data_in, //data to be sent
    output tx //tx output signal
);

    parameter BAUD_RATE = 9600 ; //波特率
    parameter SYS_CLK = 50000000 ; //系統時鐘頻率
    parameter TICK = SYS_CLK / BAUD_RATE ;

    reg [3:0] state ; //狀態機
    reg [7:0] data_reg ; //數據寄存器
    reg [3:0] bit_count ; //計數器
    reg tx_reg ; //TX寄存器

    always@(posedge clk) begin
        if(reset) begin
            state <= 4'd0 ;
            tx_reg <= 1'b1 ; //發送起始位
            data_reg <= 8'h00 ;
            bit_count <= 4'd0 ;
        end else begin
            case(state)
                4'd0 : begin //等待TX越過起始位
                    if(enable) begin
                        state <= 4'd1 ;
                    end
                end
                4'd1 : begin //發送8位數據位
                    tx_reg <= data_in[0] ;
                    data_reg > 1 ;
                    bit_count <= bit_count + 4'd1 ;
                    if(bit_count == 4'd8) begin
                        bit_count <= 4'd0 ;
                        state <= 4'd2 ;
                    end
                 end
                 4'd2 : begin //發送校驗位(這裡使用奇偶校驗)
                    tx_reg <= ~(^data_in) ;
                    bit_count <= bit_count + 4'd1 ;
                    if(bit_count == 4'd1) begin
                        bit_count <= 4'd0 ;
                        state <= 4'd3 ;
                     end
                  end
                  4'd3 : begin //發送停止位
                    tx_reg <= 1'b0 ;
                    bit_count <= bit_count + 4'd1 ;
                    if(bit_count == 4'd1) begin
                        bit_count <= 4'd0 ;
                        state <= 4'd4 ;
                    end
                 end
                 4'd4 : begin //等待下一次發送
                    if(enable) begin
                        state <= 4'd1 ;
                    end
                 end
            endcase
        end
    end

    assign tx = tx_reg ;

endmodule

2、接收數據實現

UART接收數據的核心是按照指定協議從RX引腳接收信號,並解析出數據內容。

一個基本的UART接收模塊如下所示:

module uart_rx(
    input clk, //system clock
    input reset, //system reset
    input enable, //rx enable signal
    input rx, //rx input signal
    output reg [7:0] data_out, //received data
    output reg receive_done //receive done signal
);

    parameter BAUD_RATE = 9600 ; //波特率
    parameter SYS_CLK = 50000000 ; //系統時鐘頻率
    parameter TICK = SYS_CLK / BAUD_RATE ;

    reg [3:0] state ; //狀態機
    reg [7:0] data_reg ; //數據寄存器
    reg [3:0] bit_count ; //計數器
    reg rx_reg ; //RX寄存器
    reg odd_parity ; //奇校驗位判斷

    always@(posedge clk) begin
        if(reset) begin
            state <= 4'd0 ;
            data_reg <= 8'h00 ;
            bit_count <= 4'd0 ;
            rx_reg <= 1'b1 ; //等待起始位
        end else begin
            case(state)
                4'd0 : begin //等待起始位
                    if(~rx & enable) begin
                        state <= 4'd1 ;
                        rx_reg <= rx ;
                        data_reg <= 8'h00 ;
                        bit_count <= 4'd0 ;
                        odd_parity <= 1'b0 ;
                    end
                end
                4'd1 : begin //接收8位數據位
                    rx_reg <= rx ;
                    data_reg <= {data_reg[6:0], rx} ;
                    bit_count <= bit_count + 4'd1 ;
                    odd_parity <= odd_parity ^ rx ; //奇偶校驗
                    if(bit_count == 4'd7) begin
                        state <= 4'd2 ;
                    end
                end
                4'd2 : begin //接收校驗位(這裡使用奇偶校驗)
                    rx_reg <= rx ;
                    odd_parity <= odd_parity ^ rx ; //奇偶校驗
                    bit_count <= bit_count + 4'd1 ;
                    if(bit_count == 4'd1) begin
                        state <= 4'd3 ;
                    end
                end
                4'd3 : begin //接收停止位
                    rx_reg <= rx ;
                    receive_done <= 1'b1 ; //數據接收完成
                    data_out <= data_reg ; //輸出數據
                    if(rx) begin
                        //停止位必須是邏輯0,否則認為停止位錯誤
                        state <= 4'd4 ;
                    end
                end
                4'd4 : begin //等待下一次數據接收
                    receive_done <= 1'b0 ;
                    if(~rx & enable) begin
                        state <= 4'd1 ;
                        rx_reg <= rx ;
                        data_reg <= 8'h00 ;
                        bit_count <= 4'd0 ;
                        odd_parity <= 1'b0 ;
                    end
                end
            endcase
        end
    end

endmodule

四、小結

本文主要介紹了UART通訊的基本原理,以及在Verilog中的實現方式。通過實現發送和接收兩個模塊,我們可以完成對UART通訊協議的實現。同時,我們也需要注意一些細節問題,如如何進行奇偶校驗,如何判斷起始位和停止位等等。這些問題對於保證數據傳輸的正確性非常重要。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/309896.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2025-01-04 19:31
下一篇 2025-01-04 19:31

相關推薦

  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁碟中。在執行sync之前,所有的文件系統更新將不會立即寫入磁碟,而是先緩存在內存…

    編程 2025-04-25
  • 神經網路代碼詳解

    神經網路作為一種人工智慧技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網路的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網路模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web伺服器。nginx是一個高性能的反向代理web伺服器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性感測器,能夠同時測量加速度和角速度。它由三個感測器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變數讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分散式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25

發表回復

登錄後才能評論