//----------------------------------------------------------------------------- // Title : Dual LIFO stack // Project : Common //----------------------------------------------------------------------------- // File : lifo2.v //----------------------------------------------------------------------------- // Description : // // Two Synchronous LIFO stacks using a single BRAM. // // The stacks start at each end and grow to the middle. // //----------------------------------------------------------------------------- // Copyright 2009 Beyond Circuits. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE BEYOND CIRCUITS ``AS IS'' AND ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT // SHALL BEYOND CIRCUITS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //------------------------------------------------------------------------------ `timescale 1ns/1ns `define DATA_T [width-1:0] `define PTR_T [log2(depth)-1:0] `define CNT_T [log2(depth+1)-1:0] module lifo2 #( parameter depth_a = 512, parameter depth_b = 512, parameter width = 32, parameter implementation = "SRL", parameter full_checking = 0, parameter depth = depth_a+depth_b ) ( input clk, input reset, input push_a, input pop_a, output reg empty_a, output reg full_a, output reg `CNT_T count_a, output `DATA_T tos_a, input `DATA_T push_data_a , input push_b, input pop_b, output reg empty_b, output reg full_b, output reg `CNT_T count_b, output `DATA_T tos_b, input `DATA_T push_data_b ); function integer log2; input [31:0] value; begin value = value-1; for (log2=0; value>0; log2=log2+1) value = value>>1; end endfunction wire writing_a = push_a && (!full_a || pop_a); wire writing_b = push_b && (!full_b || pop_b); wire reading_a = pop_a && !empty_a; wire reading_b = pop_b && ! empty_b; reg `CNT_T next_count_a; always @(*) if (writing_a && !reading_a) next_count_a = count_a + 1; else if (reading_a && !writing_a) next_count_a = count_a - 1; else next_count_a = count_a; always @(posedge clk) if (reset) count_a <= 0; else count_a <= next_count_a; reg `CNT_T next_count_b; always @(*) if (writing_b && !reading_b) next_count_b = count_b + 1; else if (reading_b && !writing_b) next_count_b = count_b - 1; else next_count_b = count_b; always @(posedge clk) if (reset) count_a <= 0; else count_b <= next_count_b; always @(posedge clk) if (reset) empty_a <= 1; else empty_a <= next_count_a == 0; always @(posedge clk) if (reset) empty_b <= 1; else empty_b <= next_count_b == 0; generate if (full_checking) begin always @(posedge clk) if (reset) full_a <= 0; else full_a <= next_count_a == depth_a; always @(posedge clk) if (reset) full_b <= 0; else full_b <= next_count_b == depth_b; end else begin initial full_a = 0; initial full_b = 0; end endgenerate `ifndef SYNTHESIS initial $display("***INFO: %m: lifo2.v implementation=\"%0s\".",implementation); `endif generate if (implementation == "BRAM") begin : bram_implementation reg `DATA_T mem [depth-1:0]; wire `PTR_T ptr_a = writing_a ? count_a `PTR_T : (count_a `PTR_T)-1; wire `PTR_T ptr_b = (depth-1)-(writing_b ? count_b `PTR_T : (count_b `PTR_T)-1); reg `DATA_T mem_rd_a; always @(posedge clk) if (reading_a) mem_rd_a <= mem[ptr_a]; reg `DATA_T mem_rd_b; always @(posedge clk) if (reading_b) mem_rd_b <= mem[ptr_b]; always @(posedge clk) if (writing_a && !reading_a) mem[ptr_a] <= tos_a; always @(posedge clk) if (writing_b && !reading_b) mem[ptr_b] <= tos_b; reg `DATA_T tos_shadow_a; always @(posedge clk) if (reset) tos_shadow_a <= 0; else if (writing_a) tos_shadow_a <= push_data_a; reg `DATA_T tos_shadow_b; always @(posedge clk) if (reset) tos_shadow_b <= 0; else if (writing_b) tos_shadow_b <= push_data_b; reg use_mem_rd_a; always @(posedge clk) if (reset) use_mem_rd_a <= 0; else if (writing_a) use_mem_rd_a <= 0; else if (reading_a) use_mem_rd_a <= 1; reg use_mem_rd_b; always @(posedge clk) if (reset) use_mem_rd_b <= 0; else if (writing_b) use_mem_rd_b <= 0; else if (reading_b) use_mem_rd_b <= 1; assign tos_a = use_mem_rd_a ? mem_rd_a : tos_shadow_a; assign tos_b = use_mem_rd_b ? mem_rd_b : tos_shadow_b; end else if (implementation == "SRL") begin : srl_implementation genvar i; for (i=0; i