diff --git a/.gitmodules b/.gitmodules index 404a6c8..65d4880 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "common/sim/sub/taxi"] path = common/sim/sub/taxi url = https://github.com/fpganinja/taxi.git +[submodule "common/sim/sub/fifo"] + path = common/sim/sub/fifo + url = https://github.com/olofk/fifo.git diff --git a/ChaCha20_Poly1305_64/doc/notes2.md b/ChaCha20_Poly1305_64/doc/notes2.md index 64f1f73..00ae4a2 100644 --- a/ChaCha20_Poly1305_64/doc/notes2.md +++ b/ChaCha20_Poly1305_64/doc/notes2.md @@ -24,3 +24,35 @@ Module inputs and outputs 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. + +the real requirement was to get something that works... + + +we can pipeline chacha20 as much as we want since it is trivially pipelined + +since poly1305 takes in a 32 bit stream, we can redo chacha20 to work on 32 bits +at a time instead of 256 bits. We could also reuse stages, so instead of needing +all 20 stages we can just have 2 or something. + +BUT since the number 1 requirement is to get it to work, lets just use what we already have. + +okay they 512 bit chacha implementation is a bit crazy. the latency is too high. we need +to come up with a way to do it 32 bits at a time. + +each quarter round generates 128 bits, so we could do 1 quarter round at a time and get 128 +bits per clock cycle, which is plenty fast. + +if we do 1 quarter round per clock cycle, There are 20 rounds, each of which is 4 quarter +rounds, so it would take 80 cycles. + +Compared to the current implementation which has 20 rounds, but each round takes 7 cycles, + + +this has almost half the latency. We still need to store the full state between each round, +which is 512 bits. + + +OHHH there is a big different here with encrypt vs decrypt. basically, it is always +the encrypted packet that goes through poly1305. If the packet is being encrypted then +it needs to get xored before going into poly1305. If the packet is being decrypted, then it +needs to go through poly1305 in parallel with being xored. \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/doc/notes3.md b/ChaCha20_Poly1305_64/doc/notes3.md new file mode 100644 index 0000000..320bda4 --- /dev/null +++ b/ChaCha20_Poly1305_64/doc/notes3.md @@ -0,0 +1,105 @@ +# Data from wireshark + +Ok lets work this out by hand. The encyrpted packet matches exaactly, so we +know that the chacha20 part is correct, and this must include the first block +which is used for the keys. + +84 bytes rounded to nearest multiple of 16 is 96 bytes. plus 16 for tag is 112. + +so we do know that wireguard is including the tag. + + +the first output of chacha20, which becomes the keys, is +118b9bfd676a3bd991483cb1746252272e032bfbf2597dafec72576a54d9263ae32c815b30dbd75e7000d9ec14aac879075ada63f40d22180741336f9132e14a + +The bottm 256 bits of that is + +e32c815b30dbd75e7000d9ec14aac879075ada63f40d22180741336f9132e14a + +splitting that into 128 bit sections, we get + +0xe32c815b30dbd75e7000d9ec14aac879 +0x075ada63f40d22180741336f9132e14a + +r_mask is 0x0ffffffc0ffffffc0ffffffc0fffffff + +so out final values of r and s are + +r = 0x075ada60040d22180741336c0132e14a +s = 0xe32c815b30dbd75e7000d9ec14aac879 + +oh and p = 2**130-5 + +These values line up with what what we see in the hardware. + +according to the spec, the algorithm for poly1305 is as follows: + +```text + a = 0 /* a is the accumulator */ + p = (1<<130)-5 + for i=1 upto ceil(msg length in bytes / 16) + n = le_bytes_to_num(msg[((i-1)*16)..(i*16)] | [0x01]) + a += n + a = (r * a) % p + end + a += s + return num_to_16_le_bytes(a) + end +``` + +Here is the cipher, which is msg in this case +b"\xa4\xeb\xc1.\xe3\xf9\x90\xda\x18\x03:\x07\x89\xc0N'\x00\xf6\xf5\xc2q\xd4*\xc4\xb4\xd6&.feI\xb4E\xa7Cn\x82\x9b\xff\xb6\xace\xf0VH\xbc\x0c9\x1f\xe7\xc5\x88Ht7a'\x16I@\x18\x8f\x03\xdb\xa6z\xf88\x8e\xaa\xb7lY6(\xbf\x9d\xc7\xbe\x034m\x91.\x91m\xad\x86%EEG\x016O-" + +here it is split up into 16 byte chunks + +b"\xa4\xeb\xc1.\xe3\xf9\x90\xda\x18\x03:\x07\x89\xc0N'" +b'\x00\xf6\xf5\xc2q\xd4*\xc4\xb4\xd6&.feI\xb4' +b'E\xa7Cn\x82\x9b\xff\xb6\xace\xf0VH\xbc\x0c9' +b"\x1f\xe7\xc5\x88Ht7a'\x16I@\x18\x8f\x03\xdb" +b'\xa6z\xf88\x8e\xaa\xb7lY6(\xbf\x9d\xc7\xbe\x03' +b'4m\x91.\x91m\xad\x86%EEG\x016O-' + +The length of the message is 96 bytes, so we have our 6 16 byte chunks. + +the next step is to interpret these as little endian integers, then add a leading 1. + + +0x1274ec089073a0318da90f9e32ec1eba4 +0x1b44965662e26d6b4c42ad471c2f5f600 +0x1390cbc4856f065acb6ff9b826e43a745 +0x1db038f18404916276137744888c5e71f +0x103bec79dbf2836596cb7aa8e38f87aa6 +0x12d4f36014745452586ad6d912e916d34 + +DON'T FORGET ABOUT THE LENGTHS! +The length of AAD is 0, and the length of the ciphertext is 96, +that becomes + +this is aad length, data_length +be careful of the order, since aad length comes first, it is on the +right side of this hex number, since its little endian. + +0x100000000000000600000000000000000 + +And these also match the hardware, so we are doing good so far. + +so after the first round, a = (r * n) % p, since a started at 0, a+=n is just n +so a = 0xcfd86a9543d3377baf5be686c46d8491 + +ok looks good so far. + +next is 0x312e451b2a526811c5bd976ce3c27d5e7, looks good as well. the next values in a row are + +0x22097b74ef42792da5e02cf9dd8249776 +0x2586a4ee24499da642fb6392be59137b2 +0xff1ba4984e72db7199c786a00de9de1e +0x2850e6cbbf9869bf410976e82e2ee9b04 +0x38878751382017086bc63eee8ba2cbdab + +which all match still. So the final step is to add s, + +0x46ba4f66eb2dd47e52c64c8d4ced78624 + +SO basically we need to appaned the length to the data when it is going through poly1305. +poly1305 should be able to look at the input fifo and know when it is outputting the last +valid beat. After this, we need to output the lengths. diff --git a/ChaCha20_Poly1305_64/doc/sanity.py b/ChaCha20_Poly1305_64/doc/sanity.py new file mode 100644 index 0000000..35e10de --- /dev/null +++ b/ChaCha20_Poly1305_64/doc/sanity.py @@ -0,0 +1,16 @@ +import base64 +from chacha20poly1305 import ChaCha20Poly1305 + +cleartext=base64.decodebytes(b"RQAAVOVGQABAAUFMCgoAAgoKAAEIAPlcbAAAAG+tIvUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") +key = base64.decodebytes(b"IA7buFUDsARj+YequW4OfQR3JsaE9M88dpXKrDjKzIs=") +nonce = bytes([0]*12) + +cip = ChaCha20Poly1305(key) + +ciphertag = cip.encrypt(nonce, cleartext) + +ciphertext = ciphertag[:-16] +tag = ciphertag[-16:] + +print(ciphertext) +print(tag) \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/poly1305_timing_test/constraints.sdc b/ChaCha20_Poly1305_64/poly1305_timing_test/constraints.sdc index 392311c..9bfa36e 100644 --- a/ChaCha20_Poly1305_64/poly1305_timing_test/constraints.sdc +++ b/ChaCha20_Poly1305_64/poly1305_timing_test/constraints.sdc @@ -1 +1 @@ -create_clock -period 2.5 -name clk [get_ports i_clk] \ No newline at end of file +create_clock -period 20 -name clk [get_ports i_clk] \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/poly1305_timing_test/poly1305_timing_test.xml b/ChaCha20_Poly1305_64/poly1305_timing_test/poly1305_timing_test.xml index 50827ff..8f630cf 100644 --- a/ChaCha20_Poly1305_64/poly1305_timing_test/poly1305_timing_test.xml +++ b/ChaCha20_Poly1305_64/poly1305_timing_test/poly1305_timing_test.xml @@ -1,16 +1,15 @@ - + - - - - - + + + + @@ -41,7 +40,7 @@ - + diff --git a/ChaCha20_Poly1305_64/sim/chacha20_poly1305_32_ll_core.py b/ChaCha20_Poly1305_64/sim/chacha20_poly1305_32_ll_core.py new file mode 100644 index 0000000..e1c2aa4 --- /dev/null +++ b/ChaCha20_Poly1305_64/sim/chacha20_poly1305_32_ll_core.py @@ -0,0 +1,208 @@ +import cocotb + +from cocotb.clock import Clock +from cocotb.triggers import Timer, RisingEdge, FallingEdge +from cocotb.handle import Immediate +from cocotb.queue import Queue + +from dataclasses import dataclass + +from chacha_helpers import chacha_block + +import random + +import base64 + +import struct + +CLK_PERIOD = 20 + +NONCE_BYTES = b"\x00\x00\x00\x00\x00\x00\x00\x4a\x00\x00\x00\x00" +KEY_BYTES = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +MSG_BYTES = b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it." + + +NONCE = int.from_bytes(NONCE_BYTES, "little") +KEY = int.from_bytes(KEY_BYTES, "little") + +CONSTANT = [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574] + +output_queue = Queue() + +async def receieve_output(dut): + packet = bytearray() + while True: + if dut.o_data_valid.value: + packet.extend(int(dut.o_data.value).to_bytes(4, "little")) + if dut.o_data_last.value: + await output_queue.put(bytes(packet)) + packet = bytearray() + await RisingEdge(dut.i_clk) + +# @cocotb.test +async def test_sanity(dut): + cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start()) + cocotb.start_soon(receieve_output(dut)) + + for counter in range(3): + data_in = CONSTANT[:] + data_in.extend(struct.unpack("8I", KEY_BYTES)) + data_in.extend(struct.unpack("1I", counter.to_bytes(4, "little"))) + data_in.extend(struct.unpack("3I", NONCE_BYTES)) + + data_out = chacha_block(data_in) + + print([f"{data:x}" for data in data_out]) + + 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_nonce.value = NONCE + dut.i_key.value = KEY + + dut.i_data_ready.value = 1 + + N_PKTS = 100 + + for _ in range(N_PKTS): + dut.i_last.value = 0 + dut.i_valid.value = 1 + msg = MSG_BYTES + while len(msg) > 0: + part = msg[0:4] + dut.i_data.value = int.from_bytes(part, "little") + dut.i_countm1.value = len(part)-1 + if len(msg) < 4: + dut.i_last.value = 1 + msg = msg[4:] + 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 + + for _ in range(N_PKTS): + packet = await output_queue.get() + print(packet) + + +@dataclass +class CipherContext(): + key: int + counter: int + encrypt: int + tag: int + cipher: bytes + clear: bytes + + +MESSAGE_KEY_1_BYTES = base64.decodebytes(b"IA7buFUDsARj+YequW4OfQR3JsaE9M88dpXKrDjKzIs=") +MESSAGE_KEY_2_BYTES = base64.decodebytes(b"3sZ+QBcwflnvE8t4jv9qgIqIOVaXXwO1bxRo9qWB1fM=") + +MESSAGE_KEY_1 = int.from_bytes(MESSAGE_KEY_1_BYTES, "little") +MESSAGE_KEY_2 = int.from_bytes(MESSAGE_KEY_2_BYTES, "little") + + + +PACKETS = [ + CipherContext( + key=MESSAGE_KEY_1, + counter=0, + encrypt=1, + + tag=int.from_bytes(base64.decodebytes(b"BAAAAAb0fasAAAAAAAAAAKTrwS7j+ZDaGAM6B4nATicA9vXCcdQqxLTWJi5mZUm0RadDboKb/7asZfBWSLwMOR/nxYhIdDdhJxZJQBiPA9umevg4jqq3bFk2KL+dx74DNG2RLpFtrYYlRUVHATZPLSSG187UyGQs5Ufdsm72pGs=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAAAb0fasAAAAAAAAAAKTrwS7j+ZDaGAM6B4nATicA9vXCcdQqxLTWJi5mZUm0RadDboKb/7asZfBWSLwMOR/nxYhIdDdhJxZJQBiPA9umevg4jqq3bFk2KL+dx74DNG2RLpFtrYYlRUVHATZPLSSG187UyGQs5Ufdsm72pGs=")[16:-16], + clear=base64.decodebytes(b"RQAAVOVGQABAAUFMCgoAAgoKAAEIAPlcbAAAAG+tIvUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") + ), + + CipherContext( + key=MESSAGE_KEY_2, + counter=0, + encrypt=0, + + tag=int.from_bytes(base64.decodebytes(b"BAAAANg30DAAAAAAAAAAAG9PCA6fUmkbvpSFNfecE+1o8JFF1SPu2whyZfloCC9wc1cpJj7aYnx2g83AuAozVtlTbJ8OKHJ5e1yBcguguOpyM8bev58PvujxDsGJhbgkvzUPi4GA0Ipk5r6YEAiaw9E2PtXhKcoeBCXPfpSWVlk=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAANg30DAAAAAAAAAAAG9PCA6fUmkbvpSFNfecE+1o8JFF1SPu2whyZfloCC9wc1cpJj7aYnx2g83AuAozVtlTbJ8OKHJ5e1yBcguguOpyM8bev58PvujxDsGJhbgkvzUPi4GA0Ipk5r6YEAiaw9E2PtXhKcoeBCXPfpSWVlk=")[16:-16], + clear=base64.decodebytes(b"RQAAVKEdAABAAcV1CgoAAQoKAAIAAAFdbAAAAG+tIvUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") + ) +] + + +tag_queue = Queue() + +async def tag_output_process(dut): + while True: + if dut.o_mac_valid.value: + await tag_queue.put(int(dut.o_mac.value)) + await RisingEdge(dut.i_clk) + +@cocotb.test +async def test_real_packet(dut): + cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start()) + cocotb.start_soon(receieve_output(dut)) + cocotb.start_soon(tag_output_process(dut)) + + + 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) + + + + for pkt in PACKETS: + dut.i_nonce.value = pkt.counter + dut.i_key.value = pkt.key + dut.i_encrypt.value = pkt.encrypt + + msg = pkt.clear if pkt.encrypt else pkt.cipher + dut.i_data_ready.value = 1 + + dut.i_last.value = 0 + dut.i_valid.value = 1 + while len(msg) > 0: + part = msg[0:4] + dut.i_data.value = int.from_bytes(part, "little") + dut.i_countm1.value = len(part)-1 + if len(msg) <= 4: + dut.i_last.value = 1 + msg = msg[4:] + 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 + + dut.i_nonce.value = 0 + dut.i_key.value = 0 + + for pkt in PACKETS: + packet = await output_queue.get() + + expected = pkt.cipher if pkt.encrypt else pkt.clear + # The packet is rounded up to 16 bytes before encryption, but based on the IP length we + # are supposed to truncate it. That would happen outside of this block though. + if expected not in packet: + print("Packets didn't match!") + print(f"expected={expected} actual={packet}") + + tag = await tag_queue.get() + if tag != pkt.tag: + print("Tags did not match!") + print(f"expected={pkt.tag:x} actual={tag:x}") + + + await Timer(10, "us") \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/sim/poly1305.yaml b/ChaCha20_Poly1305_64/sim/poly1305.yaml index eb5161a..4e08b0e 100644 --- a/ChaCha20_Poly1305_64/sim/poly1305.yaml +++ b/ChaCha20_Poly1305_64/sim/poly1305.yaml @@ -34,4 +34,10 @@ tests: modules: - "poly1305_ll_stage" sources: sources.list + waves: True + - name: "chacha20_poly1305_32_ll_core" + toplevel: "chacha20_poly1305_32_ll_core" + modules: + - "chacha20_poly1305_32_ll_core" + 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 index 8d445e1..1302bc9 100644 --- a/ChaCha20_Poly1305_64/sim/poly1305_ll_stage.py +++ b/ChaCha20_Poly1305_64/sim/poly1305_ll_stage.py @@ -30,27 +30,28 @@ async def test_sanity(dut): 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 + for _ in range(2): + 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 = 0 + dut.i_last.value = 1 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 + dut.i_valid.value = 0 + dut.i_last.value = 0 cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start()) diff --git a/ChaCha20_Poly1305_64/sim/sources.list b/ChaCha20_Poly1305_64/sim/sources.list index 971f6b1..4e2be88 100644 --- a/ChaCha20_Poly1305_64/sim/sources.list +++ b/ChaCha20_Poly1305_64/sim/sources.list @@ -2,3 +2,8 @@ poly1305_core_wrapper.sv ../src/sources.list ../../common/sim/sub/taxi/src/axis/rtl/taxi_axis_if.sv + +../../common/sim/sub/fifo/rtl/verilog/fifo_fwft_adapter.v +../../common/sim/sub/fifo/rtl/verilog/fifo.v +../../common/sim/sub/fifo/rtl/verilog/fifo_fwft.v +../../common/sim/sub/fifo/rtl/verilog/simple_dpram_sclk.v diff --git a/ChaCha20_Poly1305_64/src/chacha20_block.sv b/ChaCha20_Poly1305_64/src/chacha20_block.sv index 2230973..a4de16c 100644 --- a/ChaCha20_Poly1305_64/src/chacha20_block.sv +++ b/ChaCha20_Poly1305_64/src/chacha20_block.sv @@ -1,10 +1,10 @@ module chacha20_block #( parameter KEY_SIZE = 256, - parameter COUNTER_SIZE = 64, - parameter NONCE_SIZE = 64, + parameter COUNTER_SIZE = 32, + parameter NONCE_SIZE = 96, parameter STATE_SIZE = 512, parameter ROUNDS = 20, - parameter CONSTANT = 128'h657870616e642033322d62797465206b + parameter CONSTANT = 128'h617078653320646e79622d326b206574 )( input logic i_clk, input logic i_rst, @@ -68,7 +68,7 @@ always_ff @(posedge i_clk) begin initial_state_rptr <= '0; initial_state_wptr <= '0; end else begin - if (i_valid) begin + if (i_valid & i_ready) begin initial_states[initial_state_wptr] <= write_initial_state; if (initial_state_wptr < PIPE_STAGES-1) begin initial_state_wptr <= initial_state_wptr + 1; @@ -79,7 +79,7 @@ always_ff @(posedge i_clk) begin pre_add_valid <= valid[ROUNDS][0]; - if (valid[ROUNDS][0]) begin + if (valid[ROUNDS][0] & i_ready) begin read_initial_state <= initial_states[initial_state_rptr]; if (initial_state_rptr < PIPE_STAGES-1) begin initial_state_rptr <= initial_state_rptr + 1; @@ -92,13 +92,15 @@ always_ff @(posedge i_clk) begin end - o_valid <= pre_add_valid; + if (i_ready) begin + o_valid <= pre_add_valid; - // We cannot just add state_pre_add and read_initial state - // because the addition needs to be done wordwise, with no - // carries between 32 bit groups. - for (int i = 0; i < 16; i++) begin - o_state[i*32 +: 32] <= state_pre_add[i*32 +: 32] + read_initial_state[i*32 +: 32]; + // We cannot just add state_pre_add and read_initial state + // because the addition needs to be done wordwise, with no + // carries between 32 bit groups. + for (int i = 0; i < 16; i++) begin + o_state[i*32 +: 32] <= state_pre_add[i*32 +: 32] + read_initial_state[i*32 +: 32]; + end end end @@ -115,10 +117,10 @@ always_comb begin end state[0][12] = i_counter[0 +: 32]; - state[0][13] = i_counter[32 +: 32]; - - state[0][14] = i_nonce[0 +: 32]; - state[0][15] = i_nonce[32 +: 32]; + + state[0][13] = i_nonce[0 +: 32]; + state[0][14] = i_nonce[32 +: 32]; + state[0][15] = i_nonce[64 +: 32]; for (int i = 0; i < 4; i++) begin diff --git a/ChaCha20_Poly1305_64/src/chacha20_poly1305_32_ll_core.sv b/ChaCha20_Poly1305_64/src/chacha20_poly1305_32_ll_core.sv new file mode 100644 index 0000000..9a03f79 --- /dev/null +++ b/ChaCha20_Poly1305_64/src/chacha20_poly1305_32_ll_core.sv @@ -0,0 +1,320 @@ +module chacha20_poly1305_32_ll_core ( + input logic i_clk, + input logic i_rst, + + input logic [255:0] i_key, + input logic [95:0] i_nonce, + + input logic i_encrypt, + + input logic [31:0] i_data, + input logic [1:0] i_countm1, + input logic i_last, + + input logic i_valid, + output logic o_ready, + + output logic [31:0] o_data, + output logic [1:0] o_data_countm1, + output logic o_data_last, + output logic o_data_valid, + input logic i_data_ready, + + // no backpressure for the poly1305 output + output logic [127:0] o_mac, + output logic o_mac_valid +); + +logic [255:0] chacha_key; +logic [31:0] chacha_counter; +logic [95:0] chacha_nonce; + +logic chacha_i_valid; +logic chacha_i_ready; + +logic [511:0] chacha_state; +logic chacha_o_valid; +logic chacha_o_ready; + +logic poly1305_i_valid; +logic [1:0] poly1305_countm1; +logic poly1305_i_ready; +logic [31:0] poly1305_data; +logic poly1305_last; +logic [127:0] poly1305_r; +logic [127:0] poly1305_s; + +logic downconvert_i_valid; +logic [1:0] downconvert_countm1; +logic downconvert_i_ready; +logic [31:0] downconvert_data; +logic downconvert_last; + +logic poly1305_o_valid; +logic [127:0] poly1305_o_result; + +logic [511:0] fifo_data; +logic [5:0] fifo_countm1; +logic fifo_last; + +logic fifo_rd_en; +logic fifo_empty; +logic fifo_full; +logic fifo_valid; + +logic upconvert_ready; +logic upconvert_valid; +logic upconvert_last; +logic [511:0] upconvert_data; +logic [5:0] upconvert_countm1; + +logic ciphertext_ready; +logic ciphertext_valid; +logic ciphertext_last; +logic [511:0] ciphertext_data; +logic [5:0] ciphertext_countm1; + +logic ciphertext_skid_ready; +logic ciphertext_skid_valid; +logic ciphertext_skid_last; +logic [511:0] ciphertext_skid_data; +logic [5:0] ciphertext_skid_countm1; + +logic [511:0] post_data; + +logic post_skid_ready; +logic post_skid_valid; +logic post_skid_last; +logic [511:0] post_skid_data; +logic [5:0] post_skid_countm1; + +logic meta_fifo_encrypt; +logic meta_fifo_read; +logic meta_fifo_empty; + +assign chacha_nonce = i_nonce; +assign chacha_key = i_key; + +assign fifo_valid = ~fifo_empty; + +assign o_mac_valid = poly1305_o_valid; +assign o_mac = poly1305_o_result; + +poly1305_width_convert_2 u_chacha_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 & chacha_o_ready), + .o_data (upconvert_data), + .o_last (upconvert_last) +); + +assign upconvert_ready = ~fifo_full; + +logic sop; +logic in_pkt; + +always_ff @(posedge i_clk) begin + if (i_rst) begin + in_pkt <= '0; + end else begin + if (i_valid & o_ready) begin + if (i_last) begin + in_pkt <= '0; + end else begin + in_pkt <= '1; + end + end + end +end + +assign sop = i_valid & o_ready & ~in_pkt; + + +fifo_fwft #( + .DATA_WIDTH(512+6+1), + .DEPTH_WIDTH(8) +) u_input_fifo ( + .clk (i_clk), + .rst (i_rst), + .din ({upconvert_data, upconvert_countm1, upconvert_last}), + .wr_en (upconvert_valid & chacha_o_ready), + .full (fifo_full), // probably wrong, think about this + .dout ({fifo_data, fifo_countm1, fifo_last}), + .rd_en (fifo_rd_en), + .empty (fifo_empty) +); + +fifo_fwft #( + .DATA_WIDTH(1), // can increase when we have more metadata + .DEPTH_WIDTH(4) +) u_meta_fifo ( + .clk (i_clk), + .rst (i_rst), + .din (i_encrypt), + .wr_en (sop), + .full (), + .dout (meta_fifo_encrypt), + .rd_en (meta_fifo_read), + .empty (meta_fifo_empty) +); + +chacha20_poly1305_input_fsm u_chacha20_poly1305_input_fsm ( + .i_clk (i_clk), + .i_rst (i_rst), + + .i_valid (upconvert_valid), + .i_last (upconvert_last), + + .o_counter (chacha_counter), + .chacha_valid (chacha_i_valid), + .chacha_ready (chacha_i_ready) +); + +chacha20_block u_chacha20_block ( + .i_clk (i_clk), + .i_rst (i_rst), + + .i_key (chacha_key), + .i_counter (chacha_counter), + .i_nonce (chacha_nonce), + .i_valid (chacha_i_valid), + .o_ready (chacha_i_ready), + + .o_state (chacha_state), + .o_valid (chacha_o_valid), + .i_ready (chacha_o_ready) +); + +chacha20_poly1305_mid_fsm u_mid_fsm ( + .i_clk (i_clk), + .i_rst (i_rst), + + .i_chacha_state (chacha_state), + .i_chacha_valid (chacha_o_valid), + .o_chacha_ready (chacha_o_ready), + + .i_metadata_din (meta_fifo_encrypt), + .o_metadata_read (meta_fifo_read), + + .i_fifo_data (fifo_data), + .i_fifo_countm1 (fifo_countm1), + .i_fifo_valid (fifo_valid), + .i_fifo_last (fifo_last), + + .o_fifo_rd_en (fifo_rd_en), + + + .o_ciphertext (ciphertext_data), + .o_post (post_data), + .o_ciphertext_countm1 (ciphertext_countm1), + .o_ciphertext_valid (ciphertext_valid), + .o_ciphertext_last (ciphertext_last), + .i_ciphertext_ready (ciphertext_ready), + + // TODO this is most likely wrong. + .o_r (poly1305_r), + .o_s (poly1305_s) +); + +logic rstn; +assign rstn = ~i_rst; + +pipe_skid_buffer #( + .DWIDTH(512+512+6+1) +) u_ciphertext_skid_buffer ( + .clk (i_clk), + .rstn (rstn), + + .i_data ({post_data, ciphertext_data, ciphertext_countm1, ciphertext_last}), + .i_valid (ciphertext_valid), + .o_ready (ciphertext_ready), + + .o_data ({post_skid_data, ciphertext_skid_data, ciphertext_skid_countm1, ciphertext_skid_last}), + .o_valid (ciphertext_skid_valid), + .i_ready (ciphertext_skid_ready) +); + + +poly1305_width_convert_3 u_pre_poly1305_width_convert ( + .i_clk (i_clk), + .i_rst (i_rst), + + .i_valid (ciphertext_skid_valid), + .i_countm1 (ciphertext_skid_countm1), + .o_ready (ciphertext_skid_ready), + .i_data (ciphertext_skid_data), + .i_last (ciphertext_skid_last), + + .o_valid (poly1305_i_valid), + .o_countm1 (poly1305_countm1), + .i_ready (poly1305_i_ready & ~output_fifo_full), + .o_data (poly1305_data), + .o_last (poly1305_last) +); + +poly1305_width_convert_3 u_output_width_convert ( + .i_clk (i_clk), + .i_rst (i_rst), + + .i_valid (ciphertext_skid_valid), + .i_countm1 (ciphertext_skid_countm1), + .o_ready (), + .i_data (post_skid_data), + .i_last (ciphertext_skid_last), + + .o_valid (downconvert_i_valid), + .o_countm1 (downconvert_countm1), + .i_ready (poly1305_i_ready & ~output_fifo_full), + .o_data (downconvert_data), + .o_last (downconvert_last) +); + +fifo_fwft #( + .DATA_WIDTH(32+1), + .DEPTH_WIDTH(4) +) u_output_fifo ( + .clk (i_clk), + .rst (i_rst), + .din ({downconvert_data, downconvert_last}), + .wr_en (downconvert_i_valid & poly1305_i_ready & ~output_fifo_full), + .full (output_fifo_full), + .dout ({o_data, o_data_last}), + .rd_en (o_data_valid & i_data_ready), + .empty (output_fifo_empty) +); + +assign o_data_valid = ~output_fifo_empty; + +logic output_fifo_full; +logic output_fifo_empty; + + +// if output fifo is not ready, we need to backpressure poly1305 + +poly1305_ll_stage u_poly1305_ll_stage ( + .i_clk (i_clk), + .i_rst (i_rst), + + .i_valid (poly1305_i_valid & ~output_fifo_full), + .i_countm1 (poly1305_countm1), + .o_ready (poly1305_i_ready), + .i_data (poly1305_data), + .i_last (poly1305_last), + .i_r (poly1305_r), + .i_s (poly1305_s), + + .o_valid (poly1305_o_valid), + .o_result (poly1305_o_result) +); + + +endmodule diff --git a/ChaCha20_Poly1305_64/src/chacha20_poly1305_input_fsm.sv b/ChaCha20_Poly1305_64/src/chacha20_poly1305_input_fsm.sv new file mode 100644 index 0000000..06ba4f2 --- /dev/null +++ b/ChaCha20_Poly1305_64/src/chacha20_poly1305_input_fsm.sv @@ -0,0 +1,88 @@ +module chacha20_poly1305_input_fsm ( + input logic i_clk, + input logic i_rst, + + input logic i_valid, + input logic i_last, + + output logic [31:0] o_counter, + + output logic chacha_valid, + input logic chacha_ready +); + +enum logic [1:0] {IDLE, ACTIVE1, ACTIVE2, ACTIVE3} state, state_next; + +logic [31:0] counter, counter_next; + + +// in case the first beat is also the last one. +logic last_flag, last_flag_next; + +assign o_counter = counter; + +always_ff @(posedge i_clk) begin + if (i_rst) begin + state <= IDLE; + counter <= '0; + last_flag <= '0; + end else begin + state <= state_next; + counter <= counter_next; + last_flag <= last_flag_next; + end +end + +always_comb begin + state_next = state; + + counter_next = counter; + + last_flag_next = '0; + + chacha_valid = '0; + + case (state) + IDLE: begin + counter_next = '0; + chacha_valid = '0; + + if (i_valid) begin + chacha_valid = '1; + state_next = ACTIVE1; + counter_next = counter + 1; + + last_flag_next = i_last; + end + end + + ACTIVE1: begin + chacha_valid = '1; + if (chacha_ready) begin + state_next = ACTIVE2; + + counter_next = counter + 1; + end + end + + ACTIVE2: begin + if (i_valid) begin + chacha_valid = '1; + if (chacha_ready) begin + counter_next = counter + 1; + + if (i_last || last_flag) begin + state_next = IDLE; + counter_next = '0; + end + end + end + end + + default: begin + state_next = IDLE; + end + endcase +end + +endmodule \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/src/chacha20_poly1305_mid_fsm.sv b/ChaCha20_Poly1305_64/src/chacha20_poly1305_mid_fsm.sv new file mode 100644 index 0000000..ef61c60 --- /dev/null +++ b/ChaCha20_Poly1305_64/src/chacha20_poly1305_mid_fsm.sv @@ -0,0 +1,110 @@ +module chacha20_poly1305_mid_fsm ( + input logic i_clk, + input logic i_rst, + + input logic [511:0] i_chacha_state, + input logic i_chacha_valid, + output logic o_chacha_ready, + + input logic [511:0] i_fifo_data, + input logic [5:0] i_fifo_countm1, + input logic i_fifo_valid, + input logic i_fifo_last, + + output logic o_fifo_rd_en, + + input logic [0:0] i_metadata_din, + output logic o_metadata_read, + + output logic [511:0] o_ciphertext, + output logic [511:0] o_post, + output logic [5:0] o_ciphertext_countm1, + output logic o_ciphertext_valid, + output logic o_ciphertext_last, + input logic i_ciphertext_ready, + + + output logic [127:0] o_r, + output logic [127:0] o_s +); + +localparam R_MASK = 128'h0ffffffc0ffffffc0ffffffc0fffffff; + +logic encrypt; + +assign encrypt = i_metadata_din[0]; + +enum logic {IDLE, DATA} state, state_next; + +logic [127:0] r, r_next; +logic [127:0] s, s_next; + +assign o_r = r; +assign o_s = s; + + +always_ff @(posedge i_clk) begin + if (i_rst) begin + state <= IDLE; + + r <= '0; + s <= '0; + end else begin + state <= state_next; + + r <= r_next; + s <= s_next; + end +end + +always_comb begin + state_next = state; + + r_next = r; + s_next = s; + + o_fifo_rd_en = '0; + + o_chacha_ready = i_ciphertext_ready; + + o_ciphertext_valid = '0; + o_ciphertext_last = '0; + + o_metadata_read = '0; + + case (state) + IDLE: begin + if (i_chacha_valid) begin + r_next = i_chacha_state[0 +: 128] & R_MASK; + s_next = i_chacha_state[128 +: 128]; + + state_next = DATA; + end + end + + DATA: begin + if (encrypt) begin + o_ciphertext = i_fifo_data ^ i_chacha_state; + end else begin + o_ciphertext = i_fifo_data; + end + + o_post = i_fifo_data ^ i_chacha_state; + o_ciphertext_countm1 = i_fifo_countm1; + o_ciphertext_last = i_fifo_last; + o_ciphertext_valid = i_fifo_valid & i_chacha_valid; + + if (i_ciphertext_ready & i_chacha_valid) begin + o_chacha_ready = '1; + o_fifo_rd_en = i_fifo_valid; + + if (i_fifo_last) begin + state_next = IDLE; + o_metadata_read = '1; + end + end + end + endcase +end + +endmodule \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv b/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv index 8958691..6d518bb 100644 --- a/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv +++ b/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv @@ -18,7 +18,7 @@ module poly1305_ll_stage ( output logic [127:0] o_result ); -localparam [129:0] PRIME = (1 << 130) - 5; +localparam [129:0] PRIME = 130'h3fffffffffffffffffffffffffffffffb; logic upconvert_ready; logic upconvert_valid; @@ -47,7 +47,7 @@ poly1305_width_convert u_width_convert( 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 [2:0] {IDLE, SUM, LENGTHS, MULT, MODULO_1, MODULO_2} state, state_next; enum logic [1:0] {OUTPUT_IDLE, OUTPUT_ADD, OUTPUT_OUT} output_state, output_state_next; @@ -72,6 +72,9 @@ logic [130:0] final_mod; logic start_output; logic last_flag, last_flag_next; +logic length_flag, length_flag_next; + +logic [63:0] data_len, data_len_next; always_ff @(posedge i_clk) begin if (i_rst) begin @@ -79,7 +82,10 @@ always_ff @(posedge i_clk) begin s_reg <= '0; s_reg_2 <= '0; + data_len <= '0; + last_flag <= '0; + length_flag <= '0; state <= IDLE; output_state <= OUTPUT_IDLE; @@ -88,6 +94,8 @@ always_ff @(posedge i_clk) begin s_reg <= s_reg_next; s_reg_2 <= s_reg_2_next; + data_len <= data_len_next; + mod2_upper <= mod2_upper_next; mod2_lower <= mod2_lower_next; @@ -97,6 +105,7 @@ always_ff @(posedge i_clk) begin product <= product_next; last_flag <= last_flag_next; + length_flag <= length_flag_next; state <= state_next; output_state <= output_state_next; @@ -114,9 +123,12 @@ always_comb begin r_reg_next = r_reg; s_reg_next = s_reg; + data_len_next = data_len; + upconvert_ready = '0; last_flag_next = last_flag; + length_flag_next = length_flag; state_next = state; @@ -138,6 +150,8 @@ always_comb begin data_1extend = {3'b0, upconvert_data} | (131'b1 << (8*(1+upconvert_countm1))); sum_next = data_1extend; + data_len_next = {60'd0, upconvert_countm1} + 1; + state_next = MULT; r_reg_next = i_r; @@ -152,6 +166,17 @@ always_comb begin data_1extend = {3'b0, upconvert_data} | (131'b1 << (8*(1+upconvert_countm1))); sum_next = h + data_1extend; + data_len_next = data_len + {60'd0, upconvert_countm1} + 1; + + state_next = MULT; + end + + LENGTHS: begin + length_flag_next = '1; + + data_1extend = {3'b0, data_len, 64'b0} | (131'b1 << 128); + sum_next = h + data_1extend; + state_next = MULT; end @@ -180,10 +205,16 @@ always_comb begin end if (last_flag) begin - state_next = IDLE; + state_next = LENGTHS; last_flag_next = '0; + end else if (length_flag) begin + length_flag_next = '0; s_reg_2_next = s_reg; start_output = '1; + + data_len_next = '0; + + state_next = IDLE; end else begin state_next = SUM; end @@ -197,6 +228,9 @@ always_comb begin output_state_next = output_state; + o_result = '0; + o_valid = '0; + case (output_state) OUTPUT_IDLE: begin if (start_output) begin @@ -210,20 +244,14 @@ always_comb begin 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]; + o_result = final_sum[127:0]; output_state_next = OUTPUT_IDLE; end default: begin - + output_state_next = OUTPUT_IDLE; end endcase end diff --git a/ChaCha20_Poly1305_64/src/poly1305_width_convert_2.sv b/ChaCha20_Poly1305_64/src/poly1305_width_convert_2.sv new file mode 100644 index 0000000..218cf2a --- /dev/null +++ b/ChaCha20_Poly1305_64/src/poly1305_width_convert_2.sv @@ -0,0 +1,88 @@ +module poly1305_width_convert_2( + 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 [5:0] o_countm1, + input logic i_ready, + output logic [511:0] o_data, + output logic o_last +); + +// this could definitely be parameterized, +// but that can be a future project for the intern + + +logic [479:0] width_convert_save, width_convert_save_next; +logic [3: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 < 15) 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; + + + // wireguard packets are rounded up to 16 bytes + o_countm1 = width_convert_count*4 + {4'b0, i_countm1}; + if (o_countm1[3:0] != 0) begin + o_countm1 = {o_countm1[5:4], 4'hf}; + end + + 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 & i_ready) begin + o_ready = '1; + width_convert_count_next = width_convert_count + 4'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 = 6'd63 + {4'b0, i_countm1}; + o_countm1 = 6'd63; + + 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/poly1305_width_convert_3.sv b/ChaCha20_Poly1305_64/src/poly1305_width_convert_3.sv new file mode 100644 index 0000000..8094f55 --- /dev/null +++ b/ChaCha20_Poly1305_64/src/poly1305_width_convert_3.sv @@ -0,0 +1,63 @@ +// this one converts from 512 back to 32 + +module poly1305_width_convert_3( + input logic i_clk, + input logic i_rst, + + input logic i_valid, + input logic [5:0] i_countm1, + output logic o_ready, + input logic [511:0] i_data, + input logic i_last, + + output logic o_valid, + output logic [1:0] o_countm1, + input logic i_ready, + output logic [31:0] o_data, + output logic o_last +); + +logic [3:0] width_convert_count, width_convert_count_next; + +always_ff @(posedge i_clk) begin + if (i_rst) begin + width_convert_count <= '0; + end else begin + width_convert_count <= width_convert_count_next; + end +end + +always_comb begin + width_convert_count_next = width_convert_count; + + o_valid = '0; + o_last = '0; + o_ready = '0; + + o_data = i_data[width_convert_count*32 +: 32]; + o_countm1 = '0; + + o_valid = i_valid; + + if (i_valid && i_ready) begin + width_convert_count_next = width_convert_count + 1; + o_countm1 = '1; + + if (width_convert_count == 15) begin + o_ready = '1; + end + end + + if (i_last && 6'(width_convert_count+1)*4 > i_countm1) begin + o_last = '1; + o_countm1 = (2)'(i_countm1 - width_convert_count*4); + + if (i_valid && i_ready) begin + o_ready = '1; + width_convert_count_next = '0; + end + end + +end + +endmodule \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/src/skidbuffer.sv b/ChaCha20_Poly1305_64/src/skidbuffer.sv new file mode 100644 index 0000000..31eadaf --- /dev/null +++ b/ChaCha20_Poly1305_64/src/skidbuffer.sv @@ -0,0 +1,114 @@ +/*=============================================================================================================================== + Module : Pipeline Skid Buffer + + Description : Pipeline Skid Buffer is used as buffer in pipeline between two modules. + - Smallest pipeline buffer; implemented with just two registers. + - Simple valid-ready handshaking. + - Latency = 1 cycle. + - Configurable data width. + + Developer : Mitu Raj, chip@chipmunklogic.com at Chipmunk Logic ™, https://chipmunklogic.com + Notes : - + License : Open-source. + Date : Mar-26-2022 +===============================================================================================================================*/ + +/*------------------------------------------------------------------------------------------------------------------------------- + P I P E S K I D B U F F E R +-------------------------------------------------------------------------------------------------------------------------------*/ + +module pipe_skid_buffer #( + // Global Parameters + parameter DWIDTH = 8 // Data width +) +( + input logic clk , // Clock + input logic rstn , // Active-low synchronous reset + + // Input Interface + input logic [DWIDTH-1 : 0] i_data , // Data in + input logic i_valid , // Data in valid + output logic o_ready , // Ready out + + // Output Interface + output logic [DWIDTH-1 : 0] o_data , // Data out + output logic o_valid , // Data out valid + input logic i_ready // Ready in +) ; + +/*------------------------------------------------------------------------------------------------------------------------------- + Local Parameters +-------------------------------------------------------------------------------------------------------------------------------*/ +// State encoding +localparam PIPE = 1'b0 ; +localparam SKID = 1'b1 ; + +/*------------------------------------------------------------------------------------------------------------------------------- + Internal Registers/Signals +-------------------------------------------------------------------------------------------------------------------------------*/ +logic state_rg ; // State register +logic [DWIDTH-1 : 0] data_rg, sparebuff_rg ; // Data buffer, Spare buffer +logic valid_rg, ready_rg ; // Valid and Ready signals +logic ready ; // Pipeline ready signal + +/*------------------------------------------------------------------------------------------------------------------------------- + Synchronous logic +-------------------------------------------------------------------------------------------------------------------------------*/ +always @(posedge clk) begin + // Reset + if (!rstn) begin + // Internal Registers + state_rg <= PIPE ; + data_rg <= '0 ; + sparebuff_rg <= '0 ; + valid_rg <= 1'b0 ; + ready_rg <= 1'b0 ; + end + // Out of reset + else begin + case (state_rg) + + /* Stage where data is piped out or stored to spare buffer */ + PIPE : begin + // Pipe data out + if (ready) begin + data_rg <= i_data ; + valid_rg <= i_valid ; + ready_rg <= 1'b1 ; + end + // Pipeline stall, store input data to spare buffer (skid happened) + else if (i_valid) begin + sparebuff_rg <= i_data ; + ready_rg <= 1'b0 ; + state_rg <= SKID ; + end + end + + /* Stage to wait after data skid happened */ + SKID : begin + // Copy data from spare buffer to data buffer when downstream is ready, resume pipeline + if (i_ready) begin + data_rg <= sparebuff_rg ; + valid_rg <= 1'b1 ; + ready_rg <= 1'b1 ; + state_rg <= PIPE ; + end + end + + endcase + end +end + +/*------------------------------------------------------------------------------------------------------------------------------- + Continuous Assignments +-------------------------------------------------------------------------------------------------------------------------------*/ +assign ready = i_ready || ~valid_rg ; +assign o_ready = ready_rg ; +assign o_data = data_rg ; +assign o_valid = valid_rg ; + +endmodule + +/*------------------------------------------------------------------------------------------------------------------------------- + P I P E S K I D B U F F E R +-------------------------------------------------------------------------------------------------------------------------------*/ \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/src/sources.list b/ChaCha20_Poly1305_64/src/sources.list index a061972..6605440 100644 --- a/ChaCha20_Poly1305_64/src/sources.list +++ b/ChaCha20_Poly1305_64/src/sources.list @@ -9,4 +9,12 @@ poly1305_friendly_modular_mult.sv poly1305_stage.sv poly1305_width_convert.sv -poly1305_ll_stage.sv \ No newline at end of file +poly1305_width_convert_2.sv +poly1305_width_convert_3.sv +poly1305_ll_stage.sv + +skidbuffer.sv + +chacha20_poly1305_32_ll_core.sv +chacha20_poly1305_input_fsm.sv +chacha20_poly1305_mid_fsm.sv \ No newline at end of file diff --git a/common/sim/sub/fifo b/common/sim/sub/fifo new file mode 160000 index 0000000..9f35e49 --- /dev/null +++ b/common/sim/sub/fifo @@ -0,0 +1 @@ +Subproject commit 9f35e490dc33c36228bde25cc17c56ee6e5178ad diff --git a/mod_test.py b/mod_test.py new file mode 100644 index 0000000..e69de29