加入星計劃,您可以享受以下權益:

  • 創(chuàng)作內容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關推薦
  • 電子產業(yè)圖譜
申請入駐 產業(yè)圖譜

FPGA零基礎學習之Vivado-UART驅動教程

2023/07/23
2504
閱讀需 18 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

作者:李西銳??校對:陸輝

大俠好,歡迎來到FPGA技術江湖。本系列將帶來FPGA的系統(tǒng)性學習,從最基本的數(shù)字電路基礎開始,最詳細操作步驟,最直白的言語描述,手把手的“傻瓜式”講解,讓電子、信息、通信類專業(yè)學生、初入職場小白及打算進階提升的職業(yè)開發(fā)者都可以有系統(tǒng)性學習的機會。

系統(tǒng)性的掌握技術開發(fā)以及相關要求,對個人就業(yè)以及職業(yè)發(fā)展都有著潛在的幫助,希望對大家有所幫助。本次帶來Vivado系列,UART驅動教程。話不多說,上貨。

UART 驅動教程

UART即通用異步收發(fā)器,是一種通用串行數(shù)據(jù)總線,用于異步通信。該總線為雙向通信,可以實現(xiàn)數(shù)據(jù)的接收與發(fā)送。

數(shù)據(jù)傳輸過程中,我們需要解釋一下串行通信。假設現(xiàn)在我們傳輸數(shù)據(jù)的雙方為A和B,每次傳輸8bit數(shù)據(jù),這8bit的數(shù)據(jù)在傳輸時按照A與B之間的連線分為串行通信和并行通信。串行通信即A與B之間僅有一根數(shù)據(jù)線,在傳輸數(shù)據(jù)時需要一次發(fā)送1bit,總共發(fā)送8次。并行通信即A與B之間有8根線,傳輸數(shù)據(jù)時,將8bit數(shù)據(jù)通過8根線一起傳輸,這樣一次就可以全部傳輸完成。

數(shù)據(jù)傳輸時,接收方和發(fā)送方使用的時鐘不是同一個時鐘域,這也就是異步傳輸

在通信雙方傳輸數(shù)據(jù)之前,需要通過串口線進行連接,然后再傳輸數(shù)據(jù),常用的串口線為DB9接口,但是由于這種接口體積大,不易攜帶等缺點而慢慢淘汰。我們在B04的開發(fā)板上使用到的是一個USB轉串口的芯片,這樣我們的MINI USB接口不僅可以給開發(fā)板供電,還可以進行串口數(shù)據(jù)傳輸。芯片為CP2102(USB <-->UART(LVCMOS/LVTTL)),對于開發(fā)者來說,就不需要關注電平標準了。

芯片電路圖如圖所示:

在電路圖中我們可以發(fā)現(xiàn),串口接口只有兩根數(shù)據(jù)線,分別為RXD和TXD。那么在進行通信之前,我們需要先了解一下串口的傳輸規(guī)則。

在發(fā)送者沒有發(fā)送數(shù)據(jù)時,接收方如果一直接收數(shù)據(jù),那就會導致數(shù)據(jù)出錯,所以,接收方在接收數(shù)據(jù)時需要有標志信號,然后啟動接收。在我們的串口協(xié)議中是這樣規(guī)定的:

1、空閑態(tài)數(shù)據(jù)線上為高電平。

2、發(fā)送數(shù)據(jù)時,先發(fā)送起始位,邏輯電平為低。

3、起始位結束之后,發(fā)送8bit數(shù)據(jù),從低位開始傳輸。

4、數(shù)據(jù)傳輸完畢,是1bit的校驗位,采用奇偶校驗法。(可不使用)

5、停止位,為高電平,可以是1bit、1.5bit或者2bit。

那么我們清楚了數(shù)據(jù)傳輸規(guī)則之后,我們還需要明白一個內容,那就是1bit數(shù)據(jù)的時間長度。在算這個時間之前,我們需要了解一下波特率。波特率的單位是bit/s,也就是1秒時間內,傳輸?shù)腷it數(shù)。我們串口常用的波特率有9600、14400、19200等等。這個波特率是傳輸數(shù)據(jù)的雙方,提前規(guī)定好的。那么在同一速度下傳輸數(shù)據(jù),就會簡單很多。那么根據(jù)波特率我們可以計算出來1bit數(shù)據(jù)的時長為104166ns。在清楚這些之后,接下來我們做一個回環(huán)測試。

首先我們先新建一個工程:

選好代碼存放位置,修改工程名字為uart。

選擇我們的芯片型號:XC7A35TFGG484-2。

新建好工程后,開始新建文件寫代碼。

點擊OK,頂層文件新建完成,后續(xù)各個模塊新建方式相同。接收代碼如下:

1   module uart_rx(2     3     input     wire           clk,4     input     wire           rst_n,5     input     wire           RXD,6     output     reg    [7:0]       data,7     output     reg           wr_en8   );9 10    parameter t = 5208;1112    reg     [14:0]      cnt;13    reg             flag;14    reg             rxd_r, rxd_rr;15    wire             rx_en;16    reg     [3:0]      num;17    reg     [7:0]      data_r;18    19    always @ (posedge clk) rxd_r <= RXD;20    always @ (posedge clk) rxd_rr <= rxd_r;21    22    assign rx_en = (~rxd_r) & rxd_rr;23    24    always @ (posedge clk, negedge rst_n)25    begin26      if(rst_n == 1'b0)27        cnt <= 15'd0;28      else if(flag)29        begin30          if(cnt == t - 1)31            cnt <= 15'd0;32          else33            cnt <= cnt + 1'b1;34        end35      else36        cnt <= 15'd0;37    end38    39    always @ (posedge clk, negedge rst_n)40    begin41      if(rst_n == 1'b0)42        flag <= 1'b0;43      else if(rx_en)44        flag <= 1'b1;45      else if(num == 4'd10)46        flag <= 1'b0;47      else48        flag <= flag;49    end50    51    always @ (posedge clk, negedge rst_n)52    begin53      if(rst_n == 1'b0)54        num <= 4'd0;55      else if(cnt == t / 2 - 1)56        num <= num + 1'b1;57      else if(num == 4'd10)58        num <= 4'd0;59      else60        num <= num;61    end62    63    always @ (posedge clk, negedge rst_n)64    begin65      if(rst_n == 1'b0)66        begin67          data_r <= 8'd0;68          data <= 8'd0;69        end70      else if(cnt == t / 2 - 1)71        case(num)72          4'd0  :  ;73          4'd1  :  data_r[0] <= rxd_rr;74          4'd2  :  data_r[1] <= rxd_rr;75          4'd3  :  data_r[2] <= rxd_rr;76          4'd4  :  data_r[3] <= rxd_rr;77          4'd5  :  data_r[4] <= rxd_rr;78          4'd6  :  data_r[5] <= rxd_rr;79          4'd7  :  data_r[6] <= rxd_rr;80          4'd8  :  data_r[7] <= rxd_rr;81          4'd9  :  data <= data_r;82          default  :  data <= data;83        endcase84    end85    86    always @ (posedge clk, negedge rst_n)87    begin88      if(rst_n == 1'b0)89        wr_en <= 1'b0;90      else if(num == 4'd10)91        wr_en <= 1'b1;92      else93        wr_en <= 1'b0;94    end9596  endmodule

 

發(fā)送數(shù)據(jù)時,跟接收基本類似,按照數(shù)據(jù)格式發(fā)送數(shù)據(jù),代碼如下:

1   module uart_tx(2     3     input   wire             clk,4     input   wire             rst_n,5     input   wire             empty,6     input   wire     [7:0]      data,7     output   wire             rd_en,8     output   reg              TXD9   );10    11    parameter t = 5208;1213    reg     [14:0]      cnt;14    reg             flag;15    reg     [3:0]      num;16    17    18    always @ (posedge clk, negedge rst_n)19    begin20      if(rst_n == 1'b0)21        cnt <= 15'd0;22      else if(flag)23        begin24          if(cnt == t - 1)25            cnt <= 15'd0;26          else27            cnt <= cnt + 1'b1;28        end29      else30        cnt <= 15'd0;31    end32    33    always @ (posedge clk, negedge rst_n)34    begin35      if(rst_n == 1'b0)36        flag <= 1'b0;37      else if(empty == 1'b0)38        flag <= 1'b1;39      else if(num == 4'd10)40        flag <= 1'b0;41      else42        flag <= flag;43    end44    45    always @ (posedge clk, negedge rst_n)46    begin47      if(rst_n == 1'b0)48        num <= 4'd0;49      else if(cnt == t / 2 - 1)50        num <= num + 1'b1;51      else if(num == 4'd10)52        num <= 4'd0;53      else54        num <= num;55    end56    57    assign rd_en = (num == 4'd0 && cnt == 15'd1) ? 1'b1 : 1'b0;58    59    always @ (posedge clk, negedge rst_n)60    begin61      if(rst_n == 1'b0)62        TXD <= 1'b1;63      else if(cnt == t / 2 - 1)64        case(num)65          4'd0  :  TXD <= 1'b0;66          4'd1  :  TXD <= data[0];67          4'd2  :  TXD <= data[1];68          4'd3  :  TXD <= data[2];69          4'd4  :  TXD <= data[3];70          4'd5  :  TXD <= data[4];71          4'd6  :  TXD <= data[5];72          4'd7  :  TXD <= data[6];73          4'd8  :  TXD <= data[7];74          4'd9  :  TXD <= 1'b1;75          default  :  TXD <= 1'b1;76        endcase77    end7879  endmodule

其中讀使能我們只需在數(shù)據(jù)發(fā)送前將數(shù)據(jù)讀出即可。

在做完兩個模塊之后,我們還需要使用一個FIFO來做數(shù)據(jù)緩存,F(xiàn)IFO配置參數(shù)如下:

我們使用異步FIFO,深度選擇2048,位寬為8,復位信號暫時不使用。

生成FIFO后,將各個模塊例化到頂層當中,代碼如下:

1   module uart(2     3     input   wire           clk,4     input   wire           rst_n,5     input   wire           RXD,6     output   wire           TXD7   );8 9     wire     [7:0]    rx_data;10    wire           wr_en;11    wire           rd_en;12    wire     [7:0]    tx_data;13    wire           empty;14    15    uart_rx uart_rx_inst(16    17    .clk        (clk  ),18    .rst_n        (rst_n),19    .RXD        (RXD  ),20    .data        (rx_data),21    .wr_en        (wr_en)22  );23    24    fifo fifo_inst (25    .wr_clk(clk),  // input wire wr_clk26    .rd_clk(clk),  // input wire rd_clk27    .din(rx_data),        // input wire [7 : 0] din28    .wr_en(wr_en),    // input wire wr_en29    .rd_en(rd_en),    // input wire rd_en30    .dout(tx_data),      // output wire [7 : 0] dout31    .full(),      // output wire full32    .empty(empty)    // output wire empty33  );34    35    uart_tx uart_tx_inst(36    37    .clk        (clk  ),38    .rst_n        (rst_n  ),39    .empty        (empty  ),40    .data        (tx_data),41    .rd_en        (rd_en  ),42    .TXD        (TXD  )43  );4445  endmodule

 

功能部分寫完之后,我們寫一個仿真進行邏輯驗證,寫仿真時,我們按照數(shù)據(jù)順序模擬給值,每1bit持續(xù)104166ns的時間。代碼如下:

1   `timescale 1ns / 1ps2 3   module uart_tb;4 5     reg            clk;6     reg            rst_n;7     reg            RXD;8     wire           TXD;9 10    initial begin11      clk = 0;12      rst_n = 0;13      RXD = 1;14      #105;15      rst_n = 1;16      17      #1000;18      RXD = 0;19      #104166;20      21      RXD = 1;22      #104166;23      RXD = 0;24      #104166;25      RXD = 1;26      #104166;27      RXD = 0;28      #104166;29      RXD = 1;30      #104166;31      RXD = 0;32      #104166;33      RXD = 0;34      #104166;35      RXD = 1;36      #104166;37      38      RXD = 1;39      #104166;40      41      #5000;42      $stop;43    end44    45    always #10 clk = ~clk;46    47    uart uart_inst(48    49    .clk      (clk  ),50    .rst_n      (rst_n  ),51    .RXD      (RXD  ),52    .TXD      (TXD  )53  );54    55  endmodule

打開仿真波形:

如圖,我們可以看到,當我們的接收模塊接收到數(shù)據(jù)時,會將數(shù)據(jù)寫入FIFO,F(xiàn)IFO中有數(shù)據(jù)時,發(fā)送模塊就會將數(shù)據(jù)讀出并發(fā)送,仿真現(xiàn)象正確。

下板現(xiàn)象:

我們隨便寫入幾個數(shù)據(jù),會發(fā)現(xiàn)我們的發(fā)送模塊和接收模塊的數(shù)據(jù)完全一致,即接收和發(fā)送正常。

 

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風險等級 參考價格 更多信息
LFE5U-45F-7BG256I 1 Lattice Semiconductor Corporation Field Programmable Gate Array,

ECAD模型

下載ECAD模型
$18.74 查看
EP2C35F484C6N 1 Altera Corporation Field Programmable Gate Array, 2076 CLBs, 500MHz, 33216-Cell, CMOS, PBGA484, LEAD FREE, FBGA-484
$209.75 查看
EPM2210F256I5N 1 Intel Corporation Flash PLD, 11.2ns, 1700-Cell, CMOS, PBGA256, 17 X 17 MM, 1 MM PITCH, LEAD FREE, FBGA-256

ECAD模型

下載ECAD模型
$60.06 查看

相關推薦

電子產業(yè)圖譜

任何技術的學習就好比一個江湖,對于每一位俠客都需要不斷的歷練,從初入江湖的小白到歸隱山林的隱世高人,需要不斷的自我感悟自己修煉,讓我們一起仗劍闖FPGA乃至更大的江湖。