`include "VX_platform.vh" module VX_cam_buffer #( parameter DATAW = 1, parameter SIZE = 1, parameter RPORTS = 1, parameter CPORTS = 1, parameter ADDRW = `LOG2UP(SIZE) ) ( input wire clk, input wire reset, output wire [ADDRW-1:0] write_addr, input wire [DATAW-1:0] write_data, input wire acquire_slot, input wire [RPORTS-1:0][ADDRW-1:0] read_addr, output wire [RPORTS-1:0][DATAW-1:0] read_data, input wire [CPORTS-1:0][ADDRW-1:0] release_addr, input wire [CPORTS-1:0] release_slot, output wire full ); reg [DATAW-1:0] entries [SIZE-1:0]; reg [SIZE-1:0] free_slots, free_slots_n; reg [ADDRW-1:0] write_addr_r; reg full_r; wire free_valid; wire [ADDRW-1:0] free_index; VX_priority_encoder #( .N(SIZE) ) free_slots_encoder ( .data_in (free_slots_n), .data_out (free_index), .valid_out (free_valid) ); always @(*) begin free_slots_n = free_slots; for (integer i = 0; i < CPORTS; i++) begin if (release_slot[i]) begin free_slots_n[release_addr[i]] = 1; end end if (acquire_slot) begin free_slots_n[write_addr_r] = 0; end end always @(posedge clk) begin if (reset) begin free_slots <= {SIZE{1'b1}}; full_r <= 1'b0; write_addr_r <= ADDRW'(1'b0); end else begin if (acquire_slot) begin assert(1 == free_slots[write_addr]) else $display("%t: inused slot at port %d", $time, write_addr); entries[write_addr] <= write_data; end for (integer i = 0; i < CPORTS; i++) begin if (release_slot[i]) begin assert(0 == free_slots[release_addr[i]]) else $display("%t: freed slot at port %d", $time, release_addr[i]); end end free_slots <= free_slots_n; write_addr_r <= free_index; full_r <= ~free_valid; end end for (genvar i = 0; i < RPORTS; i++) begin assign read_data[i] = entries[read_addr[i]]; end assign write_addr = write_addr_r; assign full = full_r; endmodule