blob: b6d539c71b600b6de7bac44b5a947aa372e30470 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Generic synchronous fifo for use in a variety of devices.
`include "prim_assert.sv"
module prim_fifo_sync_cnt #(
parameter int Depth = 4,
parameter int Width = 16,
parameter bit Secure = 1'b0
) (
input clk_i,
input rst_ni,
input clr_i,
input incr_wptr_i,
input incr_rptr_i,
output logic [Width-1:0] wptr_o,
output logic [Width-1:0] rptr_o,
output logic err_o
);
logic wptr_wrap;
logic [Width-1:0] wptr_wrap_cnt;
logic rptr_wrap;
logic [Width-1:0] rptr_wrap_cnt;
assign wptr_wrap = incr_wptr_i & (wptr_o[Width-2:0] == unsigned'((Width-1)'(Depth-1)));
assign rptr_wrap = incr_rptr_i & (rptr_o[Width-2:0] == unsigned'((Width-1)'(Depth-1)));
assign wptr_wrap_cnt = {~wptr_o[Width-1],{(Width-1){1'b0}}};
assign rptr_wrap_cnt = {~rptr_o[Width-1],{(Width-1){1'b0}}};
if (Secure) begin : gen_secure_ptrs
logic wptr_err;
prim_count #(
.Width(Width),
.OutSelDnCnt(0),
.CntStyle(prim_count_pkg::DupCnt)
) u_wptr (
.clk_i,
.rst_ni,
.clr_i,
.set_i(wptr_wrap),
.set_cnt_i(wptr_wrap_cnt),
.en_i(incr_wptr_i),
.step_i(Width'(1'b1)),
.cnt_o(wptr_o),
.err_o(wptr_err)
);
logic rptr_err;
prim_count #(
.Width(Width),
.OutSelDnCnt(0),
.CntStyle(prim_count_pkg::DupCnt)
) u_rptr (
.clk_i,
.rst_ni,
.clr_i,
.set_i(rptr_wrap),
.set_cnt_i(rptr_wrap_cnt),
.en_i(incr_rptr_i),
.step_i(Width'(1'b1)),
.cnt_o(rptr_o),
.err_o(rptr_err)
);
assign err_o = wptr_err | rptr_err;
end else begin : gen_normal_ptrs
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
wptr_o <= {(Width){1'b0}};
end else if (clr_i) begin
wptr_o <= {(Width){1'b0}};
end else if (wptr_wrap) begin
wptr_o <= wptr_wrap_cnt;
end else if (incr_wptr_i) begin
wptr_o <= wptr_o + {{(Width-1){1'b0}},1'b1};
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rptr_o <= {(Width){1'b0}};
end else if (clr_i) begin
rptr_o <= {(Width){1'b0}};
end else if (rptr_wrap) begin
rptr_o <= rptr_wrap_cnt;
end else if (incr_rptr_i) begin
rptr_o <= rptr_o + {{(Width-1){1'b0}},1'b1};
end
end
assign err_o = '0;
end
endmodule // prim_fifo_sync_cnt