吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于FPGA的串口UART設計

FPGA技術江湖 ? 來源:FPGA技術江湖 ? 作者:FPGA技術江湖 ? 2024-12-30 14:07 ? 次閱讀

大俠好,歡迎來到FPGA技術江湖,江湖偌大,相見即是緣分。大俠可以關注FPGA技術江湖,在“闖蕩江湖”、"行俠仗義"欄里獲取其他感興趣的資源,或者一起煮酒言歡。

今天給大俠帶來基于FPGA的UART設計,附源碼,獲取源碼,請在“FPGA技術江湖”公眾號內回復“UART設計源碼”,可獲取源碼文件。話不多說,上貨。

設計背景

串口的出現是在1980年前后,數據傳輸率是115kbps~230kbps。串口出現的初期是為了實現連接計算機外設的目的,初期串口一般用來連接鼠標和外置Modem以及老式攝像頭和寫字板等設備。串口也可以應用于兩臺計算機(或設備)之間的互聯及數據傳輸。由于串口(COM)不支持熱插拔及傳輸速率較低,部分新主板和大部分便攜電腦已開始取消該接口。串口多用于工控和測量設備以及部分通信設備中。

串口是串行接口的簡稱,也稱串行通信接口或串行通訊接口(通常指COM接口),是采用串行通信方式的擴展接口。串行接口(Serial Interface)是指數據一位一位地順序傳送。其特點是通信線路簡單,只要一對傳輸線就可以實現雙向通信(可以直接利用電話線作為傳輸線),從而大大降低了成本,特別適用于遠距離通信,但傳送速度較慢。

通信協議是指通信雙方的一種約定。約定包括對數據格式、同步方式、傳送速度、傳送步驟、檢糾錯方式以及控制字符定義等問題做出統一規定,通信雙方必須共同遵守。串口通信的兩種最基本的方式為:同步串行通信方式和異步串行通信方式。

同步串行通信是指SPI(Serial Peripheral interface)的縮寫,顧名思義就是串行外圍設備接口。SPI是一種高速的全雙工通信總線。封裝芯片上總共有四根線,PCB布局布線也簡單,所以現在很多芯片集成了這個協議。主要用于CPU和各種外圍器件進行通信,TRM450是SPI接口。

異步串行通信是指UART(Universal Asynchronous Receiver/Transmitter),通用異步接收/發送。UART是一個并行輸入成為串行輸出的芯片,通常集成在主板上。UART包含TTL電平的串口和RS232電平的串口。RS232也稱標準串口,也是最常用的一種串行通訊接口。RS-232-C 標準對兩個方面作了規定,即信號電平標準和控制信號線的定義。RS-232-C 采用負邏輯規定邏輯電平,信號電平與通常的TTL電平也不兼容,RS-232-C 將-5V~-15V 規定為“1”,+5V~+15V 規定為“0”。

設計原理

uart的示意圖如下:

a49f77b8-c63d-11ef-9310-92fbcf53809c.png

端口對應的功能表如下:

a4b6ba9a-c63d-11ef-9310-92fbcf53809c.png

在設計過程中只需要關心RS232_TXD和RS232_RXD兩個信號, RS232_TXD是數據發送端口,RS232_RXD是數據接收端口。

本設計將通過串口建立起計算機和實驗板(ZX_1)之間的通信和控制關系,也就是通常所說的上下位機通信。要實現這樣的通信,首先需要用到一個外部的電平轉換芯片MAX232,其具體配置電路原理圖如下:

a4cfb8c4-c63d-11ef-9310-92fbcf53809c.png

解析:

MAX232芯片是美信(MAXIM)公司專為RS-232標準串口設計的單電源電平轉換芯片,使用+5v單電源供電。

主要特點:

1、符合所有的RS-232C技術標準;

2、只需要單一+5V電源供電;

3、片載電荷泵具有升壓、電壓極性反轉能力,能夠產生+10V和-10V電壓V+、V-;

4、功耗低,典型供電電流5mA;

5、內部集成2個RS-232C驅動器

6、高集成度,片外最低只需4個電容即可工作。

本設計還需要分析在通信過程中,UART所對應的數據格式如下:

起始位:線路空閑時為高電平,當截獲第一個低電平比特時,則為起始位;

信息位:在起始位之后,按照低位首發原則,順序發送信息位的最低位到最高位,信息位的寬度可以是4、5、6、7、8中的一個;

奇偶校驗位:信息位之后則是一個可選的奇偶校驗位,它可以是無校驗(NONE)、奇校驗(ODD)、偶校驗(EVEN)中的任意一個,無校驗時,信息位之后就是停止位。奇偶校驗是,使得信息位和校驗位的所有1的個數保持奇數或者偶數位;

停止位:停止位的長度可以是1、1.5或2中的任意一個,它為高電平;

空閑位:持續的高電平。

波特率:每秒傳輸的數據位(bit)數為波特率。RS-232-C的波特率可以是50、75、100、150、300、600、1200、2400、4800、9600、19200波特。

通過分析上述的數據格式,在本設計中,將波特率設置為9600,起始位設置為1比特,信息位設置為8比特,奇偶校驗位設置為0比特,停止位設置為2比特,空閑位設置為1比特。

因為在設計中只需要關注RS232_TXD和RS232_RXD這兩個信號,既然只有兩條線,所以只需要關注其數據收發時序即可,時序圖如下:

a4e97390-c63d-11ef-9310-92fbcf53809c.png

設計架構

設計總架構圖如下:

a50c5cac-c63d-11ef-9310-92fbcf53809c.png

uart_pll模塊是一個鎖相環,通過50M的外部時鐘(ref_clk),倍頻得到100M的上游接口的100M系統時鐘(sys_clk);divider模塊為UART的分頻模塊,通過用100M的sys_clk作為輸入,分頻得到波特率為9600的uart_clk時鐘。

transmitter模塊為串口發送模塊,并配合與其對應的trans_fifo發送數據緩存FIFO進行使用,將儲存在FIFO中的數據通過RS232-C協議發送出去;

receiver模塊為串口接收模塊,并配合與其對應的rec_fifo接收數據緩存FIFO進行使用,將儲存在FIFO中的數據通過RS232-C協議接收進來;

UART發送器(transmitter)設計

UART發送器的時序如下圖:

a51cbe30-c63d-11ef-9310-92fbcf53809c.png

a52ce594-c63d-11ef-9310-92fbcf53809c.png

UART接收器(receiver)設計

根據對UART時序的分析可以得到如下的狀態轉移表(SMF):

a53c885a-c63d-11ef-9310-92fbcf53809c.png

設計代碼

頂層uart_lsm模塊代碼:

`include "uart_lsm_head.v"


module uart_lsm(ref_clk, global_reset,tdata, twrreq, 
      tfull, rdata, rrdreq, rempty, uart_txd, uart_rxd);


  input ref_clk, global_reset;  //全局時鐘復位
  input [7:0] tdata;  //發送fifo輸入數據
  input twrreq;  //發送fifo寫請求
   output tfull;   //發送fifo輸出寫滿
  output [7:0] rdata;  //接收fifo輸出數據
  input rrdreq;   //接收fifo的輸入讀請求
  output rempty;   //接收fifo的輸出入空
   output uart_txd;  //輸出發送線信號
  input uart_rxd;  //輸入接收線信號


  wire trxd;


  wire [7:0] tf_data, rf_data;
  wire tf_rdreq, tf_empty, rf_wrreq;
  wire sys_clk, uart_clk, rst_n;




  assign rst_n = ~global_reset;


  trans_fifo t_fifo(    //發送fifo
    .data(tdata),
    .rdclk(uart_clk),
    .rdreq(tf_rdreq),
    .wrclk(sys_clk),
    .wrreq(twrreq),
    .q(tf_data),
    .rdempty(tf_empty),
    .wrfull(tfull)
  );


  transmitter trans(   //發送模塊
    .clk(uart_clk), 
    .rst_n(rst_n), 
    .empty(tf_empty), 
    .data(tf_data), 
    .rdreq(tf_rdreq), 
    .txd(trxd)
  );


  rec_fifo r_fifo(     //接收fifo
    .data(rf_data),
    .rdclk(sys_clk),
    .rdreq(rrdreq),
    .wrclk(uart_clk),
    .wrreq(rf_wrreq),
    .q(rdata),
    .rdempty(rempty)
  );


  receiver rece(     //接收模塊
    .clk(uart_clk), 
    .rst_n(rst_n), 
    .data(rf_data), 
    .wrreq(rfwrreq), 
    .rxd(trxd)
  );


  uart_pll u_pll(         //鎖相環產生系統時鐘,作用于fifo、divider
    .areset(global_reset),
    .inclk0(ref_clk),
    .c0(sys_clk)
  );


  divider_ebd_1s_mealy   //分頻模塊分頻uart_clk,作用于receiver transmitter
  #(.HW(`DW), .LW(`DW))
  div(
    .clk_in(sys_clk), 
    .rst_n(rst_n), 
    .clk_out(uart_clk)
  );


endmodule

transmitter模塊代碼:

//uart發送模塊LSM(線性序列機)
module transmitter(clk, rst_n, empty, data, rdreq, txd);


  input clk, rst_n;  //輸入時鐘復位
  input empty;       //來自fifo的輸入空標志信號
  input [7:0] data;  //來自fifo的輸入數據
  output reg rdreq;  //輸出到fifo的讀請求
  output reg txd;    //輸出發送線信號


  reg [7:0] temp;      //中間寄存器
  reg [7:0] count;    //8位計數


  `define EP 192   //終止符


  always @ (posedge clk or negedge rst_n)
  begin  : lsm_2s1   //線性序列機一段閉節點
    if (!rst_n)   //復位
      count <= `EP;
    else if ((count >= `EP) && !empty)  //計數大于終止符和非空(empty=0)
      count <= 0;
    else if (count < `EP) //計數小于終止符
      count <= count + 1;
  end 


  always @ (posedge clk or negedge rst_n)
  begin  : lsm_2s2  //線性序列機一段閉節點
    if (!rst_n)  //復位
      begin
        txd <= 1;   //發送線為高
        rdreq <= 0;  //讀請求為0
        temp <= 0;  //中間寄存器為0
      end 
    else if ((count >= `EP) && !empty) //計數大于終止符fifo為非空,讀請求拉高
        rdreq <= 1;
    else 
      case (count)
        0  :  begin
              rdreq <= 0;  //讀請求拉低
              txd <= 0;
            end 
        1  :  temp[7:0] <= data[7:0];  //輸入數據給中間寄存器
        1*16  :  txd <= temp[0];   //中間寄存器按位給發送線發送
        2*16  :  txd <= temp[1];
        3*16  :  txd <= temp[2];
        4*16  :  txd <= temp[3];
        5*16  :  txd <= temp[4];
        6*16  :  txd <= temp[5];
        7*16  :  txd <= temp[6];
        8*16  :  txd <= temp[7];
        9*16  :  txd <= 1;    //拉高
      endcase     
  end   


endmodule

接收模塊receiver代碼:

`include "uart_lsm_head.v"


module receiver(clk, rst_n, data, wrreq, rxd);   //uart接收模塊LSM(線性序列機)


  input clk, rst_n;  //輸入時鐘復位
  output reg [7:0] data;  //輸出數據
  output reg wrreq;   //輸出寫請求
  input rxd;    //輸入接收線信號


  reg [7:0] count;
  //宏定義
  `define EP   184   //終止符
  `define GET0 24
  `define GET1 `GET0+16
  `define GET2 `GET1+16
  `define GET3 `GET2+16
  `define GET4 `GET3+16
  `define GET5 `GET4+16
  `define GET6 `GET5+16
  `define GET7 `GET6+16
  `define GETW `GET7+16  //wrreq=1
  `define GLRW `GETW+1   //wrreq=0


  always @ (posedge clk or negedge rst_n)
  begin : lsm_2s1   //線性序列機一段閉節點
    if(!rst_n)
      count <= `EP;
    else if((count >= `EP) && !rxd) //rxd=0
      count <= 0;
    else if (count < `EP)
      count <= count + 1;
  end


  always @ (posedge clk or negedge rst_n)
    begin  : lsm_2s2   //線性序列機二段閉節點     
      if(!rst_n)
        begin      
          data <= 0;
          wrreq <= 0;      //寫請求為0
        end 
      else
        case(count)
          `GET0  :  data[0] <= rxd;   //將接收的數據通過data輸出
          `GET1  :  data[1] <= rxd;
          `GET2 :   data[2] <= rxd;
          `GET3 :   data[3] <= rxd;
          `GET4 :   data[4] <= rxd;
          `GET5 :   data[5] <= rxd;
          `GET6 :   data[6] <= rxd;
          `GET7 :   data[7] <= rxd;
          `GETW :   wrreq <= 1;   //寫請求拉高一拍,寫進fifo
          `GLRW :   wrreq <= 0;   //一拍后寫請求為0
        endcase
    end


endmodule

參數宏的頭文件代碼

/////uart_lsm_head.v


//////////定義時標////////////
`timescale 1us/1ns


/////////定義設計參數/////////
`define BAUD_RATE 9600   //波特率=9600
`define SYS_CLK 100000000 //系統時鐘sys_clk 頻率=100M
`define REF_CLK 50000000 //系統時鐘ref_clk頻率=50M


//////////使用宏自動計算的諸參數////////////
`define TBAUD_RATE (1000000.0/`BAUD_RATE)//波特率周期
`define UART_CLK (16*`BAUD_RATE)        //uart_clk 等于16倍波特率
`define TUART_CLK (1000000.0/`UART_CLK) //uart_clk周期
`define TEN_TUART_CLK (10.0*`TUART_CLK) //10倍uart_clk周期
`define TUART_CLK100 (100.0*`TUART_CLK) //100倍uart_clk周期


`define TUART_CLK_HALF (`TUART_CLK/2.0) //uart_clk半周期
`define TREF_CLK (1000000.0/`REF_CLK)  //參考時鐘周期
`define TREF_CLK_HALF (`TREF_CLK/2.0)  //參考時鐘半周期


//////////使用宏自動計算的分頻數(占空比50%)////////////
`define DW (`SYS_CLK/(2*`UART_CLK))

仿真測試

transmitter(發送)模塊的測試代碼:

`include "uart_lsm_head.v"


module transmitter_tb;


  reg clk, rst_n;
  reg empty;
  reg [7:0] data;
  wire rdreq;
  wire txd;
  
  reg [7:0] temp;


  transmitter transmitter_dut(
      .clk(clk),
      .rst_n(rst_n),
      .empty(empty),
      .data(data),
      .rdreq(rdreq),
      .txd(txd)
    );


  initial begin
    clk = 1;
    rst_n = 0;
    data = 0;
    empty = 1;
    temp = 0;
    #200.1 rst_n = 1;
    
    #200.1 empty=1;temp=8'h55;
    #`TBAUD_RATE
    data[0] = temp[0];  //發送第一個信息位(LSB)
    #`TBAUD_RATE
    data[1] = temp[1];
    #`TBAUD_RATE
    data[2] = temp[2];
    #`TBAUD_RATE
    data[3] = temp[3];
    #`TBAUD_RATE
    data[4] = temp[4];
    #`TBAUD_RATE
    data[5] = temp[5];
    #`TBAUD_RATE
    data[6] = temp[6];
    #`TBAUD_RATE
    data[7] = temp[7];
    #`TBAUD_RATE
    empty = 0;  
    #2000 $stop;    
    end
  
  always #`TUART_CLK_HALF clk = ~clk;
  
endmodule 

receiver(接收)模塊的測試代碼:

`include "uart_lsm_head.v"


module receiver_tb;


  reg clk, rst_n;
  reg rxd;
  wire [7:0] data;
  wire wrreq;
  
  reg [7:0] temp; //8位的中間寄存器,產生激勵
  
  receiver receiver_dut(
    .clk(clk),
    .rst_n(rst_n),
    .data(data),
    .wrreq(wrreq),
    .rxd(rxd)
  );
  
  initial begin
    clk = 1;
    rst_n = 0;
    temp = 0;
    rxd = 1;
    #`TEN_TUART_CLK  //*代表異步 //10倍uart_clk周期
    rst_n = 1;
    
    #`TEN_TUART_CLK  //啟動一個停止位  
    rxd = 0;  
    temp = 8'h55;  
    #`TBAUD_RATE    //數據使用波特率的周期
    rxd = temp[0];  //發送一個信息位(LSB)
    #`TBAUD_RATE
    rxd = temp[1];
    #`TBAUD_RATE
    rxd = temp[2];
    #`TBAUD_RATE
    rxd = temp[3];
    #`TBAUD_RATE
    rxd = temp[4];
    #`TBAUD_RATE
    rxd = temp[5];
    #`TBAUD_RATE
    rxd = temp[6];
    #`TBAUD_RATE
    rxd = temp[7];   //發送最后一個信息位(HSB)
    #`TBAUD_RATE
    rxd = 1;
    
    #`TUART_CLK100 $stop;   //100倍uart_clk周期
  end
    
  always #`TUART_CLK_HALF clk = ~clk;  // uart_clk 的時鐘,使用uart_clk的半周期


endmodule 

仿真圖:分別為發送和接收做仿真測試。

發送的仿真波形如下:

a571ac42-c63d-11ef-9310-92fbcf53809c.png

接收的仿真波形如下:

a58f1fca-c63d-11ef-9310-92fbcf53809c.png

根據以上兩個仿真波形,可以發現設計是正確的,之后則可利用串口獵人的上位機軟件,實現自發自收。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • FPGA
    +關注

    關注

    1629

    文章

    21742

    瀏覽量

    603530
  • 接口
    +關注

    關注

    33

    文章

    8610

    瀏覽量

    151212
  • 串口
    +關注

    關注

    14

    文章

    1555

    瀏覽量

    76541
  • uart
    +關注

    關注

    22

    文章

    1237

    瀏覽量

    101411
  • 串行通信
    +關注

    關注

    4

    文章

    574

    瀏覽量

    35405

原文標題:源碼系列:基于FPGA的串口UART設計(附源工程)

文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術江湖】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    什么是串口(UART)?串口的組成和FPGA實現

    串口作為常用的三大低速總線(UART、SPI、IIC)之一,在設計眾多通信接口和調試時占有重要地位。
    的頭像 發表于 01-03 11:43 ?1.5w次閱讀
    什么是<b class='flag-5'>串口</b>(<b class='flag-5'>UART</b>)?<b class='flag-5'>串口</b>的組成和<b class='flag-5'>FPGA</b>實現

    FPGA/CPLD設計UART

    UART 是廣泛使用的串行數據通訊電路。本設計包含UART 發送器、接收器和波特率發生器。設計應用EDA 技術,基于FPGA/CPLD 器件設計與實現UART。關鍵詞 :
    發表于 09-29 08:01 ?24次下載

    IO模擬串口UART

    IO模擬串口UART 本文介紹GPIO模擬UART的算法和實現
    發表于 04-03 14:11 ?86次下載

    FPGA與CPLD實現UART

    UART 是廣泛使用的串行數據通訊電路。本設計包含UART 發送器、接收器和波特率發生器。設計應用EDA 技術,基于FPGA/CPLD 器件設計與實現UART。
    發表于 12-17 00:15 ?59次下載
    <b class='flag-5'>FPGA</b>與CPLD實現<b class='flag-5'>UART</b>

    niosii的UART串口通信

    niosii的UART串口通信niosii的UART串口通信。
    發表于 04-06 17:03 ?1次下載

    UART串口在SIM卡讀寫中的應用

    UART串口在SIM卡讀寫中的應用,下來看看
    發表于 08-19 16:51 ?0次下載

    基于FPGA/CPLD的UART功能設計

    基于FPGA/CPLD的UART功能設計
    發表于 01-23 20:45 ?31次下載

    實驗五 UART串口通訊實驗

    UART串口通訊
    發表于 01-22 20:51 ?8次下載

    基于51單片機的UART串口通信

    基于51單片機的UART串口通信詳解。
    發表于 11-21 10:14 ?6.3w次閱讀
    基于51單片機的<b class='flag-5'>UART</b><b class='flag-5'>串口</b>通信

    uart是什么意思?認識uart串口

    設備沒有顯示屏,無法獲得嵌入式設備實時數據信息,通過UART串口和超級終端相連,打印嵌入式設備輸出信息。并且在對嵌入式系統進行跟蹤和調試時,UART串口了是必要的通信手段。比如:網絡路
    發表于 12-06 14:51 ?11w次閱讀
    <b class='flag-5'>uart</b>是什么意思?認識<b class='flag-5'>uart</b><b class='flag-5'>串口</b>

    UART串口WiFi模塊的工作原理及應用

    隨著物聯網智能家居應用的日漸豐富,越來越多的 WiFi 工程師開始更多的關注 UART 串口 WiFi 模塊,為讓新手工程師更快的將 UART 串口 WiFi 模塊應用于各類智能家居應
    發表于 01-08 08:00 ?23次下載
    <b class='flag-5'>UART</b><b class='flag-5'>串口</b>WiFi模塊的工作原理及應用

    一種基于FPGAUART電路的實現

    UART即通用異步收發器,傳統上采用多功能的專用集成電路實現。但是在一般的使用中往往不需要完整的UART的功能,比如對于多串口的設備或需要加密通訊的場合使用專用集成電路實現的UART
    發表于 04-27 14:07 ?8次下載

    基于FPGAUART模塊設計與實現簡介

    基于FPGAUART模塊設計與實現介紹說明。
    發表于 06-01 09:43 ?20次下載

    C51的UART 串口通信

    C51的UART 串口通信
    發表于 11-29 12:21 ?11次下載
    C51的<b class='flag-5'>UART</b> <b class='flag-5'>串口</b>通信

    UART串口通訊

    UART串口通訊總結前言串口的基本概念串口配置的基本屬性串口(Serial port)和RS-232串口
    發表于 12-20 19:31 ?24次下載
    <b class='flag-5'>UART</b><b class='flag-5'>串口</b>通訊
    网上玩百家乐犯法| 百家乐官网登封代理| 百家乐官网玩法既规则| 永利高百家乐网址| 足球赌网| 百家乐是骗人吗| 澳门百家乐官网技巧| 澳门百家乐网址多少| 御金百家乐官网娱乐城| 威尼斯人娱乐| 大发888娱乐城shouye| 百家乐视频游戏冲值| 百家乐官网真人赌场娱乐网规则| 百家乐官网的破解方法| 博e百| 旧金山百家乐官网的玩法技巧和规则| 雁荡棋牌游戏| 国际娱百家乐的玩法技巧和规则| 百家乐合理的投注法| 视频百家乐官网信誉| 立博百家乐官网游戏| 万博娱乐城| 威尼斯人娱乐城 老品牌| 百家乐官网娱乐平台官网网 | 大发888娱乐城赢钱| 百家乐必胜绝| 大西洋百家乐的玩法技巧和规则| 星级百家乐技巧| 关于百家乐官网切入点| 张北县| 汇丰百家乐官网的玩法技巧和规则 | 利都百家乐官网国际娱乐| 百家乐官网视频游戏视频| 威尼斯人娱乐城金杯娱乐城| 游戏机百家乐下载| 真人百家乐策略| 赌博百家乐官网的玩法技巧和规则| 真人百家乐官网赌场娱乐网规则 | 现金网排名| 百家乐是娱乐场最不公平的游戏| 爱赢娱乐城|