diff --git a/ChaCha20_Poly1305_64/doc/notes2.md b/ChaCha20_Poly1305_64/doc/notes2.md new file mode 100644 index 0000000..64f1f73 --- /dev/null +++ b/ChaCha20_Poly1305_64/doc/notes2.md @@ -0,0 +1,26 @@ +# Requirements + +* 2 Gbps operation +* Handles both encrypt and decrypt + +At reasonable FPGA speed of 250MHz, 2 Gbps requires a minimum width of 8 bits. + +32 bits is a reasonable data width that would be common to see, and lets us +have more breathing room while still maintaining line rate. + +Module inputs and outputs + +* clk +* rst +* data_in [31:0] +* data_valid +* data_ready +* data_last +* r [127:0] +* s [127:0] +* mac [127:0] +* mac_valid + +There is no output backpressure. since the result is just a single 128 bit number, +we don't need to have a ready signal. if you want to add backpressure, add a register +slice on the output outside of this module. diff --git a/ChaCha20_Poly1305_64/doc/poly1305_2.drawio b/ChaCha20_Poly1305_64/doc/poly1305_2.drawio new file mode 100644 index 0000000..602ba7b --- /dev/null +++ b/ChaCha20_Poly1305_64/doc/poly1305_2.drawio @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChaCha20_Poly1305_64/sim/poly1305.yaml b/ChaCha20_Poly1305_64/sim/poly1305.yaml index 0d64252..eb5161a 100644 --- a/ChaCha20_Poly1305_64/sim/poly1305.yaml +++ b/ChaCha20_Poly1305_64/sim/poly1305.yaml @@ -22,4 +22,16 @@ tests: modules: - "poly1305_stage" sources: sources.list + waves: True + - name: "poly1305_width_convert" + toplevel: "poly1305_width_convert" + modules: + - "poly1305_width_convert" + sources: sources.list + waves: True + - name: "poly1305_ll_stage" + toplevel: "poly1305_ll_stage" + modules: + - "poly1305_ll_stage" + sources: sources.list waves: True \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/sim/poly1305_ll_stage.py b/ChaCha20_Poly1305_64/sim/poly1305_ll_stage.py new file mode 100644 index 0000000..8d445e1 --- /dev/null +++ b/ChaCha20_Poly1305_64/sim/poly1305_ll_stage.py @@ -0,0 +1,72 @@ +import cocotb + +from cocotb.clock import Clock +from cocotb.triggers import Timer, RisingEdge, FallingEdge +from cocotb.handle import Immediate + +import random + +from array import array + +CLK_PERIOD = 5 + +@cocotb.test +async def test_sanity(dut): + + data_bytes = b"Cryptographic Forum Research Group" + + countm1 = [3 for _ in range(len(data_bytes)//4)] + if len(data_bytes) % 4: + countm1 += [len(data_bytes) % 4 -1] + + print(len(data_bytes) % 4) + print(len(data_bytes)) + print(countm1) + + data_bytes += (len(data_bytes) - (len(data_bytes) //4 ) * 4) * b'\x00' + data_in = array("I", data_bytes).tolist() + + + print(data_in) + + async def input_data(): + for count, word in zip(countm1, data_in[:-1]): + dut.i_data.value = word + dut.i_countm1.value = count + dut.i_valid.value = 1 + dut.i_last.value = 0 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_data.value = data_in[-1] + dut.i_countm1.value = countm1[-1] + dut.i_valid.value = 1 + dut.i_last.value = 1 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_valid.value = 0 + dut.i_last.value = 0 + + cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start()) + + dut.i_rst.value = Immediate(0) + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 1 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 0 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + + dut.i_r.value = 0x806d5400e52447c036d555408bed685 + dut.i_s.value = 0x1bf54941aff6bf4afdb20dfb8a800301 + + cocotb.start_soon(input_data()) + + await Timer(1, "us") \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/sim/poly1305_width_convert.py b/ChaCha20_Poly1305_64/sim/poly1305_width_convert.py new file mode 100644 index 0000000..5d7241c --- /dev/null +++ b/ChaCha20_Poly1305_64/sim/poly1305_width_convert.py @@ -0,0 +1,480 @@ +import cocotb + +from cocotb.clock import Clock +from cocotb.triggers import Timer, RisingEdge, FallingEdge +from cocotb.handle import Immediate + +import math + +import random + +CLK_PERIOD = 5 + + +@cocotb.test +async def test_sanity(dut): + + data_in = [random.randint(0, 2**32-1) for _ in range(32)] + + async def input_data(): + for word in data_in[:-1]: + dut.i_data.value = word + dut.i_valid.value = 1 + dut.i_last.value = 0 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_data.value = data_in[-1] + dut.i_valid.value = 1 + dut.i_last.value = 1 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_valid.value = 0 + dut.i_last.value = 0 + + data_out = [] + + async def output_data(): + while True: + if (dut.o_valid.value): + data_out.append(int(dut.o_data.value)) + await RisingEdge(dut.i_clk) + + cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start()) + + + dut.i_rst.value = Immediate(0) + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 1 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 0 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + + dut.i_ready.value = 1 + + cocotb.start_soon(input_data()) + cocotb.start_soon(output_data()) + + await RisingEdge(dut.o_last) + + await RisingEdge(dut.i_clk) + + expected_data_out = [] + for i in range(math.ceil(len(data_in)/4)): + vals = data_in[i*4:(i+1)*4] + + converted = 0 + for i, val in enumerate(vals): + converted |= val << (32*i) + + expected_data_out.append(converted) + + + assert data_out == expected_data_out + +@cocotb.test +async def test_incomplete_last(dut): + data_in = [random.randint(0, 2**32-1) for _ in range(30)] + + async def input_data(): + for word in data_in[:-1]: + dut.i_data.value = word + dut.i_valid.value = 1 + dut.i_last.value = 0 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_data.value = data_in[-1] + dut.i_valid.value = 1 + dut.i_last.value = 1 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_valid.value = 0 + dut.i_last.value = 0 + + data_out = [] + + async def output_data(): + while True: + if (dut.o_valid.value): + data_out.append(int(dut.o_data.value)) + await RisingEdge(dut.i_clk) + + cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start()) + + + dut.i_rst.value = Immediate(0) + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 1 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 0 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + + dut.i_ready.value = 1 + + cocotb.start_soon(input_data()) + cocotb.start_soon(output_data()) + + await RisingEdge(dut.o_last) + + await RisingEdge(dut.i_clk) + + expected_data_out = [] + for i in range(math.ceil(len(data_in)/4)): + vals = data_in[i*4:(i+1)*4] + + converted = 0 + for i, val in enumerate(vals): + converted |= val << (32*i) + + expected_data_out.append(converted) + + + assert data_out == expected_data_out + + +@cocotb.test +async def test_output_backpressure(dut): + data_in = [random.randint(0, 2**32-1) for _ in range(32)] + + async def input_data(): + for word in data_in[:-1]: + dut.i_data.value = word + dut.i_valid.value = 1 + dut.i_last.value = 0 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_data.value = data_in[-1] + dut.i_valid.value = 1 + dut.i_last.value = 1 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_valid.value = 0 + dut.i_last.value = 0 + + data_out = [] + + async def output_data(): + while True: + if (dut.o_valid.value and dut.i_ready.value): + data_out.append(int(dut.o_data.value)) + await RisingEdge(dut.i_clk) + + cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start()) + + + dut.i_rst.value = Immediate(0) + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 1 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 0 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + + async def output_backpressure(): + while True: + await RisingEdge(dut.i_clk) + + dut.i_ready.value = random.randint(0, 100) < 75 + + cocotb.start_soon(output_backpressure()) + cocotb.start_soon(input_data()) + cocotb.start_soon(output_data()) + + while True: + await RisingEdge(dut.i_clk) + if dut.o_last.value and dut.i_ready.value: + break + + await RisingEdge(dut.i_clk) + + + expected_data_out = [] + for i in range(math.ceil(len(data_in)/4)): + vals = data_in[i*4:(i+1)*4] + + converted = 0 + for i, val in enumerate(vals): + converted |= val << (32*i) + + expected_data_out.append(converted) + + + if not data_out == expected_data_out: + print(data_out) + print(expected_data_out) + + assert data_out == expected_data_out + +@cocotb.test +async def test_output_backpressure_nonfull(dut): + data_in = [random.randint(0, 2**32-1) for _ in range(30)] + + async def input_data(): + for word in data_in[:-1]: + dut.i_data.value = word + dut.i_valid.value = 1 + dut.i_last.value = 0 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_data.value = data_in[-1] + dut.i_valid.value = 1 + dut.i_last.value = 1 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_valid.value = 0 + dut.i_last.value = 0 + + data_out = [] + + async def output_data(): + while True: + if (dut.o_valid.value and dut.i_ready.value): + data_out.append(int(dut.o_data.value)) + await RisingEdge(dut.i_clk) + + cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start()) + + + dut.i_rst.value = Immediate(0) + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 1 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 0 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + + async def output_backpressure(): + while True: + await RisingEdge(dut.i_clk) + + dut.i_ready.value = random.randint(0, 100) < 75 + + cocotb.start_soon(output_backpressure()) + cocotb.start_soon(input_data()) + cocotb.start_soon(output_data()) + + while True: + await RisingEdge(dut.i_clk) + if dut.o_last.value and dut.i_ready.value: + break + + await RisingEdge(dut.i_clk) + + + expected_data_out = [] + for i in range(math.ceil(len(data_in)/4)): + vals = data_in[i*4:(i+1)*4] + + converted = 0 + for i, val in enumerate(vals): + converted |= val << (32*i) + + expected_data_out.append(converted) + + + if not data_out == expected_data_out: + print(data_out) + print(expected_data_out) + + assert data_out == expected_data_out + + +@cocotb.test +async def test_input_nonvalid(dut): + data_in = [random.randint(0, 2**32-1) for _ in range(32)] + + async def input_data(): + for word in data_in[:-1]: + dut.i_data.value = word + dut.i_valid.value = 1 + dut.i_last.value = 0 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + if random.randint(0, 10) > 7: + dut.i_valid.value = 0 + await RisingEdge(dut.i_clk) + + + dut.i_data.value = data_in[-1] + dut.i_valid.value = 1 + dut.i_last.value = 1 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_valid.value = 0 + dut.i_last.value = 0 + + data_out = [] + + async def output_data(): + while True: + if (dut.o_valid.value and dut.i_ready.value): + data_out.append(int(dut.o_data.value)) + await RisingEdge(dut.i_clk) + + cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start()) + + + dut.i_rst.value = Immediate(0) + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 1 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 0 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + + dut.i_ready.value = 1 + + cocotb.start_soon(input_data()) + cocotb.start_soon(output_data()) + + while True: + await RisingEdge(dut.i_clk) + if dut.o_last.value and dut.i_ready.value: + break + + await RisingEdge(dut.i_clk) + + + expected_data_out = [] + for i in range(math.ceil(len(data_in)/4)): + vals = data_in[i*4:(i+1)*4] + + converted = 0 + for i, val in enumerate(vals): + converted |= val << (32*i) + + expected_data_out.append(converted) + + + if not data_out == expected_data_out: + print(data_out) + print(expected_data_out) + + assert data_out == expected_data_out + +@cocotb.test +async def test_input_nonvalid_output_nonready(dut): + data_in = [random.randint(0, 2**32-1) for _ in range(30)] + + async def input_data(): + for word in data_in[:-1]: + dut.i_data.value = word + dut.i_valid.value = 1 + dut.i_last.value = 0 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + if random.randint(0, 10) > 7: + dut.i_valid.value = 0 + await RisingEdge(dut.i_clk) + + + dut.i_data.value = data_in[-1] + dut.i_valid.value = 1 + dut.i_last.value = 1 + + await RisingEdge(dut.i_clk) + while (not dut.o_ready.value): + await RisingEdge(dut.i_clk) + + dut.i_valid.value = 0 + dut.i_last.value = 0 + + data_out = [] + + async def output_data(): + while True: + if (dut.o_valid.value and dut.i_ready.value): + data_out.append(int(dut.o_data.value)) + await RisingEdge(dut.i_clk) + + cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start()) + + + dut.i_rst.value = Immediate(0) + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 1 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + dut.i_rst.value = 0 + await RisingEdge(dut.i_clk) + await RisingEdge(dut.i_clk) + + async def output_backpressure(): + while True: + await RisingEdge(dut.i_clk) + + dut.i_ready.value = random.randint(0, 100) < 75 + + cocotb.start_soon(output_backpressure()) + cocotb.start_soon(input_data()) + cocotb.start_soon(output_data()) + + while True: + await RisingEdge(dut.i_clk) + if dut.o_last.value and dut.i_ready.value: + break + + await RisingEdge(dut.i_clk) + + + expected_data_out = [] + for i in range(math.ceil(len(data_in)/4)): + vals = data_in[i*4:(i+1)*4] + + converted = 0 + for i, val in enumerate(vals): + converted |= val << (32*i) + + expected_data_out.append(converted) + + + if not data_out == expected_data_out: + print(data_out) + print(expected_data_out) + + assert data_out == expected_data_out \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/src/poly1305_friendly_modular_mult.sv b/ChaCha20_Poly1305_64/src/poly1305_friendly_modular_mult.sv index 985d9f4..f32e880 100644 --- a/ChaCha20_Poly1305_64/src/poly1305_friendly_modular_mult.sv +++ b/ChaCha20_Poly1305_64/src/poly1305_friendly_modular_mult.sv @@ -1,3 +1,5 @@ +// FPGA Friendly modular multiplication. takes ~6 cycles + module poly1305_friendly_modular_mult #( parameter DATA_WIDTH = 130, parameter ACC_WIDTH = 130 diff --git a/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv b/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv new file mode 100644 index 0000000..8958691 --- /dev/null +++ b/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv @@ -0,0 +1,231 @@ +// Low latency poly1305 core +// +// Target 2 cycles per 128 bit block + +module poly1305_ll_stage ( + input logic i_clk, + input logic i_rst, + + input logic i_valid, + input logic [1:0] i_countm1, + output logic o_ready, + input logic [31:0] i_data, + input logic i_last, + input logic [127:0] i_r, + input logic [127:0] i_s, + + output logic o_valid, + output logic [127:0] o_result +); + +localparam [129:0] PRIME = (1 << 130) - 5; + +logic upconvert_ready; +logic upconvert_valid; +logic upconvert_last; +logic [127:0] upconvert_data; +logic [3:0] upconvert_countm1; + + +poly1305_width_convert u_width_convert( + .i_clk (i_clk), + .i_rst (i_rst), + + .i_valid (i_valid), + .i_countm1 (i_countm1), + .o_ready (o_ready), + .i_data (i_data), + .i_last (i_last), + + .o_valid (upconvert_valid), + .o_countm1 (upconvert_countm1), + .i_ready (upconvert_ready), + .o_data (upconvert_data), + .o_last (upconvert_last) +); + +logic [127:0] r_reg, s_reg, s_reg_2; +logic [127:0] r_reg_next, s_reg_next, s_reg_2_next;; + +enum logic [2:0] {IDLE, SUM, MULT, MODULO_1, MODULO_2} state, state_next; + +enum logic [1:0] {OUTPUT_IDLE, OUTPUT_ADD, OUTPUT_OUT} output_state, output_state_next; + +logic [129:0] h, h_next; + +logic [130:0] data_1extend; + +logic [130:0] sum, sum_next; + +logic [258:0] product, product_next; + +logic [131:0] mod1; +logic [131:0] mod2_upper, mod2_upper_next; +logic [129:0] mod2_lower, mod2_lower_next; +logic [131:0] mod2; +logic [131:0] mod3; + + +logic [130:0] final_sum, final_sum_next; +logic [130:0] final_mod; + +logic start_output; + +logic last_flag, last_flag_next; + +always_ff @(posedge i_clk) begin + if (i_rst) begin + r_reg <= '0; + s_reg <= '0; + s_reg_2 <= '0; + + last_flag <= '0; + + state <= IDLE; + output_state <= OUTPUT_IDLE; + end else begin + r_reg <= r_reg_next; + s_reg <= s_reg_next; + s_reg_2 <= s_reg_2_next; + + mod2_upper <= mod2_upper_next; + mod2_lower <= mod2_lower_next; + + h <= h_next; + + sum <= sum_next; + product <= product_next; + + last_flag <= last_flag_next; + + state <= state_next; + output_state <= output_state_next; + + final_sum <= final_sum_next; + end +end + +always_comb begin + h_next = h; + + sum_next = '0; + product_next = '0; + + r_reg_next = r_reg; + s_reg_next = s_reg; + + upconvert_ready = '0; + + last_flag_next = last_flag; + + state_next = state; + + mod1 = '0; + mod2 = '0; + mod2_upper_next = '0; + mod2_lower_next = '0; + mod3 = '0; + + data_1extend = '0; + + start_output = '0; + + case (state) + IDLE: begin + upconvert_ready = '1; + + if (upconvert_valid) begin + data_1extend = {3'b0, upconvert_data} | (131'b1 << (8*(1+upconvert_countm1))); + sum_next = data_1extend; + + state_next = MULT; + + r_reg_next = i_r; + s_reg_next = i_s; + end + end + + SUM: begin + last_flag_next = upconvert_last; + + upconvert_ready = '1; + data_1extend = {3'b0, upconvert_data} | (131'b1 << (8*(1+upconvert_countm1))); + sum_next = h + data_1extend; + + state_next = MULT; + end + + MULT: begin + product_next = sum * r_reg; + + state_next = MODULO_1; + end + + MODULO_1: begin + mod1 = (product[258:130] * 5) + {2'b0, product[129:0]}; + mod2_upper_next = mod1[131:130] * 5; + mod2_lower_next = mod1[129:0]; + + state_next = MODULO_2; + end + + MODULO_2: begin + mod2 = mod2_upper + {2'b0, mod2_lower}; + mod3 = (mod2[131:130] * 5) + {2'b0, mod2[129:0]}; + + if (mod3[129:0] > PRIME) begin + h_next = mod3[129:0] - PRIME; + end else begin + h_next = mod3[129:0]; + end + + if (last_flag) begin + state_next = IDLE; + last_flag_next = '0; + s_reg_2_next = s_reg; + start_output = '1; + end else begin + state_next = SUM; + end + end + + default: begin + + end + + endcase + + output_state_next = output_state; + + case (output_state) + OUTPUT_IDLE: begin + if (start_output) begin + output_state_next = OUTPUT_ADD; + end + end + + OUTPUT_ADD: begin + final_sum_next = h + {3'b0, s_reg_2}; + output_state_next = OUTPUT_OUT; + end + + OUTPUT_OUT: begin + if (final_sum > {1'b0, PRIME}) begin + final_mod = final_sum - PRIME; + end else begin + final_mod = final_sum; + end + + o_valid = '1; + o_result = final_mod[127:0]; + + output_state_next = OUTPUT_IDLE; + end + + default: begin + + end + endcase +end + +endmodule \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/src/poly1305_width_convert.sv b/ChaCha20_Poly1305_64/src/poly1305_width_convert.sv new file mode 100644 index 0000000..e231588 --- /dev/null +++ b/ChaCha20_Poly1305_64/src/poly1305_width_convert.sv @@ -0,0 +1,79 @@ +module poly1305_width_convert( + input logic i_clk, + input logic i_rst, + + input logic i_valid, + input logic [1:0] i_countm1, + output logic o_ready, + input logic [31:0] i_data, + input logic i_last, + + output logic o_valid, + output logic [3:0] o_countm1, + input logic i_ready, + output logic [127:0] o_data, + output logic o_last +); + + +logic [95:0] width_convert_save, width_convert_save_next; +logic [1:0] width_convert_count, width_convert_count_next; + +always_ff @(posedge i_clk) begin + if (i_rst) begin + width_convert_save <= '0; + width_convert_count <= '0; + end else begin + width_convert_count <= width_convert_count_next; + width_convert_save <= width_convert_save_next; + end +end + +always_comb begin + width_convert_save_next = width_convert_save; + width_convert_count_next = width_convert_count; + + o_valid = '0; + o_ready = '0; + o_last = '0; + + o_countm1 = '1; + + if (width_convert_count < 3) begin + o_data = {32'b0, width_convert_save}; + o_data[32*width_convert_count +: 32] = i_data; + + if (i_last && i_valid) begin + o_ready = i_ready; + o_valid = '1; + o_last = '1; + + o_countm1 = width_convert_count*4 + {2'b0, i_countm1}; + + if (i_ready) begin + width_convert_count_next = '0; + width_convert_save_next = '0; + end + end else begin + width_convert_save_next[32*width_convert_count +: 32] = i_data; + if (i_valid) begin + o_ready = '1; + width_convert_count_next = width_convert_count + 2'd1; + end + end + end else begin + o_ready = i_ready; + o_valid = i_valid; + o_data = {i_data, width_convert_save}; + o_last = i_last; + + o_countm1 = 4'd12 + {2'b0, i_countm1}; + + if (i_valid && o_ready) begin + width_convert_count_next = '0; + width_convert_save_next = '0; + end + end +end + +endmodule \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/src/sources.list b/ChaCha20_Poly1305_64/src/sources.list index e488302..a061972 100644 --- a/ChaCha20_Poly1305_64/src/sources.list +++ b/ChaCha20_Poly1305_64/src/sources.list @@ -6,4 +6,7 @@ chacha20_pipelined_block.sv poly1305_core.sv poly1305_friendly_modulo.sv poly1305_friendly_modular_mult.sv -poly1305_stage.sv \ No newline at end of file +poly1305_stage.sv + +poly1305_width_convert.sv +poly1305_ll_stage.sv \ No newline at end of file