给EagleSDR做了个USB 3.0的子卡,采用FT600方案,实物如下:
用FT600DataStreamerDemoApp测试,速度如下:
由于FT600是16bit的接口,如果用FT601的32bit接口,性能应该还会有大幅提升。
测试代码很简单,参考了网上大佬的例程
`timescale 1ns / 1ns
module FT600_stream
(
//PL时钟
input pl_clk, //PL端时钟
// 复位
input rst_n, //外部复位
output reg ft600_reset_n, //ft600复位
// FIFO interface
input ft600_clk,
inout [15:0] ft600_data,
inout [1:0] ft600_be,
input ft600_rxf_n,
input ft600_txe_n,
output ft600_oe_n,
output ft600_wr_n,
output ft600_rd_n
);
reg ft600_wakeup_reg;
//从host来,退出读操作
wire r_oob;
//从host来,退出写操作
wire w_oob;
// assign ft600_siwu_n = 1'b1; // pull-up
wire [15:0] rd_data;
wire [15:0] wr_data;
wire [1:0] be_rd;
reg [1:0] be_wr;
reg [2:0] ft600_state; //状态
localparam FT600_IDLE=0,
FT600_READ=1,
FT600_READ_ABORT=2,
FT600_WRITE=3,
FT600_WRITE_ABORT=4;
assign rd_data = ft600_data;
assign ft600_data = (ft600_state==FT600_WRITE || ft600_state==FT600_WRITE_ABORT) ? wr_data : 16'bz;
assign be_rd = ft600_be;
assign ft600_be = (ft600_state==FT600_WRITE || ft600_state==FT600_WRITE_ABORT) ? be_wr : 2'bz;// write data dir
reg [15:0] wr_cnt;
assign wr_data = 16'hffff - wr_cnt;
//写计数器
always @(posedge ft600_clk)
begin
if(!ft600_reset_n)begin
wr_cnt <= 16'd0;
end
else
if(!ft600_wr_n)
begin
wr_cnt <= wr_cnt + 1'b1;
end
end
//写信号
assign ft600_wr_n=!((ft600_state==FT600_WRITE || ft600_state==FT600_WRITE_ABORT) && !ft600_txe_n);
//读信号,读状态且有数据可读
assign ft600_rd_n=!((ft600_state==FT600_READ || ft600_state==FT600_READ_ABORT) && (!ft600_rxf_n));
//在空闲态或读状态,且有数据可读时,允许FT600控制数据线
assign ft600_oe_n=!((ft600_state==FT600_IDLE || ft600_state==FT600_READ || ft600_state==FT600_READ_ABORT) && !ft600_rxf_n);
//定时器
localparam DELAY_5MS_CNT=(5*100000-1);
reg[31:0] delay_timer;
//状态机
always @(posedge ft600_clk)begin
if(!ft600_reset_n)
begin
ft600_state <= FT600_IDLE;
end
else
begin
if (r_oob)
begin
be_wr<=2'b01;
delay_timer <= DELAY_5MS_CNT;
ft600_state<=FT600_WRITE_ABORT;
end
else if (w_oob)
begin
delay_timer <= DELAY_5MS_CNT;
ft600_state<=FT600_READ_ABORT;
end
else
begin
case(ft600_state)
FT600_IDLE:
begin
be_wr <= 2'b11;
if((!ft600_rxf_n))
ft600_state <= FT600_READ; //有数据可读
else if(!ft600_txe_n)
ft600_state <= FT600_WRITE; //可写入数据
else
ft600_state <= FT600_IDLE;
end
FT600_READ:
if (ft600_rxf_n)
ft600_state <= FT600_IDLE;
FT600_READ_ABORT:
if (delay_timer==32'b0)
ft600_state <= FT600_IDLE;
else
begin
delay_timer=delay_timer-1'b1;
end
FT600_WRITE:
if(ft600_txe_n)
ft600_state <= FT600_IDLE;
FT600_WRITE_ABORT:
if (delay_timer==32'b0)
ft600_state <= FT600_IDLE;
else
begin
delay_timer=delay_timer-1'b1;
end
endcase
end
end
end
//延时复位
localparam RST_CYCLE=100;
reg [19:0] rst_cnt;
always @(posedge pl_clk)
begin
if (!rst_n)
begin
ft600_reset_n<=0;
rst_cnt<=0;
end
else
begin
if (rst_cnt<RST_CYCLE)
rst_cnt<=rst_cnt+1;
else
begin
ft600_reset_n<=1;
end
end
end
endmodule