From 5723ec1a34181f1cfef9b8e870ab2e9a0362487c Mon Sep 17 00:00:00 2001 From: mindchasers Date: Wed, 1 May 2019 18:16:45 -0400 Subject: initial commit, all basic functions work on Darsena V02 --- source/drop_fifo.v | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 source/drop_fifo.v (limited to 'source/drop_fifo.v') diff --git a/source/drop_fifo.v b/source/drop_fifo.v new file mode 100644 index 0000000..393c20b --- /dev/null +++ b/source/drop_fifo.v @@ -0,0 +1,220 @@ +/* + * drop_fifo.v + * + * Copyright (C) 2018, 2019 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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 + * + */ + +`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 + input we_in, + input wr_done, + input [8:0] d_in, + + // output + output we_out, + output reg [8:0] d_out, + + // debug + output reg active +); + +// local parameters and includes + + +// nets and registers + +// the msbit of the ptr selects top or bottom half +reg [10:0] wr_ptr; +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 kept; + +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 + */ +always @(posedge clk, negedge rstn) + if( !rstn ) + kept <= 1'b0; + else if ( wr_done ) + kept <= 1'b0; + else if ( i_keep ) + 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 + */ +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]; + +/* + * wr_ptr logic excluding msbit + * reset pointer when wr_done + */ +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; + +/* + * 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; + +/* + * d_out register + * + */ +always @(posedge clk, negedge rstn) + if( !rstn ) + d_out <= 'd0; + 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 ) + 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_ptr ), +.a_din( d_in ), +.a_dout( ), +// port B +.b_clk( clk ), +.b_clk_e( re ), +.b_we( 1'b0 ), +.b_oe( 1'b1 ), +.b_addr( rd_ptr ), +.b_din( 9'h0 ), +.b_dout( d_out_internal ) +); + + +endmodule -- cgit v1.2.3-8-gadcc