Async busses in XC

Technical questions regarding the XTC tools and programming with XMOS.
Post Reply
jensk_dk
Junior Member
Posts: 4
Joined: Mon Mar 01, 2010 8:53 pm

Async busses in XC

Post by jensk_dk »

I can see how you can easily implement synchronous (clocked) busses in XC with an input pin controlling a timer, which in turn clocks an input port etc.

But how about async (timed) busses where the specification is timing diagrams and a set of max/min timings? The best I can think of is to set an input clock on the pin that makes the most sense (like R/W, CE or whatever, depending on the exact protocol) and then use timed waits to get to the point in the R/W sequence where address/data can be expected to be valid. I can also see some cases where external logic could assist in clocking the input port, for instance "clock this input pin when X and Y is high and Z has a front edge" but this defies the whole software defined silicon concept.

Forgive me if this is obvious, but I cannot see an elegant solution. Any solutions or suggestions, example code etc. would be much appreciated.


User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

There shouldn't be a need for additional extra components. I would avoid routing port signals to clock blocks and just rely on using fixed times taken from a Timer. See example below.

So if were the master of an interface that had the following signals:
nCS: Chip select
RnW: Read not Write
A[15:0]: Address bus
D[7:0]: Data (bidirectional)

Here's some functions I think should perform a write and a read.

If the XCore device were a slave, I would set up a conditional input on nCS. Is this what you were after?

Code: Select all

// The reference clock is 100MHz, so each delay count is 10ns
void delay (int delay_10ns)
{
  timer t;
  int time;
   
  t :> time; // Read the current time
  time += delay_10ns; // Add the delay
  t when timerafter (time) :> void; // Wait for the delay's duration before continuing.
                                    // void means time is discarded
}

void writeByte (int writeData, int addr)
{
  int dummy;

  addrPort <: addr; // set address
  RnWPort <: 0;  // Write
  dataPort <: writeData; // Output write data
  delay (5); // 50ns

  nCSPort <: 0; // Assert chip select
  delay (10); // 100ns delay

  nCSPort <: 1; // Assert chip select
  delay(5); // 50ns
  RnWPort <: 1;  // End Access

  // Turn data port output drive off by performing a dummy input
  dataPort :> dummy;  
}

int readByte (int addr)
{
  int readData;

  addrPort <: addr; // set address
  RnWPort <: 1;  // Read
  delay (5); // 50ns

  nCSPort <: 0; // Assert chip select
  delay (10); // 100ns delay

  dataPort :> readData;  
  nCSPort <: 1; // Assert chip select

  return (readData);
}
jensk_dk
Junior Member
Posts: 4
Joined: Mon Mar 01, 2010 8:53 pm

Post by jensk_dk »

Hi Woody
Thanks for the reply.

It is the PC Card (formerly PCMCIA) standard I have in mind. First I intend to use the XMos as a monitoring device, snooping on the communication between a master and a slave, but an actual host and slave implementation is also on the slate. A tricky part of the PC Card standard is that the slave can assert a WAIT# signal if it needs to extend the read or write cycles.

Considering monitoring of master/slave communication, I cannot generate signals, only monitor them by sampling or connecting to clock blocks. For sampling, I am concerned if the 10nS resolution is sufficient. If I connect an input signal to a clock block I do realize that the clock will not run at >100MHz, but will the sampling/triggering be at 100MHz intervals or will an input pin immediately trigger a clock edge?

Does anyone have experience with monitoring async busses rather than being master/slave as I assume is a more normal use case?
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

You can route the nCS line into a 1 bit port and then use that to drive a clock block. Then connect the data port to be clocked off that clock block. That way when you perform an IN on the data port you'll get the data that was on the port on the +ve edge of nCS. Extending the nCS pulse by WAIT causes no problems to this.

If you need to fine tune the timings, you may want to look into using set_pad_delay(). This will allow you to move the sample point forwards or backwards by up to 12.5ns in 2.5ns steps from the +ve edge of nCS.
jensk_dk
Junior Member
Posts: 4
Joined: Mon Mar 01, 2010 8:53 pm

Post by jensk_dk »

Clocking on the address bus to CS/OE was exactly my thought.

Using your code example and the "Programming XC" manual I now have a simple async bus running with master on one core and slave on another. It is running on the simulator using the pin connect feature of the XDE. - thanks for the help!

I would like to make a bus monitor running on a third core, snooping on the communication between the master and slave, but I cannot get connection of three pins working in the simulator. Any reason why this should not be theoretically possible? Time to invest in a dev board, I guess :)
peter
XCore Addict
Posts: 230
Joined: Wed Mar 10, 2010 12:46 pm

Post by peter »

Connecting another port to monitor this bus should be possible. I have created a test case here where I drive on 1C and monitor that on ports 1A and 1B. It works fine as long as I've added two connections in the pins section of the XDE. C->A and C->B.

There should be no reason why this doesn't work, and no limit to the number of ports monitoring other ones. However, it does not currently support a bus-type system where multiple ports are connected and each one wants to drive at different times.
jensk_dk
Junior Member
Posts: 4
Joined: Mon Mar 01, 2010 8:53 pm

Post by jensk_dk »

Hi Peter

I tried something similar to what you suggest, expect it was between three cores. I just found half an hour to try it out again but I still cannot make it work reliably.

It's as if the pins that can be driven from more than one core (the data pins of an async bus in my example) does not work. I've seen it work but cannot make out exactly what to do/not to do to make it work. The pins that are driven from one place (address, RnW, OE in my example) seem to work realiably enough.

Anyone else with experience in this?
Post Reply