vortex/hw/rtl/libs/VX_index_queue.sv

64 lines
No EOL
1.7 KiB
Systemverilog

`include "VX_platform.vh"
`TRACING_OFF
module VX_index_queue #(
parameter DATAW = 1,
parameter SIZE = 1
) (
input wire clk,
input wire reset,
input wire [DATAW-1:0] write_data,
output wire [`LOG2UP(SIZE)-1:0] write_addr,
input wire push,
input wire pop,
output wire full,
output wire empty,
input wire [`LOG2UP(SIZE)-1:0] read_addr,
output wire [DATAW-1:0] read_data
);
reg [DATAW-1:0] entries [SIZE-1:0];
reg [SIZE-1:0] valid;
reg [`LOG2UP(SIZE):0] rd_ptr, wr_ptr;
wire [`LOG2UP(SIZE)-1:0] rd_a, wr_a;
wire enqueue, dequeue;
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;
assign dequeue = !empty && !valid[rd_a]; // auto-remove when head is invalid
`RUNTIME_ASSERT(!push || !full, ("%t: *** invalid inputs", $time));
always @(posedge clk) begin
if (reset) begin
rd_ptr <= 0;
wr_ptr <= 0;
valid <= 0;
end else begin
if (enqueue) begin
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
if (enqueue) begin
entries[wr_a] <= write_data;
end
end
assign write_addr = wr_a;
assign read_data = entries[read_addr];
endmodule
`TRACING_ON