[prim/fifo] Add option to harden prim fifo pointers
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/prim/prim_fifo.core b/hw/ip/prim/prim_fifo.core
index 8f2b077..df12b43 100644
--- a/hw/ip/prim/prim_fifo.core
+++ b/hw/ip/prim/prim_fifo.core
@@ -11,10 +11,12 @@
- lowrisc:prim:assert
- lowrisc:prim:util
- lowrisc:prim:flop_2sync
+ - lowrisc:prim:count_pkg
files:
- rtl/prim_fifo_async_sram_adapter.sv
- rtl/prim_fifo_async.sv
- rtl/prim_fifo_sync.sv
+ - rtl/prim_fifo_sync_cnt.sv
file_type: systemVerilogSource
files_verilator_waiver:
diff --git a/hw/ip/prim/rtl/prim_fifo_sync.sv b/hw/ip/prim/rtl/prim_fifo_sync.sv
index 77b8230..1f2115d 100644
--- a/hw/ip/prim/rtl/prim_fifo_sync.sv
+++ b/hw/ip/prim/rtl/prim_fifo_sync.sv
@@ -28,7 +28,8 @@
output [Width-1:0] rdata_o,
// occupancy
output full_o,
- output [DepthW-1:0] depth_o
+ output [DepthW-1:0] depth_o,
+ output err_o
);
@@ -94,33 +95,48 @@
assign full_o = full;
assign rvalid_o = ~empty & ~under_rst;
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- fifo_wptr <= {(PTR_WIDTH){1'b0}};
- end else if (clr_i) begin
- fifo_wptr <= {(PTR_WIDTH){1'b0}};
- end else if (fifo_incr_wptr) begin
- if (fifo_wptr[PTR_WIDTH-2:0] == (PTR_WIDTH-1)'(Depth-1)) begin
- fifo_wptr <= {~fifo_wptr[PTR_WIDTH-1],{(PTR_WIDTH-1){1'b0}}};
- end else begin
- fifo_wptr <= fifo_wptr + {{(PTR_WIDTH-1){1'b0}},1'b1};
- end
- end
- end
+ prim_fifo_sync_cnt #(
+ .Width(PTR_WIDTH),
+ .Depth(Depth),
+ .Secure('0)
+ ) u_fifo_cnt (
+ .clk_i,
+ .rst_ni,
+ .clr_i,
+ .incr_wptr_i(fifo_incr_wptr),
+ .incr_rptr_i(fifo_incr_rptr),
+ .wptr_o(fifo_wptr),
+ .rptr_o(fifo_rptr),
+ .err_o
+ );
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- fifo_rptr <= {(PTR_WIDTH){1'b0}};
- end else if (clr_i) begin
- fifo_rptr <= {(PTR_WIDTH){1'b0}};
- end else if (fifo_incr_rptr) begin
- if (fifo_rptr[PTR_WIDTH-2:0] == (PTR_WIDTH-1)'(Depth-1)) begin
- fifo_rptr <= {~fifo_rptr[PTR_WIDTH-1],{(PTR_WIDTH-1){1'b0}}};
- end else begin
- fifo_rptr <= fifo_rptr + {{(PTR_WIDTH-1){1'b0}},1'b1};
- end
- end
- end
+ //always_ff @(posedge clk_i or negedge rst_ni) begin
+ // if (!rst_ni) begin
+ // fifo_wptr <= {(PTR_WIDTH){1'b0}};
+ // end else if (clr_i) begin
+ // fifo_wptr <= {(PTR_WIDTH){1'b0}};
+ // end else if (fifo_incr_wptr) begin
+ // if (fifo_wptr[PTR_WIDTH-2:0] == (PTR_WIDTH-1)'(Depth-1)) begin
+ // fifo_wptr <= {~fifo_wptr[PTR_WIDTH-1],{(PTR_WIDTH-1){1'b0}}};
+ // end else begin
+ // fifo_wptr <= fifo_wptr + {{(PTR_WIDTH-1){1'b0}},1'b1};
+ // end
+ // end
+ //end
+ //
+ //always_ff @(posedge clk_i or negedge rst_ni) begin
+ // if (!rst_ni) begin
+ // fifo_rptr <= {(PTR_WIDTH){1'b0}};
+ // end else if (clr_i) begin
+ // fifo_rptr <= {(PTR_WIDTH){1'b0}};
+ // end else if (fifo_incr_rptr) begin
+ // if (fifo_rptr[PTR_WIDTH-2:0] == (PTR_WIDTH-1)'(Depth-1)) begin
+ // fifo_rptr <= {~fifo_rptr[PTR_WIDTH-1],{(PTR_WIDTH-1){1'b0}}};
+ // end else begin
+ // fifo_rptr <= fifo_rptr + {{(PTR_WIDTH-1){1'b0}},1'b1};
+ // end
+ // end
+ //end
assign full = (fifo_wptr == (fifo_rptr ^ {1'b1,{(PTR_WIDTH-1){1'b0}}}));
assign fifo_empty = (fifo_wptr == fifo_rptr);
diff --git a/hw/ip/prim/rtl/prim_fifo_sync_cnt.sv b/hw/ip/prim/rtl/prim_fifo_sync_cnt.sv
new file mode 100644
index 0000000..b6d539c
--- /dev/null
+++ b/hw/ip/prim/rtl/prim_fifo_sync_cnt.sv
@@ -0,0 +1,102 @@
+// 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