84fd81773a6f7b9143cb64b9e68c25bd31596eed
1 from liteeth
.common
import *
2 from liteeth
.generic
.depacketizer
import LiteEthDepacketizer
3 from liteeth
.generic
.packetizer
import LiteEthPacketizer
5 class LiteEthIPV4Depacketizer(LiteEthDepacketizer
):
7 LiteEthDepacketizer
.__init
__(self
,
8 eth_mac_description(8),
9 eth_ipv4_description(8),
13 class LiteEthIPV4Packetizer(LiteEthPacketizer
):
15 LiteEthPacketizer
.__init
__(self
,
16 eth_ipv4_description(8),
17 eth_mac_description(8),
21 class LiteEthIPV4Checksum(Module
):
22 def __init__(self
, skip_header
=False):
23 self
.header
= Signal(ipv4_header_len
*8)
24 self
.value
= Signal(16)
28 for i
in range(ipv4_header_len
//2):
29 if skip_header
and i
== 5:
35 s_next
.eq(r
+ self
.header
[i
*16:(i
+1)*16]),
36 r_next
.eq(Cat(s_next
[:16]+s_next
[16], Signal()))
39 self
.comb
+= self
.value
.eq(~
Cat(r
[8:16], r
[:8]))
41 class LiteEthIPTX(Module
):
42 def __init__(self
, mac_address
, ip_address
, arp_table
):
43 self
.sink
= Sink(eth_ipv4_user_description(8))
44 self
.source
= Source(eth_mac_description(8))
46 packetizer
= LiteEthIPV4Packetizer()
47 self
.submodules
+= packetizer
49 packetizer
.sink
.stb
.eq(self
.sink
.stb
),
50 packetizer
.sink
.sop
.eq(self
.sink
.sop
),
51 packetizer
.sink
.eop
.eq(self
.sink
.eop
),
52 self
.sink
.eq(packetizer
.sink
.ack
),
53 packetizer
.sink
.destination_ip_address
.eq(ip_address
),
54 packetizer
.sink
.protocol
.eq(self
.sink
.protocol
),
55 packetizer
.sink
.total_length
.eq(self
.sink
.length
+ (0x5*4)),
56 packetizer
.sink
.version
.eq(0x4), # ipv4
57 packetizer
.sink
.ihl
.eq(0x5), # 20 bytes
58 packetizer
.sink
.dscp
.eq(0),
59 packetizer
.sink
.ecn
.eq(0),
60 packetizer
.sink
.identification
.eq(0),
61 packetizer
.sink
.flags
.eq(0),
62 packetizer
.sink
.fragment_offset
.eq(0),
63 packetizer
.sink
.time_to_live
.eq(0x80),
64 packetizer
.sink
.source_ip_address
.eq(ip_address
)
66 sink
= packetizer
.source
68 checksum
= LiteEthIPV4Checksum(skip_header
=True)
69 self
.submodules
+= checksum
71 checksum
.header
.eq(packetizer
.header
),
72 packetizer
.sink
.header_checksum
.eq(checksum
.value
)
75 destination_mac_address
= Signal(48)
77 fsm
= FSM(reset_state
="IDLE")
78 self
.submodules
+= fsm
81 If(sink
.stb
& sink
.sop
,
83 NextState("SEND_MAC_ADDRESS_REQUEST")
86 fsm
.act("SEND_MAC_ADDRESS_REQUEST",
87 arp_table
.request
.stb
.eq(1),
88 arp_table
.request
.ip_address
.eq(self
.sink
.ip_address
),
89 If(arp_table
.request
.stb
& arp_table
.request
.ack
,
90 NextState("WAIT_MAC_ADDRESS_RESPONSE")
93 fsm
.act("WAIT_MAC_ADDRESS_RESPONSE",
95 If(arp_table
.response
.stb
,
96 arp_table
.response
.ack
.eq(1),
101 self
.sync
+= If(arp_table
.response
.stb
, destination_mac_address
.eq(arp_table
.response
.mac_address
))
103 Record
.connect(packetizer
.source
, self
.source
),
104 self
.source
.ethernet_type
.eq(ethernet_type_ip
),
105 self
.source
.destination_mac_address
.eq(destination_mac_address
),
106 self
.source
.source_mac_address
.eq(mac_address
),
107 # XXX compute check sum
108 If(self
.source
.stb
& self
.source
.eop
& self
.source
.ack
,
114 class LiteEthIPRX(Module
):
115 def __init__(self
, mac_address
, ip_address
):
116 self
.sink
= Sink(eth_mac_description(8))
117 self
.source
= source
= Source(eth_ipv4_user_description(8))
119 depacketizer
= LiteEthIPV4Depacketizer()
120 self
.submodules
+= depacketizer
121 self
.comb
+= Record
.connect(self
.sink
, depacketizer
.sink
)
122 sink
= depacketizer
.source
124 fsm
= FSM(reset_state
="IDLE")
125 self
.submodules
+= fsm
128 If(sink
.stb
& sink
.sop
,
134 self
.comb
+= valid
.eq(1) # XXX FIXME
143 source
.stb
.eq(sink
.stb
),
144 source
.sop
.eq(sink
.sop
),
145 source
.eop
.eq(sink
.eop
),
146 sink
.ack
.eq(source
.ack
),
147 source
.length
.eq(sink
.total_length
- (sink
.ihl
*4)),
148 source
.protocol
.eq(sink
.protocol
),
149 source
.ip_address
.eq(sink
.destination_ip_address
),
150 source
.data
.eq(sink
.data
),
151 source
.error
.eq(sink
.error
),
152 If(source
.stb
& source
.eop
& source
.ack
,
158 If(source
.stb
& source
.eop
& source
.ack
,
163 class LiteEthIP(Module
):
164 def __init__(self
, mac
, mac_address
, ip_address
, arp_table
):
165 self
.submodules
.tx
= LiteEthIPTX(mac_address
, ip_address
, arp_table
)
166 self
.submodules
.rx
= LiteEthIPRX(mac_address
, ip_address
)
167 mac_port
= mac
.crossbar
.get_port(ethernet_type_ip
)
169 Record
.connect(self
.tx
.source
, mac_port
.sink
),
170 Record
.connect(mac_port
.source
, self
.rx
.sink
)
172 self
.sink
, self
.source
= self
.tx
.sink
, self
.rx
.source