summaryrefslogtreecommitdiffhomepage
path: root/source
diff options
context:
space:
mode:
authormindchasers <privateisland@mindchasers.com>2021-03-02 13:02:50 -0500
committermindchasers <privateisland@mindchasers.com>2021-03-02 13:02:50 -0500
commit05366eaac0ece9c7b4312721c4d4e1dba75efc7b (patch)
treeba55d7aa3e3dff8b73636accde50d311e6e59b20 /source
parent8c3ccc0d86e06fc735d0ea862c0db11aa5311419 (diff)
drop_fifo: first pass at a simplified approach
Diffstat (limited to 'source')
-rw-r--r--source/drop_fifo.v157
1 files changed, 55 insertions, 102 deletions
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 ),

Highly Recommended Verilog Books