2 from collections
import OrderedDict
4 from migen
.fhdl
.std
import *
5 from migen
.fhdl
.decorators
import ModuleDecorator
6 from migen
.genlib
.resetsync
import AsyncResetSynchronizer
7 from migen
.genlib
.record
import *
8 from migen
.genlib
.fsm
import FSM
, NextState
9 from migen
.genlib
.misc
import chooser
10 from migen
.flow
.actor
import EndpointDescription
11 from migen
.flow
.actor
import Sink
, Source
12 from migen
.actorlib
.structuring
import Converter
, Pipeline
13 from migen
.actorlib
.fifo
import SyncFIFO
, AsyncFIFO
14 from migen
.bank
.description
import *
17 eth_preamble
= 0xD555555555555555
18 buffer_depth
= 2**log2_int(eth_mtu
, need_pow2
=False)
21 def __init__(self
, byte
, offset
, width
):
26 ethernet_type_ip
= 0x800
27 ethernet_type_arp
= 0x806
31 "destination_mac_address": HField(0, 0, 48),
32 "source_mac_address": HField(6, 0, 48),
33 "ethernet_type": HField(12, 0, 16)
36 arp_packet_length
= 60
37 arp_hwtype_ethernet
= 0x0001
39 arp_opcode_request
= 0x0001
40 arp_opcode_reply
= 0x0002
44 "hardware_type": HField( 0, 0, 16),
45 "protocol_type": HField( 2, 0, 16),
46 "hardware_address_length": HField( 4, 0, 8),
47 "protocol_address_length": HField( 5, 0, 8),
48 "operation": HField( 6, 0, 16),
49 "source_mac_address": HField( 8, 0, 48),
50 "source_ip_address": HField(14, 0, 32),
51 "destination_mac_address": HField(18, 0, 48),
52 "destination_ip_address": HField(24, 0, 32)
57 "version": HField(0, 0, 4),
58 "ihl": HField(0, 4, 4),
59 "dscp": HField(1, 0, 6),
60 "ecn": HField(1, 6, 2),
61 "total_length": HField(2, 0, 16),
62 "identification": HField(4, 0, 16),
63 "flags": HField(6, 0, 3),
64 "fragment_offset": HField(6, 3, 13),
65 "time_to_live": HField(8, 0, 8),
66 "protocol": HField(9, 0, 8),
67 "header_checksum": HField(10, 0, 16),
68 "source_ip_address": HField(12, 0, 32),
69 "destination_ip_address": HField(16, 0, 32),
70 "options": HField(20, 0, 32)
74 "source_port": HField( 0, 0, 16),
75 "destination_port": HField( 2, 0, 16),
76 "length": HField( 4, 0, 16),
77 "checksum": HField( 6, 0, 16)
81 n
= math
.ceil(flen(v
)//8)
83 for i
in reversed(range(n
)):
84 r
.append(v
[i
*8:min((i
+1)*8, flen(v
))])
88 def _layout_from_header(header
):
90 for k
, v
in sorted(header
.items()):
91 _layout
.append((k
, v
.width
))
94 def eth_phy_description(dw
):
100 return EndpointDescription(layout
, packetized
=True)
102 def eth_mac_description(dw
):
103 layout
= _layout_from_header(mac_header
) + [
108 return EndpointDescription(layout
, packetized
=True)
110 def eth_arp_description(dw
):
111 layout
= _layout_from_header(arp_header
) + [
115 return EndpointDescription(layout
, packetized
=True)
117 arp_table_request_layout
= [
121 arp_table_response_layout
= [
126 def eth_ipv4_description(dw
):
127 layout
= _layout_from_header(ipv4_header
) + [
131 return EndpointDescription(layout
, packetized
=True)
133 def eth_udp_description(dw
):
134 layout
= _layout_from_header(udp_header
) + [
138 return EndpointDescription(layout
, packetized
=True)
141 @DecorateModule(InsertReset
)
142 @DecorateModule(InsertCE
)
143 class FlipFlop(Module
):
144 def __init__(self
, **kwargs
):
145 self
.d
= Signal(**kwargs
)
146 self
.q
= Signal(**kwargs
)
147 self
.sync
+= self
.q
.eq(self
.d
)
149 @DecorateModule(InsertReset
)
150 @DecorateModule(InsertCE
)
151 class Counter(Module
):
152 def __init__(self
, signal
=None, **kwargs
):
154 self
.value
= Signal(**kwargs
)
157 self
.width
= flen(self
.value
)
158 self
.sync
+= self
.value
.eq(self
.value
+1)
160 @DecorateModule(InsertReset
)
161 @DecorateModule(InsertCE
)
162 class Timeout(Module
):
163 def __init__(self
, length
):
164 self
.reached
= Signal()
166 value
= Signal(max=length
)
167 self
.sync
+= If(~self
.reached
, value
.eq(value
+1))
168 self
.comb
+= self
.reached
.eq(value
== (length
-1))
170 class BufferizeEndpoints(ModuleDecorator
):
171 def __init__(self
, submodule
, *args
):
172 ModuleDecorator
.__init
__(self
, submodule
)
174 endpoints
= get_endpoints(submodule
)
177 for name
, endpoint
in endpoints
.items():
178 if name
in args
or len(args
) == 0:
179 if isinstance(endpoint
, Sink
):
180 sinks
.update({name
: endpoint
})
181 elif isinstance(endpoint
, Source
):
182 sources
.update({name
: endpoint
})
184 # add buffer on sinks
185 for name
, sink
in sinks
.items():
186 buf
= Buffer(sink
.description
)
187 self
.submodules
+= buf
188 setattr(self
, name
, buf
.d
)
189 self
.comb
+= Record
.connect(buf
.q
, sink
)
191 # add buffer on sources
192 for name
, source
in sources
.items():
193 buf
= Buffer(source
.description
)
194 self
.submodules
+= buf
195 self
.comb
+= Record
.connect(source
, buf
.d
)
196 setattr(self
, name
, buf
.q
)