77564f2f1cb831ba2365ea784f4c18c2eda3a637
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 cur_counter
= Signal(log2_int(ratio
, False))
52 counter_done
= Signal()
53 comb
+= counter_done
.eq(counter
== ratio
-1)
54 comb
+= cur_counter
.eq(counter
)
60 sync
+= cached_data
.eq(0)
61 with m
.If(master
.stb
& master
.cyc
):
67 with m
.State("WRITE"):
69 with m
.If(master
.stb
& master
.cyc
):
70 comb
+= slave
.we
.eq(1)
71 comb
+= slave
.cyc
.eq(1)
72 comb
+= slave
.stb
.eq(1)
74 comb
+= cur_counter
.eq(counter
+ 1)
75 sync
+= counter
.eq(cur_counter
)
76 with m
.If(counter_done
):
77 comb
+= master
.ack
.eq(1)
79 with m
.Elif(~master
.cyc
):
84 with m
.If(master
.stb
& master
.cyc
):
85 comb
+= slave
.cyc
.eq(1)
86 comb
+= slave
.stb
.eq(1)
88 comb
+= cur_counter
.eq(counter
+ 1)
89 sync
+= counter
.eq(cur_counter
)
90 with m
.If(counter_done
):
91 comb
+= master
.ack
.eq(1)
92 comb
+= master
.dat_r
.eq(shift_reg
)
94 with m
.Elif(~master
.cyc
):
98 if hasattr(slave
, 'cti'):
99 with m
.If(counter_done
):
100 comb
+= slave
.cti
.eq(7) # indicate end of burst
102 comb
+= slave
.cti
.eq(2)
103 comb
+= slave
.adr
.eq(Cat(cur_counter
, master
.adr
))
105 # write Datapath - select fragments of data, depending on "counter"
106 with m
.Switch(counter
):
107 slen
= slave
.sel
.width
108 for i
in range(ratio
):
110 # select fractions of dat_w and associated "sel" bits
111 print ("sel", i
, "from", i
*slen
, "to", (i
+1)*slen
)
112 comb
+= slave
.sel
.eq(master
.sel
[i
*slen
:(i
+1)*slen
])
113 comb
+= slave
.dat_w
.eq(master
.dat_w
[i
*dw_to
:(i
+1)*dw_to
])
115 # read Datapath - uses cached_data and master.dat_r as a shift-register.
116 # by the time "counter" is done (counter_done) this is complete
117 comb
+= shift_reg
.eq(Cat(cached_data
[dw_to
:], slave
.dat_r
))
118 with m
.If(read
& slave
.ack
):
119 sync
+= cached_data
.eq(shift_reg
)