summaryrefslogtreecommitdiff
path: root/playground/fifo.v
diff options
context:
space:
mode:
Diffstat (limited to 'playground/fifo.v')
-rw-r--r--playground/fifo.v90
1 files changed, 90 insertions, 0 deletions
diff --git a/playground/fifo.v b/playground/fifo.v
new file mode 100644
index 0000000..bcc2d3f
--- /dev/null
+++ b/playground/fifo.v
@@ -0,0 +1,90 @@
+`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