Altera_Forum
Honored Contributor
9 years agoConnecting OV9655 Camera to Cyclone II Board (Qsys/Nios)
Hi,
I'm a beginner at the FPGA domain, and would be grateful for any help. I have a Cyclone II EP2C35 board with SDRAM and DM9000A Ethernet controller. I want to connect a small OV9655 camera module, and to transmit a single frame over Ethernet - just as a self learning project. (I'm using Quartus 11) The camera has the same interface as other omnivision modules, which means 8-bit data (can use 10-bit mode but not in my setup), HSync, VSync and Pclk (pixel clock). It also has Xclk pin which is the input clock - I'm using 25[MHz] clock from a PLL. An I2C interface is used for configuring the camera, I've connected a different microcontroller to the I2C interface in order to conveniently configure it to QQVGA mode as defined here: https://github.com/mfauzi/stm32f4/blob/master/stm32f4%20discovery%20software%20examples/stm32f4xx_camera_example/project/ov9655_camera/src/dcmi_ov9655.c As for the FPGA/Nios system so far I have done this: - Built a qsys system which includes SDRAM controller, SGDMA (Stream-to-Memory), DC FIFO, and added interfaces for DM9000A and OV9655. The main clock input is 50[MHz]. https://s10.postimg.org/4gf4olb55/qsys1.png https://s3.postimg.org/5fsoauokj/qsys2.png - With the Nios II EDS IDE I've tested the DM9000A driver which is working fine - I'm succecfuly sending UDP packets over the net. Also writing and reading from the SDRAM works fine. - I'm Using the code for SGDMA from http://www.alterawiki.com/wiki/sgdma Now I'm trying to run the DMA transfer of 160x120 QQVGA frame (which at RGB565 mode is 120x160x2 bytes long, and over the 32-bit wide SDRAM memory is actually 160x120x2/4 = 9600 words ) The problem is that the data I'm getting inside the SDRAM after running the DMA descriptor seems malformed.. For example, I've attached the Signaltap output of the first bytes of a frame: https://s3.postimg.org/vtfba85yr/signaltap1.png As can be seen, it is supposed to be an alternating sequence of 0x80, 0xc3, 0x80, 0xc3 etc. (The camera is configured to Colorbar test mode) But when I'm checking the SDRAM memory at the debugger, I can see it read a sequence like: 0x80, 0xc3, 0x80, 0x80, 0x80, 0xc3 etc. The problem is probably somewhere along the OV9655->DCFIFO->SGDMA->SDRAM chain. I've put the DCFIFO because I thought that the use of 25[MHz] pixel clock along with the 50[MHz] SGDMA driven clock may cause problem to the stream, but not sure if this is correct. Attached the code for running for the SGDMA transfer: /* Open a SG-DMA for ST-->MM */ alt_sgdma_dev * transmit_DMA = alt_avalon_sgdma_open(SGDMA_ST_TO_MM_NAME);
alt_sgdma_descriptor *transmit_descriptors, *transmit_descriptors_copy;
alt_u32 return_code;
/**************************************************************
* Making sure the SG-DMAs were opened correctly *
************************************************************/
if(transmit_DMA == NULL)
{
printf("Could not open the transmit SG-DMA\n");
return 1;
}
/**************************************************************
* Allocating descriptor table space from main memory. *
* Pointers are passed by reference since they will be *
* modified by this function. *
************************************************************/
return_code = descriptor_allocation(&transmit_descriptors,
&transmit_descriptors_copy,
NUMBER_OF_BUFFERS);
if(return_code == 1)
{
printf("Allocating the descriptor memory failed... exiting\n");
return 1;
}
for (n=0; n< NUMBER_OF_BUFFERS; n++)
{
alt_avalon_sgdma_construct_stream_to_mem_desc(&transmit_descriptors, // descriptor
&transmit_descriptors, // next descriptor
(alt_u32 *)SDRAM_BASE + BUFFER_LENGTH*n, // write buffer location
(alt_u16)BUFFER_LENGTH, // length of the buffer
0); // writes are not to a fixed location
}
alt_dcache_flush_all();
/**************************************************************
* Register the ISRs that will get called when each (full) *
* transfer completes *
************************************************************/
alt_avalon_sgdma_register_callback(transmit_DMA,
&transmit_callback_function,
(ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK),
NULL);
/**************************************************************
* Starting both the transmit and receive transfers *
************************************************************/
printf("Starting up the SGDMA engines\n");
/* Prime the SGDMA engines with the descriptor lists (first one, it's a linked list) */
if(alt_avalon_sgdma_do_async_transfer(transmit_DMA, &transmit_descriptors) != 0)
//if(alt_avalon_sgdma_do_sync_transfer(transmit_DMA, &transmit_descriptors) != 0)
{
printf("Writing the head of the transmit descriptor list to the DMA failed\n");
return 1;
}
while(rx_done == 0) {}
printf("The transmit SGDMA has completed\n");
Any help will be much appreciated. Thanks, Ofir