From 05366eaac0ece9c7b4312721c4d4e1dba75efc7b Mon Sep 17 00:00:00 2001
From: mindchasers <privateisland@mindchasers.com>
Date: Tue, 2 Mar 2021 13:02:50 -0500
Subject: drop_fifo: first pass at a simplified approach

---
 source/drop_fifo.v | 157 +++++++++++++++++++----------------------------------
 1 file changed, 55 insertions(+), 102 deletions(-)

(limited to 'source')

diff --git a/source/drop_fifo.v b/source/drop_fifo.v
index 393c20b..de97d6d 100644
--- a/source/drop_fifo.v
+++ b/source/drop_fifo.v
@@ -1,7 +1,7 @@
 /*
  *   drop_fifo.v
  *
- *   Copyright (C) 2018, 2019 Mind Chasers Inc.
+ *   Copyright 2018, 2019, 2020, 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.
@@ -15,7 +15,7 @@
  *   See the License for the specific language governing permissions and
  *   limitations under the License.
  *
- *	function: Double buffered side-by-side FIFO for delaying data until keep / drop decision is made
+ *	function: FIFO that supports dropping data if not kept
  *       
  */
 
@@ -27,7 +27,7 @@ module drop_fifo(
 		input	enable, 
 		
 		// control (keep or drop by default)
-		input	keep,				// this packet won't be dropped, start transferring it
+		input	keep,				// this packet won't be dropped, start transferring it (writer must be sure FIFO won't run dry during writes)
 		input	passthrough,		// don't store / delay data, write through instead
 		
 		// input
@@ -36,7 +36,7 @@ module drop_fifo(
 		input [8:0]	d_in,
 		
 		// output
-		output 	we_out,
+		output 	reg we_out,
 		output	reg [8:0] d_out,
 		
 		// debug
@@ -47,66 +47,18 @@ module drop_fifo(
 
 
 // nets and registers
-
-// the msbit of the ptr selects top or bottom half
-reg	[10:0] 	wr_ptr;
+reg	[10:0] 	wr_ptr0, wr_ptr1;	// wr_ptr0 is updated on each write; wr_ptr1 is updated on wr_done
 reg	[10:0] 	rd_ptr;
 
 wire [8:0]  d_out_internal;
 
-reg read_run, read_run_m1;		// read continues while read_run is set
-reg i_we_out, i_we_out_m1;		// internal we_out
-wire re;						// read enable for dpram
-reg rd_done_p1, rd_done;
+reg read_run, read_run_m1;		// read continues while read_run is set					// read enable for dpram
 wire i_keep;
 reg kept;
+wire fifo_empty;
 
 assign i_keep = keep & enable;
-	
-/*
- * 	read_run logic
- *  read starts after each keep assertion
- * 	continues until the FIFO is empty
- */
-always @(posedge clk, negedge rstn)
-	if( !rstn )
-		read_run <= 1'b0;
-	else if ( rd_done_p1 )
-		read_run <= 1'b0;
-	else if ( i_keep )
-		read_run <= 1'b1;
-
-
-always @(posedge clk, negedge rstn)
-	if( !rstn )
-		read_run_m1 <= 1'b0;
-	else 
-		read_run_m1 <= read_run;	
-	
-assign re = read_run;
 
-
-/*
- * 	we_out logic
- * 	delayed version of re
- */
-always @(posedge clk, negedge rstn)
-	if( !rstn )
-		i_we_out <= 1'b0;
-	else if ( read_run && read_run_m1 )
-		i_we_out <= 1'b1;
-	else
-		i_we_out <= 1'b0;
-	
-always @(posedge clk, negedge rstn)
-	if( !rstn )
-		i_we_out_m1 <= 1'b0;
-	else
-		i_we_out_m1 <= i_we_out;
-	
-// OR these two signals to stretch we_out to the last byte from FIFO
-assign we_out = i_we_out | i_we_out_m1;
-	
 /* 
  * kept: assert for length of write duration after keep asserts
  */
@@ -119,48 +71,65 @@ always @(posedge clk, negedge rstn)
 		kept <= 1'b1;
 	
 /*
- *  upper / lower half DPRAM logic
- *  directs upper or lower write buffer in FIFO
- *  toggle each time a packet is kept and write is finished
+ * wr_ptr0 logic
  */
 always @(posedge clk, negedge rstn)
-	if ( !rstn )
-		wr_ptr[10] <= 1'b0;		// init to the lower bank
-	else if ( wr_done && kept )
-		wr_ptr[10]  <= ~wr_ptr[10]; 
+	if( !rstn )
+		wr_ptr0 <= 'd0;
+	else if ( we_in )
+		wr_ptr0 <= wr_ptr0 + 1;
+	
 	
 /*
- * wr_ptr logic excluding msbit
- * reset pointer when wr_done
- */
+ * wr_ptr1 logic
+*/
 always @(posedge clk, negedge rstn)
 	if( !rstn )
-		wr_ptr[9:0] <= 'd0;
+		wr_ptr1 <= 'd0;
 	else if ( wr_done )
-		wr_ptr[9:0] <= 'd0;
-	else if ( we_in )
-		wr_ptr[9:0] <= wr_ptr[9:0] + 1;
+		wr_ptr1 <= wr_ptr0 +1;		// a write takes place with wr_done
 
-/* 
- * each time the FIFO is empty, set rd_ptr[10] to wr_ptr[10]
- * FIFO becomes empty through reading
- */
+/*
+ * rd_ptr logic
+ */	
 always @(posedge clk, negedge rstn)
-	if ( !rstn )
-		rd_ptr[10] <= 1'b0;		// init to the lower bank
-	else if ( rd_done )
-		rd_ptr[10] <= wr_ptr[10];	
+	if( !rstn )
+		rd_ptr <= 'd0;
+	else if (read_run && !fifo_empty)
+		rd_ptr <= rd_ptr+ 1;
+	
 	
 /*
- * rd_ptr logic excluding msbit
- */	
+ * 	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 )
-		rd_ptr[9:0] <= 'd0;
-	else if ( rd_done )
-		rd_ptr[9:0] <= 'd0;
-	else if ( re )
-		rd_ptr[9:0] <= rd_ptr[9:0] + 1;
+		read_run_m1 <= 1'b0;
+	else 
+		read_run_m1 <= read_run;
+
+/*
+ * 	we_out logic
+ */
+always @(posedge 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;
+
+assign fifo_empty = wr_ptr1 == rd_ptr ? 1'b1 : 1'b0;
 	
 /*
  * d_out register
@@ -172,22 +141,6 @@ always @(posedge clk, negedge rstn)
 	else
 		d_out <= d_out_internal;
 		
-		
-/*
-*	rd_done logic
-*/
-always @(posedge clk, negedge rstn)
-	if( !rstn )
-		begin
-			rd_done_p1 <= 1'b0;
-			rd_done <= 1'b0;
-		end
-	else
-		begin
-			rd_done_p1 <= d_out_internal[8];
-			rd_done <= rd_done_p1;
-		end
-		
 	
 always @(posedge clk, negedge rstn)
 	if( !rstn )
@@ -203,12 +156,12 @@ dpram dpram_fifo(
 .a_clk_e( 1'b1 ),
 .a_we( we_in ),
 .a_oe( 1'b0 ),
-.a_addr( wr_ptr ),
+.a_addr( wr_ptr0 ),
 .a_din( d_in ),
 .a_dout( ),
 // port B
 .b_clk(  clk ),
-.b_clk_e( re ),
+.b_clk_e( read_run ),
 .b_we( 1'b0 ),
 .b_oe( 1'b1  ),
 .b_addr( rd_ptr ),
-- 
cgit v1.2.3-8-gadcc