close

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 : 運算結果會有溢位狀況


        上述的程式中,假設計數器BaudGeneratorAcmWidth16位元以上時,BaudGeneratorInc的計算會有瑕疵,因為在Verilog語言中,運算過程最多只能為232次方,而此公式計算超過32位元。因此要將程式稍作修改,以犧牲解析度的方式解決,這會使誤差變大,但只要誤差於容許範圍內即可。如下所示。



parameter BaudGeneratorInc =


(Baud<<BaudGeneratorAcmWidth-4)/(ClkFrequency>>4);




Conclusion :


        了解完串列傳輸UART專用震盪器與非專用震盪器的鮑率產生方式後,再配合通訊協定的設計概念,相信對於設計上會更有感覺。


Reference :


http://bbs.ednchina.com/BLOG_ARTICLE_219306.HTM



arrow
arrow
    全站熱搜
    創作者介紹
    創作者 jk3527101 的頭像
    jk3527101

    簡單也是另一種快樂

    jk3527101 發表在 痞客邦 留言(2) 人氣()