X-Git-Url: http://git.joshuawise.com/fpgaboy.git/blobdiff_plain/99b9687942367fd256a797bcd1f67fec07f92a37..refs/heads/master:/Ethernet.v diff --git a/Ethernet.v b/Ethernet.v index 2f0c668..56123c0 100644 --- a/Ethernet.v +++ b/Ethernet.v @@ -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