Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Nanosecond delay to bitbang an FPGA

Hi all!

I'm using an nRF52832 with SDK 15.2 to bitbang an FPGA image into an ice40 Ultra FPGA by Lattice.

To do this i'm following the relative documentation of the FPGA that gives the directives to configure this ice40 Ultra.
(Documentation available here https://www.latticesemi.com/Products/FPGAandCPLD/iCE40Ultra . The necessary os in the document "iCE40 Programming and Configuration", in the paragraph "SPI Slave Configuration Process" )

In this documentation there is a pseudocode that I report here:

//
// iCE40 Configuration Pseudo-code
//
void Config_iCE40 (type, file)
{
//
// Open Hex File early to avoid clock delay later
//
file_pointer = fopen(file);// Open bin file
//
// Reset the iCE40 Device
//
Set_Port(SPI_SS_B, false);// Set SPI_SS_B low
Set_Port(CRESET, false);// Set CRESET low
Set_Port(SPI_CLK, true);// Set SPI_CLK high
nSec_Delay(200);// Delay 200 nsec
Set_Port(CRESET, true);// Set CRESET high
if (type == L1K or L4K)
uSec_Delay(800);// Delay 800 usec if L1K,L4K
else if (type == L8K)
uSec_Delay(1200);// Delay 1200 usec for L8K
Set_Port(SPI_SS_B, true);// Set SPI_SS_B high
Send_Clocks (8);// Send 8 clocks
//
// Send data from bin file
//
Send_File(file_pointer);// Send bin file
Send_Clocks (100);// Send 100 clocks
//
// Verify successful configuration
//
if (Get_Port(CDONE))
Return PASS;// PASS if CDONE is true
else
Return FAIL;// FAIL if CDONE is false
}
//
// Clock Generation 10MHz
//
void Send_Clocks(num_clocks)
{
for {i = 0; i < num_clocks; i++}
{
Set_Port(SPI_CLOCK, false);// Set SPI_CLK low
nSec_Delay(50);// Delay 50 nsec
iCE40 Programming and Configuration
26
Set_Port(SPI_CLOCK, true);// Set SPI_CLK high
nSec_Delay(50);// Delay 50 nsec
}
}
//
// Send Data from file
//
void Send_File(file_pointer)
{
byte = getc(file_pointer);// Read first byte from file
while (byte != EOF)
{
Send_Byte (byte);// Send data byte
byte = getc(file_pointer);// read next byte from file
}
}


As written in the documentation, the binary file has to be sended serially on the MOSI, most significant bit first, on falling edge of SPI Clock and without interruption (With the SPI clock between 1MHz and 25 MHz). 

To do that i thought to use nRF_delay functions but the minimum delay in this way is 1 us.

In order to configure this FPGA i should use a delay of maximum some ns instead. For exemple to have an SPI clock of 10MHz i need a delay of 50ns in the function sendclock to compose the falling and rising edge of my clock (and the same in the function that will send data).

How can I implement some kind of delay in my code?

Have anyone have dealt with this ice40 Ultra FPGA and know a smart way to configure the FPGA through an nRF52832?


Thanks to those who light 'and will respond.

Parents
  • Hi,

    I don't have any experience with exactly this (hopefully someone else on the forum has) but, here is some thoughts from my end, the maximum toggling frequency of the GPIO peripheral in the most ideal case would be 16 MHz, which would give you a bitbanged SCLK at 8 MHz. Regarding the delay, you can use the Timer peripheral + PPI + GPIOTE to schedule task and events. See the GPIOTE example,

    regards

    Jared 

  • Hi Jared, thanks for response.

    So are you suggesting me that i could not use the delay and just let the pin switch at the maximum frequency allowed?

    For what regards the using of the timers + ppi, how you suggest to implement the delay? I know how to use that example linked to generate an interrupt, but how can I make possible to remain in that interrupt for the time needed?

Reply Children
  • Hi,

    FedericoDeSario said:
    So are you suggesting me that i could not use the delay and just let the pin switch at the maximum frequency allowed?
    As written in the documentation, the binary file has to be sended serially on the MOSI, most significant bit first, on falling edge of SPI Clock and without interruption (With the SPI clock between 1MHz and 25 MHz). 

    It wasn't clear from this description what the motivation of using the delay function was. Please elaborate on that point,

    FedericoDeSario said:
    For what regards the using of the timers + ppi, how you suggest to implement the delay? I know how to use that example linked to generate an interrupt, but how can I make possible to remain in that interrupt for the time needed?

    PPI isn't a must you can use the nrfx Timer driver and schedule the bitbang in the callback handler of the Timer by using a flag. 

    void timer_callbackhandler()
    {
        flag = 1;
    
    }
    
    int main(void)
    {
        flag = 0;
    
        start_timer(Timer_instance);
        
        while(!flag)
        {
        
        }
        
        flag = 0;
        
        //dostuff
        
    
    }
    
    
    
    

    regards

    Jared

  •  

    It wasn't clear from this description what the motivation of using the delay function was. Please elaborate on that point,

    My idea was to clear SCLK and in the same time to write the data on the MOSI.
    Than wait (for exemple) 50 ns and then set the SCLK (that for the fpga means sampling the MOSI in that instant).
    Finally wait again 50 ns and restart this procedure until the end of the fpga image. In this way i should have a SCLK of 10MHz (100ns of period) that is in the range written in the FPGA documentation (they said that a continuous clock with frequency between 1 MHz and 25MHz is needed).

Related