aboutsummaryrefslogtreecommitdiffstats
path: root/hdl/fifo_buffer.v
diff options
context:
space:
mode:
authorLeonard Kugis <leonard@kug.is>2021-02-11 14:31:02 +0100
committerLeonard Kugis <leonard@kug.is>2021-02-11 14:31:02 +0100
commit52f60a20c9d95ecf67b662589d4a4c1160ce0a2a (patch)
treeb0425a0acd757aa2a33c4db8ccaa897acea409b3 /hdl/fifo_buffer.v
parent266f2ebc6322eeccf85fcc67eccc6d6200014dab (diff)
downloadturboswap-52f60a20c9d95ecf67b662589d4a4c1160ce0a2a.tar.gz
Reimplemented all HDL files
Diffstat (limited to 'hdl/fifo_buffer.v')
-rw-r--r--hdl/fifo_buffer.v157
1 files changed, 157 insertions, 0 deletions
diff --git a/hdl/fifo_buffer.v b/hdl/fifo_buffer.v
new file mode 100644
index 0000000..dd56537
--- /dev/null
+++ b/hdl/fifo_buffer.v
@@ -0,0 +1,157 @@
+`timescale 1ns / 1ps
+
+module fifo_buffer (
+ input wire wr_clk,
+ input wire [7:0] wr_data,
+ input wire wr_valid,
+ output wire wr_ready,
+
+ input wire rd_clk,
+ output wire [7:0] rd_data,
+ output wire rd_valid,
+ input wire rd_ready,
+
+ input wire rst_n,
+
+ output wire fifo_empty,
+ output wire fifo_full,
+ output wire [7:0] fifo_level
+);
+
+ parameter DEPTH = 512;
+ parameter ADDR_WIDTH = 9;
+
+ reg [7:0] mem [0:DEPTH-1];
+
+ reg [ADDR_WIDTH:0] wr_ptr;
+ reg [ADDR_WIDTH:0] wr_ptr_gray;
+ reg [ADDR_WIDTH:0] wr_ptr_gray_sync1;
+ reg [ADDR_WIDTH:0] wr_ptr_gray_sync2;
+
+ reg [ADDR_WIDTH:0] rd_ptr;
+ reg [ADDR_WIDTH:0] rd_ptr_gray;
+ reg [ADDR_WIDTH:0] rd_ptr_gray_sync1;
+ reg [ADDR_WIDTH:0] rd_ptr_gray_sync2;
+
+ wire [ADDR_WIDTH:0] wr_ptr_bin;
+ wire [ADDR_WIDTH:0] rd_ptr_bin;
+ wire [ADDR_WIDTH:0] fifo_count;
+
+ reg wr_en;
+ reg rd_en;
+
+ reg [7:0] rd_data_reg;
+ reg rd_valid_reg;
+
+ assign wr_ready = ~fifo_full;
+
+ always @(posedge wr_clk or negedge rst_n) begin
+ if (!rst_n) begin
+ wr_ptr <= 0;
+ wr_ptr_gray <= 0;
+ wr_en <= 1'b0;
+ end else begin
+ wr_en <= wr_valid && wr_ready;
+
+ if (wr_en) begin
+ mem[wr_ptr[ADDR_WIDTH-1:0]] <= wr_data;
+ wr_ptr <= wr_ptr + 1;
+ end
+
+ wr_ptr_gray <= binary_to_gray(wr_ptr);
+ end
+ end
+
+ always @(posedge wr_clk or negedge rst_n) begin
+ if (!rst_n) begin
+ rd_ptr_gray_sync1 <= 0;
+ rd_ptr_gray_sync2 <= 0;
+ end else begin
+ rd_ptr_gray_sync1 <= rd_ptr_gray;
+ rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
+ end
+ end
+
+ assign rd_data = rd_data_reg;
+ assign rd_valid = rd_valid_reg;
+
+ always @(posedge rd_clk or negedge rst_n) begin
+ if (!rst_n) begin
+ rd_ptr <= 0;
+ rd_ptr_gray <= 0;
+ rd_en <= 1'b0;
+ rd_data_reg <= 8'h00;
+ rd_valid_reg <= 1'b0;
+ end else begin
+ rd_en <= rd_ready && ~fifo_empty;
+
+ if (rd_en) begin
+ rd_data_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
+ rd_valid_reg <= 1'b1;
+ rd_ptr <= rd_ptr + 1;
+ end else if (rd_ready) begin
+ rd_valid_reg <= 1'b0;
+ end
+
+ rd_ptr_gray <= binary_to_gray(rd_ptr);
+ end
+ end
+
+ always @(posedge rd_clk or negedge rst_n) begin
+ if (!rst_n) begin
+ wr_ptr_gray_sync1 <= 0;
+ wr_ptr_gray_sync2 <= 0;
+ end else begin
+ wr_ptr_gray_sync1 <= wr_ptr_gray;
+ wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
+ end
+ end
+
+ assign wr_ptr_bin = gray_to_binary(wr_ptr_gray_sync2);
+ assign rd_ptr_bin = gray_to_binary(rd_ptr_gray_sync2);
+
+ wire [ADDR_WIDTH:0] fifo_count_wr;
+ assign fifo_count_wr = wr_ptr - gray_to_binary(rd_ptr_gray_sync2);
+
+ wire [ADDR_WIDTH:0] fifo_count_rd;
+ assign fifo_count_rd = gray_to_binary(wr_ptr_gray_sync2) - rd_ptr;
+
+ assign fifo_full = (fifo_count_wr >= DEPTH);
+ assign fifo_empty = (fifo_count_rd == 0);
+
+ reg [7:0] fifo_level_reg;
+ always @(*) begin
+ if (fifo_count_wr > DEPTH)
+ fifo_level_reg = DEPTH;
+ else
+ fifo_level_reg = fifo_count_wr[7:0];
+ end
+
+ assign fifo_level = fifo_level_reg;
+
+ function [ADDR_WIDTH:0] binary_to_gray;
+ input [ADDR_WIDTH:0] binary;
+ begin
+ binary_to_gray = binary ^ (binary >> 1);
+ end
+ endfunction
+
+ function [ADDR_WIDTH:0] gray_to_binary;
+ input [ADDR_WIDTH:0] gray;
+ reg [ADDR_WIDTH:0] binary;
+ integer i;
+ begin
+ binary[ADDR_WIDTH] = gray[ADDR_WIDTH];
+ for (i = ADDR_WIDTH-1; i >= 0; i = i - 1)
+ binary[i] = binary[i+1] ^ gray[i];
+ gray_to_binary = binary;
+ end
+ endfunction
+
+ integer i;
+ initial begin
+ for (i = 0; i < DEPTH; i = i + 1)
+ mem[i] = 8'h00;
+ end
+
+endmodule \ No newline at end of file