Thought I would just put an example together..
So we have 3 tasks - they happen to be running on the same chip here, but in three different cores in parallel. Could just as easily be 3 different chips - makes no difference. Could also be any number of slaves, given the hardware constraints of driving signals that mon2 mentioned.
There is one master - has a port output and and synch out
Two slaves - port output and a synch in.
The synch out is looped backed to the synch inputs inside the simulator - ie. your clock wire in real life. I have chosen ports that come out on the STARTKIT so you can try this with wires and a scope/logic analyser.
Each task outputs 8, 9, 10... on a 4b port each time it sees a falling edge.
Each of the outputs is synchronised to the master strobe using a clock block driven by the synch line on a 1b port..
You can see on the waveform trace that things are pretty well aligned. There is a small lag for the slaves, but you could add a delay in the master or use a master that outputs nothing and a slave on the master startkit to compensate for this.
Just for educational purposes, I showed the 'core waiting' signal for each task. You can see when the processor is blocked waiting for something to happen. As soon as the falling edge comes, they all start together. Nice!
Also included is an extreme close up on a nanosecond scale.
Here is the code - you can see it's pretty simple. Also attached is IDE project.
Code: Select all
#include <xs1.h>
#define INITIAL_VALUE 0 //Port initial value
out port p_out_master = XS1_PORT_4E; //Master output
out port p_synch_master = XS1_PORT_1J; //Master sync out
clock clk_master = XS1_CLKBLK_1; //Master clock block
out port p_out_slave_0 = XS1_PORT_4C; //Slave output
in port p_synch_slave_0 = XS1_PORT_1F; //Slave sync in
clock clk_slave_0 = XS1_CLKBLK_2; //Slave clock block
out port p_out_slave_1 = XS1_PORT_4D; //Slave output
in port p_synch_slave_1 = XS1_PORT_1G; //Slave sync in
clock clk_slave_1 = XS1_CLKBLK_3; //Slave clock block
void master_gen(out port p_out, out port p_synch, clock clk){
configure_clock_src(clk, p_synch); //Clock block drives from synch port
configure_out_port(p_out, clk, INITIAL_VALUE); //Output clock by clockblock
start_clock(clk);
int count = 0x8;
for(int i=0; i<4; i++){
p_out <: count; //This will not block becuase we have a port buffer
delay_microseconds(1);
p_synch <: 1;
delay_microseconds(1);
p_synch <: 0; //Port output is triggered on falling edge
count++;
}
}
void slave_gen(out port p_out, in port p_synch, clock clk){
configure_clock_src(clk, p_synch); //Clock block drives from synch port
configure_out_port(p_out, clk, INITIAL_VALUE); //Output clock by clockblock
start_clock(clk);
int count = 0x8;
while(1){
p_out <: count; //This will block/only happen when a clock is received on synch
count++;
}
}
int main(void){
par{
master_gen(p_out_master, p_synch_master, clk_master);
slave_gen(p_out_slave_0, p_synch_slave_0, clk_slave_0);
slave_gen(p_out_slave_1, p_synch_slave_1, clk_slave_1);
}
return (0);
}