From: Joshua Wise Date: Mon, 26 May 2008 04:26:32 +0000 (-0400) Subject: Ethernet RX support X-Git-Url: http://git.joshuawise.com/fpgaboy.git/commitdiff_plain/faa9ae6fee7e9c9f624cafdd0df7be4dc7ca973c?ds=sidebyside Ethernet RX support --- diff --git a/CoreTop.ucf b/CoreTop.ucf index f39f846..8b15722 100644 --- a/CoreTop.ucf +++ b/CoreTop.ucf @@ -2,8 +2,8 @@ NET "xtal" LOC="B8" | CLOCK_DEDICATED_ROUTE = FALSE; # And we get it in the ASS! NET "serio" LOC = "p9"; NET "serin" LOC = "u6"; -#NET "rxm" LOC="n18" ; -#NET "rxp" LOC="p18" ; +NET "rxm" LOC="n18" ; +NET "rxp" LOC="p18" ; NET "txp" LOC="j13" ; NET "txm" LOC="m18" ; diff --git a/Ethernet.v b/Ethernet.v index 2f0c668..d961585 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), + .waddr(txwraddr), .wr(wr && state == 2'b10 && addr == `ADDR_ETH), - .clk(clk), - .ethclk(ethclk), - .rdata(outdata) - ); + .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 <= {state,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 @@ -203,7 +266,7 @@ module EnetRX( odata <= data; oaddr <= oaddr + 1; wr <= 1; - end else if (end_of_Ethernet_frame) begin + end else if (end_of_Ethernet_frame && (oaddr > 1)) begin olength <= oaddr; oaddr <= 0; wr <= 0; @@ -211,7 +274,7 @@ module EnetRX( end else if (pktclear) begin pktrdy <= 0; wr <= 0; - else + end else wr <= 0; endmodule diff --git a/System.v b/System.v index 84b33b7..ec62236 100644 --- a/System.v +++ b/System.v @@ -243,6 +243,7 @@ module CoreTop( inout [15:0] cr_DQ, input ps2c, ps2d, output txp, txm, + input rxp, rxm, `endif output wire hs, vs, output wire [2:0] r, g, @@ -483,7 +484,10 @@ module CoreTop( .addr(addr[0]), .data(data[0]), .ethclk(ethclk), + .rxclk(xtalb), .txp(txp), - .txm(txm)); + .txm(txm), + .rxp(rxp), + .rxm(rxm)); `endif endmodule diff --git a/ethertest.asm b/ethertest.asm new file mode 100644 index 0000000..79543df --- /dev/null +++ b/ethertest.asm @@ -0,0 +1,88 @@ + SECTION "wee",HOME[$0] +outlp: ; Read a packet out if one is waiting. + ld a, [$FF69] + ld h, a + call puthex+$D800 + ld a, [$FF69] + ld l, a + call puthex+$D800 +rxlp: ld a, h + or l + jr z, tx + dec hl + ld a, [$FF69] + call puthex+$D800 + jr rxlp +tx: ld a, 13 + call putc+$D800 + ld a, 10 + call putc+$D800 + ld a, [$FF51] + ld [$D800+diqing], a + ld a, $0 + ld [$FF69], a + ld a, $60 + ld c, a + ld hl, $D800+bleep + ld [$FF69], a +lp: ld a, [hli] + ld [$FF69], a + dec c + jr nz, lp + ld hl, $0000 +dl1: dec hl + ld a, [$FF68] + ld [$FF51], a + ld a, h + or l + jr nz, dl1 + jr outlp +bleep: db $FF, $FF, $FF, $FF, $FF, $FF + db $00, $12, $34, $56, $78, $90 + db $08, $00 + + db $45, $00, $00, $2E, $00, $00, $00, $00, $80, $11 + db $26, $bd + db $0A, $00, $00, $02 + db $0A, $00, $00, $01 + + db $04, $00, $04, $00, $00, $1A, $00, $00 + +diqing: db $01, $02, $03, $04, $05, $06, $07, $08 + +putc: + push af +.waitport: + ld a,[$FF53] + and $01 + jr nz,.waitport + pop af + ld [$FF52],a + ret + +puthex: ; Put two hex nibbles to the serial console. + push bc + push hl + push af + swap a + and $0F + ld hl,hex+$D800 + ld b,0 + ld c,a + add hl,bc + ld a, [hl] + call putc+$D800 + pop af + and $0F + ld hl,hex+$D800 + ld c,a + add hl,bc + ld a, [hl] + call putc+$D800 + pop hl + pop bc + ret +hex: db "0123456789ABCDEF" + + section "anus", HOME[$100] + nop