// butterfly_unit.v - Cooley-Tukey / Gentleman-Sande butterfly // // Computes one butterfly operation for NTT or inverse NTT. // // Parameters: // Q = 3329 (prime modulus) // // Forward NTT (mode=0): // t = zeta * b mod Q (via barrett_mul) // a_out = (a + t) mod Q // b_out = (a - t) mod Q // // Inverse NTT (mode=1): // a_out = (a + b) mod Q // diff = (b - a) mod Q (handled as: if b >= a: b-a; else: b-a+Q) // b_out = zeta * diff mod Q (via barrett_mul) // // Pure combinational. module butterfly_unit ( input [11:0] a, input [11:0] b, input [11:0] zeta, input mode, // 0 = forward NTT, 1 = inverse NTT output [11:0] a_out, output [11:0] b_out ); localparam Q = 3329; // Barrett modular multiplication: zeta * mul_data mod Q wire [11:0] mul_data; // what to multiply with zeta wire [11:0] mul_result; // result of barrett_mul(zeta, mul_data) // Forward: mul_data = b, t = zeta * b mod Q // Inverse: mul_data = (b - a) mod Q positive assign mul_data = (mode == 1'b0) ? b : ((b >= a) ? (b - a) : (b - a + Q)); barrett_mul u_barrett ( .a (zeta), .b (mul_data), .product (mul_result) ); // ---- a_out computation ---- // Forward: a_out = (a + t) mod Q // Inverse: a_out = (a + b) mod Q wire [12:0] a_sum; wire [11:0] add_val; assign add_val = (mode == 1'b0) ? mul_result : b; assign a_sum = {1'b0, a} + {1'b0, add_val}; // a_sum - Q produces 13-bit result; we only need lower 12 bits since // a_sum >= Q guarantees the result < Q < 2^12 wire [11:0] a_sub_12; assign a_sub_12 = a_sum[11:0] - Q[11:0]; wire [11:0] a_result = (a_sum >= Q) ? a_sub_12 : a_sum[11:0]; assign a_out = a_result; // ---- b_out computation ---- // Forward: b_out = (a - t) mod Q → if a >= t: a-t; else: a-t+Q // Inverse: b_out = t (mul_result, which is zeta * (b-a) mod Q) wire [11:0] sub_val; assign sub_val = mul_result; wire [11:0] sub_result; assign sub_result = (a >= sub_val) ? (a - sub_val) : (a - sub_val + Q); assign b_out = (mode == 1'b0) ? sub_result : mul_result; endmodule