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)和安装对应的驱动,可以到官网上去下载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/30410.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

生活反思公园散步与小雨遇记

《公园散步与小雨遇记》&#xff08;一&#xff09; 总收录于《生活小事灵感反思》与《生活小美好》 最近又新增一个习惯&#xff1a;每天至少走一小时 那天天气有雨&#xff0c;软件上显示在下雨&#xff0c;但是外面没雨&#xff0c;心想着大不了淋湿回来洗个头&#xff0c;…

夏门大学DeepSeek 手册:从社会大众到高校及企业的全面应用实践研究(附 PDF 下载)

这 3 份手册分别从 DeepSeek 大模型概念、技术与应用实践、DeepSeek 大模型赋能高校教学和科研、DeepSeek 大模型及其企业应用实践-企业人员的大模型宝典几个角度进行全面分析&#xff0c;可以结合着清华、北大系列相互对照着学习。 清华北大推出的 DeepSeek 教程&#xff08;…

微服务保护:Sentinel

home | Sentinelhttps://sentinelguard.io/zh-cn/ 微服务保护的方案有很多&#xff0c;比如&#xff1a; 请求限流 线程隔离 服务熔断 服务故障最重要原因&#xff0c;就是并发太高&#xff01;解决了这个问题&#xff0c;就能避免大部分故障。当然&#xff0c;接口的并发…

工作学习笔记:HarmonyOS 核心术语速查表(v14 实战版)

作为在 HarmonyOS 开发一线摸爬滚打的工程师&#xff0c;笔者在 v14 版本迭代中整理了这份带血的实战术语表。 一、架构基础术语速查 A 系列术语 术语官方定义笔者解读&#xff08;v14 实战版&#xff09;开发陷阱 & 解决方案abc 文件ArkCompiler 生成的字节码文件打包时…

驾校与无人机飞手培训机构合作开展低空业务技术详解

驾校与无人机飞手培训机构合作开展低空业务是一个创新的举措&#xff0c;旨在结合双方的资源和专业优势&#xff0c;为学员提供多元化的技能培训和业务拓展机会。以下是对这种合作模式下低空业务技术的详细解析&#xff1a; 一、合作背景与意义 1. 市场需求增长&#xff1a;随…

黄昏时间户外街拍人像Lr调色教程,手机滤镜PS+Lightroom预设下载!

调色介绍 黄昏时分有着独特而迷人的光线&#xff0c;使此时拍摄的人像自带一种浪漫、朦胧的氛围 。通过 Lr 调色&#xff0c;可以进一步强化这种特质并根据不同的风格需求进行创作。Lr&#xff08;Lightroom&#xff09;作为专业的图像后期处理软件&#xff0c;提供了丰富的调色…

数据结构(队列)

数据结构&#xff08;队列&#xff09; 什么是队列&#xff1f; 队列和栈类似&#xff0c;也是一类特殊的线性表。特殊之处也是在于操作上。队列&#xff1a;只允许在一端进行插入数据操作&#xff08;入队&#xff09;&#xff0c;在另一端进行删除数据操作&#xff08;出队&…

DeepSeek R1-7B 医疗大模型微调实战全流程分析(全码版)

DeepSeek R1-7B 医疗大模型微调实战全流程指南 目录 环境配置与硬件优化医疗数据工程微调策略详解训练监控与评估模型部署与安全持续优化与迭代多模态扩展伦理与合规体系故障排除与调试行业应用案例进阶调优技巧版本管理与迭代法律风险规避成本控制方案文档与知识传承1. 环境配…

[Lc7_分治-快排] 快速选择排序 | 数组中的第K个最大元素 | 库存管理 III

目录 1. 数组中的第K个最大元素 题解 代码 2.库存管理 III 代码 1. 数组中的第K个最大元素 题目链接&#xff1a;215. 数组中的第K个最大元素 题目分析&#xff1a; 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要…

集合论--形式化语言里的汇编码

如果一阶逻辑是数学这门形式化语言里的机器码&#xff0c;那么集合论就是数学这门形式化语言里的汇编码。 基本思想&#xff1a;从集合出发构建所有其它。 构建自然数构建整数构建有理数构建实数构建有序对、笛卡尔积、关系、函数、序列等构建确定有限自动机(DFA) 全景图 常…

RuoYi框架添加自己的模块(学生管理系统CRUD)

RuoYi框架添加自己的模块&#xff08;学生管理系统&#xff09; 框架顺利运行 首先肯定要顺利运行框架了&#xff0c;这个我不多说了 设计数据库表 在ry数据库中添加表tb_student 表字段如图所示 如图所示 注意id字段是自增的 注释部分是后面成功后前端要展示的部分 导入…

MybatisPlus

1.增删改查入门案例&#xff1a; 首先导入依赖&#xff1a; <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency> 然后这些增删改查…

【 <一> 炼丹初探:JavaWeb 的起源与基础】之 Servlet 过滤器:实现请求的预处理与后处理

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、过滤器&…

服务器上通过ollama部署deepseek

2025年1月下旬&#xff0c;DeepSeek的R1模型发布后的一周内就火了&#xff0c;性能比肩OpenAI的o1模型&#xff0c;且训练成本仅为560万美元&#xff0c;成本远低于openAI&#xff0c;使得英伟达股票大跌。 下面我们来看下如何个人如何部署deepseek-r1模型。 我是用的仙宫云的…

点云软件VeloView开发环境搭建与编译

官方编译说明 LidarView / LidarView-Superbuild GitLab 我的编译过程&#xff1a; 安装vs2019&#xff0c;windows sdk&#xff0c;qt5.14.2&#xff08;没安装到5.15.7&#xff09;&#xff0c;git&#xff0c;cmake3.31&#xff0c;python3.7.9&#xff0c;ninja下载放到…

【Git】创建,切换分支

理解分支 这里开始介绍Git的杀手级功能之一&#xff1a;分支。 分支就是科幻电影里的平行宇宙&#xff0c;当你正在电脑前努力学习C的时候&#xff0c;另一个你正在另一个平行宇宙里努力学习JAVA。 如果两个平行宇宙互不干扰&#xff0c;那对现在的你也没啥影响。不过&#…

FPGA 实验报告:四位全加器与三八译码器仿真实现

目录 安装Quartus软件 四位全加器 全加器、半加器 半加器&#xff1a; 全加器&#xff1a; 四位全加器电路图 创建项目 半加器 全加器 四位全加器 代码实现 半加器 全加器 四位全加器 三八译码器 创建项目 代码展示 modelsim仿真波形图 四位全加器 三八译码…

记录一次wifi版有人物联串口服务器调试经过

1、首先买了一个华为的wifi路由器&#xff0c;连接上以后&#xff0c;设置好网络名字和wifi密码 2、用网线连接串口服务器&#xff0c;通过192.168.1.1登录&#xff0c;进行配置 找到无线客户端配置&#xff0c;先在基本配置中打开5G配置&#xff0c;然后再去5.8G配置中设置 …

Vue3.5 企业级管理系统实战(八):Sidebar组件开发 2

本篇通过 Pinia 实现侧边栏&#xff08;Sidebar&#xff09;的展开收起功能&#xff0c;并通过 Pinia 实现展开状态的持久化。 1 安装 Pinia Persistedstate Pinia 是 Vue.js 的状态管理库&#xff0c;而 pinia-plugin-persistedstate 是一个针对 Pinia 的插件&#xff0c;它…

驱动 AI 边缘计算新时代!高性能 i.MX 95 应用平台引领未来

智慧浪潮崛起&#xff1a;AI与边缘计算的时代 正悄然深植于我们的日常生活之中&#xff0c;无论是火热的 ChatGPT 与 DeepSeek 语言模型&#xff0c;亦或是 Meta 智能眼镜&#xff0c;AI 技术已经无形地影响着我们的生活。这股变革浪潮并未停歇&#xff0c;而是进一步催生了更高…