diff --git a/ChaCha20_Poly1305_64/doc/notes.md b/ChaCha20_Poly1305_64/doc/notes.md index 5240428..4c7cf4d 100644 --- a/ChaCha20_Poly1305_64/doc/notes.md +++ b/ChaCha20_Poly1305_64/doc/notes.md @@ -33,4 +33,34 @@ we need r\*r = r^2 r\*r^2 = r^3 r^2\*r^2 = r^4 -r^4\*r = r^5 r^2\*r^4 = r^6 r^3\*r^4 = r^7 r^4\*r^4 = r^8 \ No newline at end of file +r^4\*r = r^5 r^2\*r^4 = r^6 r^3\*r^4 = r^7 r^4\*r^4 = r^8 + +we can do all of these in parallel, so we 4 (n/2) multiply blocks that feed back +on themselves, with some kind of FSM to control it. This can be done while another +block is being hashed, but there will be a delay between when the key is ready from +the chacha block and when the powers are ready, so there needs to be a fifo in between. + + +Basically we have to wait until we see that the accumulator was written with our index. +At reset though, the acumulator is unwritten? So we need to pretend that it was written + +Lets just write out what we want to happen: + +1. The index starts at 0. We accept new data, and send it through the pipeline +2. We increment the index to 1. +3. We accept new data and send it through the pipeline +4. We increment the index to 2 +5. We need to wait until the index 0 is written before we can say we are ready +6. If the index 1 is written then we still need to say we are ready though +7. We can just use the 1 to indicate that is a valid write then? + +So in the shift register we just need to say whether it is a valid write or not, +so always 1? + +But if we send in 0, then send in 1, then the current index will be 0 +and eventually the final index will always be 0. We need to store what +the last written one is. + +We can just say the last written one was 2 I guess + +We also need an input that tells it to reset the accumulator \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/doc/poly1305_second_attempt.drawio b/ChaCha20_Poly1305_64/doc/poly1305_second_attempt.drawio new file mode 100644 index 0000000..44207c0 --- /dev/null +++ b/ChaCha20_Poly1305_64/doc/poly1305_second_attempt.drawio @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChaCha20_Poly1305_64/sim/poly1305.yaml b/ChaCha20_Poly1305_64/sim/poly1305.yaml index 62e3618..0d64252 100644 --- a/ChaCha20_Poly1305_64/sim/poly1305.yaml +++ b/ChaCha20_Poly1305_64/sim/poly1305.yaml @@ -16,4 +16,10 @@ tests: modules: - "poly1305_friendly_modular_mult" sources: sources.list + waves: True + - name: "poly1305_stage" + toplevel: "poly1305_stage" + modules: + - "poly1305_stage" + sources: sources.list waves: True \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/sim/poly1305_friendly_modular_mult.py b/ChaCha20_Poly1305_64/sim/poly1305_friendly_modular_mult.py index 5eb40d7..0c7dbe5 100644 --- a/ChaCha20_Poly1305_64/sim/poly1305_friendly_modular_mult.py +++ b/ChaCha20_Poly1305_64/sim/poly1305_friendly_modular_mult.py @@ -78,7 +78,7 @@ async def test_sanity(dut): await tb.cycle_reset() - count = 1024 + count = 1 for _ in range(count): await tb.write_input(random.randint(1,2**128-1), random.randint(0, 2**130-6)) diff --git a/ChaCha20_Poly1305_64/sim/poly1305_stage.py b/ChaCha20_Poly1305_64/sim/poly1305_stage.py new file mode 100644 index 0000000..33148c5 --- /dev/null +++ b/ChaCha20_Poly1305_64/sim/poly1305_stage.py @@ -0,0 +1,110 @@ +import logging + + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import Timer, RisingEdge, FallingEdge +from cocotb.queue import Queue + +from cocotbext.axi import AxiStreamBus, AxiStreamSource + +from modulo_theory import friendly_modular_mult + +import random + +PRIME = 2**130-5 + +CLK_PERIOD = 4 + + +class TB: + def __init__(self, dut): + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.INFO) + + self.input_queue = Queue() + + self.expected_queue = Queue() + self.output_queue = Queue() + + cocotb.start_soon(Clock(self.dut.i_clk, CLK_PERIOD, units="ns").start()) + + cocotb.start_soon(self.run_input()) + cocotb.start_soon(self.run_output()) + + self.index = 0 + self.accumulators = [0, 0] + + async def cycle_reset(self): + await self._cycle_reset(self.dut.i_rst, self.dut.i_clk) + + async def _cycle_reset(self, rst, clk): + rst.setimmediatevalue(0) + await RisingEdge(clk) + await RisingEdge(clk) + rst.value = 1 + await RisingEdge(clk) + await RisingEdge(clk) + rst.value = 0 + await RisingEdge(clk) + await RisingEdge(clk) + + async def write_input(self, msg: int, r_power: int, clear_acc: int): + await self.input_queue.put((msg, r_power, clear_acc)) + if clear_acc: + expected_result = friendly_modular_mult((msg) % PRIME, r_power) + else: + expected_result = friendly_modular_mult((msg + self.accumulators[self.index]) % PRIME, r_power) + + self.accumulators[self.index] = expected_result + await self.expected_queue.put(expected_result) + self.index = 1 if self.index == 0 else 0 + + async def run_input(self): + while True: + msg, r_power, clear_acc = await self.input_queue.get() + self.dut.i_valid.value = 1 + self.dut.i_r_power.value = r_power + self.dut.i_message.value = msg + self.dut.i_clear_acc.value = clear_acc + while True: + await RisingEdge(self.dut.i_clk) + if (self.dut.o_ready.value == 1): + break + self.dut.i_valid.value = 0 + self.dut.i_r_power.value = 0 + self.dut.i_message.value = 0 + self.dut.i_clear_acc.value = 0 + + async def run_output(self): + while True: + await RisingEdge(self.dut.i_clk) + if self.dut.o_valid.value: + await self.output_queue.put(self.dut.o_result.value.integer) + +@cocotb.test +async def test_sanity(dut): + + tb = TB(dut) + + await tb.cycle_reset() + + count = 1024 + + for _ in range(count): + clr = 1 if random.randint(0,10) == 0 else 0 + await tb.write_input(random.randint(1,2**128-1), random.randint(0, 2**130-6), clr) + + fail = False + + for _ in range(count): + sim_val = await tb.expected_queue.get() + dut_val = await tb.output_queue.get() + + if sim_val != dut_val: + tb.log.info(f"{_} {sim_val:x} -> {dut_val:x}") + fail = True + + assert not fail diff --git a/ChaCha20_Poly1305_64/src/poly1305_friendly_modular_mult.sv b/ChaCha20_Poly1305_64/src/poly1305_friendly_modular_mult.sv index 3f6e51a..985d9f4 100644 --- a/ChaCha20_Poly1305_64/src/poly1305_friendly_modular_mult.sv +++ b/ChaCha20_Poly1305_64/src/poly1305_friendly_modular_mult.sv @@ -1,5 +1,5 @@ module poly1305_friendly_modular_mult #( - parameter DATA_WIDTH = 131, + parameter DATA_WIDTH = 130, parameter ACC_WIDTH = 130 ) ( input logic i_clk, @@ -54,7 +54,7 @@ always_ff @(posedge i_clk) begin end always_comb begin - data_next = data; + data_next = data; // If neccesary, we can remove this state? h_next = h; state_counter_next = state_counter; diff --git a/ChaCha20_Poly1305_64/src/poly1305_stage.sv b/ChaCha20_Poly1305_64/src/poly1305_stage.sv new file mode 100644 index 0000000..150ff2b --- /dev/null +++ b/ChaCha20_Poly1305_64/src/poly1305_stage.sv @@ -0,0 +1,145 @@ +module poly1305_stage #( + +) ( + input logic i_clk, + input logic i_rst, + + input logic i_valid, + output logic o_ready, + input logic i_clear_acc, + input logic [129:0] i_r_power, + input logic [127:0] i_message, + + output logic o_valid, + output logic [129:0] o_result +); + +localparam [129:0] PRIME = (1 << 130) - 5; + +logic mult_i_valid; +logic mult_o_ready; +logic [129:0] r_power, r_power_next; +logic [130:0] mult_accumulator, mult_accumulator_next; + +logic mult_valid; +logic [129:0] mult_result; + +logic [129:0] accumulators [2]; +logic [129:0] accumulators_next [2]; + +logic [1:0] ops_in_flight, ops_in_flight_next; + +logic [1:0] index, index_next; + + +logic [1:0] index_sr [16]; +logic [1:0] index_sr_next; + +enum logic [1:0] {SUM1, SUM2, MUL, STORE} state, state_next; + +always_ff @(posedge i_clk) begin + if (i_rst) begin + state <= SUM1; + r_power <= '0; + mult_accumulator <= '0; + ops_in_flight <= 2'h0; + index <= 2'h2; + + index_sr <= '{default: '0}; + + for (int i = 0; i < 2; i++) begin + accumulators[i] <= '0; + end + end else begin + state <= state_next; + r_power <= r_power_next; + mult_accumulator <= mult_accumulator_next; + index <= index_next; + ops_in_flight <= ops_in_flight_next; + + for (int i = 0; i < 2; i++) begin + accumulators[i] <= accumulators_next[i]; + end + + index_sr[0] <= index; + for (int i = 1; i < 16; i++) begin + index_sr[i] <= index_sr[i-1]; + end + end +end + +logic [1:0] ops_in_flight_state; +assign ops_in_flight_state = {i_valid & o_ready, mult_valid}; + +always_comb begin + state_next = state; + o_ready = '0; + mult_accumulator_next = mult_accumulator; + mult_i_valid = '0; + index_next = index; + + if (mult_valid) begin + accumulators_next[index_sr[12][0]] = mult_result; + end + + case (ops_in_flight_state) + 2'b00: ops_in_flight_next = ops_in_flight; + 2'b01: ops_in_flight_next = ops_in_flight - 1; + 2'b10: ops_in_flight_next = ops_in_flight + 1; + 2'b11: ops_in_flight_next = ops_in_flight; + endcase + + o_valid = mult_valid; + o_result = mult_result; + + case (state) + SUM1: begin + o_ready = ops_in_flight < 2; + + if (i_valid && o_ready) begin + r_power_next = i_r_power; + if (i_clear_acc) begin + mult_accumulator_next = {3'b0, i_message}; + end else begin + mult_accumulator_next = accumulators[index[0]] + {3'b0, i_message}; + end + state_next = SUM2; + end + end + + SUM2: begin + mult_accumulator_next = mult_accumulator >= 131'(PRIME) ? 131'(mult_accumulator - PRIME) : mult_accumulator; + state_next = MUL; + end + + MUL: begin + mult_i_valid = '1; + + if (mult_o_ready) begin + index_next = index + 1; + + state_next = SUM1; + end + end + + default: begin + state_next = SUM1; + end + + endcase +end + +poly1305_friendly_modular_mult u_modular_mult ( + .i_clk (i_clk), + .i_rst (i_rst), + + .i_valid (mult_i_valid), + .o_ready (mult_o_ready), + .i_data (r_power), + .i_accumulator (mult_accumulator[129:0]), + + .o_valid (mult_valid), + .o_result (mult_result) +); + +endmodule \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/src/sources.list b/ChaCha20_Poly1305_64/src/sources.list index 2954a74..e488302 100644 --- a/ChaCha20_Poly1305_64/src/sources.list +++ b/ChaCha20_Poly1305_64/src/sources.list @@ -5,4 +5,5 @@ chacha20_pipelined_block.sv poly1305_core.sv poly1305_friendly_modulo.sv -poly1305_friendly_modular_mult.sv \ No newline at end of file +poly1305_friendly_modular_mult.sv +poly1305_stage.sv \ No newline at end of file