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
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
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;
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
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;
end else if (pktclear) begin
pktrdy <= 0;
wr <= 0;
- else
+ end else
wr <= 0;
endmodule
--- /dev/null
+ 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