Add basic repo

This commit is contained in:
Byron Lathi
2025-06-28 15:48:14 -07:00
parent 369e29557c
commit 8136a7526b
21 changed files with 1069 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
.venv
sim_build
*.bkp
outflow
work_pnr
work_pt
work_syn
.lock

View File

@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<efxpt:design_db name="chacha20_timing_test" device_def="Ti375N1156" version="2025.1.110" db_version="20251999" last_change_date="Tue Jun 24 23:45:17 2025" xmlns:efxpt="http://www.efinixinc.com/peri_design_db" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/peri_design_db peri_design_db.xsd ">
<efxpt:device_info>
<efxpt:iobank_info>
<efxpt:iobank name="2A" iostd="1.8 V LVCMOS" is_dyn_voltage="false" mode_sel_name="2A_MODE_SEL"/>
<efxpt:iobank name="2B" iostd="1.8 V LVCMOS" is_dyn_voltage="false" mode_sel_name="2B_MODE_SEL"/>
<efxpt:iobank name="2C" iostd="1.8 V LVCMOS" is_dyn_voltage="false" mode_sel_name="2C_MODE_SEL"/>
<efxpt:iobank name="2D" iostd="1.8 V LVCMOS" is_dyn_voltage="false" mode_sel_name="2D_MODE_SEL"/>
<efxpt:iobank name="2E" iostd="1.8 V LVCMOS" is_dyn_voltage="false" mode_sel_name="2E_MODE_SEL"/>
<efxpt:iobank name="4A" iostd="1.8 V LVCMOS" is_dyn_voltage="false" mode_sel_name="4A_MODE_SEL"/>
<efxpt:iobank name="4B" iostd="1.8 V LVCMOS" is_dyn_voltage="false" mode_sel_name="4B_MODE_SEL"/>
<efxpt:iobank name="4C" iostd="1.8 V LVCMOS" is_dyn_voltage="false" mode_sel_name="4C_MODE_SEL"/>
<efxpt:iobank name="4D" iostd="1.8 V LVCMOS" is_dyn_voltage="false" mode_sel_name="4D_MODE_SEL"/>
<efxpt:iobank name="BL0" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="BL0_MODE_SEL"/>
<efxpt:iobank name="BL1" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="BL1_MODE_SEL"/>
<efxpt:iobank name="BL2" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="BL2_MODE_SEL"/>
<efxpt:iobank name="BL3" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="BL3_MODE_SEL"/>
<efxpt:iobank name="BR0" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="BR0_MODE_SEL"/>
<efxpt:iobank name="BR1" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="BR1_MODE_SEL"/>
<efxpt:iobank name="BR3" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="BR3_MODE_SEL"/>
<efxpt:iobank name="BR4" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="BR4_MODE_SEL"/>
<efxpt:iobank name="TL0" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="TL0_MODE_SEL"/>
<efxpt:iobank name="TL1_TL5" iostd="3.3 V LVCMOS" is_dyn_voltage="false">
<efxpt:mode_sel_name>
<efxpt:pin_name bank_name="TL1" value="TL1_MODE_SEL"/>
<efxpt:pin_name bank_name="TL5" value="TL5_MODE_SEL"/>
</efxpt:mode_sel_name>
</efxpt:iobank>
<efxpt:iobank name="TR0" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="TR0_MODE_SEL"/>
<efxpt:iobank name="TR1" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="TR1_MODE_SEL"/>
<efxpt:iobank name="TR2" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="TR2_MODE_SEL"/>
<efxpt:iobank name="TR3" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="TR3_MODE_SEL"/>
<efxpt:iobank name="TR5" iostd="3.3 V LVCMOS" is_dyn_voltage="false" mode_sel_name="TR5_MODE_SEL"/>
</efxpt:iobank_info>
<efxpt:ctrl_info>
<efxpt:ctrl name="cfg" ctrl_def="CONFIG_CTRL0" clock_name="" is_clk_invert="false" cbsel_bus_name="cfg_CBSEL" config_ctrl_name="cfg_CONFIG" ena_capture_name="cfg_ENA" error_status_name="cfg_ERROR" um_signal_status_name="cfg_USR_STATUS" is_remote_update_enable="false" is_user_mode_enable="false">
<efxpt:gen_param>
<efxpt:param name="remote_update_retries" value="0" value_type="int"/>
</efxpt:gen_param>
</efxpt:ctrl>
</efxpt:ctrl_info>
<efxpt:seu_info>
<efxpt:seu name="seu" block_def="CONFIG_SEU0" mode="auto" ena_detect="false" wait_interval="16500000">
<efxpt:gen_pin>
<efxpt:pin name="seu_START" type_name="START" is_bus="false"/>
<efxpt:pin name="seu_INJECT_ERROR" type_name="INJECT_ERROR" is_bus="false"/>
<efxpt:pin name="seu_RST" type_name="RST" is_bus="false"/>
<efxpt:pin name="seu_CONFIG" type_name="CONFIG" is_bus="false"/>
<efxpt:pin name="seu_ERROR" type_name="ERROR" is_bus="false"/>
<efxpt:pin name="seu_DONE" type_name="DONE" is_bus="false"/>
</efxpt:gen_pin>
</efxpt:seu>
</efxpt:seu_info>
<efxpt:clkmux_info>
<efxpt:clkmux name="GCLKMUX_B" block_def="GCLKMUX_B" is_mux_bot0_dyn="false" is_mux_bot7_dyn="false">
<efxpt:gen_pin>
<efxpt:pin name="" type_name="ROUTE0" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE1" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE2" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE3" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="DYN_MUX_OUT_0" is_bus="false"/>
<efxpt:pin name="" type_name="DYN_MUX_OUT_7" is_bus="false"/>
<efxpt:pin name="" type_name="DYN_MUX_SEL_0" is_bus="true"/>
<efxpt:pin name="" type_name="DYN_MUX_SEL_7" is_bus="true"/>
</efxpt:gen_pin>
</efxpt:clkmux>
<efxpt:clkmux name="GCLKMUX_L" block_def="GCLKMUX_L" is_mux_bot0_dyn="false" is_mux_bot7_dyn="false">
<efxpt:gen_pin>
<efxpt:pin name="" type_name="ROUTE0" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE1" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE2" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE3" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="DYN_MUX_OUT_0" is_bus="false"/>
<efxpt:pin name="" type_name="DYN_MUX_OUT_7" is_bus="false"/>
<efxpt:pin name="" type_name="DYN_MUX_SEL_0" is_bus="true"/>
<efxpt:pin name="" type_name="DYN_MUX_SEL_7" is_bus="true"/>
</efxpt:gen_pin>
</efxpt:clkmux>
<efxpt:clkmux name="GCLKMUX_R" block_def="GCLKMUX_R" is_mux_bot0_dyn="false" is_mux_bot7_dyn="false">
<efxpt:gen_pin>
<efxpt:pin name="" type_name="ROUTE0" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE1" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE2" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE3" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="DYN_MUX_OUT_0" is_bus="false"/>
<efxpt:pin name="" type_name="DYN_MUX_OUT_7" is_bus="false"/>
<efxpt:pin name="" type_name="DYN_MUX_SEL_0" is_bus="true"/>
<efxpt:pin name="" type_name="DYN_MUX_SEL_7" is_bus="true"/>
</efxpt:gen_pin>
</efxpt:clkmux>
<efxpt:clkmux name="GCLKMUX_T" block_def="GCLKMUX_T" is_mux_bot0_dyn="false" is_mux_bot7_dyn="false">
<efxpt:gen_pin>
<efxpt:pin name="" type_name="ROUTE0" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE1" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE2" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="ROUTE3" is_bus="false" is_clk="true" is_clk_invert="false"/>
<efxpt:pin name="" type_name="DYN_MUX_OUT_0" is_bus="false"/>
<efxpt:pin name="" type_name="DYN_MUX_OUT_7" is_bus="false"/>
<efxpt:pin name="" type_name="DYN_MUX_SEL_0" is_bus="true"/>
<efxpt:pin name="" type_name="DYN_MUX_SEL_7" is_bus="true"/>
</efxpt:gen_pin>
</efxpt:clkmux>
</efxpt:clkmux_info>
</efxpt:device_info>
<efxpt:gpio_info>
<efxpt:global_unused_config state="input with weak pullup"/>
</efxpt:gpio_info>
<efxpt:pll_info/>
<efxpt:osc_info/>
<efxpt:lvds_info/>
<efxpt:mipi_info/>
<efxpt:jtag_info/>
<efxpt:ddr_info/>
<efxpt:mipi_dphy_info/>
<efxpt:pll_ssc_info/>
<efxpt:quad_lane_info/>
<efxpt:quad_pcie_info/>
<efxpt:lane_10g_info/>
<efxpt:lane_1g_info/>
<efxpt:raw_serdes_info/>
<efxpt:soc_info/>
</efxpt:design_db>

View File

@@ -0,0 +1,75 @@
// do an entire round combinationally
`define ROTL(x, n) {x[31-n:0], x[31:32-n]}
module chacha20_qr #(
parameter PIPELINE_STAGES=7
)(
input i_clk,
input i_rst,
input i_valid,
output o_ready,
input logic [31:0] a_i, b_i, c_i, d_i,
output o_valid,
input i_ready,
output logic [31:0] a_o, b_o, c_o, d_o
);
logic [31:0] a_int [7];
logic [31:0] b_int [7];
logic [31:0] c_int [7];
logic [31:0] d_int [7];
logic [6:0] valid_sr;
// There is an output stage which handles isolating backpressure from the rest
// of the design from the core, so we don't need to worry about it here, we can
// have a single signal gate all of this.
assign o_ready = i_ready;
always_ff @(posedge i_clk) begin
if (i_rst) begin
valid_sr <= '0;
end else begin
if (i_ready) begin
// 1. Update A
a_int[0] <= a_i + b_i;
b_int[0] <= b_i;
c_int[0] <= c_i;
d_int[0] <= d_i;
// 2. Update D
a_int[1] <= a_int[0];
b_int[1] <= b_int[0];
c_int[1] <= c_int[0];
d_int[1] <= `ROTL(a_int[0] ^ d_int[0], 16);
end
end
end
endmodule
// always_comb begin
// a_int_0 = a_i + b_i;
// d_int_0 = a_int_0 ^ d_i;
// d_int_1 = `ROTL(d_int_0, 16);
// c_int_0 = c_i + d_int_1;
// b_int_0 = c_int_0 ^ b_i;
// b_int_1 = `ROTL(b_int_0, 12);
// a_o = a_int_0 + b_int_1;
// d_int_2 = d_int_1 ^ a_o;
// d_o = `ROTL(d_int_2, 8);
// c_o = c_int_0 + d_o;
// b_int_2 = b_int_1 ^ c_o;
// b_o = `ROTL(b_int_2, 7);
// end
// endmodule

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<efx:project name="chacha20_timing_test" description="" last_change="1751042439" sw_version="2025.1.110" last_run_state="pass" last_run_flow="syn" config_result_in_sync="true" design_ood="change" place_ood="change" 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="chacha20_block"/>
<efx:design_file name="../src/chacha20_qr.sv" version="default" library="default"/>
<efx:design_file name="../src/chacha20_block.sv" version="default" library="default"/>
<efx:top_vhdl_arch name=""/>
</efx:design_info>
<efx:constraint_info>
<efx:sdc_file name="constraints.sdc"/>
<efx:inter_file name=""/>
</efx:constraint_info>
<efx:sim_info/>
<efx:misc_info/>
<efx:ip_info/>
<efx:synthesis tool_name="efx_map">
<efx:param name="work_dir" value="work_syn" value_type="e_string"/>
<efx:param name="write_efx_verilog" value="on" value_type="e_bool"/>
<efx:param name="allow-const-ram-index" value="0" value_type="e_option"/>
<efx:param name="blackbox-error" value="1" value_type="e_option"/>
<efx:param name="blast_const_operand_adders" value="1" value_type="e_option"/>
<efx:param name="bram_output_regs_packing" value="1" value_type="e_option"/>
<efx:param name="bram-push-tco-outreg" value="0" value_type="e_option"/>
<efx:param name="create-onehot-fsms" value="0" value_type="e_option"/>
<efx:param name="fanout-limit" value="100" value_type="e_integer"/>
<efx:param name="hdl-compile-unit" value="1" value_type="e_option"/>
<efx:param name="hdl-loop-limit" value="20000" value_type="e_integer"/>
<efx:param name="infer-clk-enable" value="3" value_type="e_option"/>
<efx:param name="infer-sync-set-reset" value="1" value_type="e_option"/>
<efx:param name="max_ram" value="-1" value_type="e_integer"/>
<efx:param name="max_mult" value="-1" value_type="e_integer"/>
<efx:param name="max-bit-blast-mem-size" value="10240" value_type="e_integer"/>
<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="0" value_type="e_integer"/>
<efx:param name="mult-decomp-retime" value="0" value_type="e_option"/>
<efx:param name="operator-sharing" value="0" value_type="e_option"/>
<efx:param name="optimize-adder-tree" value="0" value_type="e_option"/>
<efx:param name="optimize-zero-init-rom" value="1" value_type="e_option"/>
<efx:param name="peri-syn-instantiation" value="0" value_type="e_option"/>
<efx:param name="peri-syn-inference" value="0" value_type="e_option"/>
<efx:param name="ram-decomp-mode" value="0" value_type="e_option"/>
<efx:param name="retiming" value="1" value_type="e_option"/>
<efx:param name="seq_opt" value="1" value_type="e_option"/>
<efx:param name="seq-opt-sync-only" value="0" value_type="e_option"/>
<efx:param name="use-logic-for-small-mem" value="64" value_type="e_integer"/>
<efx:param name="use-logic-for-small-rom" value="64" value_type="e_integer"/>
<efx:param name="max_threads" value="-1" value_type="e_integer"/>
<efx:param name="enable-mark-debug" value="1" value_type="e_option"/>
<efx:param name="dsp-input-regs-packing" value="1" value_type="e_option"/>
<efx:param name="dsp-output-regs-packing" value="1" value_type="e_option"/>
<efx:param name="dsp-mac-packing" value="1" value_type="e_option"/>
<efx:param name="insert-carry-skip" value="0" value_type="e_option"/>
<efx:param name="pack-luts-to-comb4" value="0" value_type="e_option"/>
</efx:synthesis>
<efx:place_and_route tool_name="efx_pnr">
<efx:param name="work_dir" value="work_pnr" value_type="e_string"/>
<efx:param name="verbose" value="off" value_type="e_bool"/>
<efx:param name="load_delaym" value="on" value_type="e_bool"/>
<efx:param name="optimization_level" value="TIMING_3" value_type="e_option"/>
<efx:param name="seed" value="3" value_type="e_integer"/>
<efx:param name="placer_effort_level" value="5" value_type="e_option"/>
<efx:param name="max_threads" value="-1" value_type="e_integer"/>
<efx:param name="print_critical_path" value="10" value_type="e_integer"/>
<efx:param name="classic_flow" value="off" value_type="e_noarg"/>
<efx:param name="beneficial_skew" value="on" value_type="e_option"/>
</efx:place_and_route>
<efx:bitstream_generation tool_name="efx_pgm">
<efx:param name="mode" value="active" value_type="e_option"/>
<efx:param name="width" value="1" value_type="e_option"/>
<efx:param name="enable_roms" value="smart" value_type="e_option"/>
<efx:param name="spi_low_power_mode" value="on" value_type="e_bool"/>
<efx:param name="io_weak_pullup" value="on" value_type="e_bool"/>
<efx:param name="oscillator_clock_divider" value="DIV8" value_type="e_option"/>
<efx:param name="bitstream_compression" value="off" value_type="e_bool"/>
<efx:param name="enable_external_master_clock" value="off" value_type="e_bool"/>
<efx:param name="active_capture_clk_edge" value="negedge" value_type="e_option"/>
<efx:param name="jtag_usercode" value="0xFFFFFFFF" value_type="e_string"/>
<efx:param name="release_tri_then_reset" value="on" value_type="e_bool"/>
<efx:param name="cold_boot" value="off" value_type="e_bool"/>
<efx:param name="cascade" value="off" value_type="e_option"/>
<efx:param name="generate_bit" value="on" value_type="e_bool"/>
<efx:param name="generate_bitbin" value="off" value_type="e_bool"/>
<efx:param name="generate_hex" value="on" value_type="e_bool"/>
<efx:param name="generate_hexbin" value="off" value_type="e_bool"/>
<efx:param name="four_byte_addressing" value="off" value_type="e_bool"/>
</efx:bitstream_generation>
<efx:debugger>
<efx:param name="work_dir" value="work_dbg" value_type="e_string"/>
<efx:param name="auto_instantiation" value="off" value_type="e_bool"/>
<efx:param name="profile" value="NONE" value_type="e_string"/>
</efx:debugger>
<efx:security>
<efx:param name="enable_bitstream_encrypt" value="off" value_type="e_bool"/>
<efx:param name="enable_bitstream_auth" value="off" value_type="e_bool"/>
<efx:param name="encryption_key_file" value="NONE" value_type="e_string"/>
<efx:param name="auth_key_file" value="NONE" value_type="e_string"/>
<efx:param name="randomize_iv_value" value="off" value_type="e_bool"/>
<efx:param name="iv_value" value="" value_type="e_string"/>
</efx:security>
</efx:project>

View File

@@ -0,0 +1 @@
create_clock -period 5.0 -name clk [get_ports i_clk]

View File

@@ -0,0 +1,388 @@
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/26.2.2 Chrome/134.0.6998.178 Electron/35.1.2 Safari/537.36" version="26.2.2">
<diagram name="Page-1" id="0d7VDhRL_w2sMOeykiQh">
<mxGraphModel dx="304" dy="205" 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="ga53GqhnnIqpRH2Q9tV7-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="HEWMo3yU8EMGNTpzQ4xJ-1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="360" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-9" value="to poly1305" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-8">
<mxGeometry x="-0.118" relative="1" as="geometry">
<mxPoint y="55" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-1" value="CC_0" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="320" y="280" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="HEWMo3yU8EMGNTpzQ4xJ-2" target="ga53GqhnnIqpRH2Q9tV7-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-2" value="CC_1" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="400" y="280" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="HEWMo3yU8EMGNTpzQ4xJ-4" target="ga53GqhnnIqpRH2Q9tV7-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-4" value="CC_n-1" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="480" y="280" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="HEWMo3yU8EMGNTpzQ4xJ-6" target="HEWMo3yU8EMGNTpzQ4xJ-1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="310" y="220" as="sourcePoint" />
<Array as="points">
<mxPoint x="290" y="220" />
<mxPoint x="290" y="300" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-34" value="valid" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="HEWMo3yU8EMGNTpzQ4xJ-33" vertex="1" connectable="0">
<mxGeometry x="0.2588" relative="1" as="geometry">
<mxPoint x="10" y="-68" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" target="HEWMo3yU8EMGNTpzQ4xJ-6">
<mxGeometry relative="1" as="geometry">
<mxPoint x="440" y="160" as="sourcePoint" />
<Array as="points">
<mxPoint x="440" y="170" />
<mxPoint x="440" y="170" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-17" value="key, nonce" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-16">
<mxGeometry x="-0.9174" relative="1" as="geometry">
<mxPoint y="-12" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-6" value="Metadata Scheduler" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="320" y="200" width="240" height="40" as="geometry" />
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-7" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.042;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.125;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="HEWMo3yU8EMGNTpzQ4xJ-6" target="HEWMo3yU8EMGNTpzQ4xJ-1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="370" y="300" as="sourcePoint" />
<mxPoint x="420" y="250" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-8" value="key" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="HEWMo3yU8EMGNTpzQ4xJ-7" vertex="1" connectable="0">
<mxGeometry x="0.0588" relative="1" as="geometry">
<mxPoint y="-11" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-9" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.042;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.125;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="359.9" y="240" as="sourcePoint" />
<mxPoint x="359.9" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-10" value="nonce" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="HEWMo3yU8EMGNTpzQ4xJ-9" vertex="1" connectable="0">
<mxGeometry x="0.0588" relative="1" as="geometry">
<mxPoint y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-13" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.042;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.125;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="390" y="240" as="sourcePoint" />
<mxPoint x="390" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-14" value="0" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="HEWMo3yU8EMGNTpzQ4xJ-13" vertex="1" connectable="0">
<mxGeometry x="0.0588" relative="1" as="geometry">
<mxPoint y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-55" value="c+0" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="HEWMo3yU8EMGNTpzQ4xJ-13">
<mxGeometry x="-0.0294" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-17" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.042;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.125;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="409.93" y="240" as="sourcePoint" />
<mxPoint x="409.93" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-18" value="key" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="HEWMo3yU8EMGNTpzQ4xJ-17" vertex="1" connectable="0">
<mxGeometry x="0.0588" relative="1" as="geometry">
<mxPoint y="-11" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-19" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.042;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.125;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="439.90000000000003" y="240" as="sourcePoint" />
<mxPoint x="439.90000000000003" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-20" value="nonce" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="HEWMo3yU8EMGNTpzQ4xJ-19" vertex="1" connectable="0">
<mxGeometry x="0.0588" relative="1" as="geometry">
<mxPoint y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-23" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.042;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.125;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="469.93" y="240" as="sourcePoint" />
<mxPoint x="469.93" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-24" value="c+1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="HEWMo3yU8EMGNTpzQ4xJ-23" vertex="1" connectable="0">
<mxGeometry x="0.0588" relative="1" as="geometry">
<mxPoint y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-25" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.042;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.125;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="489.93" y="240" as="sourcePoint" />
<mxPoint x="489.93" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-26" value="key" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="HEWMo3yU8EMGNTpzQ4xJ-25" vertex="1" connectable="0">
<mxGeometry x="0.0588" relative="1" as="geometry">
<mxPoint y="-11" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-27" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.042;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.125;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="519.9" y="240" as="sourcePoint" />
<mxPoint x="519.9" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-28" value="nonce" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="HEWMo3yU8EMGNTpzQ4xJ-27" vertex="1" connectable="0">
<mxGeometry x="0.0588" relative="1" as="geometry">
<mxPoint y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-31" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.042;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.125;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="549.9300000000001" y="240" as="sourcePoint" />
<mxPoint x="549.9300000000001" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="HEWMo3yU8EMGNTpzQ4xJ-32" value="c+n" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="HEWMo3yU8EMGNTpzQ4xJ-31" vertex="1" connectable="0">
<mxGeometry x="0.0588" relative="1" as="geometry">
<mxPoint y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-1" target="ga53GqhnnIqpRH2Q9tV7-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-1" value="keystream sr" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="400" y="360" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" target="ga53GqhnnIqpRH2Q9tV7-10">
<mxGeometry relative="1" as="geometry">
<mxPoint x="620" y="200" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-15" value="data" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-14">
<mxGeometry x="-0.9286" relative="1" as="geometry">
<mxPoint y="-16" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-10" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="600" y="360" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-11" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-10" target="ga53GqhnnIqpRH2Q9tV7-10">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="540" y="380" as="sourcePoint" />
<mxPoint x="590" y="330" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-12" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-10" target="ga53GqhnnIqpRH2Q9tV7-10">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="540" y="380" as="sourcePoint" />
<mxPoint x="590" y="330" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-19" target="ga53GqhnnIqpRH2Q9tV7-25">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-42" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" target="ga53GqhnnIqpRH2Q9tV7-19">
<mxGeometry relative="1" as="geometry">
<mxPoint x="309.96273291925456" y="520" as="sourcePoint" />
<Array as="points">
<mxPoint x="310" y="541" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-45" value="key" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-42">
<mxGeometry x="-0.948" relative="1" as="geometry">
<mxPoint x="-10" y="-11" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-43" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" target="ga53GqhnnIqpRH2Q9tV7-19">
<mxGeometry relative="1" as="geometry">
<mxPoint x="340" y="520" as="sourcePoint" />
<Array as="points">
<mxPoint x="340" y="530" />
<mxPoint x="340" y="530" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-46" value="counter" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-43">
<mxGeometry x="-0.9775" relative="1" as="geometry">
<mxPoint y="-10" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" target="ga53GqhnnIqpRH2Q9tV7-19">
<mxGeometry relative="1" as="geometry">
<mxPoint x="369.96273291925456" y="520" as="sourcePoint" />
<Array as="points">
<mxPoint x="370" y="541" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-48" value="nonce" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-44">
<mxGeometry x="-0.9552" relative="1" as="geometry">
<mxPoint x="10" y="-11" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-53" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-19">
<mxGeometry relative="1" as="geometry">
<mxPoint x="439.9999999999999" y="699.9999999999999" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-54" value="state_out" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-53">
<mxGeometry x="0.7409" y="1" relative="1" as="geometry">
<mxPoint x="-1" y="31" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-19" value="state" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="280" y="560" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-20" value="QR" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="280" y="660" width="30" height="20" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-21" target="ga53GqhnnIqpRH2Q9tV7-19">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="325" y="700" />
<mxPoint x="260" y="700" />
<mxPoint x="260" y="580" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-21" value="QR" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="310" y="660" width="30" height="20" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-22">
<mxGeometry relative="1" as="geometry">
<mxPoint x="280" y="579.9999999999999" as="targetPoint" />
<Array as="points">
<mxPoint x="355" y="700" />
<mxPoint x="260" y="700" />
<mxPoint x="260" y="580" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-22" value="QR" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="340" y="660" width="30" height="20" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-23" value="QR" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="370" y="660" width="30" height="20" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-25" value="even/odd shuffle" style="shape=trapezoid;perimeter=trapezoidPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxGeometry x="280" y="620" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.125;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-25" target="ga53GqhnnIqpRH2Q9tV7-20">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.375;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-25" target="ga53GqhnnIqpRH2Q9tV7-21">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.625;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-25" target="ga53GqhnnIqpRH2Q9tV7-22">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.875;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-25" target="ga53GqhnnIqpRH2Q9tV7-23">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-20" target="ga53GqhnnIqpRH2Q9tV7-19">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="295" y="700" />
<mxPoint x="260" y="700" />
<mxPoint x="260" y="580" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-23" target="ga53GqhnnIqpRH2Q9tV7-19">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="385" y="700" />
<mxPoint x="260" y="700" />
<mxPoint x="260" y="580" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-52" value="state_next" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-35">
<mxGeometry x="-0.0423" relative="1" as="geometry">
<mxPoint x="22" y="10" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-36" target="ga53GqhnnIqpRH2Q9tV7-25">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="270" y="620" />
<mxPoint x="270" y="630" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-36">
<mxGeometry relative="1" as="geometry">
<mxPoint x="220" y="680" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-39" value="valid out" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-38">
<mxGeometry x="-0.399" relative="1" as="geometry">
<mxPoint y="38" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-40" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="219.75000000000006" y="600" as="targetPoint" />
<mxPoint x="219.75" y="560" as="sourcePoint" />
<Array as="points">
<mxPoint x="220" y="581" />
<mxPoint x="220" y="581" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-41" value="valid in" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-40">
<mxGeometry x="-0.8756" relative="1" as="geometry">
<mxPoint y="-12" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-47" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-36" target="ga53GqhnnIqpRH2Q9tV7-19">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="270" y="620" />
<mxPoint x="270" y="590" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-51" value="count" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-47">
<mxGeometry x="0.1001" y="-1" relative="1" as="geometry">
<mxPoint x="19" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-49" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" edge="1" parent="1" source="ga53GqhnnIqpRH2Q9tV7-36" target="ga53GqhnnIqpRH2Q9tV7-19">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="250" y="610" />
<mxPoint x="250" y="570" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-50" value="init" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ga53GqhnnIqpRH2Q9tV7-49">
<mxGeometry x="0.4511" y="1" relative="1" as="geometry">
<mxPoint x="2" y="-9" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="ga53GqhnnIqpRH2Q9tV7-36" value="count" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="200" y="600" width="40" height="40" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -31,3 +31,71 @@ To support AEAD, The first round becomes the key for the Poly1305 block. This
can be done in parallel with the second round, which becomes the cipher, at the can be done in parallel with the second round, which becomes the cipher, at the
expense of double the gates. Otherwise, there would be a delay in between expense of double the gates. Otherwise, there would be a delay in between
packets as this is generated. packets as this is generated.
Okay so we did some timing tests and we can easily do 1 round of ChaCha20 in a
single cycle on a Titanium FPGA at 250MHz (~350-400 MHz)
So then it will take 20 cycles to calculate 512 bits, or 25.6 bits/cycle, or
6.4Gbps. So then we will need 2 of these for 10Gbps.
So in order to use multiple cores, we would calculate 1024 bits in 20 cycles.
Then we would put those bits into a memory or something and start calculating
the next 1024 bits. Those bits would all be used up in 16 cycles, (but the
throughput still checks out). Once they are used, we load the memory with the
new output.
This puts a 20 cycle minimum on small packets since the core is not completely
pipelined. This puts a hard cap at 12.5Mpps. At 42 byte packets, this is
4.2Gbps, and for 64 byte packets is 6.4Gbps. In order to saturate the link, you
would need packets of at least 100 bytes.
This is with the 20 cycle minimum, though in reality it would be more like 25
or 30 with the final addition, scheduling, pipelining etc. Adding more cores
increases the throughput for larger packets, but does nothing for small packets
since the latency is the same. To solve this, we could instantiate the entire
core twice, such that we could handle 2 minimum size packets at the same time.
If we say there is a 30 cycle latency, the worst case is 2.8Gbps. Doubling the
number of cores gives 5.6, quadrupling the number of cores gives 11.2Gbps. This
would of course more than quadrouple the area since we need 4x the cores as
well as the mux and demux between them.
This could be configurable at compile time though. The number of ChaChas per
core would also be configurable, but at the moment I choose 2.
Just counting the quarter rounds, there are 4\*2\*4 = 32 QR modules, or 64 if
we want to 8 QRs per core instead of 4 for timing reasons.
Each QR is 322 XLR, so just the QR would be either 10k or 20k XLR.. That's kind
of a lot. A fully pipelined design would use 322\*20\*4 or 25k XLR. If we can
pass timing using 10k luts than that would be nice. We get a peak throughput
of 50Gbps, its just that the latency kills our packet rate. If we reduce the
latency to 25 cycles and have 2 alternating cores, our packet rate would be
20Mpps, increasing with every cycle we take off. I think that is good. This
would result in 5k XLR which is not so bad.
Okay so starting over now, our clock speed cannot be 250MHz, the best we can do
is 200MHz. If we assume this same 25 cycle latency, thats 4Gbps per block, so
we would need 3 of them to surpass 10Gbps (each is 4096) so now we need 3 blocks
instead of 2.
We are barely going to be able to pass at 180MHz. maybe the fully pipelined
core is a better idea, but we can just fully pipeline a quarter stage, and
generate 512 bits every 4 clock cycles. This would give us a theoretical
throughput of 32Gbps, and we would not have to worry about latency and small
packets slowing us down. Lets experiment with what that would look like.
For our single round its using 1024 adders, which almost sounds like it is
instantiating 8 quarter rounds instead of just 4. Either way, we can say that
a quarter round is 128ff + 128add + 250lut.
So pipelining 20 of these gives 10k luts. Not so bad.
Actualyl its 88k luts... its 512ff * 4 * 20 = 40k ff
Lets just leave it for now even if its overkill. The hardware would support up to
40Gbps, and technically the FPGA has 16 lanes so could do 160Gbps in total, if
we designed a custom board for it (or 120 if we used FMC connectors).

View File

@@ -0,0 +1,6 @@
tests:
- name: "chacha20_block"
toplevel: "chacha20_block"
modules:
- "chacha20_block"
sources: "sources.list"

View File

@@ -0,0 +1,21 @@
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import Timer, RisingEdge, FallingEdge
CLK_PERIOD = 4
class TB:
def __init__(self, dut):
self.dut = dut
cocotb.start_soon(Clock(self.dut.i_clk, CLK_PERIOD, units="ns").start())
@cocotb.test
async def test_sanity(dut):
tb = TB(dut)
await RisingEdge(tb.dut.i_clk)
await RisingEdge(tb.dut.i_clk)

View File

@@ -0,0 +1,8 @@
<testsuites name="results">
<testsuite name="all" package="all">
<property name="random_seed" value="1751043171" />
<testcase name="test_sanity" classname="chacha20_block" file="/home/byron/Projects/crypto/ChaCha20_Poly1305_64/sim/chacha20_block.py" lineno="12" time="0.0004475116729736328" sim_time_ns="0.0" ratio_time="0.0">
<failure message="Test failed with RANDOM_SEED=1751043171" />
</testcase>
</testsuite>
</testsuites>

View File

@@ -0,0 +1 @@
../src/sources.list

View File

@@ -0,0 +1,128 @@
module chacha20_block #(
parameter KEY_SIZE = 256,
parameter COUNTER_SIZE = 64,
parameter NONCE_SIZE = 64,
parameter STATE_SIZE = 512,
parameter CONSTANT = 128'h657870616e642033322d62797465206b
)(
input logic i_clk,
input logic i_rst,
input logic [KEY_SIZE-1:0] i_key,
input logic [COUNTER_SIZE-1:0] i_counter,
input logic [NONCE_SIZE-1:0] i_nonce,
input logic i_valid,
output logic o_ready,
output logic [STATE_SIZE-1:0] o_state,
output logic o_valid,
input logic i_ready
);
`define QR(name, i, n, a, b, c, d) \
chacha20_qr u_chacha20_``name ( \
.i_clk (i_clk), \
.i_rst (i_rst), \
\
.i_valid (valid[i][n]), \
.o_ready (), \
.a_i (state[i][a]), \
.b_i (state[i][b]), \
.c_i (state[i][c]), \
.d_i (state[i][d]), \
\
.o_valid (valid[i+1][n]), \
.i_ready (i_ready), \
.a_o (state[i+1][a]), \
.b_o (state[i+1][b]), \
.c_o (state[i+1][c]), \
.d_o (state[i+1][d]) \
)
logic [31:0] state [21][16];
logic [3:0] valid[21];
// logic [3:0] ready[21];
// small fifo for storing the initial state.
// better to store it in a memory than in flops
logic [4:0] initial_state_wptr;
logic [4:0] initial_state_rptr;
logic [511:0] initial_states [20];
logic [511:0] write_initial_state, read_initial_state;
logic [31:0] original_initial_state [16];
always_ff @(posedge i_clk) begin
if (i_rst) begin
initial_state_rptr <= '0;
initial_state_wptr <= '0;
end else begin
if (i_valid) begin
initial_states[initial_state_wptr] <= write_initial_state;
end
if (valid[19][0]) begin
read_initial_state <= initial_states[initial_state_rptr];
end
o_valid <= &valid[20];
for (int i = 0; i < 16; i++) begin
o_state[i*32 +: 32] <= state[20][i] + read_initial_state[i*32 +: 32];
end
end
end
always_comb begin
for (int i = 0; i < 4; i++) begin
state[0][i] = CONSTANT[32*(3-i) +: 32]; // constant is big endian
end
for (int i = 0; i < 8; i++) begin
state[0][i+4] = i_key[32*i +: 32];
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];
for (int i = 0; i < 4; i++) begin
valid[0][i] = i_valid;
end
o_ready = i_ready;
for (int i = 0; i < 16; i++) begin
write_initial_state[i*32 +: 32] = state[0][i];
original_initial_state[i] = read_initial_state[i*32 +: 32];
end
end
generate
for (genvar round = 0; round < 20; round+=2) begin : ROUND_LOOP
`QR(0, round, 0, 0, 4, 8, 12);
`QR(1, round, 1, 1, 5, 9, 13);
`QR(2, round, 2, 2, 6, 10, 14);
`QR(3, round, 3, 3, 7, 11, 15);
`QR(4, round+1, 0, 0, 5, 10, 15);
`QR(5, round+1, 1, 1, 6, 11, 12);
`QR(6, round+1, 2, 2, 7, 8, 13);
`QR(7, round+1, 3, 3, 4, 9, 14);
end
endgenerate
endmodule

View File

@@ -0,0 +1,96 @@
// do an entire round combinationally
`define ROTL(x, n) {x[31-n:0], x[31:32-n]}
module chacha20_qr #(
parameter PIPELINE_STAGES=7
)(
input logic i_clk,
input logic i_rst,
input logic i_valid,
output logic o_ready,
input logic [31:0] a_i, b_i, c_i, d_i,
output logic o_valid,
input logic i_ready,
output logic [31:0] a_o, b_o, c_o, d_o
);
logic [31:0] a_int [7];
logic [31:0] b_int [7];
logic [31:0] c_int [7];
logic [31:0] d_int [7];
logic [6:0] valid_sr;
// There is an output stage which handles isolating backpressure from the rest
// of the design from the core, so we don't need to worry about it here, we can
// have a single signal gate all of this.
assign o_ready = i_ready;
always_ff @(posedge i_clk) begin
if (i_rst) begin
valid_sr <= '0;
end else begin
if (i_ready) begin
// 1. Update A
a_int[0] <= a_i + b_i;
b_int[0] <= b_i;
c_int[0] <= c_i;
d_int[0] <= d_i;
// 2. Update D
a_int[1] <= a_int[0];
b_int[1] <= b_int[0];
c_int[1] <= c_int[0];
d_int[1] <= `ROTL(a_int[0], 16) ^ `ROTL(d_int[0], 16);
// 3. Update C
a_int[2] <= a_int[1];
b_int[2] <= b_int[1];
c_int[2] <= c_int[1] + d_int[1];
d_int[2] <= d_int[1];
// 4. Update B
a_int[3] <= a_int[2];
b_int[3] <= `ROTL(b_int[2], 12) ^ `ROTL(c_int[2], 12);
c_int[3] <= c_int[2];
d_int[3] <= d_int[2];
// 5. Update A
a_int[4] <= a_int[3] + b_int[3];
b_int[4] <= b_int[3];
c_int[4] <= c_int[3];
d_int[4] <= d_int[3];
// 6. Update D
a_int[5] <= a_int[4];
b_int[5] <= b_int[4];
c_int[5] <= c_int[4];
d_int[5] <= `ROTL(a_int[4], 8) ^ `ROTL(d_int[4], 8);
// 7. Update C
a_int[6] <= a_int[5];
b_int[6] <= b_int[5];
c_int[6] <= c_int[5] + d_int[5];
d_int[6] <= d_int[5];
// 8. Update B
a_o <= a_int[6];
b_o <= `ROTL(b_int[6], 7) ^ `ROTL(c_int[6], 7);
c_o <= c_int[6];
d_o <= d_int[6];
// Simultaneously, update valid_sr;
valid_sr <= {valid_sr[5:0], i_valid};
o_valid <= valid_sr[6];
end
end
end
endmodule

View File

@@ -0,0 +1,2 @@
chacha20_qr.sv
chacha20_block.sv

1
constant.txt Normal file
View File

@@ -0,0 +1 @@
expand 32-byte k

11
init_env.sh Normal file
View File

@@ -0,0 +1,11 @@
PYTHON=python3.13
module load verilator
module load efinity/2025.1
$PYTHON -m venv .venv/${HOSTNAME}
source .venv/${HOSTNAME}/bin/activate
pip install -r requirements.txt
export TOP_DIR=$(git rev-parse --show-toplevel)

5
requirements.txt Normal file
View File

@@ -0,0 +1,5 @@
build-fpga
fpga-sim>=0.3.1
peakrdl
cocotb
cocotbext-axi

19
test.log Normal file
View File

@@ -0,0 +1,19 @@
-.--ns INFO gpi ..mbed/gpi_embed.cpp:108 in set_program_name_in_venv Using Python virtual environment interpreter at /home/byron/Projects/crypto/.venv/customer.sttlwax1.pop.starlinkisp.net/bin/python
-.--ns INFO gpi ../gpi/GpiCommon.cpp:101 in gpi_print_registered_impl VPI registered
0.00ns INFO cocotb Running on Verilator version 5.028 2024-08-21
0.00ns INFO cocotb Running tests with cocotb v1.9.2 from /home/byron/Projects/crypto/.venv/customer.sttlwax1.pop.starlinkisp.net/lib/python3.13/site-packages/cocotb
0.00ns INFO cocotb Seeding Python random module with 1751043027
0.00ns INFO cocotb.regression pytest not found, install it to enable better AssertionError messages
0.00ns INFO cocotb.regression Found test chacha20_block.test_sanity
0.00ns INFO cocotb.regression running test_sanity (1/1)
0.00ns ERROR cocotb.scheduler Failing test at simulator request before test run completion: Simulator shut down prematurely
0.00ns ERROR cocotb.regression Test error has lead to simulator shutting us down
0.00ns INFO cocotb.regression **************************************************************************************
** TEST STATUS SIM TIME (ns) REAL TIME (s) RATIO (ns/s) **
**************************************************************************************
** chacha20_block.test_sanity FAIL 0.00 0.00 0.00 **
**************************************************************************************
** TESTS=1 PASS=0 FAIL=1 SKIP=0 0.00 0.00 0.00 **
**************************************************************************************
- :0: Verilog $finish