diff options
Diffstat (limited to 'source/drop_fifo.v')
-rw-r--r-- | source/drop_fifo.v | 188 |
1 files changed, 72 insertions, 116 deletions
diff --git a/source/drop_fifo.v b/source/drop_fifo.v index 393c20b..736947c 100644 --- a/source/drop_fifo.v +++ b/source/drop_fifo.v @@ -1,7 +1,8 @@ /* * drop_fifo.v * - * Copyright (C) 2018, 2019 Mind Chasers Inc. + * Copyright 2018, 2019, 2020, 2021 Mind Chasers Inc. + * Copyright 2023 Private Island Networks Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,28 +16,27 @@ * 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 + * + * For more information, see https://privateisland.tech/dev/pi-doc * */ -`timescale 1ns /10ps - module drop_fifo( input rstn, input clk, - input enable, - - // control (keep or drop by default) - input keep, // this packet won't be dropped, start transferring it 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 + // input data input we_in, - input wr_done, - input [8:0] d_in, - - // output - output we_out, + 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 @@ -47,120 +47,92 @@ 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 at end of packet 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; -wire i_keep; +reg read_run, read_run_m1, read_run_m2; // read continues while read_run is set reg kept; +wire fifo_empty; -assign i_keep = keep & enable; +/* + * 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; /* - * read_run logic - * read starts after each keep assertion - * continues until the FIFO is empty + * wr_ptr0 logic */ 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; - - + wr_ptr0 <= 'd0; + else if ( we_in ) + wr_ptr0 <= wr_ptr0 + 1'b1; + +/* + * wr_ptr1 logic + * sync pointers at end of rx packet for next packet +*/ always @(posedge clk, negedge rstn) if( !rstn ) - read_run_m1 <= 1'b0; - else - read_run_m1 <= read_run; + wr_ptr1 <= 'd0; + else if ( wr_done ) + wr_ptr1 <= wr_ptr0 +1; // a write takes place with wr_done -assign re = read_run; - - /* - * we_out logic - * delayed version of re + * read_run logic + * continues until the FIFO is empty */ 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; - + 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 ) - i_we_out_m1 <= 1'b0; - else - i_we_out_m1 <= i_we_out; + read_run_m1 <= 1'b0; + else + read_run_m1 <= read_run; -// 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 - */ always @(posedge clk, negedge rstn) if( !rstn ) - kept <= 1'b0; - else if ( wr_done ) - kept <= 1'b0; - else if ( i_keep ) - kept <= 1'b1; - + read_run_m2 <= 1'b0; + else + read_run_m2 <= read_run_m1; + /* - * upper / lower half DPRAM logic - * directs upper or lower write buffer in FIFO - * toggle each time a packet is kept and write is finished - */ +* rd_ptr 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 ) + 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; /* - * wr_ptr logic excluding msbit - * reset pointer when wr_done + * we_out logic */ always @(posedge clk, negedge rstn) if( !rstn ) - wr_ptr[9:0] <= 'd0; - else if ( wr_done ) - wr_ptr[9:0] <= 'd0; - else if ( we_in ) - wr_ptr[9:0] <= wr_ptr[9:0] + 1; + we_out <= 1'b0; + else if ( read_run_m1 && read_run_m2 ) + we_out <= 1'b1; + else + we_out <= 1'b0; -/* - * each time the FIFO is empty, set rd_ptr[10] to wr_ptr[10] - * FIFO becomes empty through reading - */ -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]; - -/* - * rd_ptr logic excluding msbit - */ -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; +assign fifo_empty = (wr_ptr1 == rd_ptr); /* * d_out register @@ -172,22 +144,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 +159,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 ), |