FPGA實現串行接口 RS232_第1頁
FPGA實現串行接口 RS232_第2頁
FPGA實現串行接口 RS232_第3頁
FPGA實現串行接口 RS232_第4頁
FPGA實現串行接口 RS232_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、FPGA實現串行接口 RS232串行接口(RS-232)串行接口是連接FPGA和PC機的一種簡單方式。這個項目向大家展示了如果使用FPGA來創(chuàng)建RS-232收發(fā)器。 整個項目包括5個部分1 RS232是怎樣工作的2 如何產生需要的波特率3 發(fā)送模塊4 接收模塊5 應用實例RS-232接口是怎樣工作的作為標準設備,大多數的計算機都有1到2個RS-232串口。特性RS-232有下列特性: 使用9針的DB-9插頭(舊式計算機使用25針的DB-25插頭). 允許全雙工的雙向通訊(也就是說計算機可以在接收數據的同時發(fā)送數據). 最大可支持的傳輸速率為10KBytes/s.DB-9插頭你可能已經在你的計算

2、機背后見到過這種插頭 它一共有9個引腳,但是最重要的3個引腳是: 引腳2: RxD (接收數據). 引腳3: TxD (發(fā)送數據). 引腳5: GND (地).僅使用3跟電纜,你就可以發(fā)送和接收數據.串行通訊數據以每次一位的方式傳輸;每條線用來傳輸一個方向的數據。由于計算機通常至少需要若干位數據,因此數據在發(fā)送之前先“串行化”。通常是以8位數據為1組的。 。先發(fā)送最低有效位,最后發(fā)送最高有效位。異步通訊RS-232使用異步通訊協議。也就是說數據的傳輸沒有時鐘信號。接收端必須有某種方式,使之與接收數據同步。對于RS-232來說,是這樣處理的:6 串行線纜的兩端事先約定好串行傳輸的參數(傳輸速度、

3、傳輸格式等)7 當沒有數據傳輸的時候,發(fā)送端向數據線上發(fā)送18 每傳輸一個字節(jié)之前,發(fā)送端先發(fā)送一個0來表示傳輸已經開始。這樣接收端便可以知道有數據到來了。9 開始傳輸后,數據以約定的速度和格式傳輸,所以接收端可以與之同步10 每次傳輸完成一個字節(jié)之后,都在其后發(fā)送一個停止位(1)讓我們來看看0x55是如何傳輸的: 0x55的二進制表示為:01010101。但是由于先發(fā)送的是最低有效位,所以發(fā)送序列是這樣的: 1-0-1-0-1-0-1-0.下面是另外一個例子 : 傳輸的數據為0xC4,你能看出來嗎?從圖中很難看出來所傳輸的數據,這也說明了事先知道傳輸的速率對于接收端有多么重要。數據傳輸可以多

4、快?數據的傳輸速度是用波特來描述的,亦即每秒鐘傳輸的數據位,例如1000波特表示每秒鐘傳輸100比特的數據, 或者說每個數據位持續(xù)1毫秒。波特率不是隨意的,必須服從一定的標準,如果希望設計123456波特的RS-232接口,對不起,你很不幸運,這是不行的。常用的串行傳輸速率值包括以下幾種: 1200 波特. 9600 波特. 38400 波特. 115200 波特 (通常情況下是你可以使用的最高速度).在115200 波特傳輸速度下, 每位數據持續(xù) (1/115200) = 8.7s. 如果傳輸8位數據,共持續(xù) 8 x 8.7s = 69s。但是每個字節(jié)的傳輸又要求額外的“開始位”和“停止位”

5、,所以實際上需要花費10 x 8.7s = 87s的時間。最大的有效數據傳輸率只能達到 11.5KBytes每秒。在115200 波特傳輸速度下,一些使用了不好的芯片的計算機要求一個長的停止位(1.5或2位數據的長度),這使得最大傳輸速度降到大約10.5KBytes每秒物理層電纜上的信號使用正負電壓的機制: 1 用 -10V 的電壓表示(或者在 -5V 與 -15V之間的電壓). 0 用 +10V 的電壓表示(或者在 5V 與 15V之間的電壓).所以沒有數據傳輸的電纜上的電壓應該為-10V或-5到-10之間的某個電壓。波特率發(fā)生器這里我們使用串行連接的最大速度115200波特,其他較慢的波特

6、也很容易由此產生。FPGA通常運行在遠高于115200Hz的時鐘頻率上(對于今天的標準的來說RS-232真是太慢了),這就意味著我們需要用一個較高的時鐘來分頻產生盡量接近于115200Hz的時鐘信號。從1.8432MHz的時鐘產生通常RS-232芯片使用1.8432MHz的時鐘,以為這個時鐘很容易產生標準的波特率,所以我們假設已經擁有了一個這樣的時鐘源。只需要將 1.8432MHz 16分頻便可得到 115200Hz的時鐘,多方便??!reg 3:0 BaudDivCnt;always (posedge clk) BaudDivCnt =2000000) printf(*); else prin

7、tf( );acc %= 2000000;這段代碼會精確的以平均每 17.361111111. 個時鐘間隔打印出一個*。為了從FPGA得到同樣的效果,考慮到串行接口可以容忍一定的波特率誤差,所以即使我們使用17.3或者17.4這樣的分頻比也是沒有關系的。FPGA波特率發(fā)生器我們希望2000000是2的整數冪,但很可惜,它不是。所以我們改變分頻比,2000000/115200 約等于 1024/59 = 17.356. 這跟我們要求的分頻比很接近,并且使得在FPGA上實現起來相當有效。/10 位的累加器 (9:0), 1位進位輸出 (10)reg 10:0 acc; /一共11位!always

8、(posedge clk)acc = acc9:0 + 59; /我們使用上一次結果的低10位,但是保留11位結果wire BaudTick = acc10; /第11位作為進位輸出使用 2MHz 時鐘, BaudTick 為 115234 波特, 跟理想的115200波特存在 0.03% 的誤差。參數化的FPGA波特率發(fā)生器前面的設計我們使用的是10位的累加器,如果時鐘頻率提高的話,需要更多的位數。下面是一個使用 25MHz 時鐘和 16 位累加器的設計,該設計是參數化的,所以很容易根據具體情況修改。parameter ClkFrequency = 25000000; / 25MHzpara

9、meter Baud = 115200;parameter BaudGeneratorAccWidth = 16;parameter BaudGeneratorInc = (BaudBaudGeneratorAccWidth)/ClkFrequency;reg BaudGeneratorAccWidth:0 BaudGeneratorAcc;always (posedge clk)BaudGeneratorAcc = BaudGeneratorAccBaudGeneratorAccWidth-1:0 + BaudGeneratorInc;wire BaudTick = BaudGenerato

10、rAccBaudGeneratorAccWidth;上面的設計中存在一個錯誤: BaudGeneratorInc的計算是錯誤的, 因為 Verilog 使用 32 位的默認結果, 但實際計算過程中的某些數據超過了32位,所以改變一種計算方法。parameter BaudGeneratorInc = (Baud5)/(ClkFrequency4);這行程序也使得結果成為整數,從而避免截斷。這就是整個的設計方法了?,F在我們已經得到了足夠精確的波特率,可以繼續(xù)設計串行接收和發(fā)送模塊了。RS-232發(fā)送模塊下面是我們所想要實現的:它應該能像這樣工作: 發(fā)送器接收8位的數據,并將其串行輸出。(TxD_s

11、tart置位后開始傳輸). 當有數傳輸的時候,使busy信號有效,此時“TxD_start”信號被忽略.RS-232模塊的參數是固定的: 8位數據, 2個停止位, 無奇偶校驗.數據串行化假設我們已經有了一個115200波特的BaudTick信號.我們需要產生開始位、8位數據以及停止位。用狀態(tài)機來實現看起來比較合適。reg 3:0 state;always (posedge clk)case(state)4b0000: if(TxD_start) state = 4b0100;4b0100: if(BaudTick) state = 4b1000; / 開始位4b1000: if(BaudTic

12、k) state = 4b1001; / bit 04b1001: if(BaudTick) state = 4b1010; / bit 14b1010: if(BaudTick) state = 4b1011; / bit 24b1011: if(BaudTick) state = 4b1100; / bit 34b1100: if(BaudTick) state = 4b1101; / bit 44b1101: if(BaudTick) state = 4b1110; / bit 54b1110: if(BaudTick) state = 4b1111; / bit 64b1111: if

13、(BaudTick) state = 4b0001; / bit 74b0001: if(BaudTick) state = 4b0010; / 停止位14b0010: if(BaudTick) state = 4b0000; / 停止位2default: if(BaudTick) state = 4b0000;endcase注意看這個狀態(tài)機是怎樣實現當TxD_start有效就開始,但只在BaudTick有效的時候才轉換狀態(tài)的。.現在,我們只需要產生TxD輸出即可.reg muxbit;always (state2:0)case(state2:0)0: muxbit = TxD_data0;1

14、: muxbit = TxD_data1;2: muxbit = TxD_data2;3: muxbit = TxD_data3;4: muxbit = TxD_data4;5: muxbit = TxD_data5;6: muxbit = TxD_data6;7: muxbit = TxD_data7;endcase/將開始位、數據以及停止位結合起來assign TxD = (state4) | (state3 & muxbit);RS232接收模塊下面是我們想要實現的模塊:我們的設計目的是這樣的: 1.當RxD線上有數據時,接收模塊負責識別RxD線上的數據 2.當收到一個字節(jié)的數據時,鎖存

15、接收到的數據到data總線,并使data_ready有效一個周期。注意:只有當data_ready有效時,data總線的數據才有效,其他的時間里不要使用data總線上的數據,因為新的數據可能已經改變了其中的部分數據。過采樣異步接收機必須通過一定的機制與接收到的輸入信號同步(接收端沒有辦法得到發(fā)送斷的時鐘)。這里采用如下辦法。 1.為了確定新數據的到來,即檢測開始位,我們使用幾倍于波特率的采樣時鐘對接收到的信號進行采樣。 2.一旦檢測到開始位,再將采樣時鐘頻率降為已知的發(fā)送端的波特率。典型的過采樣時鐘頻率為接收到的信號的波特率的16倍,這里我們使用8倍的采樣時鐘。當波特率為115200時,采樣時

16、鐘為921600Hz。假設我們已經有了一個8倍于波特率的時鐘信號 Baud8Tick,其頻率為 921600Hz。具體設計首先,接受到的RxD信號與我們的時鐘沒有任何關系,所以采用兩個D觸發(fā)器對其進行過采樣,并且使之我我們的時鐘同步。reg 1:0 RxD_sync;always (posedge clk) if(Baud8Tick) RxD_sync = RxD_sync0, RxD;首先我們對接收到的數據進行濾波,這樣可以防止毛刺信號被誤認為是開始信號。reg 1:0 RxD_cnt;reg RxD_bit;always (posedge clk)if(Baud8Tick)begin if

17、(RxD_sync1 & RxD_cnt!=2b11) RxD_cnt = RxD_cnt + 1; else if(RxD_sync1 & RxD_cnt!=2b00) RxD_cnt = RxD_cnt - 1; if(RxD_cnt=2b00) RxD_bit = 0; else if(RxD_cnt=2b11) RxD_bit = 1;end一旦檢測到開始位,使用如下的狀態(tài)機可以檢測出接收到每一位數據。reg 3:0 state;always (posedge clk)if(Baud8Tick)case(state) 4b0000: if(RxD_bit) state = 4b1000

18、; / start bit found? 4b1000: if(next_bit) state = 4b1001; / bit 0 4b1001: if(next_bit) state = 4b1010; / bit 1 4b1010: if(next_bit) state = 4b1011; / bit 2 4b1011: if(next_bit) state = 4b1100; / bit 3 4b1100: if(next_bit) state = 4b1101; / bit 4 4b1101: if(next_bit) state = 4b1110; / bit 5 4b1110: i

19、f(next_bit) state = 4b1111; / bit 6 4b1111: if(next_bit) state = 4b0001; / bit 7 4b0001: if(next_bit) state = 4b0000; / stop bit default: state = 4b0000;endcase注意,我們使用了next_bit 來遍歷所有數據位。reg 2:0 bit_spacing;always (posedge clk)if(state=0) bit_spacing = 0;elseif(Baud8Tick) bit_spacing = bit_spacing + 1;wire next_bit = (bit_spacing=7);最后我們使用一個移位寄存器來存儲接受到的數據。reg 7:0 RxD_data;always (posedge clk) if(Baud8Tick & next_bit & state3) RxD_data = RxD_bit, RxD_data7:1;怎樣使用發(fā)送和接收模塊這個設計似的我們可以通過計算機的串行口來控制

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論