UART Protocol Introduction
鮑率(Baud Rate)
引用先前的文章
實作問題與討論
Abstract :
以實際範例說明如何設計串列傳輸,並討論常見問題與解決方法。
Introduction : 串列傳輸(UART)專用石英震盪器(Crystal) :
鮑率產生方式 :
如果Crystal選用7.3728MHz,那麼經過64倍除頻器後可得115200Hz,程式範例如下 :
reg [3:0] BaudDivCnt;
always @(posedge clk)
BaudDivCnt<=BaudDivCnt+1;
wire BaudTick = (BaudDivCnt==15);
假設Crystal震盪頻率選用7.3728MHz、鮑率設定為115200。扣除奇偶同位元後,僅剩起始位元、資料位元、結束位元共10位元,相當於每秒最多可以傳輸11520byte的資料量。
資料輸出(TX) : 欲透過鮑率115200的傳輸速率進行資料傳輸,只需要將輸入震盪頻率除以鮑率即可獲得除頻器的大小。
操作方法 : 7.3728M Hz/115200=64; 相當於每計數64次上緣訊號後,將資料由最低位元開始依序傳出。
資料接收(RX) : 欲透過鮑率115200的傳輸速率進行資料接收,為了減少誤差所造成的誤判,必須選擇八倍頻。相當於將原先的Crystal震盪頻率由64倍改為8倍除頻器即可。
操作方法 : 以資料端(RX)作判斷,在下緣訊號觸發時做為起始位元的開始。緊接著以震盪器的上緣訊號觸發做計算,在計數12次的上緣訊號後,將資料由最低位元開始儲存,之後每8位元儲存一筆,依此類推直到10bit的資料儲存完為止(不包含奇偶同位元)。此方法是為了能夠精確的抓取資料,如下圖所示。
位元中心取樣示意圖
Symptom 1 : 非串列傳輸(UART)專用石英震盪器(Crystal)
通常外部震盪器的頻率不會剛好是鮑率的整數倍。假設輸入以2MHz的震盪器為例、鮑率選擇115200。經運算後得2000000/115200=17.36,因此會有小數點0.36的誤差累積,相當於2.12%的誤差,造成時序錯誤。因此訊號會產生延遲造成資料誤判的可能,如下圖所示。
資料讀取錯誤示意圖
解決辦法:
在FPGA的運算器內只能透過整數做運算,因此本文選擇以定點數運算的方式以整數運算取代浮點數運算,以達到相似的效果。因為式子1約等於式子2,如式子3所示。
式子1: 2000000/115200=17.36111
式子2: 1024/59=17.356
式子3: 2000000/115200~=1024/59
經由定點數的概念,式子2的被除數選擇1024,那麼除數59是如何決定的,如式子5:
式子4 : 2000000/115200 ~= 1024/X
式子5 : X ~= (2^10 / 2*10^6) *11500
將式子5加以定義以便後續說明使用,如下式。
式子6 :
BaudGeneratorInc = (Baud<<BaudGeneratorAcmWidth)/ClkFrequency 1. BaudGeneratorInc : X 2. Baud : 需求鮑率(115200) 3. BaudGeneratorAccWidth : 1024 4. ClkFrequency : 2000000 因為式子3的兩項頻率很接近,所以可以撰寫成下列程式來產生需求的鮑率: reg [10:0] acm; // The total of accumulator is 11 bits. always @(posedge clk) acm <= acm[9:0] + 59; wire BaudTick =acm[10]; // The 11th bit is the enable flag. 經由上述公式推導,進而將程式修改如下 : parameter ClkFrequency = 20000000; // 20MHz parameter Baud = 115200; parameter BaudGeneratorAcmWidth = 10; parameter BaudGeneratorInc = (Baud< reg [BaudGeneratorAcmWidth:0] BaudGeneratorAcm; always @(posedge clk) BaudGeneratorAcm <= BuadGeneratorAcc[BaudGeneratorAcmWidth-1:0] + BaudGeneratorInc; wire BaudTick = BaudGeneratorAcm[BaudGeneratorAcmWisth]; Symptom 2 : 運算結果會有溢位狀況 上述的程式中,假設計數器BaudGeneratorAcmWidth為16位元以上時,BaudGeneratorInc的計算會有瑕疵,因為在Verilog語言中,運算過程最多只能為2的32次方,而此公式計算超過32位元。因此要將程式稍作修改,以犧牲解析度的方式解決,這會使誤差變大,但只要誤差於容許範圍內即可。如下所示。 parameter BaudGeneratorInc = (Baud<<BaudGeneratorAcmWidth-4)/(ClkFrequency>>4); Conclusion : 了解完串列傳輸UART專用震盪器與非專用震盪器的鮑率產生方式後,再配合通訊協定的設計概念,相信對於設計上會更有感覺。 Reference : http://bbs.ednchina.com/BLOG_ARTICLE_219306.HTM
留言列表