blob: 5dbeed037d9d02059c6d22687b643af90ae2925d [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
`include "prim_assert.sv"
module prim_fifo_async_simple #(
parameter int unsigned Width = 16,
parameter bit EnRstChks = 1'b0, // Enable reset-related assertion checks, disabled by
// default.
parameter bit EnRzHs = 1'b0 // By Default, the faster NRZ handshake protocol
// (EnRzHs = 0) is used. Enable the RZ handshake protocol
// if the FSMs need to be partial-reset-safe.
) (
// write port
input logic clk_wr_i,
input logic rst_wr_ni,
input logic wvalid_i,
output logic wready_o,
input logic [Width-1:0] wdata_i,
// read port
input logic clk_rd_i,
input logic rst_rd_ni,
output logic rvalid_o,
input logic rready_i,
output logic [Width-1:0] rdata_o
);
////////////////
// FIFO logic //
////////////////
// Convert ready/valid to req/ack
logic wr_en;
logic src_req, src_ack;
logic pending_d, pending_q, not_in_reset_q;
assign wready_o = !pending_q && not_in_reset_q;
assign wr_en = wvalid_i && wready_o;
assign src_req = pending_q || wvalid_i;
assign pending_d = (src_ack) ? 1'b0 :
(wr_en) ? 1'b1 : pending_q;
logic dst_req, dst_ack;
assign rvalid_o = dst_req;
assign dst_ack = dst_req && rready_i;
always_ff @(posedge clk_wr_i or negedge rst_wr_ni) begin
if (!rst_wr_ni) begin
pending_q <= 1'b0;
not_in_reset_q <= 1'b0;
end else begin
pending_q <= pending_d;
not_in_reset_q <= 1'b1;
end
end
////////////////////////////////////
// REQ/ACK synchronizer primitive //
////////////////////////////////////
prim_sync_reqack #(
.EnRstChks(EnRstChks),
.EnRzHs(EnRzHs)
) u_prim_sync_reqack (
.clk_src_i(clk_wr_i),
.rst_src_ni(rst_wr_ni),
.clk_dst_i(clk_rd_i),
.rst_dst_ni(rst_rd_ni),
.req_chk_i(1'b0),
.src_req_i(src_req),
.src_ack_o(src_ack),
.dst_req_o(dst_req),
.dst_ack_i(dst_ack)
);
//////////////////////
// Data holding reg //
//////////////////////
logic [Width-1:0] data_q;
always_ff @(posedge clk_wr_i) begin
if (wr_en) begin
data_q <= wdata_i;
end
end
assign rdata_o = data_q;
endmodule