5b41f9a939d9d40fe883eb52842a26fdca3761b2
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
))
108 if hasattr(slave
, 'stall'):
109 comb
+= slave
.stall
.eq(master
.stall
)
111 # write Datapath - select fragments of data, depending on "counter"
112 with m
.Switch(counter
):
113 slen
= slave
.sel
.width
114 for i
in range(ratio
):
116 # select fractions of dat_w and associated "sel" bits
117 print ("sel", i
, "from", i
*slen
, "to", (i
+1)*slen
)
118 comb
+= slave
.sel
.eq(master
.sel
[i
*slen
:(i
+1)*slen
])
119 comb
+= slave
.dat_w
.eq(master
.dat_w
[i
*dw_to
:(i
+1)*dw_to
])
121 # read Datapath - uses cached_data and master.dat_r as a shift-register.
122 # by the time "counter" is done (counter_done) this is complete
123 comb
+= shift_reg
.eq(Cat(cached_data
[dw_to
:], slave
.dat_r
))
124 with m
.If(read
& counter_ce
):
125 sync
+= cached_data
.eq(shift_reg
)