Strange behaviour in wishbone bus
Opened this issue · 6 comments
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.
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 same SoC works with minerva CPU.
Let me know if i can help debuging this or sending more information.
Thank you
Sorry for the delay. Could you provide a way to reproduce this bug ? It would help me track down what happened.
Yep, of course!! I'm going to clean it and make it reproducible. Give me a couples of days.
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
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.
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.
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
Minerva
python3 cli.py --cpu minerva --sim nmigen_boards.versa_ecp5_5g:VersaECP55GPlatform
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?