FT601Q介紹
??FT601Q 是 FTDI 推出的一款超高速 USB3.0 芯片,提供高達(dá) 5Gbps 的帶寬。該芯片不需要額外的固件開發(fā),共有 4 個寫通道和 4 個讀通道,每個通道的緩沖大小均為 4KB。FT601Q 具有多種工作模式,本文介紹并實(shí)現(xiàn)相對簡單的同步 FIFO 模式——245 mode。
??FT601 工作模式在上電時檢測 GPIO0/GPIO1 來確定,當(dāng) {GPIO1,GPIO0}=2‘b00 時,F(xiàn)T601Q 將進(jìn)入 245 工作模式。
??首先對 FT601Q 的引腳功能進(jìn)行介紹,QFN76 封裝如下
- DATA0 - DATA31,數(shù)據(jù)引腳,inout
- BE0 - BE3,Byte Enable 引腳,inout,高電平有效;DATA被分成了4Byte,每個 Byte 占據(jù)一個通道,通道間相互獨(dú)立,通過 BE 引腳進(jìn)行控制
- RESET_N,input,控制 FT601Q 的上電
- SIWU_N,input,保留引腳,必須拉高
- TXE_N,input,USB FIFO 可寫信號,低電平有效
- RXF_N,input,USB FIFO 可讀信號,低電平有效
- WR_N,input,USB FIFO 寫使能,低電平有效
- RD_N,input,USB FIFO 讀使能,低電平有效
- OE_N,input,USB FIFO DATA OUT Enable,數(shù)據(jù)輸出使能信號,低電平有效
- WAKEUP_N,inout,指示 FT601 是否處于休眠狀態(tài),也可以通過拉低該引腳喚醒 FT601Q
- GPIO0、GPIO1,inout,功能較多,本文這里只用到上電時確定工作模式,其余不表
- CLK,output,F(xiàn)T601Q 輸出的時鐘信號,可配置為 66MHz 或 100MHz,默認(rèn) 100MHz。有一點(diǎn)需要注意,在 FT601Q 啟動后,若沒能與上位機(jī)建立通信,F(xiàn)T601 將自動休眠,該時鐘也會消失!因此必須配合上位機(jī) api 進(jìn)行使用
??245 模式下,同步寫時序如下圖
在檢測到 FIFO 可寫信號 TXE_N=L 時,F(xiàn)PGA 拉低 WR_N 以開始寫 FT601Q 內(nèi)部的 FIFO,在 CLK 上升沿,數(shù)據(jù)將被寫入 FIFO 中。我們利用全部的 4 個通道,因此 BE 應(yīng)置為 0b1111。
??同步讀時序如下圖
在檢測到 FIFO 可讀信號 RXF_N=L 時,F(xiàn)PGA 需要拉低 OE_N 與 RD_N 引腳以開始數(shù)據(jù)讀?。y試表明 RD_N 信號可以和 OE_N 同時有效,而不必如時序圖中檢測到 OE_N 有效后才拉低),F(xiàn)T601Q 將在 CLK 的下降沿給出數(shù)據(jù),因此用戶可在上升沿讀到穩(wěn)定的數(shù)據(jù)。該模式下,讀取會用到全部的四個通道,即 USB 芯片給出 BE=0b1111。
FPGA代碼實(shí)現(xiàn)
??為了可以簡單適配各種讀寫時鐘的情況,可以例化兩個異步 FIFO,一個用于寫通道,將寫時鐘 clk 下的數(shù)據(jù)寫入 FIFO_w,而一旦檢測到 FIFO_w 非空,即可將數(shù)據(jù)推送給 USB FIFO。另一個用于讀通道,一旦檢測到 USB FIFO 可讀,就獲取數(shù)據(jù)并存入 FIFO_r,用戶可在讀時鐘 clk 域下從 FIFO_r 中獲取數(shù)據(jù)。
/*
* file : FT601Q.v
* author : 今朝無言
* Lab : WHU-EIS-LMSWE
* date : 2023-04-03
* version : v2.0
* description : usb3.0 芯片 FT601Q-QFN76 讀寫控制
* Copyright ? 2023 WHU-EIS-LMSWE, All Rights Reserved.
*/
// 兩種模式:245 Synchronous FIFO mode、Multi-Channel FIFO mode
// 這里實(shí)現(xiàn) 245 Synchronous FIFO mode
module FT601Q(
input clk, //用于復(fù)位計時及外部FIFO讀寫時鐘
input rst_n,
//---------------FT601Q------------------
input USB_CLK, //FT601Q輸出的時鐘,可配置為66MHz或100MHz
//通過官方提供的上位機(jī)軟件(FT600ChipConfigurationProgUtility_v1.3.0.2),可以配置PID、VID、Clock Freq等一系列屬性
inout [31:0] USB_D, //32bit數(shù)據(jù)總線,I/O
inout [3:0] USB_BE, //Byte Enable,高電平有效 1111 表示使用 4 Channel
input USB_TXE, //FT601Q-FIFO可寫信號(即601Q-FIFO非滿),低電平有效
input USB_RXF, //FT601Q-FIFO可讀信號(即601Q-FIFO非空),低電平有效
output reg USB_OE, //FT601Q-輸出使能(Data Output Enable),低電平有效
output reg USB_RD, //FT601Q-讀使能,低電平有效
output reg USB_WR, //FT601Q-寫使能,低電平有效
inout USB_Wakeup,
//Suspend/Remote Wakeup pin by default Low when USB is active, high when USB is in suspend.
//Application can drive this pin low in in USB suspend to generate a remote wakeup signal to the USB host.
output reg USB_RSTn, //RESET_N,也即USB_EN,控制USB的上電
output USB_SIWU, //reserved,should pull-up
inout USB_GPIO0, //GPIO0
inout USB_GPIO1, //GPIO1
//-------------FPGA Control------------------
input wr_en, //高電平有效
input [31:0] wrdat,
output full,
input rd_en, //高電平有效
output [31:0] rddat,
output empty
);
//-------------------------state define------------------------------
localparam RESET = 8'h01;
localparam IDLE = 8'h02;
localparam WRITE = 8'h04; //若write fifo非空,且usb fifo可寫,將數(shù)據(jù)推入USB,寫優(yōu)先
localparam READ = 8'h08; //若usb fifo可讀,且read fifo非滿,將數(shù)據(jù)讀到read fifo
//------------------------------------------------------------------
reg [7:0] state = RESET;
reg [7:0] next_state = RESET;
wire w_fifo_full;
wire w_fifo_empty;
wire r_fifo_full;
wire r_fifo_empty;
reg w_fifo_rden = 1'b0;
reg r_fifo_wren = 1'b0;
wire fifo_rst;
assign fifo_rst = ~rst_n;
reg [7:0] rst_cnt = 8'd0;
//----------------------------iobuf---------------------------------
wire [31:0] USB_D_buf;
reg USB_D_link = 1'b0;
assign USB_D = (USB_D_link)? USB_D_buf : 32'dz;
wire GPIO0_buf;
wire GPIO1_buf;
reg GPIO_link = 1'b0;
assign GPIO0_buf = 1'b0;
assign GPIO1_buf = 1'b0;
assign USB_GPIO0 = (GPIO_link)? GPIO0_buf : 1'bz;
assign USB_GPIO1 = (GPIO_link)? GPIO1_buf : 1'bz;
wire [3:0] USB_BE_buf;
reg USB_BE_link = 1'b0;
assign USB_BE_buf = 4'b1111;
assign USB_BE = (USB_BE_link)? USB_BE_buf : 4'dz;
//-------------------------write fifo--------------------------------
//異步FIFO 采用 First Word Fall Through 模式
fifo_generator_ft60x fifo_w(
.rst (fifo_rst),
.wr_clk (clk),
.rd_clk (USB_CLK),
.din (wrdat),
.wr_en (wr_en),
.rd_en (w_fifo_rden),
.dout (USB_D_buf),
.full (w_fifo_full),
.empty (w_fifo_empty)
);
//--------------------------read fifo--------------------------------
//異步FIFO
fifo_generator_ft60x fifo_r(
.rst (fifo_rst),
.wr_clk (USB_CLK),
.rd_clk (clk),
.din (USB_D),
.wr_en (r_fifo_wren),
.rd_en (rd_en),
.dout (rddat),
.full (r_fifo_full),
.empty (r_fifo_empty)
);
//-----------------------------FSM----------------------------------
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
state <= RESET;
rst_cnt <= 8'd0;
end
else begin
state <= next_state;
if(rst_cnt < 8'd200) begin
rst_cnt <= rst_cnt + 1'b1;
end
else begin
rst_cnt <= rst_cnt;
end
end
end
always @(*) begin
case(state)
RESET: begin
if(rst_cnt >= 8'd200) begin
next_state <= IDLE;
end
else begin
next_state <= RESET;
end
end
IDLE: begin
if((~USB_TXE) && (~w_fifo_empty)) begin
next_state <= WRITE;
end
else if((~USB_RXF) && (~r_fifo_full)) begin
next_state <= READ;
end
else begin
next_state <= IDLE;
end
end
WRITE: begin
if(USB_TXE || w_fifo_empty) begin
next_state <= IDLE;
end
else begin
next_state <= WRITE;
end
end
READ: begin
if(USB_RXF || r_fifo_full) begin
next_state <= IDLE;
end
else begin
next_state <= READ;
end
end
default: begin
next_state <= IDLE;
end
endcase
end
//----------------------------Control--------------------------------
assign full = w_fifo_full;
assign empty = r_fifo_empty;
assign USB_SIWU = 1'b1;
always @(posedge clk) begin
case(state)
RESET: begin
GPIO_link <= 1'b1;
end
default: begin
GPIO_link <= 1'b0;
end
endcase
end
always @(*) begin
case(state)
RESET: begin
USB_RSTn <= 1'b0;
end
default: begin
USB_RSTn <= 1'b1;
end
endcase
end
always @(*) begin
case(state)
WRITE: begin
USB_D_link <= 1'b1;
end
default: begin
USB_D_link <= 1'b0;
end
endcase
end
// ------------USB FIFO write--------------
always @(*) begin
case(state)
WRITE: begin
USB_BE_link <= 1'b1;
USB_WR <= ((~USB_TXE) & (~w_fifo_empty))? 1'b0 : 1'b1;
w_fifo_rden <= ((~USB_TXE) & (~w_fifo_empty))? 1'b1 : 1'b0;
end
default: begin
USB_BE_link <= 1'b0;
USB_WR <= 1'b1;
w_fifo_rden <= 1'b0;
end
endcase
end
// ------------USB FIFO read---------------
always @(*) begin
case(state)
READ: begin
USB_OE <= ((~USB_RXF) & (~r_fifo_full))? 1'b0 : 1'b1;
USB_RD <= ((~USB_RXF) & (~r_fifo_full))? 1'b0 : 1'b1;
end
default: begin
USB_OE <= 1'b1;
USB_RD <= 1'b1;
end
endcase
end
always @(posedge USB_CLK) begin
case(state)
READ: begin
r_fifo_wren <= ((~USB_RXF) & (~r_fifo_full))? 1'b1 : 1'b0;
end
default: begin
r_fifo_wren <= 1'b0;
end
endcase
end
endmodule
環(huán)回測試
??使用官方提供的上位機(jī) Loopback 測試程序進(jìn)行測試,結(jié)果如下
??由測試結(jié)果可以看到,F(xiàn)T601Q是小端傳輸,首先發(fā)送 B0(將接收到的第一個字節(jié)放在 B0),然后發(fā)送 B1(將接收到的第二個字節(jié)放在 B1),依次類推 B2、B3 的收發(fā)次序。例如本次 LoopBack 測試,發(fā)送的 0x764dfffe,在 FPGA 接收到的是 0xfeff4d76,直接轉(zhuǎn)發(fā)回上位機(jī),又得 0x764dfffe,實(shí)際使用時請務(wù)必注意這個問題!
something
??在上位機(jī)測試時遇到的一些坑,在此記錄:
- 使用 Python 進(jìn)行調(diào)試(D3XXPython_Release)時提示缺失 dll:需要將 FTD3XXLibray 壓縮包中的 FTD3XX.dll 添加到路徑
- 啟動 LoopbackDemo、StreamerDemo 后,檢測不到 USB 設(shè)備,然而查看設(shè)備管理器可以看到該設(shè)備:是因?yàn)槿鄙?FTDI 驅(qū)動,安裝驅(qū)動(ftdi_ft60x_1.2.0.5)后即可解決
以上壓縮包和驅(qū)動均能在 FTDI 官網(wǎng)找到。文章來源:http://www.zghlxwxcb.cn/news/detail-448400.html
??FT600ChipConfigurationProgUtility 壓縮包中是 FT600/FT601Q 的配置程序,通過該程序可以修改芯片的 VID、PID、Serial Number、Clock Frequency 等。文章來源地址http://www.zghlxwxcb.cn/news/detail-448400.html
到了這里,關(guān)于USB3.0芯片F(xiàn)T601Q簡介及FPGA實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!