206 lines
5.2 KiB
Verilog
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 |