eth_phy_10g_rx_ber_mon_code
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* 10G Ethernet PHY BER monitor
*/
//! Modulo que controla el bit error rate y activa dicha señal cuando hay más de 15 sync headers validos en 125us
module eth_phy_10g_rx_ber_mon #
(
parameter HDR_WIDTH = 2, //! Ancho del header
parameter COUNT_125US = 125000/10 //! Contador de 125 us
)
(
input wire clk, //! Señal de clock
input wire rst, //! Señal de reset
/*
* ! SERDES interface
*/
input wire [HDR_WIDTH-1:0] serdes_rx_hdr, //! Serdes sync header del receptor
/*
* ! Status
*/
output wire rx_high_ber //! Tasa de error de bit
);
// Bus width assertions
initial begin
if (HDR_WIDTH != 2) begin
$error("Error: HDR_WIDTH must be 2");
$finish;
end
end
parameter COUNT_WIDTH = $clog2($rtoi(COUNT_125US)); //! Determina la cantidad de bits necesarios para representar COUNT_125US
localparam [1:0] //! Sync headers de sincronizacion de bloques de datos y control
SYNC_DATA = 2'b10,
SYNC_CTRL = 2'b01;
reg [COUNT_WIDTH-1:0] time_count_reg = COUNT_125US, time_count_next; //! Registro de contador de tiempo, se inicializa en COUNT_125US.
reg [3:0] ber_count_reg = 4'd0, ber_count_next; //! Registro de contador de errores de header. Máximo 4 bits
reg rx_high_ber_reg = 1'b0, rx_high_ber_next; //! Registro que indica una ber alta.
assign rx_high_ber = rx_high_ber_reg;
//! Verifica si hay mas de 15 sync headers validos en un intervalo de 125us
always @* begin
if (time_count_reg > 0) begin // si la cuenta ya empezo
time_count_next = time_count_reg-1; // resta en uno el valor del contador de tiempo
end else begin // si termino la cuenta
time_count_next = time_count_reg; // permanece el valor del contador de tiepo
end
ber_count_next = ber_count_reg; // se asigna el valor de ber_count en el proximo ciclo
rx_high_ber_next = rx_high_ber_reg; // se asigna el valor de rx_high_ber en el proximo ciclo
if (serdes_rx_hdr == SYNC_CTRL || serdes_rx_hdr == SYNC_DATA) begin // si los header son validos
//! Valid header
if (ber_count_reg != 4'd15) begin // si la cuenta de ber no alcanzó su valor límite 15
if (time_count_reg == 0) begin // si termino la cuenta
rx_high_ber_next = 1'b0; // no hay una tasa alta de error de bit
end
end
end else begin // si el header no es valido
//! Invalid header
if (ber_count_reg == 4'd15) begin // si la cuenta de ber alcanzó su valor límite de 15
rx_high_ber_next = 1'b1; // hay tasa alta de error de bit
end else begin // si la cuenta de ber no alcanzó su valor límite de 15
ber_count_next = ber_count_reg + 1; // se incrementa en uno la cuenta de ber
if (time_count_reg == 0) begin // si terminó la cuenta
rx_high_ber_next = 1'b0; // no hay tasa alta de error de bit
end
end
end
if (time_count_reg == 0) begin // si terminó la cuenta
// 125 us timer expired
ber_count_next = 4'd0; // se resetea la cuenta de ber
time_count_next = COUNT_125US; // se resetea el timer a 125 us
end
end
always @(posedge clk) begin //! En cada flanco positivo de clock se actualizan los valores de los registros y se verifica la señal de reinicio
time_count_reg <= time_count_next;
ber_count_reg <= ber_count_next;
rx_high_ber_reg <= rx_high_ber_next;
if (rst) begin
time_count_reg <= COUNT_125US;
ber_count_reg <= 4'd0;
rx_high_ber_reg <= 1'b0;
end
end
endmodule
`resetall