0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于FPGA的USB数据传输

FPGA设计论坛 来源:FPGA设计论坛 2025-08-06 14:47 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

USB通信

你也许会有疑问,明明有这么多通信方式和数据传输(SPI、I2CUART以太网)为什么偏偏使用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芯片可以

自动处理USB复杂协议,无需开发者手动实现,

支持高速传输(FX2:支持USB2.0高速传输, 480Mbps; FX3则为 5Gbps)

提供灵活的接口(GPIF,Slave FIFO)方便直接连接外设,

内置微控制器,可以通过固件配置USB功能

FX2控制器内部结构图如下
3896d38a-6d1e-11f0-a18e-92fbcf53809c.jpg

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

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

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

38a42378-6d1e-11f0-a18e-92fbcf53809c.jpg

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

回环测试

介绍

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

38adb6ae-6d1e-11f0-a18e-92fbcf53809c.jpg

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

代码

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)begin

if(!rst_n)begin

write_ptr<=0;

read_ptr<=0;

end else if(fifo_flush)begin

write_ptr<=0;

read_ptr<=0;

end else begin

write_ptr<=next_write_ptr;

read_ptr<=next_read_ptr;

end//else

end//always

// 更行空/满信号

always @(posedge fifo_clk or negedge rst_n)begin

if(!rst_n)begin

fifo_full<=0;

fifo_empty<=1;

end else if (fifo_flush)begin

fifo_full<=0;

fifo_empty<=1;

end else begin

fifo_full<=next_fifo_full;

fifo_empty<=next_fifo_empty;

end

end//always

// 读/写计数

always @(posedge fifo_clk or negedge rst_n)begin

if(!rst_n)begin

write_occupancy<=0;

read_occupancy<=0;

end else if(fifo_flush)begin

write_occupancy<=0;

read_occupancy<=0;

end else begin

write_occupancy<=next_write_occupancy;

read_occupancy<=next_read_occupancy;

end//else

end//always

//输出数据

always @(posedge fifo_clk or negedge rst_n)begin

if(!rst_n)dout<=0;

else if(fifo_flush) dout<=0;

else dout<=data_array[read_ptr];

end//always

//数据写入存储阵列

always @(posedge fifo_clk)begin

if(write_enable)

data_array[write_ptr]<=din; 

end

// 溢出警告

always @(posedge fifo_clk) begin

if (fifo_full && write_busy) begin

$display("ERROR: %m: Fifo overflow at time %t", $time);

$finish;

end

end // always

// 下溢警告

always @(posedge fifo_clk) begin

if (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, // EP2

FIFO_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) begin

if(!reset_n) current_state <= LOOPBACK_IDLE;

else current_state <= next_state;

end

always @(*) begin

next_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: begin

if(!ep6_full_flag || fifo_empty)

next_state = LOOPBACK_IDLE;

end

default: 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: begin

faddr_n = FIFO_ADDR_READ;

slrd_n = !ep2_empty_flag; // 有数据时持续读取

sloe_n = !ep2_empty_flag;

end

LOOPBACK_WRITE: begin

faddr_n = FIFO_ADDR_WRITE;

slwr_n = !(ep6_full_flag && !fifo_empty);

// 在最后一次写入后生成包结束脉冲

pkt_end_n = (slwr_n == 1'b0) ? 1'b0 : 1'b1;

end

endcase

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) begin

if(fifo_wr_en)

fifo_din <= fx2_fdata;

end

FiFo #(

.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

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1646

    文章

    22086

    浏览量

    620183
  • usb
    usb
    +关注

    关注

    60

    文章

    8258

    浏览量

    274517
  • 数据传输
    +关注

    关注

    9

    文章

    2029

    浏览量

    66232

原文标题:FPGA之Usb数据传输

文章出处:【微信号:gh_9d70b445f494,微信公众号:FPGA设计论坛】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    基于FPGAUSB数据传输电路的设计

    本帖最后由 eehome 于 2013-1-5 09:58 编辑 1系统框架简介2USB模块设计2.1模块硬件电路2.2D12固件结构2.3主循环实现3FPGA模块的VHDL程序实现3.1模块框架3.2程序仿真4PC软件实现
    发表于 03-02 09:47

    基于FPGA的高速LVDS数据传输

    高速LVDS数据传输方案和协议基于FPGA的高速LVDS数据传输本人在北京工作6年,从事FPGA外围接口设计,非常熟悉高速LVDS数据传输,
    发表于 03-01 18:47

    求助 ,关于STM32的USB数据传输问题

    小弟正在做一项目,利用 STM32做的关于数据采集系统,打算利用USB实现和PC的数据传输,目前了解到的资料多是关于USB 读写U盘等存储设备,请问关于
    发表于 07-06 22:02

    FPGAUSB数据传输问题

    求指导,多谢大家
    发表于 08-10 21:34

    基于FPGA+USB3.0接口的高速数据传输系统设计

    速度越来越快,对数据的抗干扰性的要求也越来越高。随着以Gbyte为单位的大容量数据传输要求的出现,传统的USB2.0数据传输标准,例如RS-422,RS485,SCSI和PECL等
    发表于 08-09 14:18

    如何使用FPGA器件和USB通讯实现高速数据传输显示系统的设计

    本文设计的基于FPGAUSB的高速数据传输、记录系统不但具有体积小、功耗低、成本低、使用灵活方便、硬件电路简单、可在线更新等特点;而且还充分利用了微机的资源,因而易开发且扩展性好。
    发表于 04-30 06:50

    基于USB接口的无线数据传输系统设计

    本文提出了一种运用USB接口芯片PDIUSBD12、89C52微处理器、射频收发器nRF401构建的无线USB数据传输接口,并利用该接口成功地实现了无线数据传输。文中对
    发表于 09-24 15:48 91次下载

    基于USB2.0的红外数据传输系统

     针对有线传输的缺点或不足,为避免经常插拔接口造成测试仪器损坏,设计基于USB2.0的红外数据传输系统。详细论述系统的总体结构和关键硬件电路的设计及实现,并阐述系
    发表于 12-30 10:55 44次下载

    基于FPGAUSB的高速数据传输、记录及显示系统

    摘要:提出了一种基于FPGAUSB的高速数据传输、记录及显示系统的设计方案,并对其中的低电压差分信号(LVDS
    发表于 04-16 21:36 728次阅读
    基于<b class='flag-5'>FPGA</b>和<b class='flag-5'>USB</b>的高速<b class='flag-5'>数据传输</b>、记录及显示系统

    基于DSP的USB数据传输系统设计

    基于DSP的USB数据传输系统设计 引 言   由于DSP芯片的不断发展,以及它处理数据速度快、处理数据量大的优势,已经广泛应用到数字信号处理的许多领域。在CT
    发表于 11-20 10:50 1395次阅读
    基于DSP的<b class='flag-5'>USB</b><b class='flag-5'>数据传输</b>系统设计

    基于USB2.0的红外数据传输系统的设计与实现

    基于USB2.0的红外数据传输系统的设计与实现 摘要:针对有线传输的缺点或不足,为避免经常插拔接口造成测试仪器损坏,设计基于USB2.0的红外数据
    发表于 03-13 09:56 1767次阅读
    基于<b class='flag-5'>USB</b>2.0的红外<b class='flag-5'>数据传输</b>系统的设计与实现

    数据传输速率是什么意思

    数据传输速率是什么意思 数据传输速率是通过信道每秒可传输的数字信息量的量度。数据传输速率也称为吞吐率。数据传输速率由很
    发表于 03-18 14:45 5100次阅读

    USB2.0+FPGA实现多路数据传输系统

    基于USB2.0 的FIFO 方式, 利用FPGA 同步实现三个通道, 不同传输率的数据的发送和采集, 详细说明多路数据发送与采集时,对不同
    发表于 09-13 17:22 66次下载
    <b class='flag-5'>USB2.0+FPGA</b>实现多路<b class='flag-5'>数据传输</b>系统

    如何使用FPGA器件和USB通讯实现高速数据传输显示系统的设计

    点击上方 蓝字 关注我们 本文设计的基于FPGAUSB的高速数据传输、记录系统不但具有体积小、功耗低、成本低、使用灵活方便、硬件电路简单、可在线更新等特点;而且还充分利用了微机的资源,因而易开发且
    的头像 发表于 09-20 10:00 3576次阅读
    如何使用<b class='flag-5'>FPGA</b>器件和<b class='flag-5'>USB</b>通讯实现高速<b class='flag-5'>数据传输</b>显示系统的设计

    Micro USB接口数据传输速率分析

    Micro USB接口的数据传输速率分析,可以从以下几个方面进行: 一、Micro USB版本与传输速率 Micro USB接口存在不同的版
    的头像 发表于 11-27 10:05 2426次阅读