`timescale 1ns/1ps `include "cam_params.svh" module cam_top #( parameter bit NOISE_EN = 1'b1, parameter int NOISE_RATE_NUM = 1, parameter int NOISE_RATE_DEN = 100, parameter int NOISE_BITS = 8, parameter logic [63:0] NOISE_SEED = 64'hB504_F32D_B504_F32D ) ( 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 idle logic match_query_ready; // match_engine idle logic match_busy; // match_engine scanning/result pending // ── Internal valid forwarding ── logic storage_wr_valid; logic match_query_valid; // ── Half-duplex arbitration (write-priority) ── // When both wr_valid and query_valid are high, write wins. assign wr_ready = storage_wr_ready && match_query_ready; 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; // ── Shared read bus ── wire [(`LANES)*(`ROW_BITS)-1:0] rd_addr_lanes_flat; wire [(`LANES)*(`HASH_BITS)-1:0] rd_hash_lanes_flat; cam_noisy #( .NOISE_EN (NOISE_EN), .NOISE_RATE_NUM (NOISE_RATE_NUM), .NOISE_RATE_DEN (NOISE_RATE_DEN), .NOISE_BITS (NOISE_BITS), .NOISE_SEED (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_addr_lanes_flat (rd_addr_lanes_flat), .rd_hash_lanes_flat (rd_hash_lanes_flat) ); match_engine 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_addr_lanes_flat (rd_addr_lanes_flat), .rd_hash_lanes_flat (rd_hash_lanes_flat) `ifdef SIM_DEBUG ,.score_debug_flat (score_debug_flat) `endif ); endmodule