Host to FPGA basics

Questions and discussions about the Xillybus IP core and drivers

Host to FPGA basics

Postby Guest »

Overall Objective:
Big picture of what we are trying to do is send data packets in bursts from the host to the FPGA. The FPGA then serializes out the data it receives.

Problem: (Note: correctly means it corresponds to a predefined sequence as defined by an array of values)
The FPGA correctly serializes out a word, skips a random (no patterns and also doesn't repeat) amount of bits in a predefined sequence that was sent to the FPGA, then the FPGA correctly serializes out another word. The issue is that the FPGA is skipping a lot of data. We think it might be due to PLL (Phase-Locked Loop) within the FPGA, but we are unsure and debugging has proved difficult because of the interaction the FPGA has with Linux.

Details:
We believe that we are correctly pushing data over the DMA. The following is our code to do so. What the code does is first the code takes a 32 bit unsigned word and fills it with bit values as defined by a hardcoded array. Then the code takes this 32 bit word and pushes into a buffer which is 512 x 32 (the 32 is for each of the 32 bit words. In other words 512 x word). The code is looped to continually fill the 32 bit words from the hardcoded array which then fills the buffer (512x32). When the buffer is full, we signal this buffer (or packet) to be sent to across the DMA by Xillybus. From there, the process repeats by still cycling through the array to fill the 32 bit words to fill the buffer (512x32) to be sent across the DMA. The following is a code snippet:
(Note: This code is based upon what we read in the documentation. We do not think we need to flush every time after writing to the DMA, but we have it in there for now just in case it was an issue)
Code: Select all


#define BUFFER_SIZE 0x200
#define NUM_BITS 500

int main(){
   uint32_t pn9[NUM_BITS] ={
         0,0,0,0,0,0,0,0,1,0,
         0,0,0,1,0,0,0,1,1,0,
         0,0,0,1,0,0,1,1,1,0,
         0,1,0,1,0,1,0,1,1,0,
         0,0,0,1,1,0,1,1,1,1,
         0,1,0,0,1,1,0,1,1,1,
         0,0,1,0,0,0,1,0,1,0,
         0,0,0,1,0,1,0,1,1,0,
         1,0,0,1,1,1,1,1,1,0,
         1,1,0,0,1,0,0,1,0,0,
         1,0,1,1,0,1,1,1,1,1,
         1,0,0,1,0,0,1,1,0,1,
         0,1,0,0,1,1,0,0,1,1,
         0,0,0,0,0,0,0,1,1,0,
         0,0,1,1,0,0,1,0,1,0,
         0,0,1,1,0,1,0,0,1,0,
         1,1,1,1,1,1,1,0,1,0,
         0,0,1,0,1,1,0,0,0,1,
         1,1,0,1,0,1,1,0,0,1,
         0,1,1,0,0,1,1,1,1,0,
         0,0,1,1,1,1,1,0,1,1,
         1,0,1,0,0,0,0,0,1,1,
         0,1,0,1,1,0,1,1,0,1,
         1,1,0,1,1,0,0,0,0,0,
         1,0,1,1,0,1,0,1,1,1,
         1,1,0,1,0,1,0,1,0,1,
         0,0,0,0,0,0,1,0,1,0,
         0,1,0,1,0,1,1,1,1,0,
         0,1,0,1,1,1,0,1,1,1,
         0,0,0,0,0,0,1,1,1,0,
         0,1,1,1,0,1,0,0,1,0,
         0,1,1,1,1,0,1,0,1,1,
         1,0,1,0,1,0,0,0,1,0,
         0,1,0,0,0,0,1,1,0,0,
         1,1,1,0,0,0,0,1,0,1,
         1,1,1,0,1,1,0,1,1,0,
         0,1,1,0,1,0,0,0,0,1,
         1,1,0,1,1,1,1,0,0,0,
         0,1,1,1,1,1,1,1,1,1,
         0,0,0,0,0,1,1,1,1,0,
         1,1,1,1,1,0,0,0,1,0,
         1,1,1,0,0,1,1,0,0,1,
         0,0,0,0,0,1,0,0,1,0,
         1,0,0,1,1,1,0,1,1,0,
         1,0,0,0,1,1,1,1,0,0,
         1,1,1,1,1,0,0,1,1,0,
         1,1,0,0,0,1,0,1,0,1,
         0,0,1,0,0,0,1,1,1,0,
         0,0,1,1,0,1,1,0,1,0,
         1,0,1,1,1,0,0,0,1,0
         };
   
   
   uint32_t idxpn9 = 0;
   uint32_t FIFO_out = open("/dev/xillybus_write_32", O_WRONLY);//Opens access to the DMA
   uint32_t write_buffer_ptr = 0x000;//points to the address the the buffer. Initialized at the beginning   
   uint32_t write_buffer[BUFFER_SIZE] = {0};//creates the size of the buffer
   uint32_t buffer32 = 0;//deals with creating the 32 bit packets
   uint32_t shifter = 0;//deals with creating the 32 bit packets

   while(1){
      
      //32bit buffer
      buffer32 += pn9[idxpn9] << 31 - shifter;
      ++idxpn9;
      ++shifter;
      if (shifter == 32){
         shifter = 0;
         write_buffer[write_buffer_ptr] = buffer32;
         buffer32 = 0;
         ++write_buffer_ptr;
      }
      if (idxpn9 == NUM_BITS){
         idxpn9 = 0;
      }

      if (write_buffer_ptr >= BUFFER_SIZE){         
         
         int32_t error;
         while (1){ //writing
            //error = write(FIFO_out, &write_buffer[0], 0x1C14);
            error = write(FIFO_out, &write_buffer[0], sizeof(write_buffer));
            //returns number of bytes written
            //cout << "bytes written: " << error << endl;
            if ((error < 0) && (errno == EINTR)) {
               continue;
               //interrupted try again
               
               cout << "write error: " << error;
               //close(FIFO_out);
               //return -1;
            }
            if (error < 0){
               perror("write() failed");
               break;
            }
            if (error == 0){
               fprintf(stderr, "Reached write EOF (?!) \n");
               break;
            }
            //do something with "error" bytes of data
            //std::cout << "Error=" << error << std::endl;
      
         }
         while (1){ //flushing
            error = write(FIFO_out, NULL, 0);
            if ((error < 0) && (errno == EINTR)) {
               continue;
               //interrupted try again   
            }
            if (error < 0){
               perror("flushing failed");
               break;
            }
            break;
            //Flush successful
         }

         write_buffer_ptr = 0x000;
      }

   
   }
   close(FIFO_out);

   exit(-1);
}


Now, by what we can observe, our packets (or buffers) are being correctly sent to the DMA with the correct data. However, we find an issue with serializing out the data on the FPGA side. On the FPGA we have a 512x32 FIFO which is being given the data from the Xillybus/DMA wire (user_data_write_32 I think it's called. The important thing is that the FIFO has a 32 bit input wire). At the other end of the FIFO we have a clock (different from the input clock) to take data off of the FIFO. Each time we take data off of the FIFO, we take off a 32 bit word (because it is a 512x32 FIFO) and have a simple state machine to serialize the 32 bit word. After serialization, another piece of data or 32 bit word is taken off of the FIFO.
The issue we encounter is after we serialize the 32 bit word which correctly corresponds to a sequence in our hardcoded array. On the next 32 bit word that is serialized we have a 32 bit word which correctly corresponds to a sequence in our hardcoded array. The problem happens between each 32 bit word serializations. Although the first 32 bit word correctly corresponds to a sequence in the array and the next 32 bit word correctly corresponds to a sequence in the array, the issue we have is that a random number of bits were skipped in the array's sequence (it is a completely random number and different for every iteration. There does not appear to be any pattern with the number of bits that get skipped in the sequence). I would think that because 512x32 buffer packets are being sent to the FIFO at once, we would at least have the correct bit sequence for at least 512 words. In conclusion a random number of bits is skipped in the array sequence after each time a correct word (or 32 bits that corresponds to the array sequence) is serialized on the FPGA. I don't know if I am interfacing wrong with Xillybus, or if there is a bug in Xillybus, or if there is a known issue with proper work arounds (such as if it had to deal with the PLL of the FIFO or something else).

Thanks for all help
Guest
 

Re: Host to FPGA basics

Postby support »

Hello,

It seems like you're doing it right in general. Odds are that the data arrives correctly to the FIFO in the FPGA, but something goes wrong on the way to the serializer. Which makes me focus on
Guest wrote:At the other end of the FIFO we have a clock (different from the input clock) to take data off of the FIFO.

You should replace the FIFO in the demo bundle with a dual-clock one ("asynchronous FIFO") to cross clock domains. Feed the dual-clock FIFO with bus_clk as wr_clk and the one you're using in your serializing logic as rd_clk. The FIFO's internal logic makes sure that the synchronization between clocks is done properly.

If you've already done this, my next guess would be that the rd_en signal to the FIFO is wrong, so it pulls data when it shouldn't. Or something like that.

In short, I suggest putting the focus on the logic that fetches data from the FIFO.

Regards,
Eli
support
 
Posts: 802
Joined:


Return to Xillybus

cron