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
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
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