0

您好,我正在开发简单的 DSO,但 FT245 同步 FIFO 有问题。当我读取 4 字节确认时,从 FT245 读取正常工作,但是当我想检索采样数据时,它返回零字节(意味着 ftdi_read_data 返回 0,连续读取返回 -84 然后 -32(没有文档说明这些代码的含义))。

读取函数:

int Ft245sync::read(unsigned char * buf)
{
    int res = ftdi_read_data(ftdic, buf, getReadChunkSize());
    std::cerr << "res rd: " << res << std::endl;
    return res; 
}

发生读取的代码:

有效的部分(阅读确认):

//send SET TRIGGER
recvbuf[0] = 0;
while(recvbuf[0] != DATA_OK)
{
    unsigned char buf3[10] = { SET_TRIGGER, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    if(ft245.write(buf3) <  0)
    {
        std::cerr << "Error writing data3\n";
    }
    if(ft245.read(recvbuf) < 0)
    {
        std::cerr << "Error receiving data\n";
    }
}

不起作用的部分:

//send START CAPTURE 
unsigned char buf5[10] = { START_CAPTURE, 0x05, 0, 0, 0, 0, 0, 0, 0, 0 };
if(ft245.write(buf5) <  0)
{
    std::cerr << "Error writing data5\n";
}
usleep(700);
std::cout << "Capture started\n";
for (int i = 0; i < 30; ++i) 
{
    if(ft245.read(recvbuf) < 0)
    {
        std::cerr << "Error reading data\n";
    }
}

来自工作读取的chipscope的屏幕截图: 在此处输入图像描述

错误读取的屏幕截图: 在此处输入图像描述

可以看出,在两种情况下,在 TXE 变低两个时钟后,WR 都被置低。

部分 VHDL 工作代码如下:

        when SEND_ACKNOWLEDGE0 =>
            if to_boolean(ft245busy) then
                state <= SEND_ACKNOWLEDGE0;
            else
                state <= SEND_ACKNOWLEDGE1;
            end if;
        when SEND_ACKNOWLEDGE1 =>
            ft245rw <= '1';
            responseCounter <= "000";
            ft245din <= "10000000";
            if (ft245wr = '0') then
                state <= SEND_ACKNOWLEDGE2;
                ft245strobe <= '0';
            else
                ft245strobe <= '1';
                state <= SEND_ACKNOWLEDGE1;
            end if;
        when SEND_ACKNOWLEDGE2 =>
            if (responseCounter < 1) then
                responseCounter <= (responseCounter + 1);
                ft245din <= "10000000";
                state <= SEND_ACKNOWLEDGE2;
            else
                ft245dataWaitIn <= '1';
                ft245rw <= '0';
                responseCounter <= "000";
                case command is
                    when "10101110" =>
                        state <= INIT0;
                    when "00010000" =>
                        state <= SET_VREF0;
                    when "00010001" =>
                        state <= SET_VLOG0;
                    when "00100000" =>
                        state <= SET_ATTENUATORS;
                    when "00100001" =>
                        state <= SET_COUPLINGS;
                    when "00110000" =>
                        state <= SET_DECIMATION;
                    when "00110001" =>
                        state <= SET_ANALOGTRIGGER;
                    when "00110010" =>
                        state <= SET_DIGITALTRIGGER;
                    when "01000000" =>
                        state <= START_CAPTURE;
                    when others =>
                        state <= IDLE;
                end case;
            end if;

部分错误读取:

        when DUMP_DATA_PREPFT =>
            if to_boolean(ft245busy) then
                state <= DUMP_DATA_PREPFT;
            else
                state <= DUMP_DATA0;
            end if;
        when DUMP_DATA0 =>
            adc1pd <= '1';
            adc2pd <= '1';
            ft245rw <= '1';
            bufferDataDirection <= '0';
            answerNumber <= "00";
            ft245din <= "01010000";
            if ((ft245wr = '0') and to_boolean(bufferReady)) then
                state <= DUMP_DATA1;
                ft245strobe <= '0';
            else
                ft245strobe <= '1';
                state <= DUMP_DATA0;
            end if;
        when DUMP_DATA1 =>
            ft245din <= "01010000";
            ft245dataWaitIn <= '0';
            answerNumber <= (answerNumber + 1);
            if (answerNumber = 3) then
                state <= DUMP_DATA2;
                bufferOutputInputReady <= '1';
            else
                state <= DUMP_DATA1;
            end if;

还有我的 ft245 控制器的代码负责读取(从 FPGA 的角度写入):

        when IDLE =>
            if (strobe = '1') then
                busy <= '1';
                if (rw = '1') then
                    state <= WRITE_PREP;
                else
                    state <= READ_PREP;
                end if;
            else
                busy <= '0';
                state <= IDLE;
            end if;
        when WRITE_PREP =>
            if (txe = '0') then
                state <= WRITE;
            else
                state <= WRITE_PREP;
            end if;
        when WRITE =>
            if ((txe = '0') and (not to_boolean(dataWaitIn))) then
                wr_int <= '0';
            else
                wr_int <= '1';
                state <= IDLE;
                busy <= '0';
            end if;

并且有程序输出列表:

res wr: 10
res rd: 4
res wr: 10
Capture started
res rd: 0
res rd: 0
res rd: -84
Error reading data
res rd: -32
Error reading data
res rd: -32
...

从我的角度来看,FPGA中的一切都很好(根据chipscope)并且在程序中读取也是一样的,所以我不知道它为什么会起作用然后不知道(我可以成功地完成更多(数十个)写入/读取周期4字节确认,但它总是在这个错误读取时停止)......

//编辑:当您设置非常大的传入缓冲区(超过 16000 字节)时,它会出人意料地工作。但我还是不明白为什么..

4

2 回答 2

1

Chipscope 仅向您展示内部结构。

您应该检查的更多内容:

  • 您是否正确限制了 FTDI 芯片的所有 IO 引脚上的时序?
  • 您确定(使用快速示波器)您已满足 FTDI 芯片引脚的所有时序要求吗?

您可能会发现失败路径中的逻辑导致某些内容超出规范。

于 2013-05-01T12:20:00.917 回答
1

我通过将传入缓冲区设置为 32768 字节来解决它,这是我将传输的最大字节数。它现在运行良好,只是在每 506 个字节后有一些未对齐的字节(关闭一个字节)。但这可能是我的一些错误FPGA设计。

//编辑:请注意,最大的问题不是时序(即使您违反了 11ns 保持时序,它也会正常工作,例如我只有 7ns 设置)而是让状态机知道输入缓冲区已满时的情况 ant TXE 变高并在 TXE 变回低电平时正确地继续传输。

于 2013-05-02T11:55:21.640 回答