Question

Hello I am developing simple DSO and I have problem with FT245 sync FIFO. Reading from FT245 works normally when I read 4byte acknowledges, but when I want to retrieve sampled data it returns zero bytes (meaning ftdi_read_data returns 0, consecutive reads returns -84 then -32 (there is no documentation what these codes means)).

Function for readig:

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

Code where reading happens:

Part which works (reading acknowledge):

//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";
    }
}

Part which doesn't work:

//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";
    }
}

Screenchots from chipscope from working read: enter image description here

Screenshot from faulty read: enter image description here

As could be seen WR is put low in both situations two clocks after TXE goes low.

Part of VHDL code of working read:

        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;

Part of faulty read:

        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;

And there's code of my ft245 controller responsible for reading (writing from FPGA point of view):

        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;

And there is listing of program output:

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
...

From my point of view everything in FPGA is OK (according to chipscope) and reading in program is also the same so I don't know why it works and then don't (I can successfully do more (tens) write/read cycles with 4byte acknowledge, but then it always stops at this faulty read)...

//Edit: When you set ridiculously large incoming buffer (more than 16000 bytes) then it suprisingly works. But still I don't understand why..

Was it helpful?

Solution 2

I kind of solved it by setting incoming buffer to 32768 bytes which is maximum byte count I would transfer.. It works well now, just having some unaligned bytes (off one byte) after every 506 bytes.. But that's probably some error in my FPGA design.

//Edit: Just for note, biggest problem is not timing (even if you violate 11ns hold timing it will work correctly, I only have 7ns setup for example) but making state machine aware of situation when input buffers are full ant TXE goes high and correctly continue in transfer when TXE goes back low.

OTHER TIPS

Chipscope only shows you the internals.

More things you ought to check:

  • Have you constrained the timing correctly on all the IO pins to the FTDI chip?
  • Are you sure (using a fast scope) that you have met every timing requirement at the pins of the FTDI chip?

You might find that the logic in your failing path is causing something to be out of spec.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top