WangXuan95 / FPGA-ftdi245fifo

FPGA-based USB fast data transmission using FT232H/FT600 chip. 使用FT232H/FT600芯片进行FPGA与电脑之间的高速数据传输。
https://gitee.com/wangxuan95/FPGA-ftdi245fifo
GNU General Public License v3.0
257 stars 78 forks source link
fpga ft232h ft600 ft601 ipcore rtl systemverilog usb verilog

语言 仿真 部署 部署

English | 中文

 

FTDI 245fifo controller

An FPGA-based controller for FT232H , FT2232H , FT600 , FT601 chips in sync-245-fifo mode, which can realize fast USB communication between FPGA and Host-PC.

Update on June 2023: Add support for byte enable signals. Now it supports all features of FTDI sync-245-fifo mode, and the length of the sending and receiving bytes no longer needs to be a multiple of FTDI chip's byte-width.

 

Introduction

sync-245-fifo mode is the highest speed transmission mode of FTDI's USB series chips. This repository implement a sync-245-fifo mode controller Verilog IP core (ftdi_245fifo_top), providing AXI-stream send and receive interfaces for Verilog developers.

In addition, this repository provides supplementary:

For Host-PC, I provide:

Note: Although the example code of Host-PC is written in Python (I used to use Python), you can also write program in other languages (C++, C #, etc.) to communicate with the FTDI chip. The design on FPGA is not limited to which programming language you use on Host-PC.

 

module_structure
Figure1 : diagram of ftdi_245fifo_top.v

 

IP's Technical Features

 

Performance Test Results

FT232H / FT2232H FT600 FT601
USB generation USB2.0 HS USB3.0 SS USB3.0 SS
Theoretical Throughput 60MB/s 200MB/s 400MBps
Tested Throughput (FPGA→PC) 42MB/s 140MB/s not test yet
Tested Throughput (PC→FPGA) 35MB/s 175MB/s not test yet

 

 

ftdi_245fifo Module Manual

The top design code is in ftdi_245fifo_top.v in RTL/ftdi_245fifo folder, which can be called by FPGA developers to develop their own USB communication applications. Its interface and parameters are shown in Figure2.

module_ports
Figure2 : interfaces of ftdi_245fifo.v

 

Module Parameters

To use this module, you should first determine the value of each Verilog parameter, as shown in the following table:

parameter Introduction
TX_EW Determines the data width of the AXI-stream sending interface (that is, the width of tx_data): 0 corresponds to 8bit width, 1 corresponds to 16bit width, 2 corresponds to 32bit width, and so on. It can be set arbitrarily according to your requirement and is not limited by the FTDI USB chip you used.
TX_EA Determines the depth of send buffer, depth=2^TX_EA. The default is 10 (that is, the default depth is 1024). If the FPGA BRAM is larger, it can be set larger to improve burst performance.
RX_EW Determines the data width of the AXI-stream receiving interface (that is, the width of rx_data): 0 corresponds to 8bit width, 1 corresponds to 16bit width, 2 corresponds to 32bit width, and so on. It can be set arbitrarily according to your requirement and is not limited by the FTDI USB chip you used.
RX_EA Determines the depth of receive buffer, depth=2^RX_EA. The default is 10 (that is, the default depth is 1024). If the FPGA BRAM is larger, this item can be set larger to improve burst performance.
CHIP_TYPE should be "FTx232H" , "FT600" , or "FT601" according to the FTDI chip you used

 

Module Interface: reset

The reset signal of ftdi_245fifo_top.v is:

input  wire                    rstn_async;

rstn_async is the global asynchronous reset of the module, 0 means reset, 1 means release reset. This signal can be directly set to 1'b1, or connected to the global reset signal.

 

Module Interface: Connect to FTDI Chip

The FTDI chip's signals of ftdi_245fifo_top.v are:

// Connect to FTDI chip ------------------------------
input  wire                    ftdi_clk;
input  wire                    ftdi_rxf_n;
input  wire                    ftdi_txe_n;
output wire                    ftdi_oe_n;
output wire                    ftdi_rd_n;
output wire                    ftdi_wr_n;
inout       [(8<<CHIP_EW)-1:0] ftdi_data;
inout       [(1<<CHIP_EW)-1:0] ftdi_be;

Note:

 

Module Interface: AXI-stream sending interface

The sending interface is a standard AXI-stream slave, which allows users to send data to FTDI chip (which will be sent to Host-PC). Corresponding definations:

// AXI-stream slave sending interface ------------------------------
input  wire                    tx_clk;       // AXI-stream's clock
output wire                    tx_tready;
input  wire                    tx_tvalid;
input  wire   [(8<<TX_EW)-1:0] tx_tdata;
input  wire   [(1<<TX_EW)-1:0] tx_tkeep;
input  wire                    tx_tlast;

Firstly, you should provide a clock on tx_clk (no special limitations of frequency, usually the main clock of FPGA). The AXI-stream is synchronized with the clock.

The operation sequence of AXI-stream is detailed in AXI-stream specification . Here is a brief explanation:

:warning: FTDI chips can only send and receive pure data streams without the concept of data packets, so tx_tlast is only used to control whether to send immediately. After the data is sent to the computer, the software cannot know where is the boundary that tx_tlast specified.

 

Module Interface: AXI-stream receiving interface

The receiving interface is a standard AXI-stream master, which allows users to receive data from FTDI chip (from Host-PC). Corresponding definations:

// AXI-stream master receiving interface ------------------------------
input  wire                    rx_clk;       // AXI-stream clock
input  wire                    rx_tready;
output wire                    rx_tvalid;
output wire   [(8<<RX_EW)-1:0] rx_tdata;
output wire   [(1<<RX_EW)-1:0] rx_tkeep;
output wire                    rx_tlast;

Firstly, you should provide a clock on rx_clk (no special limitations of frequency, usually the main clock of FPGA). The AXI-stream is synchronized with the clock.

rx_clk can be as same as or different from tx_clk .

Note the following:

:warning: FTDI chips can only send and receive pure data streams without the concept of data packets, so rx_tlast is only used to indicate whether the current data is the last data taken out of the FTDI chip's buffer. The software on the Host-PC cannot control rx_tlast signal. For example, if you call usb.send() function twice in the software, the two blocks of data may be merged after being sent to the FPGA, and there may not be a rx_tlast=1 boundary between them.

 

Further explanation for tvalid&tready handshake

Take the following waveform as an example, in this waveform, the user interface sends 3 data: D1, D2, D3.

cycle                          1     2     3     4     5     6     7     8     9     10    11
                             _    __    __    __    __    __    __    __    __    __    __    __
 clk                          \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \
                                         _____________________________             _____
tx_tvalid                    ___________/                             \___________/     \________
                             _________________                   ________________________________
tx_tready                                     \_________________/
                                         _____ _______________________             _____
tx_tdata/tx_tkeep/tx_tlast   XXXXXXXXXXXX__D1_X___________D2__________XXXXXXXXXXXXX__D3_XXXXXXXXX

 

 

Simulation

Simulation related files are in the SIM folder, where:

The behavior of this simulation is that the FTDI chip continuously sends increasing bytes to the FPGA. The FPGA connects the AXI-stream sending interface and receiving interface loopback. Therefore, the data will be sent back to the FTDI chip, and the FTDI chip will receive the increasing bytes.

Use iverilog to simulate

Before using iverilog for simulation, you need to install iverilog , see: iverilog_usage

Then double-click tb_ftdi_245fifo_run_iverilog.bat to run simulation (only for Windows), and then you can open the generated dump.vcd file to view the waveform.

Use other simulators

You need to add all .v files in SIM folder and RTL/ftdi_245fifo folder into the simulation project. And set tb_ftdi_245fifo.v as the top. And then run simulation.

 

 

Getting started with FT232H

FT232H is a USB2.0 High Speed communication chip with a theoretical rate of 60MBps. In this demo, the FPGA communicates with Host-PC through FT232H.

:warning: This demo also applies to FT2232H (you need to work around it yourself), because FT2232H is highly similar to FT232H. Note that FT2232H's channel-A can be configured to sync-245-fifo mode , but channel-B cannot.

Step1: Install FTD2XX Driver and Library

Please follow the instructions in FTD2XX_guide.md to install the FTD2XX driver and Python FTD2XX library on your Host-PC (Windows system).

Step2: Deploy FPGA Project

Following is the hierarchical structure of the FPGA project:

Please add above-mentioned files to FPGA project

Then, please make pin constraints in the FPGA project. Specifically, you need to check the schematic of your FPGA board (or the supporting materials of the development board) to understand which FT232H pin should connected to which FPGA pin; then, constraint the signals of the top layer of the FPGA project to the corresponding FPGA pin. The correspondence is shown in the following table (this table is simplified from FT232H DataSheet page 9):

FT232H pin FT232H pin name FT232H pin name (in 245-fifo mode) signal name in top module
13 ADBUS0 D0 ftdi_data[0]
14 ADBUS1 D1 ftdi_data[1]
15 ADBUS2 D2 ftdi_data[2]
16 ADBUS3 D3 ftdi_data[3]
17 ADBUS4 D4 ftdi_data[4]
18 ADBUS5 D5 ftdi_data[5]
19 ADBUS6 D6 ftdi_data[6]
20 ADBUS7 D7 ftdi_data[7]
21 ACBUS0 RXF# ftdi_rxf_n
25 ACBUS1 TXE# ftdi_txe_n
26 ACBUS2 RD# ftdi_rd_n
27 ACBUS3 WR# ftdi_wr_n
28 ACBUS4 SIWU# ftdi_siwu (=1) :warning:
29 ACBUS5 CLKOUT ftdi_clk
30 ACBUS6 OE# ftdi_oe_n
31 ACBUS7 PWRSAV# ftdi_pwrsav (=1) :warning:
34 RESET# RESET# ftdi_resetn (=1) :warning:

:warning: SIWU#, PWRSAV# and RESET# in the above table are actually always pulled to high. Some boards directly use resistors to pull-up them without connecting them to the FPGA, in this case, you don't need to constrain these pins and simply comment out the statements related to them in fpga_top_example_ft232h.v.

 

If you want to design the FT232H PCB by yourself, please refer to Figure3.

ft232h_example_sch
Figure3 : Example schematic of FT232H USB interface circuit.

 

Notations of the clock and timing constraints:

 

Other Notations:

 

Step3: Program FT232H chip

For each FT232H chip, it needs to be programmed to 245-fifo mode when it is used for the first time. Each FT232H chip only needs to be programmed once, because there is an EEPROM chip on the periphery of the FT232H to permanently save the configuration, and it does not need to be programmed again every time it is used (unless you program it to another mode).

First go to the FTDI download page to download and install FT_Prog software. Then do the following steps:

ft232h_program
Figure4 : Program FT232H chip to 245-fifo mode.

 

Step4: Run Programs on Host-PC

Before running these programs, make sure that FT232H has been programmed into 245-fifo mode according to step3, and the FPGA project created in step2 has been programed to FPGA.

I provide the following Python programs in python folder that will communicate with FPGA through FT232H.

File Name Function
USB_FTX232H_FT60X.py Defines the USB_FTX232H_FT60X_sync245mode class, implements constructor, close, send, recv methods. This class is universal for FT232H, FT2232H, FT600, and FT601.
usb_loopback_simple.py The Host-PC firstly sends 16 bytes to FPGA and then receives data. Because the FPGA project loopbacks data, the Host-PC will receive these 16 bytes. This program is associated with the FPGA top design fpga_top_ft232h_loopback.v
usb_loopback_mass.py The Host-PC firstly sends a large amount of data to FPGA, and then receives data. Because the FPGA project loopbacks data, the Host-PC will receive these bytes and the program will compare whether the received data is consistent with the previously sent data to verify the correctness of the loopback. This program is associated with the FPGA top design fpga_top_ft232h_loopback.v

 

 

Getting Started with FT600

The FT600 is a USB3.0 Super Speed communication chip with a theoretical rate of 200MBps. In this example, the FPGA communicates with the Host-PC through FT600.

Step1: Install FTD3XX Driver and Library

Please follow the instructions in FTD3XX_guide.md to install the FTD3XX driver and Python FTD3XX library on your Host-PC (Windows system).

Step2: Deploy FPGA Project

Following is the hierarchical structure of the FPGA project:

Please add above-mentioned files to FPGA project.

Then, please make pin constraints in the FPGA project. Specifically, you need to check the schematic of your FPGA board (or the supporting materials of the development board) to understand which FT600 pin should connected to which FPGA pin; then, constraint the signals of the top layer of the FPGA project (that is, fpga_top_example_ft600.v) to the corresponding FPGA pin. The correspondence is shown in the following table (this table is simplified from FT600 DataSheet page 7-10):

FT600 pin number FT600 pin name signal name in top module
33 DATA_0 ftdi_data[0]
34 DATA_1 ftdi_data[1]
35 DATA_2 ftdi_data[2]
36 DATA_3 ftdi_data[3]
39 DATA_4 ftdi_data[4]
40 DATA_5 ftdi_data[5]
41 DATA_6 ftdi_data[6]
42 DATA_7 ftdi_data[7]
45 DATA_8 ftdi_data[8]
46 DATA_9 ftdi_data[9]
47 DATA_10 ftdi_data[10]
48 DATA_11 ftdi_data[11]
53 DATA_12 ftdi_data[12]
54 DATA_13 ftdi_data[13]
55 DATA_14 ftdi_data[14]
56 DATA_15 ftdi_data[15]
2 BE_0 ftdi_be[0]
3 BE_1 ftdi_be[1]
43 CLKOUT ftdi_clk
5 RXF_N ftdi_rxf
4 TXE_N ftdi_txe
9 OE_N ftdi_oe
8 RD_N ftdi_rd
7 WR_N ftdi_wr
6 SIWU_N ftdi_siwu (=1) :warning:
10 RESET_N ftdi_resetn (=1) :warning:
11 WAKEUP_N ftdi_wakeupn (=0) :triangular_flag_on_post:
12 GPIO0 ftdi_gpio0 (=0) :triangular_flag_on_post:
13 GPIO1 ftdi_gpio1 (=0) :triangular_flag_on_post:

:warning: SIWU_N and RESET_N in the above table are actually always pulled to high. Some boards directly use resistors to pull-up them without connecting them to the FPGA, in this case, you don't need to constrain these pins and simply comment out the statements related to them in fpga_top_example_ft600.v.

:triangular_flag_on_post: WAKEUP_N, GPIO0 and GPIO1 in the above table are actually always pulled to GND. Some boards directly use resistors to pull-down them without connecting them to the FPGA, in this case, you don't need to constrain these pins and simply comment out the statements related to them in fpga_top_example_ft600.v.

If you want to draw FT600 PCB by yourself, please refer to Figure5.

ft600_example_sch
Figure3 : Example schematic of FT600 USB interface circuit.

 

Notations of the clock and timing constraints:

 

Other Notations:

 

Step3: Run Programs on Host-PC

Before running these programs, make sure that the FPGA project created in step2 has been programed to FPGA.

I provide the following Python programs in python folder that will communicate with FPGA through FT600.

File Name Function
USB_FTX232H_FT60X.py Defines the USB_FTX232H_FT60X_sync245mode class, implements constructor, close, send, recv methods. This class is universal for FT232H, FT2232H, FT600, and FT601.
usb_loopback_simple.py The Host-PC firstly sends 16 bytes to FPGA and then receives data. Because the FPGA project loopbacks data, the Host-PC will receive these 16 bytes. This program is associated with the FPGA top design fpga_top_ft600_loopback.v
usb_loopback_mass.py The Host-PC firstly sends a large amount of data to FPGA, and then receives data. Because the FPGA project loopbacks data, the Host-PC will receive these bytes and the program will compare whether the received data is consistent with the previously sent data to verify the correctness of the loopback. This program is associated with the FPGA top design fpga_top_ft600_loopback.v

 

Reference

 

 

 

 

FTDI 245fifo controller

FT232HFT2232HFT600FT601 等芯片在 sync-245-fifo 模式下的控制器,实现 FPGA 与上位机 (电脑) 的高速通信。

2023/6 更新内容:加入 byte enable 信号的支持。现在已支持 FTDI sync-245-fifo 模式的所有功能,收发字节长度不再必须是 FTDI 芯片位宽的倍数。

 

简介

sync-245-fifo 模式 是 FTDI 公司的 USB 系列芯片的最高速的传输模式。本库将 sync-245-fifo 控制器封装成 Verilog 模块 (IP顶层模块名为 ftdi_245fifo_top ),它具有标准 AXI-stream 收发接口 ,供 Verilog 开发者调用。

除了 IP 核本身,本库还提供配套的:

对于电脑 (上位机) ,我提供了:

注:虽然上位机的示例代码是用 Python 编写的 (我习惯用 Python) ,但你也可以用其它语言 (C++, C# 等) 编写上位机程序与 FTDI 芯片通信。FPGA 上的设计并不局限你在上位机上使用哪种编程语言

 

图1是该系统工作时的结构框图。

module_structure
图1:系统框图

 

特点

 

性能测试结果

芯片型号 FT232H / FT2232H FT600 FT601
USB模式 USB2.0 HS USB3.0 SS USB3.0 SS
理论速率 60MB/s 200MB/s 400MB/s
实测速率 (FPGA→上位机) 42MB/s 140MB/s 未测
实测速率 (上位机→FPGA) 35MB/s 175MB/s 未测

 

 

ftdi_245fifo_top 模块说明

Verilog 设计代码见 RTL/ftdi_245fifo 目录中的 ftdi_245fifo_top.v ,它是IP的顶层,可供 FPGA 开发者调用来开发自己的 USB 通信业务。它的接口和参数如图2

module_ports
图2:ftdi_245fifo_top.v 的接口

 

模块参数

要调用本模块,首先要根据实际情况指定各个参数 (parameter) 的值,如下表:

parameter 说明
TX_EW 决定了用户发送接口的数据宽度 (即 tx_tdata 的宽度) : 0对应8bit宽,1对应16bit宽,2对应32bit宽,3对应64bit宽,…… 可以根据需要任意设置,不受 USB 芯片型号限制。
TX_EA 决定了用户发送缓存的深度,深度=2^TX_EA。默认为10 (深度为1024) ,如果 FPGA BRAM 较大,该项可以设得更大,来提高突发性能。
RX_EW 决定了用户接收接口的数据宽度 (即 rx_tdata 的宽度) : 0对应8bit宽,1对应16bit宽,2对应32bit宽,3对应64bit宽,…… 可以根据需要任意设置,不受 USB 芯片型号限制。
RX_EA 决定了用户接收缓存的深度,深度=2^RX_AEXP。默认为10(即默认深度为1024),如果 FPGA BRAM 较大,该项可以设得更大,来提高突发性能。
CHIP_TYPE 必须是 "FTx232H" , "FT600" , 或 "FT601"

 

模块接口:复位

复位信号见 ftdi_245fifo_top.v 代码中的:

input  wire                    rstn_async;

rstn_async 是模块的全局异步复位信号,1'b0 代表复位,1'b1 代表释放复位。在使用中,该信号可以直接设为 1'b1 ,或者连接到工程的复位信号上。

 

模块接口:连接 FTDI 芯片

FTDI 芯片信号见 ftdi_245fifo_top.v 代码中的:

// 连接 FTDI 芯片的信号 ------------------------------
input  wire                    ftdi_clk;
input  wire                    ftdi_rxf_n;
input  wire                    ftdi_txe_n;
output wire                    ftdi_oe_n;
output wire                    ftdi_rd_n;
output wire                    ftdi_wr_n;
inout       [(8<<CHIP_EW)-1:0] ftdi_data;
inout       [(1<<CHIP_EW)-1:0] ftdi_be;

这些信号应连接到 FTDI 芯片的引脚上。

 

模块接口:AXI-stream slave 发送接口

发送接口是标准 AXI-stream slave ,用户通过它发送数据给 FTDI 芯片 (最终会发送给电脑) 。对应代码中的:

// AXI-stream slave 发送接口 ------------------------------
input  wire                    tx_clk;       // AXI-stream 时钟
output wire                    tx_tready;
input  wire                    tx_tvalid;
input  wire   [(8<<TX_EW)-1:0] tx_tdata;
input  wire   [(1<<TX_EW)-1:0] tx_tkeep;
input  wire                    tx_tlast;

首先,需要提供一个 tx_clk 时钟 (频率不限,一般都提供 FPGA 主时钟) 。该 AXI-stream 同步于该时钟。

AXI-stream 的操作时序详见 《AXI-stream specification》 。这里简要说明如下:

:warning: FTDI 芯片只能收发单纯的数据流,而没有数据包的概念,因此 tx_tlast 仅仅用于控制是否立即发送。数据发到电脑上后,上位机的软件无法知道哪里是 tx_last 指定的包的分界点。

 

模块接口:AXI-stream master 接收接口

接收接口是标准 AXI-stream master ,用户通过它接收来自 FTDI 芯片 (来自电脑) 的数据。对应代码中的:

// AXI-stream master 接收接口 ------------------------------
input  wire                    rx_clk;       // AXI-stream 时钟
input  wire                    rx_tready;
output wire                    rx_tvalid;
output wire   [(8<<RX_EW)-1:0] rx_tdata;
output wire   [(1<<RX_EW)-1:0] rx_tkeep;
output wire                    rx_tlast;

首先,需要提供一个 rx_clk 时钟 (频率不限,一般都提供 FPGA 主时钟) 。该 AXI-stream 同步于该时钟。

rx_clk 可以和 tx_clk 是同一个时钟或不同时钟。

对 AXI-stream 各信号简要说明如下:

:warning: FTDI 芯片只能收发单纯的数据流,而没有数据包的概念,因此 rx_tlast 仅仅用于指示当前数据是不是 FTDI 芯片缓存里拿出的最后一个数据。上位机的软件上无法控制 rx_tlast 信号。例如,如果你在软件中调用 usb.send() 函数两次,发送了两次数据,发到 FPGA 上后这两次数据可能连在一起,中间不一定有 rx_tlast=1 分界。

 

关于 AXI-stream tvalid&tready 的进一步说明

treadytvalid 的握手举例如下波形图,用户接口发送了3个数据:D1, D2, D3 。其中:

cycle                          1     2     3     4     5     6     7     8     9     10    11
                             _    __    __    __    __    __    __    __    __    __    __    __
 clk                          \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \
                                         _____________________________             _____
tx_tvalid                    ___________/                             \___________/     \________
                             _________________                   ________________________________
tx_tready                                     \_________________/
                                         _____ _______________________             _____
tx_tdata/tx_tkeep/tx_tlast   XXXXXXXXXXXX__D1_X___________D2__________XXXXXXXXXXXXX__D3_XXXXXXXXX

 

 

模块仿真

仿真相关的文件在 SIM 目录中,其中:

该仿真的行为是:FTDI 芯片不断发送不断递增的字节给 FPGA ,FPGA 将 AXI-stream 发送接口和接收接口回环 (loopback) 连接,因此数据会被发回 FTDI 芯片,因此 FTDI 芯片会收到不断递增的字节。

使用 iverilog 仿真

使用 iverilog 进行仿真前,需要安装 iverilog ,见:iverilog_usage

然后双击 tb_ftdi_245fifo_run_iverilog.bat 运行仿真,然后可以打开生成的 dump.vcd 文件查看波形。

使用其它仿真工具

需要把 SIM 目录和 RTL/ftdi_245fifo 目录中 的所有 .v 文件加入仿真工程,以 tb_ftdi_245fifo.v 为仿真的顶层模块,然后运行仿真。

 

 

开始使用 FT232H

FT232H 是 USB2.0 High Speed 通信芯片,本例实现 FPGA 通过 FT232H 与上位机进行通信。

:warning: 本例也适用于 FT2232H (具体操作时需要你自己变通变通),因为 FT2232H 与 FT232H 高度相似。注意 FT2232H 的 channel-A 可配置成 sync-245-fifo 模式 ,而 channel-B 则不行。

步骤1:安装驱动和库

请按照 FTD2XX_guide.md 的指示在上位机 (以Windows系统为例) 上安装 FTD2XX 驱动和 Python FTD2XX 库。

步骤2:部署 FPGA 工程

以下是该 FPGA 工程的模块层次结构:

请将以上 .v 文件加入工程。

然后,请在 FPGA 工程中进行引脚约束,具体而言,你需要查看电路板的原理图 (或开发板配套资料) ,了解 FT232H 的各引脚被连接到了 FPGA 的哪些引脚号上;然后,把 FPGA 工程的顶层的信号分配到对应的 FPGA 引脚号上,使得这些信号与 FT232H 的引脚对应起来。对应关系见下表 (该表简化自 FT232H DataSheet 第9页) :

FT232H引脚号 FT232H引脚名 FT232H引脚名 (245-fifo 模式下) 应约束到顶层的信号名
13 ADBUS0 D0 ftdi_data[0]
14 ADBUS1 D1 ftdi_data[1]
15 ADBUS2 D2 ftdi_data[2]
16 ADBUS3 D3 ftdi_data[3]
17 ADBUS4 D4 ftdi_data[4]
18 ADBUS5 D5 ftdi_data[5]
19 ADBUS6 D6 ftdi_data[6]
20 ADBUS7 D7 ftdi_data[7]
21 ACBUS0 RXF# ftdi_rxf_n
25 ACBUS1 TXE# ftdi_txe_n
26 ACBUS2 RD# ftdi_rd_n
27 ACBUS3 WR# ftdi_wr_n
28 ACBUS4 SIWU# ftdi_siwu (=1) :warning:
29 ACBUS5 CLKOUT ftdi_clk
30 ACBUS6 OE# ftdi_oe_n
31 ACBUS7 PWRSAV# ftdi_pwrsav (=1) :warning:
34 RESET# RESET# ftdi_resetn (=1) :warning:

:warning: SIWU# 、 PWRSAV# 和 RESET# 实际上是要永远被拉为高电平的 (你也可以看到在 fpga_top_example_ft232h.v 中它们被 assign 为 1) ,因此有些板子的设计直接用电阻把它们拉到高电平上,而没有连接到 FPGA ,对于这种情况,就不用在 FPGA 约束它们的引脚,并直接在 fpga_top_example_ft232h.v 中注释掉与它们相关的语句即可。

 

如果你要自己画 FT232H 的 PCB,可参考图3

ft232h_example_sch
图3:FT232H USB 接口电路的参考原理图设计

 

关于本工程的时钟和时序约束:

 

在 FPGA 工程中,另外注意以下几点:

然后你就可以编译工程,步骤略。

 

步骤3:烧录 FT232H 芯片

针对每颗 FT232H 芯片,需要在初次使用时烧录为 sync-245-fifo 模式。每颗 FT232H 芯片只需要烧录一次,因为 FT232H 外围会有个 EEPROM 芯片用来永久保存配置,之后每次使用都不需要再烧录 (除非你又烧录了其它模式) 。

首先进入 FTDI官网下载页面 下载并安装 FT_Prog 软件。然后进行以下步骤:

ft232h_program
图4:烧录 FT232H 芯片,配置为 245-fifo 模式。

 

步骤4:在电脑上运行通信程序

运行这些程序之前,请确保 FT232H 已经按照步骤3被烧录为 sync-245-fifo 模式,且 FPGA 中下载了步骤2中建立的工程。

我在 python 文件夹中提供了以下几个 Python 程序,它们会通过 FT232H 与 FPGA 进行通信。

文件名 功能
USB_FTX232H_FT60X.py 定义了 USB_FTX232H_FT60X_sync245mode 类,用来对 FTDI USB 设备进行打开、关闭、发送数据、接收数据。适用于 FT232H、FT2232H、FT600、FT601 。会被以下程序调用。
usb_loopback_simple.py 上位机先发送 16 字节给 FPGA ,然后接收数据。因为 FPGA 工程将收发回环连接,所以上位机会接收到这 16 字节。该程序和 FPGA 顶层设计 fpga_top_ft232h_loopback.v 配套。
usb_loopback_mass.py 上位机先发送发送大量数据给 FPGA ,然后接收数据。因为 FPGA 工程将收发回环连接,所以上位机会接收到这些字节,程序会判断收到的数据和之前发出去的数据是否一致,来验证回环的正确性。该程序和 FPGA 顶层设计 fpga_top_ft232h_loopback.v 配套。

 

 

开始使用 FT600

FT600 是 USB3.0 Super Speed 通信芯片,本例实现 FPGA 通过 FT600 与上位机进行通信。

步骤1:安装驱动和库

请按照 FTD3XX_guide.md 的指示在 Host-PC (Windows系统) 上安装 FTD3XX 驱动和 Python FTD3XX 库。

步骤2:部署 FPGA 工程

以下是该 FPGA 工程的模块层次结构:

请将以上 .v 文件加入工程。

然后,请在 FPGA 工程中进行引脚约束,具体而言,你需要查看电路板的原理图 (或开发板配套资料),了解 FT600 的各引脚被连接到了 FPGA 的哪些引脚号上;然后,把 FPGA 工程的顶层的信号分配到对应的 FPGA 引脚号上,使得这些信号与 FT600 的引脚对应起来。对应关系见下表 (该表简化自 FT600 DataSheet 第 7\~10 页) :

FT600引脚号 FT600引脚名 应约束到顶层的信号名
33 DATA_0 ftdi_data[0]
34 DATA_1 ftdi_data[1]
35 DATA_2 ftdi_data[2]
36 DATA_3 ftdi_data[3]
39 DATA_4 ftdi_data[4]
40 DATA_5 ftdi_data[5]
41 DATA_6 ftdi_data[6]
42 DATA_7 ftdi_data[7]
45 DATA_8 ftdi_data[8]
46 DATA_9 ftdi_data[9]
47 DATA_10 ftdi_data[10]
48 DATA_11 ftdi_data[11]
53 DATA_12 ftdi_data[12]
54 DATA_13 ftdi_data[13]
55 DATA_14 ftdi_data[14]
56 DATA_15 ftdi_data[15]
2 BE_0 ftdi_be[0]
3 BE_1 ftdi_be[1]
43 CLKOUT ftdi_clk
5 RXF_N ftdi_rxf
4 TXE_N ftdi_txe
9 OE_N ftdi_oe
8 RD_N ftdi_rd
7 WR_N ftdi_wr
6 SIWU_N ftdi_siwu (=1) :warning:
10 RESET_N ftdi_resetn (=1) :warning:
11 WAKEUP_N ftdi_wakeupn (=0) :triangular_flag_on_post:
12 GPIO0 ftdi_gpio0 (=0) :triangular_flag_on_post:
13 GPIO1 ftdi_gpio1 (=0) :triangular_flag_on_post:

:warning: SIWU_N 和 RESET_N 实际上是要永远被拉为高电平的,因此有些板子的设计直接用电阻把它们拉到高电平上,而没有连接到 FPGA ,对于这种情况,就不用在 FPGA 约束它们的引脚,并直接在 fpga_top_example_ft600.v 中注释掉与它们相关的语句即可。

:triangular_flag_on_post: WAKEUP_N 、 GPIO0 和 GPIO1 实际上是要永远被拉为低电平的,因此有些板子的设计直接用电阻把它们拉到GND上,而没有连接到 FPGA ,对于这种情况,就不用在 FPGA 约束它们的引脚,并直接在 fpga_top_example_ft600.v 中注释掉与它们相关的语句即可。

 

如果你要自己画 FT600 的 PCB,可参考图5

ft600_example_sch
图5:FT600 USB 接口电路的参考原理图设计

 

关于本工程的时钟和时序约束:

 

在 FPGA 工程中,另外注意以下几点:

然后你就可以编译工程,步骤略。

 

步骤3:在电脑上运行通信程序

运行这些程序之前,请确保 FPGA 中下载了步骤2中建立的工程。

我在 python 文件夹中提供了以下几个 Python 程序,它们会通过 FT600 与 FPGA 进行通信。

文件名 功能
USB_FTX232H_FT60X.py 定义了 USB_FTX232H_FT60X_sync245mode 类,用来对 FTDI USB 设备进行打开、关闭、发送数据、接收数据。适用于 FT232H、FT2232H、FT600、FT601 。会被以下程序调用。
usb_loopback_simple.py 上位机先发送 16 字节给 FPGA ,然后接收数据。因为 FPGA 工程将收发回环连接,所以上位机会接收到这 16 字节。该程序和 FPGA 顶层设计 fpga_top_ft600_loopback.v 配套。
usb_loopback_mass.py 上位机先发送发送大量数据给 FPGA ,然后接收数据。因为 FPGA 工程将收发回环连接,所以上位机会接收到这些字节,程序会判断收到的数据和之前发出去的数据是否一致,来验证回环的正确性。该程序和 FPGA 顶层设计 fpga_top_ft600_loopback.v 配套。

 

参考资料