fifo refactoring

This commit is contained in:
Blaise Tine 2024-08-24 01:56:56 -07:00
parent bcf7d9f960
commit 370daf1025
2 changed files with 216 additions and 263 deletions

View file

@ -36,225 +36,134 @@ module VX_fifo_queue #(
output wire [SIZEW-1:0] size
);
localparam ADDRW = `CLOG2(DEPTH);
`STATIC_ASSERT(ALM_FULL > 0, ("alm_full must be greater than 0!"))
`STATIC_ASSERT(ALM_FULL < DEPTH, ("alm_full must be smaller than size!"))
`STATIC_ASSERT(ALM_EMPTY > 0, ("alm_empty must be greater than 0!"))
`STATIC_ASSERT(ALM_EMPTY < DEPTH, ("alm_empty must be smaller than size!"))
`STATIC_ASSERT(`IS_POW2(DEPTH), ("size must be a power of 2!"))
VX_pending_size #(
.SIZE (DEPTH),
.ALM_EMPTY (ALM_EMPTY),
.ALM_FULL (ALM_FULL)
) pending_size (
.clk (clk),
.reset (reset),
.incr (push),
.decr (pop),
.empty (empty),
.full (full),
.alm_empty(alm_empty),
.alm_full(alm_full),
.size (size)
);
if (DEPTH == 1) begin
reg [DATAW-1:0] head_r;
reg size_r;
always @(posedge clk) begin
if (reset) begin
head_r <= '0;
size_r <= '0;
end else begin
`ASSERT(~push || ~full, ("runtime error: writing to a full queue"));
`ASSERT(~pop || ~empty, ("runtime error: reading an empty queue"));
if (push) begin
if (~pop) begin
size_r <= 1;
end
end else if (pop) begin
size_r <= '0;
end
if (push) begin
head_r <= data_in;
end
if (push) begin
head_r <= data_in;
end
end
assign data_out = head_r;
assign empty = (size_r == 0);
assign alm_empty = 1'b1;
assign full = (size_r != 0);
assign alm_full = 1'b1;
assign size = size_r;
assign data_out = head_r;
end else begin
reg empty_r, alm_empty_r;
reg full_r, alm_full_r;
reg [ADDRW-1:0] used_r;
wire [ADDRW-1:0] used_n;
localparam ADDRW = `CLOG2(DEPTH);
always @(posedge clk) begin
if (reset) begin
empty_r <= 1;
alm_empty_r <= 1;
full_r <= 0;
alm_full_r <= 0;
used_r <= '0;
end else begin
`ASSERT(~(push && ~pop) || ~full, ("runtime error: incrementing full queue"));
`ASSERT(~(pop && ~push) || ~empty, ("runtime error: decrementing empty queue"));
if (push) begin
if (~pop) begin
empty_r <= 0;
if (used_r == ADDRW'(ALM_EMPTY))
alm_empty_r <= 0;
if (used_r == ADDRW'(DEPTH-1))
full_r <= 1;
if (used_r == ADDRW'(ALM_FULL-1))
alm_full_r <= 1;
end
end else if (pop) begin
full_r <= 0;
if (used_r == ADDRW'(ALM_FULL))
alm_full_r <= 0;
if (used_r == ADDRW'(1))
empty_r <= 1;
if (used_r == ADDRW'(ALM_EMPTY+1))
alm_empty_r <= 1;
end
used_r <= used_n;
end
end
if (OUT_REG != 0) begin
if (DEPTH == 2 && LUTRAM == 0) begin
wire [DATAW-1:0] dout;
reg [DATAW-1:0] dout_r;
reg [ADDRW-1:0] wr_ptr_r;
reg [ADDRW-1:0] rd_ptr_r;
reg [ADDRW-1:0] rd_ptr_n_r;
assign used_n = used_r ^ (push ^ pop);
if (0 == OUT_REG) begin
reg [1:0][DATAW-1:0] shift_reg;
always @(posedge clk) begin
if (push) begin
shift_reg[1] <= shift_reg[0];
shift_reg[0] <= data_in;
end
end
assign data_out = shift_reg[!used_r[0]];
end else begin
reg [DATAW-1:0] data_out_r;
reg [DATAW-1:0] buffer;
always @(posedge clk) begin
if (push) begin
buffer <= data_in;
end
if (push && (empty_r || (used_r && pop))) begin
data_out_r <= data_in;
end else if (pop) begin
data_out_r <= buffer;
end
end
assign data_out = data_out_r;
end
end else begin
assign used_n = $signed(used_r) + ADDRW'($signed(2'(push) - 2'(pop)));
if (0 == OUT_REG) begin
reg [ADDRW-1:0] rd_ptr_r;
reg [ADDRW-1:0] wr_ptr_r;
always @(posedge clk) begin
if (reset) begin
rd_ptr_r <= '0;
wr_ptr_r <= '0;
end else begin
wr_ptr_r <= wr_ptr_r + ADDRW'(push);
rd_ptr_r <= rd_ptr_r + ADDRW'(pop);
end
end
VX_dp_ram #(
.DATAW (DATAW),
.SIZE (DEPTH),
.LUTRAM (LUTRAM)
) dp_ram (
.clk (clk),
.reset (reset),
.read (1'b1),
.write (push),
.wren (1'b1),
.waddr (wr_ptr_r),
.wdata (data_in),
.raddr (rd_ptr_r),
.rdata (data_out)
);
end else begin
wire [DATAW-1:0] dout;
reg [DATAW-1:0] dout_r;
reg [ADDRW-1:0] wr_ptr_r;
reg [ADDRW-1:0] rd_ptr_r;
reg [ADDRW-1:0] rd_ptr_n_r;
always @(posedge clk) begin
if (reset) begin
wr_ptr_r <= '0;
rd_ptr_r <= '0;
rd_ptr_n_r <= 1;
end else begin
wr_ptr_r <= wr_ptr_r + ADDRW'(push);
if (pop) begin
rd_ptr_r <= rd_ptr_n_r;
if (DEPTH > 2) begin
rd_ptr_n_r <= rd_ptr_r + ADDRW'(2);
end else begin // (DEPTH == 2);
rd_ptr_n_r <= ~rd_ptr_n_r;
end
always @(posedge clk) begin
if (reset) begin
wr_ptr_r <= '0;
rd_ptr_r <= '0;
rd_ptr_n_r <= 1;
end else begin
wr_ptr_r <= wr_ptr_r + ADDRW'(push);
if (pop) begin
rd_ptr_r <= rd_ptr_n_r;
if (DEPTH > 2) begin
rd_ptr_n_r <= rd_ptr_r + ADDRW'(2);
end else begin // (DEPTH == 2);
rd_ptr_n_r <= ~rd_ptr_n_r;
end
end
end
wire going_empty;
if (ALM_EMPTY == 1) begin
assign going_empty = alm_empty_r;
end else begin
assign going_empty = (used_r == ADDRW'(1));
end
VX_dp_ram #(
.DATAW (DATAW),
.SIZE (DEPTH),
.LUTRAM (LUTRAM)
) dp_ram (
.clk (clk),
.reset (reset),
.read (1'b1),
.write (push),
.wren (1'b1),
.waddr (wr_ptr_r),
.wdata (data_in),
.raddr (rd_ptr_n_r),
.rdata (dout)
);
always @(posedge clk) begin
if (push && (empty_r || (going_empty && pop))) begin
dout_r <= data_in;
end else if (pop) begin
dout_r <= dout;
end
end
assign data_out = dout_r;
end
end
assign empty = empty_r;
assign alm_empty = alm_empty_r;
assign full = full_r;
assign alm_full = alm_full_r;
assign size = {full_r, used_r};
VX_dp_ram #(
.DATAW (DATAW),
.SIZE (DEPTH),
.LUTRAM (LUTRAM)
) dp_ram (
.clk (clk),
.reset (reset),
.read (1'b1),
.write (push),
.wren (1'b1),
.waddr (wr_ptr_r),
.wdata (data_in),
.raddr (rd_ptr_n_r),
.rdata (dout)
);
wire going_empty = (ALM_EMPTY == 1) ? alm_empty : (size[ADDRW] == ADDRW'(1));
always @(posedge clk) begin
if (push && (empty || (going_empty && pop))) begin
dout_r <= data_in;
end else if (pop) begin
dout_r <= dout;
end
end
assign data_out = dout_r;
end else begin
reg [ADDRW-1:0] rd_ptr_r;
reg [ADDRW-1:0] wr_ptr_r;
always @(posedge clk) begin
if (reset) begin
rd_ptr_r <= '0;
wr_ptr_r <= '0;
end else begin
wr_ptr_r <= wr_ptr_r + ADDRW'(push);
rd_ptr_r <= rd_ptr_r + ADDRW'(pop);
end
end
VX_dp_ram #(
.DATAW (DATAW),
.SIZE (DEPTH),
.LUTRAM (LUTRAM)
) dp_ram (
.clk (clk),
.reset (reset),
.read (1'b1),
.write (push),
.wren (1'b1),
.waddr (wr_ptr_r),
.wdata (data_in),
.raddr (rd_ptr_r),
.rdata (data_out)
);
end
end
`RUNTIME_ASSERT(~(push && ~pop) || ~full, ("runtime error: incrementing full queue"));
`RUNTIME_ASSERT(~(pop && ~push) || ~empty, ("runtime error: decrementing empty queue"));
endmodule
`TRACING_ON

View file

@ -13,7 +13,7 @@
`include "VX_platform.vh"
//`TRACING_OFF
`TRACING_OFF
module VX_pending_size #(
parameter SIZE = 1,
parameter INCRW = 1,
@ -34,97 +34,141 @@ module VX_pending_size #(
);
`STATIC_ASSERT(INCRW <= SIZEW, ("invalid parameter: %d vs %d", INCRW, SIZEW))
`STATIC_ASSERT(DECRW <= SIZEW, ("invalid parameter: %d vs %d", DECRW, SIZEW))
localparam ADDRW = `LOG2UP(SIZE);
reg empty_r, alm_empty_r;
reg full_r, alm_full_r;
if (SIZE == 1) begin
if (INCRW != 1 || DECRW != 1) begin
reg [SIZEW-1:0] size_r;
wire [SIZEW-1:0] size_n = size_r + SIZEW'(incr) - SIZEW'(decr);
reg size_r;
always @(posedge clk) begin
if (reset) begin
empty_r <= 1;
alm_empty_r <= 1;
alm_full_r <= 0;
full_r <= 0;
size_r <= '0;
size_r <= '0;
end else begin
`ASSERT((SIZEW'(incr) >= SIZEW'(decr)) || (size_n >= size_r), ("runtime error: counter overflow"));
`ASSERT((SIZEW'(incr) <= SIZEW'(decr)) || (size_n <= size_r), ("runtime error: counter underflow"));
size_r <= size_n;
empty_r <= (size_n == SIZEW'(0));
alm_empty_r <= (size_n == SIZEW'(ALM_EMPTY));
full_r <= (size_n == SIZEW'(SIZE));
alm_full_r <= (size_n == SIZEW'(ALM_FULL));
if (incr) begin
if (~decr) begin
size_r <= 1;
end
end else if (decr) begin
size_r <= '0;
end
end
end
assign size = size_r;
assign empty = (size_r == 0);
assign full = (size_r != 0);
assign alm_empty = 1'b1;
assign alm_full = 1'b1;
assign size = size_r;
end else begin
reg [ADDRW-1:0] used_r;
wire [ADDRW-1:0] used_n;
logic empty_r, alm_empty_r;
logic full_r, alm_full_r;
always @(posedge clk) begin
if (reset) begin
empty_r <= 1;
alm_empty_r <= 1;
full_r <= 0;
alm_full_r <= 0;
used_r <= '0;
end else begin
`ASSERT(~(incr && ~decr) || ~full, ("runtime error: counter overflow"));
`ASSERT(~(decr && ~incr) || ~empty, ("runtime error: counter underflow"));
if (incr) begin
if (~decr) begin
empty_r <= 0;
if (used_r == ADDRW'(ALM_EMPTY))
alm_empty_r <= 0;
if (used_r == ADDRW'(SIZE-1))
full_r <= 1;
if (used_r == ADDRW'(ALM_FULL-1))
alm_full_r <= 1;
end
end else if (decr) begin
if (used_r == ADDRW'(1))
empty_r <= 1;
if (used_r == ADDRW'(ALM_EMPTY+1))
alm_empty_r <= 1;
full_r <= 0;
if (used_r == ADDRW'(ALM_FULL))
alm_full_r <= 0;
if (INCRW != 1 || DECRW != 1) begin
localparam SUBW = `MIN(SIZEW, `MAX(INCRW, DECRW)+1);
logic [SIZEW-1:0] size_n, size_r;
assign size_n = $signed(size_r) + SIZEW'($signed(SUBW'(incr) - SUBW'(decr)));
always @(posedge clk) begin
if (reset) begin
empty_r <= 1;
full_r <= 0;
alm_empty_r <= 1;
alm_full_r <= 0;
size_r <= '0;
end else begin
`ASSERT((SIZEW'(incr) >= SIZEW'(decr)) || (size_n >= size_r), ("runtime error: counter overflow"));
`ASSERT((SIZEW'(incr) <= SIZEW'(decr)) || (size_n <= size_r), ("runtime error: counter underflow"));
empty_r <= (size_n == SIZEW'(0));
full_r <= (size_n == SIZEW'(SIZE));
alm_empty_r <= (size_n <= SIZEW'(ALM_EMPTY));
alm_full_r <= (size_n >= SIZEW'(ALM_FULL));
size_r <= size_n;
end
used_r <= used_n;
end
end
if (SIZE == 2) begin
assign used_n = used_r ^ (incr ^ decr);
assign size = size_r;
end else begin
assign used_n = $signed(used_r) + ADDRW'($signed(2'(incr) - 2'(decr)));
end
if (SIZE > 1) begin
if (SIZEW > ADDRW) begin
assign size = {full_r, used_r};
localparam ADDRW = `LOG2UP(SIZE);
reg [ADDRW-1:0] used_r;
wire is_empty_n = (used_r == ADDRW'(1));
wire is_full_n = (used_r == ADDRW'(SIZE-1));
if (SIZE > 2) begin
wire is_alm_empty = (used_r == ADDRW'(ALM_EMPTY));
wire is_alm_empty_n= (used_r == ADDRW'(ALM_EMPTY+1));
wire is_alm_full = (used_r == ADDRW'(ALM_FULL));
wire is_alm_full_n = (used_r == ADDRW'(ALM_FULL-1));
wire [1:0] push_minus_pop = {~incr & decr, incr ^ decr};
always @(posedge clk) begin
if (reset) begin
empty_r <= 1;
full_r <= 0;
alm_empty_r <= 0;
alm_full_r <= 0;
used_r <= '0;
end else begin
if (incr) begin
if (~decr) begin
empty_r <= 0;
if (is_alm_empty)
alm_empty_r <= 0;
if (is_full_n)
full_r <= 1;
if (is_alm_full_n)
alm_full_r <= 1;
end
end else if (decr) begin
full_r <= 0;
if (is_alm_full)
alm_full_r <= 0;
if (is_empty_n)
empty_r <= 1;
if (is_alm_empty_n)
alm_empty_r <= 1;
end
used_r <= $signed(used_r) + ADDRW'($signed(push_minus_pop));
end
end
end else begin
assign size = used_r;
always @(posedge clk) begin
if (reset) begin
empty_r <= 1;
full_r <= 0;
used_r <= '0;
end else begin
empty_r <= (empty_r & ~incr) | (~full_r & decr & ~incr);
full_r <= (~empty_r & incr & ~decr) | (full_r & ~(decr ^ incr));
used_r <= used_r ^ (incr ^ decr);
end
end
assign alm_empty_r = used_r;
assign alm_full_r = used_r;
end
end else begin
assign size = full_r;
assign size = {full_r, used_r};
end
assign empty = empty_r;
assign full = full_r;
assign alm_empty = alm_empty_r;
assign alm_full = alm_full_r;
end
assign empty = empty_r;
assign alm_empty = alm_empty_r;
assign alm_full = alm_full_r;
assign full = full_r;
endmodule
//`TRACING_ON
`TRACING_ON