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

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

3天内不再提示

在icestick板子上实现从FPGA到USB Host的数据传输

OpenFPGA 来源:OpenFPGA 2023-03-09 14:18 次阅读

背景信息

icestick 板载 USB 接口芯片 FT2232H 的端口 A 和端口 B 均与 FPGA ice40hx1k 相连。其中,端口 A 处于 MPSSE 模式,用于读写 SPI Flash 以更新 FPGA 的 bitfile,而 B 口默认处于 ASYNC Serial 模式,当作串口使用。

端口 B 都只有一部分引脚连到 FPGA,无法支持 245 FIFO 或者 245 FIFO SYNC 模式以实现高速数据传输。而在 ASYNC Serial 模式时,其支持最大 12Mbaud 即最高 1.14MBps 的数据传输。

笔者发现 FT2232H 还支持一种称为 Fast Opto-Isolated Serial Interface 的模式。在 FTDI 文档和软件中,这一模式也被称为 Fast Serial Interface 模式或者 OPTO Isolate 模式。因为引入了时钟引脚,这一模式可以在使用较少引脚的情况实现比 ASYNC Serial 模式更高带宽的数据传输。

读者可以通过此文了解 OPTO Isolate 模式如何使用并按照说明可以实现最高 2.57MBps 的数据传输。

准备工作

你需要具备以下条件:

一块 icestick 开发板

ice40 FPGA 开发工具,开源工具或者 iceCube2

FT Prog 程序及 D2XX 驱动

FT2232H Datasheet

同时,笔者使用以下软件实现 Windows 端测试程序:

zadig 软件

libusb 库及开发环境

准备妥当后,我们先尝试修改 FT2232H 芯片端口 B 的模式。

修改模式

首先,我们需要使用 FTDI 公司的 FT Prog 程序来修改端口 B 的模式。而 FT Prog 程序则需要驱动程序 D2XX 驱动。

打开设备管理器,插入 icestick 后,如果 D2XX 设备驱动程序配置正常,在通用总线控制器下会出现 USB Serial Converter AUSB Serial Converter B 设备,如下图所示。

3b79a10c-be40-11ed-bfe3-dac502259ad0.png

打开 FT Prog 程序,主菜单上点击 DEVICES 然后点击 Scan and Parse 子菜单。如果一切正常,读者应该可以看到以下界面:

3b962c96-be40-11ed-bfe3-dac502259ad0.png

选中设备,找到 Hardware SpecificPort BHardware 项,选择 OPTO Isolate 项,然后在主菜单上点击 DEVICES 然后点击 Program 子菜单。

3bb04e50-be40-11ed-bfe3-dac502259ad0.png

点击 Program 按钮就可以将修改后的配置选项写入 FT2232H 的 EEROM 中。

烧写完毕后可以重新拔插 icestick,打开 FT Prog 再次查看设备的 Port B 的属性是否已经修改成 OPTO Isolate。

修改成功后,我们看一下 OPTO Isolate 模式下接口的规格

OPTO Isolate 模式

在 FT2232H Datasheet 章节 3.1.4.6 FT2232H Pins used as a Fast Serial Interface 的 Table 3.10 中我们可以找到:

3bc1c6e4-be40-11ed-bfe3-dac502259ad0.png

由于本文侧重于 FPGA 到 FT2232H 的数据传输,我们可以暂时忽略用于 FT2232H 到 FPGA 方向数据传输的 FSDO 引脚。

在章节 4.8.2 Incoming Fast Serial Data 中 Figure 4.15 Fast Opto-Isolated Serial Interface Input Data 我们可以看到:

3bd7bb8e-be40-11ed-bfe3-dac502259ad0.png

有此时序图我们可以看出:

空闲状态下 FSCTS 和 FSDI 应为高电平

FSCLK 作为数据传输的参考时钟,FT2232H 应在 FSCLK 的上升沿采数据

FSCTS 为高电平时,FPGA 可以进行数据传输

一次传输的数据由一个由 0 表示的起始位、LSB 优先的 8 位数据和一个 DEST 位组成

在 DEST 位发送后,FSCTS 仍然会保持一段时间的低电平

然后我们在章节 4.8 Fast Opto-Isolated Serial Interface Mode Description 的 Figure 4.13 Fast Opto-Isolated Serial Interface Signal Waveforms 看到具体时序:

3beb1170-be40-11ed-bfe3-dac502259ad0.png

以及在同一章节的 Table 4.6 Fast Opto-Isolated Serial Interface Signal Timings 看到具体时序:

3c040310-be40-11ed-bfe3-dac502259ad0.png

根据这些,我们可以得到:

FSCLK 的最小周期是 20ns,即最大频率是 50MHz

FSDI 的建立时间最小为 10ns,保持时间最小为 5 ns

这样我们可以根据这些参数进行 FPGA 接口设计了。

接口电路设计

在实现接口电路之前,读者需要检查具体用到的 FPGA 的性能。如果 IO 反转性能不能达到 50MHz,那么 IO 就成为瓶颈;如果 IO 性能满足要求,但是接口电路频率不能超过 100MHz 或者在支持支持双沿输出和输入的情况下超过 50MHz,接口电路就会成为瓶颈。

通过查看 ice40hx1k 的文档,我们可以大致确定 ice40hx1k 的普通 IO 反转可以做到 50MHz,而且,在此 FPGA 上实现一个运行在近 100MHz 的电路并不十分困难。

如果我们使用 100MHz 作为内部时钟,那么数据传输时序图会变成:

3c1ce7ae-be40-11ed-bfe3-dac502259ad0.png

需要说明的是

我们使用 100MHz 使用来产生一个 50MHz 的 FSCLK 对应 IO 的反转

我们在 FSCLK 的下降沿变更数据,这样保证 FSDI 的建立时间和保持时间都是 10ns

我们会产生一个持续反转的 FSCLK,而不会在不传输数据的时候暂停 FSCLK

通过观察时序图,计数状态机来实现此电路较为简单。同时对于慢速接口电路,valid-ready 信号也是不能缺少的。加入这些信息后,数据传输时序图会变成:

3c30780a-be40-11ed-bfe3-dac502259ad0.png

有了这样的时序图,我们可以开始实现具体的电路了。

接口电路实现

首先,输入信号 FSCTS 需要经过跨时钟域处理。我们可以将 i_fscts 连接到 2 个级联的 DFF 上来进行处理,从而得到同步的信号 w_fscts。

//
//CDCsignals
//
localparamDFF_W=2;

wirew_fscts;
reg[DFF_W-1:0]r_fscts_sync;

always@(posedgei_clk)
r_fscts_sync<= {r_fscts_sync[DFF_W - 2 : 0], i_fscts};

    assign w_fscts = r_fscts_sync[DFF_W - 1];

其次,Fast Opto-Isolated Serial Interface 电路本质是将并行的数据进行串行数据,我们还需要一个移位寄存器和对应的控制信号:

//
//r_data
//
//r_datakeepsthedatatobetransmitted
//
localparamTX_DATA_W=DATA_W+3;

reg[TX_DATA_W-1:0]r_data;
reg[TX_DATA_W-1:0]w_data_next;

wirew_data_tick;
wirew_data_load;
wirew_status_tick;

always@(posedgei_clk,posedgei_arst)
if(i_arst)
r_data<= {TX_DATA_W{1'b1}};
        else
            r_data <= w_data_next;

    always @(*) begin
        w_data_next = r_data;

        if (w_data_load)
            w_data_next = {i_channel, i_data, 2'b01};
        else
            if (w_data_tick)
                w_data_next = {1'b1, r_data[TX_DATA_W - 1 : 1]};
    end

    // w_data_load indicates if r_data could be filled safely
    assign w_data_load = o_ready & i_valid;
    assign w_data_tick = w_status_tick | w_status_start;

因为数据的发送需要两个必备条件,我们需要一个 bit 来确保默认情况 FSDI 的数据为高电平。这样,加上起始位和 DEST 位后,我们共需要 11 位移位寄存器。

同时,数据发送时 LSB 优先的,我们的 FSDI 自然而然的会连接到移位寄存器的最低位。

复位时,移位寄存器全部填充为 1;复位解除后,如果需要加载数据时,即 w_data_load 为有效时,那么将表示 DEST 位的 i_channel、8 位数据 i_data 、表示起始位的 0 和默认电平 1 加载到寄存器中;如果遇到 w_data_tick 有效时,那么就将移位寄存器进行右移,最高位填充 1。

然后,因为数据发送的两个条件并不是同时发生,我们需要一个寄存器来表示 r_data 是否已经填充。

//
//r_data_status
//
//r_data_statusdecidesthevalid-readysignalsand
//ifr_statusFSMstarts
//
regr_data_filled;
regr_data_filled_next;

wirew_data_done;
wirew_status_done;

always@(posedgei_clk,posedgei_arst)
if(i_arst)
r_data_filled<= 1'b0;
        else
            r_data_filled <= r_data_filled_next;

    always @(*) begin
        r_data_filled_next = r_data_filled;

        // if the tx data has been filled
        if (r_data_filled) begin
            // and the data transmission has been done
            if (w_data_done)
                r_data_filled_next = 1'b0;
        end
        // or if the tx data is empty
        else begin
            // and upstream module's data is ready
            if (i_valid)
                r_data_filled_next = 1'b1;
        end
    end

    assign w_data_done = w_status_done & i_tick;

默认的情况下,r_data_filled 为 0 表示 r_data 是没有填充的;如果没有填充过且输入数据有效,那么就将 r_data_filled 设置为 1,表示已经填充;如果已经填充,且表示数据已经完全被发送出去,即 w_data_done 为 1 时将 r_data_filled 设置为 0。

接着,我们需要实现一个计数状态机来控制 r_data 的移位和 r_data_filled 的更新。

//
//r_status
//
//r_statuscontrolsTXFSM
//
localparamSTATUS_MAX=11;
localparamSTATUS_W=$clog2(STATUS_MAX);

reg[STATUS_W-1:0]r_status;
reg[STATUS_W-1:0]w_status_next;

wirew_status_start;
wirew_status_idle;

assignw_status_idle=(r_status=={STATUS_W{1'b0}});
assignw_status_done=(r_status==(STATUS_MAX[STATUS_W-1:0]-1'b1));
assignw_status_tick=i_tick&~w_status_idle;

always@(posedgei_clk,posedgei_arst)
if(i_arst)
r_status<= {STATUS_W{1'b0}};
        else
            r_status <= w_status_next;

    always @(*) begin
        w_status_next = r_status;

        if (w_status_start)
            w_status_next = {{STATUS_W-1{1'b0}}, 1'b1};
        else
            if (w_status_tick)
                if (w_status_done)
                    w_status_next = {STATUS_W{1'b0}};
                else
                    w_status_next = r_status + 1'b1;
    end

    // FSM begins counting when FSM is idle
    assign w_status_start = w_status_idle &
                            // r_data is filled
                            r_data_filled &
                            // i_fstcs is ready to receive data
                            w_fscts &
                            // to sync with o_fsclk signal
                            i_tick;

计数状态机的实现并不复杂。默认情况下,计数器为 0 表示接口处于空闲状态;在处于空闲状态下,如果 r_data 已经被填充,FSCTS 信号为高,在保证与时钟同步的情况下,计数器变成 1,然后每个 w_status_tick 有效时加一,知道计到最大状态 10 之后又变为 0,等待 w_status_start 再次变为 1。

最后,有了上述电路,那么输出信号处理就较为简单。

//
//outputsignals
//
//r_dataisreadywhenr_data_filledis0
assigno_ready=~r_data_filled;

assigno_fsdi=r_data[0];

对于 o_ready 信号,只要数据发送完毕就可以进行填充;而 FSDI 信号直接取 r_data 的最低位。

为了测试这一接口模块,我们还需要设计另外一个控制模块来产生数据并驱动此接口模块。笔者实现了一个控制模块,支持周期发送和最大带宽发送两种模式选择。限于篇幅,此处不再赘述其实现细节。

控制模块的代码、接口模块的代码、cocotb 仿真代码及 icestick 完整的工程可以在 icestick-oifs 库中 gateware 目录 oifs-tx 子目录下找到。

需要注意的是,由于 icestick 板载晶振频率 12MHz,使用 PLL 倍频出最大符合规范的时钟频率为 99MHz,所以,实际的 FSCLK 的反转频率是 49.5MHz,而非设计时的 50MHz。

FPGA 部分实现完毕后,我们还需要实现 USB Host 侧的软件来接收数据。

USB Host 侧软件

为了实现跨平台的代码,笔者使用 libusb 库进行 USB Host 侧的代码。

在 Windows 上,读者需要使用 zadig 软件将端口 B 的 D2XX 驱动替换成 libusb 的驱动。如下图所示:

3c50e9dc-be40-11ed-bfe3-dac502259ad0.png

同时,笔者在 msys2 环境下安装 mingw-w64-x86_64-libftdi 和必要的开发工具,用来构建 USB Host 侧的程序。

笔者编写了两个程序,一个程序用来读取数据并计算性能,名为 oifs-rxperf,另外一个程序用来将数据打印到控制台,名为 oifs-rxdump。

USB Host 侧代码可以在 icestick-oifs 库中 software 目录下找到。这些代码可以不用修改或者稍加修改运行在 Linux 平台上。

测试结果

笔者在 Windows 上测试的结果如下:

3c67925e-be40-11ed-bfe3-dac502259ad0.png

我们可以看到最高的传输速率可以达到 2.57MBps。笔者在 Ubuntu 20.04 和 Ubuntu 22.04 中分别进行了测试,测试结果与 Windows 平台上得到的结果一致。

在接口逻辑仿真环境中,我们假设了 FSCTS 信号总高,但是实际情况并非如此:

3c895934-be40-11ed-bfe3-dac502259ad0.png

通过逻辑分析仪抓到信号的波形来看,FSCTS 在 DEST 位传输完毕后保持 140ns 的低电平,那么一次传输需要大概 364ns 到 384ns,则极限带宽则约为 2.61MBps。

总结

按照本文的说明及相应的代码,读者应该可以在 icestick 上实现从 FPGA 到 USB Host最高 2.57MBps 的数据传输,从而将 icestick 变成一个 USB 数据采集板。







审核编辑:刘清

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

    关注

    1602

    文章

    21325

    浏览量

    593216
  • usb
    usb
    +关注

    关注

    59

    文章

    7436

    浏览量

    258183
  • fifo
    +关注

    关注

    3

    文章

    369

    浏览量

    43069
  • FT2232H
    +关注

    关注

    1

    文章

    4

    浏览量

    9855

原文标题:如何将 FPGA 变成 USB 数据采集板

文章出处:【微信号:Open_FPGA,微信公众号:OpenFPGA】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    基于FPGA的高速LVDS数据传输

    22.4Gbps(Kintex-7).2. 1对LVDS接收时钟+16对LVDS接收数据.本人可以提供FPGA源代码.同时还可以Xilinx评估板ML555/ML605/KC705上演示验证.如有高速LVDS
    发表于 03-01 18:47

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

    小弟正在做一项目,利用 STM32做的关于数据采集系统,打算利用USB实现和PC的数据传输,目前了解的资料多是关于
    发表于 07-06 22:02

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

    优点,通过USB3.0接口的超高速传输特性,可有效地解决高速数据采集中的数据传输和存储问题,测量结果误差小,可信度高,有利于实现
    发表于 08-09 14:18

    汽车行驶记录仪的数据传输设计

    ,建议采用主结构式USB接口;2.标准RS232CD型9针接口。具备上述通信接口的基础,本标准不排除同时使用其他通信方式的可能性。”针对以上要求,可以采用如下几种数据传输的方案。采
    发表于 12-04 10:37

    如何实现ISO数据传输

    你好,我正在尝试实现一个USB麦克风(用于测试ADC精度和USB特性)设备,PSoC枚举工作良好。我无法找到任何有关如何实现ISO数据传输
    发表于 03-26 13:10

    USB数据传输接口电路设计

      USB数据传输接口电路设计  USB接口有数据传输速度快、连接简单、兼容性好等特点。汽车行驶记录仪国家标准考虑RS232接口使用的普及
    发表于 06-17 05:00

    无线数据传输模块的实际应用

    数据传输模块可以对系统采集的数据进行传输,帮助系统实现对安防信息的采集处理。二、、智慧能源环保智慧能源环保属于智慧城市的一个部分,其物联网应用主要集中
    发表于 06-18 04:21

    如何实现FPGA和PC之间的数据传输

    嗨, 我正在使用Saturn Spartan6 numato板。我董事会中实现了一个非常简单的要求版本。现在我想将数据传输FPGA或从FPGA
    发表于 07-31 10:36

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

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

    怎么实现基于FPGA的具有流量控制机制的高速串行数据传输系统设计?

    本文介绍了基于Xilinx Virtex-6 FPGA的高速串行数据传输系统的设计与实现,系统包含AXI DMA和GTX串行收发器,系统增加了流量控制机制来保证高速数据传输的可靠性。最
    发表于 05-25 06:45

    如何将FPGA变成USB数据采集板呢?

    icestick 实现从 FPGA USB Host
    发表于 03-21 14:34

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

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

    什么是U盘的数据传输

    什么是U盘的数据传输率     便携存储是依靠USB接口与系统相连,其接口的速度就限制着移动硬盘的数据传输率。目前的US
    发表于 01-30 10:21 628次阅读

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

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

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

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