Is it possible to share Clock Block between to interfaces?

Technical questions regarding the XTC tools and programming with XMOS.
Vlad
Junior Member
Posts: 6
Joined: Wed Sep 04, 2013 1:45 pm

Is it possible to share Clock Block between to interfaces?

Post by Vlad »

Hi friends,

I faced with a problem of insufficient number of clock blocks in my design.
I'm using XS1-L8A-64-LQ64 populated on our custom board (there are 6 clock
blocks, but as far as I understood, just 5 of them are available for user).

So, I have a few interfaces there which require clock block, four of them
are already in use, but I need 2 more for SPI interface to get access to flash
and some other SPI devices.

My question is - is there any ability to share clock block between interfaces,
e.g. I disable I2S and use released clock blocks for SPI?

BTW, I found that flash fl_SPIPorts structure (for flash access) uses just 1 clock block,
but SPI master design uses 2 CLK BLK. What is the difference?

Thank you for any idea and answer!


User avatar
sethu_jangala
XCore Expert
Posts: 589
Joined: Wed Feb 29, 2012 10:03 am

Post by sethu_jangala »

You can do something like this:

Code: Select all

void processes() {
  // Configure clock block
  // configure port A to use clock block
  // configure port B to use clock block
  // start clock block
  par {
    process1();
    process2();
  }
}

int main() {
  par {
    on tile[0]: processes();
    ...
  }
  return 0;
}
Sethu.
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

Vlad wrote:I faced with a problem of insufficient number of clock blocks in my design.
I'm using XS1-L8A-64-LQ64 populated on our custom board (there are 6 clock
blocks, but as far as I understood, just 5 of them are available for user).
All six are available. Every port always is configured with a clock;
by default that is clkblk #0, a.k.a. REFCLK. There is nothing special
about that clkblk itself, but after a port is reset it defaults to that (and
it is also the clkblk used by the USB interface). You can change the
speed of clkblk 0 just fine, or drive it from an external source, as long
as you make sure every port using clock 0 is okay with that.
My question is - is there any ability to share clock block between interfaces,
e.g. I disable I2S and use released clock blocks for SPI?
That is fine. Easiest is to completely disable the ports you do not
currently need (which resets them, particularly they will go back
to using the refclk), and then init the "new" ports.
BTW, I found that flash fl_SPIPorts structure (for flash access) uses just 1 clock block,
but SPI master design uses 2 CLK BLK. What is the difference?
The design using one clkblk outputs that clock on a pin as the
free-running SPI clock, and configures the MOSI, MISO, CS ports
to use that same clock. It has to carefully use the port timers to
get everything synchronised just fine, and it has to run fast enough
so that you always have data ready for it.

The design using two clkblks runs the first at twice the speed of
the SPI. This clkblk is used for the SPI clock port. That port is
just a regular data port; you write e.g. 0x55555555 to it to
generate 16 clock ticks. The SPI clock will not transition unless
you write to the port, making it easier to get timing right, both
on the CPU and on the bus.

If you now use the same clkblk with the MOSI and MISO pins, you
will have to "double" the bits you write to MOSI, and halve what you
read from MISO. This can be done but requires quite some code
(and/or data space for tables). So instead there is a trick: you feed
the SPI clock back into another clkblk, and use _that_ clkblk to drive
the MOSI and MISO pins (you don't have to clock the CS pin, the SPI
clock is not free-running). Feeding it back from the port gives a delay
of a few system clocks (each 2ns usually), but you can still get a SPI
clock of 25MHz without much trouble.

Lastly, you can do it all without using any clkblks. This will be slow.
Vlad
Junior Member
Posts: 6
Joined: Wed Sep 04, 2013 1:45 pm

Post by Vlad »

Thank you segher, sethu for your quick and very helpful answers!

But the problem is still opened (
That is fine. Easiest is to completely disable the ports you do not
currently need (which resets them, particularly they will go back
to using the refclk), and then init the "new" ports.
I have 2 interfaces on different pins, for instance I can't define
global structure and map their on the same CLOCK BLOCKs for sharing
in future:

Code: Select all

i2s_master_t i2s_m =
{
    on tile[0]: XS1_CLKBLK_1,   // MCLK clock, 
    on tile[0]: XS1_CLKBLK_2,   // BCLK clock, 
    on tile[0]: XS1_PORT_1K,    // MCLK input,  PLL output
    on tile[0]: XS1_PORT_1F,    // BCLK output, J7-5
    on tile[0]: XS1_PORT_1L,    // LRCK output, J7-6
    on tile[0]: XS1_PORT_1G 
};

on tile[0]: spi_master_interface spi_if =
{
    on tile[0]:XS1_CLKBLK_1,   // ERROR: it's already declared
    on tile[0]:XS1_CLKBLK_2,   // ERROR: it's already declared
    on tile[0]:XS1_PORT_1D,
    on tile[0]:XS1_PORT_1C,
    on tile[0]:XS1_PORT_1A
};

Also, if I define structure for both interfaces without clock blocks
and try to implement clock blocks directly during port initialization
it's also mistake in code:

Code: Select all

typedef struct spi_master_interface
{
    //clock blk1;
    //clock blk2;
    out buffered port:8 mosi;
    out buffered port:8 sclk;
    in buffered port:8 miso;
} spi_master_interface;

....

void spi_master_init(spi_master_interface &spi_if, int spi_clock_div)
{
    clock blk1 =  XS1_CLKBLK_1;// ERROR: local variable `blk1' has type clock
    clock blk2 =  XS1_CLKBLK_2;// ERROR: local variable `blk2' has type clock
    
    // configure ports and clock blocks
    configure_clock_rate(blk1, 100, spi_clock_div); //error: incompatible type for argument 1 of `__builtin_stop_clock'
   .... 

So, maybe I do it in wrong way, please advise
Vlad
Junior Member
Posts: 6
Joined: Wed Sep 04, 2013 1:45 pm

Post by Vlad »

Pardon, it was my fault. Clock variable must be declared just as global.

Cheers
User avatar
infiniteimprobability
XCore Legend
Posts: 1126
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

It's an old thread but thought it was worth adding a link to this Q&A showing how to do this with the latest language features:

http://www.xcore.com/questions/3238/how ... rent-cores