ethernet/rtl/mii_io_rx.v

125 lines
2.2 KiB
Verilog

// SPDX-License-Identifier: AGPL-3.0-Only OR CERN-OHL-S-2.0
/*
* Copyright (C) 2022 Sean Anderson <seanga2@gmail.com>
*/
`include "common.vh"
`include "io.vh"
module mii_io_rx (
input clk,
input isolate,
/* On-chip */
input ce,
input valid,
input err,
input [3:0] data,
/* Off-chip */
output reg rx_clk,
output reg rx_dv,
output reg rx_er,
output reg [3:0] rxd
);
reg rx_clk_p_next, rx_clk_n, rx_clk_n_next;
reg [1:0] state, state_next;
initial state = HIGH;
localparam LOW = 2;
localparam RISING = 1;
localparam HIGH = 0;
always @(*) begin
if (ce) begin
state_next = LOW;
rx_clk_p_next = 0;
rx_clk_n_next = 0;
end else if (state == LOW) begin
state_next = RISING;
rx_clk_p_next = 0;
rx_clk_n_next = 0;
end else if (state == RISING) begin
state_next = HIGH;
rx_clk_p_next = 0;
rx_clk_n_next = 1;
end else begin
state_next = HIGH;
rx_clk_p_next = 1;
rx_clk_n_next = 1;
end
end
always @(posedge clk) begin
state <= state_next;
rx_clk_n <= rx_clk_n_next;
end
`ifdef SYNTHESIS
SB_IO #(
.PIN_TYPE(`PIN_OUTPUT_ENABLE | `PIN_OUTPUT_DDR)
) rx_clk_pin (
.PACKAGE_PIN(rx_clk),
.OUTPUT_CLK(clk),
.OUTPUT_ENABLE(!isolate),
.D_OUT_0(rx_clk_p_next),
.D_OUT_1(rx_clk_n)
);
SB_IO #(
.PIN_TYPE(`PIN_OUTPUT_ENABLE | `PIN_OUTPUT_REGISTERED)
) rx_dv_pin (
.PACKAGE_PIN(rx_dv),
.CLOCK_ENABLE(ce),
.OUTPUT_ENABLE(!isolate),
.OUTPUT_CLK(clk),
.D_OUT_0(valid)
);
SB_IO #(
.PIN_TYPE(`PIN_OUTPUT_ENABLE | `PIN_OUTPUT_REGISTERED)
) rx_er_pin (
.PACKAGE_PIN(rx_er),
.CLOCK_ENABLE(ce),
.OUTPUT_ENABLE(!isolate),
.OUTPUT_CLK(clk),
.D_OUT_0(err)
);
genvar i;
generate for (i = 0; i < 4; i = i + 1) begin
SB_IO #(
.PIN_TYPE(`PIN_OUTPUT_ENABLE | `PIN_OUTPUT_REGISTERED)
) rxd_pin (
.PACKAGE_PIN(rxd[i]),
.CLOCK_ENABLE(ce),
.OUTPUT_ENABLE(!isolate),
.OUTPUT_CLK(clk),
.D_OUT_0(data[i])
);
end
endgenerate
`else
always @(posedge clk) begin
if (isolate) begin
rx_dv <= 1'bz;
rx_er <= 1'bz;
rxd <= 4'bz;
end else if (ce) begin
rx_dv <= valid;
rx_er <= err;
rxd <= data;
end
end
always @(posedge clk, negedge clk) begin
if (isolate)
rx_clk <= 1'bz;
else
rx_clk <= clk ? rx_clk_p_next : rx_clk_n;
end
`endif
endmodule