// barrett_mul_pipe.v - DSP-friendly pipelined Barrett modular multiply // // Computes product = a * b mod Q with fixed latency. This module is used on // timing-critical NTT paths; the legacy barrett_mul remains combinational for // older users. module barrett_mul_pipe ( input clk, input rst_n, input valid_i, input [11:0] a, input [11:0] b, output [11:0] product, output valid_o ); localparam [24:0] Q25 = 25'd3329; localparam [12:0] K13 = 13'd5039; reg [23:0] p_s1; reg [23:0] p_s2; reg [36:0] tk_s2; reg [23:0] p_s3; reg [12:0] q_s3; reg [24:0] p_s4; reg [24:0] qprod_s4; reg [24:0] r0_s5; reg [24:0] r1_s6; reg [11:0] product_r; reg [6:0] valid_sr; assign product = product_r; assign valid_o = valid_sr[6]; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin p_s1 <= 24'd0; p_s2 <= 24'd0; tk_s2 <= 37'd0; p_s3 <= 24'd0; q_s3 <= 13'd0; p_s4 <= 25'd0; qprod_s4 <= 25'd0; r0_s5 <= 25'd0; r1_s6 <= 25'd0; product_r <= 12'd0; valid_sr <= 7'd0; end else begin valid_sr <= {valid_sr[5:0], valid_i}; // S1: full product. p_s1 <= {12'd0, a} * b; // S2: quotient-estimate product. p_s2 <= p_s1; tk_s2 <= {13'd0, p_s1} * K13; // S3: quotient estimate. p_s3 <= p_s2; q_s3 <= tk_s2[36:24]; // S4: q * Q. p_s4 <= {1'b0, p_s3}; qprod_s4 <= q_s3 * Q25; // S5/S6/S7: subtract q*Q and conditionally subtract Q twice. r0_s5 <= p_s4 - qprod_s4; r1_s6 <= (r0_s5 >= Q25) ? (r0_s5 - Q25) : r0_s5; product_r <= (r1_s6 >= Q25) ? (r1_s6 - Q25) : r1_s6[11:0]; end end endmodule