summaryrefslogtreecommitdiffhomepage
path: root/src/switch.v
diff options
context:
space:
mode:
Diffstat (limited to 'src/switch.v')
-rw-r--r--src/switch.v300
1 files changed, 105 insertions, 195 deletions
diff --git a/src/switch.v b/src/switch.v
index 98aec4a..fa6d75e 100644
--- a/src/switch.v
+++ b/src/switch.v
@@ -1,7 +1,8 @@
/*
- * switch.v
+ * switch.v
*
- * Copyright 2018, 2019, 2020, 2021 Mind Chasers Inc.
+ * Copyright 2024, 2025 Private Island Networks Inc.
+ * Copyright 2018 Mind Chasers Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,113 +16,104 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * function: Soft Ethernet Switch
+ * function: switch packet paths from RX to TX for LF_A_V01
*
*/
-`timescale 1ns /10ps
-
-module switch(
+module switch #(parameter NUM_PHYS=3)
+(
input rstn,
input clk,
// PHY status
- input [3:0] phy_up,
- input [3:0] mode_100Mbit,
+ input [NUM_PHYS-1:0] phy_up,
+ input [NUM_PHYS-1:0] mode_100Mbit,
// FIFO input data from RX FIFOs
input [8:0] rx_d_01,
input [8:0] rx_d_02,
- input [8:0] rx_d_03,
+ input [8:0] rx_d_0u,
input [8:0] rx_d_10,
input [8:0] rx_d_12,
- input [8:0] rx_d_13,
input [8:0] rx_d_20,
input [8:0] rx_d_21,
- input [8:0] rx_d_23,
- input [8:0] rx_d_2u,
- input [8:0] rx_d_30,
- input [8:0] rx_d_31,
- input [8:0] rx_d_32,
- input [8:0] rx_d_u2,
+ input [8:0] rx_d_u0,
// RX FIFO read enables
- output reg rx_fifo_re_01, rx_fifo_re_02, rx_fifo_re_03,
- output reg rx_fifo_re_10, rx_fifo_re_12, rx_fifo_re_13,
- output reg rx_fifo_re_20, rx_fifo_re_21, rx_fifo_re_23, rx_fifo_re_2u,
- output reg rx_fifo_re_30, rx_fifo_re_31, rx_fifo_re_32,
- output reg rx_fifo_re_u2,
+ output reg rx_fifo_re_01, rx_fifo_re_02, rx_fifo_re_0u,
+ output reg rx_fifo_re_10, rx_fifo_re_12,
+ output reg rx_fifo_re_20, rx_fifo_re_21,
+ output reg rx_fifo_re_u0,
// RX FIFO Empty flags
- input rx_fifo_empty_01, rx_fifo_empty_02, rx_fifo_empty_03,
- input rx_fifo_empty_10, rx_fifo_empty_12, rx_fifo_empty_13,
- input rx_fifo_empty_20, rx_fifo_empty_21, rx_fifo_empty_23, rx_fifo_empty_2u,
- input rx_fifo_empty_30, rx_fifo_empty_31, rx_fifo_empty_32,
- input rx_fifo_empty_u2,
+ input rx_fifo_empty_01, rx_fifo_empty_02, rx_fifo_empty_0u,
+ input rx_fifo_empty_10, rx_fifo_empty_12,
+ input rx_fifo_empty_20, rx_fifo_empty_21,
+ input rx_fifo_empty_u0,
+
+ input [NUM_PHYS-1:0] rx_wr_done,
// RX Byte Count
- input [3:0] rx_wr_done,
input [10:0] rx0_byte_cnt,
input [10:0] rx1_byte_cnt,
input [10:0] rx2_byte_cnt,
- input [10:0] rx3_byte_cnt,
+ input [10:0] rxu_byte_cnt,
// TX FIFO output from internal muxes
output reg [8:0] tx_d0,
output reg [8:0] tx_d1,
output reg [8:0] tx_d2,
- output reg [8:0] tx_d3,
output [8:0] tx_du,
// TX FIFO read enable inputs (need to route to RX output FIFOs)
- input [3:0] tx_fifo_re,
+ input [NUM_PHYS-1:0] tx_fifo_re,
output reg tx_fifo_we_u,
// TX FIFO Empty Flags (need to route to RX output FIFOs)
- output reg [3:0] tx_fifo_empty,
+ output reg [NUM_PHYS-1:0] tx_fifo_empty,
// TX modes for the PHYs and uc
output reg [2:0] tx_mode0,
output reg [2:0] tx_mode1,
output reg [2:0] tx_mode2,
- output reg [2:0] tx_mode3,
- output reg tx_modeu,
+ output reg [2:0] tx_modeu,
// TX byte cnt
output reg [10:0] tx0_byte_cnt,
output reg [10:0] tx1_byte_cnt,
output reg [10:0] tx2_byte_cnt,
- output reg [10:0] tx3_byte_cnt,
- // TX Source Select
- output reg [2:0] tx_src_sel0,
- output reg [2:0] tx_src_sel1,
- output reg [2:0] tx_src_sel2,
- output reg [2:0] tx_src_sel3,
+ output reg [2:0] tx0_src_sel,
+ output reg [2:0] tx1_src_sel,
+ output reg [2:0] tx2_src_sel,
// TX state machine done flag
- input [3:0] tx_f,
+ input [NUM_PHYS-1:0] tx_f,
// TX custom packet
input tx_custom
);
+
+
// IPG for Port 0
wire ipg_met;
reg [6:0] ipg_cnt;
-reg [3:0] fr_100mbit_cnt;
-reg i_tx_fifo_we_u;
+reg rx_fifo_empty_u0_m1, rx_fifo_empty_u0_m2;
-reg [10:0] i_rx0_byte_cnt, i_rx1_byte_cnt, i_rx2_byte_cnt, i_rx3_byte_cnt;
+reg [3:0] fr_100mbit_cnt;
+reg i_tx_fifo_we_u;
+reg [10:0] i_rx0_byte_cnt, i_rx1_byte_cnt, i_rx2_byte_cnt;
+
+`define INCLUDED
`include "ethernet_params.v"
-`include "sgmii_params.v"
+`undef INCLUDED
localparam SEL_PHY0 = 3'b000,
SEL_PHY1 = 3'b001,
SEL_PHY2 = 3'b010,
- SEL_PHY3 = 3'b011,
SEL_UC = 3'b111;
@@ -144,12 +136,6 @@ always @(posedge clk, negedge rstn)
else if ( rx_wr_done[2])
i_rx2_byte_cnt <= rx2_byte_cnt;
-always @(posedge clk, negedge rstn)
- if ( !rstn )
- i_rx3_byte_cnt <= 'h0;
- else if ( rx_wr_done[3])
- i_rx3_byte_cnt <= rx3_byte_cnt;
-
assign ipg_met = ipg_cnt >= IPG ? 1'b1 : 1'b0;
/* free running 100Mbit counter */
@@ -159,7 +145,7 @@ always @(posedge clk, negedge rstn)
else if ( fr_100mbit_cnt == 4'd9 )
fr_100mbit_cnt <= 4'd0;
else
- fr_100mbit_cnt <= fr_100mbit_cnt + 1;
+ fr_100mbit_cnt <= fr_100mbit_cnt + 1'b1;
/* IPG counter */
always @(posedge clk, negedge rstn)
@@ -170,16 +156,28 @@ always @(posedge clk, negedge rstn)
else if ( mode_100Mbit[0] && fr_100mbit_cnt == 4'd9 && !ipg_met )
ipg_cnt <= ipg_cnt + 1;
else if ( !mode_100Mbit[0] && !ipg_met )
- ipg_cnt <= ipg_cnt + 1;
+ ipg_cnt <= ipg_cnt + 1'b1;
+
+
+// Transfer to the pclk domain
+always @(posedge clk, negedge rstn)
+ if ( !rstn ) begin
+ rx_fifo_empty_u0_m1 <= 1'b1;
+ rx_fifo_empty_u0_m2 <= 1'b1;
+ end
+ else begin
+ rx_fifo_empty_u0_m1 <= rx_fifo_empty_u0;
+ rx_fifo_empty_u0_m2 <= rx_fifo_empty_u0_m1;
+ end
// TX0 Switch Logic
-// Possible sources: 1, 2
+// Possible sources: u, 1, 2
always @(posedge clk, negedge rstn)
if ( !rstn )
begin
tx_mode0 <= TX_MODE_AN;
- tx_src_sel0 <= SEL_PHY1;
+ tx0_src_sel <= SEL_PHY1;
tx0_byte_cnt <= 'h0;
end
else if ( tx_f[0] )
@@ -192,24 +190,34 @@ always @(posedge clk, negedge rstn)
tx_mode0 <= TX_MODE_AN;
else if ( !ipg_met )
tx_mode0 <= TX_MODE_IDLE;
- else if (tx_src_sel0==SEL_PHY1 && !rx_fifo_empty_20 )
+ else if (!rx_fifo_empty_u0_m2 ) // controller has data
begin
tx_mode0 <= TX_MODE_XMT_CUSTOM;
- tx_src_sel0 <= SEL_PHY2;
+ tx0_src_sel <= SEL_UC;
+ tx0_byte_cnt <= rxu_byte_cnt;
+ end
+`ifdef PHY2_PRESENT
+ else if (tx0_src_sel==SEL_PHY1 && !rx_fifo_empty_20 )
+ begin
+ tx_mode0 <= TX_MODE_XMT_PKT;
+ tx0_src_sel <= SEL_PHY2;
tx0_byte_cnt <= i_rx2_byte_cnt;
end
+`endif
else if (!rx_fifo_empty_10 )
begin
tx_mode0 <= TX_MODE_XMT_PKT;
- tx_src_sel0 <= SEL_PHY1;
+ tx0_src_sel <= SEL_PHY1;
tx0_byte_cnt <= i_rx1_byte_cnt;
end
+`ifdef PHY2_PRESENT
else if (!rx_fifo_empty_20 )
begin
- tx_mode0 <= TX_MODE_XMT_CUSTOM;
- tx_src_sel0 <= SEL_PHY2;
+ tx_mode0 <= TX_MODE_XMT_PKT;
+ tx0_src_sel <= SEL_PHY2;
tx0_byte_cnt <= i_rx2_byte_cnt;
end
+`endif
TX_MODE_XMT_PKT:
if ( !phy_up[0] )
tx_mode0 <= TX_MODE_AN;
@@ -218,13 +226,14 @@ always @(posedge clk, negedge rstn)
default: tx_mode0 <= TX_MODE_IDLE;
endcase
+
// TX0 data mux
always @(*) begin
- case(tx_src_sel0)
+ case(tx0_src_sel)
SEL_PHY0: tx_d0 = 9'h000;
SEL_PHY1: tx_d0 = rx_d_10;
SEL_PHY2: tx_d0 = rx_d_20;
- SEL_UC: tx_d0 = 9'h000;
+ SEL_UC: tx_d0 = rx_d_u0;
default: tx_d0 = 9'h000;
endcase
end
@@ -233,31 +242,31 @@ end
always @(*) begin
rx_fifo_re_10 = 1'b0;
rx_fifo_re_20 = 1'b0;
- rx_fifo_re_30 = 1'b0;
- case(tx_src_sel0)
+ rx_fifo_re_u0 = 1'b0;
+ case(tx0_src_sel)
SEL_PHY1: rx_fifo_re_10 = tx_fifo_re[0];
SEL_PHY2: rx_fifo_re_20 = tx_fifo_re[0];
- SEL_PHY3: rx_fifo_re_30 = tx_fifo_re[0];
+ SEL_UC: rx_fifo_re_u0 = tx_fifo_re[0];
endcase
end
// TX0 FIFO Empty Routing
always @(*) begin
- case(tx_src_sel0)
+ case(tx0_src_sel)
SEL_PHY1: tx_fifo_empty[0] = rx_fifo_empty_10;
SEL_PHY2: tx_fifo_empty[0] = rx_fifo_empty_20;
- SEL_PHY3: tx_fifo_empty[0] = rx_fifo_empty_30;
- default: tx_fifo_empty[0] = 1'b1;
+ SEL_UC: tx_fifo_empty[0] = rx_fifo_empty_u0_m2;
+ default: tx_fifo_empty[0] = 1'b1;
endcase
end
// TX1 Switch Logic
-// Possible sources: 0, 2, 3 in priority
+// Possible sources: 0, 2 in priority
always @(posedge clk, negedge rstn)
if ( !rstn )
begin
tx_mode1 <= TX_MODE_AN;
- tx_src_sel1 <= SEL_PHY0;
+ tx1_src_sel <= SEL_PHY0;
end
else if ( tx_f[1] )
case( tx_mode1 )
@@ -267,31 +276,25 @@ always @(posedge clk, negedge rstn)
TX_MODE_IDLE:
if ( !phy_up[1] )
tx_mode1 <= TX_MODE_AN;
- else if (tx_src_sel1==SEL_PHY0 && !rx_fifo_empty_21 )
- begin
- tx_mode1 <= TX_MODE_XMT_PKT;
- tx_src_sel1 <= SEL_PHY2;
- end
- else if (tx_src_sel1==SEL_PHY0 && !rx_fifo_empty_31 )
+`ifdef PHY2_PRESENT
+ else if (tx1_src_sel==SEL_PHY0 && !rx_fifo_empty_21 )
begin
tx_mode1 <= TX_MODE_XMT_PKT;
- tx_src_sel1 <= SEL_PHY3;
+ tx1_src_sel <= SEL_PHY2;
end
+`endif
else if (!rx_fifo_empty_01 )
begin
tx_mode1 <= TX_MODE_XMT_PKT;
- tx_src_sel1 <= SEL_PHY0;
+ tx1_src_sel <= SEL_PHY0;
end
+`ifdef PHY2_PRESENT
else if (!rx_fifo_empty_21 )
begin
tx_mode1 <= TX_MODE_XMT_PKT;
- tx_src_sel1 <= SEL_PHY2;
- end
- else if (!rx_fifo_empty_31 )
- begin
- tx_mode1 <= TX_MODE_XMT_PKT;
- tx_src_sel1 <= SEL_PHY3;
+ tx1_src_sel <= SEL_PHY2;
end
+`endif
TX_MODE_XMT_PKT:
if ( !phy_up[1] )
tx_mode1 <= TX_MODE_AN;
@@ -302,11 +305,10 @@ always @(posedge clk, negedge rstn)
// TX1 data mux
always @(*) begin
- case(tx_src_sel1)
+ case(tx1_src_sel)
SEL_PHY0: tx_d1 = rx_d_01;
SEL_PHY1: tx_d1 = 9'h000;
SEL_PHY2: tx_d1 = rx_d_21;
- SEL_PHY3: tx_d1 = rx_d_31;
SEL_UC: tx_d1 = 9'h000;
default: tx_d1 = 9'h000;
endcase
@@ -316,21 +318,18 @@ end
always @(*) begin
rx_fifo_re_01 = 1'b0;
rx_fifo_re_21 = 1'b0;
- rx_fifo_re_31 = 1'b0;
- case(tx_src_sel1)
+ case(tx1_src_sel)
SEL_PHY0: rx_fifo_re_01 = tx_fifo_re[1];
SEL_PHY2: rx_fifo_re_21 = tx_fifo_re[1];
- SEL_PHY3: rx_fifo_re_31 = tx_fifo_re[1];
endcase
end
// TX1 FIFO Empty Routing
always @(*) begin
- case(tx_src_sel1)
+ case(tx1_src_sel)
SEL_PHY0: tx_fifo_empty[1] = rx_fifo_empty_01;
SEL_PHY1: tx_fifo_empty[1] = 1'b1;
SEL_PHY2: tx_fifo_empty[1] = rx_fifo_empty_21;
- SEL_PHY3: tx_fifo_empty[1] = rx_fifo_empty_31;
SEL_UC: tx_fifo_empty[1] = 1'b1;
default: tx_fifo_empty[1] = 1'b1;
endcase
@@ -339,16 +338,13 @@ end
/*
* TX2 Switch Logic
- * Possible Sources: 0, 1, UC
- * Note that for TX_MODE_XMT_METRICS, we set the source to be loopback, but it is expected that the
- * phy controller will use a combination of local memory and the metrics block for its data. These decisions
- * should be revisited when implementing loopback within this switch module.
+ * Possible Sources: 0, 1
*/
always @(posedge clk, negedge rstn)
if ( !rstn )
begin
tx_mode2 <= TX_MODE_AN;
- tx_src_sel2 <= SEL_PHY0;
+ tx2_src_sel <= SEL_PHY0;
end
else if ( tx_f[2] )
case( tx_mode2 )
@@ -358,30 +354,20 @@ always @(posedge clk, negedge rstn)
TX_MODE_IDLE:
if ( !phy_up[2] )
tx_mode2 <= TX_MODE_AN;
- else if (tx_src_sel2==SEL_PHY0 && !rx_fifo_empty_12 )
+ else if (tx2_src_sel==SEL_PHY0 && !rx_fifo_empty_12 )
begin
tx_mode2 <= TX_MODE_XMT_PKT;
- tx_src_sel2 <= SEL_PHY1;
+ tx2_src_sel <= SEL_PHY1;
end
else if (!rx_fifo_empty_02 )
begin
tx_mode2 <= TX_MODE_XMT_PKT;
- tx_src_sel2 <= SEL_PHY0;
+ tx2_src_sel <= SEL_PHY0;
end
else if (!rx_fifo_empty_12 )
begin
tx_mode2 <= TX_MODE_XMT_PKT;
- tx_src_sel2 <= SEL_PHY1;
- end
- else if (!rx_fifo_empty_u2)
- begin
- tx_mode2 <= TX_MODE_XMT_PKT;
- tx_src_sel2 <= SEL_UC;
- end
- else if (tx_custom)
- begin
- tx_mode2 <= TX_MODE_XMT_CUSTOM;
- tx_src_sel2 <= SEL_PHY2;
+ tx2_src_sel <= SEL_PHY1;
end
TX_MODE_XMT_PKT:
if ( !phy_up[2] )
@@ -393,11 +379,10 @@ always @(posedge clk, negedge rstn)
// TX2 data mux
always @(*) begin
- case(tx_src_sel2)
+ case(tx2_src_sel)
SEL_PHY0: tx_d2 = rx_d_02;
SEL_PHY1: tx_d2 = rx_d_12;
SEL_PHY2: tx_d2 = 9'h000;
- SEL_UC: tx_d2 = rx_d_u2;
default: tx_d2 = 9'h000;
endcase
end
@@ -406,119 +391,44 @@ end
always @(*) begin
rx_fifo_re_02 = 1'b0;
rx_fifo_re_12 = 1'b0;
- rx_fifo_re_u2 = 1'b0;
- case(tx_src_sel2)
+ case(tx2_src_sel)
SEL_PHY0: rx_fifo_re_02 = tx_fifo_re[2];
SEL_PHY1: rx_fifo_re_12 = tx_fifo_re[2];
- SEL_UC: rx_fifo_re_u2 = tx_fifo_re[2];
endcase
end
// TX2 FIFO Empty Routing
always @(*) begin
- case(tx_src_sel2)
+ case(tx2_src_sel)
SEL_PHY0: tx_fifo_empty[2] = rx_fifo_empty_02;
SEL_PHY1: tx_fifo_empty[2] = rx_fifo_empty_12;
SEL_PHY2: tx_fifo_empty[2] = 1'b0; //
- SEL_UC: tx_fifo_empty[2] = rx_fifo_empty_u2;
default: tx_fifo_empty[2] = 1'b1;
endcase
end
-
-// TX3 Switch Logic
-// Possible sources: 0, 1
-always @(posedge clk, negedge rstn)
- if ( !rstn )
- begin
- tx_mode3 <= TX_MODE_AN;
- tx_src_sel3 <= SEL_PHY1;
- end
- else if ( tx_f[3] )
- case( tx_mode3 )
- TX_MODE_AN:
- if ( phy_up[3] )
- tx_mode3 <= TX_MODE_IDLE;
- TX_MODE_IDLE:
- if ( !phy_up[3] )
- tx_mode3 <= TX_MODE_AN;
- else if (tx_src_sel3==SEL_PHY1 && !rx_fifo_empty_03 )
- begin
- tx_mode3 <= TX_MODE_XMT_PKT;
- tx_src_sel3 <= SEL_PHY0;
- end
- else if (!rx_fifo_empty_13 )
- begin
- tx_mode3 <= TX_MODE_XMT_PKT;
- tx_src_sel3 <= SEL_PHY1;
- end
- else if (!rx_fifo_empty_03 )
- begin
- tx_mode3 <= TX_MODE_XMT_PKT;
- tx_src_sel3 <= SEL_PHY0;
- end
- TX_MODE_XMT_PKT:
- if ( !phy_up[3] )
- tx_mode3 <= TX_MODE_AN;
- else
- tx_mode3 <= TX_MODE_IDLE;
- default: tx_mode3 <= TX_MODE_IDLE;
- endcase
-
- // TX3 data mux
- always @(*) begin
- case(tx_src_sel3)
- SEL_PHY0: tx_d3 = rx_d_03;
- SEL_PHY1: tx_d3 = rx_d_13;
- SEL_PHY2: tx_d3 = rx_d_23;
- SEL_PHY3: tx_d3 = 9'h000;
- SEL_UC: tx_d3 = 9'h000;
- default: tx_d3 = 9'h000;
- endcase
- end
- // TX3 FIFO read enable
- always @(*) begin
- rx_fifo_re_03 = 1'b0;
- rx_fifo_re_13 = 1'b0;
- rx_fifo_re_23 = 1'b0;
- case(tx_src_sel3)
- SEL_PHY0: rx_fifo_re_03 = tx_fifo_re[3];
- SEL_PHY1: rx_fifo_re_13 = tx_fifo_re[3];
- SEL_PHY2: rx_fifo_re_23 = tx_fifo_re[3];
- endcase
- end
-
- // TX3 FIFO Empty Routing
- always @(*) begin
- case(tx_src_sel3)
- SEL_PHY0: tx_fifo_empty[3] = rx_fifo_empty_03;
- SEL_PHY1: tx_fifo_empty[3] = rx_fifo_empty_13;
- SEL_PHY2: tx_fifo_empty[3] = rx_fifo_empty_23;
- default: tx_fifo_empty[3] = 1'b1;
- endcase
- end
/*
* Transmit Logic for UC
*
- * The only possible driver is PHY2
+ * The only possible driver is PHY0
*
* We need to delay the fifo_we one clock since the DPRAM read data comes out one clock delayed
*/
-assign tx_du = rx_d_2u;
+assign tx_du = rx_d_0u;
always @(*)
- if ( !rx_fifo_empty_2u )
+ if ( !rx_fifo_empty_0u )
begin
i_tx_fifo_we_u = 1'b1;
- rx_fifo_re_2u = 1'b1;
+ rx_fifo_re_0u = 1'b1;
end
else
begin
i_tx_fifo_we_u = 1'b0;
- rx_fifo_re_2u = 1'b0;
+ rx_fifo_re_0u = 1'b0;
end
always @(posedge clk, negedge rstn)
@@ -528,4 +438,4 @@ always @(posedge clk, negedge rstn)
tx_fifo_we_u <= i_tx_fifo_we_u;
-endmodule
+endmodule \ No newline at end of file

Highly Recommended Verilog Books