enjoy-digital/liteiclink

[question] Loopback test with serwb

Opened this issue · 9 comments

Hello enjoy-digital,

I've tried to integrate a simple SoC to test serwb like below:

First, defined serwb memory map:

mem_map = {**soc_cls.mem_map, **{
    "ethmac":       0xb0000000,
    "spiflash":     0xd0000000,
    "serwb":        0x30000000,
    "csr":          0xf0000000,
}} 

Added serwb master:

    # serwb master
    self.submodules.serwb_master_phy = SERWBLowSpeedPHY(self.platform.device, self.platform.request("serwb_master"), mode="master")
    self.add_csr("serwb_master_phy")
            
    # led indicates phy init ready
    self.comb += [
        self.platform.request("user_led", 0).eq(self.serwb_master_phy.init.ready),
    ]

    # wishbone slave
    serwb_master_core = SERWBCore(self.serwb_master_phy, self.clk_freq, mode="slave")
    self.submodules += serwb_master_core

    # wishbone memory region
    self.add_wb_slave(self.mem_map["serwb"], serwb_master_core.etherbone.wishbone.bus, 1024)
    self.add_memory_region("serwb", self.mem_map["serwb"], 1024)

Added serwb slave:

    # serwb slave
    self.submodules.serwb_slave_phy = SERWBLowSpeedPHY(self.platform.device, self.platform.request("serwb_slave"), mode="slave")
    self.add_csr("serwb_slave_phy")
            
    # led indicates phy init ready
    self.comb += [
        self.platform.request("user_led", 1).eq(self.serwb_slave_phy.init.ready),
    ]

    # wishbone master
    serwb_slave_core = SERWBCore(self.serwb_slave_phy, self.clk_freq, mode="master")
    self.submodules += serwb_slave_core
    self.add_wb_master(serwb_slave_core.etherbone.wishbone.bus)
           
    # connect with sram 
    self.submodules.serwb_sram = wishbone.SRAM(1024, init=[i for i in range(1024//4)])
    self.comb += serwb_slave_core.etherbone.wishbone.bus.connect(self.serwb_sram.bus)

After loading the bitstream into FPGA, I saw LED0 & LED1 were on, I think the link of serwb was good, however, I couldn't read
SRAM values from the master:

1. Check serwb master phy control ready

litex> mr 0xf0004004
Memory dump:
0xf0004004 01 00 00 00

2. Read SRAM values from serwb master

litex> mr 0x30000000
Memory dump:
0x30000000 ff ff ff ff

I'm not confident about my code, would you please point out my mistakes?
Thank you.

Hi @kamejoko80,

i've planned to refresh the examples next week, so i'll be able to give more information when done.

Great! Thanks in advance.

@kamejoko80: this has been updated.

You can build and load the example design with::
./nexys_video.py --low-speed --build --load

Initialize LiteX Server with:
litex_server --uart --uart-port=/dev/ttyUSBX to open LiteX Server.

Initialize SerWB link and test access to the SRAM (through SerWB) with:
./test_serwb.py --ident --init --sram

Can you try to integrate this in your design and report your results?

Hi @enjoy-digital,

Thank you for your quick update.

I don't have nexys video board, so I've integrated it into my board.
Tried first with a single end connection:

    ("serwb_master", 0,
        Subsignal("clk",  Pins("U21")), # J12 31
        Subsignal("tx",   Pins("T20")), # J12 33
        Subsignal("rx",   Pins("T19")), # J12 35
        IOStandard("LVCMOS33"),
    ),

    ("serwb_slave", 0,
        Subsignal("clk",  Pins("V21")), # J12 32
        Subsignal("tx",   Pins("U19")), # J12 36
        Subsignal("rx",   Pins("U20")), # J12 34
        IOStandard("LVCMOS33"),
    ),

    ("serwb_enable", 0, Pins("D6"), IOStandard("LVCMOS33")),

Then I got the following result:

litex> mem_read 0x30000000 100

Memory dump:
0x30000000  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x30000010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x30000020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x30000030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x30000040  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x30000050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x30000060  00 00 00 00                                      ....

litex> mem_write 0x30000000 0xAA55AA55 100

litex> mem_read 0x30000000 100

Memory dump:
0x30000000  55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa  U.U.U.U.U.U.U.U.
0x30000010  55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa  U.U.U.U.U.U.U.U.
0x30000020  55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa  U.U.U.U.U.U.U.U.
0x30000030  55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa  U.U.U.U.U.U.U.U.
0x30000040  55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa  U.U.U.U.U.U.U.U.
0x30000050  55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa  U.U.U.U.U.U.U.U.
0x30000060  55 aa 55 aa                                                            U.U.

litex> mem_speed 0x30000000 4098

Memspeed at 0x30000000 (4KiB)...
  Write speed: 1MiB/s
   Read speed: 541KiB/s

It seems that the serwb worked well. The write speed shows 1MiB/s, does it mean 1 megabit per second?
How to increase the bandwidth? In the design, I set sys_clk_freq = 100MHz.

Thanks

I had an experiment to check the serwb is able to recover from connection loss or not.

1> Disconnect the link, try to access the SRAM:

litex> mem_write 0x30000000 0x12345678 100

litex> mem_read 0x30000000 100

Memory dump:
0x30000000  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000010  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000020  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000030  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000040  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000050  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000060  ff ff ff ff

2> Check serwb can recover or not:

Issue serwb master phy reset command:

litex> mem_write 0xf0003000 1

Check master phy ready:

litex> mem_read 0xf0003004
Memory dump:
0xf0003004  01 00 00 00                                      ....

Check master phy error:

litex> mem_read 0xf0003008
Memory dump:
0xf0003008  00 00 00 00                                      ....

Check slave phy ready:

litex> mem_read 0xf0003800
Memory dump:
0xf0003800  01 00 00 00                                      ....

Check slave phy error:

litex> mem_read 0xf0003804
Memory dump:
0xf0003804  00 00 00 00                                      ....

Check SoC is able to access the SRAM or not:

litex> mem_write 0x30000000 0x12345678 100
litex> mem_read 0x30000000 100
Memory dump:
0x30000000  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000010  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000020  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000030  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000040  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000050  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
0x30000060  ff ff ff ff                                      ....

Are there any further steps to control the serwb to recover the link?

Thank you.

Hi @kamejoko80,

thanks for the detailed feedback, that's really appreciated.

For the speed, it's 1 mega byte per second and it should be possible to increase it without too much efforts but i've not been focusing on that in my recent tests. I'm also planning to look at this in the next days. Could you eventually try to increase the Etherbone buffering here?: https://github.com/enjoy-digital/liteiclink/blob/master/liteiclink/serwb/core.py#L17 (on both side: Master and Slave). This should improve write speed, but that's possible it will not improve read speed since we are currently not supporting bursts on the Wishbone.

For the recover on disconnect, that's also something i want to add and was planning to work on this in the next days. For now it was focusing on static systems.

Hi @enjoy-digital

I've tried to change the FIFO buffer as below setting, but the write speed didn't change.

            # Wishbone Slave
            serwb_master_core = SERWBCore(
                self.serwb_master_phy, 
                self.clk_freq,
                mode = "slave",
                etherbone_buffer_depth = 16,
                tx_buffer_depth = 32,
                rx_buffer_depth = 32)
            self.submodules += serwb_master_core

            # Wishbone Master
            serwb_slave_core = SERWBCore(
                self.serwb_slave_phy, 
                self.clk_freq, 
                mode="master",
                etherbone_buffer_depth = 16,
                tx_buffer_depth = 32,
                rx_buffer_depth = 32)
            self.submodules += serwb_slave_core

There is one thing I observed that after changing SRAM size to 2048, the link was not synchronized.

            # Wishbone SRAM
            self.submodules.serwb_sram = wishbone.SRAM(2048)
            self.bus.add_slave("serwb", serwb_master_core.bus, SoCRegion(origin=0x30000000, size=2048))
            self.comb += serwb_slave_core.bus.connect(self.serwb_sram.bus)

Master/slave PHY reported error:

litex> mem_read 0xf0003008
Memory dump:
0xf0003008  01 00 00 00

litex> mem_read 0xf0003804
Memory dump:
0xf0003804  01 00 00 00            

Hi @enjoy-digital,

I've tried to communicate board to board with a single end serwb interface, however the link always not ready.
Have you ever tried with it? It is probably related to the link could not recover after disconnect, because two boards were not booted up at the same time.

I'd like to use serwb to build DAQ application, need to collect ADC (ADS1261) raw data simultaneously from other modules then send the package to the PC.

Thanks

Hi @kamejoko80,

i tested this recently with the examples in bench/serwb directory, but a manual reset of the Master is still required after a disconnect to reinitialize both Master and Slave (tested with https://github.com/enjoy-digital/liteiclink/blob/master/bench/serwb/test_serwb.py#L47-L62). Have you tried re initializing the link? I'm planning to work on auto-re initialization in the next days but haven't had time yet to do it.

Interesting use case, thanks for sharing.