Add new poly1305 stage
I highly doubt this will pass timing... need to make a test harness to synthesize
This commit is contained in:
26
ChaCha20_Poly1305_64/doc/notes2.md
Normal file
26
ChaCha20_Poly1305_64/doc/notes2.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Requirements
|
||||
|
||||
* 2 Gbps operation
|
||||
* Handles both encrypt and decrypt
|
||||
|
||||
At reasonable FPGA speed of 250MHz, 2 Gbps requires a minimum width of 8 bits.
|
||||
|
||||
32 bits is a reasonable data width that would be common to see, and lets us
|
||||
have more breathing room while still maintaining line rate.
|
||||
|
||||
Module inputs and outputs
|
||||
|
||||
* clk
|
||||
* rst
|
||||
* data_in [31:0]
|
||||
* data_valid
|
||||
* data_ready
|
||||
* data_last
|
||||
* r [127:0]
|
||||
* s [127:0]
|
||||
* mac [127:0]
|
||||
* mac_valid
|
||||
|
||||
There is no output backpressure. since the result is just a single 128 bit number,
|
||||
we don't need to have a ready signal. if you want to add backpressure, add a register
|
||||
slice on the output outside of this module.
|
||||
102
ChaCha20_Poly1305_64/doc/poly1305_2.drawio
Normal file
102
ChaCha20_Poly1305_64/doc/poly1305_2.drawio
Normal file
@@ -0,0 +1,102 @@
|
||||
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/29.3.0 Chrome/140.0.7339.249 Electron/38.7.2 Safari/537.36" version="29.3.0">
|
||||
<diagram name="Page-1" id="k3McRs0H2XJFCpbK3g7K">
|
||||
<mxGraphModel dx="1008" dy="674" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-6" edge="1" parent="1" source="EpKCKhKhuYmIKFkPyJMO-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="EpKCKhKhuYmIKFkPyJMO-5">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-24" edge="1" parent="1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" target="EpKCKhKhuYmIKFkPyJMO-1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="79.99999999999989" y="260.0000000000001" as="sourcePoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-25" connectable="0" parent="EpKCKhKhuYmIKFkPyJMO-24" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" value="din[31:0]" vertex="1">
|
||||
<mxGeometry relative="1" x="-0.8485" as="geometry">
|
||||
<mxPoint x="-33" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-1" parent="1" style="rounded=0;whiteSpace=wrap;html=1;" value="32 -&gt; 128&nbsp;<div>width convert</div>" vertex="1">
|
||||
<mxGeometry height="40" width="120" x="120" y="240" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-3" parent="1" style="rounded=0;whiteSpace=wrap;html=1;" value="h [129:0]" vertex="1">
|
||||
<mxGeometry height="40" width="80" x="360" y="240" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-11" edge="1" parent="1" source="EpKCKhKhuYmIKFkPyJMO-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" target="EpKCKhKhuYmIKFkPyJMO-8">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-5" parent="1" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" value="+" vertex="1">
|
||||
<mxGeometry height="40" width="40" x="280" y="240" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-7" edge="1" parent="1" source="EpKCKhKhuYmIKFkPyJMO-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1.046;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" target="EpKCKhKhuYmIKFkPyJMO-5">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-14" edge="1" parent="1" source="EpKCKhKhuYmIKFkPyJMO-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="EpKCKhKhuYmIKFkPyJMO-13">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-8" parent="1" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" value="*" vertex="1">
|
||||
<mxGeometry height="40" width="40" x="280" y="320" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-10" edge="1" parent="1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="EpKCKhKhuYmIKFkPyJMO-8">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="80" y="340" as="sourcePoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-22" connectable="0" parent="EpKCKhKhuYmIKFkPyJMO-10" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" value="r [127:0]" vertex="1">
|
||||
<mxGeometry relative="1" x="-0.8764" y="-1" as="geometry">
|
||||
<mxPoint x="-42" y="-1" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-15" edge="1" parent="1" source="EpKCKhKhuYmIKFkPyJMO-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" target="EpKCKhKhuYmIKFkPyJMO-3">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="460" y="340" />
|
||||
<mxPoint x="460" y="260" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-19" edge="1" parent="1" source="EpKCKhKhuYmIKFkPyJMO-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="EpKCKhKhuYmIKFkPyJMO-16">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="460" y="340" />
|
||||
<mxPoint x="460" y="260" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-13" parent="1" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" value="%" vertex="1">
|
||||
<mxGeometry height="40" width="40" x="380" y="320" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-21" edge="1" parent="1" source="EpKCKhKhuYmIKFkPyJMO-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="EpKCKhKhuYmIKFkPyJMO-20">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-16" parent="1" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" value="+" vertex="1">
|
||||
<mxGeometry height="40" width="40" x="480" y="240" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-18" edge="1" parent="1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" target="EpKCKhKhuYmIKFkPyJMO-16">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="80" y="420" as="sourcePoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-23" connectable="0" parent="EpKCKhKhuYmIKFkPyJMO-18" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" value="s [127:0]" vertex="1">
|
||||
<mxGeometry relative="1" x="-0.975" y="1" as="geometry">
|
||||
<mxPoint x="-37" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-26" edge="1" parent="1" source="EpKCKhKhuYmIKFkPyJMO-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="640" y="260" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-27" connectable="0" parent="EpKCKhKhuYmIKFkPyJMO-26" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" value="mac [127:0]" vertex="1">
|
||||
<mxGeometry relative="1" x="0.7484" y="1" as="geometry">
|
||||
<mxPoint x="35" y="1" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="EpKCKhKhuYmIKFkPyJMO-20" parent="1" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" value="%" vertex="1">
|
||||
<mxGeometry height="40" width="40" x="560" y="240" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -22,4 +22,16 @@ tests:
|
||||
modules:
|
||||
- "poly1305_stage"
|
||||
sources: sources.list
|
||||
waves: True
|
||||
- name: "poly1305_width_convert"
|
||||
toplevel: "poly1305_width_convert"
|
||||
modules:
|
||||
- "poly1305_width_convert"
|
||||
sources: sources.list
|
||||
waves: True
|
||||
- name: "poly1305_ll_stage"
|
||||
toplevel: "poly1305_ll_stage"
|
||||
modules:
|
||||
- "poly1305_ll_stage"
|
||||
sources: sources.list
|
||||
waves: True
|
||||
72
ChaCha20_Poly1305_64/sim/poly1305_ll_stage.py
Normal file
72
ChaCha20_Poly1305_64/sim/poly1305_ll_stage.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import cocotb
|
||||
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import Timer, RisingEdge, FallingEdge
|
||||
from cocotb.handle import Immediate
|
||||
|
||||
import random
|
||||
|
||||
from array import array
|
||||
|
||||
CLK_PERIOD = 5
|
||||
|
||||
@cocotb.test
|
||||
async def test_sanity(dut):
|
||||
|
||||
data_bytes = b"Cryptographic Forum Research Group"
|
||||
|
||||
countm1 = [3 for _ in range(len(data_bytes)//4)]
|
||||
if len(data_bytes) % 4:
|
||||
countm1 += [len(data_bytes) % 4 -1]
|
||||
|
||||
print(len(data_bytes) % 4)
|
||||
print(len(data_bytes))
|
||||
print(countm1)
|
||||
|
||||
data_bytes += (len(data_bytes) - (len(data_bytes) //4 ) * 4) * b'\x00'
|
||||
data_in = array("I", data_bytes).tolist()
|
||||
|
||||
|
||||
print(data_in)
|
||||
|
||||
async def input_data():
|
||||
for count, word in zip(countm1, data_in[:-1]):
|
||||
dut.i_data.value = word
|
||||
dut.i_countm1.value = count
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 0
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_data.value = data_in[-1]
|
||||
dut.i_countm1.value = countm1[-1]
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 1
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_valid.value = 0
|
||||
dut.i_last.value = 0
|
||||
|
||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
||||
|
||||
dut.i_rst.value = Immediate(0)
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 1
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 0
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_r.value = 0x806d5400e52447c036d555408bed685
|
||||
dut.i_s.value = 0x1bf54941aff6bf4afdb20dfb8a800301
|
||||
|
||||
cocotb.start_soon(input_data())
|
||||
|
||||
await Timer(1, "us")
|
||||
480
ChaCha20_Poly1305_64/sim/poly1305_width_convert.py
Normal file
480
ChaCha20_Poly1305_64/sim/poly1305_width_convert.py
Normal file
@@ -0,0 +1,480 @@
|
||||
import cocotb
|
||||
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import Timer, RisingEdge, FallingEdge
|
||||
from cocotb.handle import Immediate
|
||||
|
||||
import math
|
||||
|
||||
import random
|
||||
|
||||
CLK_PERIOD = 5
|
||||
|
||||
|
||||
@cocotb.test
|
||||
async def test_sanity(dut):
|
||||
|
||||
data_in = [random.randint(0, 2**32-1) for _ in range(32)]
|
||||
|
||||
async def input_data():
|
||||
for word in data_in[:-1]:
|
||||
dut.i_data.value = word
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 0
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_data.value = data_in[-1]
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 1
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_valid.value = 0
|
||||
dut.i_last.value = 0
|
||||
|
||||
data_out = []
|
||||
|
||||
async def output_data():
|
||||
while True:
|
||||
if (dut.o_valid.value):
|
||||
data_out.append(int(dut.o_data.value))
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
||||
|
||||
|
||||
dut.i_rst.value = Immediate(0)
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 1
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 0
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_ready.value = 1
|
||||
|
||||
cocotb.start_soon(input_data())
|
||||
cocotb.start_soon(output_data())
|
||||
|
||||
await RisingEdge(dut.o_last)
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
expected_data_out = []
|
||||
for i in range(math.ceil(len(data_in)/4)):
|
||||
vals = data_in[i*4:(i+1)*4]
|
||||
|
||||
converted = 0
|
||||
for i, val in enumerate(vals):
|
||||
converted |= val << (32*i)
|
||||
|
||||
expected_data_out.append(converted)
|
||||
|
||||
|
||||
assert data_out == expected_data_out
|
||||
|
||||
@cocotb.test
|
||||
async def test_incomplete_last(dut):
|
||||
data_in = [random.randint(0, 2**32-1) for _ in range(30)]
|
||||
|
||||
async def input_data():
|
||||
for word in data_in[:-1]:
|
||||
dut.i_data.value = word
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 0
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_data.value = data_in[-1]
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 1
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_valid.value = 0
|
||||
dut.i_last.value = 0
|
||||
|
||||
data_out = []
|
||||
|
||||
async def output_data():
|
||||
while True:
|
||||
if (dut.o_valid.value):
|
||||
data_out.append(int(dut.o_data.value))
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
||||
|
||||
|
||||
dut.i_rst.value = Immediate(0)
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 1
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 0
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_ready.value = 1
|
||||
|
||||
cocotb.start_soon(input_data())
|
||||
cocotb.start_soon(output_data())
|
||||
|
||||
await RisingEdge(dut.o_last)
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
expected_data_out = []
|
||||
for i in range(math.ceil(len(data_in)/4)):
|
||||
vals = data_in[i*4:(i+1)*4]
|
||||
|
||||
converted = 0
|
||||
for i, val in enumerate(vals):
|
||||
converted |= val << (32*i)
|
||||
|
||||
expected_data_out.append(converted)
|
||||
|
||||
|
||||
assert data_out == expected_data_out
|
||||
|
||||
|
||||
@cocotb.test
|
||||
async def test_output_backpressure(dut):
|
||||
data_in = [random.randint(0, 2**32-1) for _ in range(32)]
|
||||
|
||||
async def input_data():
|
||||
for word in data_in[:-1]:
|
||||
dut.i_data.value = word
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 0
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_data.value = data_in[-1]
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 1
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_valid.value = 0
|
||||
dut.i_last.value = 0
|
||||
|
||||
data_out = []
|
||||
|
||||
async def output_data():
|
||||
while True:
|
||||
if (dut.o_valid.value and dut.i_ready.value):
|
||||
data_out.append(int(dut.o_data.value))
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
||||
|
||||
|
||||
dut.i_rst.value = Immediate(0)
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 1
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 0
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
async def output_backpressure():
|
||||
while True:
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_ready.value = random.randint(0, 100) < 75
|
||||
|
||||
cocotb.start_soon(output_backpressure())
|
||||
cocotb.start_soon(input_data())
|
||||
cocotb.start_soon(output_data())
|
||||
|
||||
while True:
|
||||
await RisingEdge(dut.i_clk)
|
||||
if dut.o_last.value and dut.i_ready.value:
|
||||
break
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
|
||||
expected_data_out = []
|
||||
for i in range(math.ceil(len(data_in)/4)):
|
||||
vals = data_in[i*4:(i+1)*4]
|
||||
|
||||
converted = 0
|
||||
for i, val in enumerate(vals):
|
||||
converted |= val << (32*i)
|
||||
|
||||
expected_data_out.append(converted)
|
||||
|
||||
|
||||
if not data_out == expected_data_out:
|
||||
print(data_out)
|
||||
print(expected_data_out)
|
||||
|
||||
assert data_out == expected_data_out
|
||||
|
||||
@cocotb.test
|
||||
async def test_output_backpressure_nonfull(dut):
|
||||
data_in = [random.randint(0, 2**32-1) for _ in range(30)]
|
||||
|
||||
async def input_data():
|
||||
for word in data_in[:-1]:
|
||||
dut.i_data.value = word
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 0
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_data.value = data_in[-1]
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 1
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_valid.value = 0
|
||||
dut.i_last.value = 0
|
||||
|
||||
data_out = []
|
||||
|
||||
async def output_data():
|
||||
while True:
|
||||
if (dut.o_valid.value and dut.i_ready.value):
|
||||
data_out.append(int(dut.o_data.value))
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
||||
|
||||
|
||||
dut.i_rst.value = Immediate(0)
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 1
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 0
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
async def output_backpressure():
|
||||
while True:
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_ready.value = random.randint(0, 100) < 75
|
||||
|
||||
cocotb.start_soon(output_backpressure())
|
||||
cocotb.start_soon(input_data())
|
||||
cocotb.start_soon(output_data())
|
||||
|
||||
while True:
|
||||
await RisingEdge(dut.i_clk)
|
||||
if dut.o_last.value and dut.i_ready.value:
|
||||
break
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
|
||||
expected_data_out = []
|
||||
for i in range(math.ceil(len(data_in)/4)):
|
||||
vals = data_in[i*4:(i+1)*4]
|
||||
|
||||
converted = 0
|
||||
for i, val in enumerate(vals):
|
||||
converted |= val << (32*i)
|
||||
|
||||
expected_data_out.append(converted)
|
||||
|
||||
|
||||
if not data_out == expected_data_out:
|
||||
print(data_out)
|
||||
print(expected_data_out)
|
||||
|
||||
assert data_out == expected_data_out
|
||||
|
||||
|
||||
@cocotb.test
|
||||
async def test_input_nonvalid(dut):
|
||||
data_in = [random.randint(0, 2**32-1) for _ in range(32)]
|
||||
|
||||
async def input_data():
|
||||
for word in data_in[:-1]:
|
||||
dut.i_data.value = word
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 0
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
if random.randint(0, 10) > 7:
|
||||
dut.i_valid.value = 0
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
|
||||
dut.i_data.value = data_in[-1]
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 1
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_valid.value = 0
|
||||
dut.i_last.value = 0
|
||||
|
||||
data_out = []
|
||||
|
||||
async def output_data():
|
||||
while True:
|
||||
if (dut.o_valid.value and dut.i_ready.value):
|
||||
data_out.append(int(dut.o_data.value))
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
||||
|
||||
|
||||
dut.i_rst.value = Immediate(0)
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 1
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 0
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_ready.value = 1
|
||||
|
||||
cocotb.start_soon(input_data())
|
||||
cocotb.start_soon(output_data())
|
||||
|
||||
while True:
|
||||
await RisingEdge(dut.i_clk)
|
||||
if dut.o_last.value and dut.i_ready.value:
|
||||
break
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
|
||||
expected_data_out = []
|
||||
for i in range(math.ceil(len(data_in)/4)):
|
||||
vals = data_in[i*4:(i+1)*4]
|
||||
|
||||
converted = 0
|
||||
for i, val in enumerate(vals):
|
||||
converted |= val << (32*i)
|
||||
|
||||
expected_data_out.append(converted)
|
||||
|
||||
|
||||
if not data_out == expected_data_out:
|
||||
print(data_out)
|
||||
print(expected_data_out)
|
||||
|
||||
assert data_out == expected_data_out
|
||||
|
||||
@cocotb.test
|
||||
async def test_input_nonvalid_output_nonready(dut):
|
||||
data_in = [random.randint(0, 2**32-1) for _ in range(30)]
|
||||
|
||||
async def input_data():
|
||||
for word in data_in[:-1]:
|
||||
dut.i_data.value = word
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 0
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
if random.randint(0, 10) > 7:
|
||||
dut.i_valid.value = 0
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
|
||||
dut.i_data.value = data_in[-1]
|
||||
dut.i_valid.value = 1
|
||||
dut.i_last.value = 1
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
while (not dut.o_ready.value):
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_valid.value = 0
|
||||
dut.i_last.value = 0
|
||||
|
||||
data_out = []
|
||||
|
||||
async def output_data():
|
||||
while True:
|
||||
if (dut.o_valid.value and dut.i_ready.value):
|
||||
data_out.append(int(dut.o_data.value))
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
||||
|
||||
|
||||
dut.i_rst.value = Immediate(0)
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 1
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 0
|
||||
await RisingEdge(dut.i_clk)
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
async def output_backpressure():
|
||||
while True:
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
dut.i_ready.value = random.randint(0, 100) < 75
|
||||
|
||||
cocotb.start_soon(output_backpressure())
|
||||
cocotb.start_soon(input_data())
|
||||
cocotb.start_soon(output_data())
|
||||
|
||||
while True:
|
||||
await RisingEdge(dut.i_clk)
|
||||
if dut.o_last.value and dut.i_ready.value:
|
||||
break
|
||||
|
||||
await RisingEdge(dut.i_clk)
|
||||
|
||||
|
||||
expected_data_out = []
|
||||
for i in range(math.ceil(len(data_in)/4)):
|
||||
vals = data_in[i*4:(i+1)*4]
|
||||
|
||||
converted = 0
|
||||
for i, val in enumerate(vals):
|
||||
converted |= val << (32*i)
|
||||
|
||||
expected_data_out.append(converted)
|
||||
|
||||
|
||||
if not data_out == expected_data_out:
|
||||
print(data_out)
|
||||
print(expected_data_out)
|
||||
|
||||
assert data_out == expected_data_out
|
||||
@@ -1,3 +1,5 @@
|
||||
// FPGA Friendly modular multiplication. takes ~6 cycles
|
||||
|
||||
module poly1305_friendly_modular_mult #(
|
||||
parameter DATA_WIDTH = 130,
|
||||
parameter ACC_WIDTH = 130
|
||||
|
||||
231
ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv
Normal file
231
ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv
Normal file
@@ -0,0 +1,231 @@
|
||||
// Low latency poly1305 core
|
||||
//
|
||||
// Target 2 cycles per 128 bit block
|
||||
|
||||
module poly1305_ll_stage (
|
||||
input logic i_clk,
|
||||
input logic i_rst,
|
||||
|
||||
input logic i_valid,
|
||||
input logic [1:0] i_countm1,
|
||||
output logic o_ready,
|
||||
input logic [31:0] i_data,
|
||||
input logic i_last,
|
||||
input logic [127:0] i_r,
|
||||
input logic [127:0] i_s,
|
||||
|
||||
output logic o_valid,
|
||||
output logic [127:0] o_result
|
||||
);
|
||||
|
||||
localparam [129:0] PRIME = (1 << 130) - 5;
|
||||
|
||||
logic upconvert_ready;
|
||||
logic upconvert_valid;
|
||||
logic upconvert_last;
|
||||
logic [127:0] upconvert_data;
|
||||
logic [3:0] upconvert_countm1;
|
||||
|
||||
|
||||
poly1305_width_convert u_width_convert(
|
||||
.i_clk (i_clk),
|
||||
.i_rst (i_rst),
|
||||
|
||||
.i_valid (i_valid),
|
||||
.i_countm1 (i_countm1),
|
||||
.o_ready (o_ready),
|
||||
.i_data (i_data),
|
||||
.i_last (i_last),
|
||||
|
||||
.o_valid (upconvert_valid),
|
||||
.o_countm1 (upconvert_countm1),
|
||||
.i_ready (upconvert_ready),
|
||||
.o_data (upconvert_data),
|
||||
.o_last (upconvert_last)
|
||||
);
|
||||
|
||||
logic [127:0] r_reg, s_reg, s_reg_2;
|
||||
logic [127:0] r_reg_next, s_reg_next, s_reg_2_next;;
|
||||
|
||||
enum logic [2:0] {IDLE, SUM, MULT, MODULO_1, MODULO_2} state, state_next;
|
||||
|
||||
enum logic [1:0] {OUTPUT_IDLE, OUTPUT_ADD, OUTPUT_OUT} output_state, output_state_next;
|
||||
|
||||
logic [129:0] h, h_next;
|
||||
|
||||
logic [130:0] data_1extend;
|
||||
|
||||
logic [130:0] sum, sum_next;
|
||||
|
||||
logic [258:0] product, product_next;
|
||||
|
||||
logic [131:0] mod1;
|
||||
logic [131:0] mod2_upper, mod2_upper_next;
|
||||
logic [129:0] mod2_lower, mod2_lower_next;
|
||||
logic [131:0] mod2;
|
||||
logic [131:0] mod3;
|
||||
|
||||
|
||||
logic [130:0] final_sum, final_sum_next;
|
||||
logic [130:0] final_mod;
|
||||
|
||||
logic start_output;
|
||||
|
||||
logic last_flag, last_flag_next;
|
||||
|
||||
always_ff @(posedge i_clk) begin
|
||||
if (i_rst) begin
|
||||
r_reg <= '0;
|
||||
s_reg <= '0;
|
||||
s_reg_2 <= '0;
|
||||
|
||||
last_flag <= '0;
|
||||
|
||||
state <= IDLE;
|
||||
output_state <= OUTPUT_IDLE;
|
||||
end else begin
|
||||
r_reg <= r_reg_next;
|
||||
s_reg <= s_reg_next;
|
||||
s_reg_2 <= s_reg_2_next;
|
||||
|
||||
mod2_upper <= mod2_upper_next;
|
||||
mod2_lower <= mod2_lower_next;
|
||||
|
||||
h <= h_next;
|
||||
|
||||
sum <= sum_next;
|
||||
product <= product_next;
|
||||
|
||||
last_flag <= last_flag_next;
|
||||
|
||||
state <= state_next;
|
||||
output_state <= output_state_next;
|
||||
|
||||
final_sum <= final_sum_next;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
h_next = h;
|
||||
|
||||
sum_next = '0;
|
||||
product_next = '0;
|
||||
|
||||
r_reg_next = r_reg;
|
||||
s_reg_next = s_reg;
|
||||
|
||||
upconvert_ready = '0;
|
||||
|
||||
last_flag_next = last_flag;
|
||||
|
||||
state_next = state;
|
||||
|
||||
mod1 = '0;
|
||||
mod2 = '0;
|
||||
mod2_upper_next = '0;
|
||||
mod2_lower_next = '0;
|
||||
mod3 = '0;
|
||||
|
||||
data_1extend = '0;
|
||||
|
||||
start_output = '0;
|
||||
|
||||
case (state)
|
||||
IDLE: begin
|
||||
upconvert_ready = '1;
|
||||
|
||||
if (upconvert_valid) begin
|
||||
data_1extend = {3'b0, upconvert_data} | (131'b1 << (8*(1+upconvert_countm1)));
|
||||
sum_next = data_1extend;
|
||||
|
||||
state_next = MULT;
|
||||
|
||||
r_reg_next = i_r;
|
||||
s_reg_next = i_s;
|
||||
end
|
||||
end
|
||||
|
||||
SUM: begin
|
||||
last_flag_next = upconvert_last;
|
||||
|
||||
upconvert_ready = '1;
|
||||
data_1extend = {3'b0, upconvert_data} | (131'b1 << (8*(1+upconvert_countm1)));
|
||||
sum_next = h + data_1extend;
|
||||
|
||||
state_next = MULT;
|
||||
end
|
||||
|
||||
MULT: begin
|
||||
product_next = sum * r_reg;
|
||||
|
||||
state_next = MODULO_1;
|
||||
end
|
||||
|
||||
MODULO_1: begin
|
||||
mod1 = (product[258:130] * 5) + {2'b0, product[129:0]};
|
||||
mod2_upper_next = mod1[131:130] * 5;
|
||||
mod2_lower_next = mod1[129:0];
|
||||
|
||||
state_next = MODULO_2;
|
||||
end
|
||||
|
||||
MODULO_2: begin
|
||||
mod2 = mod2_upper + {2'b0, mod2_lower};
|
||||
mod3 = (mod2[131:130] * 5) + {2'b0, mod2[129:0]};
|
||||
|
||||
if (mod3[129:0] > PRIME) begin
|
||||
h_next = mod3[129:0] - PRIME;
|
||||
end else begin
|
||||
h_next = mod3[129:0];
|
||||
end
|
||||
|
||||
if (last_flag) begin
|
||||
state_next = IDLE;
|
||||
last_flag_next = '0;
|
||||
s_reg_2_next = s_reg;
|
||||
start_output = '1;
|
||||
end else begin
|
||||
state_next = SUM;
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
|
||||
end
|
||||
|
||||
endcase
|
||||
|
||||
output_state_next = output_state;
|
||||
|
||||
case (output_state)
|
||||
OUTPUT_IDLE: begin
|
||||
if (start_output) begin
|
||||
output_state_next = OUTPUT_ADD;
|
||||
end
|
||||
end
|
||||
|
||||
OUTPUT_ADD: begin
|
||||
final_sum_next = h + {3'b0, s_reg_2};
|
||||
output_state_next = OUTPUT_OUT;
|
||||
end
|
||||
|
||||
OUTPUT_OUT: begin
|
||||
if (final_sum > {1'b0, PRIME}) begin
|
||||
final_mod = final_sum - PRIME;
|
||||
end else begin
|
||||
final_mod = final_sum;
|
||||
end
|
||||
|
||||
o_valid = '1;
|
||||
o_result = final_mod[127:0];
|
||||
|
||||
output_state_next = OUTPUT_IDLE;
|
||||
end
|
||||
|
||||
default: begin
|
||||
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
79
ChaCha20_Poly1305_64/src/poly1305_width_convert.sv
Normal file
79
ChaCha20_Poly1305_64/src/poly1305_width_convert.sv
Normal file
@@ -0,0 +1,79 @@
|
||||
module poly1305_width_convert(
|
||||
input logic i_clk,
|
||||
input logic i_rst,
|
||||
|
||||
input logic i_valid,
|
||||
input logic [1:0] i_countm1,
|
||||
output logic o_ready,
|
||||
input logic [31:0] i_data,
|
||||
input logic i_last,
|
||||
|
||||
output logic o_valid,
|
||||
output logic [3:0] o_countm1,
|
||||
input logic i_ready,
|
||||
output logic [127:0] o_data,
|
||||
output logic o_last
|
||||
);
|
||||
|
||||
|
||||
logic [95:0] width_convert_save, width_convert_save_next;
|
||||
logic [1:0] width_convert_count, width_convert_count_next;
|
||||
|
||||
always_ff @(posedge i_clk) begin
|
||||
if (i_rst) begin
|
||||
width_convert_save <= '0;
|
||||
width_convert_count <= '0;
|
||||
end else begin
|
||||
width_convert_count <= width_convert_count_next;
|
||||
width_convert_save <= width_convert_save_next;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
width_convert_save_next = width_convert_save;
|
||||
width_convert_count_next = width_convert_count;
|
||||
|
||||
o_valid = '0;
|
||||
o_ready = '0;
|
||||
o_last = '0;
|
||||
|
||||
o_countm1 = '1;
|
||||
|
||||
if (width_convert_count < 3) begin
|
||||
o_data = {32'b0, width_convert_save};
|
||||
o_data[32*width_convert_count +: 32] = i_data;
|
||||
|
||||
if (i_last && i_valid) begin
|
||||
o_ready = i_ready;
|
||||
o_valid = '1;
|
||||
o_last = '1;
|
||||
|
||||
o_countm1 = width_convert_count*4 + {2'b0, i_countm1};
|
||||
|
||||
if (i_ready) begin
|
||||
width_convert_count_next = '0;
|
||||
width_convert_save_next = '0;
|
||||
end
|
||||
end else begin
|
||||
width_convert_save_next[32*width_convert_count +: 32] = i_data;
|
||||
if (i_valid) begin
|
||||
o_ready = '1;
|
||||
width_convert_count_next = width_convert_count + 2'd1;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
o_ready = i_ready;
|
||||
o_valid = i_valid;
|
||||
o_data = {i_data, width_convert_save};
|
||||
o_last = i_last;
|
||||
|
||||
o_countm1 = 4'd12 + {2'b0, i_countm1};
|
||||
|
||||
if (i_valid && o_ready) begin
|
||||
width_convert_count_next = '0;
|
||||
width_convert_save_next = '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -6,4 +6,7 @@ chacha20_pipelined_block.sv
|
||||
poly1305_core.sv
|
||||
poly1305_friendly_modulo.sv
|
||||
poly1305_friendly_modular_mult.sv
|
||||
poly1305_stage.sv
|
||||
poly1305_stage.sv
|
||||
|
||||
poly1305_width_convert.sv
|
||||
poly1305_ll_stage.sv
|
||||
Reference in New Issue
Block a user