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
)
45 dat_r
= Signal(dw_from
)
47 counter
= Signal(log2_int(ratio
, False))
48 counter_reset
= Signal()
50 with m
.If(counter_reset
):
52 with m
.Elif(counter_ce
):
53 sync
+= counter
.eq(counter
+ 1)
55 counter_done
= Signal()
56 comb
+= counter_done
.eq(counter
== ratio
-1)
61 comb
+= counter_reset
.eq(1)
63 sync
+= master
.ack
.eq(0)
64 with m
.If(master
.stb
& master
.cyc
):
65 if hasattr(master
, 'stall'):
66 comb
+= master
.stall
.eq(1)
72 with m
.State("WRITE"):
74 comb
+= slave
.we
.eq(1)
75 comb
+= slave
.cyc
.eq(1)
76 with m
.If(master
.stb
& master
.cyc
):
77 if hasattr(master
, 'stall'):
78 comb
+= master
.stall
.eq(1)
79 if hasattr(slave
, 'stall'):
80 with m
.If(~slave
.stall
):
81 comb
+= slave
.stb
.eq(1)
83 comb
+= slave
.stb
.eq(1)
85 comb
+= counter_ce
.eq(1)
86 with m
.If(counter_done
):
87 if hasattr(master
, 'stall'):
88 comb
+= master
.stall
.eq(0)
89 sync
+= master
.ack
.eq(1)
91 with m
.Elif(~master
.cyc
):
96 comb
+= slave
.cyc
.eq(1)
97 with m
.If(master
.stb
& master
.cyc
):
98 if hasattr(master
, 'stall'):
99 comb
+= master
.stall
.eq(1)
100 if hasattr(slave
, 'stall'):
101 with m
.If(~slave
.stall
):
102 comb
+= slave
.stb
.eq(1)
104 comb
+= slave
.stb
.eq(1)
105 with m
.If(slave
.ack
):
106 comb
+= counter_ce
.eq(1)
107 with m
.If(counter_done
):
108 if hasattr(master
, 'stall'):
109 comb
+= master
.stall
.eq(0)
110 sync
+= master
.ack
.eq(1)
112 with m
.Elif(~master
.cyc
):
116 if hasattr(slave
, 'cti'):
117 with m
.If(counter_done
):
118 comb
+= slave
.cti
.eq(7) # indicate end of burst
120 comb
+= slave
.cti
.eq(2)
121 comb
+= slave
.adr
.eq(Cat(counter
, master
.adr
))
123 # write Datapath - select fragments of data, depending on "counter"
124 with m
.Switch(counter
):
125 slen
= slave
.sel
.width
126 for i
in range(ratio
):
128 # select fractions of dat_w and associated "sel" bits
129 print ("sel", i
, "from", i
*slen
, "to", (i
+1)*slen
)
130 comb
+= slave
.sel
.eq(master
.sel
[i
*slen
:(i
+1)*slen
])
131 comb
+= slave
.dat_w
.eq(master
.dat_w
[i
*dw_to
:(i
+1)*dw_to
])
133 # read Datapath - uses cached_data and master.dat_r as a shift-register.
134 # by the time "counter" is done (counter_done) this is complete
135 comb
+= master
.dat_r
.eq(Cat(dat_r
[dw_to
:], slave
.dat_r
))
136 with m
.If(read
& slave
.ack
):
137 sync
+= dat_r
.eq(master
.dat_r
)