Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange behaviour in wishbone bus #13

Open
ydnatag opened this issue Jul 19, 2021 · 6 comments
Open

Strange behaviour in wishbone bus #13

ydnatag opened this issue Jul 19, 2021 · 6 comments

Comments

@ydnatag
Copy link

ydnatag commented Jul 19, 2021

Hey! First of all, thanks you for this amazing ecosystem you are building on top of nmigen!! It looks like easier to use than litex.

I'm trying to add vexriscv CPU to this building system but the serial irq is never asserted. I found an unexpected behaviour trying to write "events enable" of the serial peripheral..

As it is shown next, the wb transaction is done but the signals w_stb never goes up but the data is latched correctly.
image

Looking at a correct transaction (tx register), I noticed that the ack signal is never asserted in the previous case but it works ok in the other cases:

image

The same SoC works with minerva CPU.

Let me know if i can help debuging this or sending more information.
Thank you

@jfng
Copy link
Contributor

jfng commented Jul 26, 2021

Sorry for the delay. Could you provide a way to reproduce this bug ? It would help me track down what happened.

@ydnatag
Copy link
Author

ydnatag commented Jul 26, 2021

Yep, of course!! I'm going to clean it and make it reproducible. Give me a couples of days.

@ydnatag
Copy link
Author

ydnatag commented Aug 1, 2021

Here is a repository with some useful scripts to reproduce this bug. prepare.sh script creates a virtualenv and applies some patches to lambdasoc-bios to make vexriscv boot.

https://github.com/andresdemski/lambdasoc-vexriscv

Regards

@jfng
Copy link
Contributor

jfng commented Aug 9, 2021

So I gave it a look, and it's weird because I can't reproduce this behavior: dbus writes at 0x3C00000A assert csr_mux_1_uart_ev_enable__w_stb, regardless of the CPU. With Verilator 4.017.

lambdasoc-vexriscv

Looking at a correct transaction (tx register), I noticed that the ack signal is never asserted in the previous case but it works ok in the other cases:

The UART has two separate CSR bridges: one for its own registers (tx_data etc), and another for its event manager (ev_enable etc). Here, tx_data is located behind csr_bridge_0, and ev_enable behind csr_bridge_1.

In your screenshots, I believe that wb_ack and wb_cyc belong to csr_bridge_0, which would explain why they are not asserted when ev_enable is accessed.

@ydnatag
Copy link
Author

ydnatag commented Aug 11, 2021

Running the same "test" with minerva and vexriscv cpus and using the same gtkw to view the signals, I'm getting different results. The IRQ of the uart isn't asserted with vexriscv. I'm having the same behavior in hardware too.

Are you sure you are running the simulation with --cpu vexriscv?

Vexriscv

python3 cli.py --cpu vexriscv --sim nmigen_boards.versa_ecp5_5g:VersaECP55GPlatform

image

Minerva

python3 cli.py --cpu minerva --sim nmigen_boards.versa_ecp5_5g:VersaECP55GPlatform

image

@ydnatag
Copy link
Author

ydnatag commented Aug 21, 2021

Hey! I fixed the problem, I don't know if it is the correct way to solve this but it works... I don't know about wishbone bus but I noticed that the ACK signals keeps in 1, and vexriscv generates 2 transactions without dead clocks between each other, so the second transaction is accepted but it isn't processed at all.

I fixed it with the following changes on nmigen-soc:

diff --git a/nmigen_soc/csr/wishbone.py b/nmigen_soc/csr/wishbone.py
index ece1984..e152896 100644
--- a/nmigen_soc/csr/wishbone.py
+++ b/nmigen_soc/csr/wishbone.py
@@ -66,7 +66,10 @@ class WishboneCSRBridge(Elaboratable):
         cycle = Signal(range(len(wb_bus.sel) + 1))
         m.d.comb += csr_bus.addr.eq(Cat(cycle[:log2_int(len(wb_bus.sel))], wb_bus.adr))
 
-        with m.If(wb_bus.cyc & wb_bus.stb):
+        with m.If(wb_bus.ack):
+            m.d.sync += wb_bus.ack.eq(0)
+
+        with m.Elif(wb_bus.cyc & wb_bus.stb):
             with m.Switch(cycle):
                 def segment(index):
                     return slice(index * wb_bus.granularity, (index + 1) * wb_bus.granularity)
@@ -85,9 +88,6 @@ class WishboneCSRBridge(Elaboratable):
                     m.d.sync += wb_bus.dat_r[segment(index)].eq(csr_bus.r_data)
                     m.d.sync += wb_bus.ack.eq(1)
 
-        with m.Else():
-            m.d.sync += wb_bus.ack.eq(0)
-
         with m.If(wb_bus.ack):
             m.d.sync += cycle.eq(0)

What do you think? Is it ok?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants