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/sync2_fifo.v | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 source/sync2_fifo.v (limited to 'source/sync2_fifo.v') diff --git a/source/sync2_fifo.v b/source/sync2_fifo.v new file mode 100644 index 0000000..029cfce --- /dev/null +++ b/source/sync2_fifo.v @@ -0,0 +1,141 @@ +/* + * sync2_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: Multi Buffered Sync FIFO suitable for rate conversion from 1G to 100 Mbit + * + * + */ + + +`timescale 1ns /10ps + +module sync2_fifo #(parameter FIFO_PTR = 12, + FIFO_WIDTH = 9, + FIFO_DEPTH = 4096 ) +( + input rstn, + input clk, + + + // input + input we, + input [FIFO_WIDTH-1:0] d_in, + + // output + input re, + output [FIFO_WIDTH-1:0] d_out, + output empty, + output almost_full, + + // fifo_control + input reset_ptrs + +); + +`include "ethernet_params.v" + + +reg [FIFO_PTR-1:0] wr_ptr; +reg [FIFO_PTR-1:0] rd_ptr; +reg [FIFO_PTR:0] bytes; // use for size calculation below + +wire [FIFO_WIDTH-1:0] d_out_0, d_out_1, d_out_internal; + +wire dpram0_a_clk_e, dpram1_a_clk_e; +wire dpram0_b_clk_e, dpram1_b_clk_e; + + +always @(posedge clk, negedge rstn) + if( !rstn ) + wr_ptr <= 'd0; + else if ( reset_ptrs ) + wr_ptr <= 'd0; + else if ( we ) + wr_ptr <= wr_ptr + 1; + +/* + * rd_ptr + * use empty flat to make sure rd_ptr doesn't advance when empty ( error condition ) + */ +always @(posedge clk, negedge rstn) + if( !rstn ) + rd_ptr <= 'd0; + else if ( reset_ptrs ) + rd_ptr <= 'd0; + else if ( re && !empty ) + rd_ptr <= rd_ptr + 1; + +assign empty = ( rd_ptr == wr_ptr ) ? 1'b1 : 1'b0; + +// leave room for a MTU frame +assign almost_full = bytes > FIFO_DEPTH-MTU ? 1'b1 : 1'b0; + +always @(posedge clk, negedge rstn) + if( !rstn ) + bytes <= 'd0; + else if ( wr_ptr >= rd_ptr ) + bytes <= wr_ptr - rd_ptr; + else + bytes <= (wr_ptr - rd_ptr)+FIFO_DEPTH; + + assign dpram0_a_clk_e = ~wr_ptr[FIFO_PTR-1]; + assign dpram1_a_clk_e = wr_ptr[FIFO_PTR-1]; + + assign dpram0_b_clk_e = ~rd_ptr[FIFO_PTR-1]; + assign dpram1_b_clk_e = rd_ptr[FIFO_PTR-1]; + + assign d_out = dpram0_b_clk_e ? d_out_0 : d_out_1; + +dpram dpram_fifo0( + .rstn( rstn ), + .a_clk( clk ), + .a_clk_e( dpram0_a_clk_e ), + .a_we( we ), + .a_oe( 1'b0 ), + .a_addr( wr_ptr[10:0] ), + .a_din( d_in ), + .a_dout( ), + // port B + .b_clk( clk ), + .b_clk_e( dpram0_b_clk_e ), + .b_we( 1'b0 ), + .b_oe( 1'b1 ), + .b_addr( rd_ptr[10:0] ), + .b_din( 9'h0 ), + .b_dout( d_out_0 ) +); + +dpram dpram_fifo1( + .rstn( rstn ), + .a_clk( clk ), + .a_clk_e( dpram1_a_clk_e ), + .a_we( we ), + .a_oe( 1'b0 ), + .a_addr( wr_ptr[10:0] ), + .a_din( d_in ), + .a_dout( ), + // port B + .b_clk( clk ), + .b_clk_e( dpram1_b_clk_e ), + .b_we( 1'b0 ), + .b_oe( 1'b1 ), + .b_addr( rd_ptr[10:0] ), + .b_din( 9'h0 ), + .b_dout( d_out_1 ) + ); + +endmodule -- cgit v1.2.3-8-gadcc