ethernet/rtl/mii_io_tx.v

120 lines
2.0 KiB
Verilog

// SPDX-License-Identifier: AGPL-3.0-Only
/*
* Copyright (C) 2022 Sean Anderson <seanga2@gmail.com>
*/
`include "common.vh"
`include "io.vh"
module mii_io_tx (
input clk,
input isolate,
/* On-chip */
output reg ce,
output reg enable,
output reg err,
output reg [3:0] data,
/* Off-chip */
output reg tx_clk,
input tx_en,
input tx_er,
input [3:0] txd
);
reg ce_next, raw_enable;
reg tx_clk_p_next, tx_clk_n, tx_clk_n_next;
reg [2:0] counter, counter_next;
/* I have no idea why we need to use initial... */
initial counter = 4;
always @(*) begin
tx_clk_p_next = 0;
tx_clk_n_next = 0;
ce_next = 0;
counter_next = counter - 1;
case (counter)
4, 3: begin
tx_clk_p_next = 1;
tx_clk_n_next = 1;
end
2: tx_clk_p_next = 1;
1: ;
0: begin
ce_next = 1;
counter_next = 4;
end
endcase
enable = raw_enable && !isolate;
end
always @(posedge clk) begin
counter <= counter_next;
tx_clk_n <= tx_clk_n_next;
ce <= ce_next;
end
`ifdef SYNTHESIS
SB_IO #(
.PIN_TYPE(`PIN_OUTPUT_ENABLE | `PIN_OUTPUT_DDR)
) tx_clk_pin (
.PACKAGE_PIN(tx_clk),
.OUTPUT_CLK(clk),
.OUTPUT_ENABLE(!isolate),
.D_OUT_0(tx_clk_p_next),
.D_OUT_1(tx_clk_n)
);
SB_IO #(
.PIN_TYPE(`PIN_INPUT_REGISTERED)
) tx_en_pin (
.PACKAGE_PIN(tx_en),
.CLOCK_ENABLE(ce_next),
.INPUT_CLK(clk),
.D_IN_0(raw_enable)
);
SB_IO #(
.PIN_TYPE(`PIN_INPUT_REGISTERED)
) tx_er_pin (
.PACKAGE_PIN(tx_er),
.CLOCK_ENABLE(ce_next),
.INPUT_CLK(clk),
.D_IN_0(err)
);
genvar i;
generate for (i = 0; i < 4; i = i + 1) begin
SB_IO #(
.PIN_TYPE(`PIN_INPUT_REGISTERED)
) txd_pin (
.PACKAGE_PIN(txd[i]),
.CLOCK_ENABLE(ce_next),
.INPUT_CLK(clk),
.D_IN_0(data[i])
);
end
endgenerate
`else
always @(posedge clk) begin
if (ce_next) begin
raw_enable <= tx_en;
err <= tx_er;
data <= txd;
end
end
always @(posedge clk, negedge clk) begin
if (isolate)
tx_clk <= 1'bz;
else
tx_clk <= clk ? tx_clk_p_next : tx_clk_n;
end
`endif
`DUMP(0)
endmodule