configure_in_port_strobed_master is not reading data correctly

Technical questions regarding the XTC tools and programming with XMOS.
JohnRed
Junior Member
Posts: 5
Joined: Wed Oct 31, 2018 6:25 pm

configure_in_port_strobed_master is not reading data correctly

Post by JohnRed »

I am implementing a 16bit wide interface reading from an external FIFO but finding that the data read from the ram is incorrect and in particular the first word of data is lost.
Either I have miss configured the interface or miss understood how the configure_in_port_strobed_master function works. Can anyone help?

Data is added to the FIFO in bursts of 4 16 bit words (this happens at high speed so that by the time the XMOS processor has responded to the first word all four 16 bit words have been written).

Once there is data in the FIFO the p_fifo_data_ready line is driven high by the FIFO and this which is trapped by the select case.
The p_debug line is toggled as each of the 4 words are transferred into the processor.
As the p_data_bus is configured using configure_in_port_strobed_master, the p_rd_req line is driven by the XMOS and I would expect that data would be read into the XMOS on the next rising clock edge, BUT looking at the attached scope trace the p_debug line shows that the XMOS is reading data in at incorrect and inconsistent times. I have added blue vertical lines where I would expect the XMOS to read the data and would expect the yellow trace to toggle just after the blue lines, but that is not what happens.

Code: Select all


on tile[0] : port p_debug   = XS1_PORT_1O;
in port     p_fifo_data_ready  = on tile[0]:XS1_PORT_1F;  // goes high to indicate there is data in the FIFO
in buffered port:16     p_data_bus    = on tile[0]:XS1_PORT_16A;  // 16bit data bus from FIFO
out port    p_rd_req      = on tile[0]:XS1_PORT_1N; // drive port high to read data from FIFO
on tile[0] : out port p_rd_clk = XS1_PORT_1E;
on tile[0] : clock      rd_clk = XS1_CLKBLK_4;

main ()
{
    unsigned short temp_data_input[256];
    timer tmr;
    unsigned t, timeout;
    configure_clock_rate (rd_clk , 100, 10);    // 100/10 = 10 MHz
    configure_port_clock_output(p_rd_clk, rd_clk );
    configure_in_port(p_fifo_data_ready, rd_clk); // read fifo_data_ready on clk edge
    configure_in_port_strobed_master(p_data_bus, p_rd_req, rd_clk); // Drive rd_req high to read data
    start_clock (rd_clk);
    clearbuf(p_data_bus);
    p_debug <: 0;
    
     while(TRUE)
    {
        select 
        {
            case  p_fifo_data_ready when pinsneq(0) :> f: // wait for ready data when data is ready
                p_debug <: 1;
                p_data_bus :> temp_data_input[0];  // read 16 bit data
                p_debug <: 0;
                p_data_bus :> temp_data_input[1];  // read 16 bit data
                p_debug <: 1;
                p_data_bus :> temp_data_input[2];  // read 16 bit data
                p_debug <: 0;
                p_data_bus :> temp_data_input[3] ;  // read 16 bit data
                p_debug <: 1;
                tmr :> t;
                timeout = t + 20; // timeout in 200ns
                p_debug <: 0;
                break;
         }
    }
 }  
The tmr, and timeout lines have no effect in this version and could be removed.


The scope trace below shows the following signals:
Ch1 p_debug
ChA p_rd_clk
ChB p_fifo_data_ready
Ch2 p_rd_req

Image
You do not have the required permissions to view the files attached to this post.


User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am

Post by mon2 »

Hi. A few quick comments:

1) your port width is 16 bits so you must use a TRANSFER WIDTH of 32 for this project. That is, once the port condition is TRUE; the XMOS CPU will autonomously read in 2 x 16 bits of data and will do so using 2 clock cycles after the port condition is met. The XMOS port structure only allows for TRANSFER WIDTHS of 1, 4, 8 or 32 bits. See Section 4 of the attached document for more details.

For this reason use:

Code: Select all

in buffered port:32     p_data_bus    = on tile[0]:XS1_PORT_16A;  // 2 x 16bit data bus from FIFO
2) Believe the following may work for your needs (not tested):

Code: Select all

on tile[0] : port p_debug   = XS1_PORT_1O;
in port     p_fifo_data_ready  = on tile[0]:XS1_PORT_1F;  // goes high to indicate there is data in the FIFO
in buffered port:32     p_data_bus    = on tile[0]:XS1_PORT_16A;  // 2 x 16bit data bus from FIFO
out port    p_rd_req      = on tile[0]:XS1_PORT_1N; // drive port high to read data from FIFO
on tile[0] : out port p_rd_clk = XS1_PORT_1E;
on tile[0] : clock      rd_clk = XS1_CLKBLK_4;

main ()
{
    unsigned int temp_data_input[128]; // 32 bit array
    timer tmr;
    unsigned t, timeout;
    configure_clock_rate (rd_clk , 100, 10);    // 100/10 = 10 MHz
    configure_port_clock_output(p_rd_clk, rd_clk );
    configure_in_port(p_fifo_data_ready, rd_clk); // read fifo_data_ready on clk edge
    configure_in_port_strobed_master(p_data_bus, p_rd_req, rd_clk); // Drive rd_req high to read data
    start_clock (rd_clk);
    clearbuf(p_data_bus);
    p_debug <: 0;
    
     while(TRUE)
    {
        select 
        {
            case  p_fifo_data_ready when pinsneq(0) :> f: // wait for ready data when data is ready

                p_debug <: 1;  // may have to remove to avoid buffer overrun but test to confirm

                p_data_bus :> temp_data_input[0];  // read first 2 x 16 bit data from external FIFO after 2 clock cycles

                p_debug <: 0;  // may have to remove to avoid buffer overrun but test to confirm

                p_data_bus :> temp_data_input[1];  // read  next 2 x 16 bit data from external FIFO  after 2 clock cycles

                p_debug <: 1;

                tmr :> t;
                timeout = t + 20; // timeout in 200ns
                p_debug <: 0;
                break;
         }
    }
 }  

Please test and post your results.

Introduction-to-XS1-ports_1.0.pdf
You do not have the required permissions to view the files attached to this post.
JohnRed
Junior Member
Posts: 5
Joined: Wed Oct 31, 2018 6:25 pm

Post by JohnRed »

Thanks for your reply.

I have made the updates you suggested to make the buffer 32 bit and then use the code to read in 2 x 32bit words however as the attached scope trace shows there is still an issue.

It appears from looking at the p_debug pin that the processor reads the two 32 bit words in less than one rd_clk cycle and before the p_rd_req line is asserted meaning that the FIFO has not been instructed to output the first or second word. This would suggest that there is data in the processors buffer before the read so I have tried calling clear_buffer(..) the scope trace for that code is also attached.

Then the p_rd_req is asserted and remains asserted for 4 complete clock cycles but the the processor has not waited for the data to be transferred from the port.

Then the select case runs again, presumably because the p_fifo_data_ready is still active?

I removed the tmr and timeout lines of code so that the second p_debug pulse appears distinctly shorter than the data read pulse.

Scope trace channels
Ch1 p_debug
ChA p_rd_clk
ChB p_fifo_data_ready
Ch2 p_rd_req


The updated code looks like this:

Code: Select all

on tile[0] : port p_debug   = XS1_PORT_1O;
in port     p_fifo_data_ready  = on tile[0]:XS1_PORT_1F;  // goes high to indicate there is data in the FIFO
in buffered port:32     p_data_bus    = on tile[0]:XS1_PORT_16A;  // 2 x 16bit data bus from FIFO
out port    p_rd_req      = on tile[0]:XS1_PORT_1N; // drive port high to read data from FIFO
on tile[0] : out port p_rd_clk = XS1_PORT_1E;
on tile[0] : clock      rd_clk = XS1_CLKBLK_4;

main ()
{
    unsigned int temp_data_input[128]; // 32 bit array
    timer tmr;
    unsigned t, timeout;
    configure_clock_rate (rd_clk , 100, 10);    // 100/10 = 10 MHz
    configure_port_clock_output(p_rd_clk, rd_clk );
    configure_in_port(p_fifo_data_ready, rd_clk); // read fifo_data_ready on clk edge
    configure_in_port_strobed_master(p_data_bus, p_rd_req, rd_clk); // Drive rd_req high to read data
    start_clock (rd_clk);
    clearbuf(p_data_bus);
    p_debug <: 0;
    
     while(TRUE)
    {
        select 
        {
            case  p_fifo_data_ready when pinsneq(0) :> f: // wait for ready data when data is ready

                p_debug <: 1;  // may have to remove to avoid buffer overrun but test to confirm

                p_data_bus :> temp_data_input[0];  // read first 2 x 16 bit data from external FIFO after 2 clock cycles

                p_debug <: 0;  // may have to remove to avoid buffer overrun but test to confirm

                p_data_bus :> temp_data_input[1];  // read  next 2 x 16 bit data from external FIFO  after 2 clock cycles

                p_debug <: 1;

                //tmr :> t;
                //timeout = t + 20; // timeout in 200ns
                p_debug <: 0;
                break;
         }
    }
 } 

Image

Image
You do not have the required permissions to view the files attached to this post.
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am

Post by mon2 »

Study Figure 7 of the attached document. That should be close to your requirement. Please test and post your update.

Change your master to be in slave mode and trigger off the FIFO's output ready pin.

xmos_figure_7.png
XS1-Ports-Specification_1.02.pdf
You do not have the required permissions to view the files attached to this post.