eth: Use signal sync module for internal MAC pause handling

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2025-02-25 16:27:37 -08:00
parent 84fb93b5c3
commit 64c1cb1e39
7 changed files with 75 additions and 170 deletions

View File

@@ -9,3 +9,4 @@ taxi_mac_pause_ctrl_tx.sv
taxi_mac_pause_ctrl_rx.sv taxi_mac_pause_ctrl_rx.sv
../lfsr/taxi_lfsr.sv ../lfsr/taxi_lfsr.sv
../axis/taxi_axis_if.sv ../axis/taxi_axis_if.sv
../sync/taxi_sync_signal.sv

View File

@@ -370,56 +370,36 @@ if (MAC_CTRL_EN) begin : mac_ctrl
wire [MCF_PARAMS_SIZE*8-1:0] rx_mcf_params; wire [MCF_PARAMS_SIZE*8-1:0] rx_mcf_params;
// terminate LFC pause requests from RX internally on TX side // terminate LFC pause requests from RX internally on TX side
wire tx_pause_req_int; wire tx_pause_req_int;
wire rx_lfc_ack_int; wire rx_lfc_ack_int;
reg tx_lfc_req_sync_reg_1 = 1'b0; wire rx_lfc_req_sync;
reg tx_lfc_req_sync_reg_2 = 1'b0;
reg tx_lfc_req_sync_reg_3 = 1'b0;
always @(posedge rx_clk or posedge rx_rst) begin taxi_sync_signal #(
if (rx_rst) begin .WIDTH(1),
tx_lfc_req_sync_reg_1 <= 1'b0; .N(2)
end else begin )
tx_lfc_req_sync_reg_1 <= rx_lfc_req; rx_lfc_req_sync_inst (
end .clk(tx_clk),
end .in(rx_lfc_req),
.out(rx_lfc_req_sync)
);
always @(posedge tx_clk or posedge tx_rst) begin wire tx_pause_ack_sync;
if (tx_rst) begin
tx_lfc_req_sync_reg_2 <= 1'b0;
tx_lfc_req_sync_reg_3 <= 1'b0;
end else begin
tx_lfc_req_sync_reg_2 <= tx_lfc_req_sync_reg_1;
tx_lfc_req_sync_reg_3 <= tx_lfc_req_sync_reg_2;
end
end
reg rx_lfc_ack_sync_reg_1 = 1'b0; taxi_sync_signal #(
reg rx_lfc_ack_sync_reg_2 = 1'b0; .WIDTH(1),
reg rx_lfc_ack_sync_reg_3 = 1'b0; .N(2)
)
tx_pause_ack_sync_inst (
.clk(rx_clk),
.in(tx_lfc_pause_en && tx_pause_ack),
.out(tx_pause_ack_sync)
);
always @(posedge tx_clk or posedge tx_rst) begin assign tx_pause_req_int = tx_pause_req || (tx_lfc_pause_en && rx_lfc_req_sync);
if (tx_rst) begin
rx_lfc_ack_sync_reg_1 <= 1'b0;
end else begin
rx_lfc_ack_sync_reg_1 <= tx_lfc_pause_en ? tx_pause_ack : 0;
end
end
always @(posedge rx_clk or posedge rx_rst) begin assign rx_lfc_ack_int = rx_lfc_ack || tx_pause_ack_sync;
if (rx_rst) begin
rx_lfc_ack_sync_reg_2 <= 1'b0;
rx_lfc_ack_sync_reg_3 <= 1'b0;
end else begin
rx_lfc_ack_sync_reg_2 <= rx_lfc_ack_sync_reg_1;
rx_lfc_ack_sync_reg_3 <= rx_lfc_ack_sync_reg_2;
end
end
assign tx_pause_req_int = tx_pause_req || (tx_lfc_pause_en ? tx_lfc_req_sync_reg_3 : 0);
assign rx_lfc_ack_int = rx_lfc_ack || rx_lfc_ack_sync_reg_3;
taxi_mac_ctrl_tx #( taxi_mac_ctrl_tx #(
.ID_W(s_axis_tx.ID_W), .ID_W(s_axis_tx.ID_W),

View File

@@ -7,3 +7,4 @@ taxi_mac_pause_ctrl_tx.sv
taxi_mac_pause_ctrl_rx.sv taxi_mac_pause_ctrl_rx.sv
../lfsr/taxi_lfsr.sv ../lfsr/taxi_lfsr.sv
../axis/taxi_axis_if.sv ../axis/taxi_axis_if.sv
../sync/taxi_sync_signal.sv

View File

@@ -283,56 +283,36 @@ if (MAC_CTRL_EN) begin : mac_ctrl
wire [MCF_PARAMS_SIZE*8-1:0] rx_mcf_params; wire [MCF_PARAMS_SIZE*8-1:0] rx_mcf_params;
// terminate LFC pause requests from RX internally on TX side // terminate LFC pause requests from RX internally on TX side
wire tx_pause_req_int; wire tx_pause_req_int;
wire rx_lfc_ack_int; wire rx_lfc_ack_int;
reg tx_lfc_req_sync_reg_1 = 1'b0; wire rx_lfc_req_sync;
reg tx_lfc_req_sync_reg_2 = 1'b0;
reg tx_lfc_req_sync_reg_3 = 1'b0;
always @(posedge rx_clk or posedge rx_rst) begin taxi_sync_signal #(
if (rx_rst) begin .WIDTH(1),
tx_lfc_req_sync_reg_1 <= 1'b0; .N(2)
end else begin )
tx_lfc_req_sync_reg_1 <= rx_lfc_req; rx_lfc_req_sync_inst (
end .clk(tx_clk),
end .in(rx_lfc_req),
.out(rx_lfc_req_sync)
);
always @(posedge tx_clk or posedge tx_rst) begin wire tx_pause_ack_sync;
if (tx_rst) begin
tx_lfc_req_sync_reg_2 <= 1'b0;
tx_lfc_req_sync_reg_3 <= 1'b0;
end else begin
tx_lfc_req_sync_reg_2 <= tx_lfc_req_sync_reg_1;
tx_lfc_req_sync_reg_3 <= tx_lfc_req_sync_reg_2;
end
end
reg rx_lfc_ack_sync_reg_1 = 1'b0; taxi_sync_signal #(
reg rx_lfc_ack_sync_reg_2 = 1'b0; .WIDTH(1),
reg rx_lfc_ack_sync_reg_3 = 1'b0; .N(2)
)
tx_pause_ack_sync_inst (
.clk(rx_clk),
.in(tx_lfc_pause_en && tx_pause_ack),
.out(tx_pause_ack_sync)
);
always @(posedge tx_clk or posedge tx_rst) begin assign tx_pause_req_int = tx_pause_req || (tx_lfc_pause_en && rx_lfc_req_sync);
if (tx_rst) begin
rx_lfc_ack_sync_reg_1 <= 1'b0;
end else begin
rx_lfc_ack_sync_reg_1 <= tx_lfc_pause_en ? tx_pause_ack : 0;
end
end
always @(posedge rx_clk or posedge rx_rst) begin assign rx_lfc_ack_int = rx_lfc_ack || tx_pause_ack_sync;
if (rx_rst) begin
rx_lfc_ack_sync_reg_2 <= 1'b0;
rx_lfc_ack_sync_reg_3 <= 1'b0;
end else begin
rx_lfc_ack_sync_reg_2 <= rx_lfc_ack_sync_reg_1;
rx_lfc_ack_sync_reg_3 <= rx_lfc_ack_sync_reg_2;
end
end
assign tx_pause_req_int = tx_pause_req || (tx_lfc_pause_en ? tx_lfc_req_sync_reg_3 : 0);
assign rx_lfc_ack_int = rx_lfc_ack || rx_lfc_ack_sync_reg_3;
taxi_mac_ctrl_tx #( taxi_mac_ctrl_tx #(
.ID_W(s_axis_tx.ID_W), .ID_W(s_axis_tx.ID_W),

View File

@@ -5,3 +5,4 @@ taxi_mac_ctrl_tx.sv
taxi_mac_ctrl_rx.sv taxi_mac_ctrl_rx.sv
taxi_mac_pause_ctrl_tx.sv taxi_mac_pause_ctrl_tx.sv
taxi_mac_pause_ctrl_rx.sv taxi_mac_pause_ctrl_rx.sv
../sync/taxi_sync_signal.sv

View File

@@ -305,56 +305,36 @@ if (MAC_CTRL_EN) begin : mac_ctrl
wire [MCF_PARAMS_SIZE*8-1:0] rx_mcf_params; wire [MCF_PARAMS_SIZE*8-1:0] rx_mcf_params;
// terminate LFC pause requests from RX internally on TX side // terminate LFC pause requests from RX internally on TX side
wire tx_pause_req_int; wire tx_pause_req_int;
wire rx_lfc_ack_int; wire rx_lfc_ack_int;
reg tx_lfc_req_sync_reg_1 = 1'b0; wire rx_lfc_req_sync;
reg tx_lfc_req_sync_reg_2 = 1'b0;
reg tx_lfc_req_sync_reg_3 = 1'b0;
always @(posedge rx_clk or posedge rx_rst) begin taxi_sync_signal #(
if (rx_rst) begin .WIDTH(1),
tx_lfc_req_sync_reg_1 <= 1'b0; .N(2)
end else begin )
tx_lfc_req_sync_reg_1 <= rx_lfc_req; rx_lfc_req_sync_inst (
end .clk(tx_clk),
end .in(rx_lfc_req),
.out(rx_lfc_req_sync)
);
always @(posedge tx_clk or posedge tx_rst) begin wire tx_pause_ack_sync;
if (tx_rst) begin
tx_lfc_req_sync_reg_2 <= 1'b0;
tx_lfc_req_sync_reg_3 <= 1'b0;
end else begin
tx_lfc_req_sync_reg_2 <= tx_lfc_req_sync_reg_1;
tx_lfc_req_sync_reg_3 <= tx_lfc_req_sync_reg_2;
end
end
reg rx_lfc_ack_sync_reg_1 = 1'b0; taxi_sync_signal #(
reg rx_lfc_ack_sync_reg_2 = 1'b0; .WIDTH(1),
reg rx_lfc_ack_sync_reg_3 = 1'b0; .N(2)
)
tx_pause_ack_sync_inst (
.clk(rx_clk),
.in(tx_lfc_pause_en && tx_pause_ack),
.out(tx_pause_ack_sync)
);
always @(posedge tx_clk or posedge tx_rst) begin assign tx_pause_req_int = tx_pause_req || (tx_lfc_pause_en && rx_lfc_req_sync);
if (tx_rst) begin
rx_lfc_ack_sync_reg_1 <= 1'b0;
end else begin
rx_lfc_ack_sync_reg_1 <= tx_lfc_pause_en ? tx_pause_ack : 0;
end
end
always @(posedge rx_clk or posedge rx_rst) begin assign rx_lfc_ack_int = rx_lfc_ack || tx_pause_ack_sync;
if (rx_rst) begin
rx_lfc_ack_sync_reg_2 <= 1'b0;
rx_lfc_ack_sync_reg_3 <= 1'b0;
end else begin
rx_lfc_ack_sync_reg_2 <= rx_lfc_ack_sync_reg_1;
rx_lfc_ack_sync_reg_3 <= rx_lfc_ack_sync_reg_2;
end
end
assign tx_pause_req_int = tx_pause_req || (tx_lfc_pause_en ? tx_lfc_req_sync_reg_3 : 0);
assign rx_lfc_ack_int = rx_lfc_ack || rx_lfc_ack_sync_reg_3;
taxi_mac_ctrl_tx #( taxi_mac_ctrl_tx #(
.ID_W(s_axis_tx.ID_W), .ID_W(s_axis_tx.ID_W),

View File

@@ -1,38 +0,0 @@
# SPDX-License-Identifier: CERN-OHL-S-2.0
#
# Copyright (c) 2019-2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
# Ethernet MAC timing constraints
foreach inst [get_cells -hier -regexp -filter {(ORIG_REF_NAME =~ "taxi_eth_mac_(1g|10g)(__\w+__\d+)?" ||
REF_NAME =~ "taxi_eth_mac_(1g|10g)(__\w+__\d+)?")}] {
puts "Inserting timing constraints for Ethernet MAC instance $inst"
set sync_ffs [get_cells -quiet -hier -regexp ".*/mac_ctrl.tx_lfc_req_sync_reg_\[1234\]_reg" -filter "PARENT == $inst"]
if {[llength $sync_ffs]} {
set_property ASYNC_REG TRUE $sync_ffs
set src_clk [get_clocks -of_objects [get_pins $inst/mac_ctrl.tx_lfc_req_sync_reg_1_reg/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 1.0}]
set_max_delay -from [get_cells $inst/mac_ctrl.tx_lfc_req_sync_reg_1_reg] -to [get_cells $inst/mac_ctrl.tx_lfc_req_sync_reg_2_reg] -datapath_only $src_clk_period
}
set sync_ffs [get_cells -quiet -hier -regexp ".*/mac_ctrl.rx_lfc_ack_sync_reg_\[1234\]_reg" -filter "PARENT == $inst"]
if {[llength $sync_ffs]} {
set_property ASYNC_REG TRUE $sync_ffs
set src_clk [get_clocks -of_objects [get_pins $inst/mac_ctrl.rx_lfc_ack_sync_reg_1_reg/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 1.0}]
set_max_delay -from [get_cells $inst/mac_ctrl.rx_lfc_ack_sync_reg_1_reg] -to [get_cells $inst/mac_ctrl.rx_lfc_ack_sync_reg_2_reg] -datapath_only $src_clk_period
}
}