summaryrefslogtreecommitdiffhomepage
path: root/src/drop_fifo.v
diff options
context:
space:
mode:
authorPrivate Island Networks Inc <opensource@privateisland.tech>2025-12-21 20:51:04 -0500
committerPrivate Island Networks Inc <opensource@privateisland.tech>2025-12-21 20:51:04 -0500
commit7b1b5e7eb712d41888398934834cae730e0aa5a0 (patch)
tree8b8aba85e19a079fbbd4962c57ff89ca701c6e4d /src/drop_fifo.v
parentf4bdc9f4365d3a3ce3f906e68cd018cb57561e56 (diff)
betsy: preliminary beta snapshot
Diffstat (limited to 'src/drop_fifo.v')
-rw-r--r--src/drop_fifo.v328
1 files changed, 187 insertions, 141 deletions
diff --git a/src/drop_fifo.v b/src/drop_fifo.v
index 736947c..faefac0 100644
--- a/src/drop_fifo.v
+++ b/src/drop_fifo.v
@@ -1,8 +1,8 @@
/*
* drop_fifo.v
*
- * Copyright 2018, 2019, 2020, 2021 Mind Chasers Inc.
- * Copyright 2023 Private Island Networks Inc.
+ * Copyright (C) 2023-2025 Private Island Networks Inc.
+ * Copyright (C) 2018-2021 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.
@@ -23,154 +23,200 @@
*/
module drop_fifo(
- input rstn,
- input clk,
- input passthrough, // don't store / delay data, write through instead
- input enable, // enable the FIFO
- input keep, // this packet won't be dropped, start transferring it (writer must be sure FIFO won't run dry during writes)
-
- // input data
- input we_in,
- input [8:0] d_in,
- input wr_done, // keep should occur before wr_done is asserted.
- input rx_eop,
-
- // output data
- output reg we_out,
- output reg [8:0] d_out,
-
- // debug
- output reg active
+ input rstn,
+ input phy_up, // Use the associated PHY state to gate write activity into the DF
+ input rx_clk,
+ input tx_clk,
+ input passthrough, // don't store / delay data, write through instead
+ input enable, // enable the FIFO
+ input keep, // this packet won't be dropped, start transferring it (writer must be sure FIFO won't run dry during writes)
+
+ // input data
+ input we_in,
+ input [8:0] d_in,
+ input wr_done, // keep should occur before wr_done is asserted.
+ input rx_idle, // Use to clean up states and pointers
+ input rx_error,
+
+ // output data
+ output reg we_out, // assert when data is available for writing to the next stage
+ output reg [8:0] d_out,
+
+ // debug
+ output reg active
);
-
-// local parameters and includes
-
-
-// nets and registers
-reg [10:0] wr_ptr0, wr_ptr1; // wr_ptr0 is updated on each write; wr_ptr1 is updated at end of packet
-reg [10:0] rd_ptr;
-wire [8:0] d_out_internal;
-reg read_run, read_run_m1, read_run_m2; // read continues while read_run is set
-reg kept;
-wire fifo_empty;
-
-/*
- * kept: assert for length of write duration after keep asserts (when enable is active)
- */
-always @(posedge clk, negedge rstn)
- if( !rstn )
- kept <= 1'b0;
- else if ( wr_done )
- kept <= 1'b0;
- else if ( keep && enable )
- kept <= 1'b1;
-/*
- * wr_ptr0 logic
- */
-always @(posedge clk, negedge rstn)
- if( !rstn )
- wr_ptr0 <= 'd0;
- else if ( we_in )
- wr_ptr0 <= wr_ptr0 + 1'b1;
+ // local parameters and includes
+ localparam SZ_DPRAM = 16'd2048;
-/*
- * wr_ptr1 logic
- * sync pointers at end of rx packet for next packet
-*/
-always @(posedge clk, negedge rstn)
- if( !rstn )
- wr_ptr1 <= 'd0;
- else if ( wr_done )
- wr_ptr1 <= wr_ptr0 +1; // a write takes place with wr_done
-/*
- * read_run logic
- * continues until the FIFO is empty
- */
-always @(posedge clk, negedge rstn)
- if( !rstn )
- read_run <= 1'b0;
- else if (kept && wr_done)
- read_run <= 1'b1;
- else if ( fifo_empty )
- read_run <= 1'b0;
-
-
-always @(posedge clk, negedge rstn)
- if( !rstn )
- read_run_m1 <= 1'b0;
- else
- read_run_m1 <= read_run;
+ // nets and registers
+ reg [10:0] wr_ptr0, wr_ptr1; // wr_ptr0 is updated on each write; wr_ptr1 is updated at end of packet
+ reg [10:0] rd_ptr;
+ wire [8:0] d_out_internal;
+ reg read_run, read_run_m1, read_run_m2; // read continues while read_run is set
+ reg wr_done_m1, wr_done_m2, wr_done_m3; // CDC flag
+ reg rx_idle_m1, rx_idle_m2;
+ reg kept;
+ wire fifo_empty;
+ reg [15:0] df_bytes;
+
+ /*
+ * kept: assert for length of write duration after keep asserts (when enable is active)
+ */
+ always @(posedge rx_clk, negedge rstn)
+ if(!rstn)
+ kept <= 1'b0;
+ else if (read_run_m2) // CDC flag that is asserted for multiple clocks
+ kept <= 1'b0;
+ else if (phy_up && keep && enable)
+ kept <= 1'b1;
+
+ /*
+ * wr_ptr0 logic
+ */
+ always @(posedge rx_clk, negedge rstn)
+ if(!rstn)
+ wr_ptr0 <= 'd0;
+ else if (phy_up && we_in)
+ wr_ptr0 <= wr_ptr0 + 1'b1;
+
+
+ // convert clock domain for rx_idle
+ always @(posedge tx_clk, negedge rstn)
+ if(!rstn) begin
+ rx_idle_m1 <= 1'b0;
+ rx_idle_m2 <= 1'b0;
+ end
+ else begin
+ rx_idle_m1 <= rx_idle;
+ rx_idle_m2 <= rx_idle_m1;
+ end
+
+ // convert clock domain for wr_done
+ always @(posedge tx_clk, negedge rstn)
+ if(!rstn) begin
+ wr_done_m1 <= 1'b0;
+ wr_done_m2 <= 1'b0;
+ wr_done_m3 <= 1'b0;
+ end
+ else begin
+ wr_done_m1 <= wr_done;
+ wr_done_m2 <= wr_done_m1;
+ wr_done_m3 <= wr_done_m2;
+ end
+
+ /*
+ * wr_ptr1 logic
+ * sync pointers at end of RX packet
+ */
+ always @(posedge tx_clk, negedge rstn)
+ if(!rstn)
+ wr_ptr1 <= 'd0;
+ else if (phy_up && wr_done_m3)
+ wr_ptr1 <= wr_ptr0; //
+ else if (rx_idle_m2 && !read_run)
+ wr_ptr1 <= wr_ptr0; // final clean up
+
+ /*
+ * read_run logic
+ * continues until the FIFO is empty
+ */
+ always @(posedge tx_clk, negedge rstn)
+ if(!rstn)
+ read_run <= 1'b0;
+ else if (phy_up && kept && wr_done_m3)
+ read_run <= 1'b1;
+ else if (fifo_empty)
+ read_run <= 1'b0;
-always @(posedge clk, negedge rstn)
- if( !rstn )
- read_run_m2 <= 1'b0;
- else
- read_run_m2 <= read_run_m1;
-
-/*
-* rd_ptr logic
-*/
-always @(posedge clk, negedge rstn)
- if( !rstn )
- rd_ptr <= 'd0;
- else if (kept && wr_done)
- rd_ptr <= wr_ptr1; // set rd_ptr to the beginning of where the write started
- else if (read_run && !fifo_empty)
- rd_ptr <= rd_ptr+ 1'b1;
+ always @(posedge tx_clk, negedge rstn)
+ if(!rstn) begin
+ read_run_m1 <= 1'b0;
+ read_run_m2 <= 1'b0;
+ end
+ else begin
+ read_run_m1 <= read_run;
+ read_run_m2 <= read_run_m1;
+ end
-/*
- * we_out logic
- */
-always @(posedge clk, negedge rstn)
- if( !rstn )
- we_out <= 1'b0;
- else if ( read_run_m1 && read_run_m2 )
- we_out <= 1'b1;
- else
- we_out <= 1'b0;
-
-assign fifo_empty = (wr_ptr1 == rd_ptr);
+ /*
+ * rd_ptr logic
+ */
+ always @(posedge tx_clk, negedge rstn)
+ if(!rstn)
+ rd_ptr <= 'd0;
+ else if (phy_up && kept && wr_done_m2)
+ rd_ptr <= wr_ptr1; // set rd_ptr to the beginning of where the write started
+ else if (read_run && !fifo_empty)
+ rd_ptr <= rd_ptr+ 1'b1;
-/*
- * d_out register
- *
- */
-always @(posedge clk, negedge rstn)
- if( !rstn )
- d_out <= 'd0;
- else
- d_out <= d_out_internal;
+ /*
+ * we_out logic
+ */
+ always @(posedge tx_clk, negedge rstn)
+ if(!rstn)
+ we_out <= 1'b0;
+ else if (read_run && read_run_m1)
+ we_out <= 1'b1;
+ else
+ we_out <= 1'b0;
-always @(posedge clk, negedge rstn)
- if( !rstn )
- active <= 1'b0;
- else if ( we_in || we_out )
- active <= 1'b1;
- else
- active <= 1'b0;
-
-dpram dpram_fifo(
-.rstn( rstn ),
-.a_clk( clk ),
-.a_clk_e( 1'b1 ),
-.a_we( we_in ),
-.a_oe( 1'b0 ),
-.a_addr( wr_ptr0 ),
-.a_din( d_in ),
-.a_dout( ),
-// port B
-.b_clk( clk ),
-.b_clk_e( read_run ),
-.b_we( 1'b0 ),
-.b_oe( 1'b1 ),
-.b_addr( rd_ptr ),
-.b_din( 9'h0 ),
-.b_dout( d_out_internal )
-);
-
+ assign fifo_empty = (wr_ptr1 == rd_ptr);
+
+ /*
+ * d_out register
+ *
+ */
+ always @(posedge tx_clk, negedge rstn)
+ if(!rstn)
+ d_out <= 'd0;
+ else
+ d_out <= d_out_internal;
+
+ // debug flag
+ always @(posedge tx_clk, negedge rstn)
+ if(!rstn)
+ active <= 1'b0;
+ else if (we_in || we_out)
+ active <= 1'b1;
+ else
+ active <= 1'b0;
+
+ /*
+ * debug: bytes in DF
+ */
+ always @(posedge rx_clk, negedge rstn)
+ if(!rstn)
+ df_bytes <= 'd0;
+ else if (! phy_up)
+ df_bytes <= 'd0;
+ else
+ if (wr_ptr1 <= wr_ptr0)
+ df_bytes <= (wr_ptr0 + 1'b1) - wr_ptr1;
+ else
+ df_bytes <= SZ_DPRAM + (wr_ptr0+1'b1) - wr_ptr1;
+
+
+ dpram_inf dpram_fifo(
+ .rstn(rstn),
+ .a_clk(rx_clk),
+ .a_clk_e(1'b1),
+ .a_we(we_in),
+ .a_oe(1'b0),
+ .a_addr(wr_ptr0),
+ .a_din(d_in),
+ .a_dout(),
+ // port B
+ .b_clk(tx_clk),
+ .b_clk_e(read_run),
+ .b_we(1'b0),
+ .b_oe(1'b1),
+ .b_addr(rd_ptr),
+ .b_din(9'h0),
+ .b_dout(d_out_internal)
+ );
endmodule

Highly Recommended Verilog Books