`include "VX_define.vh" module VX_indexable_queue #( parameter DATAW, parameter SIZE ) ( input wire clk, input wire reset, input wire [DATAW-1:0] write_data, output wire [`LOG2UP(SIZE)-1:0] write_addr, input wire push, output wire full, input wire pop, input wire [`LOG2UP(SIZE)-1:0] read_addr, output wire [DATAW-1:0] read_data ); reg [DATAW-1:0] data [SIZE-1:0]; reg valid [SIZE-1:0]; reg [`LOG2UP(SIZE):0] rd_ptr, wr_ptr; wire [`LOG2UP(SIZE)-1:0] rd_a, wr_a; wire enqueue, dequeue, empty; assign rd_a = rd_ptr[`LOG2UP(SIZE)-1:0]; assign wr_a = wr_ptr[`LOG2UP(SIZE)-1:0]; assign empty = (wr_ptr == rd_ptr); assign full = (wr_a == rd_a) && (wr_ptr[`LOG2UP(SIZE)] != rd_ptr[`LOG2UP(SIZE)]); assign enqueue = push && ~full; assign dequeue = ~empty && ~valid[rd_a]; // auto-remove when head is invalid always @(posedge clk) begin if (reset) begin rd_ptr <= 0; wr_ptr <= 0; end else begin if (enqueue) begin data[wr_a] <= write_data; valid[wr_a] <= 1; wr_ptr <= wr_ptr + 1; end if (dequeue) begin rd_ptr <= rd_ptr + 1; end if (pop) begin valid[read_addr] <= 0; end end end assign write_addr = wr_a; assign read_data = data[read_addr]; endmodule