From 52f60a20c9d95ecf67b662589d4a4c1160ce0a2a Mon Sep 17 00:00:00 2001 From: Leonard Kugis Date: Thu, 11 Feb 2021 14:31:02 +0100 Subject: Reimplemented all HDL files --- hdl/fifo_buffer.v | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 hdl/fifo_buffer.v (limited to 'hdl/fifo_buffer.v') 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 -- cgit v1.2.3