一、背景

高通量在体神经信号采集系统,随着通道数增加、增加实时刺激需求等,采用以太网传输面临带宽极限,亟需一种更快的传输介质。

目前以太网的带宽极限:实测800Mbit/s左右,[移植并使用Iperf3测试ARM Linux网口带宽]https://www.cnblogs.com/dy-stairmed/p/18796116

在8port 30K采集速率下:16*64*2*8*30k = 491.5Mbit/s接近传输极限。

因此采用USB3.0 传输,理论传输带宽:5Gb/s。通过前期调研,目前USB3.0 PHY方案一般通过 FPGA实现。

二、硬件方案

FT601Q FIFO-USB3.0 Bridge,理论:400MB/s,连接至ZYNQ_PL端。

三、逻辑架构设计

  1. 系统框图

采用两个异步fifo实现多比特跨时钟域处理,将硬件接口转换为 FIFO的读写接口,后续可以根据应用调整为

AXI-STREAM接口。



2. 引脚定义:



3. 拟实现的读写时序



四、代码

  1. 驱动module

点击查看代码
/*
* file : FT601Q.v
* author : D.y
* date : 2025-03-19
* version : v0.1
* description : usb3.0 FT601Q-QFN76 write and read control rtl.use 245 Synchronous FIFO mode.first release
use async fifo to deal with multi bit cross clock domain
actual test result: 380MB/s for read,340MB/s for write
*
*/ module FT601Q(
input clk, //sysclk,50Mhz at least
input rst_n, //active low //---------------FT601Q------------------
input USB_CLK, //FT601Q phy output clk, configure to 100MHz using FT600ChipConfigurationProgUtility_v1.3.0.2)
inout [31:0] USB_D, //32bit data inout,I/O
inout [3:0] USB_BE, //Byte Enable,active high,4'b1111 means using 4 Channel input USB_TXE, //FT601Q-FIFO write enable?601Q-FIFO not full),active low
input USB_RXF, //FT601Q-FIFO read enable ?601Q-FIFO not empty),active low output reg USB_OE, //FT601Q Data Output Enable active low
output reg USB_RD, //FT601Q-read enable,active low
output reg USB_WR, //FT601Q-write enable,active low 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,enable use
output USB_SIWU, //reserved,should pull-up
inout USB_GPIO0, //GPIO0
inout USB_GPIO1, //GPIO1 //-------------FPGA Control------------------
input wr_en, //active high
input [31:0] wrdat,
output full, input rd_en, //active high
output [31:0] rddat,
output empty
); //-------------------------state define------------------------------
localparam RESET = 8'h01;
localparam IDLE = 8'h02;
localparam WRITE = 8'h04; //write fifo not empty,and USB_TXE keep low ,push data into USB
localparam READ = 8'h08; //USB_RXF keep low,and read fifo not full,read data to read fifo //-------------------------signal define-----------------------------
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;
reg [7:0] rst_cnt = 8'd0; assign fifo_rst = ~rst_n; //----------------------------iobuf---------------------------------
wire [31:0] USB_D_buf;
(* mark_debug = "true" *) 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;
reg [31:0] USB_DATA;
reg r_fifo_wren_r1;
assign USB_BE_buf = 4'b1111;
assign USB_BE = (USB_BE_link)? USB_BE_buf : 4'dz; (* mark_debug = "true" *) wire [31:0] debug_data ; //----------------------------logic---------------------------------
// for debud only
assign debug_data = USB_D;
//always @(posedge USB_CLK) begin
// if(USB_BE_link)
// debug_data <= USB_D;
// else
// debug_data <= 'd0;
//end //-------------------------write fifo--------------------------------
//async FIFO First Word Fall Through mode
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--------------------------------
//always @(posedge USB_CLK or negedge rst_n) begin
// if(~rst_n) begin
// USB_DATA <= 'b0;
// r_fifo_wren_r1 <= 1'b0;
// end
// else begin
// USB_DATA <= USB_D;
// r_fifo_wren_r1 <= r_fifo_wren;
// end
//end
//异步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

2. ## 例化top:

点击查看代码
/*
* file : top.v
* author : D.y
* date : 2025-03-19
* version : v0.1
* description : top module for FT601Q USB3.0 PHY
install FT601 MODULE,and generate sys_rst_n and system clk soure 100Mhz
*
*/
module top(
input sys_clk , // using outside 200M OSC
// inout GPIO_0_0_tri_io ,
// inout IIC_0_0_scl_io ,
// inout IIC_0_0_sda_io ,
// output MDIO_ETHERNET_0_0_mdc,
// inout MDIO_ETHERNET_0_0_mdio_io,
//FT601
input USB_CLK ,
inout [31:0] USB_D ,
inout [3:0] USB_BE ,
input USB_TXE ,
input USB_RXF ,
output USB_OE ,
output USB_RD ,
output USB_WR ,
inout USB_Wake ,
output USB_RSTn ,
output USB_SIWU ,
inout USB_GPIO_0 ,
inout USB_GPIO_1
); //wire define
wire clk_50M ;
wire clk_200M_nRst ;
wire pll_locked ;
wire sys_rst_n ;
wire empty ;
wire fifo_full ;
reg fifo_wr_en ;
reg fifo_rd_en ;
reg [15:0] test_data ='d0 ;
wire [31:0] loop_back_data ;
wire [31:0] rd_data ; // delay reset, active low
delayed_nReset U_delayed_nReset
(
.CLK(sys_clk),
.nRst(clk_200M_nRst)
); // mmcm for output 100Mhz sysclk
clk_wiz_0 my_clk_wiz_0
(
// Clock out ports
.clk_out1(clk_50M), // output clk_out1
// Status and control signals
.reset(~clk_200M_nRst), // input reset
.locked(pll_locked), // output locked
// Clock in ports
.clk_in1(sys_clk)
); // input clk_in1 assign sys_rst_n = pll_locked; //my_block_design_wrapper my_block_design_wrapper_ins
// (
// .MDIO_ETHERNET_0_0_mdc (MDIO_ETHERNET_0_0_mdc) ,
// .MDIO_ETHERNET_0_0_mdio_io (MDIO_ETHERNET_0_0_mdio_io) ,
// .GPIO_0_0_tri_io (GPIO_0_0_tri_io),
// .IIC_0_0_scl_io (IIC_0_0_scl_io),
// .IIC_0_0_sda_io (IIC_0_0_sda_io),
// .clk_out1_0 (clk_50M),
// .locked_0 (pll_locked)
// ); //-------------------------write data test-------------------------------
// USB_TXE is low , fifo write enable,and toggle data
always @(posedge clk_50M or negedge sys_rst_n) begin
if(~sys_rst_n) begin
fifo_wr_en <= 1'b0;
test_data <= 'd0;
end
else begin
if(~USB_TXE) begin
fifo_wr_en <= 1'b1;
test_data <= test_data + 1'b1;
end
else begin
fifo_wr_en <= 1'b0;
test_data <= 'd0;
end
end
end //-------------------------read data test-------------------------------
//USB_RD is low ,fifo read enable,read data from fifo
always @(posedge USB_CLK or negedge sys_rst_n) begin
if(~sys_rst_n) begin
fifo_rd_en <= 1'b0;
end
else begin
if(~USB_RXF) begin
fifo_rd_en <= 1'b1;
end
else begin
fifo_rd_en <= 1'b0;
end
end
end FT601Q FT601Q_ins
(
.clk (clk_50M) ,
.rst_n (sys_rst_n) ,
.USB_CLK (USB_CLK) ,
.USB_D (USB_D) ,
.USB_BE (USB_BE) ,
.USB_TXE (USB_TXE) ,
.USB_RXF (USB_RXF) ,
.USB_OE (USB_OE) ,
.USB_RD (USB_RD) ,
.USB_WR (USB_WR) ,
.USB_Wakeup(USB_Wake) ,
.USB_RSTn (USB_RSTn) ,
.USB_SIWU (USB_SIWU) ,
.USB_GPIO0 (USB_GPIO_0) ,
.USB_GPIO1 (USB_GPIO_1) ,
.wr_en (fifo_wr_en) ,
.wrdat ({test_data,test_data}) ,
.full (fifo_full) ,
.rd_en (fifo_rd_en) ,
.rddat (rd_data) ,
.empty (empty )
); (* mark_debug = "true" *) wire [31:0] top_debug_data = rd_data;
//fifo_generator_ft60x my_fifo_generator_ft60x (
// .rst(~sys_rst_n), // input wire rst
// .wr_clk(USB_CLK), // input wire wr_clk
// .rd_clk(USB_CLK), // input wire rd_clk
// .din(rd_data), // input wire [31 : 0] din
// .wr_en(fifo_rd_en), // input wire wr_en
// .rd_en(fifo_wr_en), // input wire rd_en
// .dout(loop_back_data), // output wire [31 : 0] dout
// .full(), // output wire full
// .empty() // output wire empty
//); endmodule

五、测试过程

  1. 驱动安装(需要使用支持 USB3.0 的USB-TYPE B线缆,)



同时电脑的USB接口也需要支持USB3.0,带SS(Super Speed)标志



插入后,windows会自行安装设备驱动,通过设备管理器可以识别如下:



通过Vivado创建项目,并进行引脚约束,生成bitstream,烧录。

  1. 测试工具

使用官方提供的流测试工具:FT600DataStreamerDemoApp_v1.3.0.10

下载链接如下:

https://ftdichip.com/software-examples/ft600-601-software-examples-2/

六、测试结果

  1. 写速率(上位机---> FPGA****),382MB/s.

  1. 读速率(FPGA ---->上位机),344MB/s

需要使用支持 USB3.0 的USB-TYPE B线缆,

USB3.0 PHY方案(FT601Q)在 FPGA上的速率验证的更多相关文章

  1. AC6102开发板USB3.0测试和使用说明

    AC6102开发板USB3.0测试和使用说明 概述 AC6102上集成了一颗Cypress 推出的高性能USB3.0传输芯片CYUSB3014,Cypress称之为EZ-USBFX3.该芯片性能强劲, ...

  2. USB3.0测试和使用说明

    概述 AC6102上集成了一颗Cypress 推出的高性能USB3.0传输芯片CYUSB3014,Cypress称之为EZ-USBFX3.该芯片性能强劲,功能强大,接口简单,非常适合用于各种需要高速数 ...

  3. CC1605&CC1604 usb3.0+FPGA 高速视频采集 双目相机测评

    CC1605&CC1604 usb3.0+FPGA 高速视频采集 双目相机测评 摄像头配置:ov5640.OV5642.mt9p031.mt9m001c12stm OV5640 xclk:24 ...

  4. Capstone CS5266替代AG9311 Type-C转HDMI带PD3.0+USB3.0拓展坞方案

    Capstone CS5266替代AG9311   Type-C转HDMI带PD3.0+USB3.0拓展坞方案CS5266是 Capstone 最新推出的一款用于USB TYPE-C端口的高度集成.高 ...

  5. Capstone CS5268DEMOBOARD原理图|TYPEC转HDMI+VGA+PD3.0+USB3.0扩展坞方案

    Capstone CS5268DEMOBOARD原理图|TYPEC转HDMI+VGA+PD3.0+USB3.0四合一设计参考 CS5268 是typec转HDMI+VGA+pd3.0+U3四合一拓展坞 ...

  6. TYPEC转HDMI+PD+USB3.0拓展坞三合一优化方案|CS5266 dmeoboard原理图

    CS5266 Capstone 是Type-C转HDMI带PD3.0快充的音视频转换芯片. CS5266接收器端口将信道配置(CC)控制器.电源传输(PD)控制器.Billboard控制器和displ ...

  7. [Xilinx笔记] 《FPGA伴你玩转USB3.0与LVDS》 读书笔记

    2019年10月15日09:31:10 第一部分·哪些要看(优先级由高到低) 0.8.1   LVDS数据收发实例 8.2   带CRC校验的LVDS数据收发实例 1.3.6   USB3.0 控制器 ...

  8. CYPRESS最新的USB3.0控制器

    CYPRESS近日发布了其最新的USB3.0控制器,产品序号为CX3,主要是针对高像素摄像头方面的应用,接口支持MIPI的CSI-2,并不支持传统的基于并口的数据传输模式. MIPI(Mobile I ...

  9. USB3.0 和usb 2.0的区别

    USB3.0拥有10倍于USB2.0的速度,可惜DIY“江湖”险恶,如果咱们不掌握如何识别USB3.0的方法,很容易被JS忽悠.何况,USB3.0主板不等于USB3.0机箱,很多朋友在选购时都忽略了一 ...

  10. FPGA上如何求32个输入的最大值和次大值:分治

    上午在论坛看到个热帖,里头的题目挺有意思的,简单的记录了一下. 0. 题目 在FPGA上实现一个模块,求32个输入中的最大值和次大值,32个输入由一个时钟周期给出.(题目来自论坛,面试题,如果觉得不合 ...

随机推荐

  1. 使用 AOT 编译保护 .NET 核心逻辑,同时支持第三方扩展

    引言 在开发大型ERP .NET 应用程序时,我面临一个挑战:如何创建一个可供第三方引用的组件(DLL)以便二次开发,但同时保护核心逻辑不被轻易反编译,还要支持反射机制(包括私有字段访问),并且坚持使 ...

  2. 使用 Podman Desktop 在 Windows 11 WSL2 环境中启动宿主机的 GPU 进行深度学习

    使用 Podman Desktop 在 Windows 11 WSL2 环境中启动宿主机的 GPU 进行深度学习 概述 本文将指导您如何利用 Podman Desktop 安装时提供的 WSL2 环境 ...

  3. 设计即合规: 开放AI生态中的用户数据治理实践

    Hugging Face Hub 已成为 AI 协作的核心平台,托管了数万个模型.数据集以及交互式应用程序 (Space). 在开放生态系统中,用户知情同意的管理方式与那些更 "数据饥渴&q ...

  4. Linux之删除命令

    一.格式 只能删除文件夹 rmdir 文件名 删除文件 rm 是强大的删除命令,它可以 永久性地 删除文件系统中指定的文件或目录. 在使用 rm 命令删除文件或目录时,系统不会产生任何提示信息.此命令 ...

  5. 将查询集SQL-存为物理 OR 临时表

    最近的BI项目, 就是会涉及大量的 sql, 后台处理也全是 sql 来拼接成一张物理宽表, 然后前台也是用 sql 来做各种图形骚操作. 尤其是后台处理部分, 大量的sql, 有点尴尬的事情是, s ...

  6. Flutter制作桌面图标长按展示操作项面板

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...

  7. CUDA简单介绍

    并行计算 并行计算(parallel computing)是一种计算形式,它将大的问题分解为许多可以并行的小问题. 并行计算分为:任务并行(task parallel)和数据并行(data paral ...

  8. 网络编程:TCP故障模式

    故障模式总结 异常情况可归结为两大类: 第一类,是对端无FIN包发送出来的情况:第二类是对端有FIN包发出来 对端无FIN包发送出 网络终端造成对端无FIN包 很多原因都会造成网络中断,这种情况,TC ...

  9. C#数据结构之Tree

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  10. Seata源码—6.Seata AT模式的数据源代理

    大纲 1.Seata的Resource资源接口源码 2.Seata数据源连接池代理的实现源码 3.Client向Server发起注册RM的源码 4.Client向Server注册RM时的交互源码 5. ...