- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I recently developing an FPGA program that will be used to measure something. IO inputs will be stored in the FPGA SRAM and later transferred with over USB with the FTDI chip to be processed on a PC. With testing only the USB part of the program I noticed that some bytes are missing (on regular base each 128 bytes there is one missing, and on rare occurrence there are several missing). To test this I implemented a counter in VHDL code generating bytes to transmit to the PC. Part of the VHDL code :elsif (State_WR = '1' ) then
STM_RD<= rd_idle;
--# Start sequence of setting flags to write to the FTDI
case STM_WR is
--## WRITE IDLE : prepare flags of FTDI and RAM
when wr_idle =>
FTDI_OE_n<='1';
--If FTDI_TXE_n is 0, then FTDI will allow data to be transmitted
if(FTDI_TXE_n ='1') then
STM_WR <= do_WR;
end if;
FTDI_WR_n <= '1';
--## WRITE START: start write command to FTDI
when do_WR =>
FTDI_WR_n <= '0'; -- Enables the data byte on the D0...D7 pins to be written into the transmit FIFO buffer
STM_WR <= burst_write;
​
--## WRITE BURST: burst bytes to FTDI
when burst_write =>
-- If FTDI_TXE_n is asserted, FTDI does not want data anymore, so we pause XMIT:
if(FTDI_TXE_n = '0') then
STM_WR <= wr_pause;
FTDI_WR_n <= '1'; -- Disable write enable
else
counter <= counter+1;
--******************Output data*************
FTDI_Data<=std_logic_vector(to_unsigned(counter,8));
end if;
--# # PAUSE : FTDI chip needs a break...
when wr_pause =>
State_ReadyToWrite <='0';
if(FTDI_TXE_n = '1') then
State_ReadyToWrite <='1';
STM_WR <= burst_write;
FTDI_WR_n <= '0'; -- enable writing again
end if;
when others =>
end case;
C++ program (used functions): bool FT2232H::Initialize()
{
UCHAR mask = 0xff; // set all IOs to output
UCHAR mode = 0x00; // reset value of bitmode
//UCHAR bitMode;
UCHAR latencyTimer = 2; // default setting is 16
int deviceIndx=0; // Select first FTDI device
FT_STATUS ftStatus;
int readTimeout = 900; //
int writeTimeout =2000; //
// Obtain handle
ftStatus = FT_Open(deviceIndx, &ftHandle);
if (ftHandle == INVALID_HANDLE_VALUE)
cout<<"failed opening connection";
ftStatus = FT_SetBitMode(ftHandle, mask, mode);
Sleep(1000);
mode = 0x40; //Sync FIFO mode
ftStatus = FT_SetBitMode(ftHandle, mask, mode);
if (ftStatus == FT_OK)
{
ftStatus = FT_SetLatencyTimer(ftHandle, latencyTimer);
ftStatus = FT_SetUSBParameters(ftHandle,0x10000,0x10000);
ftStatus = FT_SetFlowControl(ftHandle,FT_FLOW_RTS_CTS,0,0);
ftStatus = FT_SetTimeouts(ftHandle,readTimeout,writeTimeout);
//ftStatus = FT_GetBitMode(ftHandle, &bitMode);
return true;
}
else
{
//TODO add recovery and feedback wheb ftStatus is not OK
return false;
}
}
bool FT2232H::Read(char *pRxBuf,int bufSize)
{
bool isReadDone= false;
DWORD bytesReceived;
FT_STATUS ftStatus;
char *pRxBufCur = pRxBuf;
int maxBufSize = bufSize>MAX_RXBUFF ? MAX_RXBUFF : bufSize; // limit bufsize
int currReceivedBytes=0;
int cyclesToRead=(int) bufSize/maxBufSize + 2;
int cyclesReaded=0;
Purge();
while(cyclesReaded<cyclesToRead){
Sleep(1);
cyclesReaded++;
// prevent to big bufsize on the end of the buffer
maxBufSize = ((bufSize - currReceivedBytes)> maxBufSize)? maxBufSize : bufSize- currReceivedBytes;
ftStatus = FT_Read(ftHandle,pRxBufCur,maxBufSize,&bytesReceived);
if(bytesReceived<maxBufSize)
break;
currReceivedBytes += bytesReceived;
pRxBufCur += maxBufSize; // set pointer further in buffer
if(currReceivedBytes >= bufSize){
break;
}
}
if(currReceivedBytes<bufSize && ftStatus== FT_OK)
{
std::cout<< "Reading failed due timeout: Received"<<std::endl;
}
else if (ftStatus != FT_OK)
{
std::cout<<"Reading failed"<<std::endl;
PrintError(ftStatus);
}
else
{
std::cout<<"Reading successfully: "<<currReceivedBytes<<" received." <<std::endl;
isReadDone= true;
}
return isReadDone? true : false;
}
void FT2232H::Purge()
{
FT_STATUS ftStatus;
ftStatus=FT_Purge(ftHandle,FT_PURGE_RX);
if(ftStatus!=FT_OK)
{
cout<<"READ BUF NOT PURGED"<<endl;
PrintError(ftStatus);
}
ftStatus=FT_Purge(ftHandle,FT_PURGE_TX);
if(ftStatus!=FT_OK)
{
cout<<"READ BUF NOT PURGED"<<endl;
PrintError(ftStatus);
}
}
The result of this read operation is : (counter = 8 bit counter) 0,2,3,4,............127,128,130,131,132,....,255,0,2,3,4,5,......,127,128,130,.........,224,226,227,......,255,0,2,3,4,5,......,12,120,.....127,128,130,131,.......255,.................... => missing one byte on 0->2 and 128->131 occurs on regular base => missing one or more than one byte like 120->120 and 224->226 occurs less frequent and irregular. Does have some one the same experience with the Sync FT245 mode of the FTDI 2232H chip ? Are there suggestions to solve this problem ? Thanks in Advance
Link Copied
3 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here are my notes for the FTDI devices;
http://www.ovro.caltech.edu/~dwh/correlator/pdf/ftdi.pdf and I've attached a loopback example program. There's one comment in there that may be relevant to your problem ...
/* Set flow control per AN130 - apparantly this stops the
* driver from dropping data.
*/
ftStatus = FT_SetFlowControl(ftHandle, FT_FLOW_RTS_CTS, 0, 0);
if (ftStatus != FT_OK) {
printf("Error: FT_SetFlowControl returned %d\n", (int)ftStatus);
return 1;
}
Ah, but I see you already have that line in your code. So perhaps your issue is with the interface logic. Look at the waveforms in the PDF I linked to. Use SignalTap II in your design to reproduce them. Perhaps you have an issue. Do you have a testbench that you have used to test your design? Cheers, Dave
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I found my problem.... I switched the input pins TXE and RXF of the FTDI in my FPGA program.
I didn't noticed the problem directly because I also inverted the signals TXE and RXF. Below the working code of my FTDI controller :library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FTDI_Controller is
port(
-- communication with software
State_WR : in std_logic; -- start writing
State_RD : in std_logic; -- start reading
State_DONE : out std_logic; -- finished with reading or writing
State_Accepted : in std_logic;
State_ReadyToRead : out std_logic;
State_ReadyToWrite : out std_logic; -- when FTDI is ready to write
D_ToWrite : in std_logic_vector(7 downto 0); -- data to write
D_Readed : out std_logic_vector(7 downto 0); -- data readed by interface
-- Connection to hardware FTDI (FT245 COnfiguration)
FTDI_RXF_n : in std_logic; -- When low -> there is Data availible in the fifo
FTDI_TXE_n : in std_logic; -- When low -> Data can be written into the fifo
FTDI_RD_n : out std_logic; -- When low (and RXF_n low)-> Data is clocked to D0..D7 to receive
FTDI_WR_n : out std_logic; -- When low (and TXF_n low)-> Data is written to transmit FIFO
FTDI_OE_n : out std_logic; -- Output enable -> Should be low one clock to drive data onto D0..D7
FTDI_Data : inout std_logic_vector(7 downto 0); -- Data vector
-- Other Connections:
CLK_FTDI : in std_logic ; -- 60 MHz clock driven by FDTI
Reset_n : in std_logic ; -- reset input
);
end FTDI_Controller;
architecture RTL of FTDI_Controller is
-- Create state machine cases
type T_STM_RD is (rd_idle, do_OE, do_RD, read_data,read_done);
type T_STM_WR is (wr_idle, do_WR, burst_write, wr_pause, slow_wr);
signal STM_RD : T_STM_RD;
signal STM_WR : T_STM_WR;
begin
--# EXECUTE EACH CLOCK PULS
process(CLK_FTDI,reset_n)
begin
if(Reset_n = '0') then
D_Readed <= (others => '0');
elsif (rising_edge(CLK_FTDI)) then
if (State_RD = '1' ) then
--# Start sequence of setting flags to read from the FTDI
STM_WR <= wr_idle;
State_ReadyToWrite <='0';
-- Evaluate the read STM.
case STM_RD is
--# # READ IDLE : initialize variables
when rd_idle =>
State_ReadyToRead <='0';
test_outC<='0';
FTDI_OE_n <= '1';
FTDI_RD_n <= '1';
FTDI_Data <= (others => 'Z');
D_Readed <= (others => '0');
-- If FTDI pulls RXF low then data is available. We need to do OE next.
if(FTDI_RXF_n = '0') then
STM_RD <= do_OE;
end if;
--## OUTPUT ENABLE : enable to start reading
when do_OE =>
-- Set output enable one clock pulse before reading command
FTDI_OE_n <= '0';
STM_RD <= do_RD;
--## READ FLAG : Pull RD_n low and go to read state
when do_RD =>
FTDI_RD_n <= '0';
State_ReadyToRead <='1';
STM_RD <= read_data;
--## READING : read until FTDI stops
when read_data =>
-- Finish read operation ?
if(FTDI_RXF_n = '1') then
-- reset FT245 signals
FTDI_OE_n <= '1';
FTDI_RD_n <= '1';
STM_RD <= read_done;
State_DONE<='1';
else
-- *** Here data is comming @ 60MHz ***
D_Readed <= FTDI_Data;
end if;
when read_done =>
State_ReadyToRead <='0';
test_outC<='1';
if(State_Accepted='1') then
State_DONE <='0';
STM_RD<= rd_idle;
else
State_DONE<='1';
end if;
when others =>
end case;
elsif (State_WR = '1' ) then
STM_RD<= rd_idle;
--# Start sequence of setting flags to write to the FTDI
case STM_WR is
--## WRITE IDLE : prepare flags of FTDI and RAM
when wr_idle =>
FTDI_OE_n<='1';
FTDI_Data <= (others => 'Z');
--If FTDI_TXE_n is 0, then FTDI will allow data to be transmitted
if(FTDI_TXE_n ='0') then
STM_WR <= do_WR;
end if;
FTDI_WR_n <= '1';
--## WRITE START: start write command to FTDI
when do_WR =>
FTDI_WR_n <= '0'; -- Enables the data byte on the D0...D7 pins to be written into the transmit FIFO buffer
STM_WR <= burst_write;
when burst_write =>
-- If FTDI_TXE_n is asserted, FTDI does not want data anymore, so we pause XMIT:
if(FTDI_TXE_n ='1') then
STM_WR <= wr_pause;
FTDI_WR_n <= '1'; -- Disable write enable
else
FTDI_Data <= D_ToWrite;
end if;
--# # PAUSE : FTDI chip needs a break...
when wr_pause =>
State_ReadyToWrite <='0';
if(FTDI_TXE_n ='0') then
State_ReadyToWrite <='1';
STM_WR <= burst_write;
FTDI_WR_n <= '0'; -- enable writing again
FTDI_Data <= (others => 'Z');
end if;
when others =>
end case;
else
STM_WR <= wr_idle;
STM_RD <= rd_idle;
-- disable FTDI actions
FTDI_WR_n <= '1';
FTDI_OE_n <= '1';
FTDI_RD_n <= '1';
State_ReadyToWrite <='0';
State_ReadyToRead <='0';
State_DONE <='0';
D_Readed<=(others=>'0');
end if;
end if;
end process;
end RTL;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, I am Bharat
I am using FPGA (1-ADC 2314 2- FPGA (spartan-6) 3- FTDI 2232 4- LabVIEW), FTDI 2232 module and LabVIEW for my project. My first aim is to establish simple byte reading from my board (ADC) As you have made FTDI controller, I would like to have some inputs from your side. Please help for following queries. I read FTDI datasheet, what I understood is: --it might not be possible to transmit single byte transfer using FTDI 2232 module (minimum - 64 bytes). is it correct ? --if possible, pl. share your complete code. (might be asking too much then sorry ) ---What is the purpose of C codes you are referring above ? thanks & best regards Bharat
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page