This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Access from TIVA to FPGA via EPI0

Hello,

We are using EPI0 in TIVA to write data to an FPGA.

The code for initialization is:

	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPI0);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOR);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOS);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOT);

	//
	// Enable pin PN2 for EPI0 EPI0S29
	//
	ROM_GPIOPinConfigure(GPIO_PN2_EPI0S29);
	GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_2);

	//
	// Enable pin PH1 for EPI0 EPI0S1
	//
	ROM_GPIOPinConfigure(GPIO_PH1_EPI0S1);
	GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_1);

	//
	// Enable pin PK3 for EPI0 EPI0S3
	//
	ROM_GPIOPinConfigure(GPIO_PK3_EPI0S3);
	GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_3);

	//
	// Enable pin PK2 for EPI0 EPI0S2
	//
	ROM_GPIOPinConfigure(GPIO_PK2_EPI0S2);
	GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_2);

	//
	// Enable pin PC5 for EPI0 EPI0S6
	//
	ROM_GPIOPinConfigure(GPIO_PC5_EPI0S6);
	GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_5);

	//
	// Enable pin PM1 for EPI0 EPI0S14
	//
	ROM_GPIOPinConfigure(GPIO_PM1_EPI0S14);
	GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_1);

	//
	// Enable pin PL1 for EPI0 EPI0S17
	//
	ROM_GPIOPinConfigure(GPIO_PL1_EPI0S17);
	GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_1);

	//
	// Enable pin PA6 for EPI0 EPI0S8
	//
	ROM_GPIOPinConfigure(GPIO_PA6_EPI0S8);
	GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_6);

	//
	// Enable pin PK7 for EPI0 EPI0S24
	//
	ROM_GPIOPinConfigure(GPIO_PK7_EPI0S24);
	GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_7);

	//
	// Enable pin PN3 for EPI0 EPI0S30
	//
	ROM_GPIOPinConfigure(GPIO_PN3_EPI0S30);
	GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_3);

	//
	// Enable pin PB2 for EPI0 EPI0S27
	//
	ROM_GPIOPinConfigure(GPIO_PB2_EPI0S27);
	GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_2);

	//
	// Enable pin PC4 for EPI0 EPI0S7
	//
	ROM_GPIOPinConfigure(GPIO_PC4_EPI0S7);
	GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_4);

	//
	// Enable pin PK6 for EPI0 EPI0S25
	//
	ROM_GPIOPinConfigure(GPIO_PK6_EPI0S25);
	GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_6);

	//
	// Enable pin PL4 for EPI0 EPI0S26
	//
	ROM_GPIOPinConfigure(GPIO_PL4_EPI0S26);
	GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_4);

	//
	// Enable pin PA7 for EPI0 EPI0S9
	//
	ROM_GPIOPinConfigure(GPIO_PA7_EPI0S9);
	GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_7);

	//
	// Enable pin PK0 for EPI0 EPI0S0
	//
	ROM_GPIOPinConfigure(GPIO_PK0_EPI0S0);
	GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_0);

	//
	// Enable pin PG0 for EPI0 EPI0S11
	//
	ROM_GPIOPinConfigure(GPIO_PG0_EPI0S11);
	GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_0);

	//
	// Enable pin PL0 for EPI0 EPI0S16
	//
	ROM_GPIOPinConfigure(GPIO_PL0_EPI0S16);
	GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_0);

	//
	// Enable pin PB3 for EPI0 EPI0S28
	//
	ROM_GPIOPinConfigure(GPIO_PB3_EPI0S28);
	GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_3);

	//
	// Enable pin PM2 for EPI0 EPI0S13
	//
	ROM_GPIOPinConfigure(GPIO_PM2_EPI0S13);
	GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_2);

	//
	// Enable pin PQ2 for EPI0 EPI0S22
	//
	ROM_GPIOPinConfigure(GPIO_PQ2_EPI0S22);
	GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_2);

	//
	// Enable pin PG1 for EPI0 EPI0S10
	//
	ROM_GPIOPinConfigure(GPIO_PG1_EPI0S10);
	GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_1);

	//
	// Enable pin PC6 for EPI0 EPI0S5
	//
	ROM_GPIOPinConfigure(GPIO_PC6_EPI0S5);
	GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_6);

	//
	// Enable pin PQ3 for EPI0 EPI0S23
	//
	ROM_GPIOPinConfigure(GPIO_PQ3_EPI0S23);
	GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_3);

	//
	// Enable pin PM0 for EPI0 EPI0S15
	//
	ROM_GPIOPinConfigure(GPIO_PM0_EPI0S15);
	GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_0);

	//
	// Enable pin PL2 for EPI0 EPI0S18
	//
	ROM_GPIOPinConfigure(GPIO_PL2_EPI0S18);
	GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_2);

	//
	// Enable pin PQ1 for EPI0 EPI0S21
	//
	ROM_GPIOPinConfigure(GPIO_PQ1_EPI0S21);
	GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_1);

	//
	// Enable pin PC7 for EPI0 EPI0S4
	//
	ROM_GPIOPinConfigure(GPIO_PC7_EPI0S4);
	GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_7);

	//
	// Enable pin PQ0 for EPI0 EPI0S20
	//
	ROM_GPIOPinConfigure(GPIO_PQ0_EPI0S20);
	GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_0);

	//
	// Enable pin PM3 for EPI0 EPI0S12
	//
	ROM_GPIOPinConfigure(GPIO_PM3_EPI0S12);
	GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_3);

	//
	// Enable pin PL3 for EPI0 EPI0S19
	//
	ROM_GPIOPinConfigure(GPIO_PL3_EPI0S19);
	GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_3);

The initialization of the EPI device is:

	//
	// Set the EPI divider.
	//
	EPIDividerSet(EPI0_BASE, 4);

	//
	// Select GENERAL mode.
	//
	EPIModeSet(EPI0_BASE, EPI_MODE_GENERAL);

	EPIConfigGPModeSet (EPI0_BASE, EPI_GPMODE_ASIZE_12 | EPI_GPMODE_DSIZE_16,0,0);

	//Sets the peripheral address space to 64 Kbytes, base address to 0xA0000000
	EPIAddressMapSet (EPI0_BASE, EPI_ADDR_PER_SIZE_64KB | EPI_ADDR_PER_BASE_A);

	// Wait for the EPI initialization to complete.
	//
	while(HWREG(EPI0_BASE + EPI_O_STAT) & EPI_STAT_INITSEQ) {};

Then we write 5 16bits words to the FPGA using this code:

HWREGH(0xA0000000) = 0x1111;
		HWREGH(0xA0000000+2) = 0x2222;
		HWREGH(0xA0000000+4) = 0x3333;
		HWREGH(0xA0000000+6) = 0x4444;
		HWREGH(0xA0000000+8) = 0x5555;

The attached doc contains 2 snapshots of the FPGA debugger.

You can see that framing signal sometimes wraps more than one writing.

We not using FIFO nor DMA.

Each chip select should wrap only one read\write.

Can we specify the chip select width ?

Can we specify the interval between 2 chip select ?

In case of read, what is the trigger to TIVA to start reading ?

The FPGA is not using TIVA's clock.

Regards,

Z.V

  • Hello Zvi,

    The waveform snapshots are missing? Also can you please mark them as to where each of the HWREGH transactions are coming.

    Regards

    Amit

  • Hi Amit,

    I will upload the snapsohts tomorrow morning.

    My FPGA does not use the TIVA's clock.

    In this case, should I use:  EPIDividerCSSet,  EPIDividerSet ?

    Can you tell if my EPI setup is correct for a "no clock"  scenario ?

    Regards,

    Z.V

  • Hello Zvi,

    There has to be some method for the FPGA to send the data back to the Tiva in the General Purpose mode. That is why the waveform is essential to understand the interface interaction between the two devices.

    It is fine not to use the clock (though using it may benefit timing), but you need to make sure that the data launch from the FPGA or data capture by the FPGA are then based of the Asynchronos FRAME-RD-WR signals.

    Regards

    Amit

  • 4846.Tiva.pdf

    Hi Amit,

    Attached a PDF with 2 snapshots.

    As you can see, the write signal and chip select signal (frame) are not synchonized with the period when address+data are on the bus.

    According to http://www.ti.com/lit/ds/symlink/tm4c1294ncpdt.pdf  (page 850), in general purpose mode the FRAME and WR should be '1' when data,address are put on the bus.

    This is not we are getting.

    Regards

    Z.V

  • Hi Amit,

    When we added SysCtlDelay (40) after each HWREGH we got a frame signal with constant width (5 FGPA clocks) for each writing.

    In this code I did not call to EPIDividerSet.

    In my opinion it's not an elegant solution.

    Can we control the width of the frame ?

    Regards,

    Z.V

  • Hello Zvi,

    I would need to re-create the signals on the test board to see what is happening. But from the initial analysis it seems that the WFIFO is being filled up due to CPU access and since the access is to the same CS, it would not de-assert the CS between transfers.

    Also we would need to check how GP mode is being set (please attach the latest code for EPI corresponding to the waveforms)

    Regards
    Amit
  • Hi Amit,

    To access FPGA we are using the general purpose mode:
    EPIModeSet(EPI0_BASE, EPI_MODE_GENERAL);

    We configure data, address size:
    EPIConfigGPModeSet (EPI0_BASE, EPI_GPMODE_ASIZE_12 | EPI_GPMODE_DSIZE_16,0,0);

    We set the base address of the FGPA registers:
    EPIAddressMapSet (EPI0_BASE, EPI_ADDR_PER_SIZE_64KB | EPI_ADDR_PER_BASE_A);

    Then we wait till EPI init complete:
    while(HWREG(EPI0_BASE + EPI_O_STAT) & EPI_STAT_INITSEQ) {};

    After this stage we are using :
    HWREGH(0xA0000000+4) for writing and data= HWREGH(0xA0000000+4) for reading.

    Are there any further APIs (or registers) relevant for General purpose mode ?

    It seems I can not control the width of the WR,RD,CS signals.

    Regards,
    Z.V
  • Hello Zvi,

    Thanks for the info. The Read and Write width cannot be controlled by a setting. They are dependent on the EPIDivder Settings. Also the relation between CS-WR and CS-RD are also based on the FRM and CYC bit settings of the General Purpose Mode.

    Regards
    Amit
  • Hello Zvi,

    Thanks for the code. I was able to replicate the issue and it turns out that the sampling clock is not enabled. Following should be the code

    EPIConfigGPModeSet (EPI0_BASE, EPI_GPMODE_CLKPIN | EPI_GPMODE_ASIZE_12 | EPI_GPMODE_DSIZE_16,0,0);

    You can still disable the clock at the pin by configuring the IO as a GPIO.

    The read is done on the next clock edge after the RD and FR signals are de-asserted so it should be 1 EPI clock cycle worth of delay from the external FPGA after the RD-FR signals are deasserted.

    Regards
    Amit
  • Hi Amit,

    After adding EPI_GPMODE_CLKPIN we can now read from FPGA and write to FPGA.

    But it seems there must be (at least)  1usec delay between 2 reads , 1 read and then 1 write, 2 writes.

    Without the delay it does not work.

    Regards,

    Z.V

  • Hello Zvi,

    I would disagree. I checked the wavforms and access with less than 1us are possible, unless the FPGA externally takes time for address-data decoding and updating a location before accepting the next data payload.

    Regards
    Amit
  • Hi Amit,

    Currently we managed to read\write with 1usec delay.

    Our FPGA is not using the TIVA's clock.

    Do you think this is the cause to the problem (that we must use a delay) ?

    Best regards,

    Z.V

  • Hello Zvi

    In the FPGA logic how much time does the logic require to process a back to back operation?

    Regards
    Amit