FPGA学习之路—接口(1)—URAT Verilog程序设计
FPGA學習之路——URAT Verilog程序設計
UART(Universal Asynchronous Receiver Transmitter,通用異步收發器)是廣泛使用的異步串行數據通信協議。
UART是一種通用串行數據總線,用于異步通信。該總線雙向通信,可以實現全雙工傳輸和接收。
- Tx—數據發送接口
- Rx—數據接收接口
兩個設備間將TX與RX相連,RX與TX相連即可正常工作。最常用到的就是我們電腦上的USB那就是個最典型的UART接口。
UART傳輸時序
UART傳輸時序圖如下圖所示
發送數據過程: 空閑狀態,線路位于高電平;當接收到發送數據指令后,拉低線路一個數據位的時間T,接著數據按低位到高位依次發送,數據發送完畢后,接著發送奇偶校驗位和停止位(停止位為高電平),一幀數據發送完畢。
接收數據過程: 空閑狀態,線路處于高電平;當檢測到線路的下降沿(線路點位由高電位變為低電位)時說明線路有數據傳輸,按規定的波特率從低位到高位接收數據,數據接收完畢后,接著接收并比較奇偶校驗位是否正確,若正確則通知后續設備準備接收或存入緩存。
因為UART是異步傳輸,沒有同步時鐘。所以為了保證數據傳輸的正確性,UART采用16倍數據波特率的時鐘進行采樣。每個數據有16個時鐘采樣,取中間的采樣值。
UART的接收數據時序為:當檢測到數據的下降沿時,表明線路上有數據在傳輸,這時計數子CNT開始計數,當計數器為24=16+8(去除開始的拉低數據,在第0位數據中間采樣)時,采樣的值為第0位數據;當計數子的值為40時,采樣的為第一位數據,以此類推。若進行奇偶校驗,則當計數子的值為152時,采樣的值即為奇偶位;當計數子的值為168時,采樣的值“1”表示停止位,表示一幀數據接收完成。
假設數據的波特率為b,那么時鐘頻率就是16b。以b=115200,系統時鐘為50MHz為例,則分頻系數為50,000,000/(16115200)=27.127,取整為27。分頻器Verilog HDL代碼如下:
module clkdiv(clk,rst,clkout); input clk; input rst; output clkout;reg clkout; reg [15:0] cnt;always @(negedge rst)beginclkout<=1'd1;cnt<=16'd0; endalways @(posedge clk)beginif(cnt==16'd12)beginclkout<=1'd1;cnt<=cnt+16'd1;endelse if(cnt==16'd26)beginclkout<=1'd0;cnt<=16'd0;endelse begincnt<=cnt+16'd1;end end endmodule編碼過程中需注意,若部分寄存器不通過rst賦初值,如代碼塊中的cnt和clk_out,則Vivado會報錯,Vivado版本為2018.3,目前我也只想到引入rst進行賦值的方法解決。
更:可以在定義寄存器時直接賦初值。如reg [7:0]cnt =8’d0;
此外,UART發送和接受模塊中部分代碼如下,完整代碼我稍后上傳至CSDN,有需的朋友可以下載參考。
上升沿檢測代碼,其中wrsig發送命令,上升沿有效。該部分代碼完成了wrsig的上升沿檢測。
啟動數據發送進程的代碼,需滿足發送命令有效且線路空閑的條件
always @(posedge clk)beginif(wrsigrise && (~idle))begin //發送命令有效且線路空閑,啟動數據發送進程send<=1'd1;endelse if(cnt == 8'd176)begin //一幀數據發送結束send<=1'd0;end end數據發送進程中的部分代碼,設計思路在上文中已表述,其中paritymode為常數0,用于奇偶校驗;datain為待傳輸的數據;presult存放數據校驗的結果;cnt為32—112的被省略。在cnt為144時發送奇偶校驗位,然后拉高電平,表示傳輸過程結束。接收進程編碼思路與發送進程類似,此處不表。
always @(posedge clk)beginif(send == 1'd1)begincase(cnt)8'd0:begintx<=1'd0;idle<=1'd1;cnt<=cnt+8'd1;end8'd16:begintx<=datain[0];presult<=datain[0]^paritymode;idle<=1'b1;cnt<=cnt+8'd1;end……8'd128:begintx <= datain[7];presult <= datain[7]^presult;idle <= 1'b1;cnt <= cnt + 8'd1;end8'd144:begintx<=presult;idle <= 1'b1;cnt <= cnt + 8'd1;end8'd160:begintx<=1'd1;idle<=1'd1;cnt<=cnt+1'd1;end8'd176:begintx<=1'd1;idle<=1'd0;cnt<=cnt+8'd1;enddefault:begincnt<=cnt+8'd1;end endcaseendelse begintx<=1'd1;cnt<=8'd0;idle<=1'b0;end end本文搭建的系統結構圖如下,clkdiv為分頻模塊;testuart為激勵產生模塊,輸出待發送的數據和發送使能;uarttx為uart發送模塊,輸入為分頻后的時鐘、待發送的數據和發送使能,輸出為數據信號tx和idle,idle為線路指示狀態,高為線路忙,低為空閑;uartrx為uart接收模塊,輸入為分頻后的時鐘和數據信號,輸出為數據、數據出錯指示和幀出錯指示。
本文搭建系統的仿真結果如下圖所示:
從圖中我們可以看到,接受數據與發送數據結果相同。若接收數據的奇偶校驗位與收到的奇偶校驗位不符,則dataerror為1。若接收幀的第11位即停止位不為1,則幀發生錯誤,frameerror為1。文中結果均未發生錯誤。
項目下載鏈接
參考資料:《VERILOG HDL應用程序設計實例精講》
總結
以上是生活随笔為你收集整理的FPGA学习之路—接口(1)—URAT Verilog程序设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vivado不识别HLS生成的IP解决方
- 下一篇: unix-ln 命令