//////////////////////////////////////////////////////////////////////////// | |
// SPDX-FileCopyrightText: 2022 , Julien OURY | |
// | |
// 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 | |
// SPDX-FileContributor: Created by Julien OURY <julien.oury@outlook.fr> | |
// | |
//////////////////////////////////////////////////////////////////////////// | |
module simple_fifo #( | |
parameter ASIZE = 4, // FIFO size (FIFO_size=(2**ASIZE)-1) | |
parameter DSIZE = 32 // Number of bits of data | |
)( | |
input wire rst_n , // Asynchronous reset (active low) | |
input wire clk , // Clock (rising edge) | |
input wire clear_n , // Synchronous clear (active low) | |
// Write port | |
input wire [DSIZE-1:0] wr_data , | |
input wire wr_valid, | |
output wire wr_ready, // Ready flag (0: FIFO full, 1: FIFO not full) | |
// Read port | |
output wire [DSIZE-1:0] rd_data , | |
output wire rd_valid, | |
input wire rd_ready // Ready flag (0: FIFO empty, 1: FIFO not empty) | |
); | |
wire [ASIZE-1:0] rd_ptr_next ; | |
wire [ASIZE-1:0] wr_ptr_next ; | |
reg [ASIZE-1:0] rd_ptr ; | |
reg [ASIZE-1:0] wr_ptr ; | |
reg [DSIZE-1:0] memory[2**ASIZE-1:0]; | |
integer i = 0; | |
assign wr_ptr_next = wr_ptr + 1'b1; | |
assign rd_ptr_next = rd_ptr + 1'b1; | |
assign wr_ready = (wr_ptr_next != rd_ptr); | |
assign rd_valid = (rd_ptr != wr_ptr); | |
// Write pointer update | |
always @(negedge rst_n or posedge clk) begin | |
if (rst_n == 1'b0) begin | |
wr_ptr <= 1'b0; | |
end else begin | |
if (clear_n == 1'b0) begin | |
wr_ptr <= 1'b0; | |
end else if (wr_valid && wr_ready) begin | |
wr_ptr <= wr_ptr_next; | |
end | |
end | |
end | |
// Write operation | |
always @(negedge rst_n or posedge clk) begin | |
if (rst_n == 1'b0) begin | |
for (i = 0; i < (2**ASIZE); i = i + 1) begin | |
memory[i] <= {DSIZE{1'b0}}; | |
end | |
end else begin | |
if (wr_valid && wr_ready) begin | |
memory[wr_ptr] <= wr_data; | |
end | |
end | |
end | |
// Read pointer update | |
always @(negedge rst_n or posedge clk) begin | |
if (rst_n == 1'b0) begin | |
rd_ptr <= 1'b0; | |
end else begin | |
if (clear_n == 1'b0) begin | |
rd_ptr <= 1'b0; | |
end else if (rd_valid && rd_ready) begin | |
rd_ptr <= rd_ptr_next; | |
end | |
end | |
end | |
// Read operation | |
assign rd_data = memory[rd_ptr]; | |
endmodule |