1 from nmigen
import Elaboratable
, Module
, Signal
, Repl
, Cat
, Mux
2 from nmigen
.utils
import log2_int
4 class WishboneDownConvert(Elaboratable
):
7 This module splits Wishbone accesses from a master interface to a smaller
11 Writes from master are split N writes to the slave. Access
12 is acked when the last access is acked by the slave.
15 Read from master are split in N reads to the the slave.
16 Read data from the slave are cached before being presented,
17 concatenated on the last access.
20 Manage err signal? (Not implemented since we generally don't
21 use it on Migen/MiSoC modules)
23 def __init__(self
, master
, slave
):
27 def elaborate(self
, platform
):
35 dw_from
= len(master
.dat_r
)
36 dw_to
= len(slave
.dat_w
)
37 ratio
= dw_from
//dw_to
39 print ("wb downconvert from to ratio", dw_from
, dw_to
, ratio
)
46 cached_data
= Signal(dw_from
)
47 shift_reg
= Signal(dw_from
)
49 counter
= Signal(log2_int(ratio
, False))
50 counter_reset
= Signal()
52 with m
.If(counter_reset
):
54 with m
.Elif(counter_ce
):
55 sync
+= counter
.eq(counter
+ 1)
57 counter_done
= Signal()
58 comb
+= counter_done
.eq(counter
== ratio
-1)
63 comb
+= counter_reset
.eq(1)
64 sync
+= cached_data
.eq(0)
65 with m
.If(master
.stb
& master
.cyc
):
71 with m
.State("WRITE"):
73 comb
+= slave
.we
.eq(1)
74 comb
+= slave
.cyc
.eq(1)
75 with m
.If(master
.stb
& master
.cyc
):
76 comb
+= slave
.stb
.eq(1)
78 comb
+= counter_ce
.eq(1)
79 with m
.If(counter_done
):
80 comb
+= master
.ack
.eq(1)
82 with m
.Elif(~master
.cyc
):
87 comb
+= slave
.cyc
.eq(1)
88 with m
.If(master
.stb
& master
.cyc
):
89 comb
+= slave
.stb
.eq(1)
91 comb
+= counter_ce
.eq(1)
92 with m
.If(counter_done
):
93 comb
+= master
.ack
.eq(1)
94 comb
+= master
.dat_r
.eq(shift_reg
)
96 with m
.Elif(~master
.cyc
):
100 if hasattr(slave
, 'cti'):
101 with m
.If(counter_done
):
102 comb
+= slave
.cti
.eq(7) # indicate end of burst
104 comb
+= slave
.cti
.eq(2)
105 comb
+= slave
.adr
.eq(Cat(counter
, master
.adr
))
107 # write Datapath - select fragments of data, depending on "counter"
108 with m
.Switch(counter
):
109 slen
= slave
.sel
.width
110 for i
in range(ratio
):
112 # select fractions of dat_w and associated "sel" bits
113 print ("sel", i
, "from", i
*slen
, "to", (i
+1)*slen
)
114 comb
+= slave
.sel
.eq(master
.sel
[i
*slen
:(i
+1)*slen
])
115 comb
+= slave
.dat_w
.eq(master
.dat_w
[i
*dw_to
:(i
+1)*dw_to
])
117 # read Datapath - uses cached_data and master.dat_r as a shift-register.
118 # by the time "counter" is done (counter_done) this is complete
119 comb
+= shift_reg
.eq(Cat(cached_data
[dw_to
:], slave
.dat_r
))
120 with m
.If(read
& counter_ce
):
121 sync
+= cached_data
.eq(shift_reg
)