Ethernet RX support
authorJoshua Wise <joshua@rebirth.joshuawise.com>
Mon, 26 May 2008 04:26:32 +0000 (00:26 -0400)
committerJoshua Wise <joshua@rebirth.joshuawise.com>
Mon, 26 May 2008 04:26:32 +0000 (00:26 -0400)
CoreTop.ucf
Ethernet.v
System.v
ethertest.asm [new file with mode: 0644]

index f39f846..8b15722 100644 (file)
@@ -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" ;
 
index 2f0c668..d961585 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),
+               .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
index 84b33b7..ec62236 100644 (file)
--- 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 (file)
index 0000000..79543df
--- /dev/null
@@ -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
This page took 0.050929 seconds and 4 git commands to generate.