`timescale 1us/1us `include "my_mem.v" module fifo #( parameter DATA_WIDTH = 8, parameter DATA_DEPTH = 1024 ) ( input rst_i, input clk_i, input write_i, input read_i, output empty_o, output full_o, //output data_valid_o, input [(DATA_WIDTH-1) : 0] data_i, output reg [(DATA_WIDTH-1) : 0] data_o ); localparam DATA_DEPTH_BITS = $clog2(DATA_DEPTH); // the -1 will make sure it fits /* verilator lint_off WIDTHTRUNC */ localparam [DATA_DEPTH_BITS-1:0] MAX_ADDRESS = (DATA_DEPTH - 1); /* verilator lint_on WIDTHTRUNC */ // need to "count" to number *including* depth reg [$clog2(DATA_DEPTH + 1)-1:0] r_count; reg [DATA_DEPTH_BITS-1:0] r_read_addr; reg [DATA_DEPTH_BITS-1:0] r_write_addr; assign empty_o = r_count == 0; assign full_o = r_count == DATA_DEPTH; wire int_wr_en = write_i && !full_o; wire int_rd_en = read_i && !empty_o; my_mem #( .DATA_WIDTH(DATA_WIDTH), .DATA_DEPTH(DATA_DEPTH) ) fifo_mem ( .clk_i(clk_i), .write_en_i(int_wr_en), .read_en_i(int_rd_en), .r_read_addr(r_read_addr), .r_write_addr(r_write_addr), .data_i(data_i), .data_o(data_o) ); initial begin r_count = 0; r_read_addr = 0; r_write_addr = 0; end always @(posedge clk_i or negedge rst_i) begin if (!rst_i) r_count <= 0; else if (write_i && read_i) // nothing to do // count stays the same ; else if (write_i && !full_o) r_count <= r_count + 1; else if (read_i && !empty_o) r_count <= r_count - 1; end always @(posedge clk_i or negedge rst_i) begin if (!rst_i) r_read_addr <= 0; else if (read_i && !empty_o) r_read_addr <= (r_read_addr < MAX_ADDRESS) ? (r_read_addr + 1) : 0; end always @(posedge clk_i or negedge rst_i) begin if (!rst_i) r_write_addr <= 0; else if (write_i && !full_o) r_write_addr <= (r_write_addr < MAX_ADDRESS) ? (r_write_addr + 1) : 0; end endmodule