]> Joshua Wise's Git repositories - fpgaboy.git/blobdiff - Ethernet.v
Fix stupid ethernet bug
[fpgaboy.git] / Ethernet.v
index 2f0c668624e12a232f0158440e8d8524ec6b3067..56123c09d251530f11b4858277a9c90805f9486e 100644 (file)
@@ -9,67 +9,131 @@ module Ethernet (
        inout [7:0] data,
        input ethclk, rxclk,
        input rxp, rxm,
-       output txp, txm,
-);
+       output txp, txm);
 
-       wire [10:0] outaddr;
-       wire [7:0] outdata;
-       wire busy;
+       wire [10:0] txhwaddr;
+       wire [7:0] txhwdata;
+       wire txbusy;
 
-       reg [10:0] len = 0;
-       reg [10:0] addrcnt = 0;
-       reg [1:0] state = 0;
-       reg start = 0;
+       reg [10:0] txlength = 0;
+       reg [10:0] txwraddr = 0;
+       reg [1:0] txstate = 0;
+       reg txstart = 0;
        
        reg [15:0] addrlatch;
        reg rdlatch;
-
-       assign data = (addrlatch == `ADDR_ETH_STATUS && rdlatch) ? {state,5'b0,busy} : 8'bzzzzzzzz;
+       
+       wire decode = (addrlatch == `ADDR_ETH_STATUS) || (addrlatch == `ADDR_ETH);
+       reg [7:0] odata;
+       assign data = (decode && rdlatch) ? odata : 8'bzzzzzzzz;
 
        EnetTX tx(
                .clk20(ethclk),
                .Ethernet_TDp(txp),
                .Ethernet_TDm(txm),
-               .busy(busy),
-               .length(len),
-               .rdaddress(outaddr),
-               .start(start),
-               .indata(outdata));
+               .busy(txbusy),
+               .length(txlength),
+               .rdaddress(txhwaddr),
+               .start(txstart),
+               .indata(txhwdata));
        
        EthModRam txram(
                .wdata(data),
-               .waddr(addrcnt),
-               .raddr(outaddr),
-               .wr(wr && state == 2'b10 && addr == `ADDR_ETH),
-               .clk(clk),
-               .ethclk(ethclk),
-               .rdata(outdata)
-       );      
+               .waddr(txwraddr),
+               .wr(wr && txstate == 2'b10 && addr == `ADDR_ETH),
+               .wrclk(clk),
+               .rdata(txhwdata),
+               .raddr(txhwaddr),
+               .rdclk(ethclk));
+       
+       wire [10:0] rxphyaddr;
+       wire [7:0] rxphydata;
+       wire rxphywr;
+       wire rxpktrdy;
+       reg rxclear = 0;
+       reg [1:0] rxstate = 0;
+       wire [10:0] rxlength;
+       reg [10:0] rxcurlength;
+       
+       reg [10:0] rxcoreaddr = 0;
+       wire [7:0] rxcoredata;
        
+       EnetRX rx(
+               .rxclk(rxclk),
+               .manchester_data_in(~rxp),
+               .wr(rxphywr),
+               .oaddr(rxphyaddr),
+               .odata(rxphydata),
+               .pktrdy(rxpktrdy),
+               .olength(rxlength),
+               .pktclear(rxclear));
+       
+       EthModRam rxram(
+               .wdata(rxphydata),
+               .waddr(rxphyaddr),
+               .wr(rxphywr),
+               .wrclk(rxclk),
+               .rdata(rxcoredata),
+               .raddr(rxcoreaddr),
+               .rdclk(clk));
+
        always @ (posedge clk) begin
                addrlatch <= addr;
                rdlatch <= rd;
-               if(wr && addr == `ADDR_ETH) begin
-                       case(state)
+               
+               if (rd && addr == `ADDR_ETH_STATUS)
+                       odata <= {txstate,4'b0,rxpktrdy,txbusy};
+               else if (wr && addr == `ADDR_ETH_STATUS) begin          /* Reset the state machines. */
+                       rxstate <= 2'b00;
+                       txstate <= 2'b00;
+               end else if (rd && addr == `ADDR_ETH) begin
+                       case (rxstate)
                        2'b00: begin
-                               len[10:8] <= data[2:0];
-                               state <= 2'b01;
+                               if (!rxpktrdy)
+                                       rxcurlength <= 0;
+                               else
+                                       rxcurlength <= rxlength;
+                               odata <= rxpktrdy ? {5'b0,rxlength[10:8]} : 8'b0;
+                               rxstate <= 2'b01;
                        end
                        2'b01: begin
-                               len[7:0] <= data[7:0];
-                               state <= 2'b10;
+                               rxstate <= (rxcurlength == 0) ? 2'b00 : 2'b10;
+                               odata <= rxcurlength[7:0];
+                               rxcoreaddr <= 0;
+                       end
+                       2'b10: begin
+                               odata <= rxcoredata;
+                               if (rxcoreaddr == (rxcurlength - 1)) begin
+                                       rxstate <= 2'b11;
+                                       rxclear <= 1;
+                               end else
+                                       rxcoreaddr <= rxcoreaddr + 1;
+                       end
+                       endcase
+               end else if (rxstate == 2'b11 || rxclear) begin
+                       rxstate <= 2'b00;
+                       rxclear <= 0;
+               end else if (wr && addr == `ADDR_ETH) begin
+                       case(txstate)
+                       2'b00: begin
+                               txlength[10:8] <= data[2:0];
+                               txstate <= 2'b01;
+                       end
+                       2'b01: begin
+                               txlength[7:0] <= data[7:0];
+                               txstate <= 2'b10;
+                               txwraddr <= 0;
                        end
                        2'b10:
-                               if(addrcnt == len) begin
-                                       state <= 2'b11;
-                                       start <= 1'b1;
-                                       addrcnt <= 0;
+                               if(txwraddr == (txlength - 1)) begin
+                                       txstate <= 2'b11;
+                                       txstart <= 1'b1;
                                end else
-                                       addrcnt <= addrcnt + 1;
+                                       txwraddr <= txwraddr + 1;
                        endcase
-               end else if (state == 2'b11) begin
-                       start <= 1'b0;
-                       state <= 2'b00;
+               end else if (txstate == 2'b11) begin
+                       txstart <= 1'b0;
+                       txstate <= 2'b00;
                end
        end
 
@@ -80,19 +144,18 @@ module EthModRam (
        input [10:0] waddr,
        input [10:0] raddr,
        input wr,
-       input clk,
-       input ethclk,
-       output reg [7:0] rdata
-);
+       input wrclk,
+       input rdclk,
+       output reg [7:0] rdata);
 
        reg [7:0] mem [1600:0];
 
-       always @ (posedge clk) begin
+       always @(posedge wrclk) begin
                if(wr)
                        mem[waddr] <= wdata;
        end
 
-       always @(posedge ethclk)
+       always @(posedge rdclk)
                rdata <= mem[raddr];
 endmodule
 
@@ -141,11 +204,11 @@ endmodule
 module EnetRX(
        input rxclk,
        input manchester_data_in,
-       output wire wr,
+       output reg wr,
        output reg [10:0] oaddr,
-       output wire [7:0] odata,
-       output reg pktrdy,
-       output reg [10:0] olength,
+       output reg [7:0] odata,
+       output reg pktrdy = 0,
+       output reg [10:0] olength = 0,
        input pktclear);
        
        reg [2:0] in_data;
@@ -178,7 +241,7 @@ module EnetRX(
        
        reg [9:0] sync2;
        always @(posedge rxclk)
-               if(end_of_Ethernet_frame || !pktrdy)
+               if(end_of_Ethernet_frame || pktrdy)     // i.e., if we're busy, drop it on the floor
                        sync2 <= 0;
                else 
                if(new_bit_avail) begin
@@ -196,22 +259,24 @@ module EnetRX(
        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;
+       reg [11:0] iaddr;
        
        /////////////////////////////////////////////////
        always @(posedge rxclk)
                if (new_byte_available && !pktrdy) begin
                        odata <= data;
-                       oaddr <= oaddr + 1;
+                       oaddr <= iaddr;
+                       iaddr <= iaddr + 1;
                        wr <= 1;
-               end else if (end_of_Ethernet_frame) begin
-                       olength <= oaddr;
-                       oaddr <= 0;
+               end else if (end_of_Ethernet_frame && (iaddr > 1)) begin
+                       olength <= iaddr;
+                       iaddr <= 0;
                        wr <= 0;
                        pktrdy <= 1;
                end else if (pktclear) begin
                        pktrdy <= 0;
                        wr <= 0;
-               else
+               end else
                        wr <= 0;
        
 endmodule
This page took 0.036995 seconds and 4 git commands to generate.