今天給大俠帶來基于FPGA的USB2.0設計,附源碼,獲取源碼,請在“FPGA技術江湖”公眾號內回復“ USB2.0設計源碼”,可獲取源碼文件。話不多說,上貨。
2019年9月4日,USB-IF終于正式公布USB 4規范。它引入了Intel此前捐獻給USB推廣組織的Thunderbolt雷電協議規范,雙鏈路運行(Two-lane),傳輸帶寬因此提升,與雷電3持平,都是40Gbps。需要注意的是,你想要體驗最高傳輸速度,就必須使用經過認證的全新數據線。USB4保留了良好的兼容性,可向下兼容USB 3.2/3.1/3.0、雷電3。除此之外,USB4將只有USB Type-C一種接口,并支持多種數據、顯示協議,包括DisplayPort,可以一起充分利用高速帶寬,也支持USB PD供電。
比較遺憾的是,USB4的發布時間暫未公布。值得注意的是,此次發布的USB4是規范,而并非USB4.0。在此之前,USB Implementers Forum(USB-IF)計劃取消USB 3.0/3.1命名,統一劃歸為USB 3.2。其中USB 3.0更名USB 3.2 Gen 1(5Gbps),USB 3.1更名USB 3.2 Gen 2(10Gbps),USB 3.2更名為USB 3.2 Gen 2x2(20Gbps)。
以上就是關于USB標準以及命名的訊息,而今天我們要做設計的是USB2.0,USB2.0的設備是按照2.0的電源標準設計的,設備所需的電流小于500mA,而USB3.0接口可以提供更大的電流,所以用在USB3.0接口是安全的,這就是標準向下兼容的道理。反之,USB3.0的設備,是否能夠在USB2.0接口使用,就要查看設備的說明書。通常的電源都是電壓源,設備與電源的電壓必須相等,而電源的輸出電流要大于設備的電流,即電源功率要大于設備功率。
現在大部分USB設備(比如USB接口的鼠標、鍵盤、閃存、U盤等等)都是采用了USB通用驅動,而你的系統有USB通用驅動的話(比如XP就內建了USB通用驅動)就能用。而有些USB設備是需要特殊驅動的,比如某些手機,連接到電腦的USB口,是需要安裝驅動才能使用的。下面我們一起動手做一做,了解一下如何設計。
設計原理
USB(Universal Serial Bus2.0,通用串行總線)是一種應用在計算機領域的新型接口技術。USB接口具有傳輸速度更快,支持熱插拔以及連接多個設備的特點。目前已經在各類外部設備中廣泛的被采用。USB接口有三種:USB1.1,USB2.0和USB3.2。理論上USB1.1的傳輸速度可以達到12Mbps,而USB2.0則可以達到速度480Mbps,并且可以向下兼容USB1.1。
本次設計我們選擇一款開發設備,一塊廉價的開發板,其中的USB芯片是Cypress的FX2LP系列中的CY7C68013A代,詳細的介紹大家可以去Cypress的官網查詢。下面簡述一下設計思路。
FX2的設計架構如下圖,內嵌480MBit/s的收發器,鎖相環PLL,串行接口引擎SIE——集成了整個USB 2.0協議的物理層。為適應USB 2.0的480MBit/s的速率,FIFO端點可配置成2,3,4個緩沖區。配置用的是“軟配置”——USB固件可由USB總線下載,片上不需集成ROM。擁有四個FIFO接口,可工作在內部或外部時鐘下。端點和FIFO接口的應用使外部邏輯和USB總線可高速連接。
基于FX2LP的USB開發,包括三部分:固件程序、驅動、上位機軟件。 固件程序我們在kiil中寫出來,然后配置到我們的芯片中,固件的開發對于FPGA工程師來說是不用寫的,是其他工程師配置好芯片后我們直接拿來使用,其主要的配置過程如下圖。
先上電復位,然后初始化寄存器變量,然后調用配置函數,打開中斷后,判斷是否接受到了配置包,如果接收到了就調用TD_POLL()函數,這個是函數是不停的執行掃描端點等。然后判斷芯片是否掛起,如果掛起就叫醒芯片,如果沒有就一直調用TD_POLL函數,這樣就完成所需要的配置。
這里的項目設計要求是要把FX2配置成從FIFO的模式, 配置為單片機工作時鐘24M,端點2輸出,字節1024,端點6輸入,字節1024,信號全設置為低電平有效等。模塊驅動時鐘配置成內部輸出時鐘,也就是讓FX2給項目設計當作時鐘源,輸出一個最大的配置時鐘48M的時鐘。FX2的數據存儲區叫端點,有512、1024字節兩個存儲大小之分。
從FIFO說明
當有一個與FX2芯片相連的外部邏輯只需要利用FX2做為一個USB 2.0接口而實現與主機的高速通訊,而它本身又能夠提供滿足Slave FIFO要求的傳輸時序,可以做為Slave FIFO主控制器時,即可考慮用此傳輸方式。?
Slave FIFO傳輸的示意圖如下:?
在這種方式下,FX2內嵌的8051固件的功能只是配置Slave FIFO相關的寄存器以及控制FX2何時工作在Slave FIFO模式下。一旦8051固件將相關的寄存器配置完畢,且使自身工作在Slave FIFO模式下后,外部邏輯(如FPGA)即可按照Slave FIFO的傳輸時序,高速與主機進行通訊,而在通訊過程中不需要8051固件的參與。
FX2系列的有3種封裝方式,我們我的開發板用的是56引腳的封裝方式的電路圖,其電路圖如下所示:
端口介紹
IFCLK:FX2輸出的時鐘,可做為通訊的同步時鐘。
SLCS:FIFO的片選信號,外部邏輯控制,當SLCS輸出高時,不可進行數據傳輸。
SLOE:FIFO輸出使能,外部邏輯控制,當SLOE無效時,數據線不輸出有效數據。
SLRD:FIFO讀信號,外部邏輯控制,同步讀時,FIFO指針在SLRD有效時的每個IFCLK的上升沿遞增。
SLWR:FIFO寫信號,外部邏輯控制,同步寫時,在SLWR有效時的每個IFCLK的上升沿時數據被寫入,FIFO指針遞增。
FD[15:0]:數據線。
FIFOADR[1:0]:選擇四個FIFO端點的地址線,外部邏輯控制。
FLAG A,B,C端點的空滿標志位。
開發驅動大家可以在網上找,然后根據自己系統裝上合適的驅動。上位機軟件用的是官方的開發工具,只有如下的安裝包,然后安裝第一個和第二個就好了。
設計代碼
總模塊usb:
module usb(pi_clk, clk, pi_rst_n, pi_usb_flagb, pi_usb_flagc, pio_usb_data, po_usb_oe_n, po_usb_wr_n, po_usb_address, po_usb_rd_n, led); input clk; input pi_clk; input pi_rst_n; input pi_usb_flagb; input pi_usb_flagc; inout [15:0] pio_usb_data; output po_usb_oe_n; output po_usb_wr_n; output po_usb_rd_n; output [1:0] po_usb_address; output led; wire po_rst_n; delay delay_dut( .pi_clk(pi_clk), .pi_rst_n(pi_rst_n), .po_rst_n(po_rst_n) ); usb_wr wr_dut( .pi_clk(pi_clk), .pi_rst_n(po_rst_n), .pi_usb_flagb(pi_usb_flagb), .pi_usb_flagc(pi_usb_flagc), .pio_usb_data(pio_usb_data), .po_usb_oe_n(po_usb_oe_n), .po_usb_wr_n(po_usb_wr_n), .po_usb_address(po_usb_address), .po_usb_rd_n(po_usb_rd_n) ); my_pll my_pll_inst ( .areset ( ~ pi_rst_n ), .inclk0 ( clk ), .c0 ( c0_sig ), .locked ( locked_sig ) ); ?? endmodule
讀模塊usb_rd:
module usb_rd(pi_clk, pi_rst_n, pi_usb_flagb, pi_usb_flagc, pio_usb_data, po_usb_oe_n, po_usb_rd_n, po_usb_address, po_usb_wr_n, led); input pi_clk; input pi_rst_n; input pi_usb_flagb; //端點2標志信號 input pi_usb_flagc; //端點6標志信號 inout [15:0] pio_usb_data; //輸入輸出端口 output reg po_usb_oe_n; //讀標志信號 output reg po_usb_rd_n; //寫使能 output reg po_usb_wr_n; //讀使能 output reg [1:0] po_usb_address; //端點地址選擇 output reg led; reg [15:0] temp_data; reg [9:0] count; reg [2:0] state; assign pio_usb_data = (state == 10) ? 1 : 16'hzzzz; //讀數據,可以一直釋放數據總線的控制權 always @ (posedge pi_clk or negedge pi_rst_n) if(!pi_rst_n) begin state <= 0; po_usb_oe_n <= 1; po_usb_rd_n <= 1; count <= 0; po_usb_wr_n <= 1; temp_data <= 0; end else case (state) 0 : state <= 1; 1 : begin po_usb_address <= 2'b00; //地址指向端點2 state <= 2; end 2 : if(!pi_usb_flagb) //判斷端點2已經滿 begin po_usb_rd_n <= 0; state <= 3; po_usb_oe_n <= 0; end else state <= 2; 3 : begin if(count < 512 - 1) //接收1024字節的數據 begin count <= count + 1'b1; end else begin count <= 0; state <= 4; end if (count == 2) begin temp_data <= pio_usb_data; end end 4 : begin po_usb_rd_n <= 1; po_usb_oe_n <= 1; state <= 0; end default: state <= 0; endcase always @ (*) if(!pi_rst_n) led <= 1; else if (temp_data == 16'h33ff) led <= 0; endmodule
寫模塊 usb_wr:
module usb_wr(pi_clk, pi_rst_n, pi_usb_flagb, pi_usb_flagc, pio_usb_data, po_usb_oe_n, po_usb_wr_n, po_usb_address, po_usb_rd_n); input pi_clk; input pi_rst_n; input pi_usb_flagb; //端點2標志信號 input pi_usb_flagc; //端點6標志信號 inout [15:0] pio_usb_data; //輸入輸出端口 output reg po_usb_oe_n; //讀標志信號 output reg po_usb_wr_n; //寫使能 output reg po_usb_rd_n; //讀使能 output reg [1:0] po_usb_address; //端點地址選擇 reg [15:0] temp_data; reg [2:0] state; //在狀態的3,拿回數據總線控制全,給寫入數據 assign pio_usb_data = (state == 3) ? temp_data : 16'hzzzz; always @ (posedge pi_clk or negedge pi_rst_n) if(!pi_rst_n) begin state <= 0; po_usb_oe_n <= 1; po_usb_wr_n <= 1; temp_data <= 0; po_usb_rd_n <= 1; end else case (state) 0 : state <= 1; 1 : begin po_usb_address <= 2'b10; //地址指向端點6 state <= 2; end 2 : if(!pi_usb_flagc) //判斷端點6已經空 begin po_usb_wr_n <= 0; state <= 3; end else state <= 2; 3 : if(temp_data < 512 - 1) //發送1024字節的數據 temp_data <= temp_data + 1'b1; else begin temp_data <= 0; state <= 4; end 4 : begin po_usb_wr_n <= 1; state <= 0; end default: state <= 0; endcase endmodule
延時模塊?delay:
module delay(pi_clk, pi_rst_n, po_rst_n); input pi_clk; input pi_rst_n; output reg po_rst_n; parameter T1ms = 50000; reg [15:0] count; always @ (posedge pi_clk or negedge pi_rst_n) if(!pi_rst_n) begin count <= 0; po_rst_n <= 0; end else begin if(count < T1ms - 1) count <= count + 1; else begin count <= count; po_rst_n <= 1; end end endmodule
上位機測試
安裝好驅動和下載的上位機軟件,然后在下面的界面中,點擊”LGEEPROM”按鈕,下載我們寫好的的.IIC固件。
然后在下面的頁面中會出現先選擇other endpt xfers選項中會出現4個端點,然后選擇寫入的端點或者讀的端點執行讀寫操作。
寫的端點是6端點,選擇這個端點,寫入端點是1024個字節,這里設置的是512字節,也就是寫入2次就可以寫滿了,如下圖,和我們編寫的代碼中寫入數據值是一樣的。
讀操作也就是要讀端點2,我們先要給端點一個數,然后才能讀我們的端點,我們寫入圖中顯示的數,因為我們設計的是讀出的數,如果第三個數位33ff ,就讓我們的燈亮,值得一說的是,我們上位機顯示的時候是把低位顯示到了前面,高位顯示到了后面,我們一個包是1024字節,后面的數自動補零,讀出數據后可以看到我們的led燈亮,驗證出我們的設計正確。
以上就是我們的基于FPGA的usb2.0設計了,希望能給各位大俠起到參考學習作用,此次設計到此結束,有緣再見,告辭。
審核編輯:黃飛
?
評論
查看更多