[prim/fifo_async] Disallow non-power-of-two depths
If the depth is not a power of two, the transitions will not be
gray-coded when the pointers wrap.
Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
diff --git a/hw/ip/prim/rtl/prim_fifo_async.sv b/hw/ip/prim/rtl/prim_fifo_async.sv
index 3a7e8c1..558ab57 100644
--- a/hw/ip/prim/rtl/prim_fifo_async.sv
+++ b/hw/ip/prim/rtl/prim_fifo_async.sv
@@ -28,10 +28,10 @@
output [DepthW-1:0] rdepth_o
);
- `ASSERT_INIT(paramCheckDepth, Depth >= 3)
+ // Depth must be a power of 2 for the gray code pointers to work
+ `ASSERT_INIT(ParamCheckDepth_A, (Depth > 2) && (Depth == 2**$clog2(Depth)))
localparam int unsigned PTRV_W = $clog2(Depth);
- localparam logic [PTRV_W-1:0] DepthMinus1 = PTRV_W'(Depth - 1);
localparam int unsigned PTR_WIDTH = PTRV_W+1;
logic [PTR_WIDTH-1:0] fifo_wptr, fifo_rptr;
@@ -58,23 +58,15 @@
if (!rst_wr_ni) begin
fifo_wptr <= {(PTR_WIDTH){1'b0}};
end else if (fifo_incr_wptr) begin
- if (fifo_wptr[PTR_WIDTH-2:0] == DepthMinus1) 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};
+ fifo_wptr <= fifo_wptr + PTR_WIDTH'(1);
end
- end
// gray-coded version
always_ff @(posedge clk_wr_i or negedge rst_wr_ni)
if (!rst_wr_ni) begin
fifo_wptr_gray <= {(PTR_WIDTH){1'b0}};
end else if (fifo_incr_wptr) begin
- if (fifo_wptr[PTR_WIDTH-2:0] == DepthMinus1) begin
- fifo_wptr_gray <= dec2gray({~fifo_wptr[PTR_WIDTH-1],{(PTR_WIDTH-1){1'b0}}});
- end else begin
- fifo_wptr_gray <= dec2gray(fifo_wptr + {{(PTR_WIDTH-1){1'b0}},1'b1});
- end
+ fifo_wptr_gray <= dec2gray(fifo_wptr + PTR_WIDTH'(1));
end
prim_flop_2sync #(.Width(PTR_WIDTH)) sync_wptr (
@@ -93,23 +85,15 @@
if (!rst_rd_ni) begin
fifo_rptr <= {(PTR_WIDTH){1'b0}};
end else if (fifo_incr_rptr) begin
- if (fifo_rptr[PTR_WIDTH-2:0] == DepthMinus1) 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};
+ fifo_rptr <= fifo_rptr + PTR_WIDTH'(1);
end
- end
// gray-coded version
always_ff @(posedge clk_rd_i or negedge rst_rd_ni)
if (!rst_rd_ni) begin
fifo_rptr_gray <= {(PTR_WIDTH){1'b0}};
end else if (fifo_incr_rptr) begin
- if (fifo_rptr[PTR_WIDTH-2:0] == DepthMinus1) begin
- fifo_rptr_gray <= dec2gray({~fifo_rptr[PTR_WIDTH-1],{(PTR_WIDTH-1){1'b0}}});
- end else begin
- fifo_rptr_gray <= dec2gray(fifo_rptr + {{(PTR_WIDTH-1){1'b0}},1'b1});
- end
+ fifo_rptr_gray <= dec2gray(fifo_rptr + PTR_WIDTH'(1));
end
prim_flop_2sync #(.Width(PTR_WIDTH)) sync_rptr (
diff --git a/hw/top_earlgrey/ip/xbar_main/rtl/autogen/xbar_main.sv b/hw/top_earlgrey/ip/xbar_main/rtl/autogen/xbar_main.sv
index 0f79510..5b5ec0b 100644
--- a/hw/top_earlgrey/ip/xbar_main/rtl/autogen/xbar_main.sv
+++ b/hw/top_earlgrey/ip/xbar_main/rtl/autogen/xbar_main.sv
@@ -746,8 +746,8 @@
.dev_select_i (dev_sel_s1n_27)
);
tlul_fifo_async #(
- .ReqDepth (3),// At least 3 to make async work
- .RspDepth (3) // At least 3 to make async work
+ .ReqDepth (4),// At least 4 to make async work
+ .RspDepth (4) // At least 4 to make async work
) u_asf_28 (
.clk_h_i (clk_main_i),
.rst_h_ni (rst_main_ni),
diff --git a/util/tlgen/xbar.rtl.sv.tpl b/util/tlgen/xbar.rtl.sv.tpl
index 5dce4df..cf1e2be 100644
--- a/util/tlgen/xbar.rtl.sv.tpl
+++ b/util/tlgen/xbar.rtl.sv.tpl
@@ -198,8 +198,8 @@
% for block in xbar.nodes:
% if block.node_type.name == "ASYNC_FIFO":
tlul_fifo_async #(
- .ReqDepth (3),// At least 3 to make async work
- .RspDepth (3) // At least 3 to make async work
+ .ReqDepth (4),// At least 4 to make async work
+ .RspDepth (4) // At least 4 to make async work
) u_${block.name} (
.clk_h_i (${block.clocks[0]}),
.rst_h_ni (${block.resets[0]}),