braindump
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -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
|
||||
|
||||
@@ -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.
|
||||
105
ChaCha20_Poly1305_64/doc/notes3.md
Normal file
105
ChaCha20_Poly1305_64/doc/notes3.md
Normal file
@@ -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.
|
||||
16
ChaCha20_Poly1305_64/doc/sanity.py
Normal file
16
ChaCha20_Poly1305_64/doc/sanity.py
Normal file
@@ -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)
|
||||
@@ -1 +1 @@
|
||||
create_clock -period 2.5 -name clk [get_ports i_clk]
|
||||
create_clock -period 20 -name clk [get_ports i_clk]
|
||||
@@ -1,16 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<efx:project name="poly1305_timing_test" description="" last_change="1752448578" sw_version="2025.1.110" last_run_state="pass" last_run_flow="bitstream" config_result_in_sync="true" design_ood="sync" place_ood="sync" route_ood="sync" xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">
|
||||
<efx:project name="poly1305_timing_test" description="" last_change="1784047128" sw_version="2025.1.110" last_run_state="pass" last_run_flow="bitstream" config_result_in_sync="true" design_ood="sync" place_ood="sync" route_ood="sync" xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">
|
||||
<efx:device_info>
|
||||
<efx:family name="Titanium"/>
|
||||
<efx:device name="Ti375N1156"/>
|
||||
<efx:timing_model name="C4"/>
|
||||
</efx:device_info>
|
||||
<efx:design_info def_veri_version="sv_09" def_vhdl_version="vhdl_2008" unified_flow="false">
|
||||
<efx:top_module name="mult_timing_test"/>
|
||||
<efx:design_file name="../src/poly1305_core.sv" version="default" library="default"/>
|
||||
<efx:design_file name="../../common/sim/sub/taxi/src/axis/rtl/taxi_axis_if.sv" version="default" library="default"/>
|
||||
<efx:design_file name="../sim/poly1305_core_wrapper.sv" version="default" library="default"/>
|
||||
<efx:design_file name="mult_timing_test.sv" version="default" library="default"/>
|
||||
<efx:top_module name="chacha20_flat_qr"/>
|
||||
<efx:design_file name="../src/poly1305_ll_stage.sv" version="default" library="default"/>
|
||||
<efx:design_file name="../src/poly1305_width_convert.sv" version="default" library="default"/>
|
||||
<efx:design_file name="../src/chacha20_flat_qr.sv" version="default" library="default"/>
|
||||
<efx:top_vhdl_arch name=""/>
|
||||
</efx:design_info>
|
||||
<efx:constraint_info>
|
||||
@@ -41,7 +40,7 @@
|
||||
<efx:param name="min-sr-fanout" value="0" value_type="e_integer"/>
|
||||
<efx:param name="min-ce-fanout" value="0" value_type="e_integer"/>
|
||||
<efx:param name="mode" value="speed" value_type="e_option"/>
|
||||
<efx:param name="mult-auto-pipeline" value="1" value_type="e_integer"/>
|
||||
<efx:param name="mult-auto-pipeline" value="0" value_type="e_integer"/>
|
||||
<efx:param name="mult-decomp-retime" value="1" value_type="e_option"/>
|
||||
<efx:param name="operator-sharing" value="1" value_type="e_option"/>
|
||||
<efx:param name="optimize-adder-tree" value="1" value_type="e_option"/>
|
||||
|
||||
208
ChaCha20_Poly1305_64/sim/chacha20_poly1305_32_ll_core.py
Normal file
208
ChaCha20_Poly1305_64/sim/chacha20_poly1305_32_ll_core.py
Normal file
@@ -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")
|
||||
@@ -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
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
320
ChaCha20_Poly1305_64/src/chacha20_poly1305_32_ll_core.sv
Normal file
320
ChaCha20_Poly1305_64/src/chacha20_poly1305_32_ll_core.sv
Normal file
@@ -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
|
||||
88
ChaCha20_Poly1305_64/src/chacha20_poly1305_input_fsm.sv
Normal file
88
ChaCha20_Poly1305_64/src/chacha20_poly1305_input_fsm.sv
Normal file
@@ -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
|
||||
110
ChaCha20_Poly1305_64/src/chacha20_poly1305_mid_fsm.sv
Normal file
110
ChaCha20_Poly1305_64/src/chacha20_poly1305_mid_fsm.sv
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
88
ChaCha20_Poly1305_64/src/poly1305_width_convert_2.sv
Normal file
88
ChaCha20_Poly1305_64/src/poly1305_width_convert_2.sv
Normal file
@@ -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
|
||||
63
ChaCha20_Poly1305_64/src/poly1305_width_convert_3.sv
Normal file
63
ChaCha20_Poly1305_64/src/poly1305_width_convert_3.sv
Normal file
@@ -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
|
||||
114
ChaCha20_Poly1305_64/src/skidbuffer.sv
Normal file
114
ChaCha20_Poly1305_64/src/skidbuffer.sv
Normal file
@@ -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
|
||||
-------------------------------------------------------------------------------------------------------------------------------*/
|
||||
@@ -9,4 +9,12 @@ poly1305_friendly_modular_mult.sv
|
||||
poly1305_stage.sv
|
||||
|
||||
poly1305_width_convert.sv
|
||||
poly1305_ll_stage.sv
|
||||
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
|
||||
1
common/sim/sub/fifo
Submodule
1
common/sim/sub/fifo
Submodule
Submodule common/sim/sub/fifo added at 9f35e490dc
0
mod_test.py
Normal file
0
mod_test.py
Normal file
Reference in New Issue
Block a user