86 lines
3.5 KiB
Systemverilog
86 lines
3.5 KiB
Systemverilog
`default_nettype none
|
|
|
|
// The Genesys 2 straps the RTL8211E-VL for auto-negotiation and PHY address 1.
|
|
// After the mandatory post-reset settling time, this controller polls PHYSR
|
|
// (register 0x11) and permits transmit only for resolved 1000 Mb/s full duplex.
|
|
module phy_init #(
|
|
parameter int unsigned CLK_HZ = 125_000_000,
|
|
parameter int unsigned SETTLE_MS = 30,
|
|
parameter int unsigned POLL_MS = 100
|
|
) (
|
|
input wire logic clk,
|
|
input wire logic rst,
|
|
input wire logic phy_reset_complete,
|
|
output logic mdio_start,
|
|
output logic mdio_write,
|
|
output logic [4:0] mdio_phy_address,
|
|
output logic [4:0] mdio_register_address,
|
|
output logic [15:0] mdio_write_data,
|
|
input wire logic mdio_busy,
|
|
input wire logic mdio_done,
|
|
input wire logic [15:0] mdio_read_data,
|
|
output logic initialization_complete,
|
|
output logic link_ready,
|
|
output logic [63:0] link_down_events
|
|
);
|
|
localparam longint unsigned SETTLE_CYCLES = (CLK_HZ / 1000) * SETTLE_MS;
|
|
localparam longint unsigned POLL_CYCLES = (CLK_HZ / 1000) * POLL_MS;
|
|
localparam int unsigned TIMER_W = $clog2(((POLL_CYCLES > SETTLE_CYCLES) ? POLL_CYCLES : SETTLE_CYCLES) + 1);
|
|
typedef enum logic [2:0] {I_WAIT_RESET, I_SETTLE, I_START, I_WAIT_MDIO, I_POLL_WAIT} istate_t;
|
|
istate_t state;
|
|
logic [TIMER_W-1:0] timer;
|
|
logic new_link_ready;
|
|
|
|
always_comb begin
|
|
mdio_write = 1'b0;
|
|
mdio_phy_address = 5'd1;
|
|
mdio_register_address = 5'h11;
|
|
mdio_write_data = 16'd0;
|
|
new_link_ready = (mdio_read_data[15:14] == 2'b10) &&
|
|
mdio_read_data[13] && mdio_read_data[11] && mdio_read_data[10];
|
|
end
|
|
|
|
always_ff @(posedge clk) begin
|
|
if (rst) begin
|
|
state <= I_WAIT_RESET;
|
|
timer <= '0;
|
|
mdio_start <= 1'b0;
|
|
initialization_complete <= 1'b0;
|
|
link_ready <= 1'b0;
|
|
link_down_events <= 64'd0;
|
|
end else begin
|
|
mdio_start <= 1'b0;
|
|
case (state)
|
|
I_WAIT_RESET: begin
|
|
link_ready <= 1'b0;
|
|
if (phy_reset_complete) begin timer <= '0; state <= I_SETTLE; end
|
|
end
|
|
I_SETTLE: begin
|
|
if (timer == SETTLE_CYCLES-1) begin timer <= '0; state <= I_START; end
|
|
else timer <= timer + {{(TIMER_W-1){1'b0}},1'b1};
|
|
end
|
|
I_START: begin
|
|
if (!mdio_busy) begin mdio_start <= 1'b1; state <= I_WAIT_MDIO; end
|
|
end
|
|
I_WAIT_MDIO: begin
|
|
if (mdio_done) begin
|
|
initialization_complete <= 1'b1;
|
|
if (link_ready && !new_link_ready)
|
|
link_down_events <= link_down_events + 64'd1;
|
|
link_ready <= new_link_ready;
|
|
timer <= '0;
|
|
state <= I_POLL_WAIT;
|
|
end
|
|
end
|
|
I_POLL_WAIT: begin
|
|
if (timer == POLL_CYCLES-1) begin timer <= '0; state <= I_START; end
|
|
else timer <= timer + {{(TIMER_W-1){1'b0}},1'b1};
|
|
end
|
|
default: state <= I_WAIT_RESET;
|
|
endcase
|
|
end
|
|
end
|
|
endmodule
|
|
|
|
`default_nettype wire
|