| // 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 |