一、背景

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

目前以太网的带宽极限:实测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. 常用的 JVM 配置参数有哪些?

    常用的 JVM 配置参数 JVM 配置参数可以用来控制 Java 程序的内存分配.垃圾回收.性能优化等.以下是一些常用的 JVM 配置参数: 1. 堆内存相关参数 -Xms:设置 JVM 初始堆内存大 ...

  2. [笔记]PHP里类的申明和对象的实例化(笔记)

    1.申明类 class 类名{  //属性----------  public 属性 = 值:  public 属性:  //方法-----------  function 方法名($n1,$n2){ ...

  3. CF1740C题解

    众所周知,这道题的难度是 1400,所以是简单题. 分析 首先,坚信这是一道简单题,所以不要想复杂了. 首先我们需要对 aaa 数组排序,这点是肯定的,为啥应该不用我解释. 下面,我们假设 p1,   ...

  4. PHP中的精确计算bcadd,bcsub,bcmul,bcdiv 及 扩展安装

    <?php/** * 精确加法 * @param [type] $a [description] * @param [type] $b [description] */function math ...

  5. FastJSON序列化扩展接口与特性详解

    结论先行 FastJSON 的 SerializeFilter 接口通过 动态拦截和修改序列化过程,可实现字段名重命名.敏感数据脱敏.字段过滤等高级功能.其核心子接口包括 PropertyPreFil ...

  6. .NET Core 和 .NET 标准类库项目类型有什么区别?

    在 Visual Studio 中,至少可以创建三种不同类型的类库: 类库(.NET Framework) 类库(.NET 标准) 类库 (.NET Core) 虽然第一种是我们多年来一直在使用的,但 ...

  7. 深度解析3D模型生成器:基于StyleGAN3与PyTorch3D的多风格生成工具开发实战

    引言:跨模态生成的革命性突破 在元宇宙与数字孪生技术蓬勃发展的今天,3D内容生成已成为制约产业发展的关键瓶颈.传统建模方式依赖专业软件和人工操作,而基于深度学习的生成模型正颠覆这一范式.本文将深入解析 ...

  8. WPF 用 DrawingBrush实现图形的平铺

    WPF平铺图像,一般用到 DrawingBrush 来实现对图形.图形的平铺,查阅了 微软官方文档的 DrawingBrush  属性 创建一个 DrawingBrush,其中: TileMode=& ...

  9. GC-QA-RAG 智能问答系统的向量检索

    本章节介绍 GC-QA-RAG 智能问答系统的核心检索技术原理,包括向量化策略.混合检索机制.RRF 融合排序等关键实现细节. 1. 检索流程概述 系统采用典型的 RAG(Retrieval-Augm ...

  10. anaconda基本操作及一些问题的解决记录

    anaconda虚拟环境 # anaconda 创建虚拟环境: conda create -n 虚拟环境名称 python=版本号 查看所有虚拟环境: conda env list 使用虚拟环境: c ...