FPGA_UART

1.UART 概述?(通用異步收發傳輸器)


1. 基本定義

UART(Universal Asynchronous Receiver/Transmitter)是一種常見的串行通信協議,用于在設備間通過異步串行通信傳輸數據。它不依賴獨立的時鐘信號,而是通過預定義的波特率(Baud Rate)?同步數據的收發。?核心特點

  • 異步通信:無需共享時鐘信號,僅通過數據線傳輸。
  • 全雙工模式:收發雙方可同時發送和接收數據(需獨立TX、RX線)。
  • 靈活配置:支持自定義波特率、數據位長度、校驗位、停止位等。

2. 工作原理

(1) 數據傳輸格式

每一幀數據包含以下部分(以典型8N1格式為例):

起始位數據位(8位)校驗位(可選)停止位(1位)
1位,低電平LSB先發奇偶校驗(可選)1位,高電平
  • 起始位:低電平(0)表示數據傳輸開始。
  • 數據位:傳輸的有效數據(5~9位),通常低位(LSB)先發送(如用戶之前的案例)。
  • 校驗位:用于簡單錯誤檢測(奇校驗/偶校驗/無校驗)。
  • 停止位:高電平(1)表示一幀數據結束,并允許接收端校準時序。

(2) 異步同步機制

  • 波特率校準:收發雙方必須使用相同的波特率(如115200、9600)。 例如:

復制

波特率115200 → 每位持續時間 ≈ 1/115200 ≈ 8.68μs

  • 數據采樣:接收端在起始位下降沿觸發,并在數據位中間點采樣,抵消時鐘偏移影響。

3. 典型應用場景

  • 微控制器與外圍模塊通信:如ESP8266(Wi-Fi)、GPS模塊、傳感器(溫濕度)。
  • 調試接口:通過UART輸出調試信息(常見于嵌入式開發板)。
  • 有線設備互聯:舊式打印機、工業設備(如Modbus RTU協議)。
  • 信號轉換:結合電平轉換芯片(如MAX232)實現RS232、RS485等長距離通信。

4. 優缺點分析

優點缺點
硬件簡單(僅需兩根數據線)傳輸距離短(通常<1米)
成本低(無需復雜協議棧)無硬件錯誤恢復機制(需軟件糾錯)
廣泛兼容性(幾乎所有MCU支持)需嚴格匹配波特率(誤差<3%)

5. 硬件實現關鍵點

  • 發送端(TX)
    • 將并行數據轉為串行,按波特率逐位發送。
    • 使用分頻器生成波特率時鐘(如50MHz主頻 → 115200波特率需分頻系數:50e6 / 115200 ≈ 434)。
  • 接收端(RX)
    • 檢測起始位下降沿,啟動同步采樣。
    • 通過移位寄存器重組串行數據為并行數據。

6. 常見問題與解決方案

  • 波特率失配: 若收發波特率差超過3%,會導致采樣偏移,需重新校準。
  • 電磁干擾: 長距離使用需加屏蔽線或轉換為差分信號(如RS485)。
  • 數據沖突: 全雙工通信需避免同時發送,可通過流控信號(RTS/CTS)解決。

7. 主流擴展協議

  • RS-232:電平標準(±3~15V),支持更長距離(<15米)。
  • RS-485:差分信號,可多點通信(工業現場總線)。
  • USB轉UART:通過芯片(如CH340、CP2102)實現USB與串口無縫銜接。

2.verilog編寫

? ?這里需要講解下,這里使用到50mhz的時鐘, 波特率為115200,這里的50mhz的時鐘是在1秒內有50_000_000個周期的數據,波特率115200是在1秒內有115200bit的傳輸。

? ?50_000_000/115200? 指的是傳輸1bit需要傳輸多少個時鐘周期

在寫測試代碼的時候,#8680 是因為 在?50_000_000/115200= 434 個時鐘周期傳輸1bit, 而434個時鐘周期每個時鐘周期為20ns 434*20= 8680.

1,波形圖

接收和發送都根據這個圖編寫就行

2.1接收模塊代碼

module uart_rx (
input          clk,
input          rst,
input          rx_en,
input          data_in,
output reg [7:0]  data_out,
output         uart_rx_done
);localparam   CLK   =  50_000_000,BOTE  = 115200,CNT   = CLK / BOTE ;reg             rx_en_d1;
reg             rx_en_d2;
reg             rx_flag ;
reg             rx_valid;
reg   [3:0]     rx_cnt  ;
reg  [15:0]     clk_cnt ;
reg  [7:0]      data_out_r;
reg             uart_rx_done_r;assign       uart_rx_done = uart_rx_done_r;always @(posedge clk or negedge rst )beginif (rst == 1'b1)beginrx_en_d1 <= 1'b0;rx_en_d2 <= 1'b0;endelse beginrx_en_d1 <= rx_en;rx_en_d2 <= rx_en_d1;end
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)rx_flag <= 1'b0;else if (rx_en_d1 == 1'b1 && rx_en_d2 == 1'b0)rx_flag <= 1'b1;else rx_flag <= 1'b0;
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)rx_valid <= 1'b0;else if (rx_cnt == 4'd9 && clk_cnt == CNT /2 )rx_valid <= 1'b0;else if (rx_flag == 1'b1)rx_valid <= 1'b1;else;
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)clk_cnt <= 16'd0;else if (clk_cnt == CNT )clk_cnt <= 16'd0;else if (rx_valid == 1'b1)clk_cnt <= clk_cnt +1'b1;else clk_cnt <= 16'd0;
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)rx_cnt <= 4'd0;else if (rx_en_d1 == 1'b1 && rx_en_d2 == 1'b0)rx_cnt <= 4'd0;else if (clk_cnt == CNT) rx_cnt <= rx_cnt +1'b1;else;
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)uart_rx_done_r <= 1'b0;else if (rx_valid == 1'b1) beginif (rx_cnt == 4'd9)uart_rx_done_r <= 1'b1;else uart_rx_done_r <= 4'd0;endelseuart_rx_done_r <= 1'b0;
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)data_out_r <= 8'd0;else if (rx_valid == 1'b1   ) beginif (clk_cnt == CNT /4) case (rx_cnt )4'd1  : data_out_r[0] = data_in ; 4'd2  : data_out_r[1] = data_in ; 4'd3  : data_out_r[2] = data_in ; 4'd4  : data_out_r[3] = data_in ; 4'd5  : data_out_r[4] = data_in ; 4'd6  : data_out_r[5] = data_in ; 4'd7  : data_out_r[6] = data_in ; 4'd8  : data_out_r[7] = data_in ; default : ;endcaseelse data_out_r <= data_out_r;endelse data_out_r <= 8'd0;  endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)data_out <= 8'd0;else if (rx_cnt == 4'd9)data_out <= data_out_r;else data_out <= 8'd0;
endendmodule 

?2.2發送模塊代碼

module uart_tx(
input           clk,
input           rst,input           tx_en,
input   [7:0]   data_din,
output          data_out,
output          uart_tx_done );
localparam  CLK  = 50_000_000, //時鐘 50_000_000 一秒 50000000個時鐘周期 數據 波特率 9600 一秒9600個數據bit  5000000/9600 一個bit需要多少時鐘周期 BOTE =115200,  CNT  = CLK /BOTE ;reg          tx_en_d1;
reg          tx_en_d2;
reg          start_flag;
reg          tx_valid;
reg [3:0]    tx_cnt;
reg [15:0]   clk_cnt;
reg          uart_done_r;
reg          uart_dout_r;
reg  [7:0]   data_din_r;assign     data_out  = uart_dout_r;
assign     uart_tx_done = uart_done_r;always @ (posedge clk or negedge rst) beginif (rst == 1'b1) begintx_en_d1 <= 1'b0;tx_en_d2 <= 1'b0;endelse begintx_en_d1 <=tx_en;tx_en_d2 <= tx_en_d1;end
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)data_din_r <= 8'd0;else if (tx_cnt ==4'd9 && clk_cnt == CNT /2)data_din_r <= 8'd0;else if ( tx_en_d1 == 1'b1 && tx_en_d2 == 1'b0 ) data_din_r <= data_din;else;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)start_flag <= 1'b0;else if ( tx_en_d1 == 1'b1 && tx_en_d2 == 1'b0 ) start_flag <= 1'b1;else start_flag <= 1'b0;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)tx_valid <= 1'b0;else if (start_flag == 1'b1)tx_valid <= 1'b1;else if (tx_cnt ==4'd9 && clk_cnt == CNT /2 )tx_valid <= 1'b0;else;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)clk_cnt <= 16'd0;else if (clk_cnt == CNT )clk_cnt <= 16'd0;else if (tx_valid == 1'b1)clk_cnt <= clk_cnt +1'b1;else clk_cnt <= 16'd0;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)tx_cnt <= 4'd0;else if (tx_en_d1 == 1'b1 && tx_en_d2 == 1'b0)tx_cnt <= 4'd0;else if (clk_cnt == CNT)tx_cnt <= tx_cnt +1'b1;else;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)uart_done_r <= 1'b0;else if (tx_valid == 1'b1) beginif (tx_cnt == 4'd9) uart_done_r <= 1'b1;elseuart_done_r <= 1'b0;  endelseuart_done_r <= 1'b0;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)uart_dout_r <= 1'b0;  else if (tx_valid == 1'b1) begincase (tx_cnt)4'd0  : uart_dout_r <= 1'b0;4'd1  : uart_dout_r <=data_din_r[0];    4'd2  : uart_dout_r <=data_din_r[1];4'd3  : uart_dout_r <=data_din_r[2];4'd4  : uart_dout_r <=data_din_r[3];4'd5  : uart_dout_r <=data_din_r[4];4'd6  : uart_dout_r <=data_din_r[5];4'd7  : uart_dout_r <=data_din_r[6];4'd8  : uart_dout_r <=data_din_r[7];       4'd9  : uart_dout_r <=1'b1;default  : ;endcaseendelseuart_dout_r <= 1'b1;  
endendmodule 

2.3頂層模塊代碼

module uart_top (
input          clk,
input          rst,
input          uart_data_rx,
input          rx_en,
output         uart_data_out
);wire       uart_tx_done;
wire       uart_rx_done;
wire [7:0] data_out;uart_rx uart_rx (
.clk          (clk           ),      //input                      
.rst          ( rst          ),      //input                      
.rx_en        ( rx_en ),      //input                        
.data_in      ( uart_data_rx      ),      //input                          
.data_out     ( data_out ),      //output reg [7:0]                
.uart_rx_done ( uart_rx_done )       //output                             
);uart_tx uart_tx(
.clk          ( clk           ),  //input                      
.rst          ( rst           ),  //input                             
.tx_en        ( uart_rx_done  ),  //input                        
.data_din     ( data_out      ),  //input   [7:0]                    
.data_out     ( uart_data_out ),  //output                          
.uart_tx_done ( uart_tx_done  )  //output                              );endmodule 

2.4仿真模塊代碼

module uart_tb();reg clk;
reg rst;
reg  rx_en;
reg uart_data_rx;
wire uart_data_out;initial beginrst = 1'b1;clk = 1'b1;uart_data_rx = 1'b1;rx_en = 1'b0;#20rst = 1'b0;#4340uart_data_rx = 1'b0;rx_en = 1'b1;#20rx_en = 1'b0;#8680  uart_data_rx = 1'b1;#8680  uart_data_rx = 1'b0;#8680  uart_data_rx = 1'b1;#8680  uart_data_rx = 1'b0;#8680  uart_data_rx = 1'b1;#8680  uart_data_rx = 1'b0;#8680  uart_data_rx = 1'b1;#8680  uart_data_rx = 1'b0;#8680  uart_data_rx = 1'b1;endalways #10 clk = !clk;uart_top  uart_top_inst (.clk(clk),.rst(rst),.rx_en(rx_en),.uart_data_rx(uart_data_rx),.uart_data_out(uart_data_out)
);endmodule

3.仿真波形

3.1 接收模塊仿真波形

?數據輸入先放到低位依次傳入

?

3.2 發送模塊仿真波形

?發送的時候,把需要發送的數據低位先發

?

3.3 頂層模塊仿真波形

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/76779.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/76779.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/76779.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

openwrt軟路由配置4--文件共享

1.安裝samba opkg update opkg install luci-app-samba4安裝好之后重啟設備&#xff0c;系統界面服務下面會多一個network shares 2.創建磁盤分區并掛載到共享目錄 openwrt剛剛安裝的時候空間都是很小的&#xff0c;共享目錄我是打算用來存放一些電影視頻之類的大文件。所以我…

Vue ‘v-model‘ directives require the attribute value which is valid as LHS.

1、問題描述 在項目開發中&#xff0c;如果將el-checkbox組件的v-model指令改為使用三元表達式時&#xff0c;會報出【vue/valid-v-model】的錯誤&#xff0c;如下圖所示&#xff1a; 2、分析原因 根據錯誤提示&#xff0c;是因為v-model指令始終把Vue實例的data視為數據真實…

基于 Qt 的 BMP 圖像數據存取至 SQLite 數據庫的實現

基于 Qt 的 BMP 圖像數據存取至 SQLite 數據庫的實現說明 本項目通過 Qt 框架實現了將 BMP 圖像文件以二進制形式存入 SQLite 數據庫&#xff0c;并可從數據庫中讀取還原為 BMP 圖像文件的功能&#xff0c;適用于需要圖像與結構化數據統一管理的場景。 整個流程分為兩個主要部…

嵌入式基礎(三)基礎外設

嵌入式基礎&#xff08;三&#xff09;基礎外設 1.什么是UART&#xff1f;與USART有什么區別??? (1)什么是UART 通用異步收發傳輸器&#xff08;Universal Asynchronous Receiver/Transmitter)&#xff0c;通常稱作UART。是一種異步全雙工串行通信協議&#xff0c;它將要…

人力資源管理方向論文怎么寫?

目錄 一、人力資源管理方向論文選題 二、人力資源管理方向論文參考資料 隨著經濟的蓬勃發展&#xff0c;企業日益意識到引才、善用人才、留住人才對于業務發展的至關重要性。人力資源管理逐漸成為企業管理中的核心職能&#xff0c;其角色日益凸顯。近年來&#xff0c;“人力資…

機器學習 從入門到精通 day_05

1. 線性回歸 前面介紹了很多分類算法&#xff0c;分類的目標變量是標稱型數據&#xff0c;回歸是對連續型的數據做出預測。 標稱型數據&#xff08;Nominal Data&#xff09;是統計學和數據分析中的一種數據類型&#xff0c;它用于分類或標記不同的類別或組別,數據點之間并沒有…

神經子圖同構計數

摘要 本文研究了一個新的圖學習問題&#xff1a;學習計算子圖同構。與其他傳統的圖學習問題&#xff0c;如節點分類和鏈接預測不同&#xff0c;子圖同構計數是NP完全的&#xff0c;需要更多的全局推理來監督整個圖。為了使其可擴展為大規模的圖形和模式&#xff0c;我們提出了一…

開源模型應用落地-模型上下文協議(MCP)-第三方MCP Server實戰指南(五)

一、前言 在AI技術高速發展的2025年,如何讓大語言模型(LLM)更靈活地調用外部工具與數據,成為開發者關注的焦點。?模型上下文協議(MCP)?作為AI與外部資源的“萬能接口”,通過標準化交互框架解決了傳統集成中的碎片化問題。而第三方MCP Server的引入,進一步降低了開發門…

【2025年認證杯數學中國數學建模網絡挑戰賽】C題 數據預處理與問題一二求解

目錄 【2025年認證杯數學建模挑戰賽】C題數據預處理與問題一求解三、數據預處理及分析3.1 數據可視化3.2 滑動窗口相關系數統計與動態置信區間耦合分析模型3.3 耦合關系分析結果 四、問題一代碼數據預處理問題一 【2025年認證杯數學建模挑戰賽】C題 數據預處理與問題一求解 三…

AI Agent開發大全第二十八課-MCP實現本地命令調用怎么做的?

開篇 MCP很強大,Client端一旦實現了穩定的連接和執行流程后任Server端隨意改動都可兼容,這就是熱插撥功能。 如果我們僅僅滿足于MCP查點網上資料、讀點圖片即文字型的功能肯定是不能充分發揮MCP的強大之處的,正應了Google以及Anthropic最近的研究報告上說的:不要再在chat…

AJAX原理與XMLHttpRequest

目錄 一、XMLHttpRequest使用步驟 基本語法 步驟 1&#xff1a;創建 XHR 對象 步驟 2&#xff1a;調用 open() 方法 步驟 3&#xff1a;監聽 loadend 事件 步驟 4&#xff1a;調用 send() 方法 二、完整示例 1. GET 請求&#xff08;帶查詢參數&#xff09; 2. POST 請…

python寫個0~12個月寶寶喂養規劃表

下載字體&#xff1a;https://github.com/adobe-fonts/source-han-sans/releases 下載fpdf2 pip uninstall fpdf pip install fpdf2運行代碼 ?from fpdf import FPDF from fpdf.enums import XPos, YPos# 創建 PDF 類 class BabyFeedingPDF(FPDF):def header(self):self.s…

集中趨勢描述

一、集中趨勢的定義與核心目標 集中趨勢指數據向其中心值聚集的傾向,反映數據的典型水平或分布中心。其核心是通過統計指標(如眾數、中位數、均值)概括數據的核心特征,幫助快速理解數據分布的核心位置。 核心作用:簡化復雜數據、指導業務決策(如確定用戶平均消費水平)、…

【NLP】Attention機制

1.模型對比 RNN(馬爾科夫鏈式編碼) 通過遞歸計算逐個處理 token,當前編碼結果 h t h_t ht?僅依賴前一步的隱藏狀態 h t ? 1 h_{t-1} ht?1?和當前輸入 x t x_t xt?局限性:序列建模需嚴格串行,無法并行;長距離依賴易丟失(梯度消失/爆炸)例:雙向 LSTM 需正向+反向兩…

基于OpenCV與PyTorch的智能相冊分類器全棧實現教程

引言&#xff1a;為什么需要智能相冊分類器&#xff1f; 在數字影像爆炸的時代&#xff0c;每個人的相冊都存儲著數千張未整理的照片。手動分類不僅耗時&#xff0c;還容易遺漏重要瞬間。本文將手把手教你構建一個基于深度學習的智能相冊分類系統&#xff0c;實現&#xff1a;…

活動安排問題 之 前綴和與差分

文章目錄 D. Robert Hood and Mrs Hood 考慮到一個活動開始時間和結束時間s,e&#xff0c;那么可以影響到的范圍就是 s-d1,e,所以我們只需對這個每一個活動可以影響到的區域進行標記即可&#xff0c;當然為了降低時間復雜度&#xff0c;我們將使用前綴和與差分 t int(input()…

C++之 多繼承

在學校里有老師和學生&#xff0c;他們都是人&#xff0c;我么應該創建一個名為 Person 的基類和兩個名為 Teacher 和Student 的子類&#xff0c;后兩者是從前者繼承來的 有一部分學生還教課掙錢&#xff08;助教&#xff09;&#xff0c;也就是同時存在著兩個”是一個”關系&…

大數據學習棧記——Redis安裝及其使用

本文介紹NoSQL技術&#xff1a;Redis的安裝及其使用。操作系統&#xff1a;Ubuntu24.04 Redis介紹 Redis是一個鍵值&#xff08;key-value&#xff09;存儲系統&#xff0c;即鍵值對非關系型數據庫&#xff0c;和Memcached類似&#xff0c;目前正在被越來越多的互聯網公司采用…

2024團體程序設計天梯賽L3-1 奪寶大賽

L3-037 奪寶大賽 分數 30 作者 陳越 單位 浙江大學 奪寶大賽的地圖是一個由 nm 個方格子組成的長方形&#xff0c;主辦方在地圖上標明了所有障礙、以及大本營寶藏的位置。參賽的隊伍一開始被隨機投放在地圖的各個方格里&#xff0c;同時開始向大本營進發。所有參賽隊從一個方格…

JMeter的高并發和高頻率和分布式

性能測試 模擬各種正常的、峰值的測試環境&#xff0c;檢測程序的各項性能指標是否能夠達標 高并發 JMeter中內置了定時器&#xff0c;可以實現時間模式相關的性能測試 需求1:同一時刻100個同學去訪問學生管理系統的查詢所有學院信息功能&#xff0c;統計高并發情況下平均響…