📄 k20test.v
字号:
module TENBASET_TxD(clk20, Ethernet_TDp, Ethernet_TDm,inp,rdaddress);
// a 20MHz clock (this code won't work with a different frequency)
input clk20;
// the two differential 10BASE-T outputs
output Ethernet_TDp, Ethernet_TDm;
input [7:0] inp;
output [6:0] rdaddress;
// "IP source" - put an unused IP - if unsure, see comment below after the source code
parameter IPsource_1 = 0;//202;
parameter IPsource_2 = 0;//114;
parameter IPsource_3 = 0;//251;
parameter IPsource_4 = 0;//137;
// "IP destination" - put the IP of the PC you want to send to
parameter IPdestination_1 = 202;
parameter IPdestination_2 = 114;
parameter IPdestination_3 = 251;
parameter IPdestination_4 = 255;
// "Physical Address" - put the address of the PC you want to send to
parameter PhysicalAddress_1 = 8'h00;
parameter PhysicalAddress_2 = 8'h40;
parameter PhysicalAddress_3 = 8'hd0;
parameter PhysicalAddress_4 = 8'h91;
parameter PhysicalAddress_5 = 8'h76;
parameter PhysicalAddress_6 = 8'h75;
//////////////////////////////////////////////////////////////////////
// sends a packet roughly every second
reg [23:0] counter; always @(posedge clk20) counter<=counter+1;
reg StartSending; always @(posedge clk20) StartSending<=&counter;
//////////////////////////////////////////////////////////////////////
// we send a UDP packet, 18 bytes payload
// calculate the IP checksum, big-endian style
parameter IPchecksum1 = 32'h0000C53F + (IPsource_1<<8)+IPsource_2+(IPsource_3<<8)+IPsource_4+
(IPdestination_1<<8)+IPdestination_2+(IPdestination_3<<8)+(IPdestination_4);
parameter IPchecksum2 = ((IPchecksum1&32'h0000FFFF)+(IPchecksum1>>16));
parameter IPchecksum3 = ~((IPchecksum2&32'h0000FFFF)+(IPchecksum2>>16));
reg [6:0] rdaddress;
reg [7:0] pkt_data;
always @(posedge clk20)
case(rdaddress)
// Ethernet preamble
7'h00: pkt_data <= inp;//8'h55;
7'h01: pkt_data <= inp;//8'h55;
7'h02: pkt_data <= inp;//8'h55;
7'h03: pkt_data <= inp;//8'h55;
7'h04: pkt_data <= inp;//8'h55;
7'h05: pkt_data <= inp;//8'h55;
7'h06: pkt_data <= inp;//8'h55;
7'h07: pkt_data <= inp;//8'hD5;
// Ethernet header
7'h08: pkt_data <= inp;//PhysicalAddress_1;
7'h09: pkt_data <= inp;//PhysicalAddress_2;
7'h0A: pkt_data <= inp;//PhysicalAddress_3;
7'h0B: pkt_data <= inp;//PhysicalAddress_4;
7'h0C: pkt_data <= inp;//PhysicalAddress_5;
7'h0D: pkt_data <= inp;//PhysicalAddress_6;
7'h0E: pkt_data <= inp;//8'h00;
7'h0F: pkt_data <= inp;//8'h12;
7'h10: pkt_data <= inp;//8'h34;
7'h11: pkt_data <= inp;//8'h56;
7'h12: pkt_data <= inp;//8'h78;
7'h13: pkt_data <= inp;//8'h90;
// IP header
7'h14: pkt_data <= inp;//8'h08;
7'h15: pkt_data <= inp;//8'h00;
//上层数据类型 0x0800:IP协议数据;0x809B:AppleTalk协议数据;
7'h16: pkt_data <= inp;//8'h45;//长度不包括0x0800
//1、Version=4,表示IP协议的版本号为4。该部分占4个BIT位。
//2、Header Length=20 Bytes,表示IP包头的总长度为20个字节。
//该部分占4个BIT位,单位为4个字节,因此,一个IP包头的长度最长为“1111”,即15*4=60个字节。
7'h17: pkt_data <= inp;//8'h00;
//3、Type of Service=00,表示服务类型为0。该部分用二个十六进制值来表示,共占8个BIT。
//8个BIT的含义是:
//000 前三位不用
//0 表示最小时延,如Telnet服务使用该位
//0 表示吞吐量,如FTP服务使用该位
//0 表示可靠性,如SNMP服务使用该位
//0 表示最小代价
//0 不用
7'h18: pkt_data <= inp;//8'h00;
7'h19: pkt_data <= inp;//8'h2E;//0x2e->46
//Total Length=48Bytes,表示该IP包的总长度为48个字节。该部分占16个BIT,单位为Byte。
//由此IP数据包的最大长度为2的16次方减1,即:65535个字节。
//因此,在以太网中能够传输的最大IP数据包为65535个字节。
7'h1A: pkt_data <= inp;//8'h00;
7'h1B: pkt_data <= inp;//8'h00;
//Identification=363,表示IP包识别号为363。该部分占16个BIT,以十进制数表示。[程序当中没有这个东西]
7'h1C: pkt_data <= inp;//8'h00;
7'h1D: pkt_data <= inp;//8'h00;
//Flags,表示片标志,占3个BIT。各位含义分别为:第一个“0”不用,第二个“0”为分片标志位,“1”表示分片,“0”表示不分版本。
//第三个0为是否最后一片标志位,0表示最后一片,1表示还有更多的片。
//Fragment Offset=0,表示片偏移为0个Bytes。该部分占13个BIT。
7'h1E: pkt_data <= inp;//8'h80;
//Time to Live=128Secongs/Hops,表示生存时间TTL值为128.该部分占8个BIT
//当IP包通过一个路由器时,TTL就会减一,当TTL为0时,此IP包将被直接丢弃
7'h1F: pkt_data <= inp;//8'h11;
//Proctol=6(TCP),表示协议类型为TCP,协议代码是6.如果是UDP协议,则此处的协议代码应为17.
//如果是ICMP协议,则此处的协议代码应为1.该部分占8个BIT.
//1:ICMP;2:IGMP;3:GGP;4:IP;6:TCP;8:EGP;17:UDP
7'h20: pkt_data <= inp;//IPchecksum3[15:8];
7'h21: pkt_data <= inp;//IPchecksum3[ 7:0];
7'h22: pkt_data <= inp;//IPsource_1;
7'h23: pkt_data <= inp;//IPsource_2;
7'h24: pkt_data <= inp;//IPsource_3;
7'h25: pkt_data <= inp;//IPsource_4;
7'h26: pkt_data <= inp;//IPdestination_1;
7'h27: pkt_data <= inp;//IPdestination_2;
7'h28: pkt_data <= inp;//IPdestination_3;
7'h29: pkt_data <= inp;//IPdestination_4;//上面说的长度20是到这里
// UDP header
7'h2A: pkt_data <= inp;//8'h04;
7'h2B: pkt_data <= inp;//8'h00;
//source port
7'h2C: pkt_data <= inp;//8'h04;
7'h2D: pkt_data <= inp;//8'h00;
//destination port
7'h2E: pkt_data <= inp;//8'h00;
7'h2F: pkt_data <= inp;//8'h1A;
7'h30: pkt_data <= inp;//8'h00;
7'h31: pkt_data <= inp;//8'h00;
// payload
7'h32: pkt_data <= inp; // put here the data that you want to send
7'h33: pkt_data <= inp; // put here the data that you want to send
7'h34: pkt_data <= inp; // put here the data that you want to send
7'h35: pkt_data <= inp; // put here the data that you want to send
7'h36: pkt_data <= inp; // put here the data that you want to send
7'h37: pkt_data <= inp; // put here the data that you want to send
7'h38: pkt_data <= inp; // put here the data that you want to send
7'h39: pkt_data <= inp; // put here the data that you want to send
7'h3A: pkt_data <= inp; // put here the data that you want to send
7'h3B: pkt_data <= inp; // put here the data that you want to send
7'h3C: pkt_data <= inp; // put here the data that you want to send
7'h3D: pkt_data <= inp; // put here the data that you want to send
7'h3E: pkt_data <= inp; // put here the data that you want to send
7'h3F: pkt_data <= inp; // put here the data that you want to send
7'h40: pkt_data <= inp; // put here the data that you want to send
7'h41: pkt_data <= inp; // put here the data that you want to send
7'h42: pkt_data <= inp; // put here the data that you want to send
7'h43: pkt_data <= inp; // put here the data that you want to send
default: pkt_data <= 8'h00;
endcase
//////////////////////////////////////////////////////////////////////
// and finally the 10BASE-T's magic
reg [3:0] ShiftCount;
reg SendingPacket;
always @(posedge clk20) if(StartSending) SendingPacket<=1; else if(ShiftCount==14 && rdaddress==7'h48) SendingPacket<=0;
always @(posedge clk20) ShiftCount <= SendingPacket ? ShiftCount+1 : 15;
wire readram = (ShiftCount==15);
always @(posedge clk20) if(ShiftCount==15) rdaddress <= SendingPacket ? rdaddress+1 : 0;
reg [7:0] ShiftData; always @(posedge clk20) if(ShiftCount[0]) ShiftData <= readram ? pkt_data : {1'b0, ShiftData[7:1]};
// generate the CRC32
reg [31:0] CRC;
reg CRCflush; always @(posedge clk20) if(CRCflush) CRCflush <= SendingPacket; else if(readram) CRCflush <= (rdaddress==7'h44);
reg CRCinit; always @(posedge clk20) if(readram) CRCinit <= (rdaddress==7);
wire CRCinput = CRCflush ? 0 : (ShiftData[0] ^ CRC[31]);
always @(posedge clk20) if(ShiftCount[0]) CRC <= CRCinit ? ~0 : ({CRC[30:0],1'b0} ^ ({32{CRCinput}} & 32'h04C11DB7));
// generate the NLP --OK
reg [17:0] LinkPulseCount; always @(posedge clk20) LinkPulseCount <= SendingPacket ? 0 : LinkPulseCount+1;
reg LinkPulse; always @(posedge clk20) LinkPulse <= &LinkPulseCount[17:1];
// TP_IDL, shift-register and manchester encoder
reg SendingPacketData; always @(posedge clk20) SendingPacketData <= SendingPacket;
reg [2:0] idlecount; always @(posedge clk20) if(SendingPacketData) idlecount<=0; else if(~&idlecount) idlecount<=idlecount+1;
wire dataout = CRCflush ? ~CRC[31] : ShiftData[0];
reg qo; always @(posedge clk20) qo <= SendingPacketData ? ~dataout^ShiftCount[0] : 1;
reg qoe; always @(posedge clk20) qoe <= SendingPacketData | LinkPulse | (idlecount<6);
reg Ethernet_TDp; always @(posedge clk20) Ethernet_TDp <= (qoe ? qo : 1'b0);
reg Ethernet_TDm; always @(posedge clk20) Ethernet_TDm <= (qoe ? ~qo : 1'b0);
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -