-NET "xtal" LOC="B8";
+NET "xtal" LOC="B8" | CLOCK_DEDICATED_ROUTE = FALSE; # And we get it in the ASS!
NET "serio" LOC = "p9";
NET "serin" LOC = "u6";
-NET "leds<0>" LOC = "j14" ;
-NET "leds<1>" LOC = "j15" ;
-NET "leds<2>" LOC = "k15" ;
-NET "leds<3>" LOC = "k14" ;
-NET "leds<4>" LOC = "e17" ;
-NET "leds<5>" LOC = "p15" ;
-NET "leds<6>" LOC = "f4" ;
-NET "leds<7>" LOC = "r4" ;
+#NET "rxm" LOC="n18" ;
+#NET "rxp" LOC="p18" ;
+NET "txp" LOC="j13" ;
+NET "txm" LOC="m18" ;
+
+NET "leds<0>" LOC = "j14" ;
+NET "leds<1>" LOC = "j15" ;
+NET "leds<2>" LOC = "k15" ;
+NET "leds<3>" LOC = "k14" ;
+NET "leds<4>" LOC = "e17" ;
+NET "leds<5>" LOC = "p15" ;
+NET "leds<6>" LOC = "f4" ;
+NET "leds<7>" LOC = "r4" ;
NET "switches<7>" LOC="r17";
NET "switches<6>" LOC="n17";
--- /dev/null
+`define ADDR_ETH_STATUS 16'hFF68
+`define ADDR_ETH 16'hFF69
+
+module Ethernet (
+ input clk,
+ input wr,
+ input rd,
+ input [15:0] addr,
+ inout [7:0] data,
+ input ethclk, rxclk,
+ input rxp, rxm,
+ output txp, txm,
+);
+
+ wire [10:0] outaddr;
+ wire [7:0] outdata;
+ wire busy;
+
+ reg [10:0] len = 0;
+ reg [10:0] addrcnt = 0;
+ reg [1:0] state = 0;
+ reg start = 0;
+
+ reg [15:0] addrlatch;
+ reg rdlatch;
+
+ assign data = (addrlatch == `ADDR_ETH_STATUS && rdlatch) ? {state,5'b0,busy} : 8'bzzzzzzzz;
+
+ EnetTX tx(
+ .clk20(ethclk),
+ .Ethernet_TDp(txp),
+ .Ethernet_TDm(txm),
+ .busy(busy),
+ .length(len),
+ .rdaddress(outaddr),
+ .start(start),
+ .indata(outdata));
+
+ EthModRam txram(
+ .wdata(data),
+ .waddr(addrcnt),
+ .raddr(outaddr),
+ .wr(wr && state == 2'b10 && addr == `ADDR_ETH),
+ .clk(clk),
+ .ethclk(ethclk),
+ .rdata(outdata)
+ );
+
+ always @ (posedge clk) begin
+ addrlatch <= addr;
+ rdlatch <= rd;
+ if(wr && addr == `ADDR_ETH) begin
+ case(state)
+ 2'b00: begin
+ len[10:8] <= data[2:0];
+ state <= 2'b01;
+ end
+ 2'b01: begin
+ len[7:0] <= data[7:0];
+ state <= 2'b10;
+ end
+ 2'b10:
+ if(addrcnt == len) begin
+ state <= 2'b11;
+ start <= 1'b1;
+ addrcnt <= 0;
+ end else
+ addrcnt <= addrcnt + 1;
+ endcase
+ end else if (state == 2'b11) begin
+ start <= 1'b0;
+ state <= 2'b00;
+ end
+ end
+
+endmodule
+
+module EthModRam (
+ input [7:0] wdata,
+ input [10:0] waddr,
+ input [10:0] raddr,
+ input wr,
+ input clk,
+ input ethclk,
+ output reg [7:0] rdata
+);
+
+ reg [7:0] mem [1600:0];
+
+ always @ (posedge clk) begin
+ if(wr)
+ mem[waddr] <= wdata;
+ end
+
+ always @(posedge ethclk)
+ rdata <= mem[raddr];
+endmodule
+
+module EnetTX(input clk20, output reg Ethernet_TDp, output reg Ethernet_TDm, output wire busy, input start, input [11:0] length, output wire [11:0] rdaddress, input [7:0] indata);
+ reg StartSending; always @(posedge clk20) StartSending<=start;
+ reg [11:0] curlen = 0; always @(posedge clk20) if (start) curlen <= length + 8;
+
+ reg [11:0] internaladdr;
+ assign rdaddress = internaladdr - 8;
+ wire [7:0] pkt_data = (internaladdr < 7) ? 8'h55 :
+ (internaladdr == 7) ? 8'hD5 :
+ indata;
+
+ //////////////////////////////////////////////////////////////////////
+ // and finally the 10BASE-T's magic
+ reg [3:0] ShiftCount;
+ reg SendingPacket;
+ always @(posedge clk20) if(StartSending) SendingPacket<=1; else if(ShiftCount==14 && internaladdr==(curlen + 4)) SendingPacket<=0;
+ always @(posedge clk20) ShiftCount <= SendingPacket ? ShiftCount+1 : 15;
+ wire readram = (ShiftCount==15);
+ always @(posedge clk20) if(ShiftCount==15) internaladdr <= SendingPacket ? internaladdr+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 <= (internaladdr==curlen);
+ reg CRCinit; always @(posedge clk20) if(readram) CRCinit <= (internaladdr==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
+ 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;
+ assign busy = SendingPacketData;
+ 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);
+ always @(posedge clk20) Ethernet_TDp <= (qoe ? qo : 1'b0);
+ always @(posedge clk20) Ethernet_TDm <= (qoe ? ~qo : 1'b0);
+endmodule
+
+module EnetRX(
+ input rxclk,
+ input manchester_data_in,
+ output wire wr,
+ output reg [10:0] oaddr,
+ output wire [7:0] odata,
+ output reg pktrdy,
+ output reg [10:0] olength,
+ input pktclear);
+
+ reg [2:0] in_data;
+ always @(posedge rxclk) in_data <= {in_data[1:0], manchester_data_in};
+
+ reg [7:0] data;
+
+ reg [1:0] cnt;
+ always @(posedge rxclk) if(|cnt || (in_data[2] ^ in_data[1])) cnt<=cnt+1;
+
+ reg new_bit_avail;
+ always @(posedge rxclk) new_bit_avail <= (cnt==3);
+ always @(posedge rxclk) if(cnt==3) data<={in_data[1],data[7:1]};
+
+ /////////////////////////////////////////////////
+ reg end_of_Ethernet_frame;
+
+ reg [4:0] sync1;
+ always @(posedge rxclk)
+ if(end_of_Ethernet_frame)
+ sync1<=0;
+ else if(new_bit_avail) begin
+ if(!(data==8'h55 || data==8'hAA)) // not preamble?
+ sync1 <= 0;
+ else
+ if(~&sync1) // if all bits of this "sync1" counter are one, we decide that enough of the preamble
+ // has been received, so stop counting and wait for "sync2" to detect the SFD
+ sync1 <= sync1 + 1; // otherwise keep counting
+ end
+
+ reg [9:0] sync2;
+ always @(posedge rxclk)
+ if(end_of_Ethernet_frame || !pktrdy)
+ sync2 <= 0;
+ else
+ if(new_bit_avail) begin
+ if(|sync2) // if the SFD has already been detected (Ethernet data is coming in)
+ sync2 <= sync2 + 1; // then count the bits coming in
+ else if(&sync1 && data==8'hD5) // otherwise, let's wait for the SFD (0xD5)
+ sync2 <= sync2 + 1;
+ end
+
+ wire new_byte_available = new_bit_avail && (sync2[2:0]==3'h0) && (sync2[9:3]!=0);
+
+ /////////////////////////////////////////////////
+ // if no clock transistion is detected for some time, that's the end of the Ethernet frame
+
+ reg [2:0] transition_timeout;
+ always @(posedge rxclk) if(in_data[2]^in_data[1]) transition_timeout<=0; else if(~&cnt) transition_timeout<=transition_timeout+1;
+ always @(posedge rxclk) end_of_Ethernet_frame <= &transition_timeout;
+
+ /////////////////////////////////////////////////
+ always @(posedge rxclk)
+ if (new_byte_available && !pktrdy) begin
+ odata <= data;
+ oaddr <= oaddr + 1;
+ wr <= 1;
+ end else if (end_of_Ethernet_frame) begin
+ olength <= oaddr;
+ oaddr <= 0;
+ wr <= 0;
+ pktrdy <= 1;
+ end else if (pktclear) begin
+ pktrdy <= 0;
+ wr <= 0;
+ else
+ wr <= 0;
+
+endmodule
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 1995-2008 Xilinx, Inc. All rights reserved.
+////////////////////////////////////////////////////////////////////////////////
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version : 10.1
+// \ \ Application : xaw2verilog
+// / / Filename : CPUDCM.v
+// /___/ /\ Timestamp : 03/31/2008 23:51:44
+// \ \ / \
+// \___\/\___\
+//
+//Command: xaw2verilog -intstyle /home/joshua/projects/fpga/FPGABoy/CPUDCM.xaw -st CPUDCM.v
+//Design Name: CPUDCM
+//Device: xc3s500e-5fg320
+//
+// Module CPUDCM
+// Generated by Xilinx Architecture Wizard
+// Written for synthesis tool: XST
+// Period Jitter (unit interval) for block DCM_SP_INST = 0.04 UI
+// Period Jitter (Peak-to-Peak) for block DCM_SP_INST = 4.90 ns
+`timescale 1ns / 1ps
+
+module ethDCM(CLKIN_IN,
+ CLKFX_OUT,
+ CLKIN_IBUFG_OUT,
+ LOCKED_OUT);
+
+ input CLKIN_IN;
+ output CLKFX_OUT;
+ output CLKIN_IBUFG_OUT;
+ output LOCKED_OUT;
+
+ wire CLKFX_BUF;
+ wire CLKIN_IBUFG;
+ wire GND_BIT;
+
+ assign GND_BIT = 0;
+ assign CLKIN_IBUFG_OUT = CLKIN_IBUFG;
+ BUFG CLKFX_BUFG_INST (.I(CLKFX_BUF),
+ .O(CLKFX_OUT));
+ DCM_SP DCM_SP_INST (.CLKFB(GND_BIT),
+ .CLKIN(CLKIN_IN),
+ .DSSEN(GND_BIT),
+ .PSCLK(GND_BIT),
+ .PSEN(GND_BIT),
+ .PSINCDEC(GND_BIT),
+ .RST(GND_BIT),
+ .CLKDV(),
+ .CLKFX(CLKFX_BUF),
+ .CLKFX180(),
+ .CLK0(),
+ .CLK2X(),
+ .CLK2X180(),
+ .CLK90(),
+ .CLK180(),
+ .CLK270(),
+ .LOCKED(LOCKED_OUT),
+ .PSDONE(),
+ .STATUS());
+ defparam DCM_SP_INST.CLK_FEEDBACK = "NONE";
+ defparam DCM_SP_INST.CLKDV_DIVIDE = 2.0;
+ defparam DCM_SP_INST.CLKFX_DIVIDE = 5;
+ defparam DCM_SP_INST.CLKFX_MULTIPLY = 2;
+ defparam DCM_SP_INST.CLKIN_DIVIDE_BY_2 = "FALSE";
+ defparam DCM_SP_INST.CLKIN_PERIOD = 20.000;
+ defparam DCM_SP_INST.CLKOUT_PHASE_SHIFT = "NONE";
+ defparam DCM_SP_INST.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS";
+ defparam DCM_SP_INST.DFS_FREQUENCY_MODE = "LOW";
+ defparam DCM_SP_INST.DLL_FREQUENCY_MODE = "LOW";
+ defparam DCM_SP_INST.DUTY_CYCLE_CORRECTION = "TRUE";
+ defparam DCM_SP_INST.FACTORY_JF = 16'hC080;
+ defparam DCM_SP_INST.PHASE_SHIFT = 0;
+ defparam DCM_SP_INST.STARTUP_WAIT = "FALSE";
+endmodule