48 lines
1.3 KiB
Systemverilog
48 lines
1.3 KiB
Systemverilog
module poly1305_friendly_modulo #(
|
|
parameter WIDTH = 130,
|
|
parameter MDIFF = 5, // modulo difference
|
|
parameter SHIFT_SIZE = 26
|
|
) (
|
|
input logic i_clk,
|
|
input logic i_rst,
|
|
|
|
input logic i_valid,
|
|
input logic [2*WIDTH-1:0] i_val,
|
|
input logic [2:0] i_shift_amount,
|
|
|
|
output logic o_valid,
|
|
output logic [WIDTH-1:0] o_result
|
|
);
|
|
|
|
localparam WIDE_WIDTH = WIDTH + $clog2(MDIFF);
|
|
localparam [WIDTH-1:0] PRIME = (1 << WIDTH) - MDIFF;
|
|
|
|
logic [WIDE_WIDTH-1:0] high_part_1, high_part_2;
|
|
logic [WIDTH-1:0] low_part_1, low_part_2;
|
|
|
|
logic [WIDE_WIDTH-1:0] intermediate_val;
|
|
logic [WIDTH-1:0] final_val;
|
|
|
|
logic [2:0] unused_final;
|
|
|
|
logic [2:0] valid_sr;
|
|
|
|
assign intermediate_val = high_part_1 + WIDE_WIDTH'(low_part_1);
|
|
|
|
assign o_result = (final_val >= PRIME) ? final_val - PRIME : final_val;
|
|
|
|
assign o_valid = valid_sr[2];
|
|
|
|
always_ff @(posedge i_clk) begin
|
|
valid_sr <= {valid_sr[1:0], i_valid};
|
|
|
|
high_part_1 <= WIDTH'({3'b0, i_val} >> (130 - (i_shift_amount*SHIFT_SIZE))) * MDIFF;
|
|
low_part_1 <= WIDTH'(i_val << (i_shift_amount*SHIFT_SIZE));
|
|
|
|
high_part_2 <= (intermediate_val >> WIDTH) * 5;
|
|
low_part_2 <= intermediate_val[WIDTH-1:0];
|
|
|
|
{unused_final, final_val} <= high_part_2 + WIDE_WIDTH'(low_part_2);
|
|
end
|
|
|
|
endmodule |