`timescale 1ns/1ps `include "cam_params.svh" module cam_top #( parameter bit WRITE_NOISE_EN = 1'b1, parameter int WRITE_NOISE_RATE_NUM = 1, parameter int WRITE_NOISE_RATE_DEN = 100, parameter int WRITE_NOISE_BITS = 8, parameter logic [63:0] WRITE_NOISE_SEED = 64'hB504_F32D_B504_F32D, parameter bit READ_NOISE_EN = 1'b1, parameter int READ_NOISE_RATE_NUM = 1, parameter int READ_NOISE_RATE_DEN = 100, parameter int READ_NOISE_BITS = 8, parameter logic [63:0] READ_NOISE_SEED = 64'h6A09_E667_F3BC_C909 ) ( input logic clk, input logic rst_n, // Write interface (handshake) input logic wr_valid, output logic wr_ready, input logic [(`ROW_BITS)-1:0] wr_addr, input logic [(`HASH_BITS)-1:0] write_hash, // Query interface input logic query_valid, output logic query_ready, input logic [(`HASH_BITS)-1:0] query_hash, // Result interface output logic result_valid, input logic result_ready, output logic [(`ROW_BITS)-1:0] top1_index, output logic [(`SCORE_BITS)-1:0] top1_score, `ifdef SIM_DEBUG output logic [(`NUM_ROWS)*(`SCORE_BITS)-1:0] score_debug_flat, `endif output logic busy ); // ── Internal signals ── logic storage_wr_ready; // cam_noisy write-side ready logic match_query_ready; // match_engine_pipeline idle logic match_busy; // match_engine_pipeline scanning/result pending // ── Internal valid forwarding ── logic storage_wr_valid; logic match_query_valid; // ── Half-duplex arbitration (write-priority) ── // Active query scan blocks new writes. assign wr_ready = storage_wr_ready && match_query_ready && !match_busy; assign query_ready = storage_wr_ready && match_query_ready && !wr_valid; assign busy = (!storage_wr_ready) || match_busy || (!match_query_ready); // ── Internal valid forwarding (only assert to sub-modules when top-level accepts) ── assign storage_wr_valid = wr_valid && wr_ready; assign match_query_valid = query_valid && query_ready; // ── Read request/response bus between cam_noisy and match_engine_pipeline ── wire rd_req_valid; wire [(`ROW_BITS)-1:0] rd_req_base_row; wire rd_resp_valid; wire [(`LANES)*(`ROW_BITS)-1:0] rd_resp_row_ids; wire [(`LANES)*(`HASH_BITS)-1:0] rd_resp_hashes; wire [(`LANES)-1:0] rd_resp_lane_valid; cam_noisy #( .WRITE_NOISE_EN (WRITE_NOISE_EN), .WRITE_NOISE_RATE_NUM (WRITE_NOISE_RATE_NUM), .WRITE_NOISE_RATE_DEN (WRITE_NOISE_RATE_DEN), .WRITE_NOISE_BITS (WRITE_NOISE_BITS), .WRITE_NOISE_SEED (WRITE_NOISE_SEED), .READ_NOISE_EN (READ_NOISE_EN), .READ_NOISE_RATE_NUM (READ_NOISE_RATE_NUM), .READ_NOISE_RATE_DEN (READ_NOISE_RATE_DEN), .READ_NOISE_BITS (READ_NOISE_BITS), .READ_NOISE_SEED (READ_NOISE_SEED) ) u_noisy ( .clk (clk), .rst_n (rst_n), .wr_valid (storage_wr_valid), .wr_ready (storage_wr_ready), .wr_addr (wr_addr), .write_hash (write_hash), .rd_valid_i (rd_req_valid), .rd_base_row_i (rd_req_base_row), .rd_valid_o (rd_resp_valid), .rd_row_ids_o (rd_resp_row_ids), .rd_hashes_o (rd_resp_hashes), .rd_lane_valid_o (rd_resp_lane_valid) ); match_engine_pipeline u_match ( .clk (clk), .rst_n (rst_n), .query_valid (match_query_valid), .query_ready (match_query_ready), .query_hash (query_hash), .result_valid (result_valid), .result_ready (result_ready), .result_row (top1_index), .result_score (top1_score), .busy (match_busy), .rd_valid_o (rd_req_valid), .rd_base_row_o (rd_req_base_row), .rd_valid_i (rd_resp_valid), .rd_row_ids_i (rd_resp_row_ids), .rd_hashes_i (rd_resp_hashes), .rd_lane_valid_i (rd_resp_lane_valid) `ifdef SIM_DEBUG ,.score_debug_flat (score_debug_flat) `endif ); endmodule