Hello,
the "XMOS Programming Guide" has a chapter "6.12 Deserializing input data using a port".
What I don't understand is why an output port is needed. Wouldn't I want to have an input port to use the external clock that belongs to the serial data? Also the clock of 25MHz for p_in normally would not be synchronous to the serial data.
Am I missing something?
Regards,
Martin H.
Deserializing input data using a port
-
- Member++
- Posts: 19
- Joined: Thu Oct 01, 2015 10:55 am
-
- Active Member
- Posts: 32
- Joined: Thu Sep 25, 2014 1:19 am
Hi Martin,
Which device is the data source (sender) and which one is the receiver, is a different issue to which one is the clock master.
The example in section 6.12 has serial data flowing in from an external device, into PORT_4A. PORT_1A is an from the XMOS device which, as you say, is generating the clock.
The example in section 6.13 - although more complex in that it's using a strobe - also shows how to configure a port to follow an external clock (PORT_1B in this case).
Note the numbers after _ denote the port width. You use 1-bit ports for clocks.
There is an example project here:
https://github.com/xcore/sc_i2s/tree/ma ... _slave/src showing how accept serial input timed by an external clock master (i.e. the XMOS device is the slave).
Which device is the data source (sender) and which one is the receiver, is a different issue to which one is the clock master.
The example in section 6.12 has serial data flowing in from an external device, into PORT_4A. PORT_1A is an from the XMOS device which, as you say, is generating the clock.
The example in section 6.13 - although more complex in that it's using a strobe - also shows how to configure a port to follow an external clock (PORT_1B in this case).
Note the numbers after _ denote the port width. You use 1-bit ports for clocks.
There is an example project here:
https://github.com/xcore/sc_i2s/tree/ma ... _slave/src showing how accept serial input timed by an external clock master (i.e. the XMOS device is the slave).
-
- Member++
- Posts: 19
- Joined: Thu Oct 01, 2015 10:55 am
Hi tuck1s,
thank you for taking care of this.
The example at 6.13 would suite me, if I could get it working.
I have got exactly 16 clock pulses accompanied be a ready-in signal, i.e. there are no more clock pulses while the ready-in signal is HIGH.
Both clock edges coincide with the data bits, none of the edges appears simultanously with any edge of the data signal.
So I tried to adapt the example at 6.13 to my needs, but the instruction
on tile[0] : in buffered port:16 pSerData = XS1_PORT_1H;
produced
"error: transfer width of 16 is not supported on a 1-bit port"
Also, no 'select' instruction has been used in the example to fetch the data. When would I do that?
In the description it is pointed out that "data is available for input until the ready-in
signal is high for the next two rising edges of the clock".
In my case there are no more than 16 clock pulses.
How could that case be handled?
Regards,
Martin H.
thank you for taking care of this.
The example at 6.13 would suite me, if I could get it working.
I have got exactly 16 clock pulses accompanied be a ready-in signal, i.e. there are no more clock pulses while the ready-in signal is HIGH.
Both clock edges coincide with the data bits, none of the edges appears simultanously with any edge of the data signal.
So I tried to adapt the example at 6.13 to my needs, but the instruction
on tile[0] : in buffered port:16 pSerData = XS1_PORT_1H;
produced
"error: transfer width of 16 is not supported on a 1-bit port"
Also, no 'select' instruction has been used in the example to fetch the data. When would I do that?
In the description it is pointed out that "data is available for input until the ready-in
signal is high for the next two rising edges of the clock".
In my case there are no more than 16 clock pulses.
How could that case be handled?
Regards,
Martin H.
-
- XCore Legend
- Posts: 1913
- Joined: Thu Jun 10, 2010 11:43 am
From AN10046:
The allowable sizes for the FIFO on XS1 devices are: 1, 4, 8 and 32.
https://www.xmos.com/published/an10046- ... ion=latest
Follow the example from 6.13 but change your FIFO size to 32 to oblige the compiler syntax. You should be able to retrieve your 16 bits of sampled input data and then adjust the FIFO contents to suit your project.
==========
Not sure due to lack of experience on this exact topic if 32 FIFO depth will work for your case since you have only 16 cycles of clock. That is, not deep enough to fill the FIFO.
Consider to shrink the buffered port FIFO value to 8 and the repeat the reading 2 times.
p_in :> data_in_A;
p_in :> data_in_B;
In theory, data_in_A and data_in_B should be the 16 bit contents of your external data stream.
The allowable sizes for the FIFO on XS1 devices are: 1, 4, 8 and 32.
https://www.xmos.com/published/an10046- ... ion=latest
Follow the example from 6.13 but change your FIFO size to 32 to oblige the compiler syntax. You should be able to retrieve your 16 bits of sampled input data and then adjust the FIFO contents to suit your project.
==========
Not sure due to lack of experience on this exact topic if 32 FIFO depth will work for your case since you have only 16 cycles of clock. That is, not deep enough to fill the FIFO.
Consider to shrink the buffered port FIFO value to 8 and the repeat the reading 2 times.
p_in :> data_in_A;
p_in :> data_in_B;
In theory, data_in_A and data_in_B should be the 16 bit contents of your external data stream.
-
- Member++
- Posts: 19
- Joined: Thu Oct 01, 2015 10:55 am
This information was very helpful.
I have tested both versions. They both provide a useful result.
32-bit-width
When reading the port for the first time I would have expected to have zeroes in the upper 2 bytes. That was not the case. Instead the upper two bytes were identical to the lower 2 bytes even though I had set the breakpoint at the first instruction after the port-in-instruction. As the ready-in-signal is received periodically, I asume that this is the result of having detected the ready-in signal twice.
It seems that it is not necessary to have the port-in-instruction running in a 'select' as shown in the code below, providing the ready-in-signal does not coincide with the port-in-instruction. When I run it outside a select instruction the result was shifted.
8-bit-width
The following code will be chosen. Hopefully somebody can benefit from it:
configure_clock_src(clkSerData, p_clkSerData);
configure_in_port_strobed_slave(pSerData, p_Addr_Tx_Muster, clkSerData);
start_clock(clkSerData);
...
in the function:
configure_clock_src(clkSerData, p_clkSerData);
configure_in_port_strobed_slave(pSerData, p_Addr_Tx_Muster, clkSerData);
start_clock(clkSerData);
select {
case p_Addr_Tx_Muster when pinsneq(bTxMuster) :> void:
pSerData :> KeyJustRead; // LSB
pSerData :> Msb; // MSB
break;
...
}
The pitfall is the external serial data signal. It must come in with the least significant bit first, otherwise one has to modify the result accordingly.
Thank you very much for your help.
Regards,
Martin H.
An additional remark:
The code above works fine but it blocks the next event that comes about 0.5ms later.
I have no idea yet why this is happening.
I have tested both versions. They both provide a useful result.
32-bit-width
When reading the port for the first time I would have expected to have zeroes in the upper 2 bytes. That was not the case. Instead the upper two bytes were identical to the lower 2 bytes even though I had set the breakpoint at the first instruction after the port-in-instruction. As the ready-in-signal is received periodically, I asume that this is the result of having detected the ready-in signal twice.
It seems that it is not necessary to have the port-in-instruction running in a 'select' as shown in the code below, providing the ready-in-signal does not coincide with the port-in-instruction. When I run it outside a select instruction the result was shifted.
8-bit-width
The following code will be chosen. Hopefully somebody can benefit from it:
configure_clock_src(clkSerData, p_clkSerData);
configure_in_port_strobed_slave(pSerData, p_Addr_Tx_Muster, clkSerData);
start_clock(clkSerData);
...
in the function:
configure_clock_src(clkSerData, p_clkSerData);
configure_in_port_strobed_slave(pSerData, p_Addr_Tx_Muster, clkSerData);
start_clock(clkSerData);
select {
case p_Addr_Tx_Muster when pinsneq(bTxMuster) :> void:
pSerData :> KeyJustRead; // LSB
pSerData :> Msb; // MSB
break;
...
}
The pitfall is the external serial data signal. It must come in with the least significant bit first, otherwise one has to modify the result accordingly.
Thank you very much for your help.
Regards,
Martin H.
An additional remark:
The code above works fine but it blocks the next event that comes about 0.5ms later.
I have no idea yet why this is happening.
-
- Member++
- Posts: 19
- Joined: Thu Oct 01, 2015 10:55 am
The problem still exists. While the read serial data is correct, the next event within the same select instruction is not reached.
Is that behaviour correct? If not, what might be the reason?
I have put the code for reading serial data on a separate core and both cores do their job as expected.
If I add code to the same 'select' instruction to read serial data while an additional ready-in signal is valid, both case instructions are never reached.
Is it allowed to run the following 2 functions?
configure_in_port_strobed_slave(pSerData, p_Addr_Tx_Muster, clkSerData);
configure_in_port_strobed_slave(pSerData, p_Addr_Schw, clkSerData);
Or would I have to use different ports for pSerData and clkSerData in the second function?
How would I read serial data from different ready-in signals without wasting cores and ports?
Thank you.
Regards,
Martin H.
Is that behaviour correct? If not, what might be the reason?
I have put the code for reading serial data on a separate core and both cores do their job as expected.
If I add code to the same 'select' instruction to read serial data while an additional ready-in signal is valid, both case instructions are never reached.
Is it allowed to run the following 2 functions?
configure_in_port_strobed_slave(pSerData, p_Addr_Tx_Muster, clkSerData);
configure_in_port_strobed_slave(pSerData, p_Addr_Schw, clkSerData);
Or would I have to use different ports for pSerData and clkSerData in the second function?
How would I read serial data from different ready-in signals without wasting cores and ports?
Thank you.
Regards,
Martin H.