当前位置: 首页 > news >正文

FPGA之USB通信实战:基于FX2芯片的Slave FIFO回环测试详解

FPGA之Usb数据传输

Usb 通信

你也许会有疑问,明明有这么多通信方式和数据传输(SPI、I2C、UART、以太网)为什么偏偏使用USB呢?

原因有很多,如下:

1. 高速数据传输能力

  • 高带宽:USB接口提供了较高的数据传输速率,尤其是随着USB版本的升级(如USB 3.0及更高版本),其理论速度可达5 Gbps甚至更高。这对于需要高速数据传输的应用(如视频处理、实时数据采集等)尤为重要。
  • 低延迟:相比一些其他接口(如UART),USB的延迟更低,能够满足实时性要求较高的场景。

2. 通用性和兼容性

  • 广泛的硬件支持:几乎所有现代计算机和嵌入式系统都配备了USB接口,这意味着使用USB进行通信可以轻松实现跨平台支持,无需额外的硬件适配。
  • 标准化接口:USB是一种标准化的接口,遵循统一的协议和规范。这不仅简化了开发过程,还确保了不同设备之间的互操作性。

3. 开发便利性

  • 丰富的工具支持:大多数FPGA开发工具(如Xilinx Vivado、Altera Quartus等)都提供了对USB接口的支持,简化了设计和验证过程。
  • 成熟的驱动和库资源:大量的现成驱动程序和库资源可以轻松集成到项目中,减少了软件开发的工作量。

4. 灵活的通信模式

  • 全双工通信:USB支持全双工通信模式,允许同时进行数据的上传和下载,提高了通信效率。
  • 多种数据传输类型:USB支持控制传输、批量传输、中断传输和同步传输等多种数据传输类型,能够适应不同应用场景的需求。

成本效益

  • 低成本解决方案:相比于一些高端接口(如PCIe),USB的成本较低,适合预算有限的项目。
  • 减少外部组件需求:由于USB的标准化和广泛支持,可以减少对外部组件的需求,从而降低整体硬件成本。

也正是因为如此,usb广泛应用于数据的采集和处理、视频和音频传输、嵌入式系统开发等。

而我们今天即将要学习的,就是FPGA的USB传输,以FX2芯片为例

FX2

USB是一种通用的数据传输协议和接口标准,定义了设备与主机(如电脑)之间的通信规则(如协议、电气特性、数据传输模式等);FX系列芯片(FX2, FX3)是Cypress(现英飞凌)推出的USB控制芯片,用于实现高速USB设备的功能。说的再简单,直白一点:USB是协议标准,FX芯片是实现这一标准的硬件载体

FX芯片可以

  1. 自动处理USB复杂协议,无需开发者手动实现,
  2. 支持高速传输(FX2:支持USB2.0高速传输, 480Mbps; FX3则为 5Gbps)
  3. 提供灵活的接口(GPIF,Slave FIFO)方便直接连接外设,
  4. 内置微控制器,可以通过固件配置USB功能

FX2控制器内部结构图如下
在这里插入图片描述

FX2可以通过两种方式到FPGA,一个是(通用可编程接口)GPIF模式和从设备FIFO模式

GPIF:FX2是总线的主控者,用户自定义时序,灵活但开发复杂

Slave FIFO: FX2是被动的FIFO从设备,外部主控直接控制,简单但灵活性受限

在这里插入图片描述

在实际项目中,Slave FIFO模式更常用(尤其是FPGA做为主控的场景),而GPIF模式需要更精确控制总线的特殊需求

回环测试

介绍

我们此处就以简单的回环测试为例,实现FPGA的Usb数据传输。

在这里插入图片描述

所谓回环测试,就是说由 PC 发送数据到 FX2 芯片的 OUT 端点 2,然后再由主机将端点 2 中的数据读出,拷贝到IN 端点 6。使用 FPGA 设计 SlaveFIFO 读取和写入接口逻辑,将端点 2 中的数据读出,然后写入端点 6 中,再由电脑上位机从端点 6 中将数据读回,从而实现数据的回环。

代码

FIFO

module FiFo #( Depth = 512,Width = 16
)
(input fifo_clk,input rst_n,input write_busy,input read_busy,input fifo_flush,input [Width-1:0]din,output reg fifo_full,output reg fifo_empty,output reg [Width-1:0] dout
);localparam ADDR_Width =$clog2(Depth);//计数多加一位,防止溢出
reg  [ADDR_Width:0] write_occupancy;
reg  [ADDR_Width:0] read_occupancy;
wire  [ADDR_Width:0] next_write_occupancy;
wire  [ADDR_Width:0] next_read_occupancy;//fifo 地址索引
wire [ADDR_Width-1:0] next_write_ptr;
reg  [ADDR_Width-1:0] write_ptr;
wire [ADDR_Width-1:0] next_read_ptr;
reg  [ADDR_Width-1:0] read_ptr;reg  [Width-1:0] data_array[Depth-1:0];wire write_enable; 
wire read_enable;// 写使能和读使能逻辑
assign write_enable = !write_busy && !fifo_full;
assign read_enable  = !read_busy  && !fifo_empty;// 下一个指针和计数器计算
assign next_write_ptr = (write_enable) ? (write_ptr + 1) : write_ptr;
assign next_read_ptr  = (read_enable)  ? (read_ptr + 1)  : read_ptr;assign next_write_occupancy = fifo_flush ? 10'd0 : (write_enable ? (write_occupancy + 1) : write_occupancy);
assign next_read_occupancy  = fifo_flush ? 10'd0 : (read_enable  ? (read_occupancy + 1)  : read_occupancy);// 满/空状态判断(基于下一个计数器值)
wire [ADDR_Width:0] next_occupancy_diff = next_write_occupancy - next_read_occupancy;
wire next_fifo_full = (next_occupancy_diff >= Depth);
wire next_fifo_empty = (next_occupancy_diff == 0);//更新指针
always @(posedge fifo_clk or negedge rst_n)beginif(!rst_n)beginwrite_ptr<=0;read_ptr<=0;end else if(fifo_flush)beginwrite_ptr<=0;read_ptr<=0;end else beginwrite_ptr<=next_write_ptr;read_ptr<=next_read_ptr;end//else
end//always// 更行空/满信号
always @(posedge fifo_clk or negedge rst_n)beginif(!rst_n)beginfifo_full<=0;fifo_empty<=1;end else if (fifo_flush)beginfifo_full<=0;fifo_empty<=1;end else beginfifo_full<=next_fifo_full;fifo_empty<=next_fifo_empty;end
end//always// 读/写计数always @(posedge fifo_clk or negedge rst_n)beginif(!rst_n)beginwrite_occupancy<=0;read_occupancy<=0;end else if(fifo_flush)beginwrite_occupancy<=0;read_occupancy<=0;end else beginwrite_occupancy<=next_write_occupancy;read_occupancy<=next_read_occupancy;end//else
end//always//输出数据
always @(posedge fifo_clk or negedge rst_n)beginif(!rst_n)dout<=0;else if(fifo_flush) dout<=0;else dout<=data_array[read_ptr];
end//always//数据写入存储阵列
always @(posedge fifo_clk)beginif(write_enable)data_array[write_ptr]<=din; 
end// 溢出警告
always @(posedge fifo_clk) beginif (fifo_full && write_busy) begin$display("ERROR: %m: Fifo overflow at time %t", $time);$finish;end
end // always// 下溢警告
always @(posedge fifo_clk) beginif (fifo_empty && read_busy) begin$display("ERROR: %m: Fifo underflow at time %t", $time);$finish;end
end // always
// synthesis translate_on
endmodule
FX2_SF
module FX2_SF(input        clk,input        reset_n,inout [15:0] fx2_fdata,     // 双向数据总线output [1:0] fx2_faddr,     // FIFO地址选择output       fx2_slrd,      // 读使能(低有效)output       fx2_slwr,      // 写使能(低有效)output       fx2_sloe,      // 输出使能(低有效)input        ep6_full_flag,     // EP6满标志(可写)input        ep2_empty_flag,     // EP2空标志(可读)input        fx2_ifclk,     // 接口时钟(60MHz)output       fx2_pkt_end,   // 包结束脉冲output       fx2_clear,     // 复位信号output       fx2_slcs       // 片选(常低)
);//------------------------ 参数优化 ------------------------//
localparam [1:0] LOOPBACK_IDLE       = 2'd0,LOOPBACK_READ       = 2'd1,LOOPBACK_WAIT_ep6_full = 2'd2,LOOPBACK_WRITE      = 2'd3;localparam [1:0]FIFO_ADDR_READ  = 2'b00,  // EP2FIFO_ADDR_WRITE = 2'b10;  // EP6//------------------------ 信号声明 ------------------------//
reg [1:0] current_state, next_state;// FIFO控制信号
wire fifo_wr_en;
wire fifo_rd_en;
reg [15:0] fifo_din;
wire [15:0] fifo_dout;// FX2接口信号
reg slrd_n;
reg slwr_n;
reg sloe_n;
reg [1:0] faddr_n;
reg pkt_end_n;//------------------------ 接口分配 ------------------------//
assign fx2_slwr   = slwr_n;
assign fx2_slrd   = slrd_n;
assign fx2_sloe   = sloe_n;
assign fx2_faddr  = faddr_n;
assign fx2_pkt_end= pkt_end_n;
assign fx2_slcs   = 1'b0;     // 常使能
assign fx2_clear  = 1'b0;     // 未使用// 三态总线控制
assign fx2_fdata = (slwr_n == 1'b0) ? fifo_dout : 16'hzzzz;//------------------------ 状态机 ------------------------//
always @(posedge fx2_ifclk or negedge reset_n) beginif(!reset_n) current_state <= LOOPBACK_IDLE;else current_state <= next_state;
endalways @(*) beginnext_state = current_state;case(current_state)LOOPBACK_IDLE: //ep2为空, 上位机可传输数据if(ep2_empty_flag) next_state = LOOPBACK_READ;LOOPBACK_READ: if(!ep2_empty_flag) next_state = LOOPBACK_WAIT_ep6_full;LOOPBACK_WAIT_ep6_full: if(ep6_full_flag) next_state = LOOPBACK_WRITE;LOOPBACK_WRITE: beginif(!ep6_full_flag || fifo_empty) next_state = LOOPBACK_IDLE;enddefault: next_state = LOOPBACK_IDLE;endcase
end//------------------------ 控制信号生成 ------------------------//
always @(*) begin// 默认值slrd_n  = 1'b1;sloe_n  = 1'b1;slwr_n  = 1'b1;faddr_n = FIFO_ADDR_READ;pkt_end_n = 1'b1;case(current_state)LOOPBACK_READ: beginfaddr_n = FIFO_ADDR_READ;slrd_n  = !ep2_empty_flag;  // 有数据时持续读取sloe_n  = !ep2_empty_flag;endLOOPBACK_WRITE: beginfaddr_n = FIFO_ADDR_WRITE;slwr_n  = !(ep6_full_flag && !fifo_empty);// 在最后一次写入后生成包结束脉冲pkt_end_n = (slwr_n == 1'b0) ? 1'b0 : 1'b1;endendcase
end//------------------------ FIFO接口 ------------------------//
assign fifo_wr_en = (current_state == LOOPBACK_READ) && !slrd_n;
assign fifo_rd_en = (current_state == LOOPBACK_WRITE) && !slwr_n;// 数据输入寄存器
always @(posedge fx2_ifclk) beginif(fifo_wr_en) fifo_din <= fx2_fdata;
endFiFo #(.Depth(512),.Width(16)
) u_fifo (.fifo_clk     (fx2_ifclk),.rst_n        (reset_n),.write_busy   (1'b0),       // 外部无写阻塞.read_busy    (1'b0),       // 外部无读阻塞.fifo_flush   (1'b0),       // 禁用自动flush.din          (fifo_din),.fifo_full    (fifo_full),.fifo_empty   (fifo_empty),.dout         (fifo_dout)
);wire clk_96m;//生成96M时钟用于ILA采样pll pll_inst(.clk_out1(clk_96m),.clk_in1(clk));//------------------------ 调试模块注释 ------------------------//ila_0 ila_0_inst(.clk(clk_96m), // input wire clk.probe0(fx2_fdata), // input wire [15:0]  probe0  .probe1(fx2_faddr), // input wire [1:0]  probe1 .probe2(ep2_empty_flag), // input wire [0:0]  probe2 .probe3(ep6_full_flag), // input wire [0:0]  probe3 .probe4(fx2_sloe), // input wire [0:0]  probe4 .probe5(fx2_slwr), // input wire [0:0]  probe5 .probe6(fx2_slrd), // input wire [0:0]  probe6 .probe7(fifo_empty), // input wire [0:0]  probe7 .probe8(fifo_full), // input wire [0:0]  probe8 .probe9(fifo_flush) // input wire [0:0]  probe9);endmodule

注:实现该项目时需要使用到 Cypress提供的基本开发包(名为CySuiteUsb)和安装对应的驱动,可以到官网上去下载。

相关文章:

FPGA之USB通信实战:基于FX2芯片的Slave FIFO回环测试详解

FPGA之Usb数据传输 Usb 通信 你也许会有疑问&#xff0c;明明有这么多通信方式和数据传输&#xff08;SPI、I2C、UART、以太网&#xff09;为什么偏偏使用USB呢? 原因有很多&#xff0c;如下&#xff1a; 1. 高速数据传输能力 高带宽&#xff1a;USB接口提供了较高的数据传…...

【MySQL_03】数据库基本--核心概念

文章目录 一、数据库基础1.1 数据库基础定义1.2 数据库分类与典型产品1.3 数据库模型1.4 数据库层次结构1.5 数据库核心机制1.6 数据表和视图1.61 数据表&#xff08;Table&#xff09;1.62 视图&#xff08;View&#xff09; 1.7 键类型1.8 MySQL数据类型1.9 数据库范式化 二、…...

神经网络|(十四)|霍普菲尔德神经网络-Hebbian训练

【1】引言 前序学习进程中&#xff0c;除了对基本的神经网络知识进行了学习&#xff0c;还掌握了SOM神经网络原理&#xff0c;文章链接包括且不限于&#xff1a; 神经网络|(十一)|神经元和神经网络-CSDN博客 神经网络|(十二)|常见激活函数-CSDN博客 神经网络|(十三)|SOM神经…...

【JAVA架构师成长之路】【Redis】第13集:Redis缓存击穿原理、规避、解决方案

30分钟自学教程&#xff1a;Redis缓存击穿原理与解决方案 目标 理解缓存击穿的定义及核心原因。掌握互斥锁、逻辑过期时间等预防技术。能够通过代码实现高并发场景下的缓存保护。学会熔断降级、热点探测等应急方案。 教程内容 0~2分钟&#xff1a;缓存击穿的定义与典型场景 …...

preloaded-classes裁剪

系统预加载了哪些class类&#xff1f;system/etc/preloaded-classes 修改源代码&#xff1f; frameworks\base\config\preloaded-classes 默认位置&#xff0c;如果改了不生效&#xff0c;可能有其它模块的mk文件指定了preloaded-classes覆盖了framework模块&#xff0c;例如…...

爬虫案例五多进程与多线程爬取斗图网

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、多进程与多线程爬取斗图网总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 爬取斗图网 提示&#xff1a;以下是本篇文章正文内…...

Redis的CPU高达90%时如何处理

Redis的CPU高达90%时如何处理 1. 分析和优化2. 扩展和分片3. 缓存策略调整4. 资源提升5. 负载均衡6. 进程调整7. 代码层面改进8. 其他 当Redis的CPU使用率高达90%时&#xff0c;说明Redis服务器可能处于过载状态&#xff0c;这可能会导致响应时间变长甚至服务中断。要处理这种…...

计算机视觉之dlib人脸关键点绘制及微笑测试

dlib人脸关键点绘制及微笑测试 目录 dlib人脸关键点绘制及微笑测试1 dlib人脸关键点1.1 dlib1.2 人脸关键点检测1.3 检测模型1.4 凸包1.5 笑容检测1.6 函数 2 人脸检测代码2.1 关键点绘制2.2 关键点连线2.3 微笑检测 1 dlib人脸关键点 1.1 dlib dlib 是一个强大的机器学习库&a…...

FPGA时序约束的几种方法

一,时钟约束 时钟约束是最基本的一个约束,因为FPGA工具是不知道你要跑多高的频率的,你必要要告诉工具你要跑的时钟频率。时钟约束也就是经常看到的Fmax,因为Fmax是针对“最差劲路径”,也就是说,如果该“最差劲路径”得到好成绩,那些不是最差劲的路径的成绩当然比…...

【0013】Python数据类型-列表类型详解

如果你觉得我的文章写的不错&#xff0c;请关注我哟&#xff0c;请点赞、评论&#xff0c;收藏此文章&#xff0c;谢谢&#xff01; 本文内容体系结构如下&#xff1a; Python列表&#xff0c;作为编程中的基础数据结构&#xff0c;扮演着至关重要的角色。它不仅能够存储一系…...

10.RabbitMQ集群

十、集群与高可用 RabbitMQ 的集群分两种模式,一种是默认集群模式,一种是镜像集群模式&#xff1b; 在RabbitMQ集群中所有的节点(一个节点就是一个RabbitMQ的broker服务器) 被归为两类:一类是磁盘节点,一类是内存节点&#xff1b; 磁盘节点会把集群的所有信息(比如交换机、绑…...

Web网页开发——水果忍者

1.介绍 复刻经典小游戏——水果忍者 2.预览 3.代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&…...

信息安全访问控制、抗攻击技术、安全体系和评估(高软42)

系列文章目录 信息安全访问控制、抗攻击技术、安全体系和评估 文章目录 系列文章目录前言一、信息安全技术1.访问控制2.抗攻击技术 二、欺骗技术1.ARP欺骗2.DNS欺骗3.IP欺骗 三、抗攻击技术1.端口扫描2.强化TCP/IP堆栈 四、保证体系和评估1.保证体系2.安全风险管理 五、真题在…...

【算法】009、单双链表反转

【算法】009、单双链表反转 文章目录 一、单链表反转1.1 实现思路1.2 多语言解法 二、双链表反转2.1 实现思路2.2 多语言解法 一、单链表反转 1.1 实现思路 维护 pre 变量。 从前向后遍历 head&#xff0c;首先记录 next head.next&#xff0c;其次反转指针使 head.next pr…...

物联网设备接入系统后如何查看硬件实时数据?

要在软件中实时查看硬件设备的信息&#xff0c;通常需要结合前后端技术来实现。以下是设计思路和实现步骤&#xff1a; 1. 系统架构设计 实时查看硬件设备信息的系统通常采用以下架构&#xff1a; 数据采集层: 硬件设备通过传感器采集数据&#xff0c;发送到InfluxDB。数据存…...

【Linux系统编程】初识系统编程

目录 一、什么是系统编程1. 系统编程的定义2. 系统编程的特点3. 系统编程的应用领域4. 系统编程的核心概念5. 系统编程的工具和技术 二、操作系统四大基本功能1. 进程管理&#xff08;Process Management&#xff09;2. 内存管理&#xff08;Memory Management&#xff09;3. 文…...

解决stylelint对deep报错

报错如图 在.stylelintrc.json的rules中配置 "selector-pseudo-class-no-unknown": [true,{"ignorePseudoClasses": ["deep"]} ]...

React基础之useInperativehandlle

通过ref调用子组件内部的focus方法来实现聚焦 与forwardRef类似&#xff0c;但是forwardRef是通过暴露整个Ref来实现&#xff0c;而useInperativehandle是通过对外暴露一个方法来实现的 import { forwardRef, useImperativeHandle, useRef, useState } from "react";…...

使用joblib 多线程/多进程

文章目录 1. Joblib 并行计算的两种模式多进程(Multiprocessing,适用于 CPU 密集型任务)多线程(Multithreading,适用于 I/O 密集型任务)2. Joblib 的基本用法3. Joblib 多进程示例(适用于 CPU 密集型任务)示例:计算平方4. Joblib 多线程示例(适用于 I/O 密集型任务)…...

⭐算法OJ⭐N-皇后问题 II【回溯剪枝】(C++实现)N-Queens II

⭐算法OJ⭐N-皇后问题【回溯剪枝】&#xff08;C实现&#xff09;N-Queens 问题描述 The n-queens puzzle is the problem of placing n n n queens on an n n n \times n nn chessboard such that no two queens attack each other. Given an integer n, return the num…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

CSS3相关知识点

CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

Java后端检查空条件查询

通过抛出运行异常&#xff1a;throw new RuntimeException("请输入查询条件&#xff01;");BranchWarehouseServiceImpl.java // 查询试剂交易&#xff08;入库/出库&#xff09;记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...

k8s从入门到放弃之Pod的容器探针检测

k8s从入门到放弃之Pod的容器探针检测 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;容器探测是指kubelet对容器执行定期诊断的过程&#xff0c;以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...