module poly1305_core #( ) ( input i_clk, input i_rst, input [255:0] i_otk, input i_otk_valid, output [127:0] o_tag, output o_tag_valid, taxi_axis_if.snk s_data_axis ); // incoming data must be 128 bit and packed, i.e. tkeep is 1 except for the last beat with no gaps localparam R_MASK = 128'h0ffffffc0ffffffc0ffffffc0fffffff; localparam P130M5 = 258'h3fffffffffffffffffffffffffffffffb; logic [127:0] poly1305_r, poly1305_s; logic [129:0] accumulator, accumulator_next; logic [129:0] data_one_extended; logic [130:0] data_post_add; logic [257:0] data_post_mul, data_post_mul_reg; logic phase; logic [1:0] valid_sr; function logic [129:0] tkeep_expand (input [15:0] tkeep); tkeep_expand = '0; for (int i = 0; i < 16; i++) begin tkeep_expand[i*8 +: 8] = {8{tkeep[i]}}; end endfunction // only ready in phase 0 assign s_data_axis.tready = phase == 0; assign o_tag_valid = valid_sr[1]; always_ff @(posedge i_clk) begin if (i_rst) begin phase <= '0; valid_sr <= '0; end valid_sr <= {valid_sr[0], s_data_axis.tlast & s_data_axis.tvalid & s_data_axis.tready & ~phase}; if (i_otk_valid) begin poly1305_r <= i_otk[255:128] & R_MASK; poly1305_s <= i_otk[127:0]; end if (s_data_axis.tvalid && phase == 0) begin data_post_mul_reg <= data_post_mul; phase <= '1; end if (phase == '1) begin accumulator <= accumulator_next; phase <= '0; end end always_comb begin accumulator_next = accumulator; data_post_mul = '0; // phase == 0 data_one_extended = (tkeep_expand(s_data_axis.tkeep) + 1) | {2'b0, s_data_axis.tdata}; data_post_add = data_one_extended + accumulator; data_post_mul = data_post_add * poly1305_r; // phase == 1 accumulator_next = 130'(data_post_mul_reg % P130M5); end assign o_tag = accumulator[127:0] + poly1305_s; endmodule