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
.ack
.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
),
65 packetizer
.sink
.data
.eq(self
.sink
.data
)
67 sink
= packetizer
.source
69 checksum
= LiteEthIPV4Checksum(skip_header
=True)
70 self
.submodules
+= checksum
72 checksum
.header
.eq(packetizer
.header
),
73 packetizer
.sink
.header_checksum
.eq(checksum
.value
)
76 destination_mac_address
= Signal(48)
78 fsm
= FSM(reset_state
="IDLE")
79 self
.submodules
+= fsm
82 If(sink
.stb
& sink
.sop
,
84 NextState("SEND_MAC_ADDRESS_REQUEST")
87 fsm
.act("SEND_MAC_ADDRESS_REQUEST",
88 arp_table
.request
.stb
.eq(1),
89 arp_table
.request
.ip_address
.eq(self
.sink
.ip_address
),
90 If(arp_table
.request
.stb
& arp_table
.request
.ack
,
91 NextState("WAIT_MAC_ADDRESS_RESPONSE")
94 fsm
.act("WAIT_MAC_ADDRESS_RESPONSE",
96 If(arp_table
.response
.stb
,
97 arp_table
.response
.ack
.eq(1),
102 self
.sync
+= If(arp_table
.response
.stb
, destination_mac_address
.eq(arp_table
.response
.mac_address
))
104 Record
.connect(packetizer
.source
, self
.source
),
105 self
.source
.ethernet_type
.eq(ethernet_type_ip
),
106 self
.source
.destination_mac_address
.eq(destination_mac_address
),
107 self
.source
.source_mac_address
.eq(mac_address
),
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 checksum
= LiteEthIPV4Checksum(skip_header
=False)
125 self
.submodules
+= checksum
126 self
.comb
+= checksum
.header
.eq(depacketizer
.header
)
128 fsm
= FSM(reset_state
="IDLE")
129 self
.submodules
+= fsm
132 If(sink
.stb
& sink
.sop
,
138 self
.comb
+= valid
.eq(
140 (sink
.destination_ip_address
== ip_address
) &
141 (sink
.version
== 0x4) &
143 (checksum
.value
== 0)
154 source
.stb
.eq(sink
.stb
),
155 source
.sop
.eq(sink
.sop
),
156 source
.eop
.eq(sink
.eop
),
157 sink
.ack
.eq(source
.ack
),
158 source
.length
.eq(sink
.total_length
- (sink
.ihl
*4)),
159 source
.protocol
.eq(sink
.protocol
),
160 source
.ip_address
.eq(sink
.destination_ip_address
),
161 source
.data
.eq(sink
.data
),
162 source
.error
.eq(sink
.error
),
163 If(source
.stb
& source
.eop
& source
.ack
,
169 If(source
.stb
& source
.eop
& source
.ack
,
174 class LiteEthIP(Module
):
175 def __init__(self
, mac
, mac_address
, ip_address
, arp_table
):
176 self
.submodules
.tx
= LiteEthIPTX(mac_address
, ip_address
, arp_table
)
177 self
.submodules
.rx
= LiteEthIPRX(mac_address
, ip_address
)
178 mac_port
= mac
.crossbar
.get_port(ethernet_type_ip
)
180 Record
.connect(self
.tx
.source
, mac_port
.sink
),
181 Record
.connect(mac_port
.source
, self
.rx
.sink
)
183 self
.sink
, self
.source
= self
.tx
.sink
, self
.rx
.source