// barrett_mul.v - Barrett modular multiplication (a * b mod Q) // // Computes product = a * b mod Q using Barrett reduction. // Q = 3329, k = floor(2^24 / Q) = 5039 // // Pure combinational, single-cycle latency. // All multiplication widths explicitly controlled to avoid Verilog truncation. module barrett_mul ( input [11:0] a, input [11:0] b, output [11:0] product ); localparam Q = 3329; localparam K = 5039; // floor(2^24 / 3329) localparam R = 24; // Full product: a * b (both < 3329, product < 11,082,241 < 2^24) // Force 24-bit evaluation by extending operand wire [23:0] p; assign p = {12'd0, a} * b; // Extend p to 37 bits for multiplication with K wire [36:0] p_ext; assign p_ext = {13'd0, p}; // Compute t_shifted = (p * K) >> 24 // Use explicit wire for the product to control width /* verilator lint_off UNUSEDSIGNAL */ wire [36:0] t_product; /* verilator lint_on UNUSEDSIGNAL */ assign t_product = p_ext * K; wire [12:0] t_shifted; assign t_shifted = t_product[36:R]; // q_approx = t_shifted * Q wire [24:0] q_approx; assign q_approx = t_shifted * Q; // r = p - q_approx wire [24:0] r0; assign r0 = {1'b0, p} - q_approx; // Conditional subtract Q (at most twice) wire [24:0] r1; assign r1 = (r0 >= Q) ? (r0 - Q) : r0; wire [11:0] r2; assign r2 = (r1[11:0] >= Q) ? (r1[11:0] - Q) : r1[11:0]; assign product = (r1 >= Q) ? r2 : r1[11:0]; endmodule