1 |
3 |
graver |
`timescale 1ns / 1ps
|
2 |
|
|
`include "const.vh"
|
3 |
|
|
//////////////////////////////////////////////////////////////////////////////////
|
4 |
|
|
// Company:
|
5 |
|
|
// Engineer: Ivan Krutov (grvfrv@gmail.com)
|
6 |
|
|
//
|
7 |
|
|
// Create Date: 22:59:14 08/28/2012
|
8 |
|
|
// Design Name:
|
9 |
|
|
// Module Name: EthernetTX
|
10 |
|
|
// Project Name: Cheap Ethernet
|
11 |
|
|
// Target Devices: Spartan 3E
|
12 |
|
|
// Tool versions: ISE 14.1
|
13 |
|
|
// Description: Base functional or ARP, ICMP, UDP
|
14 |
|
|
//
|
15 |
|
|
// Dependencies: TENBASET_TxD.v, const.vh
|
16 |
|
|
//
|
17 |
|
|
// Revision:
|
18 |
|
|
// Revision 0.9 beta
|
19 |
|
|
// Additional Comments:
|
20 |
|
|
//
|
21 |
|
|
//////////////////////////////////////////////////////////////////////////////////
|
22 |
|
|
module EthernetTX(clk20,
|
23 |
|
|
HostIP, RemoteIP, HostMAC, RemoteMAC, HostPort, RemotePort,
|
24 |
|
|
SendStart, SendDataReq, SendData, SendDataLen, SendDataPos, SendingPacket,
|
25 |
|
|
SendPacketType, SendICMPId, SendICMPSeq, SendICMPCRC,
|
26 |
|
|
Ethernet_TDp, Ethernet_TDm);
|
27 |
|
|
|
28 |
|
|
input clk20;
|
29 |
|
|
input [31:0] HostIP;
|
30 |
|
|
input [31:0] RemoteIP;
|
31 |
|
|
input [47:0] HostMAC;
|
32 |
|
|
input [47:0] RemoteMAC;
|
33 |
|
|
input [15:0] HostPort;
|
34 |
|
|
input [15:0] RemotePort;
|
35 |
|
|
input SendStart;
|
36 |
|
|
input [7:0] SendData;
|
37 |
|
|
input [9:0] SendDataLen;
|
38 |
|
|
output [9:0] SendDataPos;
|
39 |
|
|
output SendingPacket;
|
40 |
|
|
output SendDataReq;
|
41 |
|
|
input [2:0] SendPacketType;
|
42 |
|
|
input [15:0] SendICMPId;
|
43 |
|
|
input [15:0] SendICMPSeq;
|
44 |
|
|
input [15:0] SendICMPCRC;
|
45 |
|
|
output Ethernet_TDp, Ethernet_TDm;
|
46 |
|
|
|
47 |
|
|
reg [7:0] pkt_data = 0;
|
48 |
|
|
|
49 |
|
|
reg SendingPacket = 0;
|
50 |
|
|
wire [10:0] rdaddress;
|
51 |
|
|
wire [7:0] ShiftData;
|
52 |
|
|
wire [3:0] ShiftCount;
|
53 |
|
|
wire readram;
|
54 |
|
|
|
55 |
|
|
wire [9:0] SendDataPos = (rdaddress > 12'h32) ? (rdaddress - 12'h32) : 0;
|
56 |
|
|
wire [15:0] IPHLen = 8'd20 + 8'd8 + SendDataLen;
|
57 |
|
|
wire [15:0] UDPHLen = 8'd8 + SendDataLen;
|
58 |
|
|
|
59 |
|
|
reg [31:0] CRC = 0;
|
60 |
|
|
reg CRCflush = 0;
|
61 |
|
|
reg CRCinit = 0;
|
62 |
|
|
|
63 |
|
|
assign SendDataReq = (rdaddress > 8'h30) && readram;
|
64 |
|
|
|
65 |
|
|
// calculate the IP checksum, big-endian style
|
66 |
|
|
wire [18:0] IPchecksum1 = (SendPacketType == `ICMPReply ? 19'hC51D : 19'hC52D) + SendDataLen +
|
67 |
|
|
HostIP[31:16] + HostIP[15:0] + RemoteIP[31:16] + RemoteIP[15:0];
|
68 |
|
|
wire [15:0] IPchecksum2 = ~((IPchecksum1[15:0] + IPchecksum1[18:16]));
|
69 |
|
|
|
70 |
|
|
|
71 |
|
|
TENBASET_TxD TENBASET_TxD1 (clk20,
|
72 |
|
|
SendingPacket, pkt_data, rdaddress, ShiftData, ShiftCount, CRCflush, ~CRC[31], readram,
|
73 |
|
|
Ethernet_TDp, Ethernet_TDm);
|
74 |
|
|
|
75 |
|
|
|
76 |
|
|
always @(posedge clk20) begin
|
77 |
|
|
if (SendStart)
|
78 |
|
|
SendingPacket <= 1;
|
79 |
|
|
else if (ShiftCount == 14 && rdaddress == (54 + SendDataLen))
|
80 |
|
|
SendingPacket <= 0;
|
81 |
|
|
end
|
82 |
|
|
|
83 |
|
|
// generate the CRC32
|
84 |
|
|
wire CRCinput = CRCflush ? 0 : (ShiftData[0] ^ CRC[31]);
|
85 |
|
|
always @(posedge clk20) begin
|
86 |
|
|
if (CRCflush)
|
87 |
|
|
CRCflush <= SendingPacket;
|
88 |
|
|
else if (readram)
|
89 |
|
|
CRCflush <= (rdaddress == (50 + SendDataLen));
|
90 |
|
|
if (readram)
|
91 |
|
|
CRCinit <= (rdaddress == 7);
|
92 |
|
|
if (ShiftCount[0])
|
93 |
|
|
CRC <= CRCinit ? ~0 : ({CRC[30:0],1'b0} ^ ({32{CRCinput}} & 32'h04C11DB7));
|
94 |
|
|
end
|
95 |
|
|
|
96 |
|
|
wire ARP = (SendPacketType == `ARPReply || SendPacketType == `ARPReq);
|
97 |
|
|
|
98 |
|
|
always @(posedge clk20)
|
99 |
|
|
case (rdaddress)
|
100 |
|
|
// Ethernet preamble
|
101 |
|
|
12'h00: pkt_data <= 8'h55;
|
102 |
|
|
12'h01: pkt_data <= 8'h55;
|
103 |
|
|
12'h02: pkt_data <= 8'h55;
|
104 |
|
|
12'h03: pkt_data <= 8'h55;
|
105 |
|
|
12'h04: pkt_data <= 8'h55;
|
106 |
|
|
12'h05: pkt_data <= 8'h55;
|
107 |
|
|
12'h06: pkt_data <= 8'h55;
|
108 |
|
|
12'h07: pkt_data <= 8'hD5;
|
109 |
|
|
// Ethernet header
|
110 |
|
|
12'h08: pkt_data <= SendPacketType == `ARPReq ? 8'hFF : RemoteMAC[47:40];
|
111 |
|
|
12'h09: pkt_data <= SendPacketType == `ARPReq ? 8'hFF : RemoteMAC[39:32];
|
112 |
|
|
12'h0A: pkt_data <= SendPacketType == `ARPReq ? 8'hFF : RemoteMAC[31:24];
|
113 |
|
|
12'h0B: pkt_data <= SendPacketType == `ARPReq ? 8'hFF : RemoteMAC[23:16];
|
114 |
|
|
12'h0C: pkt_data <= SendPacketType == `ARPReq ? 8'hFF : RemoteMAC[15:8];
|
115 |
|
|
12'h0D: pkt_data <= SendPacketType == `ARPReq ? 8'hFF : RemoteMAC[7:0];
|
116 |
|
|
12'h0E: pkt_data <= HostMAC[47:40];
|
117 |
|
|
12'h0F: pkt_data <= HostMAC[39:32];
|
118 |
|
|
12'h10: pkt_data <= HostMAC[31:24];
|
119 |
|
|
12'h11: pkt_data <= HostMAC[23:16];
|
120 |
|
|
12'h12: pkt_data <= HostMAC[15:8];
|
121 |
|
|
12'h13: pkt_data <= HostMAC[7:0];
|
122 |
|
|
// IP header / ARP / ICMP
|
123 |
|
|
12'h14: pkt_data <= 8'h08;
|
124 |
|
|
12'h15: pkt_data <= ARP ? 8'h06 : 8'h00;
|
125 |
|
|
12'h16: pkt_data <= ARP ? 8'h00 : 8'h45;
|
126 |
|
|
12'h17: pkt_data <= ARP ? 8'h01 : 8'h00;
|
127 |
|
|
12'h18: pkt_data <= ARP ? 8'h08 : IPHLen[15:8];
|
128 |
|
|
12'h19: pkt_data <= ARP ? 8'h00 : IPHLen[7:0];
|
129 |
|
|
12'h1A: pkt_data <= ARP ? 8'h06 : 8'h00;
|
130 |
|
|
12'h1B: pkt_data <= ARP ? 8'h04 : 8'h00;
|
131 |
|
|
12'h1C: pkt_data <= 8'h00;
|
132 |
|
|
12'h1D: pkt_data <= SendPacketType == `ARPReply ? 8'h02 : SendPacketType == `ARPReq ? 8'h01 : 8'h00;
|
133 |
|
|
12'h1E: pkt_data <= ARP ? HostMAC[47:40] : 8'h80;
|
134 |
|
|
12'h1F: pkt_data <= ARP ? HostMAC[39:32] : SendPacketType == `ICMPReply ? 8'h01 : 8'h11;
|
135 |
|
|
12'h20: pkt_data <= ARP ? HostMAC[31:24] : IPchecksum2[15:8];
|
136 |
|
|
12'h21: pkt_data <= ARP ? HostMAC[23:16] : IPchecksum2[ 7:0];
|
137 |
|
|
12'h22: pkt_data <= ARP ? HostMAC[15:8] : HostIP[31:24];
|
138 |
|
|
12'h23: pkt_data <= ARP ? HostMAC[7:0] : HostIP[23:16];
|
139 |
|
|
12'h24: pkt_data <= ARP ? HostIP[31:24] : HostIP[15:8];
|
140 |
|
|
12'h25: pkt_data <= ARP ? HostIP[23:16] : HostIP[7:0];
|
141 |
|
|
12'h26: pkt_data <= ARP ? HostIP[15:8] : RemoteIP[31:24];
|
142 |
|
|
12'h27: pkt_data <= ARP ? HostIP[7:0] : RemoteIP[23:16];
|
143 |
|
|
12'h28: pkt_data <= SendPacketType == `ARPReply ? RemoteMAC[47:40] : SendPacketType == `ARPReq ? 8'h00 : RemoteIP[15:8];
|
144 |
|
|
12'h29: pkt_data <= SendPacketType == `ARPReply ? RemoteMAC[39:32] : SendPacketType == `ARPReq ? 8'h00 : RemoteIP[7:0];
|
145 |
|
|
// UDP header / ARP / ICMP
|
146 |
|
|
12'h2A: pkt_data <= SendPacketType == `ARPReply ? RemoteMAC[31:24] : SendPacketType == `ICMPReply ? 8'h00 : SendPacketType == `ARPReq ? 8'h00 : HostPort[15:8];
|
147 |
|
|
12'h2B: pkt_data <= SendPacketType == `ARPReply ? RemoteMAC[23:16] : HostPort[7:0];
|
148 |
|
|
12'h2C: pkt_data <= SendPacketType == `ARPReply ? RemoteMAC[15:8] : SendPacketType == `ICMPReply ? SendICMPCRC[15:8] : SendPacketType == `ARPReq ? 8'h00 : RemotePort[15:8];
|
149 |
|
|
12'h2D: pkt_data <= SendPacketType == `ARPReply ? RemoteMAC[7:0] : SendPacketType == `ICMPReply ? SendICMPCRC[7:0] : RemotePort[7:0];
|
150 |
|
|
12'h2E: pkt_data <= ARP ? RemoteIP[31:24] : SendPacketType == `ICMPReply ? SendICMPId[15:8] : UDPHLen[15:8];
|
151 |
|
|
12'h2F: pkt_data <= ARP ? RemoteIP[23:16] : SendPacketType == `ICMPReply ? SendICMPId[7:0] : UDPHLen[7:0];
|
152 |
|
|
12'h30: pkt_data <= ARP ? RemoteIP[15:8] : SendPacketType == `ICMPReply ? SendICMPSeq[15:8] : 8'h00;
|
153 |
|
|
12'h31: pkt_data <= ARP ? RemoteIP[7:0] : SendPacketType == `ICMPReply ? SendICMPSeq[7:0] : 8'h00;
|
154 |
|
|
default: pkt_data <= ARP ? 8'h00 : SendData;
|
155 |
|
|
endcase
|
156 |
|
|
|
157 |
|
|
endmodule
|