Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

Need Help with Assigning Pins for Ethernet Interface

Hello everyone,

I'm new to FPGA programming. I'm trying to assign pins for an ethernet interface with no luck. Anyone has experience with this please guide me how to do.

Thank you very much. :oops:

Here is the code:

module TENBASET_TxD(clk20, Ethernet_TDp, Ethernet_TDm);
// 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;
// "IP source" - put an unused IP - if unsure, see comment below after the source code
parameter IPsource_1 = 192;
parameter IPsource_2 = 168;
parameter IPsource_3 = 0;
parameter IPsource_4 = 44;
// "IP destination" - put the IP of the PC you want to send to
parameter IPdestination_1 = 192;
parameter IPdestination_2 = 168;
parameter IPdestination_3 = 0;
parameter IPdestination_4 = 2;
// "Physical Address" - put the address of the PC you want to send to
parameter PhysicalAddress_1 = 8'h00;
parameter PhysicalAddress_2 = 8'h07;
parameter PhysicalAddress_3 = 8'h95;
parameter PhysicalAddress_4 = 8'h0B;
parameter PhysicalAddress_5 = 8'hFB;
parameter PhysicalAddress_6 = 8'hAF;
//////////////////////////////////////////////////////////////////////
// sends a packet roughly every second
reg  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  rdaddress;
reg  pkt_data;
always @(posedge clk20) 
case(rdaddress)
// Ethernet preamble
  7'h00: pkt_data <= 8'h55;
  7'h01: pkt_data <= 8'h55;
  7'h02: pkt_data <= 8'h55;
  7'h03: pkt_data <= 8'h55;
  7'h04: pkt_data <= 8'h55;
  7'h05: pkt_data <= 8'h55;
  7'h06: pkt_data <= 8'h55;
  7'h07: pkt_data <= 8'hD5;
// Ethernet header
  7'h08: pkt_data <= PhysicalAddress_1;
  7'h09: pkt_data <= PhysicalAddress_2;
  7'h0A: pkt_data <= PhysicalAddress_3;
  7'h0B: pkt_data <= PhysicalAddress_4;
  7'h0C: pkt_data <= PhysicalAddress_5;
  7'h0D: pkt_data <= PhysicalAddress_6;
  7'h0E: pkt_data <= 8'h00;
  7'h0F: pkt_data <= 8'h12;
  7'h10: pkt_data <= 8'h34;
  7'h11: pkt_data <= 8'h56;
  7'h12: pkt_data <= 8'h78;
  7'h13: pkt_data <= 8'h90;
// IP header
  7'h14: pkt_data <= 8'h08;
  7'h15: pkt_data <= 8'h00;
  7'h16: pkt_data <= 8'h45;
  7'h17: pkt_data <= 8'h00;
  7'h18: pkt_data <= 8'h00;
  7'h19: pkt_data <= 8'h2E;
  7'h1A: pkt_data <= 8'h00;
  7'h1B: pkt_data <= 8'h00;
  7'h1C: pkt_data <= 8'h00;
  7'h1D: pkt_data <= 8'h00;
  7'h1E: pkt_data <= 8'h80;
  7'h1F: pkt_data <= 8'h11;
  7'h20: pkt_data <= IPchecksum3;
  7'h21: pkt_data <= IPchecksum3;
  7'h22: pkt_data <= IPsource_1;
  7'h23: pkt_data <= IPsource_2;
  7'h24: pkt_data <= IPsource_3;
  7'h25: pkt_data <= IPsource_4;
  7'h26: pkt_data <= IPdestination_1;
  7'h27: pkt_data <= IPdestination_2;
  7'h28: pkt_data <= IPdestination_3;
  7'h29: pkt_data <= IPdestination_4;
// UDP header
  7'h2A: pkt_data <= 8'h04;
  7'h2B: pkt_data <= 8'h00;
  7'h2C: pkt_data <= 8'h04;
  7'h2D: pkt_data <= 8'h00;
  7'h2E: pkt_data <= 8'h00;
  7'h2F: pkt_data <= 8'h1A;
  7'h30: pkt_data <= 8'h00;
  7'h31: pkt_data <= 8'h00;
// payload
  7'h32: pkt_data <= 8'h00;	// put here the data that you want to send
  7'h33: pkt_data <= 8'h01;	// put here the data that you want to send
  7'h34: pkt_data <= 8'h02;	// put here the data that you want to send
  7'h35: pkt_data <= 8'h03;	// put here the data that you want to send
  7'h36: pkt_data <= 8'h04;	// put here the data that you want to send
  7'h37: pkt_data <= 8'h05;	// put here the data that you want to send
  7'h38: pkt_data <= 8'h06;	// put here the data that you want to send
  7'h39: pkt_data <= 8'h07;	// put here the data that you want to send
  7'h3A: pkt_data <= 8'h08;	// put here the data that you want to send
  7'h3B: pkt_data <= 8'h09;	// put here the data that you want to send
  7'h3C: pkt_data <= 8'h0A;	// put here the data that you want to send
  7'h3D: pkt_data <= 8'h0B;	// put here the data that you want to send
  7'h3E: pkt_data <= 8'h0C;	// put here the data that you want to send
  7'h3F: pkt_data <= 8'h0D;	// put here the data that you want to send
  7'h40: pkt_data <= 8'h0E;	// put here the data that you want to send
  7'h41: pkt_data <= 8'h0F;	// put here the data that you want to send
  7'h42: pkt_data <= 8'h10;	// put here the data that you want to send
  7'h43: pkt_data <= 8'h11;	// put here the data that you want to send
  default: pkt_data <= 8'h00;
endcase
//////////////////////////////////////////////////////////////////////
// and finally the 10BASE-T's magic
reg  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  ShiftData; always @(posedge clk20) if(ShiftCount) ShiftData <= readram ? pkt_data : {1'b0, ShiftData};
// generate the CRC32
reg  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 ^ CRC);
always @(posedge clk20) if(ShiftCount) CRC <= CRCinit ? ~0 : ({CRC,1'b0} ^ ({32{CRCinput}} & 32'h04C11DB7));
// generate the NLP
reg  LinkPulseCount; always @(posedge clk20) LinkPulseCount <= SendingPacket ? 0 : LinkPulseCount+1;
reg LinkPulse; always @(posedge clk20) LinkPulse <= &LinkPulseCount;
// TP_IDL, shift-register and manchester encoder
reg SendingPacketData; always @(posedge clk20) SendingPacketData <= SendingPacket;
reg  idlecount; always @(posedge clk20) if(SendingPacketData) idlecount<=0; else if(~&idlecount) idlecount<=idlecount+1;
wire dataout = CRCflush ? ~CRC : ShiftData;
reg qo; always @(posedge clk20) qo <= SendingPacketData ? ~dataout^ShiftCount : 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

5 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    That's a very basic Ethernet transmitter.

    What kind of board you are designing the interface to?

    Provided it indeed works (and I'm concerned about this), you only need to assign the 2 Ethernet_TDp/TDm signals to the proper fgpa pins.

    In your case you don't need a full featured ethernet phy, since you only have the tx section, no rx. So, you are only required to have a differential line driver which take the 2 signals and drives the 10baseT pulse transformer.

    A simple solution I used a lot of years ago was two 74AC04 drivers between each fpga pin (Ethernet_TDp/_TMm signals) and the transformer coil.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I am using Cyclone IV GX Starter Kit. I've already connected the clk20 to a PLL, but I got trouble when assigning the 2 Ethernet_TDp/TDm.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I took a look at the ref manual and I think you must follow the instructions at page 2-22.

    Since I don't know your Kit and application, I'm afraid I can't give you more help.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I read the reference manual, but I don't think it's useful for newbie. Anyways, I gave that up. Can you suggest the easiest method to transfer data between FPGA and PC? :oops:

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I think your dev kit came with a bunch of design examples.

    Look for Simple Socket Server project sample. That's what almost everyone starts with.