litex_sim: Rework Makefiles to put output files in gateware directory.
[litex.git] / litex / soc / interconnect / wishbonebridge.py
1 # This file is Copyright (c) 2015-2018 Florent Kermarrec <florent@enjoy-digital.fr>
2 # License: BSD
3
4 from migen import *
5
6 from migen.genlib.misc import chooser, WaitTimer
7 from migen.genlib.record import Record
8 from migen.genlib.fsm import FSM, NextState
9
10 from litex.soc.interconnect import wishbone
11 from litex.soc.interconnect import stream
12
13
14 class WishboneStreamingBridge(Module):
15 cmds = {
16 "write": 0x01,
17 "read": 0x02
18 }
19
20 def __init__(self, phy, clk_freq):
21 self.wishbone = wishbone.Interface()
22
23 # # #
24
25 byte_counter = Signal(3, reset_less=True)
26 byte_counter_reset = Signal()
27 byte_counter_ce = Signal()
28 self.sync += \
29 If(byte_counter_reset,
30 byte_counter.eq(0)
31 ).Elif(byte_counter_ce,
32 byte_counter.eq(byte_counter + 1)
33 )
34
35 word_counter = Signal(3, reset_less=True)
36 word_counter_reset = Signal()
37 word_counter_ce = Signal()
38 self.sync += \
39 If(word_counter_reset,
40 word_counter.eq(0)
41 ).Elif(word_counter_ce,
42 word_counter.eq(word_counter + 1)
43 )
44
45 cmd = Signal(8, reset_less=True)
46 cmd_ce = Signal()
47
48 length = Signal(8, reset_less=True)
49 length_ce = Signal()
50
51 address = Signal(32, reset_less=True)
52 address_ce = Signal()
53
54 data = Signal(32, reset_less=True)
55 rx_data_ce = Signal()
56 tx_data_ce = Signal()
57
58 self.sync += [
59 If(cmd_ce, cmd.eq(phy.source.data)),
60 If(length_ce, length.eq(phy.source.data)),
61 If(address_ce, address.eq(Cat(phy.source.data, address[0:24]))),
62 If(rx_data_ce,
63 data.eq(Cat(phy.source.data, data[0:24]))
64 ).Elif(tx_data_ce,
65 data.eq(self.wishbone.dat_r)
66 )
67 ]
68
69 fsm = ResetInserter()(FSM(reset_state="IDLE"))
70 timer = WaitTimer(clk_freq//10)
71 self.submodules += fsm, timer
72 self.comb += [
73 fsm.reset.eq(timer.done),
74 phy.source.ready.eq(1)
75 ]
76 fsm.act("IDLE",
77 If(phy.source.valid,
78 cmd_ce.eq(1),
79 If((phy.source.data == self.cmds["write"]) |
80 (phy.source.data == self.cmds["read"]),
81 NextState("RECEIVE_LENGTH")
82 ),
83 byte_counter_reset.eq(1),
84 word_counter_reset.eq(1)
85 )
86 )
87 fsm.act("RECEIVE_LENGTH",
88 If(phy.source.valid,
89 length_ce.eq(1),
90 NextState("RECEIVE_ADDRESS")
91 )
92 )
93 fsm.act("RECEIVE_ADDRESS",
94 If(phy.source.valid,
95 address_ce.eq(1),
96 byte_counter_ce.eq(1),
97 If(byte_counter == 3,
98 If(cmd == self.cmds["write"],
99 NextState("RECEIVE_DATA")
100 ).Elif(cmd == self.cmds["read"],
101 NextState("READ_DATA")
102 ),
103 byte_counter_reset.eq(1),
104 )
105 )
106 )
107 fsm.act("RECEIVE_DATA",
108 If(phy.source.valid,
109 rx_data_ce.eq(1),
110 byte_counter_ce.eq(1),
111 If(byte_counter == 3,
112 NextState("WRITE_DATA"),
113 byte_counter_reset.eq(1)
114 )
115 )
116 )
117 self.comb += [
118 self.wishbone.adr.eq(address + word_counter),
119 self.wishbone.dat_w.eq(data),
120 self.wishbone.sel.eq(2**len(self.wishbone.sel) - 1)
121 ]
122 fsm.act("WRITE_DATA",
123 self.wishbone.stb.eq(1),
124 self.wishbone.we.eq(1),
125 self.wishbone.cyc.eq(1),
126 If(self.wishbone.ack,
127 word_counter_ce.eq(1),
128 If(word_counter == (length-1),
129 NextState("IDLE")
130 ).Else(
131 NextState("RECEIVE_DATA")
132 )
133 )
134 )
135 fsm.act("READ_DATA",
136 self.wishbone.stb.eq(1),
137 self.wishbone.we.eq(0),
138 self.wishbone.cyc.eq(1),
139 If(self.wishbone.ack,
140 tx_data_ce.eq(1),
141 NextState("SEND_DATA")
142 )
143 )
144 self.comb += \
145 chooser(data, byte_counter, phy.sink.data, n=4, reverse=True)
146 fsm.act("SEND_DATA",
147 phy.sink.valid.eq(1),
148 If(phy.sink.ready,
149 byte_counter_ce.eq(1),
150 If(byte_counter == 3,
151 word_counter_ce.eq(1),
152 If(word_counter == (length-1),
153 NextState("IDLE")
154 ).Else(
155 NextState("READ_DATA"),
156 byte_counter_reset.eq(1)
157 )
158 )
159 )
160 )
161
162 self.comb += timer.wait.eq(~fsm.ongoing("IDLE"))
163
164 self.comb += phy.sink.last.eq((byte_counter == 3) & (word_counter == length - 1))
165
166 if hasattr(phy.sink, "length"):
167 self.comb += phy.sink.length.eq(4*length)