blob: d21446ded625bd48d4dd28241b0c239a136ffa2c [file] [log] [blame]
// SPDX-FileCopyrightText: 2022 Johannes Kepler University, Institute for
// Integrated Circuits (H. Pretl, L. Blagojevic, M. Esen, K. Freinberger,
// M. Golser, M. Hackl, A. Hinterdorfer, O. Kara, D. Kellerer, P. Kotek,
// J. Mayrhofer, M. Meingast, T. Pankratz, J. Ratschenberger, R. Reddy.Mitta,
// P. Schmidt, S. Seidl, I. Shala, M. Zöbl)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
`ifndef _FIFO_
`define _FIFO_
`include "stud_synchronizer.v"
module stud_fifo
#( parameter LENGTH = 128,
parameter WIDTH = 16,
parameter SYNC_LEN = 2
)
(
input [WIDTH-1:0] fifo_i,
input fifo_rdy_i, audio_rd_i, rst_n_i, clk_i,
output reg fifo_ack_o, fifo_full_o, fifo_empty_o,
output [WIDTH-1:0] audio_o
);
/* Internal buffers */
reg [WIDTH-1:0] buffer [LENGTH - 1 : 0];
reg [$clog2(LENGTH)-1:0] buffer_r_ind;
reg [$clog2(LENGTH)-1:0] buffer_w_ind;
wire fifo_rdy; // Synchronous fifo_rdy
reg [WIDTH-1:0] audio_tmp;
reg fifo_ack_next;
reg fifo_rdy_last;
reg audio_rd_last;
/* External modules */
stud_synchronizer #(SYNC_LEN,1) fifo_rdy_sync(
.clk_i(clk_i),
.rst_n_i(rst_n_i),
.input_i(fifo_rdy_i),
.output_o(fifo_rdy)
);
/* CLK_i process */
always @(posedge clk_i) begin
if(~rst_n_i) begin
/* Reset whole buffer, for loops are allowed (according to internet) */
buffer[0] <= {WIDTH{1'b0}};
buffer_r_ind <= {$clog2(LENGTH){1'b0}};
buffer_w_ind <= {$clog2(LENGTH){1'b0}};
audio_tmp <= {WIDTH{1'b0}};
fifo_empty_o <= 1'b1;
fifo_full_o <= 1'b0;
fifo_ack_o <= 1'b0;
fifo_ack_next <= 1'b0;
end else begin
/* FIFO WRITE */
if(fifo_rdy && ! fifo_rdy_last && !fifo_full_o) begin
buffer[buffer_w_ind] <= fifo_i;
buffer_w_ind <= buffer_w_ind + 1'b1;
fifo_ack_next <= 1'b1;
end else begin
buffer[buffer_w_ind] <= buffer[buffer_w_ind];
buffer_w_ind <= buffer_w_ind;
fifo_ack_next <= 1'b0;
end
/* FIFO READ */
if(audio_rd_i && !audio_rd_last && !fifo_empty_o) begin
audio_tmp <= buffer[buffer_r_ind];
buffer_r_ind <= buffer_r_ind + 1'b1;
end else begin
audio_tmp <= audio_tmp;
buffer_r_ind <= buffer_r_ind;
end
/* FIFO status */
if (buffer_r_ind == buffer_w_ind) begin
fifo_empty_o <= 1'b1;
end else begin
fifo_empty_o <= 1'b0;
end
if(buffer_w_ind == (buffer_r_ind - 1'b1)) begin
fifo_full_o <= 1'b1;
end else begin
fifo_full_o <= 1'b0;
end
fifo_ack_o <= fifo_ack_next;
fifo_rdy_last <= fifo_rdy;
audio_rd_last <= audio_rd_i;
end
end
assign audio_o = audio_tmp;
endmodule
`endif