目录
1.介绍
FT232HQ芯片是FTDI公司生产的单通道USB2.0驱动芯片,其USB通信速度可以达到480Mb/s。在芯片内部,有USB硬件接口差分电平转换,并封装了USB相关协议,留有数据交互接口。支持转UART/FIFO模式,可配置成多种工业串行和并行接口,在本文中配置成FT245同步FIFO接口模式。
2.内部原理图
-
LDO Regulator:产生基准电压供内部使用且可对外输出;
-
EEPROM_Interface:配置接口,配置FT232H不同的工作模式;
-
UTMI_PHY:USB2.0传输MAC层接口,主要负责处理解析物理底层的USB协议及信号;
-
USB_Protocol Engine And FIFO Control:与UTMI_PHY进行交互,进一步解析处理USB2.0协议层的数据;
-
MPSSE/Multi_purpose UART/FIFO controler:多功能UART/FIFO控制器,集成面向用户的IO,直接负责与用户端进行数据交互。
3.引脚说明
引脚图如下:
在不同工作模式下,引脚的作用也不一样,下图为具体工作模式下所需要用到的引脚。
在FT245同步FIFO接口工作模式下,所用到的引脚和信号描述如下图所示。
引脚号 | 引脚名 | 类型 | FT245配置说明 |
---|---|---|---|
13,14,15,16,14,18,19,20 | ADBUS[7:0] | I/O | FT232数据端口,双向FIFO数据,8位位宽 |
21 | RXF# | OUTPUT | 可读标志信号。低电平有效,可通过驱动RD#读取数据。在此模式下,在RXF#和RD#都很低的每个时钟上传输数据,注意的是再确认RD#低之前,必须驱动至少1个时钟周期 |
25 | TXE# | OUTPUT | 数据可写标志,低电平有效,可以通过驱动WR#低将数据写入FIFO。在同步模式下,在TXE#和WR#都很低的每个时钟上传输数据。 |
26 | RD# | INPUT | 读FIFO数据输出使能,低电平有效,使当前的FIFO数据字节被驱动到D0...D7上。下一个FIFO数据字节(如果可用)从每个CLKOUT周期从接收FIFO缓冲区获取,直到RD#变高。 |
27 | WR# | INPUT | 写FIFO数据输入使能,低电平有效,允许将D0...D7引脚上的数据字节写入传输FIFO缓冲区。下一个FIFO数据字节将被写入传输FIFO缓冲区,直到WR#变高。 |
28 | SIWU# | INPUT | 发送/唤醒信号,拉高处理 |
29 | CLKOUT | OUTPUT | 由芯片驱动的60MHz时钟。所有的信号都应同步到这个时钟上。 |
30 | OE# | INPUT | 输出使能,低电平有效,将数据驱动到D0-7。在RD#低之前,至少1个时钟周期,以允许数据缓冲区周转。 |
4.FT245同步FIFO接口模式时序操作
该模式使用同步接口来获得较高的数据传输速度。该芯片驱动一个60MHz的CLKOUT时钟,供外部系统使用。注意,任何时间只能执行读或写循环。数据在CLKOUT时钟的上升边缘上被读取或写入。
4.1读取操作
当芯片驱动RXF#low时,将启动一个读取操作。
外部系统然后可以驱动OE#低,使数据总线驱动程序在周围,然后确认数据与RD#信号去低。第一个数据字节在OE#较低后就在总线上。
外部系统可以通过保持RD#的低水平将数据从芯片中分离出来,也可以在RD#信号中插入等待状态。
如果有更多的数据要读取,它将改变在RD#采样低。一旦所有的数据都被消耗掉了,芯片将驱动RXF#高。
在RXF#高之后,数据总线上出现的任何数据都无效,应该忽略。
4.2 写入操作
当TXE#值较低时,可以启动写操作。
当数据有效时,WR#就会变低。如果TXE#仍然很低,则可以在每个时钟上进行突发操作。
外部系统必须监控TXE#和它自己的WR#,以检查数据是否已被接受。
TXE#和WR#必须都很低才能接受数据。
5.其他说明
-
工具软件“FT_Prog”
FT232H在模式配置上,有官方提供的工具软件“FT_Prog”,可在电脑上安装,然后直接在UI界面进行模式配置。
-
上位机软件
使用FT245同步FIFO接口模式时,外部EEPROM必须设置为245个模式。然后,应用程序将一个软件命令(FT_SetBitMode)发送到FTDI D2xx驱动程序,告诉芯片进入245同步FIFO模式。
6.Verilog实现
主控芯片:Cyclone IV E系列的EP4CE10F17C8
6.1实现功能
上位机通过USB SLAVE接口发送数据给FT232H的数据FIFO,再写入到FPGA的FIFO,从FPGA的FIFO读出数据再回传给FT232H,最后通过USB SLAVE接口传回给上位机显示。
6.2顶层模块
顶层模块完成对FIFO、ft232接收模块和ft232发送模块的例化。
module ft232(
//时钟、复位
input sys_clock, //时钟
input rst_n, //复位
//FT232接收接口
input ft_clk,
input wire ft232_rxf_n,
input wire ft_txe_n,
inout wire [7:0] ft232_data_n,
output wire ft232_wr_n,
output wire ft232_rd_n,
output wire ft232_oe_n,
output wire ft232_siwu
);
//parameter define
parameter CLK_FREQ = 50000000; //定义系统时钟频率
parameter UART_BPS = 115200; //定义串口波特率
//fifo写接口
wire wrreq;
wire [7:0] ft_data_in;
wire wrfull;
//fifo读接口
wire rdreq;
wire [7:0] fifo_data_out;
wire rdempty;
//*****************************************************
//** main code
//*****************************************************
assign ft232_siwu = 1'b1; //注意这个引脚一定要拉高,否则上位机无法接受到数据
//例化fifo
fifo u_fifo(
.wrclk (ft_clk),
.wrreq (wrreq),
.data (ft_data_in),
.wrfull (wrfull),
.rdclk (ft_clk),
.rdreq (rdreq),
.q (fifo_data_out),
.rdempty (rdempty)
);
//例化ft232接收模块
ft232hq_recv u_ft232hq_recv(
.clock (ft_clk),
.rst_n (rst_n),
.rxf_n (ft232_rxf_n),
.wr_n (ft232_wr_n),
.data_recv (ft232_data_n),
.oe_n (ft232_oe_n),
.rd_n (ft232_rd_n),
.fifo_wrfull_n (wrfull),
.fifo_wr_en (wrreq),
.fifo_data_in (ft_data_in)
);
//例化ft232发送模块
ft232hq_send u_ft232hq_send(
.clock (ft_clk),
.rst_n (rst_n),
.rd_n (ft232_rd_n),
.txe_n (ft_txe_n),
.wr_n (ft232_wr_n),
.data_send (ft232_data_n),
.fifo_data_out (fifo_data_out),
.fifo_empty_n (rdempty),
.fifo_rd_en (rdreq)
);
endmodule
6.3FT232H接收模块
module ft232hq_recv(
input clock,
input rst_n,
//ft接口
input wire rxf_n,
input wire wr_n,
input wire [7:0] data_recv,
output reg oe_n,
output wire rd_n,
//写入fifo接口
input wire fifo_wrfull_n,
output wire fifo_wr_en,
output wire [7:0] fifo_data_in
);
reg oe_n_d0;//oe_n下一拍
reg rxf_n_d0;//oe_n下一拍
//*****************************************************
//** main code
//*****************************************************
//在oe_n为低且在oe_n下一拍也为低时拉低rd_n,其他时候为高
assign rd_n = ((oe_n_d0 == 0) && (oe_n == 0 ) && (wr_n == 1))?1'b0 : 1'b1;
//FT232H读状态,将USB数据总线上的值赋给FIFO数据输入,其他时候赋值为高阻态
assign fifo_data_in = ((rxf_n_d0 == 0) && (wr_n == 1))? data_recv:8'hzz;
//在usb_oe_n下一拍也为低,且usb_rxf_n也为低时使能FIFO写
assign fifo_wr_en = ((oe_n_d0 == 0) && (rxf_n == 0 ) && (fifo_wrfull_n == 0) && (wr_n == 1))?1'b1 : 1'b0;
//产生FT232H数据输出使能oe_n
always@(posedge clock or negedge rst_n)begin
if(!rst_n)
oe_n<=1;
else if (!rxf_n)
oe_n<=0;
else if(rxf_n)
oe_n<=1;
end
//FT232H数据输出使能oe_n打一拍
always@(posedge clock or negedge rst_n)begin
if(!rst_n)
oe_n_d0 <= 1'b1;
else
oe_n_d0 <=oe_n;
end
//FT232H数据接收使能rxf_n打一拍
always@(posedge clock or negedge rst_n)begin
if(!rst_n)
rxf_n_d0 <= 1'b1;
else
rxf_n_d0 <=rxf_n;
end
endmodule
6.4FT232H发送模块
module ft232hq_send(
input clock,
input rst_n,
//ft接口
input wire rd_n,
input wire txe_n,
output wire wr_n,
output wire [7:0] data_send,
//读fifo接口
input wire [7:0] fifo_data_out,
input wire fifo_empty_n,
output wire fifo_rd_en
);
reg txe_n_d0;
reg fifo_rd_en_d0;
reg fifo_empty_n_d0;
//*****************************************************
//** main code
//*****************************************************
//在FT232H写状态,且usb_txe_n为低,且FPGA FIFO 不空时,使能FT232H FIFO写
assign wr_n = ((txe_n_d0 == 0) && (txe_n == 0 )&& (fifo_empty_n_d0 == 0)&& rd_n && (fifo_rd_en_d0 == 1))?1'b0 : 1'b1;
//在FT232H写状态,将FIFO的数据输出赋值给将USB数据总线,其他时候为高阻态
assign data_send = ((txe_n_d0 == 0) &&(txe_n == 0) && (fifo_empty_n_d0 == 0) && rd_n && (fifo_rd_en_d0 == 1))? fifo_data_out: 8'hzz;
//在FT232H写状态,且usb_txe_n也为低时,且FPGA FIFO 不空时,使能FIFO读
assign fifo_rd_en =((txe_n_d0 == 0) && (txe_n == 0 )&& (fifo_empty_n == 0)&& rd_n)?1'b1 : 1'b0;
//FT232H数据接收txe_n打一拍
always@(posedge clock or negedge rst_n)begin
if(!rst_n)
txe_n_d0 <= 1'b1;
else
txe_n_d0 <= txe_n;
end
always@(posedge clock or negedge rst_n)begin
if(!rst_n) begin
fifo_rd_en_d0 <= 1'b1;
fifo_empty_n_d0 <= 1;
end
else begin
fifo_rd_en_d0 <= fifo_rd_en;
fifo_empty_n_d0 <= fifo_empty_n;
end
end
endmodule
6.5SignalTap II捕获波形
开始接收数据:
过程:上位机通过USB SLAVE接口发送数据给FT232H的数据FIFO,再写入到FPGA的FIFO;
操作:当rxf_n被拉低时,意味着可以接收数据,此时拉低oe_n和rd_n,开始对数据的接收。data_recv接收的数据是0x00-0xff。
接收数据结束,开始发送数据:
过程:从FPGA的FIFO读出数据再回传给FT232H,最后通过USB SLAVE接口传回给上位机显示。
操作:当rxf_n被拉高时,意味着停止接收数据,此时拉高oe_n和rd_n,停止对数据的接收,可以看到rxf_n拉高的时候接收的最后一个数据是0xff。
txe_n一直为低,接收数据结束后,FPGA这边就可以读取FIFO的数据回传给FT232,在传回给上位机,拉低wr_n开始发送数据,可看到wr_n拉低时,data_recv发送的数据是从0x00开始发送。
注意:发送和接收数据都是同一个接口。
发送数据结束:
当发送完最后一个数据0xff后结束发送数据,拉高wr_n。
7.总结
-
所写的代码还不太符合Verilog的规范,需要完善;
-
可以参考下面的链接和正点原子《达芬奇之FPGA开发指南》的USB通信实验