Files
fpga6502/fpga/ip/gTSE/T120F324_devkit/rgmii_2_rmii.v
2026-04-14 21:34:37 -07:00

206 lines
5.2 KiB
Verilog

/////////////////////////////////////////////////////////////////////////////
// _____
// / _______ Copyright (C) 2013-2020 Efinix Inc. All rights reserved.
// / / \
// / / .. /
// / / .' /
// __/ /.' /
// __ \ /
// /_/ /\ \_____/ /
// ____/ \_______/
//
// *******************************
// Revisions:
// 1.0 Initial rev
//
// *******************************
`timescale 1 ns / 1 ns
module rgmii_2_rmii (
input clk_50m, //50Mhz refclock
input rst_n,
//conduit
input [2:0] eth_speed,
//rgmii interface
input [3:0] rgmii_txd,
input rgmii_tx_ctl,
output wire [3:0] rgmii_rxd,
output wire rgmii_rx_ctl,
output reg rgmii_rxc,
//rmii interface
output wire rmii_clk,
output reg [1:0] rmii_txd,
output reg rmii_txen,
input [1:0] rmii_rxd,
input rmii_crsdv
);
wire [3:0] rxd_c;
wire rx_ctl_c;
reg [3:0] rxd_r;
reg rx_ctl_r;
reg rmii_crsdv_r, shift_en;
reg [4:0] txd_cnt, rxd_cnt;
reg [3:0] rxd_shiftreg;
reg [1:0] shift2;
reg [19:0] shift20;
reg [1:0] rx_ctl_p2;
reg [19:0] rx_ctl_p20;
assign rmii_clk = ~clk_50m; //create 180deg phaseshift
/*--------------- TX path ---------------------*/
always @(posedge clk_50m or negedge rst_n)
begin
if (!rst_n) begin
txd_cnt <= 5'd0;
end
else if (rgmii_tx_ctl) begin
if (((eth_speed == 3'h2) && txd_cnt == 5'd1) ||
((eth_speed == 3'h1) && txd_cnt == 5'd19)) begin
txd_cnt <= 5'd0;
end
else begin
txd_cnt <= txd_cnt + 5'd1;
end
end
end
always @(posedge clk_50m or negedge rst_n)
begin
if (!rst_n) begin
rmii_txen <= 1'b0;
end
else begin
rmii_txen <= rgmii_tx_ctl;
end
end
always @(posedge clk_50m or negedge rst_n)
begin
if (!rst_n) begin
rmii_txd <= 2'b00;
end
else begin
if ((eth_speed == 3'h2) && txd_cnt == 5'd0) begin
rmii_txd <= rgmii_txd[1:0];
end
else if ((eth_speed == 3'h2) && txd_cnt == 5'd1) begin
rmii_txd <= rgmii_txd[3:2];
end
if ((eth_speed == 3'h1) && txd_cnt == 5'd0) begin
rmii_txd <= rgmii_txd[1:0];
end
else if ((eth_speed == 3'h1) && txd_cnt == 5'd10) begin
rmii_txd <= rgmii_txd[3:2];
end
end
end
/*------------------ end of TX path ------------------------*/
/*------------ RX path ------------------*/
always @(posedge clk_50m or negedge rst_n)
begin
if (!rst_n) begin
rxd_cnt <= 5'd0;
end
else if (rmii_crsdv) begin
if (((eth_speed == 3'h2) && rxd_cnt == 5'd1) || ((eth_speed == 3'h1) && rxd_cnt == 5'd19)) begin
rxd_cnt <= 5'd0;
end
else begin
rxd_cnt <= rxd_cnt + 5'd1;
end
end
end
always @(posedge clk_50m or negedge rst_n)
begin
if (!rst_n) begin
rxd_shiftreg <= 4'd0;
end
else if (rmii_crsdv) begin
if (eth_speed == 3'h2 || ((eth_speed == 3'h1) && (rxd_cnt == 5'd0 || rxd_cnt == 5'd10))) begin
rxd_shiftreg <= {rmii_rxd, rxd_shiftreg[3:2]};
end
end
end
always @(posedge clk_50m or negedge rst_n)
begin
if (!rst_n) begin
shift2 <= 2'b1;
shift20 <= 20'b1;
end
else begin
shift2 <= {shift2[0],shift2[1]};
shift20 <= {shift20[18:0],shift20[19]};
end
end
always @(posedge clk_50m or negedge rst_n)
begin
if (!rst_n) begin
rgmii_rxc <= 1'b0;
end
else begin
if ((eth_speed == 3'h2 && shift2[1]) || (eth_speed == 3'h1 && (shift20[10]))) begin
rgmii_rxc <= 1'b1;
end
else if ((eth_speed == 3'h2 && shift2[0]) || (eth_speed == 3'h1 && (shift20[0]))) begin
rgmii_rxc <= 1'b0;
end
end
end
always @(posedge clk_50m or negedge rst_n)
begin
if (!rst_n) begin
rx_ctl_p2 <= 2'd0;
rx_ctl_p20 <= 20'd0;
end
else begin
rx_ctl_p2 <= {rmii_crsdv , rx_ctl_p2[1]};
rx_ctl_p20 <= {rmii_crsdv, rx_ctl_p20[19:1]};
end
end
/*---- shift rxd & rx_ctl so that they are not edge align with rgmii_rxc ----*/
assign rxd_c = (rxd_cnt == 5'd0) ? rxd_shiftreg : rxd_r;
assign rx_ctl_c = (eth_speed == 3'h2) ? rx_ctl_p2[0] : rx_ctl_p20[0];
always @(posedge clk_50m or negedge rst_n)
begin
if (!rst_n) begin
rxd_r <= 4'd0;
rx_ctl_r <= 1'd0;
rmii_crsdv_r <= 1'd0;
end
else begin
rxd_r <= rxd_c;
rx_ctl_r <= rx_ctl_c;
rmii_crsdv_r <= rmii_crsdv;
end
end
always @(posedge clk_50m or negedge rst_n)
begin
if (!rst_n) begin
shift_en <= 1'd0;
end // to detect if rmii_crsdv assert at the posedge of rgmii_rxc, delay rgmii_rxd & rgmii_rx_ctl if they are aligned with rgmii_rxc
else if (rmii_crsdv && ~rmii_crsdv_r) begin
if (((eth_speed == 3'h2) && shift2[0]) || ((eth_speed == 3'h1) && shift20[11])) begin
shift_en <= 1'd1;
end
else begin
shift_en <= 1'd0;
end
end
end
assign rgmii_rxd = shift_en ? rxd_r : rxd_c;
assign rgmii_rx_ctl = shift_en ? rx_ctl_r : rx_ctl_c;
/*--------------------------------------------------------*/
/*------------------ end of RX path ------------------------*/
endmodule