[Cryptech-Commits] [user/paul/core] 01/01: Group cores by function (hash, cipher, rng, comm, platform).
git at cryptech.is
git at cryptech.is
Wed Mar 4 21:30:27 UTC 2015
This is an automated email from the git hooks/post-receive script.
paul at psgd.org pushed a commit to branch platform
in repository user/paul/core.
commit 35d98f43057004f14a8e1cce795e0d9f4fea3451
Author: Paul Selkirk <paul at psgd.org>
Date: Wed Mar 4 16:10:57 2015 -0500
Group cores by function (hash, cipher, rng, comm, platform).
---
{uart => cipher/aes}/LICENSE | 0
cipher/aes/README.md | 53 +
cipher/aes/src/model/python/aes.py | 1057 +++++++++++++++
cipher/aes/src/model/python/aes_key_gen.py | 567 +++++++++
cipher/aes/src/model/python/rcon.py | 585 +++++++++
cipher/aes/src/rtl/aes.v | 586 +++++++++
cipher/aes/src/rtl/aes_core.v | 344 +++++
cipher/aes/src/rtl/aes_decipher_block.v | 542 ++++++++
cipher/aes/src/rtl/aes_encipher_block.v | 501 ++++++++
cipher/aes/src/rtl/aes_inv_sbox.v | 320 +++++
cipher/aes/src/rtl/aes_key_mem.v | 479 +++++++
cipher/aes/src/rtl/aes_sbox.v | 321 +++++
cipher/aes/src/tb/tb_aes.v | 553 ++++++++
cipher/aes/src/tb/tb_aes_core.v | 469 +++++++
cipher/aes/src/tb/tb_aes_decipher_block.v | 411 ++++++
cipher/aes/src/tb/tb_aes_encipher_block.v | 427 +++++++
cipher/aes/src/tb/tb_aes_key_mem.v | 655 ++++++++++
cipher/aes/toolruns/Makefile | 126 ++
cipher/chacha/LICENSE.txt | 27 +
cipher/chacha/README.md | 49 +
cipher/chacha/src/model/python/chacha.py | 696 ++++++++++
cipher/chacha/src/rtl/chacha.v | 880 +++++++++++++
cipher/chacha/src/rtl/chacha_core.v | 1342 ++++++++++++++++++++
cipher/chacha/src/rtl/chacha_qr.v | 117 ++
cipher/chacha/src/tb/tb_chacha.v | 761 +++++++++++
cipher/chacha/src/tb/tb_chacha_core.v | 689 ++++++++++
cipher/chacha/toolruns/Makefile | 84 ++
{coretest => comm/coretest}/LICENSE | 0
{coretest => comm/coretest}/README.md | 0
{coretest => comm/coretest}/src/rtl/coretest.v | 0
{coretest => comm/coretest}/src/sw/seriedebug.py | 0
{coretest => comm/coretest}/src/tb/tb_coretest.v | 0
{coretest => comm/coretest}/toolruns/Makefile | 0
.../coretest}/toolruns/modelsim/coretest_wave.do | 0
{eim => comm/eim}/src/rtl/cdc_bus_pulse.v | 0
{eim => comm/eim}/src/rtl/eim.v | 0
{eim => comm/eim}/src/rtl/eim_arbiter.v | 0
{eim => comm/eim}/src/rtl/eim_arbiter_cdc.v | 0
{eim => comm/eim}/src/rtl/eim_da_phy.v | 0
{eim => comm/eim}/src/rtl/eim_indicator.v | 0
{eim => comm/eim}/src/rtl/eim_regs.v | 0
{eim => comm/eim}/src/sw/Makefile | 0
{eim => comm/eim}/src/sw/hash_tester_eim.c | 0
{eim => comm/eim}/src/sw/novena-eim.c | 0
{eim => comm/eim}/src/sw/novena-eim.h | 0
{sha512 => comm/i2c}/LICENSE | 0
{i2c => comm/i2c}/README.md | 0
{i2c => comm/i2c}/src/rtl/i2c_core.v | 0
{i2c => comm/i2c}/src/rtl/i2c_regs.v | 0
{i2c => comm/i2c}/src/sw/Makefile | 0
{i2c => comm/i2c}/src/sw/hash_tester_i2c.c | 0
{i2c => comm/uart}/LICENSE | 0
{uart => comm/uart}/README.md | 0
{uart => comm/uart}/src/rtl/uart_core.v | 0
{uart => comm/uart}/src/rtl/uart_regs.v | 0
{uart => comm/uart}/src/sw/seriedebug.py | 0
{uart => comm/uart}/src/tb/tb_uart.v | 0
{uart => comm/uart}/toolruns/Makefile | 0
{sha256 => hash/sha1}/LICENSE.txt | 0
{sha1 => hash/sha1}/README.md | 0
{sha1 => hash/sha1}/src/model/python/sha1.py | 0
{sha1 => hash/sha1}/src/rtl/sha1.v | 0
{sha1 => hash/sha1}/src/rtl/sha1_core.v | 0
{sha1 => hash/sha1}/src/rtl/sha1_w_mem.v | 0
{sha1 => hash/sha1}/src/tb/tb_sha1.v | 0
{sha1 => hash/sha1}/src/tb/tb_sha1_core.v | 0
{sha1 => hash/sha1}/src/tb/tb_sha1_w_mem.v | 0
{sha1 => hash/sha1}/toolruns/Makefile | 0
{sha1 => hash/sha256}/LICENSE.txt | 0
{sha256 => hash/sha256}/README.md | 0
{sha256 => hash/sha256}/src/model/sha256.py | 0
{sha256 => hash/sha256}/src/rtl/sha256.v | 0
{sha256 => hash/sha256}/src/rtl/sha256_core.v | 0
.../sha256}/src/rtl/sha256_k_constants.v | 0
{sha256 => hash/sha256}/src/rtl/sha256_w_mem.v | 0
{sha256 => hash/sha256}/src/rtl/wb_sha256.v | 0
{sha256 => hash/sha256}/src/tb/tb_sha256.v | 0
{sha256 => hash/sha256}/src/tb/tb_sha256_core.v | 0
{sha256 => hash/sha256}/src/tb/tb_sha256_w_mem.v | 0
{sha256 => hash/sha256}/src/tb/tb_wb_sha256.v | 0
{sha256 => hash/sha256}/toolruns/Makefile | 0
{uart => hash/sha512}/LICENSE | 0
{sha512 => hash/sha512}/README.md | 0
{sha512 => hash/sha512}/src/model/python/sha512.py | 0
{sha512 => hash/sha512}/src/rtl/sha512.v | 0
{sha512 => hash/sha512}/src/rtl/sha512_core.v | 0
.../sha512}/src/rtl/sha512_h_constants.v | 0
.../sha512}/src/rtl/sha512_k_constants.v | 0
{sha512 => hash/sha512}/src/rtl/sha512_w_mem.v | 0
{sha512 => hash/sha512}/src/tb/tb_sha512.v | 0
{sha512 => hash/sha512}/src/tb/tb_sha512_core.v | 0
{sha512 => hash/sha512}/toolruns/Makefile | 0
.../core_selector}/src/rtl/cipher_selector.v | 0
.../common/core_selector}/src/rtl/core_selector.v | 0
.../common/core_selector}/src/rtl/hash_selector.v | 0
.../common/core_selector}/src/rtl/rng_selector.v | 0
.../novena/eim}/build/.gitignore | 0
.../novena => platform/novena/eim}/build/Makefile | 0
.../novena => platform/novena/eim}/build/xilinx.mk | 0
.../novena/eim}/build/xilinx.opt | 0
platform/novena/eim/iseconfig/.gitignore | 48 +
.../novena/eim}/iseconfig/novena_reorg_eim.xise | 0
.../novena/eim}/rtl/ipcore/_xmsgs/cg.xmsgs | 0
.../novena/eim}/rtl/ipcore/_xmsgs/pn_parser.xmsgs | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm.asy | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm.gise | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm.ncf | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm.sym | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm.ucf | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm.v | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm.veo | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm.xco | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm.xdc | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm.xise | 0
.../rtl/ipcore/clkmgr_dcm}/clk_wiz_v3_6_readme.txt | 0
.../ipcore/clkmgr_dcm/doc}/clk_wiz_v3_6_readme.txt | 0
.../ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_vinfo.html | 0
.../rtl/ipcore/clkmgr_dcm/doc/pg065_clk_wiz.pdf | Bin
.../clkmgr_dcm/example_design/clkmgr_dcm_exdes.ucf | 0
.../clkmgr_dcm/example_design/clkmgr_dcm_exdes.v | 0
.../clkmgr_dcm/example_design/clkmgr_dcm_exdes.xdc | 0
.../rtl/ipcore/clkmgr_dcm/implement/implement.bat | 0
.../rtl/ipcore/clkmgr_dcm/implement/implement.sh | 0
.../ipcore/clkmgr_dcm/implement/planAhead_ise.bat | 0
.../ipcore/clkmgr_dcm/implement/planAhead_ise.sh | 0
.../ipcore/clkmgr_dcm/implement/planAhead_ise.tcl | 0
.../ipcore/clkmgr_dcm/implement/planAhead_rdn.bat | 0
.../ipcore/clkmgr_dcm/implement/planAhead_rdn.sh | 0
.../ipcore/clkmgr_dcm/implement/planAhead_rdn.tcl | 0
.../eim}/rtl/ipcore/clkmgr_dcm/implement/xst.prj | 0
.../eim}/rtl/ipcore/clkmgr_dcm/implement/xst.scr | 0
.../ipcore/clkmgr_dcm/simulation/clkmgr_dcm_tb.v | 0
.../clkmgr_dcm/simulation/functional/simcmds.tcl | 0
.../simulation/functional/simulate_isim.bat | 0
.../simulation/functional/simulate_isim.sh | 0
.../simulation/functional/simulate_mti.bat | 0
.../simulation/functional/simulate_mti.do | 0
.../simulation/functional/simulate_mti.sh | 0
.../simulation/functional/simulate_ncsim.sh | 0
.../simulation/functional/simulate_vcs.sh | 0
.../simulation/functional/ucli_commands.key | 0
.../simulation/functional/vcs_session.tcl | 0
.../clkmgr_dcm/simulation/functional/wave.do | 0
.../clkmgr_dcm/simulation/functional/wave.sv | 0
.../clkmgr_dcm/simulation/timing/clkmgr_dcm_tb.v | 0
.../clkmgr_dcm/simulation/timing/sdf_cmd_file | 0
.../clkmgr_dcm/simulation/timing/simcmds.tcl | 0
.../clkmgr_dcm/simulation/timing/simulate_isim.sh | 0
.../clkmgr_dcm/simulation/timing/simulate_mti.bat | 0
.../clkmgr_dcm/simulation/timing/simulate_mti.do | 0
.../clkmgr_dcm/simulation/timing/simulate_mti.sh | 0
.../clkmgr_dcm/simulation/timing/simulate_ncsim.sh | 0
.../clkmgr_dcm/simulation/timing/simulate_vcs.sh | 0
.../clkmgr_dcm/simulation/timing/ucli_commands.key | 0
.../clkmgr_dcm/simulation/timing/vcs_session.tcl | 0
.../ipcore/clkmgr_dcm/simulation/timing/wave.do | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm_flist.txt | 0
.../novena/eim}/rtl/ipcore/clkmgr_dcm_xmdf.tcl | 0
.../novena/eim}/rtl/ipcore/coregen.cgp | 0
.../novena/eim}/rtl/ipcore/create_clkmgr_dcm.tcl | 0
.../novena/eim}/rtl/ipcore/edit_clkmgr_dcm.tcl | 0
.../novena/eim}/rtl/novena_clkmgr.v | 0
.../novena/eim}/rtl/novena_eim.v | 0
.../novena/eim}/ucf/novena_eim.ucf | 0
.../novena/i2c}/build/.gitignore | 0
.../novena => platform/novena/i2c}/build/Makefile | 0
.../novena => platform/novena/i2c}/build/xilinx.mk | 0
.../novena/i2c}/build/xilinx.opt | 0
platform/novena/i2c/iseconfig/.gitignore | 48 +
.../novena/i2c}/iseconfig/_xmsgs/pn_parser.xmsgs | 0
.../novena/i2c}/iseconfig/_xmsgs/xst.xmsgs | 0
.../iseconfig/novena_baseline_top.xreport | 0
.../iseconfig/novena_reorg_i2c.projectmgr | 0
.../i2c}/iseconfig/novena_baseline_top.cmd_log | 0
.../novena/i2c}/iseconfig/novena_baseline_top.lso | 0
.../novena/i2c}/iseconfig/novena_baseline_top.prj | 0
.../novena/i2c}/iseconfig/novena_baseline_top.syr | 0
.../novena/i2c}/iseconfig/novena_baseline_top.xst | 0
.../iseconfig/novena_baseline_top_summary.html | 0
.../novena/i2c}/iseconfig/novena_reorg_i2c.gise | 0
.../novena/i2c}/iseconfig/novena_reorg_i2c.xise | 0
.../novena/i2c}/iseconfig/webtalk_pn.xml | 0
.../novena/i2c}/iseconfig/xst/work/work.sdbl | Bin
.../novena/i2c}/iseconfig/xst/work/work.sdbx | Bin
.../novena/i2c}/rtl/novena_i2c.v | 0
.../novena/i2c}/ucf/novena_i2c.ucf | 0
platform/terasic_c5g/.gitignore | 5 +
.../terasic_c5g/c5_pin_model_dump.txt | 0
.../quartus => platform}/terasic_c5g/db/.cmp.kpt | Bin
.../db/coretest_hashes.quiproj.13348.rdr.flock | 0
.../terasic_c5g/db/coretest_hashes.smp_dump.txt | 0
.../terasic_c5g/db/terasic_top.(0).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(0).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(1).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(1).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(10).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(10).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(11).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(11).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(12).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(12).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(13).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(13).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(14).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(14).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(15).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(15).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(16).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(16).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(17).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(17).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(18).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(18).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(19).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(19).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(2).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(2).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(3).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(3).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(4).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(4).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(5).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(5).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(6).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(6).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(7).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(7).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(8).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(8).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.(9).cnf.cdb | Bin
.../terasic_c5g/db/terasic_top.(9).cnf.hdb | Bin
.../terasic_c5g/db/terasic_top.asm.qmsg | 0
.../terasic_c5g/db/terasic_top.asm.rdb | Bin
.../terasic_c5g/db/terasic_top.cbx.xml | 0
.../terasic_c5g/db/terasic_top.cmp.bpm | Bin
.../terasic_c5g/db/terasic_top.cmp.cdb | Bin
.../terasic_c5g/db/terasic_top.cmp.hdb | Bin
.../terasic_c5g/db/terasic_top.cmp.idb | Bin
.../terasic_c5g/db/terasic_top.cmp.logdb | 0
.../terasic_c5g/db/terasic_top.cmp.rdb | Bin
.../terasic_c5g/db/terasic_top.cmp_merge.kpt | Bin
...erasic_top.cyclonev_io_sim_cache.ff_0c_fast.hsd | Bin
...rasic_top.cyclonev_io_sim_cache.ff_85c_fast.hsd | Bin
...erasic_top.cyclonev_io_sim_cache.ii_0c_slow.hsd | Bin
...rasic_top.cyclonev_io_sim_cache.ii_85c_slow.hsd | Bin
.../terasic_c5g/db/terasic_top.db_info | 0
.../terasic_c5g/db/terasic_top.fit.qmsg | 0
.../terasic_c5g/db/terasic_top.hier_info | 0
.../terasic_c5g/db/terasic_top.hif | Bin
.../db/terasic_top.logic_util_heuristic.dat | Bin
.../terasic_c5g/db/terasic_top.lpc.html | 0
.../terasic_c5g/db/terasic_top.lpc.rdb | Bin
.../terasic_c5g/db/terasic_top.lpc.txt | 0
.../terasic_c5g/db/terasic_top.map.ammdb | Bin
.../terasic_c5g/db/terasic_top.map.bpm | Bin
.../terasic_c5g/db/terasic_top.map.cdb | Bin
.../terasic_c5g/db/terasic_top.map.hdb | Bin
.../terasic_c5g/db/terasic_top.map.kpt | Bin
.../terasic_c5g/db/terasic_top.map.qmsg | 0
.../terasic_c5g/db/terasic_top.map.rdb | Bin
.../terasic_c5g/db/terasic_top.map_bb.cdb | Bin
.../terasic_c5g/db/terasic_top.map_bb.hdb | Bin
.../terasic_c5g/db/terasic_top.pre_map.hdb | Bin
.../terasic_c5g/db/terasic_top.pti_db_list.ddb | Bin
...ic_top.rom0_sha256_k_constants_e63d9e28.hdl.mif | 0
.../db/terasic_top.root_partition.map.reg_db.cdb | Bin
.../terasic_c5g/db/terasic_top.routing.rdb | Bin
.../terasic_c5g/db/terasic_top.rtlv.hdb | Bin
.../terasic_c5g/db/terasic_top.rtlv_sg.cdb | Bin
.../terasic_c5g/db/terasic_top.rtlv_sg_swap.cdb | Bin
.../db/terasic_top.sld_design_entry.sci | Bin
.../db/terasic_top.sld_design_entry_dsc.sci | Bin
.../terasic_c5g/db/terasic_top.smart_action.txt | 0
.../terasic_c5g/db/terasic_top.sta.qmsg | 0
.../terasic_c5g/db/terasic_top.sta.rdb | Bin
.../terasic_top.sta_cmp.7_H6_slow_1100mv_85c.tdb | Bin
.../terasic_c5g/db/terasic_top.tis_db_list.ddb | Bin
.../db/terasic_top.tiscmp.fast_1100mv_0c.ddb | Bin
.../db/terasic_top.tiscmp.fast_1100mv_85c.ddb | Bin
.../terasic_top.tiscmp.fastest_slow_1100mv_0c.ddb | Bin
.../terasic_top.tiscmp.fastest_slow_1100mv_85c.ddb | Bin
.../db/terasic_top.tiscmp.slow_1100mv_0c.ddb | Bin
.../db/terasic_top.tiscmp.slow_1100mv_85c.ddb | Bin
.../terasic_c5g/db/terasic_top.vpr.ammdb | Bin
.../terasic_c5g/incremental_db/README | 0
.../compiled_partitions/terasic_top.db_info | 0
.../terasic_top.root_partition.cmp.ammdb | Bin
.../terasic_top.root_partition.cmp.cdb | Bin
.../terasic_top.root_partition.cmp.dfp | Bin
.../terasic_top.root_partition.cmp.hbdb.cdb | Bin
.../terasic_top.root_partition.cmp.hbdb.hdb | Bin
.../terasic_top.root_partition.cmp.hbdb.sig | 0
.../terasic_top.root_partition.cmp.hdb | Bin
.../terasic_top.root_partition.cmp.logdb | 0
.../terasic_top.root_partition.cmp.rcfdb | Bin
.../terasic_top.root_partition.map.cdb | Bin
.../terasic_top.root_partition.map.dpi | Bin
.../terasic_top.root_partition.map.hbdb.cdb | Bin
.../terasic_top.root_partition.map.hbdb.hb_info | Bin
.../terasic_top.root_partition.map.hbdb.hdb | Bin
.../terasic_top.root_partition.map.hbdb.sig | 0
.../terasic_top.root_partition.map.hdb | Bin
.../terasic_top.root_partition.map.kpt | Bin
.../compiled_partitions/terasic_top.rrp.hdb | Bin
.../compiled_partitions/terasic_top.rrs.cdb | Bin
.../terasic_c5g/output_files/terasic_top.asm.rpt | 0
.../terasic_c5g/output_files/terasic_top.done | 0
.../terasic_c5g/output_files/terasic_top.fit.rpt | 0
.../terasic_c5g/output_files/terasic_top.fit.smsg | 0
.../output_files/terasic_top.fit.summary | 0
.../terasic_c5g/output_files/terasic_top.flow.rpt | 0
.../terasic_c5g/output_files/terasic_top.jdi | 0
.../terasic_c5g/output_files/terasic_top.map.rpt | 0
.../terasic_c5g/output_files/terasic_top.map.smsg | 0
.../output_files/terasic_top.map.summary | 0
.../terasic_c5g/output_files/terasic_top.pin | 0
.../terasic_c5g/output_files/terasic_top.sof | Bin
.../terasic_c5g/output_files/terasic_top.sta.rpt | 0
.../output_files/terasic_top.sta.summary | 0
.../terasic_c5g/terasic_top.qpf | 0
.../terasic_c5g/terasic_top.qsf | 0
platform/terasic_c5g/terasic_top.sdc | 40 +
.../quartus => platform}/terasic_c5g/terasic_top.v | 0
rng/rosc_entropy/LICENSE.txt | 27 +
rng/rosc_entropy/README.md | 4 +
rng/rosc_entropy/src/rtl/rosc.v | 107 ++
rng/rosc_entropy/src/rtl/rosc_entropy.v | 311 +++++
rng/rosc_entropy/src/rtl/rosc_entropy_core.v | 301 +++++
rng/trng/LICENSE.txt | 27 +
rng/trng/README.md | 175 +++
rng/trng/src/rtl/trng.v | 614 +++++++++
rng/trng/src/rtl/trng_csprng.v | 673 ++++++++++
rng/trng/src/rtl/trng_csprng_fifo.v | 507 ++++++++
rng/trng/src/rtl/trng_mixer.v | 1125 ++++++++++++++++
.../trng/src/tb/fake_modules/pseudo_entropy.v | 67 +-
rng/trng/src/tb/tb_csprng.v | 371 ++++++
rng/trng/src/tb/tb_mixer.v | 374 ++++++
rng/trng/src/tb/tb_trng.v | 377 ++++++
rng/trng/toolruns/Makefile | 103 ++
.../toolruns/quartus/terasic_de0_nano/trng.qpf | 30 +
.../toolruns/quartus/terasic_de0_nano/trng.qsf | 90 ++
.../toolruns/quartus/terasic_de0_nano/trng.sdc | 40 +
.../toolruns/quartus/terasic_de0_nano/trng.sof | Bin 0 -> 703935 bytes
rng/vndecorrelator/LICENSE.txt | 27 +
rng/vndecorrelator/README.md | 20 +
rng/vndecorrelator/src/rtl/vndecorrelator.v | 164 +++
rng/vndecorrelator/src/tb/tb_vndecorrelator.v | 277 ++++
rng/vndecorrelator/toolruns/Makefile | 69 +
348 files changed, 18630 insertions(+), 32 deletions(-)
diff --git a/uart/LICENSE b/cipher/aes/LICENSE
similarity index 100%
copy from uart/LICENSE
copy to cipher/aes/LICENSE
diff --git a/cipher/aes/README.md b/cipher/aes/README.md
new file mode 100644
index 0000000..f8a04fc
--- /dev/null
+++ b/cipher/aes/README.md
@@ -0,0 +1,53 @@
+aes
+======
+
+Verilog implementation of the symmetric block cipher AES (Advanced
+Encryption Standard) as specified in the NIST document [FIPS 197](http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf).
+
+
+## Introduction ##
+
+This implementation supports 128 and 256 bit keys. The
+implementation is iterative and process one 128 block at a time. Blocks
+are processed on a word level with 4 S-boxes in the data path. The
+S-boxes for encryption are shared with the key expansion and the core
+can thus not do key update in parallel with block processing.
+
+The encipher and decipher block processing datapaths are separated and
+basically self contained given access to a set of round keys and a
+block. This makes it possible to hard wire either encipher or decipher
+and allow the build tools to optimize away the other functionality which
+will reduce the size to about 50%. For cipher modes such as CTR, GCM
+decryption in the AES core will never be used and thus the decipher
+block processing can be removed.
+
+This is a fairly compact implementation. Further reduction could be
+achived by just having a single S-box. Similarly the performane can be
+increased by having 8 or even 16 S-boxes which would reduce the number
+of cycles to two cycles for each round.
+
+
+## Implementation results ##
+The core has been implemented in Altera and Xilinx FPGA devices.
+
+### Altera Cyclone IV GX ###
+- 7497 LEs
+- 2994 Regs
+- 96 MHz fmax
+- 5 cycles/round
+
+This means that we can do just about 2 Mblocks/s or 256 Mbps
+performance.
+
+Removing the decipher module yields:
+- 5497 LEs
+- 2855 Regs
+- 106 MHz fmax
+- 5 cycles/round
+
+
+### Xilinx Spartan6LX-3 ###
+- 2576 slices
+- 3000 regs
+- 100 MHz
+- 5 cycles/round
diff --git a/cipher/aes/src/model/python/aes.py b/cipher/aes/src/model/python/aes.py
new file mode 100755
index 0000000..582f2b4
--- /dev/null
+++ b/cipher/aes/src/model/python/aes.py
@@ -0,0 +1,1057 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#=======================================================================
+#
+# aes.py
+# ------
+# Simple, pure Python, word based model of the AES cipher with
+# support for 128 and 256 bit keys.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2014, SUNET
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#=======================================================================
+
+#-------------------------------------------------------------------
+# Python module imports.
+#-------------------------------------------------------------------
+import sys
+
+
+#-------------------------------------------------------------------
+# Constants.
+#-------------------------------------------------------------------
+VERBOSE = True
+DUMP_VARS = True
+
+AES_128_ROUNDS = 10
+AES_256_ROUNDS = 14
+
+
+sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]
+
+
+inv_sbox = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
+ 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
+ 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
+ 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
+ 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
+ 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
+ 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
+ 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
+ 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
+ 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
+ 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
+ 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
+ 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
+ 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
+ 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
+ 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]
+
+
+#-------------------------------------------------------------------
+# print_bytekeys()
+#
+# Print a set of round keys given as an array of bytes.
+#-------------------------------------------------------------------
+def print_bytekeys(keys):
+ i = 0
+ print("Number of round keys: %d" % (int(len(keys) / 16)))
+ while i < (len(keys) - 1):
+ for j in range(16):
+ print("0x%02x " % keys[i + j], end="")
+ print("")
+ i += 16
+
+#-------------------------------------------------------------------
+# print_block()
+#
+# Print the given block as four 32 bit words.
+#-------------------------------------------------------------------
+def print_block(block):
+ (w0, w1, w2, w3) = block
+ print("0x%08x, 0x%08x, 0x%08x, 0x%08x" % (w0, w1, w2, w3))
+
+
+#-------------------------------------------------------------------
+# print_key()
+#
+# Print the given key as on or two sets of four 32 bit words.
+#-------------------------------------------------------------------
+def print_key(key):
+ if len(key) == 8:
+ (k0, k1, k2, k3, k4, k5, k6, k7) = key
+ print_block((k0, k1, k2, k3))
+ print_block((k4, k5, k6, k7))
+ else:
+ print_block(key)
+
+
+#-------------------------------------------------------------------
+# b2w()
+#
+# Create a word from the given bytes.
+#-------------------------------------------------------------------
+def b2w(b0, b1, b2, b3):
+ return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3
+
+
+#-------------------------------------------------------------------
+# w2b()
+#
+# Extracts the bytes in a word.
+#-------------------------------------------------------------------
+def w2b(w):
+ b0 = w >> 24
+ b1 = w >> 16 & 0xff
+ b2 = w >> 8 & 0xff
+ b3 = w & 0xff
+
+ return (b0, b1, b2, b3)
+
+
+#-------------------------------------------------------------------
+# gm2()
+#
+# The specific Galois Multiplication by two for a given byte.
+#-------------------------------------------------------------------
+def gm2(b):
+ return ((b << 1) ^ (0x1b & ((b >> 7) * 0xff))) & 0xff
+
+
+#-------------------------------------------------------------------
+# gm3()
+#
+# The specific Galois Multiplication by three for a given byte.
+#-------------------------------------------------------------------
+def gm3(b):
+ return gm2(b) ^ b
+
+
+#-------------------------------------------------------------------
+# gm4()
+#
+# The specific Galois Multiplication by four for a given byte.
+#-------------------------------------------------------------------
+def gm4(b):
+ return gm2(gm2(b))
+
+
+#-------------------------------------------------------------------
+# gm8()
+#
+# The specific Galois Multiplication by eight for a given byte.
+#-------------------------------------------------------------------
+def gm8(b):
+ return gm2(gm4(b))
+
+
+#-------------------------------------------------------------------
+# gm09()
+#
+# The specific Galois Multiplication by nine for a given byte.
+#-------------------------------------------------------------------
+def gm09(b):
+ return gm8(b) ^ b
+
+
+#-------------------------------------------------------------------
+# gm11()
+#
+# The specific Galois Multiplication by 11 for a given byte.
+#-------------------------------------------------------------------
+def gm11(b):
+ return gm8(b) ^ gm2(b) ^ b
+
+
+#-------------------------------------------------------------------
+# gm13()
+#
+# The specific Galois Multiplication by 13 for a given byte.
+#-------------------------------------------------------------------
+def gm13(b):
+ return gm8(b) ^ gm4(b) ^ b
+
+
+#-------------------------------------------------------------------
+# gm14()
+#
+# The specific Galois Multiplication by 14 for a given byte.
+#-------------------------------------------------------------------
+def gm14(b):
+ return gm8(b) ^ gm4(b) ^ gm2(b)
+
+
+#-------------------------------------------------------------------
+# substw()
+#
+# Returns a 32-bit word in which each of the bytes in the
+# given 32-bit word has been used as lookup into the AES S-box.
+#-------------------------------------------------------------------
+def substw(w):
+ (b0, b1, b2, b3) = w2b(w)
+
+ s0 = sbox[b0]
+ s1 = sbox[b1]
+ s2 = sbox[b2]
+ s3 = sbox[b3]
+
+ res = b2w(s0, s1, s2, s3)
+
+ if VERBOSE:
+ print("Inside substw:")
+ print("b0 = 0x%02x, b1 = 0x%02x, b2 = 0x%02x, b3 = 0x%02x" %
+ (b0, b1, b2, b3))
+ print("s0 = 0x%02x, s1 = 0x%02x, s2 = 0x%02x, s3 = 0x%02x" %
+ (s0, s1, s2, s3))
+ print("res = 0x%08x" % (res))
+
+ return res
+
+
+#-------------------------------------------------------------------
+# inv_substw()
+#
+# Returns a 32-bit word in which each of the bytes in the
+# given 32-bit word has been used as lookup into
+# the inverse AES S-box.
+#-------------------------------------------------------------------
+def inv_substw(w):
+ (b0, b1, b2, b3) = w2b(w)
+
+ s0 = inv_sbox[b0]
+ s1 = inv_sbox[b1]
+ s2 = inv_sbox[b2]
+ s3 = inv_sbox[b3]
+
+ res = b2w(s0, s1, s2, s3)
+
+ if VERBOSE:
+ print("Inside inv_substw:")
+ print("b0 = 0x%02x, b1 = 0x%02x, b2 = 0x%02x, b3 = 0x%02x" %
+ (b0, b1, b2, b3))
+ print("s0 = 0x%02x, s1 = 0x%02x, s2 = 0x%02x, s3 = 0x%02x" %
+ (s0, s1, s2, s3))
+ print("res = 0x%08x" % (res))
+
+ return res
+
+
+#-------------------------------------------------------------------
+# rolx()
+#
+# Rotate the given 32 bit word x bits left.
+#-------------------------------------------------------------------
+def rolx(w, x):
+ return ((w << x) | (w >> (32 - x))) & 0xffffffff
+
+
+#-------------------------------------------------------------------
+# next_128bit_key()
+#
+# Generate the next four key words for aes-128 based on given
+# rcon and previous key words.
+#-------------------------------------------------------------------
+def next_128bit_key(prev_key, rcon):
+ (w0, w1, w2, w3) = prev_key
+
+ rol = rolx(w3, 8)
+ subst = substw(rol)
+ t = subst ^ (rcon << 24)
+
+ k0 = w0 ^ t
+ k1 = w1 ^ w0 ^ t
+ k2 = w2 ^ w1 ^ w0 ^ t
+ k3 = w3 ^ w2 ^ w1 ^ w0 ^ t
+
+ if VERBOSE:
+ print("Inside next 128bit key:")
+ print("w0 = 0x%08x, w1 = 0x%08x, w2 = 0x%08x, w3 = 0x%08x" %
+ (w0, w1, w2, w3))
+ print("rol = 0x%08x, subst = 0x%08x, rcon = 0x%02x, t = 0x%08x" %
+ (rol, subst, rcon, t))
+ print("k0 = 0x%08x, k1 = 0x%08x, k2 = 0x%08x, k3 = 0x%08x" %
+ (k0, k1, k2, k3))
+
+ return (k0, k1, k2, k3)
+
+
+#-------------------------------------------------------------------
+# key_gen128()
+#
+# Generating the keys for 128 bit keys.
+#-------------------------------------------------------------------
+def key_gen128(key):
+ print("Doing the 128 bit key expansion")
+
+ round_keys = []
+
+ round_keys.append(key)
+
+ for i in range(10):
+ round_keys.append(next_128bit_key(round_keys[i], get_rcon(i + 1)))
+
+ if VERBOSE:
+ print("Input key:")
+ print_block(key)
+ print("")
+
+ print("Generated keys:")
+ for k in round_keys:
+ print_block(k)
+ print("")
+
+ return round_keys
+
+
+#-------------------------------------------------------------------
+# next_256bit_key_a()
+#
+# Generate the next four key words for aes-256 using algorithm A
+# based on given rcon and the previous two keys.
+#-------------------------------------------------------------------
+def next_256it_key_a(key0, key1, rcon):
+ (w0, w1, w2, w3) = key0
+ (w4, w5, w6, w7) = key1
+
+ sw = substw(rolx(w7, 8))
+ rw = (rcon << 24)
+ t = sw ^ rw
+
+ k0 = w0 ^ t
+ k1 = w1 ^ w0 ^ t
+ k2 = w2 ^ w1 ^ w0 ^ t
+ k3 = w3 ^ w2 ^ w1 ^ w0 ^ t
+
+ if (DUMP_VARS):
+ print("next_256bit_key_a:")
+ print("w0 = 0x%08x, w0 = 0x%08x, w0 = 0x%08x, w0 = 0x%08x" % (w0, w1, w2, w3))
+ print("w4 = 0x%08x, w5 = 0x%08x, w6 = 0x%08x, w7 = 0x%08x" % (w4, w5, w6, w7))
+ print("t = 0x%08x, sw = 0x%08x, rw = 0x%08x" % (t, sw, rw))
+ print("k0 = 0x%08x, k0 = 0x%08x, k0 = 0x%08x, k0 = 0x%08x" % (k0, k1, k2, k3))
+ print("")
+
+ return (k0, k1, k2, k3)
+
+
+#-------------------------------------------------------------------
+# next_256bit_key_b()
+#
+# Generate the next four key words for aes-256 using algorithm B
+# based on given previous eight keywords.
+#-------------------------------------------------------------------
+def next_256it_key_b(key0, key1):
+ (w0, w1, w2, w3) = key0
+ (w4, w5, w6, w7) = key1
+
+ t = substw(w7)
+
+ k0 = w0 ^ t
+ k1 = w1 ^ w0 ^ t
+ k2 = w2 ^ w1 ^ w0 ^ t
+ k3 = w3 ^ w2 ^ w1 ^ w0 ^ t
+
+ if (DUMP_VARS):
+ print("next_256bit_key_b:")
+ print("w0 = 0x%08x, w0 = 0x%08x, w0 = 0x%08x, w0 = 0x%08x" % (w0, w1, w2, w3))
+ print("w4 = 0x%08x, w5 = 0x%08x, w6 = 0x%08x, w7 = 0x%08x" % (w4, w5, w6, w7))
+ print("t = 0x%08x" % (t))
+ print("k0 = 0x%08x, k0 = 0x%08x, k0 = 0x%08x, k0 = 0x%08x" % (k0, k1, k2, k3))
+ print("")
+
+ return (k0, k1, k2, k3)
+
+
+#-------------------------------------------------------------------
+# key_gen256()
+#
+# Generating the keys for 256 bit keys.
+#-------------------------------------------------------------------
+def key_gen256(key):
+ round_keys = []
+ (k0, k1, k2, k3, k4, k5, k6, k7) = key
+
+ round_keys.append((k0, k1, k2, k3))
+ round_keys.append((k4, k5, k6, k7))
+
+ j = 1
+ for i in range(0, (AES_256_ROUNDS - 2), 2):
+ k = next_256it_key_a(round_keys[i], round_keys[i + 1], get_rcon(j))
+ round_keys.append(k)
+ k = next_256it_key_b(round_keys[i + 1], round_keys[i + 2])
+ round_keys.append(k)
+ j += 1
+
+ # One final key needs to be generated.
+ k = next_256it_key_a(round_keys[12], round_keys[13], get_rcon(7))
+ round_keys.append(k)
+
+ if VERBOSE:
+ print("Input key:")
+ print_block((k0, k1, k2, k3))
+ print_block((k4, k5, k6, k7))
+ print("")
+
+ print("Generated keys:")
+ for k in round_keys:
+ print_block(k)
+ print("")
+
+ return round_keys
+
+
+#-------------------------------------------------------------------
+# get_rcon()
+#
+# Function implementation of rcon. Calculates rcon for a
+# given round. This could be implemented as an iterator.
+#-------------------------------------------------------------------
+def get_rcon(round):
+ rcon = 0x8d
+
+ for i in range(0, round):
+ rcon = ((rcon << 1) ^ (0x11b & - (rcon >> 7))) & 0xff
+
+ return rcon
+
+
+#-------------------------------------------------------------------
+# addroundkey()
+#
+# AES AddRoundKey block operation.
+# Perform XOR combination of the given block and the given key.
+#-------------------------------------------------------------------
+def addroundkey(key, block):
+ (w0, w1, w2, w3) = block
+ (k0, k1, k2, k3) = key
+
+ res_block = (w0 ^ k0, w1 ^ k1, w2 ^ k2, w3 ^ k3)
+
+ if VERBOSE:
+ print("AddRoundKey key, block in and block out:")
+ print_block(key)
+ print_block(block)
+ print_block(res_block)
+ print("")
+
+ return res_block
+
+
+#-------------------------------------------------------------------
+# mixw()
+#
+# Perform bit mixing of the given words.
+#-------------------------------------------------------------------
+def mixw(w):
+ (b0, b1, b2, b3) = w2b(w)
+
+ mb0 = gm2(b0) ^ gm3(b1) ^ b2 ^ b3
+ mb1 = b0 ^ gm2(b1) ^ gm3(b2) ^ b3
+ mb2 = b0 ^ b1 ^ gm2(b2) ^ gm3(b3)
+ mb3 = gm3(b0) ^ b1 ^ b2 ^ gm2(b3)
+
+ return b2w(mb0, mb1, mb2, mb3)
+
+
+#-------------------------------------------------------------------
+# mixcolumns()
+#
+# AES MixColumns on the given block.
+#-------------------------------------------------------------------
+def mixcolumns(block):
+ (c0, c1, c2, c3) = block
+
+ mc0 = mixw(c0)
+ mc1 = mixw(c1)
+ mc2 = mixw(c2)
+ mc3 = mixw(c3)
+
+ res_block = (mc0, mc1, mc2, mc3)
+
+ if VERBOSE:
+ print("MixColumns block in and block out:")
+ print_block(block)
+ print_block(res_block)
+ print("")
+
+ return res_block
+
+
+#-------------------------------------------------------------------
+# subbytes()
+#
+# AES SubBytes operation on the given block.
+#-------------------------------------------------------------------
+def subbytes(block):
+ (w0, w1, w2, w3) = block
+
+ res_block = (substw(w0), substw(w1), substw(w2), substw(w3))
+
+ if VERBOSE:
+ print("SubBytes block in and block out:")
+ print_block(block)
+ print_block(res_block)
+ print("")
+
+ return res_block
+
+
+#-------------------------------------------------------------------
+# shiftrows()
+#
+# AES ShiftRows block operation.
+#-------------------------------------------------------------------
+def shiftrows(block):
+ (w0, w1, w2, w3) = block
+
+ c0 = w2b(w0)
+ c1 = w2b(w1)
+ c2 = w2b(w2)
+ c3 = w2b(w3)
+
+ ws0 = b2w(c0[0], c1[1], c2[2], c3[3])
+ ws1 = b2w(c1[0], c2[1], c3[2], c0[3])
+ ws2 = b2w(c2[0], c3[1], c0[2], c1[3])
+ ws3 = b2w(c3[0], c0[1], c1[2], c2[3])
+
+ res_block = (ws0, ws1, ws2, ws3)
+
+ if VERBOSE:
+ print("ShiftRows block in and block out:")
+ print_block(block)
+ print_block(res_block)
+ print("")
+
+ return res_block
+
+
+#-------------------------------------------------------------------
+# aes_encipher()
+#
+# Perform AES encipher operation for the given block using the
+# given key length.
+#-------------------------------------------------------------------
+def aes_encipher_block(key, block):
+ tmp_block = block[:]
+
+ # Get round keys based on the given key.
+ if len(key) == 4:
+ round_keys = key_gen128(key)
+ num_rounds = AES_128_ROUNDS
+ else:
+ round_keys = key_gen256(key)
+ num_rounds = AES_256_ROUNDS
+
+ # Init round
+ print(" Initial AddRoundKeys round.")
+ tmp_block4 = addroundkey(round_keys[0], block)
+
+ # Main rounds
+ for i in range(1 , (num_rounds)):
+ print("")
+ print(" Round %02d" % i)
+ print(" ---------")
+
+ tmp_block1 = subbytes(tmp_block4)
+ tmp_block2 = shiftrows(tmp_block1)
+ tmp_block3 = mixcolumns(tmp_block2)
+ tmp_block4 = addroundkey(round_keys[i], tmp_block3)
+
+
+ # Final round
+ print(" Final round.")
+ tmp_block1 = subbytes(tmp_block4)
+ tmp_block2 = shiftrows(tmp_block1)
+ tmp_block3 = addroundkey(round_keys[num_rounds], tmp_block2)
+
+ return tmp_block3
+
+
+#-------------------------------------------------------------------
+# inv_mixw()
+#
+# Perform inverse bit mixing of the given words.
+#-------------------------------------------------------------------
+def inv_mixw(w):
+ (b0, b1, b2, b3) = w2b(w)
+
+ mb0 = gm14(b0) ^ gm11(b1) ^ gm13(b2) ^ gm09(b3)
+ mb1 = gm09(b0) ^ gm14(b1) ^ gm11(b2) ^ gm13(b3)
+ mb2 = gm13(b0) ^ gm09(b1) ^ gm14(b2) ^ gm11(b3)
+ mb3 = gm11(b0) ^ gm13(b1) ^ gm09(b2) ^ gm14(b3)
+
+ return b2w(mb0, mb1, mb2, mb3)
+
+
+#-------------------------------------------------------------------
+# inv_mixcolumns()
+#
+# AES Inverse MixColumns on the given block.
+#-------------------------------------------------------------------
+def inv_mixcolumns(block):
+ (c0, c1, c2, c3) = block
+
+ mc0 = inv_mixw(c0)
+ mc1 = inv_mixw(c1)
+ mc2 = inv_mixw(c2)
+ mc3 = inv_mixw(c3)
+
+ res_block = (mc0, mc1, mc2, mc3)
+
+ if VERBOSE:
+ print("Inverse MixColumns block in and block out:")
+ print_block(block)
+ print_block(res_block)
+ print("")
+
+ return res_block
+
+
+#-------------------------------------------------------------------
+# inv_shiftrows()
+#
+# AES inverse ShiftRows block operation.
+#-------------------------------------------------------------------
+def inv_shiftrows(block):
+ (w0, w1, w2, w3) = block
+
+ c0 = w2b(w0)
+ c1 = w2b(w1)
+ c2 = w2b(w2)
+ c3 = w2b(w3)
+
+ ws0 = b2w(c0[0], c3[1], c2[2], c1[3])
+ ws1 = b2w(c1[0], c0[1], c3[2], c2[3])
+ ws2 = b2w(c2[0], c1[1], c0[2], c3[3])
+ ws3 = b2w(c3[0], c2[1], c1[2], c0[3])
+
+ res_block = (ws0, ws1, ws2, ws3)
+
+ if VERBOSE:
+ print("Inverse ShiftRows block in and block out:")
+ print_block(block)
+ print_block(res_block)
+ print("")
+
+ return res_block
+
+
+#-------------------------------------------------------------------
+# inv_subbytes()
+#
+# AES inverse SubBytes operation on the given block.
+#-------------------------------------------------------------------
+def inv_subbytes(block):
+ (w0, w1, w2, w3) = block
+
+ res_block = (inv_substw(w0), inv_substw(w1), inv_substw(w2), inv_substw(w3))
+
+ if VERBOSE:
+ print("Inverse SubBytes block in and block out:")
+ print_block(block)
+ print_block(res_block)
+ print("")
+
+ return res_block
+
+
+#-------------------------------------------------------------------
+# aes_decipher()
+#
+# Perform AES decipher operation for the given block
+# using the given key length.
+#-------------------------------------------------------------------
+def aes_decipher_block(key, block):
+ tmp_block = block[:]
+
+ # Get round keys based on the given key.
+ if len(key) == 4:
+ round_keys = key_gen128(key)
+ num_rounds = AES_128_ROUNDS
+ else:
+ round_keys = key_gen256(key)
+ num_rounds = AES_256_ROUNDS
+
+ # Initial round
+ print(" Initial, partial round.")
+ tmp_block1 = addroundkey(round_keys[len(round_keys) - 1], tmp_block)
+ tmp_block2 = inv_shiftrows(tmp_block1)
+ tmp_block4 = inv_subbytes(tmp_block2)
+
+ # Main rounds
+ for i in range(1 , (num_rounds)):
+ print("")
+ print(" Round %02d" % i)
+ print(" ---------")
+
+ tmp_block1 = addroundkey(round_keys[(len(round_keys) - i - 1)], tmp_block4)
+ tmp_block2 = inv_mixcolumns(tmp_block1)
+ tmp_block3 = inv_shiftrows(tmp_block2)
+ tmp_block4 = inv_subbytes(tmp_block3)
+
+ # Final round
+ print(" Final AddRoundKeys round.")
+ res_block = addroundkey(round_keys[0], tmp_block4)
+
+ return res_block
+
+
+#-------------------------------------------------------------------
+# test_mixcolumns()
+#
+# Test the mixcolumns and inverse mixcolumns operations using
+# some simple test values.
+#-------------------------------------------------------------------
+def test_mixcolumns():
+ nist_aes128_key = (0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c)
+
+ print("Test of mixcolumns and inverse mixcolumns:")
+ mixresult = mixcolumns(nist_aes128_key)
+ inv_mixresult = inv_mixcolumns(mixresult)
+
+ print("Test of mixw ochi inv_mixw:")
+ testw = 0xdb135345
+ expw = 0x8e4da1bc
+ mixresult = mixw(testw)
+ inv_mixresult = inv_mixw(mixresult)
+ print("Testword: 0x%08x" % testw)
+ print("expexted: 0x%08x" % expw)
+ print("mixword: 0x%08x" % mixresult)
+ print("invmixword: 0x%08x" % inv_mixresult)
+
+
+#-------------------------------------------------------------------
+# test_aes()
+#
+# Test the AES implementation with 128 and 256 bit keys.
+#-------------------------------------------------------------------
+def test_aes():
+ nist_aes128_key = (0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c)
+ nist_aes256_key = (0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781,
+ 0x1f352c07, 0x3b6108d7, 0x2d9810a3, 0x0914dff4)
+
+ nist_plaintext0 = (0x6bc1bee2, 0x2e409f96, 0xe93d7e11, 0x7393172a)
+ nist_plaintext1 = (0xae2d8a57, 0x1e03ac9c, 0x9eb76fac, 0x45af8e51)
+ nist_plaintext2 = (0x30c81c46, 0xa35ce411, 0xe5fbc119, 0x1a0a52ef)
+ nist_plaintext3 = (0xf69f2445, 0xdf4f9b17, 0xad2b417b, 0xe66c3710)
+
+ nist_exp128_0 = (0x3ad77bb4, 0x0d7a3660, 0xa89ecaf3, 0x2466ef97)
+ nist_exp128_1 = (0xf5d3d585, 0x03b9699d, 0xe785895a, 0x96fdbaaf)
+ nist_exp128_2 = (0x43b1cd7f, 0x598ece23, 0x881b00e3, 0xed030688)
+ nist_exp128_3 = (0x7b0c785e, 0x27e8ad3f, 0x82232071, 0x04725dd4)
+
+ nist_exp256_0 = (0xf3eed1bd, 0xb5d2a03c, 0x064b5a7e, 0x3db181f8)
+ nist_exp256_1 = (0x591ccb10, 0xd410ed26, 0xdc5ba74a, 0x31362870)
+ nist_exp256_2 = (0xb6ed21b9, 0x9ca6f4f9, 0xf153e7b1, 0xbeafed1d)
+ nist_exp256_3 = (0x23304b7a, 0x39f9f3ff, 0x067d8d8f, 0x9e24ecc7)
+
+
+ print("Doing block encryption.")
+ enc_result128_0 = aes_encipher_block(nist_aes128_key, nist_plaintext0)
+ enc_result128_1 = aes_encipher_block(nist_aes128_key, nist_plaintext1)
+ enc_result128_2 = aes_encipher_block(nist_aes128_key, nist_plaintext2)
+ enc_result128_3 = aes_encipher_block(nist_aes128_key, nist_plaintext3)
+
+ enc_result256_0 = aes_encipher_block(nist_aes256_key, nist_plaintext0)
+ enc_result256_1 = aes_encipher_block(nist_aes256_key, nist_plaintext1)
+ enc_result256_2 = aes_encipher_block(nist_aes256_key, nist_plaintext2)
+ enc_result256_3 = aes_encipher_block(nist_aes256_key, nist_plaintext3)
+
+ print("Doing block decryption.")
+ dec_result128_0 = aes_decipher_block(nist_aes128_key, nist_exp128_0)
+ dec_result128_1 = aes_decipher_block(nist_aes128_key, nist_exp128_1)
+ dec_result128_2 = aes_decipher_block(nist_aes128_key, nist_exp128_2)
+ dec_result128_3 = aes_decipher_block(nist_aes128_key, nist_exp128_3)
+
+ dec_result256_0 = aes_decipher_block(nist_aes256_key, nist_exp256_0)
+ dec_result256_1 = aes_decipher_block(nist_aes256_key, nist_exp256_1)
+ dec_result256_2 = aes_decipher_block(nist_aes256_key, nist_exp256_2)
+ dec_result256_3 = aes_decipher_block(nist_aes256_key, nist_exp256_3)
+
+
+ if VERBOSE:
+ print(" AES Encipher tests")
+ print(" ==================")
+
+ print("Test 0 for AES-128.")
+ print("Key:")
+ print_key(nist_aes128_key)
+ print("Block in:")
+ print_block(nist_plaintext0)
+ print("Expected block out:")
+ print_block(nist_exp128_0)
+ print("Got block out:")
+ print_block(enc_result128_0)
+ print("")
+
+ print("Test 1 for AES-128.")
+ print("Key:")
+ print_key(nist_aes128_key)
+ print("Block in:")
+ print_block(nist_plaintext1)
+ print("Expected block out:")
+ print_block(nist_exp128_1)
+ print("Got block out:")
+ print_block(enc_result128_1)
+ print("")
+
+ print("Test 2 for AES-128.")
+ print("Key:")
+ print_key(nist_aes128_key)
+ print("Block in:")
+ print_block(nist_plaintext2)
+ print("Expected block out:")
+ print_block(nist_exp128_2)
+ print("Got block out:")
+ print_block(enc_result128_2)
+ print("")
+
+ print("Test 3 for AES-128.")
+ print("Key:")
+ print_key(nist_aes128_key)
+ print("Block in:")
+ print_block(nist_plaintext3)
+ print("Expected block out:")
+ print_block(nist_exp128_3)
+ print("Got block out:")
+ print_block(enc_result128_3)
+ print("")
+
+
+ print("Test 0 for AES-256.")
+ print("Key:")
+ print_key(nist_aes256_key)
+ print("Block in:")
+ print_block(nist_plaintext0)
+ print("Expected block out:")
+ print_block(nist_exp256_0)
+ print("Got block out:")
+ print_block(enc_result256_0)
+ print("")
+
+ print("Test 1 for AES-256.")
+ print("Key:")
+ print_key(nist_aes256_key)
+ print("Block in:")
+ print_block(nist_plaintext1)
+ print("Expected block out:")
+ print_block(nist_exp256_1)
+ print("Got block out:")
+ print_block(enc_result256_1)
+ print("")
+
+ print("Test 2 for AES-256.")
+ print("Key:")
+ print_key(nist_aes256_key)
+ print("Block in:")
+ print_block(nist_plaintext2)
+ print("Expected block out:")
+ print_block(nist_exp256_2)
+ print("Got block out:")
+ print_block(enc_result256_2)
+ print("")
+
+ print("Test 3 for AES-256.")
+ print("Key:")
+ print_key(nist_aes256_key)
+ print("Block in:")
+ print_block(nist_plaintext3)
+ print("Expected block out:")
+ print_block(nist_exp256_3)
+ print("Got block out:")
+ print_block(enc_result256_3)
+ print("")
+
+ print("")
+ print(" AES Decipher tests")
+ print(" ==================")
+
+ print("Test 0 for AES-128.")
+ print("Key:")
+ print_key(nist_aes128_key)
+ print("Block in:")
+ print_block(nist_exp128_0)
+ print("Expected block out:")
+ print_block(nist_plaintext0)
+ print("Got block out:")
+ print_block(dec_result128_0)
+ print("")
+
+ print("Test 1 for AES-128.")
+ print("Key:")
+ print_key(nist_aes128_key)
+ print("Block in:")
+ print_block(nist_exp128_1)
+ print("Expected block out:")
+ print_block(nist_plaintext1)
+ print("Got block out:")
+ print_block(dec_result128_1)
+ print("")
+
+ print("Test 2 for AES-128.")
+ print("Key:")
+ print_key(nist_aes128_key)
+ print("Block in:")
+ print_block(nist_exp128_2)
+ print("Expected block out:")
+ print_block(nist_plaintext2)
+ print("Got block out:")
+ print_block(dec_result128_2)
+ print("")
+
+ print("Test 3 for AES-128.")
+ print("Key:")
+ print_key(nist_aes128_key)
+ print("Block in:")
+ print_block(nist_exp128_3)
+ print("Expected block out:")
+ print_block(nist_plaintext3)
+ print("Got block out:")
+ print_block(dec_result128_3)
+ print("")
+
+ print("Test 0 for AES-256.")
+ print("Key:")
+ print_key(nist_aes256_key)
+ print("Block in:")
+ print_block(nist_exp256_0)
+ print("Expected block out:")
+ print_block(nist_plaintext0)
+ print("Got block out:")
+ print_block(dec_result256_0)
+ print("")
+
+ print("Test 1 for AES-256.")
+ print("Key:")
+ print_key(nist_aes256_key)
+ print("Block in:")
+ print_block(nist_exp256_1)
+ print("Expected block out:")
+ print_block(nist_plaintext1)
+ print("Got block out:")
+ print_block(dec_result256_1)
+ print("")
+
+ print("Test 2 for AES-256.")
+ print("Key:")
+ print_key(nist_aes256_key)
+ print("Block in:")
+ print_block(nist_exp256_2)
+ print("Expected block out:")
+ print_block(nist_plaintext2)
+ print("Got block out:")
+ print_block(dec_result256_2)
+ print("")
+
+ print("Test 3 for AES-256.")
+ print("Key:")
+ print_key(nist_aes256_key)
+ print("Block in:")
+ print_block(nist_exp256_3)
+ print("Expected block out:")
+ print_block(nist_plaintext3)
+ print("Got block out:")
+ print_block(dec_result256_3)
+ print("")
+
+
+#-------------------------------------------------------------------
+# main()
+#
+# If executed tests the ChaCha class using known test vectors.
+#-------------------------------------------------------------------
+def main():
+ print("Testing the AES cipher model")
+ print("============================")
+ print
+
+ # test_mixcolumns()
+ test_aes()
+
+
+#-------------------------------------------------------------------
+# __name__
+# Python thingy which allows the file to be run standalone as
+# well as parsed from within a Python interpreter.
+#-------------------------------------------------------------------
+if __name__=="__main__":
+ # Run the main function.
+ sys.exit(main())
+
+#=======================================================================
+# EOF aes_key_gen.py
+#=======================================================================
diff --git a/cipher/aes/src/model/python/aes_key_gen.py b/cipher/aes/src/model/python/aes_key_gen.py
new file mode 100755
index 0000000..54ff617
--- /dev/null
+++ b/cipher/aes/src/model/python/aes_key_gen.py
@@ -0,0 +1,567 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#=======================================================================
+#
+# aes_key_gen.py
+# -------------
+# Simple, pure Python test model of the AES key generation.
+# This one is operating on 32 bit words. The key generation
+# supports 128 and 256 bit keys.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2014, SUNET
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#=======================================================================
+
+#-------------------------------------------------------------------
+# Python module imports.
+#-------------------------------------------------------------------
+import sys
+
+
+#-------------------------------------------------------------------
+# Constants.
+#-------------------------------------------------------------------
+VERBOSE = True
+
+DUMP_VARS = True
+
+AES_128_ROUNDS = 10
+AES_256_ROUNDS = 14
+
+
+sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]
+
+
+#-------------------------------------------------------------------
+# substw()
+#
+# Returns a 32-bit word in which each of the bytes in the
+# given 32-bit word has been used as lookup into the AES S-box.
+#-------------------------------------------------------------------
+def substw(w):
+ b0 = w >> 24
+ b1 = w >> 16 & 0xff
+ b2 = w >> 8 & 0xff
+ b3 = w & 0xff
+
+ s0 = sbox[b0]
+ s1 = sbox[b1]
+ s2 = sbox[b2]
+ s3 = sbox[b3]
+
+ res = (s0 << 24) + (s1 << 16) + (s2 << 8) + s3
+
+ if VERBOSE:
+ print("Inside substw:")
+ print("b0 = 0x%02x, b1 = 0x%02x, b2 = 0x%02x, b3 = 0x%02x" %
+ (b0, b1, b2, b3))
+ print("s0 = 0x%02x, s1 = 0x%02x, s2 = 0x%02x, s3 = 0x%02x" %
+ (s0, s1, s2, s3))
+ print("res = 0x%08x" % (res))
+
+ return res
+
+
+#-------------------------------------------------------------------
+# rol8()
+#
+# Rotate the given 32 bit word 8 bits left.
+#-------------------------------------------------------------------
+def rol8(w):
+ return ((w << 8) | (w >> 24)) & 0xffffffff
+
+
+#-------------------------------------------------------------------
+# next_128bit_key()
+#
+# Generate the next four key words for aes-128 based on given
+# rcon and previous key words.
+#-------------------------------------------------------------------
+def next_128bit_key(prev_key, rcon):
+ (w0, w1, w2, w3) = prev_key
+
+ rol = rol8(w3)
+ subst = substw(rol)
+ t = subst ^ (rcon << 24)
+
+ k0 = w0 ^ t
+ k1 = w1 ^ w0 ^ t
+ k2 = w2 ^ w1 ^ w0 ^ t
+ k3 = w3 ^ w2 ^ w1 ^ w0 ^ t
+
+ if VERBOSE:
+ print("Inside next 128bit key:")
+ print("w0 = 0x%08x, w1 = 0x%08x, w2 = 0x%08x, w3 = 0x%08x" %
+ (w0, w1, w2, w3))
+ print("rol = 0x%08x, subst = 0x%08x, rcon = 0x%02x, t = 0x%08x" %
+ (rol, subst, rcon, t))
+ print("k0 = 0x%08x, k1 = 0x%08x, k2 = 0x%08x, k3 = 0x%08x" %
+ (k0, k1, k2, k3))
+
+ return (k0, k1, k2, k3)
+
+
+#-------------------------------------------------------------------
+# key_gen128()
+#
+# Generating the keys for 128 bit keys.
+#-------------------------------------------------------------------
+def key_gen128(key):
+ round_keys = []
+
+ round_keys.append(key)
+
+ round_keys.append(next_128bit_key(round_keys[0], get_rcon(1)))
+ round_keys.append(next_128bit_key(round_keys[1], get_rcon(2)))
+ round_keys.append(next_128bit_key(round_keys[2], get_rcon(3)))
+ round_keys.append(next_128bit_key(round_keys[3], get_rcon(4)))
+ round_keys.append(next_128bit_key(round_keys[4], get_rcon(5)))
+ round_keys.append(next_128bit_key(round_keys[5], get_rcon(6)))
+ round_keys.append(next_128bit_key(round_keys[6], get_rcon(7)))
+ round_keys.append(next_128bit_key(round_keys[7], get_rcon(8)))
+ round_keys.append(next_128bit_key(round_keys[8], get_rcon(9)))
+ round_keys.append(next_128bit_key(round_keys[9], get_rcon(10)))
+
+ return round_keys
+
+
+#-------------------------------------------------------------------
+# next_256bit_key_a()
+#
+# Generate the next four key words for aes-256 using algorithm A
+# based on given rcon and the previous two keys.
+#-------------------------------------------------------------------
+def next_256it_key_a(key0, key1, rcon):
+ (w0, w1, w2, w3) = key0
+ (w4, w5, w6, w7) = key1
+
+ sw = substw(rol8(w7))
+ rw = (rcon << 24)
+ t = sw ^ rw
+
+ k0 = w0 ^ t
+ k1 = w1 ^ w0 ^ t
+ k2 = w2 ^ w1 ^ w0 ^ t
+ k3 = w3 ^ w2 ^ w1 ^ w0 ^ t
+
+ if (DUMP_VARS):
+ print("next_256bit_key_a:")
+ print("w0 = 0x%08x, w0 = 0x%08x, w0 = 0x%08x, w0 = 0x%08x" % (w0, w1, w2, w3))
+ print("w4 = 0x%08x, w5 = 0x%08x, w6 = 0x%08x, w7 = 0x%08x" % (w4, w5, w6, w7))
+ print("t = 0x%08x, sw = 0x%08x, rw = 0x%08x" % (t, sw, rw))
+ print("k0 = 0x%08x, k0 = 0x%08x, k0 = 0x%08x, k0 = 0x%08x" % (k0, k1, k2, k3))
+ print("")
+
+ return (k0, k1, k2, k3)
+
+
+#-------------------------------------------------------------------
+# next_256bit_key_b()
+#
+# Generate the next four key words for aes-256 using algorithm B
+# based on given previous eight keywords.
+#-------------------------------------------------------------------
+def next_256it_key_b(key0, key1):
+ (w0, w1, w2, w3) = key0
+ (w4, w5, w6, w7) = key1
+
+ t = substw(w7)
+
+ k0 = w0 ^ t
+ k1 = w1 ^ w0 ^ t
+ k2 = w2 ^ w1 ^ w0 ^ t
+ k3 = w3 ^ w2 ^ w1 ^ w0 ^ t
+
+ if (DUMP_VARS):
+ print("next_256bit_key_b:")
+ print("w0 = 0x%08x, w0 = 0x%08x, w0 = 0x%08x, w0 = 0x%08x" % (w0, w1, w2, w3))
+ print("w4 = 0x%08x, w5 = 0x%08x, w6 = 0x%08x, w7 = 0x%08x" % (w4, w5, w6, w7))
+ print("t = 0x%08x" % (t))
+ print("k0 = 0x%08x, k0 = 0x%08x, k0 = 0x%08x, k0 = 0x%08x" % (k0, k1, k2, k3))
+ print("")
+
+ return (k0, k1, k2, k3)
+
+
+#-------------------------------------------------------------------
+# key_gen256()
+#
+# Generating the keys for 256 bit keys.
+#-------------------------------------------------------------------
+def key_gen256(key):
+ round_keys = []
+ (k0, k1, k2, k3, k4, k5, k6, k7) = key
+
+ round_keys.append((k0, k1, k2, k3))
+ round_keys.append((k4, k5, k6, k7))
+
+ j = 1
+ for i in range(0, (AES_256_ROUNDS - 2), 2):
+ k = next_256it_key_a(round_keys[i], round_keys[i + 1], get_rcon(j))
+ round_keys.append(k)
+ k = next_256it_key_b(round_keys[i + 1], round_keys[i + 2])
+ round_keys.append(k)
+ j += 1
+
+ # One final key needs to be generated.
+ k = next_256it_key_a(round_keys[12], round_keys[13], get_rcon(7))
+ round_keys.append(k)
+
+ return round_keys
+
+
+#-------------------------------------------------------------------
+# key_gen()
+#
+# The actual key generation.
+#-------------------------------------------------------------------
+def key_gen(key):
+ if VERBOSE:
+ print("Generating keys for AES-%d." % (len(key) * 32))
+
+ if (len(key) * 32) == 128:
+ return key_gen128(key)
+
+ else:
+ return key_gen256(key)
+
+
+#-------------------------------------------------------------------
+# get_rcon()
+#
+# Function implementation of rcon. Calculates rcon for a
+# given round. This could be implemented as an iterator.
+#-------------------------------------------------------------------
+def get_rcon(round):
+ rcon = 0x8d
+
+ for i in range(0, round):
+ rcon = ((rcon << 1) ^ (0x11b & - (rcon >> 7))) & 0xff
+
+ return rcon
+
+
+#-------------------------------------------------------------------
+# print_bytekeys()
+#
+# Print a set of round keys given as an array of bytes.
+#-------------------------------------------------------------------
+def print_bytekeys(keys):
+ i = 0
+ print("Number of round keys: %d" % (int(len(keys) / 16)))
+ while i < (len(keys) - 1):
+ for j in range(16):
+ print("0x%02x " % keys[i + j], end="")
+ print("")
+ i += 16
+
+
+#-------------------------------------------------------------------
+# test_rcon()
+#
+# Test of the rcon function.
+#-------------------------------------------------------------------
+def test_rcon():
+ print("Testing rcon:")
+ for i in range(20):
+ print("rcon %02d = 0x%02x" % (i, get_rcon(i)))
+
+
+#-------------------------------------------------------------------
+# test_key()
+#
+# Generate round keys for a given key and compare them to
+# the given expected round keys.
+#-------------------------------------------------------------------
+def test_key(key, expected):
+ if len(key) not in [4, 8]:
+ print("Error: Key is %d bits, not 128 or 256 bits" % (len(key) * 32))
+ return
+
+ generated = key_gen(key)
+
+ if VERBOSE:
+ for k in generated:
+ (w0, w1, w2, w3) = k
+ print("0x%08x, 0x%08x, 0x%08x, 0x%08x" %
+ (w0, w1, w2, w3))
+
+ if (len(generated) != len(expected)):
+ print("Error: Incorrect number of keys generated.")
+ print("Expected number of round keys: %d" % len(expected))
+ print("Got number of round keys: %d" % len(generated))
+
+ for i in range(len(generated)):
+ exp = expected[i]
+ got = generated[i]
+ if (exp != got):
+ print("Error: Error in round key %d." % i)
+ (e0, e1, e2, e3) = exp
+ (g0, g1, g2, g3) = got
+ print("Expected: 0x%08x 0x%08x 0x%08x 0x%08x"\
+ % (e0, e1, e2, e3))
+ print("Got: 0x%08x 0x%08x 0x%08x 0x%08x"\
+ % (g0, g1, g2, g3))
+ else:
+ print("Correct key generated.")
+
+
+#-------------------------------------------------------------------
+# test_key_expansion()
+#
+# Perform key expansion tests.
+# The test keys and expected round keys are taken from:
+# http://www.samiam.org/key-schedule.html
+#-------------------------------------------------------------------
+def test_key_expansion():
+ # 128 bit keys.
+ key128_1 = (0x00000000, 0x00000000, 0x00000000, 0x00000000)
+ exp128_1 = ((0x00000000, 0x00000000, 0x00000000, 0x00000000),
+ (0x62636363, 0x62636363, 0x62636363, 0x62636363),
+ (0x9b9898c9, 0xf9fbfbaa, 0x9b9898c9, 0xf9fbfbaa),
+ (0x90973450, 0x696ccffa, 0xf2f45733, 0x0b0fac99),
+ (0xee06da7b, 0x876a1581, 0x759e42b2, 0x7e91ee2b),
+ (0x7f2e2b88, 0xf8443e09, 0x8dda7cbb, 0xf34b9290),
+ (0xec614b85, 0x1425758c, 0x99ff0937, 0x6ab49ba7),
+ (0x21751787, 0x3550620b, 0xacaf6b3c, 0xc61bf09b),
+ (0x0ef90333, 0x3ba96138, 0x97060a04, 0x511dfa9f),
+ (0xb1d4d8e2, 0x8a7db9da, 0x1d7bb3de, 0x4c664941),
+ (0xb4ef5bcb, 0x3e92e211, 0x23e951cf, 0x6f8f188e))
+
+ key128_2 = (0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff)
+ exp128_2 = ((0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
+ (0xe8e9e9e9, 0x17161616, 0xe8e9e9e9, 0x17161616),
+ (0xadaeae19, 0xbab8b80f, 0x525151e6, 0x454747f0),
+ (0x090e2277, 0xb3b69a78, 0xe1e7cb9e, 0xa4a08c6e),
+ (0xe16abd3e, 0x52dc2746, 0xb33becd8, 0x179b60b6),
+ (0xe5baf3ce, 0xb766d488, 0x045d3850, 0x13c658e6),
+ (0x71d07db3, 0xc6b6a93b, 0xc2eb916b, 0xd12dc98d),
+ (0xe90d208d, 0x2fbb89b6, 0xed5018dd, 0x3c7dd150),
+ (0x96337366, 0xb988fad0, 0x54d8e20d, 0x68a5335d),
+ (0x8bf03f23, 0x3278c5f3, 0x66a027fe, 0x0e0514a3),
+ (0xd60a3588, 0xe472f07b, 0x82d2d785, 0x8cd7c326))
+
+ key128_3 = (0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)
+ exp128_3 = ((0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f),
+ (0xd6aa74fd, 0xd2af72fa, 0xdaa678f1, 0xd6ab76fe),
+ (0xb692cf0b, 0x643dbdf1, 0xbe9bc500, 0x6830b3fe),
+ (0xb6ff744e, 0xd2c2c9bf, 0x6c590cbf, 0x0469bf41),
+ (0x47f7f7bc, 0x95353e03, 0xf96c32bc, 0xfd058dfd),
+ (0x3caaa3e8, 0xa99f9deb, 0x50f3af57, 0xadf622aa),
+ (0x5e390f7d, 0xf7a69296, 0xa7553dc1, 0x0aa31f6b),
+ (0x14f9701a, 0xe35fe28c, 0x440adf4d, 0x4ea9c026),
+ (0x47438735, 0xa41c65b9, 0xe016baf4, 0xaebf7ad2),
+ (0x549932d1, 0xf0855768, 0x1093ed9c, 0xbe2c974e),
+ (0x13111d7f, 0xe3944a17, 0xf307a78b, 0x4d2b30c5))
+
+ key128_4 = (0x6920e299, 0xa5202a6d, 0x656e6368, 0x69746f2a)
+ exp128_4 = ((0x6920e299, 0xa5202a6d, 0x656e6368, 0x69746f2a),
+ (0xfa880760, 0x5fa82d0d, 0x3ac64e65, 0x53b2214f),
+ (0xcf75838d, 0x90ddae80, 0xaa1be0e5, 0xf9a9c1aa),
+ (0x180d2f14, 0x88d08194, 0x22cb6171, 0xdb62a0db),
+ (0xbaed96ad, 0x323d1739, 0x10f67648, 0xcb94d693),
+ (0x881b4ab2, 0xba265d8b, 0xaad02bc3, 0x6144fd50),
+ (0xb34f195d, 0x096944d6, 0xa3b96f15, 0xc2fd9245),
+ (0xa7007778, 0xae6933ae, 0x0dd05cbb, 0xcf2dcefe),
+ (0xff8bccf2, 0x51e2ff5c, 0x5c32a3e7, 0x931f6d19),
+ (0x24b7182e, 0x7555e772, 0x29674495, 0xba78298c),
+ (0xae127cda, 0xdb479ba8, 0xf220df3d, 0x4858f6b1))
+
+ nist_aes128_key = (0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c)
+ exp_nist128_key = ((0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c),
+ (0xa0fafe17, 0x88542cb1, 0x23a33939, 0x2a6c7605),
+ (0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f),
+ (0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b),
+ (0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00),
+ (0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc),
+ (0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd),
+ (0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f),
+ (0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f),
+ (0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e),
+ (0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6))
+
+
+ # 256 bit keys.
+ key256_1 = (0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x0000000)
+ exp256_1 = ((0x00000000, 0x00000000, 0x00000000, 0x00000000),
+ (0x00000000, 0x00000000, 0x00000000, 0x00000000),
+ (0x62636363, 0x62636363, 0x62636363, 0x62636363),
+ (0xaafbfbfb, 0xaafbfbfb, 0xaafbfbfb, 0xaafbfbfb),
+ (0x6f6c6ccf, 0x0d0f0fac, 0x6f6c6ccf, 0x0d0f0fac),
+ (0x7d8d8d6a, 0xd7767691, 0x7d8d8d6a, 0xd7767691),
+ (0x5354edc1, 0x5e5be26d, 0x31378ea2, 0x3c38810e),
+ (0x968a81c1, 0x41fcf750, 0x3c717a3a, 0xeb070cab),
+ (0x9eaa8f28, 0xc0f16d45, 0xf1c6e3e7, 0xcdfe62e9),
+ (0x2b312bdf, 0x6acddc8f, 0x56bca6b5, 0xbdbbaa1e),
+ (0x6406fd52, 0xa4f79017, 0x553173f0, 0x98cf1119),
+ (0x6dbba90b, 0x07767584, 0x51cad331, 0xec71792f),
+ (0xe7b0e89c, 0x4347788b, 0x16760b7b, 0x8eb91a62),
+ (0x74ed0ba1, 0x739b7e25, 0x2251ad14, 0xce20d43b),
+ (0x10f80a17, 0x53bf729c, 0x45c979e7, 0xcb706385))
+
+
+ key256_2 = (0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff)
+ exp256_2 = ((0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
+ (0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
+ (0xe8e9e9e9, 0x17161616, 0xe8e9e9e9, 0x17161616),
+ (0x0fb8b8b8, 0xf0474747, 0x0fb8b8b8, 0xf0474747),
+ (0x4a494965, 0x5d5f5f73, 0xb5b6b69a, 0xa2a0a08c),
+ (0x355858dc, 0xc51f1f9b, 0xcaa7a723, 0x3ae0e064),
+ (0xafa80ae5, 0xf2f75596, 0x4741e30c, 0xe5e14380),
+ (0xeca04211, 0x29bf5d8a, 0xe318faa9, 0xd9f81acd),
+ (0xe60ab7d0, 0x14fde246, 0x53bc014a, 0xb65d42ca),
+ (0xa2ec6e65, 0x8b5333ef, 0x684bc946, 0xb1b3d38b),
+ (0x9b6c8a18, 0x8f91685e, 0xdc2d6914, 0x6a702bde),
+ (0xa0bd9f78, 0x2beeac97, 0x43a565d1, 0xf216b65a),
+ (0xfc223491, 0x73b35ccf, 0xaf9e35db, 0xc5ee1e05),
+ (0x0695ed13, 0x2d7b4184, 0x6ede2455, 0x9cc8920f),
+ (0x546d424f, 0x27de1e80, 0x88402b5b, 0x4dae355e))
+
+
+ key256_3 = (0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f,
+ 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)
+ exp256_3 = ((0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f),
+ (0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f),
+ (0xa573c29f, 0xa176c498, 0xa97fce93, 0xa572c09c),
+ (0x1651a8cd, 0x0244beda, 0x1a5da4c1, 0x0640bade),
+ (0xae87dff0, 0x0ff11b68, 0xa68ed5fb, 0x03fc1567),
+ (0x6de1f148, 0x6fa54f92, 0x75f8eb53, 0x73b8518d),
+ (0xc656827f, 0xc9a79917, 0x6f294cec, 0x6cd5598b),
+ (0x3de23a75, 0x524775e7, 0x27bf9eb4, 0x5407cf39),
+ (0x0bdc905f, 0xc27b0948, 0xad5245a4, 0xc1871c2f),
+ (0x45f5a660, 0x17b2d387, 0x300d4d33, 0x640a820a),
+ (0x7ccff71c, 0xbeb4fe54, 0x13e6bbf0, 0xd261a7df),
+ (0xf01afafe, 0xe7a82979, 0xd7a5644a, 0xb3afe640),
+ (0x2541fe71, 0x9bf50025, 0x8813bbd5, 0x5a721c0a),
+ (0x4e5a6699, 0xa9f24fe0, 0x7e572baa, 0xcdf8cdea),
+ (0x24fc79cc, 0xbf0979e9, 0x371ac23c, 0x6d68de36))
+
+
+ nist_aes256_key = (0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781,
+ 0x1f352c07, 0x3b6108d7, 0x2d9810a3, 0x0914dff4)
+
+ exp_nist256_key = ((0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781),
+ (0x1f352c07, 0x3b6108d7, 0x2d9810a3, 0x0914dff4),
+ (0x9ba35411, 0x8e6925af, 0xa51a8b5f, 0x2067fcde),
+ (0xa8b09c1a, 0x93d194cd, 0xbe49846e, 0xb75d5b9a),
+ (0xd59aecb8, 0x5bf3c917, 0xfee94248, 0xde8ebe96),
+ (0xb5a9328a, 0x2678a647, 0x98312229, 0x2f6c79b3),
+ (0x812c81ad, 0xdadf48ba, 0x24360af2, 0xfab8b464),
+ (0x98c5bfc9, 0xbebd198e, 0x268c3ba7, 0x09e04214),
+ (0x68007bac, 0xb2df3316, 0x96e939e4, 0x6c518d80),
+ (0xc814e204, 0x76a9fb8a, 0x5025c02d, 0x59c58239),
+ (0xde136967, 0x6ccc5a71, 0xfa256395, 0x9674ee15),
+ (0x5886ca5d, 0x2e2f31d7, 0x7e0af1fa, 0x27cf73c3),
+ (0x749c47ab, 0x18501dda, 0xe2757e4f, 0x7401905a),
+ (0xcafaaae3, 0xe4d59b34, 0x9adf6ace, 0xbd10190d),
+ (0xfe4890d1, 0xe6188d0b, 0x046df344, 0x706c631e))
+
+ print("*** Test of 128 bit keys: ***")
+ test_key(key128_1, exp128_1)
+ test_key(key128_2, exp128_2)
+ test_key(key128_3, exp128_3)
+ test_key(key128_4, exp128_4)
+
+ print("The NIST 128 key:")
+ test_key(nist_aes128_key, exp_nist128_key)
+ print("")
+
+
+ print("*** Test of 256 bit keys: ***")
+ test_key(key256_1, exp256_1)
+ test_key(key256_2, exp256_2)
+ test_key(key256_3, exp256_3)
+
+ print("The NIST 256 key:")
+ test_key(nist_aes256_key, exp_nist256_key)
+ print("")
+
+ print("")
+
+
+#-------------------------------------------------------------------
+# main()
+#
+# If executed tests the ChaCha class using known test vectors.
+#-------------------------------------------------------------------
+def main():
+ print("Testing the AES key generation")
+ print("==============================")
+ print
+
+ test_key_expansion()
+
+
+#-------------------------------------------------------------------
+# __name__
+# Python thingy which allows the file to be run standalone as
+# well as parsed from within a Python interpreter.
+#-------------------------------------------------------------------
+if __name__=="__main__":
+ # Run the main function.
+ sys.exit(main())
+
+#=======================================================================
+# EOF aes_key_gen.py
+#=======================================================================
diff --git a/cipher/aes/src/model/python/rcon.py b/cipher/aes/src/model/python/rcon.py
new file mode 100644
index 0000000..ffc0140
--- /dev/null
+++ b/cipher/aes/src/model/python/rcon.py
@@ -0,0 +1,585 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#=======================================================================
+#
+# aes_key_gen.py
+# -------------
+# Simple, pure Python test model of the AES key generation.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2014, SUNET
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#=======================================================================
+
+#-------------------------------------------------------------------
+# Python module imports.
+#-------------------------------------------------------------------
+import sys
+
+
+#-------------------------------------------------------------------
+# Constants.
+#-------------------------------------------------------------------
+VERBOSE = True
+
+AES_128_ROUNDS = 10
+AES_192_ROUNDS = 12
+AES_256_ROUNDS = 14
+
+
+sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]
+
+
+#-------------------------------------------------------------------
+# substw()
+#
+# Returns a 32-bit word in which each of the bytes in the
+# given 32-bit word has been used as lookup into the AES S-box.
+#-------------------------------------------------------------------
+def substw(w):
+ b0 = w >> 24
+ b1 = w >> 16 & 0xff
+ b2 = w >> 8 & 0xff
+ b3 = w & 0xff
+
+ s0 = sbox[b0]
+ s1 = sbox[b1]
+ s2 = sbox[b2]
+ s3 = sbox[b3]
+
+ return (s0 << 24) + (s1 << 16) + (s2 << 8) + s3
+
+
+#-------------------------------------------------------------------
+# rol8()
+#
+# Rotate the given 32 bit word 8 bits left.
+#-------------------------------------------------------------------
+def rol8(w):
+ return ((w << 8) | (w >> 24)) & 0xffffffff
+
+
+#-------------------------------------------------------------------
+# next_words()
+#
+# Generate the next four key words based on given rcon and
+# previous key words.
+#-------------------------------------------------------------------
+def next_words(prev_words, rcon):
+ (prev_x0, prev_x1, prev_x2, prev_x3) = prev_words
+ tmp = substw(rol8(prev_x3)) ^ (rcon << 24)
+ x0 = prev_x0 ^ tmp
+ x1 = prev_x1 ^ x0
+ x2 = prev_x2 ^ x1
+ x3 = prev_x3 ^ x2
+ return (x0, x1, x2, x3)
+
+
+#-------------------------------------------------------------------
+# key_gen()
+#
+# The actual key generation.
+#-------------------------------------------------------------------
+def key_gen(key):
+ nr_rounds = {4:AES_128_ROUNDS, 6:AES_192_ROUNDS, 8:AES_256_ROUNDS}[len(key)]
+ if VERBOSE:
+ print("Generating keys for AES-%d." % (len(key) * 32))
+
+ round_keys = []
+ if nr_rounds == AES_128_ROUNDS:
+ round_keys.append(key)
+
+ elif nr_rounds == AES_192_ROUNDS:
+ (k0, k1, k2, k3, k4, k5) = key
+ round_keys.append((k0, k1, k2, k3))
+ rcon = ((0x8d << 1) ^ (0x11b & - (0x8d >> 7))) & 0xff
+ (x0, x1, x2, x3) = next_words((k0, k1, k2, k3), rcon)
+ round_keys.append((k4, k5, x2, x3))
+ nr_rounds -= 1
+
+ else:
+ # nr_rounds == AES_192_ROUNDS
+ (k0, k1, k2, k3, k4, k5, k6, k7) = key
+ round_keys.append((k0, k1, k2, k3))
+ round_keys.append((k4, k5, k6, k7))
+ nr_rounds -= 1
+
+ rcon = 0x8d
+
+ for i in range(0, nr_rounds):
+ rcon = ((rcon << 1) ^ (0x11b & - (rcon >> 7))) & 0xff
+ round_keys.append(next_words(round_keys[i], rcon))
+
+ return round_keys
+
+
+#-------------------------------------------------------------------
+# sam_rcon()
+#
+# Function implementation of rcon. Calculates rcon for a
+# given round. This could be implemented as an iterator
+#-------------------------------------------------------------------
+def sam_rcon(round):
+ rcon = 0x8d
+
+ for i in range(0, round):
+ rcon = ((rcon << 1) ^ (0x11b & - (rcon >> 7))) & 0xff
+
+ return rcon
+
+
+#-------------------------------------------------------------------
+# sam_schedule_core()
+#
+# Perform the rotate and SubBytes operation used in all schedules.
+#-------------------------------------------------------------------
+def sam_schedule_core(word, i):
+ # Rotate one byte left
+ word = word[1 : 4] + [word[0]]
+
+ # Perform SubBytes on all bytes in the word.
+ for a in range(4):
+ word[a] = sbox[word[a]]
+
+ # XOR with rcon on the first byte
+ rcon = sam_rcon(i)
+ print("rcon = 0x%02x" % rcon)
+ word[0] = word[0] ^ rcon
+
+ return word
+
+
+#-------------------------------------------------------------------
+# sam_128_bit_key_expansion()
+#
+# Byte based key expansion for 128 bit keys by Sam Trenholme:
+# http://www.samiam.org/key-schedule.html
+#
+# the key here should be supplied as an array of bytes.
+# The array will be updated during processing.
+#-------------------------------------------------------------------
+def sam_128_bit_key_expansion(key):
+ t = [0] * 4
+ expkey = [0x0] * (11 * 16)
+ expkey[0:15] = key[:]
+
+ # c is 16 because the first sub-key is the user-supplied key
+ c = 16;
+ i = 1;
+
+ # We need 11 sets of sixteen bytes each for 128-bit mode
+ # 11 * 16 = 176
+ while (c < 176):
+ # Copy the temporary variable over from the last 4-byte block
+ for a in range(4):
+ t[a] = expkey[a + c - 4]
+
+ # Every four blocks (of four bytes), do a complex calculation */
+ if (c % 16 == 0):
+ t = sam_schedule_core(t, i)
+ i += 1
+
+ # New key is old key xored with the copied and possibly
+ # transformed word.
+ for a in range(4):
+ expkey[c] = expkey[c - 16] ^ t[a]
+ c += 1
+
+ return expkey
+
+
+#-------------------------------------------------------------------
+# sam_192_bit_key_expansion()
+#
+# Byte based key expansion for 192 bit keys by Sam Trenholme:
+# http://www.samiam.org/key-schedule.html
+#-------------------------------------------------------------------
+def sam_192_bit_key_expansion(key):
+ pass
+#void expand_key(unsigned char *key) {
+# unsigned char t[4];
+# unsigned char c = 24;
+# unsigned char i = 1;
+# unsigned char a;
+# while(c < 208) {
+# /* Copy the temporary variable over */
+# for(a = 0; a < 4; a++)
+# t[a] = key[a + c - 4];
+# /* Every six sets, do a complex calculation */
+# if(c % 24 == 0) {
+# schedule_code(t,i);
+# i++;
+# }
+# for(a = 0; a < 4; a++) {
+# key[c] = key[c - 24] ^ t[a];
+# c++;
+# }
+# }
+#}
+
+
+
+
+#-------------------------------------------------------------------
+# sam_256_bit_key_expansion()
+#
+# Byte based key expansion for 256 bit keys by Sam Trenholme:
+# http://www.samiam.org/key-schedule.html
+#-------------------------------------------------------------------
+def sam_256_bit_key_expansion(key):
+ pass
+#void expand_key(unsigned char *key) {
+# unsigned char t[4];
+# unsigned char c = 32;
+# unsigned char i = 1;
+# unsigned char a;
+# while(c < 240) {
+# /* Copy the temporary variable over */
+# for(a = 0; a < 4; a++)
+# t[a] = key[a + c - 4];
+# /* Every eight sets, do a complex calculation */
+# if(c % 32 == 0) {
+# schedule_core(t,i);
+# i++;
+# }
+# /* For 256-bit keys, we add an extra sbox to the
+# * calculation */
+# if(c % 32 == 16) {
+# for(a = 0; a < 4; a++)
+# t[a] = sbox(t[a]);
+# }
+# for(a = 0; a < 4; a++) {
+# key[c] = key[c - 32] ^ t[a];
+# c++;
+# }
+# }
+#}
+
+
+#-------------------------------------------------------------------
+# print_bytekeys()
+#
+# Print a set of round keys given as an array of bytes.
+#-------------------------------------------------------------------
+def print_bytekeys(keys):
+ i = 0
+ print("Number of round keys: %d" % (int(len(keys) / 16)))
+ while i < (len(keys) - 1):
+ for j in range(16):
+ print("0x%02x " % keys[i + j], end="")
+ print("")
+ i += 16
+
+
+#-------------------------------------------------------------------
+# test_key()
+#
+# Generate round keys for a given key and compare them to
+# the given expected round keys.
+#-------------------------------------------------------------------
+def test_key(key, expected):
+ if len(key) not in [4, 6, 8]:
+ print("Error: Key is %d bits, not 128, 192 or 256 bits" % (len(key) * 32))
+ return
+
+ generated = key_gen(key)
+
+ if (len(generated) != len(expected)):
+ print("Error: Incorrect number of keys generated.")
+ print("Expected number of round keys: %d" % len(expected))
+ print("Got number of round keys: %d" % len(generated))
+
+ for i in range(len(generated)):
+ exp = expected[i]
+ got = generated[i]
+ if (exp != got):
+ print("Error: Error in round key %d." % i)
+ (e0, e1, e2, e3) = exp
+ (g0, g1, g2, g3) = got
+ print("Expected: 0x%08x 0x%08x 0x%08x 0x%08x"\
+ % (e0, e1, e2, e3))
+ print("Got: 0x%08x 0x%08x 0x%08x 0x%08x"\
+ % (g0, g1, g2, g3))
+
+
+#-------------------------------------------------------------------
+# test_key_expansion()
+#
+# Perform key expansion tests.
+# The test keys and expected round keys are taken from:
+# http://www.samiam.org/key-schedule.html
+#-------------------------------------------------------------------
+def test_key_expansion():
+ # recon-test
+ print("rcon test:")
+ for i in range(20):
+ print("rcon %02d = 0x%02x" % (i, sam_rcon(i)))
+
+ # Test of sam-implementations.
+ sam_key128_1 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+ my_expkey = sam_128_bit_key_expansion(sam_key128_1)
+ print_bytekeys(my_expkey)
+
+
+ # 128 bit keys.
+# key128_1 = (0x00000000, 0x00000000, 0x00000000, 0x00000000)
+# exp128_1 = ((0x00000000, 0x00000000, 0x00000000, 0x00000000),
+# (0x62636363, 0x62636363, 0x62636363, 0x62636363),
+# (0x9b9898c9, 0xf9fbfbaa, 0x9b9898c9, 0xf9fbfbaa),
+# (0x90973450, 0x696ccffa, 0xf2f45733, 0x0b0fac99),
+# (0xee06da7b, 0x876a1581, 0x759e42b2, 0x7e91ee2b),
+# (0x7f2e2b88, 0xf8443e09, 0x8dda7cbb, 0xf34b9290),
+# (0xec614b85, 0x1425758c, 0x99ff0937, 0x6ab49ba7),
+# (0x21751787, 0x3550620b, 0xacaf6b3c, 0xc61bf09b),
+# (0x0ef90333, 0x3ba96138, 0x97060a04, 0x511dfa9f),
+# (0xb1d4d8e2, 0x8a7db9da, 0x1d7bb3de, 0x4c664941),
+# (0xb4ef5bcb, 0x3e92e211, 0x23e951cf, 0x6f8f188e))
+#
+# key128_2 = (0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff)
+# exp128_2 = ((0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
+# (0xe8e9e9e9, 0x17161616, 0xe8e9e9e9, 0x17161616),
+# (0xadaeae19, 0xbab8b80f, 0x525151e6, 0x454747f0),
+# (0x090e2277, 0xb3b69a78, 0xe1e7cb9e, 0xa4a08c6e),
+# (0xe16abd3e, 0x52dc2746, 0xb33becd8, 0x179b60b6),
+# (0xe5baf3ce, 0xb766d488, 0x045d3850, 0x13c658e6),
+# (0x71d07db3, 0xc6b6a93b, 0xc2eb916b, 0xd12dc98d),
+# (0xe90d208d, 0x2fbb89b6, 0xed5018dd, 0x3c7dd150),
+# (0x96337366, 0xb988fad0, 0x54d8e20d, 0x68a5335d),
+# (0x8bf03f23, 0x3278c5f3, 0x66a027fe, 0x0e0514a3),
+# (0xd60a3588, 0xe472f07b, 0x82d2d785, 0x8cd7c326))
+#
+# key128_3 = (0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)
+# exp128_3 = ((0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f),
+# (0xd6aa74fd, 0xd2af72fa, 0xdaa678f1, 0xd6ab76fe),
+# (0xb692cf0b, 0x643dbdf1, 0xbe9bc500, 0x6830b3fe),
+# (0xb6ff744e, 0xd2c2c9bf, 0x6c590cbf, 0x0469bf41),
+# (0x47f7f7bc, 0x95353e03, 0xf96c32bc, 0xfd058dfd),
+# (0x3caaa3e8, 0xa99f9deb, 0x50f3af57, 0xadf622aa),
+# (0x5e390f7d, 0xf7a69296, 0xa7553dc1, 0x0aa31f6b),
+# (0x14f9701a, 0xe35fe28c, 0x440adf4d, 0x4ea9c026),
+# (0x47438735, 0xa41c65b9, 0xe016baf4, 0xaebf7ad2),
+# (0x549932d1, 0xf0855768, 0x1093ed9c, 0xbe2c974e),
+# (0x13111d7f, 0xe3944a17, 0xf307a78b, 0x4d2b30c5))
+#
+# key128_4 = (0x6920e299, 0xa5202a6d, 0x656e6368, 0x69746f2a)
+# exp128_4 = ((0x6920e299, 0xa5202a6d, 0x656e6368, 0x69746f2a),
+# (0xfa880760, 0x5fa82d0d, 0x3ac64e65, 0x53b2214f),
+# (0xcf75838d, 0x90ddae80, 0xaa1be0e5, 0xf9a9c1aa),
+# (0x180d2f14, 0x88d08194, 0x22cb6171, 0xdb62a0db),
+# (0xbaed96ad, 0x323d1739, 0x10f67648, 0xcb94d693),
+# (0x881b4ab2, 0xba265d8b, 0xaad02bc3, 0x6144fd50),
+# (0xb34f195d, 0x096944d6, 0xa3b96f15, 0xc2fd9245),
+# (0xa7007778, 0xae6933ae, 0x0dd05cbb, 0xcf2dcefe),
+# (0xff8bccf2, 0x51e2ff5c, 0x5c32a3e7, 0x931f6d19),
+# (0x24b7182e, 0x7555e772, 0x29674495, 0xba78298c),
+# (0xae127cda, 0xdb479ba8, 0xf220df3d, 0x4858f6b1))
+#
+# # 192 bit keys.
+# key192_1 = (0x00000000, 0x00000000, 0x00000000,
+# 0x00000000, 0x00000000, 0x00000000)
+# exp192_1 = ((0x00000000, 0x00000000, 0x00000000, 0x00000000),
+# (0x00000000, 0x00000000, 0x62636363, 0x62636363),
+# (0x62636363, 0x62636363, 0x62636363, 0x62636363),
+# (0x9b9898c9, 0xf9fbfbaa, 0x9b9898c9, 0xf9fbfbaa),
+# (0x9b9898c9, 0xf9fbfbaa, 0x90973450, 0x696ccffa),
+# (0xf2f45733, 0x0b0fac99, 0x90973450, 0x696ccffa),
+# (0xc81d19a9, 0xa171d653, 0x53858160, 0x588a2df9),
+# (0xc81d19a9, 0xa171d653, 0x7bebf49b, 0xda9a22c8),
+# (0x891fa3a8, 0xd1958e51, 0x198897f8, 0xb8f941ab),
+# (0xc26896f7, 0x18f2b43f, 0x91ed1797, 0x407899c6),
+# (0x59f00e3e, 0xe1094f95, 0x83ecbc0f, 0x9b1e0830),
+# (0x0af31fa7, 0x4a8b8661, 0x137b885f, 0xf272c7ca),
+# (0x432ac886, 0xd834c0b6, 0xd2c7df11, 0x984c5970))
+#
+# key192_2 = (0xffffffff, 0xffffffff, 0xffffffff,
+# 0xffffffff, 0xffffffff, 0xffffffff)
+# exp192_2 = ((0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
+# (0xffffffff, 0xffffffff, 0xe8e9e9e9, 0x17161616),
+# (0xe8e9e9e9, 0x17161616, 0xe8e9e9e9, 0x17161616),
+# (0xadaeae19, 0xbab8b80f, 0x525151e6, 0x454747f0),
+# (0xadaeae19, 0xbab8b80f, 0xc5c2d8ed, 0x7f7a60e2),
+# (0x2d2b3104, 0x686c76f4, 0xc5c2d8ed, 0x7f7a60e2),
+# (0x1712403f, 0x686820dd, 0x454311d9, 0x2d2f672d),
+# (0xe8edbfc0, 0x9797df22, 0x8f8cd3b7, 0xe7e4f36a),
+# (0xa2a7e2b3, 0x8f88859e, 0x67653a5e, 0xf0f2e57c),
+# (0x2655c33b, 0xc1b13051, 0x6316d2e2, 0xec9e577c),
+# (0x8bfb6d22, 0x7b09885e, 0x67919b1a, 0xa620ab4b),
+# (0xc53679a9, 0x29a82ed5, 0xa25343f7, 0xd95acba9),
+# (0x598e482f, 0xffaee364, 0x3a989acd, 0x1330b418))
+#
+# key192_3 = (0x00010203, 0x04050607, 0x08090a0b,
+# 0x0c0d0e0f, 0x10111213, 0x14151617)
+# exp192_3 = ((0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f),
+# (0x10111213, 0x14151617, 0x5846f2f9, 0x5c43f4fe),
+# (0x544afef5, 0x5847f0fa, 0x4856e2e9, 0x5c43f4fe),
+# (0x40f949b3, 0x1cbabd4d, 0x48f043b8, 0x10b7b342),
+# (0x58e151ab, 0x04a2a555, 0x7effb541, 0x6245080c),
+# (0x2ab54bb4, 0x3a02f8f6, 0x62e3a95d, 0x66410c08),
+# (0xf5018572, 0x97448d7e, 0xbdf1c6ca, 0x87f33e3c),
+# (0xe5109761, 0x83519b69, 0x34157c9e, 0xa351f1e0),
+# (0x1ea0372a, 0x99530916, 0x7c439e77, 0xff12051e),
+# (0xdd7e0e88, 0x7e2fff68, 0x608fc842, 0xf9dcc154),
+# (0x859f5f23, 0x7a8d5a3d, 0xc0c02952, 0xbeefd63a),
+# (0xde601e78, 0x27bcdf2c, 0xa223800f, 0xd8aeda32),
+# (0xa4970a33, 0x1a78dc09, 0xc418c271, 0xe3a41d5d))
+#
+# # 256 bit keys.
+# key256_1 = (0x00000000, 0x00000000, 0x00000000, 0x00000000,
+# 0x00000000, 0x00000000, 0x00000000, 0x0000000)
+# exp256_1 = ((0x00000000, 0x00000000, 0x00000000, 0x00000000),
+# (0x00000000, 0x00000000, 0x00000000, 0x00000000),
+# (0x62636363, 0x62636363, 0x62636363, 0x62636363),
+# (0xaafbfbfb, 0xaafbfbfb, 0xaafbfbfb, 0xaafbfbfb),
+# (0x6f6c6ccf, 0x0d0f0fac, 0x6f6c6ccf, 0x0d0f0fac),
+# (0x7d8d8d6a, 0xd7767691, 0x7d8d8d6a, 0xd7767691),
+# (0x5354edc1, 0x5e5be26d, 0x31378ea2, 0x3c38810e),
+# (0x968a81c1, 0x41fcf750, 0x3c717a3a, 0xeb070cab),
+# (0x9eaa8f28, 0xc0f16d45, 0xf1c6e3e7, 0xcdfe62e9),
+# (0x2b312bdf, 0x6acddc8f, 0x56bca6b5, 0xbdbbaa1e),
+# (0x6406fd52, 0xa4f79017, 0x553173f0, 0x98cf1119),
+# (0x6dbba90b, 0x07767584, 0x51cad331, 0xec71792f),
+# (0xe7b0e89c, 0x4347788b, 0x16760b7b, 0x8eb91a62),
+# (0x74ed0ba1, 0x739b7e25, 0x2251ad14, 0xce20d43b),
+# (0x10f80a17, 0x53bf729c, 0x45c979e7, 0xcb706385))
+#
+# key256_2 = (0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+# 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff)
+# exp256_2 = ((0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
+# (0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
+# (0xe8e9e9e9, 0x17161616, 0xe8e9e9e9, 0x17161616),
+# (0x0fb8b8b8, 0xf0474747, 0x0fb8b8b8, 0xf0474747),
+# (0x4a494965, 0x5d5f5f73, 0xb5b6b69a, 0xa2a0a08c),
+# (0x355858dc, 0xc51f1f9b, 0xcaa7a723, 0x3ae0e064),
+# (0xafa80ae5, 0xf2f75596, 0x4741e30c, 0xe5e14380),
+# (0xeca04211, 0x29bf5d8a, 0xe318faa9, 0xd9f81acd),
+# (0xe60ab7d0, 0x14fde246, 0x53bc014a, 0xb65d42ca),
+# (0xa2ec6e65, 0x8b5333ef, 0x684bc946, 0xb1b3d38b),
+# (0x9b6c8a18, 0x8f91685e, 0xdc2d6914, 0x6a702bde),
+# (0xa0bd9f78, 0x2beeac97, 0x43a565d1, 0xf216b65a),
+# (0xfc223491, 0x73b35ccf, 0xaf9e35db, 0xc5ee1e05),
+# (0x0695ed13, 0x2d7b4184, 0x6ede2455, 0x9cc8920f),
+# (0x546d424f, 0x27de1e80, 0x88402b5b, 0x4dae355e))
+#
+# key256_3 = (0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f,
+# 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)
+# exp256_3 = ((0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f),
+# (0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f),
+# (0xa573c29f, 0xa176c498, 0xa97fce93, 0xa572c09c),
+# (0x1651a8cd, 0x0244beda, 0x1a5da4c1, 0x0640bade),
+# (0xae87dff0, 0x0ff11b68, 0xa68ed5fb, 0x03fc1567),
+# (0x6de1f148, 0x6fa54f92, 0x75f8eb53, 0x73b8518d),
+# (0xc656827f, 0xc9a79917, 0x6f294cec, 0x6cd5598b),
+# (0x3de23a75, 0x524775e7, 0x27bf9eb4, 0x5407cf39),
+# (0x0bdc905f, 0xc27b0948, 0xad5245a4, 0xc1871c2f),
+# (0x45f5a660, 0x17b2d387, 0x300d4d33, 0x640a820a),
+# (0x7ccff71c, 0xbeb4fe54, 0x13e6bbf0, 0xd261a7df),
+# (0xf01afafe, 0xe7a82979, 0xd7a5644a, 0xb3afe640),
+# (0x2541fe71, 0x9bf50025, 0x8813bbd5, 0x5a721c0a),
+# (0x4e5a6699, 0xa9f24fe0, 0x7e572baa, 0xcdf8cdea),
+# (0x24fc79cc, 0xbf0979e9, 0x371ac23c, 0x6d68de36))
+#
+# print("*** Test of 128 bit keys: ***")
+# test_key(key128_1, exp128_1)
+# test_key(key128_2, exp128_2)
+# test_key(key128_3, exp128_3)
+# test_key(key128_4, exp128_4)
+# print("")
+#
+# print("*** Test of 192 bit keys: ***")
+# test_key(key192_1, exp192_1)
+# test_key(key192_2, exp192_2)
+# test_key(key192_3, exp192_3)
+# print("")
+#
+# print("*** Test of 256 bit keys: ***")
+# test_key(key256_1, exp256_1)
+# test_key(key256_2, exp256_2)
+# test_key(key256_3, exp256_3)
+# print("")
+
+
+#-------------------------------------------------------------------
+# main()
+#
+# If executed tests the ChaCha class using known test vectors.
+#-------------------------------------------------------------------
+def main():
+ print("Testing the AES key generation")
+ print("==============================")
+ print
+
+ test_key_expansion()
+
+
+#-------------------------------------------------------------------
+# __name__
+# Python thingy which allows the file to be run standalone as
+# well as parsed from within a Python interpreter.
+#-------------------------------------------------------------------
+if __name__=="__main__":
+ # Run the main function.
+ sys.exit(main())
+
+#=======================================================================
+# EOF aes_key_gen.py
+#=======================================================================
diff --git a/cipher/aes/src/rtl/aes.v b/cipher/aes/src/rtl/aes.v
new file mode 100644
index 0000000..2ead578
--- /dev/null
+++ b/cipher/aes/src/rtl/aes.v
@@ -0,0 +1,586 @@
+//======================================================================
+//
+// aes.v
+// --------
+// Top level wrapper for the AES block cipher core.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module aes(
+ // Clock and reset.
+ input wire clk,
+ input wire reset_n,
+
+ // Control.
+ input wire cs,
+ input wire we,
+
+ // Data ports.
+ input wire [7 : 0] address,
+ input wire [31 : 0] write_data,
+ output wire [31 : 0] read_data,
+ output wire error
+ );
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter ADDR_NAME0 = 8'h00;
+ parameter ADDR_NAME1 = 8'h01;
+ parameter ADDR_VERSION = 8'h02;
+
+ parameter ADDR_CTRL = 8'h08;
+ parameter CTRL_INIT_BIT = 0;
+ parameter CTRL_NEXT_BIT = 1;
+
+ parameter ADDR_CONFIG = 8'h09;
+ parameter CTRL_ENCDEC_BIT = 0;
+ parameter CTRL_KEYLEN_BIT = 1;
+
+ parameter ADDR_STATUS = 8'h0a;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_KEY0 = 8'h10;
+ parameter ADDR_KEY1 = 8'h11;
+ parameter ADDR_KEY2 = 8'h12;
+ parameter ADDR_KEY3 = 8'h13;
+ parameter ADDR_KEY4 = 8'h14;
+ parameter ADDR_KEY5 = 8'h15;
+ parameter ADDR_KEY6 = 8'h16;
+ parameter ADDR_KEY7 = 8'h17;
+
+ parameter ADDR_BLOCK0 = 8'h20;
+ parameter ADDR_BLOCK1 = 8'h21;
+ parameter ADDR_BLOCK2 = 8'h22;
+ parameter ADDR_BLOCK3 = 8'h23;
+
+ parameter ADDR_RESULT0 = 8'h30;
+ parameter ADDR_RESULT1 = 8'h31;
+ parameter ADDR_RESULT2 = 8'h32;
+ parameter ADDR_RESULT3 = 8'h33;
+
+ parameter CORE_NAME0 = 32'h6165732d; // "aes-"
+ parameter CORE_NAME1 = 32'h31323820; // "128 "
+ parameter CORE_VERSION = 32'h302e3530; // "0.50"
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg init_reg;
+ reg init_new;
+ reg init_we;
+ reg init_set;
+
+ reg next_reg;
+ reg next_new;
+ reg next_we;
+ reg next_set;
+
+ reg encdec_reg;
+ reg keylen_reg;
+ reg config_we;
+
+ reg [31 : 0] block0_reg;
+ reg block0_we;
+ reg [31 : 0] block1_reg;
+ reg block1_we;
+ reg [31 : 0] block2_reg;
+ reg block2_we;
+ reg [31 : 0] block3_reg;
+ reg block3_we;
+
+ reg [31 : 0] key0_reg;
+ reg key0_we;
+ reg [31 : 0] key1_reg;
+ reg key1_we;
+ reg [31 : 0] key2_reg;
+ reg key2_we;
+ reg [31 : 0] key3_reg;
+ reg key3_we;
+ reg [31 : 0] key4_reg;
+ reg key4_we;
+ reg [31 : 0] key5_reg;
+ reg key5_we;
+ reg [31 : 0] key6_reg;
+ reg key6_we;
+ reg [31 : 0] key7_reg;
+ reg key7_we;
+
+ reg [127 : 0] result_reg;
+ reg valid_reg;
+ reg ready_reg;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] tmp_read_data;
+ reg tmp_error;
+
+ wire core_encdec;
+ wire core_init;
+ wire core_next;
+ wire core_ready;
+ wire [255 : 0] core_key;
+ wire core_keylen;
+ wire [127 : 0] core_block;
+ wire [127 : 0] core_result;
+ wire core_valid;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign read_data = tmp_read_data;
+ assign error = tmp_error;
+
+ assign core_key = {key0_reg, key1_reg, key2_reg, key3_reg,
+ key4_reg, key5_reg, key6_reg, key7_reg};
+
+ assign core_block = {block0_reg, block1_reg, block2_reg, block3_reg};
+ assign core_init = init_reg;
+ assign core_next = next_reg;
+ assign core_encdec = encdec_reg;
+ assign core_keylen = keylen_reg;
+
+
+ //----------------------------------------------------------------
+ // core instantiation.
+ //----------------------------------------------------------------
+ aes_core core(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .encdec(core_encdec),
+ .init(core_init),
+ .next(core_next),
+ .ready(core_ready),
+
+ .key(core_key),
+ .keylen(core_keylen),
+
+ .block(core_block),
+ .result(core_result),
+ .result_valid(core_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ block0_reg <= 32'h00000000;
+ block1_reg <= 32'h00000000;
+ block2_reg <= 32'h00000000;
+ block3_reg <= 32'h00000000;
+
+ key0_reg <= 32'h00000000;
+ key1_reg <= 32'h00000000;
+ key2_reg <= 32'h00000000;
+ key3_reg <= 32'h00000000;
+ key4_reg <= 32'h00000000;
+ key5_reg <= 32'h00000000;
+ key6_reg <= 32'h00000000;
+ key7_reg <= 32'h00000000;
+
+ init_reg <= 0;
+ next_reg <= 0;
+ encdec_reg <= 0;
+ keylen_reg <= 0;
+
+ result_reg <= 128'h00000000000000000000000000000000;
+ valid_reg <= 0;
+ ready_reg <= 0;
+ end
+ else
+ begin
+ ready_reg <= core_ready;
+ valid_reg <= core_valid;
+ result_reg <= core_result;
+
+ if (init_we)
+ begin
+ init_reg <= init_new;
+ end
+
+ if (next_we)
+ begin
+ next_reg <= next_new;
+ end
+
+ if (config_we)
+ begin
+ encdec_reg <= write_data[CTRL_ENCDEC_BIT];
+ keylen_reg <= write_data[CTRL_KEYLEN_BIT];
+ end
+
+ if (key0_we)
+ begin
+ key0_reg <= write_data;
+ end
+
+ if (key1_we)
+ begin
+ key1_reg <= write_data;
+ end
+
+ if (key2_we)
+ begin
+ key2_reg <= write_data;
+ end
+
+ if (key3_we)
+ begin
+ key3_reg <= write_data;
+ end
+
+ if (key4_we)
+ begin
+ key4_reg <= write_data;
+ end
+
+ if (key5_we)
+ begin
+ key5_reg <= write_data;
+ end
+
+ if (key6_we)
+ begin
+ key6_reg <= write_data;
+ end
+
+ if (key7_we)
+ begin
+ key7_reg <= write_data;
+ end
+
+ if (block0_we)
+ begin
+ block0_reg <= write_data;
+ end
+
+ if (block1_we)
+ begin
+ block1_reg <= write_data;
+ end
+
+ if (block2_we)
+ begin
+ block2_reg <= write_data;
+ end
+
+ if (block3_we)
+ begin
+ block3_reg <= write_data;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // flag_ctrl
+ //
+ // Logic to set and the automatically reset init- and
+ // next flags that has been set.
+ //----------------------------------------------------------------
+ always @*
+ begin : flag_reset
+ init_new = 0;
+ init_we = 0;
+ next_new = 0;
+ next_we = 0;
+
+ if (init_set)
+ begin
+ init_new = 1;
+ init_we = 1;
+ end
+ else if (init_reg)
+ begin
+ init_new = 0;
+ init_we = 1;
+ end
+
+ if (next_set)
+ begin
+ next_new = 1;
+ next_we = 1;
+ end
+ else if (next_reg)
+ begin
+ next_new = 0;
+ next_we = 1;
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // api
+ //
+ // The interface command decoding logic.
+ //----------------------------------------------------------------
+ always @*
+ begin : api
+ init_set = 0;
+ next_set = 0;
+ config_we = 0;
+ key0_we = 0;
+ key1_we = 0;
+ key2_we = 0;
+ key3_we = 0;
+ key4_we = 0;
+ key5_we = 0;
+ key6_we = 0;
+ key7_we = 0;
+ block0_we = 0;
+ block1_we = 0;
+ block2_we = 0;
+ block3_we = 0;
+ tmp_read_data = 32'h00000000;
+ tmp_error = 0;
+
+ if (cs)
+ begin
+ if (we)
+ begin
+ case (address)
+ // Write operations.
+ ADDR_CTRL:
+ begin
+ init_set = write_data[CTRL_INIT_BIT];
+ next_set = write_data[CTRL_NEXT_BIT];
+ end
+
+ ADDR_CONFIG:
+ begin
+ config_we = 1;
+ end
+
+ ADDR_KEY0:
+ begin
+ key0_we = 1;
+ end
+
+ ADDR_KEY1:
+ begin
+ key1_we = 1;
+ end
+
+ ADDR_KEY2:
+ begin
+ key2_we = 1;
+ end
+
+ ADDR_KEY3:
+ begin
+ key3_we = 1;
+ end
+
+ ADDR_KEY4:
+ begin
+ key4_we = 1;
+ end
+
+ ADDR_KEY5:
+ begin
+ key5_we = 1;
+ end
+
+ ADDR_KEY6:
+ begin
+ key6_we = 1;
+ end
+
+ ADDR_KEY7:
+ begin
+ key7_we = 1;
+ end
+
+ ADDR_BLOCK0:
+ begin
+ block0_we = 1;
+ end
+
+ ADDR_BLOCK1:
+ begin
+ block1_we = 1;
+ end
+
+ ADDR_BLOCK2:
+ begin
+ block2_we = 1;
+ end
+
+ ADDR_BLOCK3:
+ begin
+ block3_we = 1;
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end // if (we)
+
+ else
+ begin
+ case (address)
+ // Read operations.
+ ADDR_NAME0:
+ begin
+ tmp_read_data = CORE_NAME0;
+ end
+
+ ADDR_NAME1:
+ begin
+ tmp_read_data = CORE_NAME1;
+ end
+
+ ADDR_VERSION:
+ begin
+ tmp_read_data = CORE_VERSION;
+ end
+
+ ADDR_CTRL:
+ begin
+ tmp_read_data = {28'h0000000, keylen_reg, encdec_reg,
+ next_reg, init_reg};
+ end
+
+ ADDR_STATUS:
+ begin
+ tmp_read_data = {30'h00000000, valid_reg, ready_reg};
+ end
+
+ ADDR_KEY0:
+ begin
+ tmp_read_data = key0_reg;
+ end
+
+ ADDR_KEY1:
+ begin
+ tmp_read_data = key1_reg;
+ end
+
+ ADDR_KEY2:
+ begin
+ tmp_read_data = key2_reg;
+ end
+
+ ADDR_KEY3:
+ begin
+ tmp_read_data = key3_reg;
+ end
+
+ ADDR_KEY4:
+ begin
+ tmp_read_data = key4_reg;
+ end
+
+ ADDR_KEY5:
+ begin
+ tmp_read_data = key5_reg;
+ end
+
+ ADDR_KEY6:
+ begin
+ tmp_read_data = key6_reg;
+ end
+
+ ADDR_KEY7:
+ begin
+ tmp_read_data = key7_reg;
+ end
+
+ ADDR_BLOCK0:
+ begin
+ tmp_read_data = block0_reg;
+ end
+
+ ADDR_BLOCK1:
+ begin
+ tmp_read_data = block1_reg;
+ end
+
+ ADDR_BLOCK2:
+ begin
+ tmp_read_data = block2_reg;
+ end
+
+ ADDR_BLOCK3:
+ begin
+ tmp_read_data = block3_reg;
+ end
+
+ ADDR_RESULT0:
+ begin
+ tmp_read_data = result_reg[127 : 96];
+ end
+
+ ADDR_RESULT1:
+ begin
+ tmp_read_data = result_reg[95 : 64];
+ end
+
+ ADDR_RESULT2:
+ begin
+ tmp_read_data = result_reg[63 : 32];
+ end
+
+ ADDR_RESULT3:
+ begin
+ tmp_read_data = result_reg[31 : 0];
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end
+ end
+ end // addr_decoder
+endmodule // aes
+
+//======================================================================
+// EOF aes.v
+//======================================================================
diff --git a/cipher/aes/src/rtl/aes_core.v b/cipher/aes/src/rtl/aes_core.v
new file mode 100644
index 0000000..c43c943
--- /dev/null
+++ b/cipher/aes/src/rtl/aes_core.v
@@ -0,0 +1,344 @@
+//======================================================================
+//
+// aes.core.v
+// ----------
+// The AES core. This core supports key size of 128, and 256 bits.
+// Most of the functionality is within the submodules.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module aes_core(
+ input wire clk,
+ input wire reset_n,
+
+ input wire encdec,
+ input wire init,
+ input wire next,
+ output wire ready,
+
+ input wire [255 : 0] key,
+ input wire keylen,
+
+ input wire [127 : 0] block,
+ output wire [127 : 0] result,
+ output wire result_valid
+ );
+
+
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter CTRL_IDLE = 2'h0;
+ parameter CTRL_INIT = 2'h1;
+ parameter CTRL_NEXT = 2'h2;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [1 : 0] aes_core_ctrl_reg;
+ reg [1 : 0] aes_core_ctrl_new;
+ reg aes_core_ctrl_we;
+
+ reg result_valid_reg;
+ reg result_valid_new;
+ reg result_valid_we;
+
+ reg ready_reg;
+ reg ready_new;
+ reg ready_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg init_state;
+
+ wire [127 : 0] round_key;
+ wire key_ready;
+
+ reg enc_next;
+ wire [3 : 0] enc_round_nr;
+ wire [127 : 0] enc_new_block;
+ wire enc_ready;
+ wire [31 : 0] enc_sboxw;
+
+ reg dec_next;
+ wire [3 : 0] dec_round_nr;
+ wire [127 : 0] dec_new_block;
+ wire dec_ready;
+
+ reg [127 : 0] muxed_new_block;
+ reg [3 : 0] muxed_round_nr;
+ reg muxed_ready;
+
+ wire [31 : 0] keymem_sboxw;
+
+ reg [31 : 0] muxed_sboxw;
+ wire [31 : 0] new_sboxw;
+
+
+ //----------------------------------------------------------------
+ // Instantiations.
+ //----------------------------------------------------------------
+ aes_encipher_block enc_block(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .next(enc_next),
+
+ .keylen(keylen),
+ .round(enc_round_nr),
+ .round_key(round_key),
+
+ .sboxw(enc_sboxw),
+ .new_sboxw(new_sboxw),
+
+ .block(block),
+ .new_block(enc_new_block),
+ .ready(enc_ready)
+ );
+
+
+ aes_decipher_block dec_block(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .next(dec_next),
+
+ .keylen(keylen),
+ .round(dec_round_nr),
+ .round_key(round_key),
+
+ .block(block),
+ .new_block(dec_new_block),
+ .ready(dec_ready)
+ );
+
+
+ aes_key_mem keymem(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .key(key),
+ .keylen(keylen),
+ .init(init),
+
+ .round(muxed_round_nr),
+ .round_key(round_key),
+ .ready(key_ready),
+
+ .sboxw(keymem_sboxw),
+ .new_sboxw(new_sboxw)
+ );
+
+
+ aes_sbox sbox(.sboxw(muxed_sboxw), .new_sboxw(new_sboxw));
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign ready = ready_reg;
+ assign result = muxed_new_block;
+ assign result_valid = result_valid_reg;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin: reg_update
+ if (!reset_n)
+ begin
+ result_valid_reg <= 1'b0;
+ ready_reg <= 1'b1;
+ aes_core_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ if (result_valid_we)
+ begin
+ result_valid_reg <= result_valid_new;
+ end
+
+ if (ready_we)
+ begin
+ ready_reg <= ready_new;
+ end
+
+ if (aes_core_ctrl_we)
+ begin
+ aes_core_ctrl_reg <= aes_core_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // sbox_mux
+ //
+ // Controls which of the encipher datapath or the key memory
+ // that gets access to the sbox.
+ //----------------------------------------------------------------
+ always @*
+ begin : sbox_mux
+ if (init_state)
+ begin
+ muxed_sboxw = keymem_sboxw;
+ end
+ else
+ begin
+ muxed_sboxw = enc_sboxw;
+ end
+ end // sbox_mux
+
+
+ //----------------------------------------------------------------
+ // encdex_mux
+ //
+ // Controls which of the datapaths that get the next signal, have
+ // access to the memory as well as the block processing result.
+ //----------------------------------------------------------------
+ always @*
+ begin : encdec_mux
+ enc_next = 0;
+ dec_next = 0;
+
+ if (encdec)
+ begin
+ // Encipher operations
+ enc_next = next;
+ muxed_round_nr = enc_round_nr;
+ muxed_new_block = enc_new_block;
+ muxed_ready = enc_ready;
+ end
+ else
+ begin
+ // Decipher operations
+ dec_next = next;
+ muxed_round_nr = dec_round_nr;
+ muxed_new_block = dec_new_block;
+ muxed_ready = dec_ready;
+ end
+ end // encdec_mux
+
+
+ //----------------------------------------------------------------
+ // aes_core_ctrl
+ //
+ // Control FSM for aes core. Basically tracks if we are in
+ // key init, encipher or decipher modes and connects the
+ // different submodules to shared resources and interface ports.
+ //----------------------------------------------------------------
+ always @*
+ begin : aes_core_ctrl
+ init_state = 0;
+ ready_new = 0;
+ ready_we = 0;
+ result_valid_new = 0;
+ result_valid_we = 0;
+ aes_core_ctrl_new = CTRL_IDLE;
+ aes_core_ctrl_we = 0;
+
+ case (aes_core_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (init)
+ begin
+ init_state = 1;
+ ready_new = 0;
+ ready_we = 1;
+ result_valid_new = 0;
+ result_valid_we = 1;
+ aes_core_ctrl_new = CTRL_INIT;
+ aes_core_ctrl_we = 1;
+ end
+ else if (next)
+ begin
+ init_state = 0;
+ ready_new = 0;
+ ready_we = 1;
+ result_valid_new = 0;
+ result_valid_we = 1;
+ aes_core_ctrl_new = CTRL_NEXT;
+ aes_core_ctrl_we = 1;
+ end
+ end
+
+ CTRL_INIT:
+ begin
+ init_state = 1;
+
+ if (key_ready)
+ begin
+ ready_new = 1;
+ ready_we = 1;
+ aes_core_ctrl_new = CTRL_IDLE;
+ aes_core_ctrl_we = 1;
+ end
+ end
+
+ CTRL_NEXT:
+ begin
+ init_state = 0;
+
+ if (muxed_ready)
+ begin
+ ready_new = 1;
+ ready_we = 1;
+ result_valid_new = 1;
+ result_valid_we = 1;
+ aes_core_ctrl_new = CTRL_IDLE;
+ aes_core_ctrl_we = 1;
+ end
+ end
+
+ default:
+ begin
+
+ end
+ endcase // case (aes_core_ctrl_reg)
+
+ end // aes_core_ctrl
+endmodule // aes_core
+
+//======================================================================
+// EOF aes_core.v
+//======================================================================
diff --git a/cipher/aes/src/rtl/aes_decipher_block.v b/cipher/aes/src/rtl/aes_decipher_block.v
new file mode 100644
index 0000000..ebcd164
--- /dev/null
+++ b/cipher/aes/src/rtl/aes_decipher_block.v
@@ -0,0 +1,542 @@
+//======================================================================
+//
+// aes_decipher_block.v
+// --------------------
+// The AES decipher round. A pure combinational module that implements
+// the initial round, main round and final round logic for
+// decciper operations.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module aes_decipher_block(
+ input wire clk,
+ input wire reset_n,
+
+ input wire next,
+
+ input wire keylen,
+ output wire [3 : 0] round,
+ input wire [127 : 0] round_key,
+
+ input wire [127 : 0] block,
+ output wire [127 : 0] new_block,
+ output wire ready
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter AES_128_BIT_KEY = 1'h0;
+ parameter AES_256_BIT_KEY = 1'h1;
+
+ parameter AES128_ROUNDS = 4'ha;
+ parameter AES256_ROUNDS = 4'he;
+
+ parameter NO_UPDATE = 3'h0;
+ parameter INIT_UPDATE = 3'h1;
+ parameter SBOX_UPDATE = 3'h2;
+ parameter MAIN_UPDATE = 3'h3;
+ parameter FINAL_UPDATE = 3'h4;
+
+ parameter CTRL_IDLE = 3'h0;
+ parameter CTRL_INIT = 3'h1;
+ parameter CTRL_SBOX = 3'h2;
+ parameter CTRL_MAIN = 3'h3;
+ parameter CTRL_FINAL = 3'h4;
+
+
+ //----------------------------------------------------------------
+ // Gaolis multiplication functions for Inverse MixColumn.
+ //----------------------------------------------------------------
+ function [7 : 0] gm2(input [7 : 0] op);
+ begin
+ gm2 = {op[6 : 0], 1'b0} ^ (8'h1b & {8{op[7]}});
+ end
+ endfunction // gm2
+
+ function [7 : 0] gm3(input [7 : 0] op);
+ begin
+ gm3 = gm2(op) ^ op;
+ end
+ endfunction // gm3
+
+ function [7 : 0] gm4(input [7 : 0] op);
+ begin
+ gm4 = gm2(gm2(op));
+ end
+ endfunction // gm4
+
+ function [7 : 0] gm8(input [7 : 0] op);
+ begin
+ gm8 = gm2(gm4(op));
+ end
+ endfunction // gm8
+
+ function [7 : 0] gm09(input [7 : 0] op);
+ begin
+ gm09 = gm8(op) ^ op;
+ end
+ endfunction // gm09
+
+ function [7 : 0] gm11(input [7 : 0] op);
+ begin
+ gm11 = gm8(op) ^ gm2(op) ^ op;
+ end
+ endfunction // gm11
+
+ function [7 : 0] gm13(input [7 : 0] op);
+ begin
+ gm13 = gm8(op) ^ gm4(op) ^ op;
+ end
+ endfunction // gm13
+
+ function [7 : 0] gm14(input [7 : 0] op);
+ begin
+ gm14 = gm8(op) ^ gm4(op) ^ gm2(op);
+ end
+ endfunction // gm14
+
+ function [31 : 0] inv_mixw(input [31 : 0] w);
+ reg [7 : 0] b0, b1, b2, b3;
+ reg [7 : 0] mb0, mb1, mb2, mb3;
+ begin
+ b0 = w[31 : 24];
+ b1 = w[23 : 16];
+ b2 = w[15 : 08];
+ b3 = w[07 : 00];
+
+ mb0 = gm14(b0) ^ gm11(b1) ^ gm13(b2) ^ gm09(b3);
+ mb1 = gm09(b0) ^ gm14(b1) ^ gm11(b2) ^ gm13(b3);
+ mb2 = gm13(b0) ^ gm09(b1) ^ gm14(b2) ^ gm11(b3);
+ mb3 = gm11(b0) ^ gm13(b1) ^ gm09(b2) ^ gm14(b3);
+
+ inv_mixw = {mb0, mb1, mb2, mb3};
+ end
+ endfunction // mixw
+
+ function [127 : 0] inv_mixcolumns(input [127 : 0] data);
+ reg [31 : 0] w0, w1, w2, w3;
+ reg [31 : 0] ws0, ws1, ws2, ws3;
+ begin
+ w0 = data[127 : 096];
+ w1 = data[095 : 064];
+ w2 = data[063 : 032];
+ w3 = data[031 : 000];
+
+ ws0 = inv_mixw(w0);
+ ws1 = inv_mixw(w1);
+ ws2 = inv_mixw(w2);
+ ws3 = inv_mixw(w3);
+
+ inv_mixcolumns = {ws0, ws1, ws2, ws3};
+ end
+ endfunction // inv_mixcolumns
+
+ function [127 : 0] inv_shiftrows(input [127 : 0] data);
+ reg [31 : 0] w0, w1, w2, w3;
+ reg [31 : 0] ws0, ws1, ws2, ws3;
+ begin
+ w0 = data[127 : 096];
+ w1 = data[095 : 064];
+ w2 = data[063 : 032];
+ w3 = data[031 : 000];
+
+ ws0 = {w0[31 : 24], w3[23 : 16], w2[15 : 08], w1[07 : 00]};
+ ws1 = {w1[31 : 24], w0[23 : 16], w3[15 : 08], w2[07 : 00]};
+ ws2 = {w2[31 : 24], w1[23 : 16], w0[15 : 08], w3[07 : 00]};
+ ws3 = {w3[31 : 24], w2[23 : 16], w1[15 : 08], w0[07 : 00]};
+
+ inv_shiftrows = {ws0, ws1, ws2, ws3};
+ end
+ endfunction // inv_shiftrows
+
+ function [127 : 0] addroundkey(input [127 : 0] data, input [127 : 0] rkey);
+ begin
+ addroundkey = data ^ rkey;
+ end
+ endfunction // addroundkey
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [1 : 0] sword_ctr_reg;
+ reg [1 : 0] sword_ctr_new;
+ reg sword_ctr_we;
+ reg sword_ctr_inc;
+ reg sword_ctr_rst;
+
+ reg [3 : 0] round_ctr_reg;
+ reg [3 : 0] round_ctr_new;
+ reg round_ctr_we;
+ reg round_ctr_set;
+ reg round_ctr_dec;
+
+ reg [127 : 0] block_new;
+ reg [31 : 0] block_w0_reg;
+ reg [31 : 0] block_w1_reg;
+ reg [31 : 0] block_w2_reg;
+ reg [31 : 0] block_w3_reg;
+ reg block_w0_we;
+ reg block_w1_we;
+ reg block_w2_we;
+ reg block_w3_we;
+
+ reg ready_reg;
+ reg ready_new;
+ reg ready_we;
+
+ reg [2 : 0] dec_ctrl_reg;
+ reg [2 : 0] dec_ctrl_new;
+ reg dec_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] tmp_sboxw;
+ wire [31 : 0] new_sboxw;
+ reg [2 : 0] update_type;
+ reg [3 : 0] num_rounds;
+
+
+ //----------------------------------------------------------------
+ // Instantiations.
+ //----------------------------------------------------------------
+ aes_inv_sbox inv_sbox(.sword(tmp_sboxw), .new_sword(new_sboxw));
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign round = round_ctr_reg;
+ assign new_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg};
+ assign ready = ready_reg;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with synchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin: reg_update
+ if (!reset_n)
+ begin
+ block_w0_reg <= 32'h00000000;
+ block_w1_reg <= 32'h00000000;
+ block_w2_reg <= 32'h00000000;
+ block_w3_reg <= 32'h00000000;
+ sword_ctr_reg <= 2'h0;
+ round_ctr_reg <= 4'h0;
+ ready_reg <= 1;
+ dec_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ if (block_w0_we)
+ begin
+ block_w0_reg <= block_new[127 : 096];
+ end
+
+ if (block_w1_we)
+ begin
+ block_w1_reg <= block_new[095 : 064];
+ end
+
+ if (block_w2_we)
+ begin
+ block_w2_reg <= block_new[063 : 032];
+ end
+
+ if (block_w3_we)
+ begin
+ block_w3_reg <= block_new[031 : 000];
+ end
+
+ if (sword_ctr_we)
+ begin
+ sword_ctr_reg <= sword_ctr_new;
+ end
+
+ if (round_ctr_we)
+ begin
+ round_ctr_reg <= round_ctr_new;
+ end
+
+ if (ready_we)
+ begin
+ ready_reg <= ready_new;
+ end
+
+ if (dec_ctrl_we)
+ begin
+ dec_ctrl_reg <= dec_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // round_logic
+ //
+ // The logic needed to implement init, main and final rounds.
+ //----------------------------------------------------------------
+ always @*
+ begin : round_logic
+ reg [127 : 0] old_block, inv_shiftrows_block, inv_mixcolumns_block;
+ reg [127 : 0] addkey_block;
+
+ inv_shiftrows_block = 128'h00000000000000000000000000000000;
+ inv_mixcolumns_block = 128'h00000000000000000000000000000000;
+ addkey_block = 128'h00000000000000000000000000000000;
+ block_new = 128'h00000000000000000000000000000000;
+ tmp_sboxw = 32'h00000000;
+ block_w0_we = 0;
+ block_w1_we = 0;
+ block_w2_we = 0;
+ block_w3_we = 0;
+
+ old_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg};
+
+ // Update based on update type.
+ case (update_type)
+ // InitRound
+ INIT_UPDATE:
+ begin
+ old_block = block;
+ addkey_block = addroundkey(old_block, round_key);
+ inv_shiftrows_block = inv_shiftrows(addkey_block);
+ block_new = inv_shiftrows_block;
+ block_w0_we = 1;
+ block_w1_we = 1;
+ block_w2_we = 1;
+ block_w3_we = 1;
+ end
+
+ SBOX_UPDATE:
+ begin
+ block_new = {new_sboxw, new_sboxw, new_sboxw, new_sboxw};
+
+ case (sword_ctr_reg)
+ 2'h0:
+ begin
+ tmp_sboxw = block_w0_reg;
+ block_w0_we = 1;
+ end
+
+ 2'h1:
+ begin
+ tmp_sboxw = block_w1_reg;
+ block_w1_we = 1;
+ end
+
+ 2'h2:
+ begin
+ tmp_sboxw = block_w2_reg;
+ block_w2_we = 1;
+ end
+
+ 2'h3:
+ begin
+ tmp_sboxw = block_w3_reg;
+ block_w3_we = 1;
+ end
+ endcase // case (sbox_mux_ctrl_reg)
+ end
+
+ MAIN_UPDATE:
+ begin
+ addkey_block = addroundkey(old_block, round_key);
+ inv_mixcolumns_block = inv_mixcolumns(addkey_block);
+ inv_shiftrows_block = inv_shiftrows(inv_mixcolumns_block);
+ block_new = inv_shiftrows_block;
+ block_w0_we = 1;
+ block_w1_we = 1;
+ block_w2_we = 1;
+ block_w3_we = 1;
+ end
+
+ FINAL_UPDATE:
+ begin
+ block_new = addroundkey(old_block, round_key);
+ block_w0_we = 1;
+ block_w1_we = 1;
+ block_w2_we = 1;
+ block_w3_we = 1;
+ end
+
+ default:
+ begin
+ end
+ endcase // case (update_type)
+ end // round_logic
+
+
+ //----------------------------------------------------------------
+ // sword_ctr
+ //
+ // The subbytes word counter with reset and increase logic.
+ //----------------------------------------------------------------
+ always @*
+ begin : sword_ctr
+ sword_ctr_new = 2'h0;
+ sword_ctr_we = 1'b0;
+
+ if (sword_ctr_rst)
+ begin
+ sword_ctr_new = 2'h0;
+ sword_ctr_we = 1'b1;
+ end
+ else if (sword_ctr_inc)
+ begin
+ sword_ctr_new = sword_ctr_reg + 1'b1;
+ sword_ctr_we = 1'b1;
+ end
+ end // sword_ctr
+
+
+ //----------------------------------------------------------------
+ // round_ctr
+ //
+ // The round counter with reset and increase logic.
+ //----------------------------------------------------------------
+ always @*
+ begin : round_ctr
+ round_ctr_new = 4'h0;
+ round_ctr_we = 1'b0;
+
+ if (round_ctr_set)
+ begin
+ if (keylen == AES_256_BIT_KEY)
+ begin
+ round_ctr_new = AES256_ROUNDS;
+ end
+ else
+ begin
+ round_ctr_new = AES128_ROUNDS;
+ end
+ round_ctr_we = 1'b1;
+ end
+ else if (round_ctr_dec)
+ begin
+ round_ctr_new = round_ctr_reg - 1'b1;
+ round_ctr_we = 1'b1;
+ end
+ end // round_ctr
+
+
+ //----------------------------------------------------------------
+ // decipher_ctrl
+ //
+ // The FSM that controls the decipher operations.
+ //----------------------------------------------------------------
+ always @*
+ begin: decipher_ctrl
+ sword_ctr_inc = 0;
+ sword_ctr_rst = 0;
+ round_ctr_dec = 0;
+ round_ctr_set = 0;
+ ready_new = 0;
+ ready_we = 0;
+ update_type = NO_UPDATE;
+ dec_ctrl_new = CTRL_IDLE;
+ dec_ctrl_we = 0;
+
+ case(dec_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (next)
+ begin
+ round_ctr_set = 1;
+ ready_new = 0;
+ ready_we = 1;
+ dec_ctrl_new = CTRL_INIT;
+ dec_ctrl_we = 1;
+ end
+ end
+
+ CTRL_INIT:
+ begin
+ sword_ctr_rst = 1;
+ update_type = INIT_UPDATE;
+ dec_ctrl_new = CTRL_SBOX;
+ dec_ctrl_we = 1;
+ end
+
+ CTRL_SBOX:
+ begin
+ sword_ctr_inc = 1;
+ update_type = SBOX_UPDATE;
+ if (sword_ctr_reg == 2'h3)
+ begin
+ round_ctr_dec = 1;
+ dec_ctrl_new = CTRL_MAIN;
+ dec_ctrl_we = 1;
+ end
+ end
+
+ CTRL_MAIN:
+ begin
+ sword_ctr_rst = 1;
+ if (round_ctr_reg > 0)
+ begin
+ update_type = MAIN_UPDATE;
+ dec_ctrl_new = CTRL_SBOX;
+ dec_ctrl_we = 1;
+ end
+ else
+ begin
+ update_type = FINAL_UPDATE;
+ ready_new = 1;
+ ready_we = 1;
+ dec_ctrl_new = CTRL_IDLE;
+ dec_ctrl_we = 1;
+ end
+ end
+
+ default:
+ begin
+ // Empty. Just here to make the synthesis tool happy.
+ end
+ endcase // case (dec_ctrl_reg)
+ end // decipher_ctrl
+
+endmodule // aes_decipher_block
+
+//======================================================================
+// EOF aes_decipher_block.v
+//======================================================================
diff --git a/cipher/aes/src/rtl/aes_encipher_block.v b/cipher/aes/src/rtl/aes_encipher_block.v
new file mode 100644
index 0000000..2761d5b
--- /dev/null
+++ b/cipher/aes/src/rtl/aes_encipher_block.v
@@ -0,0 +1,501 @@
+//======================================================================
+//
+// aes_encipher_block.v
+// --------------------
+// The AES encipher round. A pure combinational module that implements
+// the initial round, main round and final round logic for
+// enciper operations.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module aes_encipher_block(
+ input wire clk,
+ input wire reset_n,
+
+ input wire next,
+
+ input wire keylen,
+ output wire [3 : 0] round,
+ input wire [127 : 0] round_key,
+
+ output wire [31 : 0] sboxw,
+ input wire [31 : 0] new_sboxw,
+
+ input wire [127 : 0] block,
+ output wire [127 : 0] new_block,
+ output wire ready
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter AES_128_BIT_KEY = 1'h0;
+ parameter AES_256_BIT_KEY = 1'h1;
+
+ parameter AES128_ROUNDS = 4'ha;
+ parameter AES256_ROUNDS = 4'he;
+
+ parameter NO_UPDATE = 3'h0;
+ parameter INIT_UPDATE = 3'h1;
+ parameter SBOX_UPDATE = 3'h2;
+ parameter MAIN_UPDATE = 3'h3;
+ parameter FINAL_UPDATE = 3'h4;
+
+ parameter CTRL_IDLE = 3'h0;
+ parameter CTRL_INIT = 3'h1;
+ parameter CTRL_SBOX = 3'h2;
+ parameter CTRL_MAIN = 3'h3;
+ parameter CTRL_FINAL = 3'h4;
+
+
+ //----------------------------------------------------------------
+ // Round functions with sub functions.
+ //----------------------------------------------------------------
+ function [7 : 0] gm2(input [7 : 0] op);
+ begin
+ gm2 = {op[6 : 0], 1'b0} ^ (8'h1b & {8{op[7]}});
+ end
+ endfunction // gm2
+
+ function [7 : 0] gm3(input [7 : 0] op);
+ begin
+ gm3 = gm2(op) ^ op;
+ end
+ endfunction // gm3
+
+ function [31 : 0] mixw(input [31 : 0] w);
+ reg [7 : 0] b0, b1, b2, b3;
+ reg [7 : 0] mb0, mb1, mb2, mb3;
+ begin
+ b0 = w[31 : 24];
+ b1 = w[23 : 16];
+ b2 = w[15 : 08];
+ b3 = w[07 : 00];
+
+ mb0 = gm2(b0) ^ gm3(b1) ^ b2 ^ b3;
+ mb1 = b0 ^ gm2(b1) ^ gm3(b2) ^ b3;
+ mb2 = b0 ^ b1 ^ gm2(b2) ^ gm3(b3);
+ mb3 = gm3(b0) ^ b1 ^ b2 ^ gm2(b3);
+
+ mixw = {mb0, mb1, mb2, mb3};
+ end
+ endfunction // mixw
+
+ function [127 : 0] mixcolumns(input [127 : 0] data);
+ reg [31 : 0] w0, w1, w2, w3;
+ reg [31 : 0] ws0, ws1, ws2, ws3;
+ begin
+ w0 = data[127 : 096];
+ w1 = data[095 : 064];
+ w2 = data[063 : 032];
+ w3 = data[031 : 000];
+
+ ws0 = mixw(w0);
+ ws1 = mixw(w1);
+ ws2 = mixw(w2);
+ ws3 = mixw(w3);
+
+ mixcolumns = {ws0, ws1, ws2, ws3};
+ end
+ endfunction // mixcolumns
+
+ function [127 : 0] shiftrows(input [127 : 0] data);
+ reg [31 : 0] w0, w1, w2, w3;
+ reg [31 : 0] ws0, ws1, ws2, ws3;
+ begin
+ w0 = data[127 : 096];
+ w1 = data[095 : 064];
+ w2 = data[063 : 032];
+ w3 = data[031 : 000];
+
+ ws0 = {w0[31 : 24], w1[23 : 16], w2[15 : 08], w3[07 : 00]};
+ ws1 = {w1[31 : 24], w2[23 : 16], w3[15 : 08], w0[07 : 00]};
+ ws2 = {w2[31 : 24], w3[23 : 16], w0[15 : 08], w1[07 : 00]};
+ ws3 = {w3[31 : 24], w0[23 : 16], w1[15 : 08], w2[07 : 00]};
+
+ shiftrows = {ws0, ws1, ws2, ws3};
+ end
+ endfunction // shiftrows
+
+ function [127 : 0] addroundkey(input [127 : 0] data, input [127 : 0] rkey);
+ begin
+ addroundkey = data ^ rkey;
+ end
+ endfunction // addroundkey
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [1 : 0] sword_ctr_reg;
+ reg [1 : 0] sword_ctr_new;
+ reg sword_ctr_we;
+ reg sword_ctr_inc;
+ reg sword_ctr_rst;
+
+ reg [3 : 0] round_ctr_reg;
+ reg [3 : 0] round_ctr_new;
+ reg round_ctr_we;
+ reg round_ctr_rst;
+ reg round_ctr_inc;
+
+ reg [127 : 0] block_new;
+ reg [31 : 0] block_w0_reg;
+ reg [31 : 0] block_w1_reg;
+ reg [31 : 0] block_w2_reg;
+ reg [31 : 0] block_w3_reg;
+ reg block_w0_we;
+ reg block_w1_we;
+ reg block_w2_we;
+ reg block_w3_we;
+
+ reg ready_reg;
+ reg ready_new;
+ reg ready_we;
+
+ reg [2 : 0] enc_ctrl_reg;
+ reg [2 : 0] enc_ctrl_new;
+ reg enc_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [2 : 0] update_type;
+ reg [31 : 0] muxed_sboxw;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign round = round_ctr_reg;
+ assign sboxw = muxed_sboxw;
+ assign new_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg};
+ assign ready = ready_reg;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin: reg_update
+ if (!reset_n)
+ begin
+ block_w0_reg <= 32'h00000000;
+ block_w1_reg <= 32'h00000000;
+ block_w2_reg <= 32'h00000000;
+ block_w3_reg <= 32'h00000000;
+ sword_ctr_reg <= 2'h0;
+ round_ctr_reg <= 4'h0;
+ ready_reg <= 1;
+ enc_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ if (block_w0_we)
+ begin
+ block_w0_reg <= block_new[127 : 096];
+ end
+
+ if (block_w1_we)
+ begin
+ block_w1_reg <= block_new[095 : 064];
+ end
+
+ if (block_w2_we)
+ begin
+ block_w2_reg <= block_new[063 : 032];
+ end
+
+ if (block_w3_we)
+ begin
+ block_w3_reg <= block_new[031 : 000];
+ end
+
+ if (sword_ctr_we)
+ begin
+ sword_ctr_reg <= sword_ctr_new;
+ end
+
+ if (round_ctr_we)
+ begin
+ round_ctr_reg <= round_ctr_new;
+ end
+
+ if (ready_we)
+ begin
+ ready_reg <= ready_new;
+ end
+
+ if (enc_ctrl_we)
+ begin
+ enc_ctrl_reg <= enc_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // round_logic
+ //
+ // The logic needed to implement init, main and final rounds.
+ //----------------------------------------------------------------
+ always @*
+ begin : round_logic
+ reg [127 : 0] old_block, shiftrows_block, mixcolumns_block;
+ reg [127 : 0] addkey_init_block, addkey_main_block, addkey_final_block;
+
+ block_new = 128'h00000000000000000000000000000000;
+ muxed_sboxw = 32'h00000000;
+ block_w0_we = 0;
+ block_w1_we = 0;
+ block_w2_we = 0;
+ block_w3_we = 0;
+
+ old_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg};
+ shiftrows_block = shiftrows(old_block);
+ mixcolumns_block = mixcolumns(shiftrows_block);
+ addkey_init_block = addroundkey(block, round_key);
+ addkey_main_block = addroundkey(mixcolumns_block, round_key);
+ addkey_final_block = addroundkey(shiftrows_block, round_key);
+
+ case (update_type)
+ INIT_UPDATE:
+ begin
+ block_new = addkey_init_block;
+ block_w0_we = 1;
+ block_w1_we = 1;
+ block_w2_we = 1;
+ block_w3_we = 1;
+ end
+
+ SBOX_UPDATE:
+ begin
+ block_new = {new_sboxw, new_sboxw, new_sboxw, new_sboxw};
+
+ case (sword_ctr_reg)
+ 2'h0:
+ begin
+ muxed_sboxw = block_w0_reg;
+ block_w0_we = 1;
+ end
+
+ 2'h1:
+ begin
+ muxed_sboxw = block_w1_reg;
+ block_w1_we = 1;
+ end
+
+ 2'h2:
+ begin
+ muxed_sboxw = block_w2_reg;
+ block_w2_we = 1;
+ end
+
+ 2'h3:
+ begin
+ muxed_sboxw = block_w3_reg;
+ block_w3_we = 1;
+ end
+ endcase // case (sbox_mux_ctrl_reg)
+ end
+
+ MAIN_UPDATE:
+ begin
+ block_new = addkey_main_block;
+ block_w0_we = 1;
+ block_w1_we = 1;
+ block_w2_we = 1;
+ block_w3_we = 1;
+ end
+
+ FINAL_UPDATE:
+ begin
+ block_new = addkey_final_block;
+ block_w0_we = 1;
+ block_w1_we = 1;
+ block_w2_we = 1;
+ block_w3_we = 1;
+ end
+
+ default:
+ begin
+ end
+ endcase // case (update_type)
+ end // round_logic
+
+
+ //----------------------------------------------------------------
+ // sword_ctr
+ //
+ // The subbytes word counter with reset and increase logic.
+ //----------------------------------------------------------------
+ always @*
+ begin : sword_ctr
+ sword_ctr_new = 2'h0;
+ sword_ctr_we = 1'b0;
+
+ if (sword_ctr_rst)
+ begin
+ sword_ctr_new = 2'h0;
+ sword_ctr_we = 1'b1;
+ end
+ else if (sword_ctr_inc)
+ begin
+ sword_ctr_new = sword_ctr_reg + 1'b1;
+ sword_ctr_we = 1'b1;
+ end
+ end // sword_ctr
+
+
+ //----------------------------------------------------------------
+ // round_ctr
+ //
+ // The round counter with reset and increase logic.
+ //----------------------------------------------------------------
+ always @*
+ begin : round_ctr
+ round_ctr_new = 4'h0;
+ round_ctr_we = 1'b0;
+
+ if (round_ctr_rst)
+ begin
+ round_ctr_new = 4'h0;
+ round_ctr_we = 1'b1;
+ end
+ else if (round_ctr_inc)
+ begin
+ round_ctr_new = round_ctr_reg + 1'b1;
+ round_ctr_we = 1'b1;
+ end
+ end // round_ctr
+
+
+ //----------------------------------------------------------------
+ // encipher_ctrl
+ //
+ // The FSM that controls the encipher operations.
+ //----------------------------------------------------------------
+ always @*
+ begin: encipher_ctrl
+ reg [3 : 0] num_rounds;
+
+ if (keylen == AES_256_BIT_KEY)
+ begin
+ num_rounds = AES256_ROUNDS;
+ end
+ else
+ begin
+ num_rounds = AES128_ROUNDS;
+ end
+
+ sword_ctr_inc = 0;
+ sword_ctr_rst = 0;
+ round_ctr_inc = 0;
+ round_ctr_rst = 0;
+ ready_new = 0;
+ ready_we = 0;
+ update_type = NO_UPDATE;
+ enc_ctrl_new = CTRL_IDLE;
+ enc_ctrl_we = 0;
+
+ case(enc_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (next)
+ begin
+ round_ctr_rst = 1;
+ ready_new = 0;
+ ready_we = 1;
+ enc_ctrl_new = CTRL_INIT;
+ enc_ctrl_we = 1;
+ end
+ end
+
+ CTRL_INIT:
+ begin
+ round_ctr_inc = 1;
+ sword_ctr_rst = 1;
+ update_type = INIT_UPDATE;
+ enc_ctrl_new = CTRL_SBOX;
+ enc_ctrl_we = 1;
+ end
+
+ CTRL_SBOX:
+ begin
+ sword_ctr_inc = 1;
+ update_type = SBOX_UPDATE;
+ if (sword_ctr_reg == 2'h3)
+ begin
+ enc_ctrl_new = CTRL_MAIN;
+ enc_ctrl_we = 1;
+ end
+ end
+
+ CTRL_MAIN:
+ begin
+ sword_ctr_rst = 1;
+ round_ctr_inc = 1;
+ if (round_ctr_reg < num_rounds)
+ begin
+ update_type = MAIN_UPDATE;
+ enc_ctrl_new = CTRL_SBOX;
+ enc_ctrl_we = 1;
+ end
+ else
+ begin
+ update_type = FINAL_UPDATE;
+ ready_new = 1;
+ ready_we = 1;
+ enc_ctrl_new = CTRL_IDLE;
+ enc_ctrl_we = 1;
+ end
+ end
+
+ default:
+ begin
+ // Empty. Just here to make the synthesis tool happy.
+ end
+ endcase // case (enc_ctrl_reg)
+ end // encipher_ctrl
+
+endmodule // aes_encipher_block
+
+//======================================================================
+// EOF aes_encipher_block.v
+//======================================================================
diff --git a/cipher/aes/src/rtl/aes_inv_sbox.v b/cipher/aes/src/rtl/aes_inv_sbox.v
new file mode 100644
index 0000000..99d0b00
--- /dev/null
+++ b/cipher/aes/src/rtl/aes_inv_sbox.v
@@ -0,0 +1,320 @@
+//======================================================================
+//
+// aes_inv_sbox.v
+// --------------
+// The inverse AES S-box. Basically a 256 Byte ROM.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module aes_inv_sbox(
+ input wire [31 : 0] sword,
+ output wire [31 : 0] new_sword
+ );
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ wire [7 : 0] inv_sbox [0 : 255];
+
+
+ //----------------------------------------------------------------
+ // Concurrent assignments for ports.
+ //----------------------------------------------------------------
+ assign inv_sbox[8'h00] = 8'h52;
+ assign inv_sbox[8'h01] = 8'h09;
+ assign inv_sbox[8'h02] = 8'h6a;
+ assign inv_sbox[8'h03] = 8'hd5;
+ assign inv_sbox[8'h04] = 8'h30;
+ assign inv_sbox[8'h05] = 8'h36;
+ assign inv_sbox[8'h06] = 8'ha5;
+ assign inv_sbox[8'h07] = 8'h38;
+ assign inv_sbox[8'h08] = 8'hbf;
+ assign inv_sbox[8'h09] = 8'h40;
+ assign inv_sbox[8'h0a] = 8'ha3;
+ assign inv_sbox[8'h0b] = 8'h9e;
+ assign inv_sbox[8'h0c] = 8'h81;
+ assign inv_sbox[8'h0d] = 8'hf3;
+ assign inv_sbox[8'h0e] = 8'hd7;
+ assign inv_sbox[8'h0f] = 8'hfb;
+ assign inv_sbox[8'h10] = 8'h7c;
+ assign inv_sbox[8'h11] = 8'he3;
+ assign inv_sbox[8'h12] = 8'h39;
+ assign inv_sbox[8'h13] = 8'h82;
+ assign inv_sbox[8'h14] = 8'h9b;
+ assign inv_sbox[8'h15] = 8'h2f;
+ assign inv_sbox[8'h16] = 8'hff;
+ assign inv_sbox[8'h17] = 8'h87;
+ assign inv_sbox[8'h18] = 8'h34;
+ assign inv_sbox[8'h19] = 8'h8e;
+ assign inv_sbox[8'h1a] = 8'h43;
+ assign inv_sbox[8'h1b] = 8'h44;
+ assign inv_sbox[8'h1c] = 8'hc4;
+ assign inv_sbox[8'h1d] = 8'hde;
+ assign inv_sbox[8'h1e] = 8'he9;
+ assign inv_sbox[8'h1f] = 8'hcb;
+ assign inv_sbox[8'h20] = 8'h54;
+ assign inv_sbox[8'h21] = 8'h7b;
+ assign inv_sbox[8'h22] = 8'h94;
+ assign inv_sbox[8'h23] = 8'h32;
+ assign inv_sbox[8'h24] = 8'ha6;
+ assign inv_sbox[8'h25] = 8'hc2;
+ assign inv_sbox[8'h26] = 8'h23;
+ assign inv_sbox[8'h27] = 8'h3d;
+ assign inv_sbox[8'h28] = 8'hee;
+ assign inv_sbox[8'h29] = 8'h4c;
+ assign inv_sbox[8'h2a] = 8'h95;
+ assign inv_sbox[8'h2b] = 8'h0b;
+ assign inv_sbox[8'h2c] = 8'h42;
+ assign inv_sbox[8'h2d] = 8'hfa;
+ assign inv_sbox[8'h2e] = 8'hc3;
+ assign inv_sbox[8'h2f] = 8'h4e;
+ assign inv_sbox[8'h30] = 8'h08;
+ assign inv_sbox[8'h31] = 8'h2e;
+ assign inv_sbox[8'h32] = 8'ha1;
+ assign inv_sbox[8'h33] = 8'h66;
+ assign inv_sbox[8'h34] = 8'h28;
+ assign inv_sbox[8'h35] = 8'hd9;
+ assign inv_sbox[8'h36] = 8'h24;
+ assign inv_sbox[8'h37] = 8'hb2;
+ assign inv_sbox[8'h38] = 8'h76;
+ assign inv_sbox[8'h39] = 8'h5b;
+ assign inv_sbox[8'h3a] = 8'ha2;
+ assign inv_sbox[8'h3b] = 8'h49;
+ assign inv_sbox[8'h3c] = 8'h6d;
+ assign inv_sbox[8'h3d] = 8'h8b;
+ assign inv_sbox[8'h3e] = 8'hd1;
+ assign inv_sbox[8'h3f] = 8'h25;
+ assign inv_sbox[8'h40] = 8'h72;
+ assign inv_sbox[8'h41] = 8'hf8;
+ assign inv_sbox[8'h42] = 8'hf6;
+ assign inv_sbox[8'h43] = 8'h64;
+ assign inv_sbox[8'h44] = 8'h86;
+ assign inv_sbox[8'h45] = 8'h68;
+ assign inv_sbox[8'h46] = 8'h98;
+ assign inv_sbox[8'h47] = 8'h16;
+ assign inv_sbox[8'h48] = 8'hd4;
+ assign inv_sbox[8'h49] = 8'ha4;
+ assign inv_sbox[8'h4a] = 8'h5c;
+ assign inv_sbox[8'h4b] = 8'hcc;
+ assign inv_sbox[8'h4c] = 8'h5d;
+ assign inv_sbox[8'h4d] = 8'h65;
+ assign inv_sbox[8'h4e] = 8'hb6;
+ assign inv_sbox[8'h4f] = 8'h92;
+ assign inv_sbox[8'h50] = 8'h6c;
+ assign inv_sbox[8'h51] = 8'h70;
+ assign inv_sbox[8'h52] = 8'h48;
+ assign inv_sbox[8'h53] = 8'h50;
+ assign inv_sbox[8'h54] = 8'hfd;
+ assign inv_sbox[8'h55] = 8'hed;
+ assign inv_sbox[8'h56] = 8'hb9;
+ assign inv_sbox[8'h57] = 8'hda;
+ assign inv_sbox[8'h58] = 8'h5e;
+ assign inv_sbox[8'h59] = 8'h15;
+ assign inv_sbox[8'h5a] = 8'h46;
+ assign inv_sbox[8'h5b] = 8'h57;
+ assign inv_sbox[8'h5c] = 8'ha7;
+ assign inv_sbox[8'h5d] = 8'h8d;
+ assign inv_sbox[8'h5e] = 8'h9d;
+ assign inv_sbox[8'h5f] = 8'h84;
+ assign inv_sbox[8'h60] = 8'h90;
+ assign inv_sbox[8'h61] = 8'hd8;
+ assign inv_sbox[8'h62] = 8'hab;
+ assign inv_sbox[8'h63] = 8'h00;
+ assign inv_sbox[8'h64] = 8'h8c;
+ assign inv_sbox[8'h65] = 8'hbc;
+ assign inv_sbox[8'h66] = 8'hd3;
+ assign inv_sbox[8'h67] = 8'h0a;
+ assign inv_sbox[8'h68] = 8'hf7;
+ assign inv_sbox[8'h69] = 8'he4;
+ assign inv_sbox[8'h6a] = 8'h58;
+ assign inv_sbox[8'h6b] = 8'h05;
+ assign inv_sbox[8'h6c] = 8'hb8;
+ assign inv_sbox[8'h6d] = 8'hb3;
+ assign inv_sbox[8'h6e] = 8'h45;
+ assign inv_sbox[8'h6f] = 8'h06;
+ assign inv_sbox[8'h70] = 8'hd0;
+ assign inv_sbox[8'h71] = 8'h2c;
+ assign inv_sbox[8'h72] = 8'h1e;
+ assign inv_sbox[8'h73] = 8'h8f;
+ assign inv_sbox[8'h74] = 8'hca;
+ assign inv_sbox[8'h75] = 8'h3f;
+ assign inv_sbox[8'h76] = 8'h0f;
+ assign inv_sbox[8'h77] = 8'h02;
+ assign inv_sbox[8'h78] = 8'hc1;
+ assign inv_sbox[8'h79] = 8'haf;
+ assign inv_sbox[8'h7a] = 8'hbd;
+ assign inv_sbox[8'h7b] = 8'h03;
+ assign inv_sbox[8'h7c] = 8'h01;
+ assign inv_sbox[8'h7d] = 8'h13;
+ assign inv_sbox[8'h7e] = 8'h8a;
+ assign inv_sbox[8'h7f] = 8'h6b;
+ assign inv_sbox[8'h80] = 8'h3a;
+ assign inv_sbox[8'h81] = 8'h91;
+ assign inv_sbox[8'h82] = 8'h11;
+ assign inv_sbox[8'h83] = 8'h41;
+ assign inv_sbox[8'h84] = 8'h4f;
+ assign inv_sbox[8'h85] = 8'h67;
+ assign inv_sbox[8'h86] = 8'hdc;
+ assign inv_sbox[8'h87] = 8'hea;
+ assign inv_sbox[8'h88] = 8'h97;
+ assign inv_sbox[8'h89] = 8'hf2;
+ assign inv_sbox[8'h8a] = 8'hcf;
+ assign inv_sbox[8'h8b] = 8'hce;
+ assign inv_sbox[8'h8c] = 8'hf0;
+ assign inv_sbox[8'h8d] = 8'hb4;
+ assign inv_sbox[8'h8e] = 8'he6;
+ assign inv_sbox[8'h8f] = 8'h73;
+ assign inv_sbox[8'h90] = 8'h96;
+ assign inv_sbox[8'h91] = 8'hac;
+ assign inv_sbox[8'h92] = 8'h74;
+ assign inv_sbox[8'h93] = 8'h22;
+ assign inv_sbox[8'h94] = 8'he7;
+ assign inv_sbox[8'h95] = 8'had;
+ assign inv_sbox[8'h96] = 8'h35;
+ assign inv_sbox[8'h97] = 8'h85;
+ assign inv_sbox[8'h98] = 8'he2;
+ assign inv_sbox[8'h99] = 8'hf9;
+ assign inv_sbox[8'h9a] = 8'h37;
+ assign inv_sbox[8'h9b] = 8'he8;
+ assign inv_sbox[8'h9c] = 8'h1c;
+ assign inv_sbox[8'h9d] = 8'h75;
+ assign inv_sbox[8'h9e] = 8'hdf;
+ assign inv_sbox[8'h9f] = 8'h6e;
+ assign inv_sbox[8'ha0] = 8'h47;
+ assign inv_sbox[8'ha1] = 8'hf1;
+ assign inv_sbox[8'ha2] = 8'h1a;
+ assign inv_sbox[8'ha3] = 8'h71;
+ assign inv_sbox[8'ha4] = 8'h1d;
+ assign inv_sbox[8'ha5] = 8'h29;
+ assign inv_sbox[8'ha6] = 8'hc5;
+ assign inv_sbox[8'ha7] = 8'h89;
+ assign inv_sbox[8'ha8] = 8'h6f;
+ assign inv_sbox[8'ha9] = 8'hb7;
+ assign inv_sbox[8'haa] = 8'h62;
+ assign inv_sbox[8'hab] = 8'h0e;
+ assign inv_sbox[8'hac] = 8'haa;
+ assign inv_sbox[8'had] = 8'h18;
+ assign inv_sbox[8'hae] = 8'hbe;
+ assign inv_sbox[8'haf] = 8'h1b;
+ assign inv_sbox[8'hb0] = 8'hfc;
+ assign inv_sbox[8'hb1] = 8'h56;
+ assign inv_sbox[8'hb2] = 8'h3e;
+ assign inv_sbox[8'hb3] = 8'h4b;
+ assign inv_sbox[8'hb4] = 8'hc6;
+ assign inv_sbox[8'hb5] = 8'hd2;
+ assign inv_sbox[8'hb6] = 8'h79;
+ assign inv_sbox[8'hb7] = 8'h20;
+ assign inv_sbox[8'hb8] = 8'h9a;
+ assign inv_sbox[8'hb9] = 8'hdb;
+ assign inv_sbox[8'hba] = 8'hc0;
+ assign inv_sbox[8'hbb] = 8'hfe;
+ assign inv_sbox[8'hbc] = 8'h78;
+ assign inv_sbox[8'hbd] = 8'hcd;
+ assign inv_sbox[8'hbe] = 8'h5a;
+ assign inv_sbox[8'hbf] = 8'hf4;
+ assign inv_sbox[8'hc0] = 8'h1f;
+ assign inv_sbox[8'hc1] = 8'hdd;
+ assign inv_sbox[8'hc2] = 8'ha8;
+ assign inv_sbox[8'hc3] = 8'h33;
+ assign inv_sbox[8'hc4] = 8'h88;
+ assign inv_sbox[8'hc5] = 8'h07;
+ assign inv_sbox[8'hc6] = 8'hc7;
+ assign inv_sbox[8'hc7] = 8'h31;
+ assign inv_sbox[8'hc8] = 8'hb1;
+ assign inv_sbox[8'hc9] = 8'h12;
+ assign inv_sbox[8'hca] = 8'h10;
+ assign inv_sbox[8'hcb] = 8'h59;
+ assign inv_sbox[8'hcc] = 8'h27;
+ assign inv_sbox[8'hcd] = 8'h80;
+ assign inv_sbox[8'hce] = 8'hec;
+ assign inv_sbox[8'hcf] = 8'h5f;
+ assign inv_sbox[8'hd0] = 8'h60;
+ assign inv_sbox[8'hd1] = 8'h51;
+ assign inv_sbox[8'hd2] = 8'h7f;
+ assign inv_sbox[8'hd3] = 8'ha9;
+ assign inv_sbox[8'hd4] = 8'h19;
+ assign inv_sbox[8'hd5] = 8'hb5;
+ assign inv_sbox[8'hd6] = 8'h4a;
+ assign inv_sbox[8'hd7] = 8'h0d;
+ assign inv_sbox[8'hd8] = 8'h2d;
+ assign inv_sbox[8'hd9] = 8'he5;
+ assign inv_sbox[8'hda] = 8'h7a;
+ assign inv_sbox[8'hdb] = 8'h9f;
+ assign inv_sbox[8'hdc] = 8'h93;
+ assign inv_sbox[8'hdd] = 8'hc9;
+ assign inv_sbox[8'hde] = 8'h9c;
+ assign inv_sbox[8'hdf] = 8'hef;
+ assign inv_sbox[8'he0] = 8'ha0;
+ assign inv_sbox[8'he1] = 8'he0;
+ assign inv_sbox[8'he2] = 8'h3b;
+ assign inv_sbox[8'he3] = 8'h4d;
+ assign inv_sbox[8'he4] = 8'hae;
+ assign inv_sbox[8'he5] = 8'h2a;
+ assign inv_sbox[8'he6] = 8'hf5;
+ assign inv_sbox[8'he7] = 8'hb0;
+ assign inv_sbox[8'he8] = 8'hc8;
+ assign inv_sbox[8'he9] = 8'heb;
+ assign inv_sbox[8'hea] = 8'hbb;
+ assign inv_sbox[8'heb] = 8'h3c;
+ assign inv_sbox[8'hec] = 8'h83;
+ assign inv_sbox[8'hed] = 8'h53;
+ assign inv_sbox[8'hee] = 8'h99;
+ assign inv_sbox[8'hef] = 8'h61;
+ assign inv_sbox[8'hf0] = 8'h17;
+ assign inv_sbox[8'hf1] = 8'h2b;
+ assign inv_sbox[8'hf2] = 8'h04;
+ assign inv_sbox[8'hf3] = 8'h7e;
+ assign inv_sbox[8'hf4] = 8'hba;
+ assign inv_sbox[8'hf5] = 8'h77;
+ assign inv_sbox[8'hf6] = 8'hd6;
+ assign inv_sbox[8'hf7] = 8'h26;
+ assign inv_sbox[8'hf8] = 8'he1;
+ assign inv_sbox[8'hf9] = 8'h69;
+ assign inv_sbox[8'hfa] = 8'h14;
+ assign inv_sbox[8'hfb] = 8'h63;
+ assign inv_sbox[8'hfc] = 8'h55;
+ assign inv_sbox[8'hfd] = 8'h21;
+ assign inv_sbox[8'hfe] = 8'h0c;
+ assign inv_sbox[8'hff] = 8'h7d;
+
+ assign new_sword[31 : 24] = inv_sbox[sword[31 : 24]];
+ assign new_sword[23 : 16] = inv_sbox[sword[23 : 16]];
+ assign new_sword[15 : 08] = inv_sbox[sword[15 : 08]];
+ assign new_sword[07 : 00] = inv_sbox[sword[07 : 00]];
+
+endmodule // aes_inv_sbox
+
+//======================================================================
+// EOF aes_inv_sbox.v
+//======================================================================
diff --git a/cipher/aes/src/rtl/aes_key_mem.v b/cipher/aes/src/rtl/aes_key_mem.v
new file mode 100644
index 0000000..e681c93
--- /dev/null
+++ b/cipher/aes/src/rtl/aes_key_mem.v
@@ -0,0 +1,479 @@
+//======================================================================
+//
+// aes_key_mem.v
+// -------------
+// The AES key memort including round key generator.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module aes_key_mem(
+ input wire clk,
+ input wire reset_n,
+
+ input wire [255 : 0] key,
+ input wire keylen,
+ input wire init,
+
+ input wire [3 : 0] round,
+ output wire [127 : 0] round_key,
+ output wire ready,
+
+
+ output wire [31 : 0] sboxw,
+ input wire [31 : 0] new_sboxw
+ );
+
+
+ //----------------------------------------------------------------
+ // Parameters.
+ //----------------------------------------------------------------
+ parameter AES_128_BIT_KEY = 1'h0;
+ parameter AES_256_BIT_KEY = 1'h1;
+
+ parameter AES_128_NUM_ROUNDS = 4'ha;
+ parameter AES_256_NUM_ROUNDS = 4'he;
+
+ parameter CTRL_IDLE = 3'h0;
+ parameter CTRL_INIT = 3'h1;
+ parameter CTRL_GENERATE = 3'h2;
+ parameter CTRL_DONE = 3'h3;
+
+
+ //----------------------------------------------------------------
+ // Registers.
+ //----------------------------------------------------------------
+ reg [127 : 0] key_mem [0 : 14];
+ reg [127 : 0] key_mem_new;
+ reg key_mem_we;
+
+ reg [127 : 0] prev_key0_reg;
+ reg [127 : 0] prev_key0_new;
+ reg prev_key0_we;
+
+ reg [127 : 0] prev_key1_reg;
+ reg [127 : 0] prev_key1_new;
+ reg prev_key1_we;
+
+ reg [3 : 0] round_ctr_reg;
+ reg [3 : 0] round_ctr_new;
+ reg round_ctr_rst;
+ reg round_ctr_inc;
+ reg round_ctr_we;
+
+ reg [2 : 0] key_mem_ctrl_reg;
+ reg [2 : 0] key_mem_ctrl_new;
+ reg key_mem_ctrl_we;
+
+ reg ready_reg;
+ reg ready_new;
+ reg ready_we;
+
+ reg [7 : 0] rcon_reg;
+ reg [7 : 0] rcon_new;
+ reg rcon_we;
+ reg rcon_set;
+ reg rcon_next;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] tmp_sboxw;
+
+ reg round_key_update;
+ reg [3 : 0] num_rounds;
+
+ reg [127 : 0] tmp_round_key;
+
+
+ //----------------------------------------------------------------
+ // Concurrent assignments for ports.
+ //----------------------------------------------------------------
+ assign round_key = tmp_round_key;
+ assign ready = ready_reg;
+ assign sboxw = tmp_sboxw;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin: reg_update
+ if (!reset_n)
+ begin
+ key_mem [0] <= 128'h00000000000000000000000000000000;
+ key_mem [1] <= 128'h00000000000000000000000000000000;
+ key_mem [2] <= 128'h00000000000000000000000000000000;
+ key_mem [3] <= 128'h00000000000000000000000000000000;
+ key_mem [4] <= 128'h00000000000000000000000000000000;
+ key_mem [5] <= 128'h00000000000000000000000000000000;
+ key_mem [6] <= 128'h00000000000000000000000000000000;
+ key_mem [7] <= 128'h00000000000000000000000000000000;
+ key_mem [8] <= 128'h00000000000000000000000000000000;
+ key_mem [9] <= 128'h00000000000000000000000000000000;
+ key_mem [10] <= 128'h00000000000000000000000000000000;
+ key_mem [11] <= 128'h00000000000000000000000000000000;
+ key_mem [12] <= 128'h00000000000000000000000000000000;
+ key_mem [13] <= 128'h00000000000000000000000000000000;
+ key_mem [14] <= 128'h00000000000000000000000000000000;
+ prev_key0_reg <= 128'h00000000000000000000000000000000;
+ prev_key1_reg <= 128'h00000000000000000000000000000000;
+ rcon_reg <= 8'h00;
+ ready_reg <= 0;
+ round_ctr_reg <= 4'h0;
+ key_mem_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ if (round_ctr_we)
+ begin
+ round_ctr_reg <= round_ctr_new;
+ end
+
+ if (ready_we)
+ begin
+ ready_reg <= ready_new;
+ end
+
+ if (rcon_we)
+ begin
+ rcon_reg <= rcon_new;
+ end
+
+ if (key_mem_we)
+ begin
+ key_mem[round_ctr_reg] <= key_mem_new;
+ end
+
+ if (prev_key0_we)
+ begin
+ prev_key0_reg <= prev_key0_new;
+ end
+
+ if (prev_key1_we)
+ begin
+ prev_key1_reg <= prev_key1_new;
+ end
+
+ if (key_mem_ctrl_we)
+ begin
+ key_mem_ctrl_reg <= key_mem_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // key_mem_read
+ //
+ // Combinational read port for the key memory.
+ //----------------------------------------------------------------
+ always @*
+ begin : key_mem_read
+ tmp_round_key = key_mem[round];
+ end // key_mem_read
+
+
+ //----------------------------------------------------------------
+ // round_key_gen
+ //
+ // The round key generator logic for AES-128 and AES-256.
+ //----------------------------------------------------------------
+ always @*
+ begin: round_key_gen
+ reg [31 : 0] w0, w1, w2, w3, w4, w5, w6, w7;
+ reg [31 : 0] k0, k1, k2, k3;
+ reg [31 : 0] rconw, rotstw, tw, trw;
+
+ // Default assignments.
+ key_mem_new = 128'h00000000000000000000000000000000;
+ key_mem_we = 0;
+ prev_key0_new = 128'h00000000000000000000000000000000;
+ prev_key0_we = 0;
+ prev_key1_new = 128'h00000000000000000000000000000000;
+ prev_key1_we = 0;
+
+ k0 = 32'h00000000;
+ k1 = 32'h00000000;
+ k2 = 32'h00000000;
+ k3 = 32'h00000000;
+
+ rcon_set = 1;
+ rcon_next = 0;
+
+ // Extract words and calculate intermediate values.
+ // Perform rotation of sbox word etc.
+ w0 = prev_key0_reg[127 : 096];
+ w1 = prev_key0_reg[095 : 064];
+ w2 = prev_key0_reg[063 : 032];
+ w3 = prev_key0_reg[031 : 000];
+
+ w4 = prev_key1_reg[127 : 096];
+ w5 = prev_key1_reg[095 : 064];
+ w6 = prev_key1_reg[063 : 032];
+ w7 = prev_key1_reg[031 : 000];
+
+ rconw = {rcon_reg, 24'h000000};
+ tmp_sboxw = w7;
+ rotstw = {new_sboxw[23 : 00], new_sboxw[31 : 24]};
+ trw = rotstw ^ rconw;
+ tw = new_sboxw;
+
+ // Generate the specific round keys.
+ if (round_key_update)
+ begin
+ rcon_set = 0;
+ key_mem_we = 1;
+ case (keylen)
+ AES_128_BIT_KEY:
+ begin
+ if (round_ctr_reg == 0)
+ begin
+ key_mem_new = key[255 : 128];
+ prev_key1_new = key[255 : 128];
+ prev_key1_we = 1;
+ rcon_next = 1;
+ end
+ else
+ begin
+ k0 = w4 ^ trw;
+ k1 = w5 ^ w4 ^ trw;
+ k2 = w6 ^ w5 ^ w4 ^ trw;
+ k3 = w7 ^ w6 ^ w5 ^ w4 ^ trw;
+
+ key_mem_new = {k0, k1, k2, k3};
+ prev_key1_new = {k0, k1, k2, k3};
+ prev_key1_we = 1;
+ rcon_next = 1;
+ end
+ end
+
+ AES_256_BIT_KEY:
+ begin
+ if (round_ctr_reg == 0)
+ begin
+ key_mem_new = key[255 : 128];
+ prev_key0_new = key[255 : 128];
+ prev_key0_we = 1;
+ end
+ else if (round_ctr_reg == 1)
+ begin
+ key_mem_new = key[127 : 0];
+ prev_key1_new = key[127 : 0];
+ prev_key1_we = 1;
+ rcon_next = 1;
+ end
+ else
+ begin
+ if (round_ctr_reg[0] == 0)
+ begin
+ k0 = w0 ^ trw;
+ k1 = w1 ^ w0 ^ trw;
+ k2 = w2 ^ w1 ^ w0 ^ trw;
+ k3 = w3 ^ w2 ^ w1 ^ w0 ^ trw;
+ end
+ else
+ begin
+ k0 = w0 ^ tw;
+ k1 = w1 ^ w0 ^ tw;
+ k2 = w2 ^ w1 ^ w0 ^ tw;
+ k3 = w3 ^ w2 ^ w1 ^ w0 ^ tw;
+ rcon_next = 1;
+ end
+
+ // Store the generated round keys.
+ key_mem_new = {k0, k1, k2, k3};
+ prev_key1_new = {k0, k1, k2, k3};
+ prev_key1_we = 1;
+ prev_key0_new = prev_key1_reg;
+ prev_key0_we = 1;
+ end
+ end
+
+ default:
+ begin
+ end
+ endcase // case (keylen)
+ end
+ end // round_key_gen
+
+
+ //----------------------------------------------------------------
+ // rcon_logic
+ //
+ // Caclulates the rcon value for the different key expansion
+ // iterations.
+ //----------------------------------------------------------------
+ always @*
+ begin : rcon_logic
+ reg [7 : 0] tmp_rcon;
+ rcon_new = 8'h00;
+ rcon_we = 0;
+
+ tmp_rcon = {rcon_reg[6 : 0], 1'b0} ^ (8'h1b & {8{rcon_reg[7]}});
+
+ if (rcon_set)
+ begin
+ rcon_new = 8'h8d;
+ rcon_we = 1;
+ end
+
+ if (rcon_next)
+ begin
+ rcon_new = tmp_rcon[7 : 0];
+ rcon_we = 1;
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // round_ctr
+ //
+ // The round counter logic with increase and reset.
+ //----------------------------------------------------------------
+ always @*
+ begin : round_ctr
+ round_ctr_new = 4'h0;
+ round_ctr_we = 0;
+
+ if (round_ctr_rst)
+ begin
+ round_ctr_new = 4'h0;
+ round_ctr_we = 1;
+ end
+
+ else if (round_ctr_inc)
+ begin
+ round_ctr_new = round_ctr_reg + 1'b1;
+ round_ctr_we = 1;
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // num_rounds_logic
+ //
+ // Logic to select the number of rounds to generate keys for
+ //----------------------------------------------------------------
+ always @*
+ begin : num_rounds_logic
+ num_rounds = 4'h0;
+
+ case (keylen)
+ AES_128_BIT_KEY:
+ begin
+ num_rounds = AES_128_NUM_ROUNDS;
+ end
+
+ AES_256_BIT_KEY:
+ begin
+ num_rounds = AES_256_NUM_ROUNDS;
+ end
+
+ default:
+ begin
+ end
+ endcase // case (keylen)
+ end
+
+
+ //----------------------------------------------------------------
+ // key_mem_ctrl
+ //
+ //
+ // The FSM that controls the round key generation.
+ //----------------------------------------------------------------
+ always @*
+ begin: key_mem_ctrl
+ // Default assignments.
+ ready_new = 0;
+ ready_we = 0;
+ round_key_update = 0;
+ round_ctr_rst = 0;
+ round_ctr_inc = 0;
+ key_mem_ctrl_new = CTRL_IDLE;
+ key_mem_ctrl_we = 0;
+
+ case(key_mem_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (init)
+ begin
+ ready_new = 0;
+ ready_we = 1;
+ key_mem_ctrl_new = CTRL_INIT;
+ key_mem_ctrl_we = 1;
+ end
+ end
+
+ CTRL_INIT:
+ begin
+ round_ctr_rst = 1;
+ key_mem_ctrl_new = CTRL_GENERATE;
+ key_mem_ctrl_we = 1;
+ end
+
+ CTRL_GENERATE:
+ begin
+ round_ctr_inc = 1;
+ round_key_update = 1;
+ if (round_ctr_reg == num_rounds)
+ begin
+ key_mem_ctrl_new = CTRL_DONE;
+ key_mem_ctrl_we = 1;
+ end
+ end
+
+ CTRL_DONE:
+ begin
+ ready_new = 1;
+ ready_we = 1;
+ key_mem_ctrl_new = CTRL_IDLE;
+ key_mem_ctrl_we = 1;
+ end
+
+ default:
+ begin
+ end
+ endcase // case (key_mem_ctrl_reg)
+
+ end // key_mem_ctrl
+endmodule // aes_key_mem
+
+//======================================================================
+// EOF aes_key_mem.v
+//======================================================================
diff --git a/cipher/aes/src/rtl/aes_sbox.v b/cipher/aes/src/rtl/aes_sbox.v
new file mode 100644
index 0000000..47e9569
--- /dev/null
+++ b/cipher/aes/src/rtl/aes_sbox.v
@@ -0,0 +1,321 @@
+//======================================================================
+//
+// aes_sbox.v
+// ----------
+// The AES S-box. Basically a 256 Byte ROM. This implementation
+// contains four parallel S-boxes to handle a 32 bit word.
+//
+//
+// Copyright (c) 2013 Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module aes_sbox(
+ input wire [31 : 0] sboxw,
+ output wire [31 : 0] new_sboxw
+ );
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ wire [7 : 0] sbox [0 : 255];
+
+
+ //----------------------------------------------------------------
+ // Concurrent assignments for ports.
+ //----------------------------------------------------------------
+ assign sbox[8'h00] = 8'h63;
+ assign sbox[8'h01] = 8'h7c;
+ assign sbox[8'h02] = 8'h77;
+ assign sbox[8'h03] = 8'h7b;
+ assign sbox[8'h04] = 8'hf2;
+ assign sbox[8'h05] = 8'h6b;
+ assign sbox[8'h06] = 8'h6f;
+ assign sbox[8'h07] = 8'hc5;
+ assign sbox[8'h08] = 8'h30;
+ assign sbox[8'h09] = 8'h01;
+ assign sbox[8'h0a] = 8'h67;
+ assign sbox[8'h0b] = 8'h2b;
+ assign sbox[8'h0c] = 8'hfe;
+ assign sbox[8'h0d] = 8'hd7;
+ assign sbox[8'h0e] = 8'hab;
+ assign sbox[8'h0f] = 8'h76;
+ assign sbox[8'h10] = 8'hca;
+ assign sbox[8'h11] = 8'h82;
+ assign sbox[8'h12] = 8'hc9;
+ assign sbox[8'h13] = 8'h7d;
+ assign sbox[8'h14] = 8'hfa;
+ assign sbox[8'h15] = 8'h59;
+ assign sbox[8'h16] = 8'h47;
+ assign sbox[8'h17] = 8'hf0;
+ assign sbox[8'h18] = 8'had;
+ assign sbox[8'h19] = 8'hd4;
+ assign sbox[8'h1a] = 8'ha2;
+ assign sbox[8'h1b] = 8'haf;
+ assign sbox[8'h1c] = 8'h9c;
+ assign sbox[8'h1d] = 8'ha4;
+ assign sbox[8'h1e] = 8'h72;
+ assign sbox[8'h1f] = 8'hc0;
+ assign sbox[8'h20] = 8'hb7;
+ assign sbox[8'h21] = 8'hfd;
+ assign sbox[8'h22] = 8'h93;
+ assign sbox[8'h23] = 8'h26;
+ assign sbox[8'h24] = 8'h36;
+ assign sbox[8'h25] = 8'h3f;
+ assign sbox[8'h26] = 8'hf7;
+ assign sbox[8'h27] = 8'hcc;
+ assign sbox[8'h28] = 8'h34;
+ assign sbox[8'h29] = 8'ha5;
+ assign sbox[8'h2a] = 8'he5;
+ assign sbox[8'h2b] = 8'hf1;
+ assign sbox[8'h2c] = 8'h71;
+ assign sbox[8'h2d] = 8'hd8;
+ assign sbox[8'h2e] = 8'h31;
+ assign sbox[8'h2f] = 8'h15;
+ assign sbox[8'h30] = 8'h04;
+ assign sbox[8'h31] = 8'hc7;
+ assign sbox[8'h32] = 8'h23;
+ assign sbox[8'h33] = 8'hc3;
+ assign sbox[8'h34] = 8'h18;
+ assign sbox[8'h35] = 8'h96;
+ assign sbox[8'h36] = 8'h05;
+ assign sbox[8'h37] = 8'h9a;
+ assign sbox[8'h38] = 8'h07;
+ assign sbox[8'h39] = 8'h12;
+ assign sbox[8'h3a] = 8'h80;
+ assign sbox[8'h3b] = 8'he2;
+ assign sbox[8'h3c] = 8'heb;
+ assign sbox[8'h3d] = 8'h27;
+ assign sbox[8'h3e] = 8'hb2;
+ assign sbox[8'h3f] = 8'h75;
+ assign sbox[8'h40] = 8'h09;
+ assign sbox[8'h41] = 8'h83;
+ assign sbox[8'h42] = 8'h2c;
+ assign sbox[8'h43] = 8'h1a;
+ assign sbox[8'h44] = 8'h1b;
+ assign sbox[8'h45] = 8'h6e;
+ assign sbox[8'h46] = 8'h5a;
+ assign sbox[8'h47] = 8'ha0;
+ assign sbox[8'h48] = 8'h52;
+ assign sbox[8'h49] = 8'h3b;
+ assign sbox[8'h4a] = 8'hd6;
+ assign sbox[8'h4b] = 8'hb3;
+ assign sbox[8'h4c] = 8'h29;
+ assign sbox[8'h4d] = 8'he3;
+ assign sbox[8'h4e] = 8'h2f;
+ assign sbox[8'h4f] = 8'h84;
+ assign sbox[8'h50] = 8'h53;
+ assign sbox[8'h51] = 8'hd1;
+ assign sbox[8'h52] = 8'h00;
+ assign sbox[8'h53] = 8'hed;
+ assign sbox[8'h54] = 8'h20;
+ assign sbox[8'h55] = 8'hfc;
+ assign sbox[8'h56] = 8'hb1;
+ assign sbox[8'h57] = 8'h5b;
+ assign sbox[8'h58] = 8'h6a;
+ assign sbox[8'h59] = 8'hcb;
+ assign sbox[8'h5a] = 8'hbe;
+ assign sbox[8'h5b] = 8'h39;
+ assign sbox[8'h5c] = 8'h4a;
+ assign sbox[8'h5d] = 8'h4c;
+ assign sbox[8'h5e] = 8'h58;
+ assign sbox[8'h5f] = 8'hcf;
+ assign sbox[8'h60] = 8'hd0;
+ assign sbox[8'h61] = 8'hef;
+ assign sbox[8'h62] = 8'haa;
+ assign sbox[8'h63] = 8'hfb;
+ assign sbox[8'h64] = 8'h43;
+ assign sbox[8'h65] = 8'h4d;
+ assign sbox[8'h66] = 8'h33;
+ assign sbox[8'h67] = 8'h85;
+ assign sbox[8'h68] = 8'h45;
+ assign sbox[8'h69] = 8'hf9;
+ assign sbox[8'h6a] = 8'h02;
+ assign sbox[8'h6b] = 8'h7f;
+ assign sbox[8'h6c] = 8'h50;
+ assign sbox[8'h6d] = 8'h3c;
+ assign sbox[8'h6e] = 8'h9f;
+ assign sbox[8'h6f] = 8'ha8;
+ assign sbox[8'h70] = 8'h51;
+ assign sbox[8'h71] = 8'ha3;
+ assign sbox[8'h72] = 8'h40;
+ assign sbox[8'h73] = 8'h8f;
+ assign sbox[8'h74] = 8'h92;
+ assign sbox[8'h75] = 8'h9d;
+ assign sbox[8'h76] = 8'h38;
+ assign sbox[8'h77] = 8'hf5;
+ assign sbox[8'h78] = 8'hbc;
+ assign sbox[8'h79] = 8'hb6;
+ assign sbox[8'h7a] = 8'hda;
+ assign sbox[8'h7b] = 8'h21;
+ assign sbox[8'h7c] = 8'h10;
+ assign sbox[8'h7d] = 8'hff;
+ assign sbox[8'h7e] = 8'hf3;
+ assign sbox[8'h7f] = 8'hd2;
+ assign sbox[8'h80] = 8'hcd;
+ assign sbox[8'h81] = 8'h0c;
+ assign sbox[8'h82] = 8'h13;
+ assign sbox[8'h83] = 8'hec;
+ assign sbox[8'h84] = 8'h5f;
+ assign sbox[8'h85] = 8'h97;
+ assign sbox[8'h86] = 8'h44;
+ assign sbox[8'h87] = 8'h17;
+ assign sbox[8'h88] = 8'hc4;
+ assign sbox[8'h89] = 8'ha7;
+ assign sbox[8'h8a] = 8'h7e;
+ assign sbox[8'h8b] = 8'h3d;
+ assign sbox[8'h8c] = 8'h64;
+ assign sbox[8'h8d] = 8'h5d;
+ assign sbox[8'h8e] = 8'h19;
+ assign sbox[8'h8f] = 8'h73;
+ assign sbox[8'h90] = 8'h60;
+ assign sbox[8'h91] = 8'h81;
+ assign sbox[8'h92] = 8'h4f;
+ assign sbox[8'h93] = 8'hdc;
+ assign sbox[8'h94] = 8'h22;
+ assign sbox[8'h95] = 8'h2a;
+ assign sbox[8'h96] = 8'h90;
+ assign sbox[8'h97] = 8'h88;
+ assign sbox[8'h98] = 8'h46;
+ assign sbox[8'h99] = 8'hee;
+ assign sbox[8'h9a] = 8'hb8;
+ assign sbox[8'h9b] = 8'h14;
+ assign sbox[8'h9c] = 8'hde;
+ assign sbox[8'h9d] = 8'h5e;
+ assign sbox[8'h9e] = 8'h0b;
+ assign sbox[8'h9f] = 8'hdb;
+ assign sbox[8'ha0] = 8'he0;
+ assign sbox[8'ha1] = 8'h32;
+ assign sbox[8'ha2] = 8'h3a;
+ assign sbox[8'ha3] = 8'h0a;
+ assign sbox[8'ha4] = 8'h49;
+ assign sbox[8'ha5] = 8'h06;
+ assign sbox[8'ha6] = 8'h24;
+ assign sbox[8'ha7] = 8'h5c;
+ assign sbox[8'ha8] = 8'hc2;
+ assign sbox[8'ha9] = 8'hd3;
+ assign sbox[8'haa] = 8'hac;
+ assign sbox[8'hab] = 8'h62;
+ assign sbox[8'hac] = 8'h91;
+ assign sbox[8'had] = 8'h95;
+ assign sbox[8'hae] = 8'he4;
+ assign sbox[8'haf] = 8'h79;
+ assign sbox[8'hb0] = 8'he7;
+ assign sbox[8'hb1] = 8'hc8;
+ assign sbox[8'hb2] = 8'h37;
+ assign sbox[8'hb3] = 8'h6d;
+ assign sbox[8'hb4] = 8'h8d;
+ assign sbox[8'hb5] = 8'hd5;
+ assign sbox[8'hb6] = 8'h4e;
+ assign sbox[8'hb7] = 8'ha9;
+ assign sbox[8'hb8] = 8'h6c;
+ assign sbox[8'hb9] = 8'h56;
+ assign sbox[8'hba] = 8'hf4;
+ assign sbox[8'hbb] = 8'hea;
+ assign sbox[8'hbc] = 8'h65;
+ assign sbox[8'hbd] = 8'h7a;
+ assign sbox[8'hbe] = 8'hae;
+ assign sbox[8'hbf] = 8'h08;
+ assign sbox[8'hc0] = 8'hba;
+ assign sbox[8'hc1] = 8'h78;
+ assign sbox[8'hc2] = 8'h25;
+ assign sbox[8'hc3] = 8'h2e;
+ assign sbox[8'hc4] = 8'h1c;
+ assign sbox[8'hc5] = 8'ha6;
+ assign sbox[8'hc6] = 8'hb4;
+ assign sbox[8'hc7] = 8'hc6;
+ assign sbox[8'hc8] = 8'he8;
+ assign sbox[8'hc9] = 8'hdd;
+ assign sbox[8'hca] = 8'h74;
+ assign sbox[8'hcb] = 8'h1f;
+ assign sbox[8'hcc] = 8'h4b;
+ assign sbox[8'hcd] = 8'hbd;
+ assign sbox[8'hce] = 8'h8b;
+ assign sbox[8'hcf] = 8'h8a;
+ assign sbox[8'hd0] = 8'h70;
+ assign sbox[8'hd1] = 8'h3e;
+ assign sbox[8'hd2] = 8'hb5;
+ assign sbox[8'hd3] = 8'h66;
+ assign sbox[8'hd4] = 8'h48;
+ assign sbox[8'hd5] = 8'h03;
+ assign sbox[8'hd6] = 8'hf6;
+ assign sbox[8'hd7] = 8'h0e;
+ assign sbox[8'hd8] = 8'h61;
+ assign sbox[8'hd9] = 8'h35;
+ assign sbox[8'hda] = 8'h57;
+ assign sbox[8'hdb] = 8'hb9;
+ assign sbox[8'hdc] = 8'h86;
+ assign sbox[8'hdd] = 8'hc1;
+ assign sbox[8'hde] = 8'h1d;
+ assign sbox[8'hdf] = 8'h9e;
+ assign sbox[8'he0] = 8'he1;
+ assign sbox[8'he1] = 8'hf8;
+ assign sbox[8'he2] = 8'h98;
+ assign sbox[8'he3] = 8'h11;
+ assign sbox[8'he4] = 8'h69;
+ assign sbox[8'he5] = 8'hd9;
+ assign sbox[8'he6] = 8'h8e;
+ assign sbox[8'he7] = 8'h94;
+ assign sbox[8'he8] = 8'h9b;
+ assign sbox[8'he9] = 8'h1e;
+ assign sbox[8'hea] = 8'h87;
+ assign sbox[8'heb] = 8'he9;
+ assign sbox[8'hec] = 8'hce;
+ assign sbox[8'hed] = 8'h55;
+ assign sbox[8'hee] = 8'h28;
+ assign sbox[8'hef] = 8'hdf;
+ assign sbox[8'hf0] = 8'h8c;
+ assign sbox[8'hf1] = 8'ha1;
+ assign sbox[8'hf2] = 8'h89;
+ assign sbox[8'hf3] = 8'h0d;
+ assign sbox[8'hf4] = 8'hbf;
+ assign sbox[8'hf5] = 8'he6;
+ assign sbox[8'hf6] = 8'h42;
+ assign sbox[8'hf7] = 8'h68;
+ assign sbox[8'hf8] = 8'h41;
+ assign sbox[8'hf9] = 8'h99;
+ assign sbox[8'hfa] = 8'h2d;
+ assign sbox[8'hfb] = 8'h0f;
+ assign sbox[8'hfc] = 8'hb0;
+ assign sbox[8'hfd] = 8'h54;
+ assign sbox[8'hfe] = 8'hbb;
+ assign sbox[8'hff] = 8'h16;
+
+
+ assign new_sboxw[31 : 24] = sbox[sboxw[31 : 24]];
+ assign new_sboxw[23 : 16] = sbox[sboxw[23 : 16]];
+ assign new_sboxw[15 : 08] = sbox[sboxw[15 : 08]];
+ assign new_sboxw[07 : 00] = sbox[sboxw[07 : 00]];
+
+endmodule // aes_sbox
+
+//======================================================================
+// EOF aes_sbox.v
+//======================================================================
diff --git a/cipher/aes/src/tb/tb_aes.v b/cipher/aes/src/tb/tb_aes.v
new file mode 100644
index 0000000..4413ded
--- /dev/null
+++ b/cipher/aes/src/tb/tb_aes.v
@@ -0,0 +1,553 @@
+//======================================================================
+//
+// tb_aes.v
+// --------
+// Testbench for the aes top level wrapper.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_aes();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+ // The DUT address map.
+ parameter ADDR_NAME0 = 8'h00;
+ parameter ADDR_NAME1 = 8'h01;
+ parameter ADDR_VERSION = 8'h02;
+
+ parameter ADDR_CTRL = 8'h08;
+ parameter CTRL_INIT_BIT = 0;
+ parameter CTRL_NEXT_BIT = 1;
+ parameter CTRL_ENCDEC_BIT = 2;
+ parameter CTRL_KEYLEN_BIT = 3;
+
+ parameter ADDR_CONFIG = 8'h09;
+
+ parameter ADDR_STATUS = 8'h0a;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_KEY0 = 8'h10;
+ parameter ADDR_KEY1 = 8'h11;
+ parameter ADDR_KEY2 = 8'h12;
+ parameter ADDR_KEY3 = 8'h13;
+ parameter ADDR_KEY4 = 8'h14;
+ parameter ADDR_KEY5 = 8'h15;
+ parameter ADDR_KEY6 = 8'h16;
+ parameter ADDR_KEY7 = 8'h17;
+
+ parameter ADDR_BLOCK0 = 8'h20;
+ parameter ADDR_BLOCK1 = 8'h21;
+ parameter ADDR_BLOCK2 = 8'h22;
+ parameter ADDR_BLOCK3 = 8'h23;
+
+ parameter ADDR_RESULT0 = 8'h30;
+ parameter ADDR_RESULT1 = 8'h31;
+ parameter ADDR_RESULT2 = 8'h32;
+ parameter ADDR_RESULT3 = 8'h33;
+
+ parameter AES_128_BIT_KEY = 0;
+ parameter AES_256_BIT_KEY = 1;
+
+ parameter AES_DECIPHER = 1'b0;
+ parameter AES_ENCIPHER = 1'b1;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg [31 : 0] read_data;
+ reg [127 : 0] result_data;
+
+ reg tb_clk;
+ reg tb_reset_n;
+ reg tb_cs;
+ reg tb_we;
+ reg [7 : 0] tb_address;
+ reg [31 : 0] tb_write_data;
+ wire [31 : 0] tb_read_data;
+ wire tb_error;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ aes dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+ .cs(tb_cs),
+ .we(tb_we),
+ .address(tb_address),
+ .write_data(tb_write_data),
+ .read_data(tb_read_data),
+ .error(tb_error)
+ );
+
+
+ //----------------------------------------------------------------
+ // Concurrent assignments.
+ //----------------------------------------------------------------
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Always running clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD;
+ tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor()
+ //
+ // An always running process that creates a cycle counter and
+ // conditionally displays information about the DUT.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ cycle_ctr = cycle_ctr + 1;
+
+ #(CLK_PERIOD);
+
+ if (DEBUG)
+ begin
+ dump_dut_state();
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state();
+ begin
+ $display("cycle: 0x%016x", cycle_ctr);
+ $display("State of DUT");
+ $display("------------");
+ $display("ctrl_reg: init = 0x%01x, next = 0x%01x", dut.init_reg, dut.next_reg);
+ $display("config_reg: encdec = 0x%01x, length = 0x%01x ", dut.encdec_reg, dut.keylen_reg);
+ $display("");
+
+ $display("block: 0x%08x, 0x%08x, 0x%08x, 0x%08x",
+ dut.block0_reg, dut.block1_reg, dut.block2_reg, dut.block3_reg);
+ $display("");
+
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggle reset to put the DUT into a well known state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+
+ #(2 * CLK_PERIOD);
+ tb_reset_n = 1;
+ $display("");
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // display_test_results()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_results();
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %02d test cases completed successfully", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d tests completed - %02d test cases did not complete successfully.",
+ tc_ctr, error_ctr);
+ end
+ end
+ endtask // display_test_results
+
+
+ //----------------------------------------------------------------
+ // init_sim()
+ //
+ // Initialize all counters and testbed functionality as well
+ // as setting the DUT inputs to defined values.
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+
+ tb_cs = 0;
+ tb_we = 0;
+ tb_address = 8'h00;
+ tb_write_data = 32'h00000000;
+ end
+ endtask // init_sim
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [11 : 0] address,
+ input [31 : 0] word);
+ begin
+ if (DEBUG)
+ begin
+ $display("*** Writing 0x%08x to 0x%02x.", word, address);
+ $display("");
+ end
+
+ tb_address = address;
+ tb_write_data = word;
+ tb_cs = 1;
+ tb_we = 1;
+ #(2 * CLK_PERIOD);
+ tb_cs = 0;
+ tb_we = 0;
+ end
+ endtask // write_word
+
+
+ //----------------------------------------------------------------
+ // write_block()
+ //
+ // Write the given block to the dut.
+ //----------------------------------------------------------------
+ task write_block(input [127 : 0] block);
+ begin
+ write_word(ADDR_BLOCK0, block[127 : 96]);
+ write_word(ADDR_BLOCK1, block[95 : 64]);
+ write_word(ADDR_BLOCK2, block[63 : 32]);
+ write_word(ADDR_BLOCK3, block[31 : 0]);
+ end
+ endtask // write_block
+
+
+ //----------------------------------------------------------------
+ // read_word()
+ //
+ // Read a data word from the given address in the DUT.
+ // the word read will be available in the global variable
+ // read_data.
+ //----------------------------------------------------------------
+ task read_word(input [11 : 0] address);
+ begin
+ tb_address = address;
+ tb_cs = 1;
+ tb_we = 0;
+ #(CLK_PERIOD);
+ read_data = tb_read_data;
+ tb_cs = 0;
+
+ if (DEBUG)
+ begin
+ $display("*** Reading 0x%08x from 0x%02x.", read_data, address);
+ $display("");
+ end
+ end
+ endtask // read_word
+
+
+ //----------------------------------------------------------------
+ // read_result()
+ //
+ // Read the result block in the dut.
+ //----------------------------------------------------------------
+ task read_result();
+ begin
+ read_word(ADDR_RESULT0);
+ result_data[127 : 096] = read_data;
+ read_word(ADDR_RESULT1);
+ result_data[095 : 064] = read_data;
+ read_word(ADDR_RESULT2);
+ result_data[063 : 032] = read_data;
+ read_word(ADDR_RESULT3);
+ result_data[031 : 000] = read_data;
+ end
+ endtask // read_result
+
+
+ //----------------------------------------------------------------
+ // init_key()
+ //
+ // init the key in the dut by writing the given key and
+ // key length and then trigger init processing.
+ //----------------------------------------------------------------
+ task init_key(input [255 : 0] key, input key_length);
+ begin
+ if (DEBUG)
+ begin
+ $display("key length: 0x%01x", key_length);
+ $display("Initializing key expansion for key: 0x%016x", key);
+ end
+
+ write_word(ADDR_KEY0, key[255 : 224]);
+ write_word(ADDR_KEY1, key[223 : 192]);
+ write_word(ADDR_KEY2, key[191 : 160]);
+ write_word(ADDR_KEY3, key[159 : 128]);
+ write_word(ADDR_KEY4, key[127 : 96]);
+ write_word(ADDR_KEY5, key[95 : 64]);
+ write_word(ADDR_KEY6, key[63 : 32]);
+ write_word(ADDR_KEY7, key[31 : 0]);
+
+ if (key_length)
+ begin
+ write_word(ADDR_CONFIG, 8'h02);
+ end
+ else
+ begin
+ write_word(ADDR_CONFIG, 8'h00);
+ end
+
+ write_word(ADDR_CTRL, 8'h01);
+
+ #(100 * CLK_PERIOD);
+ end
+ endtask // init_key
+
+
+ //----------------------------------------------------------------
+ // ecb_mode_single_block_test()
+ //
+ // Perform ECB mode encryption or decryption single block test.
+ //----------------------------------------------------------------
+ task ecb_mode_single_block_test(input [7 : 0] tc_number,
+ input encdec,
+ input [255 : 0] key,
+ input key_length,
+ input [127 : 0] block,
+ input [127 : 0] expected);
+ begin
+ $display("*** TC %0d ECB mode test started.", tc_number);
+ tc_ctr = tc_ctr + 1;
+
+ init_key(key, key_length);
+ write_block(block);
+ dump_dut_state();
+
+ write_word(ADDR_CONFIG, (8'h00 + (key_length << 1)+ encdec));
+ write_word(ADDR_CTRL, 8'h02);
+
+ #(100 * CLK_PERIOD);
+
+ read_result();
+
+ if (result_data == expected)
+ begin
+ $display("*** TC %0d successful.", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d NOT successful.", tc_number);
+ $display("Expected: 0x%032x", expected);
+ $display("Got: 0x%032x", result_data);
+ $display("");
+
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // ecb_mode_single_block_test
+
+
+ //----------------------------------------------------------------
+ // aes_test()
+ //
+ // Main test task will perform complete NIST test of AES.
+ //----------------------------------------------------------------
+ task aes_test();
+ reg [255 : 0] nist_aes128_key;
+ reg [255 : 0] nist_aes256_key;
+
+ reg [127 : 0] nist_plaintext0;
+ reg [127 : 0] nist_plaintext1;
+ reg [127 : 0] nist_plaintext2;
+ reg [127 : 0] nist_plaintext3;
+
+ reg [127 : 0] nist_ecb_128_enc_expected0;
+ reg [127 : 0] nist_ecb_128_enc_expected1;
+ reg [127 : 0] nist_ecb_128_enc_expected2;
+ reg [127 : 0] nist_ecb_128_enc_expected3;
+
+ reg [127 : 0] nist_ecb_256_enc_expected0;
+ reg [127 : 0] nist_ecb_256_enc_expected1;
+ reg [127 : 0] nist_ecb_256_enc_expected2;
+ reg [127 : 0] nist_ecb_256_enc_expected3;
+
+ begin
+ nist_aes128_key = 256'h2b7e151628aed2a6abf7158809cf4f3c00000000000000000000000000000000;
+ nist_aes256_key = 256'h603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4;
+
+ nist_plaintext0 = 128'h6bc1bee22e409f96e93d7e117393172a;
+ nist_plaintext1 = 128'hae2d8a571e03ac9c9eb76fac45af8e51;
+ nist_plaintext2 = 128'h30c81c46a35ce411e5fbc1191a0a52ef;
+ nist_plaintext3 = 128'hf69f2445df4f9b17ad2b417be66c3710;
+
+ nist_ecb_128_enc_expected0 = 128'h3ad77bb40d7a3660a89ecaf32466ef97;
+ nist_ecb_128_enc_expected1 = 128'hf5d3d58503b9699de785895a96fdbaaf;
+ nist_ecb_128_enc_expected2 = 128'h43b1cd7f598ece23881b00e3ed030688;
+ nist_ecb_128_enc_expected3 = 128'h7b0c785e27e8ad3f8223207104725dd4;
+
+ nist_ecb_256_enc_expected0 = 128'hf3eed1bdb5d2a03c064b5a7e3db181f8;
+ nist_ecb_256_enc_expected1 = 128'h591ccb10d410ed26dc5ba74a31362870;
+ nist_ecb_256_enc_expected2 = 128'hb6ed21b99ca6f4f9f153e7b1beafed1d;
+ nist_ecb_256_enc_expected3 = 128'h23304b7a39f9f3ff067d8d8f9e24ecc7;
+
+
+ $display("ECB 128 bit key tests");
+ $display("---------------------");
+ ecb_mode_single_block_test(8'h01, AES_ENCIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_plaintext0, nist_ecb_128_enc_expected0);
+
+ ecb_mode_single_block_test(8'h02, AES_ENCIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_plaintext1, nist_ecb_128_enc_expected1);
+
+ ecb_mode_single_block_test(8'h03, AES_ENCIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_plaintext2, nist_ecb_128_enc_expected2);
+
+ ecb_mode_single_block_test(8'h04, AES_ENCIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_plaintext3, nist_ecb_128_enc_expected3);
+
+
+ ecb_mode_single_block_test(8'h05, AES_DECIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_ecb_128_enc_expected0, nist_plaintext0);
+
+ ecb_mode_single_block_test(8'h06, AES_DECIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_ecb_128_enc_expected1, nist_plaintext1);
+
+ ecb_mode_single_block_test(8'h07, AES_DECIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_ecb_128_enc_expected2, nist_plaintext2);
+
+ ecb_mode_single_block_test(8'h08, AES_DECIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_ecb_128_enc_expected3, nist_plaintext3);
+
+
+ $display("");
+ $display("ECB 256 bit key tests");
+ $display("---------------------");
+ ecb_mode_single_block_test(8'h10, AES_ENCIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_plaintext0, nist_ecb_256_enc_expected0);
+
+ ecb_mode_single_block_test(8'h11, AES_ENCIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_plaintext1, nist_ecb_256_enc_expected1);
+
+ ecb_mode_single_block_test(8'h12, AES_ENCIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_plaintext2, nist_ecb_256_enc_expected2);
+
+ ecb_mode_single_block_test(8'h13, AES_ENCIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_plaintext3, nist_ecb_256_enc_expected3);
+
+
+ ecb_mode_single_block_test(8'h14, AES_DECIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_ecb_256_enc_expected0, nist_plaintext0);
+
+ ecb_mode_single_block_test(8'h15, AES_DECIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_ecb_256_enc_expected1, nist_plaintext1);
+
+ ecb_mode_single_block_test(8'h16, AES_DECIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_ecb_256_enc_expected2, nist_plaintext2);
+
+ ecb_mode_single_block_test(8'h17, AES_DECIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_ecb_256_enc_expected3, nist_plaintext3);
+ end
+ endtask // aes_test
+
+
+ //----------------------------------------------------------------
+ // main
+ //
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : main
+
+ $display(" -= Testbench for AES started =-");
+ $display(" ==============================");
+ $display("");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+ aes_test();
+
+ display_test_results();
+
+ $display("");
+ $display("*** AES simulation done. ***");
+ $finish;
+ end // main
+endmodule // tb_aes
+
+//======================================================================
+// EOF tb_aes.v
+//======================================================================
diff --git a/cipher/aes/src/tb/tb_aes_core.v b/cipher/aes/src/tb/tb_aes_core.v
new file mode 100644
index 0000000..426e817
--- /dev/null
+++ b/cipher/aes/src/tb/tb_aes_core.v
@@ -0,0 +1,469 @@
+//======================================================================
+//
+// tb_aes_core.v
+// -------------
+// Testbench for the AES block cipher core.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_aes_core();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+ parameter DUMP_WAIT = 0;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+ parameter AES_128_BIT_KEY = 0;
+ parameter AES_256_BIT_KEY = 1;
+
+ parameter AES_DECIPHER = 1'b0;
+ parameter AES_ENCIPHER = 1'b1;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg tb_clk;
+ reg tb_reset_n;
+ reg tb_encdec;
+ reg tb_init;
+ reg tb_next;
+ wire tb_ready;
+ reg [255 : 0] tb_key;
+ reg tb_keylen;
+ reg [127 : 0] tb_block;
+ wire [127 : 0] tb_result;
+ wire tb_result_valid;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ aes_core dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .encdec(tb_encdec),
+ .init(tb_init),
+ .next(tb_next),
+ .ready(tb_ready),
+
+ .key(tb_key),
+ .keylen(tb_keylen),
+
+ .block(tb_block),
+ .result(tb_result)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Always running clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD;
+ tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor()
+ //
+ // An always running process that creates a cycle counter and
+ // conditionally displays information about the DUT.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ cycle_ctr = cycle_ctr + 1;
+ #(CLK_PERIOD);
+ if (DEBUG)
+ begin
+ dump_dut_state();
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state();
+ begin
+ $display("State of DUT");
+ $display("------------");
+ $display("Inputs and outputs:");
+ $display("encdec = 0x%01x, init = 0x%01x, next = 0x%01x",
+ dut.encdec, dut.init, dut.next);
+ $display("keylen = 0x%01x, key = 0x%032x ", dut.keylen, dut.key);
+ $display("block = 0x%032x", dut.block);
+ $display("");
+ $display("ready = 0x%01x", dut.ready);
+ $display("result_valid = 0x%01x, result = 0x%032x",
+ dut.result_valid, dut.result);
+ $display("");
+ $display("Encipher state::");
+ $display("enc_ctrl = 0x%01x, round_ctr = 0x%01x",
+ dut.enc_block.enc_ctrl_reg, dut.enc_block.round_ctr_reg);
+ $display("");
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // dump_keys()
+ //
+ // Dump the keys in the key memory of the dut.
+ //----------------------------------------------------------------
+ task dump_keys();
+ begin
+ $display("State of key memory in DUT:");
+ $display("key[00] = 0x%016x", dut.keymem.key_mem[00]);
+ $display("key[01] = 0x%016x", dut.keymem.key_mem[01]);
+ $display("key[02] = 0x%016x", dut.keymem.key_mem[02]);
+ $display("key[03] = 0x%016x", dut.keymem.key_mem[03]);
+ $display("key[04] = 0x%016x", dut.keymem.key_mem[04]);
+ $display("key[05] = 0x%016x", dut.keymem.key_mem[05]);
+ $display("key[06] = 0x%016x", dut.keymem.key_mem[06]);
+ $display("key[07] = 0x%016x", dut.keymem.key_mem[07]);
+ $display("key[08] = 0x%016x", dut.keymem.key_mem[08]);
+ $display("key[09] = 0x%016x", dut.keymem.key_mem[09]);
+ $display("key[10] = 0x%016x", dut.keymem.key_mem[10]);
+ $display("key[11] = 0x%016x", dut.keymem.key_mem[11]);
+ $display("key[12] = 0x%016x", dut.keymem.key_mem[12]);
+ $display("key[13] = 0x%016x", dut.keymem.key_mem[13]);
+ $display("key[14] = 0x%016x", dut.keymem.key_mem[14]);
+ $display("");
+ end
+ endtask // dump_keys
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggle reset to put the DUT into a well known state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(2 * CLK_PERIOD);
+ tb_reset_n = 1;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // init_sim()
+ //
+ // Initialize all counters and testbed functionality as well
+ // as setting the DUT inputs to defined values.
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+ tb_encdec = 0;
+ tb_init = 0;
+ tb_next = 0;
+ tb_key = {8{32'h00000000}};
+ tb_keylen = 0;
+
+ tb_block = {4{32'h00000000}};
+ end
+ endtask // init_sim
+
+
+ //----------------------------------------------------------------
+ // display_test_result()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_result();
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %02d test cases completed successfully", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d tests completed - %02d test cases did not complete successfully.",
+ tc_ctr, error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is actively processing and will in fact at some
+ // point set the flag.
+ //----------------------------------------------------------------
+ task wait_ready();
+ begin
+ while (!tb_ready)
+ begin
+ #(CLK_PERIOD);
+ if (DUMP_WAIT)
+ begin
+ dump_dut_state();
+ end
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // wait_valid()
+ //
+ // Wait for the result_valid flag in the dut to be set.
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is actively processing a block and will in fact
+ // at some point set the flag.
+ //----------------------------------------------------------------
+ task wait_valid();
+ begin
+ while (!tb_result_valid)
+ begin
+ #(CLK_PERIOD);
+ end
+ end
+ endtask // wait_valid
+
+
+ //----------------------------------------------------------------
+ // ecb_mode_single_block_test()
+ //
+ // Perform ECB mode encryption or decryption single block test.
+ //----------------------------------------------------------------
+ task ecb_mode_single_block_test(input [7 : 0] tc_number,
+ input encdec,
+ input [255 : 0] key,
+ input key_length,
+ input [127 : 0] block,
+ input [127 : 0] expected);
+ begin
+ $display("*** TC %0d ECB mode test started.", tc_number);
+ tc_ctr = tc_ctr + 1;
+
+ // Init the cipher with the given key and length.
+ tb_key = key;
+ tb_keylen = key_length;
+ tb_init = 1;
+ #(2 * CLK_PERIOD);
+ tb_init = 0;
+ wait_ready();
+
+ $display("Key expansion done");
+ $display("");
+
+ dump_keys();
+
+
+ // Perform encipher och decipher operation on the block.
+ tb_encdec = encdec;
+ tb_block = block;
+ tb_next = 1;
+ #(2 * CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+
+ if (tb_result == expected)
+ begin
+ $display("*** TC %0d successful.", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d NOT successful.", tc_number);
+ $display("Expected: 0x%032x", expected);
+ $display("Got: 0x%032x", tb_result);
+ $display("");
+
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // ecb_mode_single_block_test
+
+
+ //----------------------------------------------------------------
+ // aes_core_test
+ // The main test functionality.
+ //
+ // Test cases taken from NIST SP 800-38A:
+ // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ //----------------------------------------------------------------
+ initial
+ begin : aes_core_test
+ reg [255 : 0] nist_aes128_key;
+ reg [255 : 0] nist_aes256_key;
+
+ reg [127 : 0] nist_plaintext0;
+ reg [127 : 0] nist_plaintext1;
+ reg [127 : 0] nist_plaintext2;
+ reg [127 : 0] nist_plaintext3;
+
+ reg [127 : 0] nist_ecb_128_enc_expected0;
+ reg [127 : 0] nist_ecb_128_enc_expected1;
+ reg [127 : 0] nist_ecb_128_enc_expected2;
+ reg [127 : 0] nist_ecb_128_enc_expected3;
+
+ reg [127 : 0] nist_ecb_256_enc_expected0;
+ reg [127 : 0] nist_ecb_256_enc_expected1;
+ reg [127 : 0] nist_ecb_256_enc_expected2;
+ reg [127 : 0] nist_ecb_256_enc_expected3;
+
+ nist_aes128_key = 256'h2b7e151628aed2a6abf7158809cf4f3c00000000000000000000000000000000;
+ nist_aes256_key = 256'h603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4;
+
+ nist_plaintext0 = 128'h6bc1bee22e409f96e93d7e117393172a;
+ nist_plaintext1 = 128'hae2d8a571e03ac9c9eb76fac45af8e51;
+ nist_plaintext2 = 128'h30c81c46a35ce411e5fbc1191a0a52ef;
+ nist_plaintext3 = 128'hf69f2445df4f9b17ad2b417be66c3710;
+
+ nist_ecb_128_enc_expected0 = 128'h3ad77bb40d7a3660a89ecaf32466ef97;
+ nist_ecb_128_enc_expected1 = 128'hf5d3d58503b9699de785895a96fdbaaf;
+ nist_ecb_128_enc_expected2 = 128'h43b1cd7f598ece23881b00e3ed030688;
+ nist_ecb_128_enc_expected3 = 128'h7b0c785e27e8ad3f8223207104725dd4;
+
+ nist_ecb_256_enc_expected0 = 128'hf3eed1bdb5d2a03c064b5a7e3db181f8;
+ nist_ecb_256_enc_expected1 = 128'h591ccb10d410ed26dc5ba74a31362870;
+ nist_ecb_256_enc_expected2 = 128'hb6ed21b99ca6f4f9f153e7b1beafed1d;
+ nist_ecb_256_enc_expected3 = 128'h23304b7a39f9f3ff067d8d8f9e24ecc7;
+
+
+ $display(" -= Testbench for aes core started =-");
+ $display(" ================================");
+ $display("");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+
+ $display("ECB 128 bit key tests");
+ $display("---------------------");
+ ecb_mode_single_block_test(8'h01, AES_ENCIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_plaintext0, nist_ecb_128_enc_expected0);
+
+ ecb_mode_single_block_test(8'h02, AES_ENCIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_plaintext1, nist_ecb_128_enc_expected1);
+
+ ecb_mode_single_block_test(8'h03, AES_ENCIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_plaintext2, nist_ecb_128_enc_expected2);
+
+ ecb_mode_single_block_test(8'h04, AES_ENCIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_plaintext3, nist_ecb_128_enc_expected3);
+
+
+ ecb_mode_single_block_test(8'h05, AES_DECIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_ecb_128_enc_expected0, nist_plaintext0);
+
+ ecb_mode_single_block_test(8'h06, AES_DECIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_ecb_128_enc_expected1, nist_plaintext1);
+
+ ecb_mode_single_block_test(8'h07, AES_DECIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_ecb_128_enc_expected2, nist_plaintext2);
+
+ ecb_mode_single_block_test(8'h08, AES_DECIPHER, nist_aes128_key, AES_128_BIT_KEY,
+ nist_ecb_128_enc_expected3, nist_plaintext3);
+
+
+ $display("");
+ $display("ECB 256 bit key tests");
+ $display("---------------------");
+ ecb_mode_single_block_test(8'h10, AES_ENCIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_plaintext0, nist_ecb_256_enc_expected0);
+
+ ecb_mode_single_block_test(8'h11, AES_ENCIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_plaintext1, nist_ecb_256_enc_expected1);
+
+ ecb_mode_single_block_test(8'h12, AES_ENCIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_plaintext2, nist_ecb_256_enc_expected2);
+
+ ecb_mode_single_block_test(8'h13, AES_ENCIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_plaintext3, nist_ecb_256_enc_expected3);
+
+
+ ecb_mode_single_block_test(8'h14, AES_DECIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_ecb_256_enc_expected0, nist_plaintext0);
+
+ ecb_mode_single_block_test(8'h15, AES_DECIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_ecb_256_enc_expected1, nist_plaintext1);
+
+ ecb_mode_single_block_test(8'h16, AES_DECIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_ecb_256_enc_expected2, nist_plaintext2);
+
+ ecb_mode_single_block_test(8'h17, AES_DECIPHER, nist_aes256_key, AES_256_BIT_KEY,
+ nist_ecb_256_enc_expected3, nist_plaintext3);
+
+
+ display_test_result();
+ $display("");
+ $display("*** AES core simulation done. ***");
+ $finish;
+ end // aes_core_test
+endmodule // tb_aes_core
+
+//======================================================================
+// EOF tb_aes_core.v
+//======================================================================
diff --git a/cipher/aes/src/tb/tb_aes_decipher_block.v b/cipher/aes/src/tb/tb_aes_decipher_block.v
new file mode 100644
index 0000000..5a89102
--- /dev/null
+++ b/cipher/aes/src/tb/tb_aes_decipher_block.v
@@ -0,0 +1,411 @@
+//======================================================================
+//
+// tb_aes_decipher_block.v
+// -----------------------
+// Testbench for the AES decipher block module.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_aes_decipher_block();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 1;
+ parameter DUMP_WAIT = 0;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+ parameter AES_128_BIT_KEY = 0;
+ parameter AES_256_BIT_KEY = 1;
+
+ parameter AES_DECIPHER = 1'b0;
+ parameter AES_ENCIPHER = 1'b1;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg tb_clk;
+ reg tb_reset_n;
+
+ reg tb_next;
+ reg tb_keylen;
+ wire tb_ready;
+ wire [3 : 0] tb_round;
+ wire [127 : 0] tb_round_key;
+
+ reg [127 : 0] tb_block;
+ wire [127 : 0] tb_new_block;
+
+ reg [127 : 0] key_mem [0 : 14];
+
+
+ //----------------------------------------------------------------
+ // Assignments.
+ //----------------------------------------------------------------
+ assign tb_round_key = key_mem[tb_round];
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ aes_decipher_block dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .next(tb_next),
+
+ .keylen(tb_keylen),
+ .round(tb_round),
+ .round_key(tb_round_key),
+
+ .block(tb_block),
+ .new_block(tb_new_block),
+ .ready(tb_ready)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Always running clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD;
+ tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor()
+ //
+ // An always running process that creates a cycle counter and
+ // conditionally displays information about the DUT.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ cycle_ctr = cycle_ctr + 1;
+ #(CLK_PERIOD);
+ if (DEBUG)
+ begin
+ dump_dut_state();
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state();
+ begin
+ $display("State of DUT");
+ $display("------------");
+ $display("Interfaces");
+ $display("ready = 0x%01x, next = 0x%01x, keylen = 0x%01x",
+ dut.ready, dut.next, dut.keylen);
+ $display("block = 0x%032x", dut.block);
+ $display("new_block = 0x%032x", dut.new_block);
+ $display("");
+
+ $display("Control states");
+ $display("round = 0x%01x", dut.round);
+ $display("dec_ctrl = 0x%01x, update_type = 0x%01x, sword_ctr = 0x%01x, round_ctr = 0x%01x",
+ dut.dec_ctrl_reg, dut.update_type, dut.sword_ctr_reg, dut.round_ctr_reg);
+ $display("");
+
+ $display("Internal data values");
+ $display("round_key = 0x%016x", dut.round_key);
+ $display("sboxw = 0x%08x, new_sboxw = 0x%08x", dut.tmp_sboxw, dut.new_sboxw);
+ $display("block_w0_reg = 0x%08x, block_w1_reg = 0x%08x, block_w2_reg = 0x%08x, block_w3_reg = 0x%08x",
+ dut.block_w0_reg, dut.block_w1_reg, dut.block_w2_reg, dut.block_w3_reg);
+ $display("");
+ $display("old_block = 0x%08x", dut.round_logic.old_block);
+ $display("inv_shiftrows_block = 0x%08x", dut.round_logic.inv_shiftrows_block);
+ $display("inv_mixcolumns_block = 0x%08x", dut.round_logic.inv_mixcolumns_block);
+ $display("addkey_block = 0x%08x", dut.round_logic.addkey_block);
+ $display("block_w0_new = 0x%08x, block_w1_new = 0x%08x, block_w2_new = 0x%08x, block_w3_new = 0x%08x",
+ dut.block_new[127 : 096], dut.block_new[095 : 064],
+ dut.block_new[063 : 032], dut.block_new[031 : 000]);
+ $display("");
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggle reset to put the DUT into a well known state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(2 * CLK_PERIOD);
+ tb_reset_n = 1;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // init_sim()
+ //
+ // Initialize all counters and testbed functionality as well
+ // as setting the DUT inputs to defined values.
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+
+ tb_next = 0;
+ tb_keylen = 0;
+
+ tb_block = {4{32'h00000000}};
+ end
+ endtask // init_sim
+
+
+ //----------------------------------------------------------------
+ // display_test_result()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_result();
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %02d test cases completed successfully", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d tests completed - %02d test cases did not complete successfully.",
+ tc_ctr, error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is actively processing and will in fact at some
+ // point set the flag.
+ //----------------------------------------------------------------
+ task wait_ready();
+ begin
+ while (!tb_ready)
+ begin
+ #(CLK_PERIOD);
+ if (DUMP_WAIT)
+ begin
+ dump_dut_state();
+ end
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // test_ecb_de()
+ //
+ // Perform ECB mode encryption test.
+ //----------------------------------------------------------------
+ task test_ecb_dec(
+ input key_length,
+ input [127 : 0] block,
+ input [127 : 0] expected);
+ begin
+ $display("*** TC %0d ECB mode test started.", tc_ctr);
+
+ // Init the cipher with the given key and length.
+ tb_keylen = key_length;
+
+ // Perform decipher operation on the block.
+ tb_block = block;
+ tb_next = 1;
+ #(2 * CLK_PERIOD);
+ tb_next = 0;
+ #(2 * CLK_PERIOD);
+
+ wait_ready();
+
+ if (tb_new_block == expected)
+ begin
+ $display("*** TC %0d successful.", tc_ctr);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d NOT successful.", tc_ctr);
+ $display("Expected: 0x%032x", expected);
+ $display("Got: 0x%032x", tb_new_block);
+ $display("");
+
+ error_ctr = error_ctr + 1;
+ end
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // ecb_mode_single_block_test
+
+
+ //----------------------------------------------------------------
+ // tb_aes_decipher_block
+ // The main test functionality.
+ //
+ // Test cases taken from NIST SP 800-38A:
+ // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ //----------------------------------------------------------------
+ initial
+ begin : tb_aes_decipher_block
+ reg [127 : 0] nist_plaintext0;
+ reg [127 : 0] nist_plaintext1;
+ reg [127 : 0] nist_plaintext2;
+ reg [127 : 0] nist_plaintext3;
+
+ reg [127 : 0] nist_ecb_128_dec_ciphertext0;
+ reg [127 : 0] nist_ecb_128_dec_ciphertext1;
+ reg [127 : 0] nist_ecb_128_dec_ciphertext2;
+ reg [127 : 0] nist_ecb_128_dec_ciphertext3;
+
+ reg [127 : 0] nist_ecb_256_dec_ciphertext0;
+ reg [127 : 0] nist_ecb_256_dec_ciphertext1;
+ reg [127 : 0] nist_ecb_256_dec_ciphertext2;
+ reg [127 : 0] nist_ecb_256_dec_ciphertext3;
+
+ nist_plaintext0 = 128'h6bc1bee22e409f96e93d7e117393172a;
+ nist_plaintext1 = 128'hae2d8a571e03ac9c9eb76fac45af8e51;
+ nist_plaintext2 = 128'h30c81c46a35ce411e5fbc1191a0a52ef;
+ nist_plaintext3 = 128'hf69f2445df4f9b17ad2b417be66c3710;
+
+ nist_ecb_128_dec_ciphertext0 = 128'h3ad77bb40d7a3660a89ecaf32466ef97;
+ nist_ecb_128_dec_ciphertext1 = 128'hf5d3d58503b9699de785895a96fdbaaf;
+ nist_ecb_128_dec_ciphertext2 = 128'h43b1cd7f598ece23881b00e3ed030688;
+ nist_ecb_128_dec_ciphertext3 = 128'h7b0c785e27e8ad3f8223207104725dd4;
+
+ nist_ecb_256_dec_ciphertext0 = 255'hf3eed1bdb5d2a03c064b5a7e3db181f8;
+ nist_ecb_256_dec_ciphertext1 = 255'h591ccb10d410ed26dc5ba74a31362870;
+ nist_ecb_256_dec_ciphertext2 = 255'hb6ed21b99ca6f4f9f153e7b1beafed1d;
+ nist_ecb_256_dec_ciphertext3 = 255'h23304b7a39f9f3ff067d8d8f9e24ecc7;
+
+
+ $display(" -= Testbench for aes decipher block started =-");
+ $display(" ============================================");
+ $display("");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+
+ // NIST 128 bit ECB tests.
+ key_mem[00] = 128'h2b7e151628aed2a6abf7158809cf4f3c;
+ key_mem[01] = 128'ha0fafe1788542cb123a339392a6c7605;
+ key_mem[02] = 128'hf2c295f27a96b9435935807a7359f67f;
+ key_mem[03] = 128'h3d80477d4716fe3e1e237e446d7a883b;
+ key_mem[04] = 128'hef44a541a8525b7fb671253bdb0bad00;
+ key_mem[05] = 128'hd4d1c6f87c839d87caf2b8bc11f915bc;
+ key_mem[06] = 128'h6d88a37a110b3efddbf98641ca0093fd;
+ key_mem[07] = 128'h4e54f70e5f5fc9f384a64fb24ea6dc4f;
+ key_mem[08] = 128'head27321b58dbad2312bf5607f8d292f;
+ key_mem[09] = 128'hac7766f319fadc2128d12941575c006e;
+ key_mem[10] = 128'hd014f9a8c9ee2589e13f0cc8b6630ca6;
+ key_mem[11] = 128'h00000000000000000000000000000000;
+ key_mem[12] = 128'h00000000000000000000000000000000;
+ key_mem[13] = 128'h00000000000000000000000000000000;
+ key_mem[14] = 128'h00000000000000000000000000000000;
+
+ test_ecb_dec(AES_128_BIT_KEY, nist_ecb_128_dec_ciphertext0, nist_plaintext0);
+ test_ecb_dec(AES_128_BIT_KEY, nist_ecb_128_dec_ciphertext1, nist_plaintext1);
+ test_ecb_dec(AES_128_BIT_KEY, nist_ecb_128_dec_ciphertext2, nist_plaintext2);
+ test_ecb_dec(AES_128_BIT_KEY, nist_ecb_128_dec_ciphertext3, nist_plaintext3);
+
+
+ // NIST 256 bit ECB tests.
+ key_mem[00] = 128'h603deb1015ca71be2b73aef0857d7781;
+ key_mem[01] = 128'h1f352c073b6108d72d9810a30914dff4;
+ key_mem[02] = 128'h9ba354118e6925afa51a8b5f2067fcde;
+ key_mem[03] = 128'ha8b09c1a93d194cdbe49846eb75d5b9a;
+ key_mem[04] = 128'hd59aecb85bf3c917fee94248de8ebe96;
+ key_mem[05] = 128'hb5a9328a2678a647983122292f6c79b3;
+ key_mem[06] = 128'h812c81addadf48ba24360af2fab8b464;
+ key_mem[07] = 128'h98c5bfc9bebd198e268c3ba709e04214;
+ key_mem[08] = 128'h68007bacb2df331696e939e46c518d80;
+ key_mem[09] = 128'hc814e20476a9fb8a5025c02d59c58239;
+ key_mem[10] = 128'hde1369676ccc5a71fa2563959674ee15;
+ key_mem[11] = 128'h5886ca5d2e2f31d77e0af1fa27cf73c3;
+ key_mem[12] = 128'h749c47ab18501ddae2757e4f7401905a;
+ key_mem[13] = 128'hcafaaae3e4d59b349adf6acebd10190d;
+ key_mem[14] = 128'hfe4890d1e6188d0b046df344706c631e;
+
+ test_ecb_dec(AES_256_BIT_KEY, nist_ecb_256_dec_ciphertext0, nist_plaintext0);
+ test_ecb_dec(AES_256_BIT_KEY, nist_ecb_256_dec_ciphertext1, nist_plaintext1);
+ test_ecb_dec(AES_256_BIT_KEY, nist_ecb_256_dec_ciphertext2, nist_plaintext2);
+ test_ecb_dec(AES_256_BIT_KEY, nist_ecb_256_dec_ciphertext3, nist_plaintext3);
+
+
+ display_test_result();
+ $display("");
+ $display("*** AES decipher block module simulation done. ***");
+ $finish;
+ end // aes_core_test
+endmodule // tb_aes_decipher_block
+
+//======================================================================
+// EOF tb_aes_decipher_block.v
+//======================================================================
diff --git a/cipher/aes/src/tb/tb_aes_encipher_block.v b/cipher/aes/src/tb/tb_aes_encipher_block.v
new file mode 100644
index 0000000..39d7c26
--- /dev/null
+++ b/cipher/aes/src/tb/tb_aes_encipher_block.v
@@ -0,0 +1,427 @@
+//======================================================================
+//
+// tb_aes_encipher_block.v
+// -----------------------
+// Testbench for the AES encipher block module.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_aes_encipher_block();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 1;
+ parameter DUMP_WAIT = 0;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+ parameter AES_128_BIT_KEY = 0;
+ parameter AES_256_BIT_KEY = 1;
+
+ parameter AES_DECIPHER = 1'b0;
+ parameter AES_ENCIPHER = 1'b1;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg tb_clk;
+ reg tb_reset_n;
+
+ reg tb_next;
+ reg tb_keylen;
+ wire tb_ready;
+ wire [3 : 0] tb_round;
+ wire [127 : 0] tb_round_key;
+
+ wire [31 : 0] tb_sboxw;
+ wire [31 : 0] tb_new_sboxw;
+
+ reg [127 : 0] tb_block;
+ wire [127 : 0] tb_new_block;
+
+ reg [127 : 0] key_mem [0 : 14];
+
+
+ //----------------------------------------------------------------
+ // Assignments.
+ //----------------------------------------------------------------
+ assign tb_round_key = key_mem[tb_round];
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ // We need an sbox for the tests.
+ aes_sbox sbox(
+ .sboxw(tb_sboxw),
+ .new_sboxw(tb_new_sboxw)
+ );
+
+
+ // The device under test.
+ aes_encipher_block dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .next(tb_next),
+
+ .keylen(tb_keylen),
+ .round(tb_round),
+ .round_key(tb_round_key),
+
+ .sboxw(tb_sboxw),
+ .new_sboxw(tb_new_sboxw),
+
+ .block(tb_block),
+ .new_block(tb_new_block),
+ .ready(tb_ready)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Always running clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD;
+ tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor()
+ //
+ // An always running process that creates a cycle counter and
+ // conditionally displays information about the DUT.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ cycle_ctr = cycle_ctr + 1;
+ #(CLK_PERIOD);
+ if (DEBUG)
+ begin
+ dump_dut_state();
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state();
+ begin
+ $display("State of DUT");
+ $display("------------");
+ $display("Interfaces");
+ $display("ready = 0x%01x, next = 0x%01x, keylen = 0x%01x",
+ dut.ready, dut.next, dut.keylen);
+ $display("block = 0x%032x", dut.block);
+ $display("new_block = 0x%032x", dut.new_block);
+ $display("");
+
+ $display("Control states");
+ $display("round = 0x%01x", dut.round);
+ $display("enc_ctrl = 0x%01x, update_type = 0x%01x, sword_ctr = 0x%01x, round_ctr = 0x%01x",
+ dut.enc_ctrl_reg, dut.update_type, dut.sword_ctr_reg, dut.round_ctr_reg);
+ $display("");
+
+ $display("Internal data values");
+ $display("round_key = 0x%016x", dut.round_key);
+ $display("sboxw = 0x%08x, new_sboxw = 0x%08x", dut.sboxw, dut.new_sboxw);
+ $display("block_w0_reg = 0x%08x, block_w1_reg = 0x%08x, block_w2_reg = 0x%08x, block_w3_reg = 0x%08x",
+ dut.block_w0_reg, dut.block_w1_reg, dut.block_w2_reg, dut.block_w3_reg);
+ $display("");
+ $display("old_block = 0x%08x", dut.round_logic.old_block);
+ $display("shiftrows_block = 0x%08x", dut.round_logic.shiftrows_block);
+ $display("mixcolumns_block = 0x%08x", dut.round_logic.mixcolumns_block);
+ $display("addkey_init_block = 0x%08x", dut.round_logic.addkey_init_block);
+ $display("addkey_main_block = 0x%08x", dut.round_logic.addkey_main_block);
+ $display("addkey_final_block = 0x%08x", dut.round_logic.addkey_final_block);
+ $display("block_w0_new = 0x%08x, block_w1_new = 0x%08x, block_w2_new = 0x%08x, block_w3_new = 0x%08x",
+ dut.block_new[127 : 096], dut.block_new[095 : 064],
+ dut.block_new[063 : 032], dut.block_new[031 : 000]);
+ $display("");
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggle reset to put the DUT into a well known state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(2 * CLK_PERIOD);
+ tb_reset_n = 1;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // init_sim()
+ //
+ // Initialize all counters and testbed functionality as well
+ // as setting the DUT inputs to defined values.
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+
+ tb_next = 0;
+ tb_keylen = 0;
+
+ tb_block = {4{32'h00000000}};
+ end
+ endtask // init_sim
+
+
+ //----------------------------------------------------------------
+ // display_test_result()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_result();
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %02d test cases completed successfully", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d tests completed - %02d test cases did not complete successfully.",
+ tc_ctr, error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is actively processing and will in fact at some
+ // point set the flag.
+ //----------------------------------------------------------------
+ task wait_ready();
+ begin
+ while (!tb_ready)
+ begin
+ #(CLK_PERIOD);
+ if (DUMP_WAIT)
+ begin
+ dump_dut_state();
+ end
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // test_ecb_enc()
+ //
+ // Perform ECB mode encryption test.
+ //----------------------------------------------------------------
+ task test_ecb_enc(
+ input key_length,
+ input [127 : 0] block,
+ input [127 : 0] expected);
+ begin
+ $display("*** TC %0d ECB mode test started.", tc_ctr);
+
+ // Init the cipher with the given key and length.
+ tb_keylen = key_length;
+
+ // Perform encipher operation on the block.
+ tb_block = block;
+ tb_next = 1;
+ #(2 * CLK_PERIOD);
+ tb_next = 0;
+ #(2 * CLK_PERIOD);
+
+ wait_ready();
+
+ if (tb_new_block == expected)
+ begin
+ $display("*** TC %0d successful.", tc_ctr);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d NOT successful.", tc_ctr);
+ $display("Expected: 0x%032x", expected);
+ $display("Got: 0x%032x", tb_new_block);
+ $display("");
+
+ error_ctr = error_ctr + 1;
+ end
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // ecb_mode_single_block_test
+
+
+ //----------------------------------------------------------------
+ // tb_aes_encipher_block
+ // The main test functionality.
+ //
+ // Test cases taken from NIST SP 800-38A:
+ // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ //----------------------------------------------------------------
+ initial
+ begin : tb_aes_encipher_block
+ reg [127 : 0] nist_plaintext0;
+ reg [127 : 0] nist_plaintext1;
+ reg [127 : 0] nist_plaintext2;
+ reg [127 : 0] nist_plaintext3;
+
+ reg [127 : 0] nist_ecb_128_enc_expected0;
+ reg [127 : 0] nist_ecb_128_enc_expected1;
+ reg [127 : 0] nist_ecb_128_enc_expected2;
+ reg [127 : 0] nist_ecb_128_enc_expected3;
+
+ reg [127 : 0] nist_ecb_256_enc_expected0;
+ reg [127 : 0] nist_ecb_256_enc_expected1;
+ reg [127 : 0] nist_ecb_256_enc_expected2;
+ reg [127 : 0] nist_ecb_256_enc_expected3;
+
+ nist_plaintext0 = 128'h6bc1bee22e409f96e93d7e117393172a;
+ nist_plaintext1 = 128'hae2d8a571e03ac9c9eb76fac45af8e51;
+ nist_plaintext2 = 128'h30c81c46a35ce411e5fbc1191a0a52ef;
+ nist_plaintext3 = 128'hf69f2445df4f9b17ad2b417be66c3710;
+
+ nist_ecb_128_enc_expected0 = 128'h3ad77bb40d7a3660a89ecaf32466ef97;
+ nist_ecb_128_enc_expected1 = 128'hf5d3d58503b9699de785895a96fdbaaf;
+ nist_ecb_128_enc_expected2 = 128'h43b1cd7f598ece23881b00e3ed030688;
+ nist_ecb_128_enc_expected3 = 128'h7b0c785e27e8ad3f8223207104725dd4;
+
+ nist_ecb_256_enc_expected0 = 255'hf3eed1bdb5d2a03c064b5a7e3db181f8;
+ nist_ecb_256_enc_expected1 = 255'h591ccb10d410ed26dc5ba74a31362870;
+ nist_ecb_256_enc_expected2 = 255'hb6ed21b99ca6f4f9f153e7b1beafed1d;
+ nist_ecb_256_enc_expected3 = 255'h23304b7a39f9f3ff067d8d8f9e24ecc7;
+
+
+ $display(" -= Testbench for aes encipher block started =-");
+ $display(" ============================================");
+ $display("");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+
+ // NIST 128 bit ECB tests.
+ key_mem[00] = 128'h2b7e151628aed2a6abf7158809cf4f3c;
+ key_mem[01] = 128'ha0fafe1788542cb123a339392a6c7605;
+ key_mem[02] = 128'hf2c295f27a96b9435935807a7359f67f;
+ key_mem[03] = 128'h3d80477d4716fe3e1e237e446d7a883b;
+ key_mem[04] = 128'hef44a541a8525b7fb671253bdb0bad00;
+ key_mem[05] = 128'hd4d1c6f87c839d87caf2b8bc11f915bc;
+ key_mem[06] = 128'h6d88a37a110b3efddbf98641ca0093fd;
+ key_mem[07] = 128'h4e54f70e5f5fc9f384a64fb24ea6dc4f;
+ key_mem[08] = 128'head27321b58dbad2312bf5607f8d292f;
+ key_mem[09] = 128'hac7766f319fadc2128d12941575c006e;
+ key_mem[10] = 128'hd014f9a8c9ee2589e13f0cc8b6630ca6;
+ key_mem[11] = 128'h00000000000000000000000000000000;
+ key_mem[12] = 128'h00000000000000000000000000000000;
+ key_mem[13] = 128'h00000000000000000000000000000000;
+ key_mem[14] = 128'h00000000000000000000000000000000;
+
+ test_ecb_enc(AES_128_BIT_KEY, nist_plaintext0, nist_ecb_128_enc_expected0);
+ test_ecb_enc(AES_128_BIT_KEY, nist_plaintext1, nist_ecb_128_enc_expected1);
+ test_ecb_enc(AES_128_BIT_KEY, nist_plaintext2, nist_ecb_128_enc_expected2);
+ test_ecb_enc(AES_128_BIT_KEY, nist_plaintext3, nist_ecb_128_enc_expected3);
+
+
+ // NIST 256 bit ECB tests.
+ key_mem[00] = 128'h603deb1015ca71be2b73aef0857d7781;
+ key_mem[01] = 128'h1f352c073b6108d72d9810a30914dff4;
+ key_mem[02] = 128'h9ba354118e6925afa51a8b5f2067fcde;
+ key_mem[03] = 128'ha8b09c1a93d194cdbe49846eb75d5b9a;
+ key_mem[04] = 128'hd59aecb85bf3c917fee94248de8ebe96;
+ key_mem[05] = 128'hb5a9328a2678a647983122292f6c79b3;
+ key_mem[06] = 128'h812c81addadf48ba24360af2fab8b464;
+ key_mem[07] = 128'h98c5bfc9bebd198e268c3ba709e04214;
+ key_mem[08] = 128'h68007bacb2df331696e939e46c518d80;
+ key_mem[09] = 128'hc814e20476a9fb8a5025c02d59c58239;
+ key_mem[10] = 128'hde1369676ccc5a71fa2563959674ee15;
+ key_mem[11] = 128'h5886ca5d2e2f31d77e0af1fa27cf73c3;
+ key_mem[12] = 128'h749c47ab18501ddae2757e4f7401905a;
+ key_mem[13] = 128'hcafaaae3e4d59b349adf6acebd10190d;
+ key_mem[14] = 128'hfe4890d1e6188d0b046df344706c631e;
+
+ test_ecb_enc(AES_256_BIT_KEY, nist_plaintext0, nist_ecb_256_enc_expected0);
+ test_ecb_enc(AES_256_BIT_KEY, nist_plaintext1, nist_ecb_256_enc_expected1);
+ test_ecb_enc(AES_256_BIT_KEY, nist_plaintext2, nist_ecb_256_enc_expected2);
+ test_ecb_enc(AES_256_BIT_KEY, nist_plaintext3, nist_ecb_256_enc_expected3);
+
+
+ display_test_result();
+ $display("");
+ $display("*** AES encipher block module simulation done. ***");
+ $finish;
+ end // aes_core_test
+endmodule // tb_aes_encipher_block
+
+//======================================================================
+// EOF tb_aes_encipher_block.v
+//======================================================================
diff --git a/cipher/aes/src/tb/tb_aes_key_mem.v b/cipher/aes/src/tb/tb_aes_key_mem.v
new file mode 100644
index 0000000..748ae3f
--- /dev/null
+++ b/cipher/aes/src/tb/tb_aes_key_mem.v
@@ -0,0 +1,655 @@
+//======================================================================
+//
+// tb_aes_key_mem.v
+// ----------------
+// Testbench for the AES key memory module.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_aes_key_mem();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 1;
+ parameter SHOW_SBOX = 0;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+ parameter AES_128_BIT_KEY = 0;
+ parameter AES_256_BIT_KEY = 1;
+
+ parameter AES_128_NUM_ROUNDS = 10;
+ parameter AES_192_NUM_ROUNDS = 12;
+ parameter AES_256_NUM_ROUNDS = 14;
+
+ parameter AES_DECIPHER = 1'b0;
+ parameter AES_ENCIPHER = 1'b1;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg tb_clk;
+ reg tb_reset_n;
+ reg [255 : 0] tb_key;
+ reg tb_keylen;
+ reg tb_init;
+ reg [3 : 0] tb_round;
+ wire [127 : 0] tb_round_key;
+ wire tb_ready;
+
+ wire [31 : 0] tb_sboxw;
+ wire [31 : 0] tb_new_sboxw;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ aes_key_mem dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .key(tb_key),
+ .keylen(tb_keylen),
+ .init(tb_init),
+
+ .round(tb_round),
+ .round_key(tb_round_key),
+ .ready(tb_ready),
+
+ .sboxw(tb_sboxw),
+ .new_sboxw(tb_new_sboxw)
+ );
+
+ // The DUT requirees Sboxes.
+ aes_sbox sbox(.sboxw(tb_sboxw), .new_sboxw(tb_new_sboxw));
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Always running clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD;
+ tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor()
+ //
+ // An always running process that creates a cycle counter and
+ // conditionally displays information about the DUT.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ cycle_ctr = cycle_ctr + 1;
+ #(CLK_PERIOD);
+ if (DEBUG)
+ begin
+ dump_dut_state();
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state();
+ begin
+ $display("State of DUT");
+ $display("------------");
+ $display("Inputs and outputs:");
+ $display("key = 0x%032x", dut.key);
+ $display("keylen = 0x%01x, init = 0x%01x, ready = 0x%01x",
+ dut.keylen, dut.init, dut.ready);
+ $display("round = 0x%02x", dut.round);
+ $display("round_key = 0x%016x", dut.round_key);
+ $display("");
+
+ $display("Internal states:");
+ $display("key_mem_ctrl = 0x%01x, round_key_update = 0x%01x, round_ctr_reg = 0x%01x, rcon_reg = 0x%01x",
+ dut.key_mem_ctrl_reg, dut.round_key_update, dut.round_ctr_reg, dut.rcon_reg);
+
+ $display("prev_key0_reg = 0x%016x, prev_key0_new = 0x%016x, prev_key0_we = 0x%01x",
+ dut.prev_key0_reg, dut.prev_key0_new, dut.prev_key0_we);
+ $display("prev_key1_reg = 0x%016x, prev_key1_new = 0x%016x, prev_key1_we = 0x%01x",
+ dut.prev_key1_reg, dut.prev_key1_new, dut.prev_key1_we);
+
+ $display("w0 = 0x%04x, w1 = 0x%04x, w2 = 0x%04x, w3 = 0x%04x",
+ dut.round_key_gen.w0, dut.round_key_gen.w1,
+ dut.round_key_gen.w2, dut.round_key_gen.w3);
+ $display("w4 = 0x%04x, w5 = 0x%04x, w6 = 0x%04x, w7 = 0x%04x",
+ dut.round_key_gen.w4, dut.round_key_gen.w5,
+ dut.round_key_gen.w6, dut.round_key_gen.w7);
+ $display("sboxw = 0x%04x, new_sboxw = 0x%04x, rconw = 0x%04x",
+ dut.sboxw, dut.new_sboxw, dut.round_key_gen.rconw);
+ $display("tw = 0x%04x, trw = 0x%04x", dut.round_key_gen.tw, dut.round_key_gen.trw);
+ $display("key_mem_new = 0x%016x, key_mem_we = 0x%01x",
+ dut.key_mem_new, dut.key_mem_we);
+ $display("");
+
+ if (SHOW_SBOX)
+ begin
+ $display("Sbox functionality:");
+ $display("sboxw = 0x%08x", sbox.sboxw);
+ $display("tmp_new_sbox0 = 0x%02x, tmp_new_sbox1 = 0x%02x, tmp_new_sbox2 = 0x%02x, tmp_new_sbox3",
+ sbox.tmp_new_sbox0, sbox.tmp_new_sbox1, sbox.tmp_new_sbox2, sbox.tmp_new_sbox3);
+ $display("new_sboxw = 0x%08x", sbox.new_sboxw);
+ $display("");
+ end
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggle reset to put the DUT into a well known state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(2 * CLK_PERIOD);
+ tb_reset_n = 1;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // init_sim()
+ //
+ // Initialize all counters and testbed functionality as well
+ // as setting the DUT inputs to defined values.
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+ tb_key = {8{32'h00000000}};
+ tb_keylen = 0;
+ tb_init = 0;
+ tb_round = 4'h0;
+ end
+ endtask // init_sim
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is actively processing and will in fact at some
+ // point set the flag.
+ //----------------------------------------------------------------
+ task wait_ready();
+ begin
+ while (!tb_ready)
+ begin
+ #(CLK_PERIOD);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // check_key()
+ //
+ // Check a given key in the dut key memory against a given
+ // expected key.
+ //----------------------------------------------------------------
+ task check_key(input [3 : 0] key_nr, input [127 : 0] expected);
+ begin
+ tb_round = key_nr;
+ #(CLK_PERIOD);
+ if (tb_round_key == expected)
+ begin
+ $display("** key 0x%01x matched expected round key.", key_nr);
+ $display("** Got: 0x%016x **", tb_round_key);
+ end
+ else
+ begin
+ $display("** Error: key 0x%01x did not match expected round key. **", key_nr);
+ $display("** Expected: 0x%016x **", expected);
+ $display("** Got: 0x%016x **", tb_round_key);
+ error_ctr = error_ctr + 1;
+ end
+ $display("");
+ end
+ endtask // check_key
+
+
+ //----------------------------------------------------------------
+ // test_key_128()
+ //
+ // Test 128 bit keys. Due to array problems, the result check
+ // is fairly ugly.
+ //----------------------------------------------------------------
+ task test_key_128(input [255 : 0] key,
+ input [127 : 0] expected00,
+ input [127 : 0] expected01,
+ input [127 : 0] expected02,
+ input [127 : 0] expected03,
+ input [127 : 0] expected04,
+ input [127 : 0] expected05,
+ input [127 : 0] expected06,
+ input [127 : 0] expected07,
+ input [127 : 0] expected08,
+ input [127 : 0] expected09,
+ input [127 : 0] expected10
+ );
+ begin
+ $display("** Testing with 128-bit key 0x%16x", key[255 : 128]);
+ $display("");
+
+ tb_key = key;
+ tb_keylen = AES_128_BIT_KEY;
+ tb_init = 1;
+ #(2 * CLK_PERIOD);
+ tb_init = 0;
+ wait_ready();
+
+ check_key(4'h0, expected00);
+ check_key(4'h1, expected01);
+ check_key(4'h2, expected02);
+ check_key(4'h3, expected03);
+ check_key(4'h4, expected04);
+ check_key(4'h5, expected05);
+ check_key(4'h6, expected06);
+ check_key(4'h7, expected07);
+ check_key(4'h8, expected08);
+ check_key(4'h9, expected09);
+ check_key(4'ha, expected10);
+
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // test_key_128
+
+
+ //----------------------------------------------------------------
+ // test_key_256()
+ //
+ // Test 256 bit keys. Due to array problems, the result check
+ // is fairly ugly.
+ //----------------------------------------------------------------
+ task test_key_256(input [255 : 0] key,
+ input [127 : 0] expected00,
+ input [127 : 0] expected01,
+ input [127 : 0] expected02,
+ input [127 : 0] expected03,
+ input [127 : 0] expected04,
+ input [127 : 0] expected05,
+ input [127 : 0] expected06,
+ input [127 : 0] expected07,
+ input [127 : 0] expected08,
+ input [127 : 0] expected09,
+ input [127 : 0] expected10,
+ input [127 : 0] expected11,
+ input [127 : 0] expected12,
+ input [127 : 0] expected13,
+ input [127 : 0] expected14
+ );
+ begin
+ $display("** Testing with 256-bit key 0x%32x", key[255 : 000]);
+ $display("");
+
+ tb_key = key;
+ tb_keylen = AES_256_BIT_KEY;
+ tb_init = 1;
+ #(2 * CLK_PERIOD);
+ tb_init = 0;
+
+ wait_ready();
+
+ check_key(4'h0, expected00);
+ check_key(4'h1, expected01);
+ check_key(4'h2, expected02);
+ check_key(4'h3, expected03);
+ check_key(4'h4, expected04);
+ check_key(4'h5, expected05);
+ check_key(4'h6, expected06);
+ check_key(4'h7, expected07);
+ check_key(4'h8, expected08);
+ check_key(4'h9, expected09);
+ check_key(4'ha, expected10);
+ check_key(4'hb, expected11);
+ check_key(4'hc, expected12);
+ check_key(4'hd, expected13);
+ check_key(4'he, expected14);
+
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // test_key_256
+
+
+ //----------------------------------------------------------------
+ // display_test_result()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_result();
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %02d test cases completed successfully", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d tests completed - %02d test cases did not complete successfully.",
+ tc_ctr, error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // aes_key_mem_test
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : aes_key_mem_test
+ reg [255 : 0] key128_0;
+ reg [255 : 0] key128_1;
+ reg [255 : 0] key128_2;
+ reg [255 : 0] key128_3;
+ reg [255 : 0] nist_key128;
+ reg [255 : 0] key256_0;
+ reg [255 : 0] key256_1;
+ reg [255 : 0] key256_2;
+ reg [255 : 0] nist_key256;
+
+ reg [127 : 0] expected_00;
+ reg [127 : 0] expected_01;
+ reg [127 : 0] expected_02;
+ reg [127 : 0] expected_03;
+ reg [127 : 0] expected_04;
+ reg [127 : 0] expected_05;
+ reg [127 : 0] expected_06;
+ reg [127 : 0] expected_07;
+ reg [127 : 0] expected_08;
+ reg [127 : 0] expected_09;
+ reg [127 : 0] expected_10;
+ reg [127 : 0] expected_11;
+ reg [127 : 0] expected_12;
+ reg [127 : 0] expected_13;
+ reg [127 : 0] expected_14;
+
+ $display(" -= Testbench for aes key mem started =-");
+ $display(" =====================================");
+ $display("");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+
+ $display("State after reset:");
+ dump_dut_state();
+ $display("");
+
+ #(100 *CLK_PERIOD);
+
+ // AES-128 test case 1 key and expected values.
+ key128_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ expected_00 = 128'h00000000000000000000000000000000;
+ expected_01 = 128'h62636363626363636263636362636363;
+ expected_02 = 128'h9b9898c9f9fbfbaa9b9898c9f9fbfbaa;
+ expected_03 = 128'h90973450696ccffaf2f457330b0fac99;
+ expected_04 = 128'hee06da7b876a1581759e42b27e91ee2b;
+ expected_05 = 128'h7f2e2b88f8443e098dda7cbbf34b9290;
+ expected_06 = 128'hec614b851425758c99ff09376ab49ba7;
+ expected_07 = 128'h217517873550620bacaf6b3cc61bf09b;
+ expected_08 = 128'h0ef903333ba9613897060a04511dfa9f;
+ expected_09 = 128'hb1d4d8e28a7db9da1d7bb3de4c664941;
+ expected_10 = 128'hb4ef5bcb3e92e21123e951cf6f8f188e;
+
+ test_key_128(key128_0,
+ expected_00, expected_01, expected_02, expected_03,
+ expected_04, expected_05, expected_06, expected_07,
+ expected_08, expected_09, expected_10);
+
+
+ // AES-128 test case 2 key and expected values.
+ key128_1 = 256'hffffffffffffffffffffffffffffffff00000000000000000000000000000000;
+ expected_00 = 128'hffffffffffffffffffffffffffffffff;
+ expected_01 = 128'he8e9e9e917161616e8e9e9e917161616;
+ expected_02 = 128'hadaeae19bab8b80f525151e6454747f0;
+ expected_03 = 128'h090e2277b3b69a78e1e7cb9ea4a08c6e;
+ expected_04 = 128'he16abd3e52dc2746b33becd8179b60b6;
+ expected_05 = 128'he5baf3ceb766d488045d385013c658e6;
+ expected_06 = 128'h71d07db3c6b6a93bc2eb916bd12dc98d;
+ expected_07 = 128'he90d208d2fbb89b6ed5018dd3c7dd150;
+ expected_08 = 128'h96337366b988fad054d8e20d68a5335d;
+ expected_09 = 128'h8bf03f233278c5f366a027fe0e0514a3;
+ expected_10 = 128'hd60a3588e472f07b82d2d7858cd7c326;
+
+ test_key_128(key128_1,
+ expected_00, expected_01, expected_02, expected_03,
+ expected_04, expected_05, expected_06, expected_07,
+ expected_08, expected_09, expected_10);
+
+
+ // AES-128 test case 3 key and expected values.
+ key128_2 = 256'h000102030405060708090a0b0c0d0e0f00000000000000000000000000000000;
+ expected_00 = 128'h000102030405060708090a0b0c0d0e0f;
+ expected_01 = 128'hd6aa74fdd2af72fadaa678f1d6ab76fe;
+ expected_02 = 128'hb692cf0b643dbdf1be9bc5006830b3fe;
+ expected_03 = 128'hb6ff744ed2c2c9bf6c590cbf0469bf41;
+ expected_04 = 128'h47f7f7bc95353e03f96c32bcfd058dfd;
+ expected_05 = 128'h3caaa3e8a99f9deb50f3af57adf622aa;
+ expected_06 = 128'h5e390f7df7a69296a7553dc10aa31f6b;
+ expected_07 = 128'h14f9701ae35fe28c440adf4d4ea9c026;
+ expected_08 = 128'h47438735a41c65b9e016baf4aebf7ad2;
+ expected_09 = 128'h549932d1f08557681093ed9cbe2c974e;
+ expected_10 = 128'h13111d7fe3944a17f307a78b4d2b30c5;
+
+ test_key_128(key128_2,
+ expected_00, expected_01, expected_02, expected_03,
+ expected_04, expected_05, expected_06, expected_07,
+ expected_08, expected_09, expected_10);
+
+
+ // AES-128 test case 4 key and expected values.
+ key128_3 = 256'h6920e299a5202a6d656e636869746f2a00000000000000000000000000000000;
+ expected_00 = 128'h6920e299a5202a6d656e636869746f2a;
+ expected_01 = 128'hfa8807605fa82d0d3ac64e6553b2214f;
+ expected_02 = 128'hcf75838d90ddae80aa1be0e5f9a9c1aa;
+ expected_03 = 128'h180d2f1488d0819422cb6171db62a0db;
+ expected_04 = 128'hbaed96ad323d173910f67648cb94d693;
+ expected_05 = 128'h881b4ab2ba265d8baad02bc36144fd50;
+ expected_06 = 128'hb34f195d096944d6a3b96f15c2fd9245;
+ expected_07 = 128'ha7007778ae6933ae0dd05cbbcf2dcefe;
+ expected_08 = 128'hff8bccf251e2ff5c5c32a3e7931f6d19;
+ expected_09 = 128'h24b7182e7555e77229674495ba78298c;
+ expected_10 = 128'hae127cdadb479ba8f220df3d4858f6b1;
+
+ test_key_128(key128_3,
+ expected_00, expected_01, expected_02, expected_03,
+ expected_04, expected_05, expected_06, expected_07,
+ expected_08, expected_09, expected_10);
+
+
+ // NIST AES-128 test case.
+ nist_key128 = 256'h2b7e151628aed2a6abf7158809cf4f3c00000000000000000000000000000000;
+ expected_00 = 128'h2b7e151628aed2a6abf7158809cf4f3c;
+ expected_01 = 128'ha0fafe1788542cb123a339392a6c7605;
+ expected_02 = 128'hf2c295f27a96b9435935807a7359f67f;
+ expected_03 = 128'h3d80477d4716fe3e1e237e446d7a883b;
+ expected_04 = 128'hef44a541a8525b7fb671253bdb0bad00;
+ expected_05 = 128'hd4d1c6f87c839d87caf2b8bc11f915bc;
+ expected_06 = 128'h6d88a37a110b3efddbf98641ca0093fd;
+ expected_07 = 128'h4e54f70e5f5fc9f384a64fb24ea6dc4f;
+ expected_08 = 128'head27321b58dbad2312bf5607f8d292f;
+ expected_09 = 128'hac7766f319fadc2128d12941575c006e;
+ expected_10 = 128'hd014f9a8c9ee2589e13f0cc8b6630ca6;
+
+ $display("Testing the NIST AES-128 key.");
+ test_key_128(nist_key128,
+ expected_00, expected_01, expected_02, expected_03,
+ expected_04, expected_05, expected_06, expected_07,
+ expected_08, expected_09, expected_10);
+
+
+ // AES-256 test case 1 key and expected values.
+ key256_0 = 256'h000000000000000000000000000000000000000000000000000000000000000;
+ expected_00 = 128'h00000000000000000000000000000000;
+ expected_01 = 128'h00000000000000000000000000000000;
+ expected_02 = 128'h62636363626363636263636362636363;
+ expected_03 = 128'haafbfbfbaafbfbfbaafbfbfbaafbfbfb;
+ expected_04 = 128'h6f6c6ccf0d0f0fac6f6c6ccf0d0f0fac;
+ expected_05 = 128'h7d8d8d6ad77676917d8d8d6ad7767691;
+ expected_06 = 128'h5354edc15e5be26d31378ea23c38810e;
+ expected_07 = 128'h968a81c141fcf7503c717a3aeb070cab;
+ expected_08 = 128'h9eaa8f28c0f16d45f1c6e3e7cdfe62e9;
+ expected_09 = 128'h2b312bdf6acddc8f56bca6b5bdbbaa1e;
+ expected_10 = 128'h6406fd52a4f79017553173f098cf1119;
+ expected_11 = 128'h6dbba90b0776758451cad331ec71792f;
+ expected_12 = 128'he7b0e89c4347788b16760b7b8eb91a62;
+ expected_13 = 128'h74ed0ba1739b7e252251ad14ce20d43b;
+ expected_14 = 128'h10f80a1753bf729c45c979e7cb706385;
+
+ test_key_256(key256_0,
+ expected_00, expected_01, expected_02, expected_03,
+ expected_04, expected_05, expected_06, expected_07,
+ expected_08, expected_09, expected_10, expected_11,
+ expected_12, expected_13, expected_14);
+
+
+ // AES-256 test case 2 key and expected values.
+ key256_1 = 256'hffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
+ expected_00 = 128'hffffffffffffffffffffffffffffffff;
+ expected_01 = 128'hffffffffffffffffffffffffffffffff;
+ expected_02 = 128'he8e9e9e917161616e8e9e9e917161616;
+ expected_03 = 128'h0fb8b8b8f04747470fb8b8b8f0474747;
+ expected_04 = 128'h4a4949655d5f5f73b5b6b69aa2a0a08c;
+ expected_05 = 128'h355858dcc51f1f9bcaa7a7233ae0e064;
+ expected_06 = 128'hafa80ae5f2f755964741e30ce5e14380;
+ expected_07 = 128'heca0421129bf5d8ae318faa9d9f81acd;
+ expected_08 = 128'he60ab7d014fde24653bc014ab65d42ca;
+ expected_09 = 128'ha2ec6e658b5333ef684bc946b1b3d38b;
+ expected_10 = 128'h9b6c8a188f91685edc2d69146a702bde;
+ expected_11 = 128'ha0bd9f782beeac9743a565d1f216b65a;
+ expected_12 = 128'hfc22349173b35ccfaf9e35dbc5ee1e05;
+ expected_13 = 128'h0695ed132d7b41846ede24559cc8920f;
+ expected_14 = 128'h546d424f27de1e8088402b5b4dae355e;
+
+ test_key_256(key256_1,
+ expected_00, expected_01, expected_02, expected_03,
+ expected_04, expected_05, expected_06, expected_07,
+ expected_08, expected_09, expected_10, expected_11,
+ expected_12, expected_13, expected_14);
+
+
+ // AES-256 test case 3 key and expected values.
+ key256_2 = 256'h000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;
+ expected_00 = 128'h000102030405060708090a0b0c0d0e0f;
+ expected_01 = 128'h101112131415161718191a1b1c1d1e1f;
+ expected_02 = 128'ha573c29fa176c498a97fce93a572c09c;
+ expected_03 = 128'h1651a8cd0244beda1a5da4c10640bade;
+ expected_04 = 128'hae87dff00ff11b68a68ed5fb03fc1567;
+ expected_05 = 128'h6de1f1486fa54f9275f8eb5373b8518d;
+ expected_06 = 128'hc656827fc9a799176f294cec6cd5598b;
+ expected_07 = 128'h3de23a75524775e727bf9eb45407cf39;
+ expected_08 = 128'h0bdc905fc27b0948ad5245a4c1871c2f;
+ expected_09 = 128'h45f5a66017b2d387300d4d33640a820a;
+ expected_10 = 128'h7ccff71cbeb4fe5413e6bbf0d261a7df;
+ expected_11 = 128'hf01afafee7a82979d7a5644ab3afe640;
+ expected_12 = 128'h2541fe719bf500258813bbd55a721c0a;
+ expected_13 = 128'h4e5a6699a9f24fe07e572baacdf8cdea;
+ expected_14 = 128'h24fc79ccbf0979e9371ac23c6d68de36;
+
+ test_key_256(key256_2,
+ expected_00, expected_01, expected_02, expected_03,
+ expected_04, expected_05, expected_06, expected_07,
+ expected_08, expected_09, expected_10, expected_11,
+ expected_12, expected_13, expected_14);
+
+
+ nist_key256 = 256'h603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4;
+ expected_00 = 128'h603deb1015ca71be2b73aef0857d7781;
+ expected_01 = 128'h1f352c073b6108d72d9810a30914dff4;
+ expected_02 = 128'h9ba354118e6925afa51a8b5f2067fcde;
+ expected_03 = 128'ha8b09c1a93d194cdbe49846eb75d5b9a;
+ expected_04 = 128'hd59aecb85bf3c917fee94248de8ebe96;
+ expected_05 = 128'hb5a9328a2678a647983122292f6c79b3;
+ expected_06 = 128'h812c81addadf48ba24360af2fab8b464;
+ expected_07 = 128'h98c5bfc9bebd198e268c3ba709e04214;
+ expected_08 = 128'h68007bacb2df331696e939e46c518d80;
+ expected_09 = 128'hc814e20476a9fb8a5025c02d59c58239;
+ expected_10 = 128'hde1369676ccc5a71fa2563959674ee15;
+ expected_11 = 128'h5886ca5d2e2f31d77e0af1fa27cf73c3;
+ expected_12 = 128'h749c47ab18501ddae2757e4f7401905a;
+ expected_13 = 128'hcafaaae3e4d59b349adf6acebd10190d;
+ expected_14 = 128'hfe4890d1e6188d0b046df344706c631e;
+
+ test_key_256(nist_key256,
+ expected_00, expected_01, expected_02, expected_03,
+ expected_04, expected_05, expected_06, expected_07,
+ expected_08, expected_09, expected_10, expected_11,
+ expected_12, expected_13, expected_14);
+
+
+ display_test_result();
+ $display("");
+ $display("*** AES core simulation done. ***");
+ $finish;
+ end // aes_key_mem_test
+endmodule // tb_aes_key_mem
+
+//======================================================================
+// EOF tb_aes_key_mem.v
+//======================================================================
diff --git a/cipher/aes/toolruns/Makefile b/cipher/aes/toolruns/Makefile
new file mode 100755
index 0000000..e37b2e0
--- /dev/null
+++ b/cipher/aes/toolruns/Makefile
@@ -0,0 +1,126 @@
+#===================================================================
+#
+# Makefile
+# --------
+# Makefile for building the aes keygen, core and top simulations.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2014, SUNET
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#===================================================================
+
+SBOX_SRC=../src/rtl/aes_sbox.v
+INV_SBOX_SRC=../src/rtl/aes_inv_sbox.v
+KEYMEM_SRC=../src/rtl/aes_key_mem.v
+ENCIPHER_SRC=../src/rtl/aes_encipher_block.v
+DECIPHER_SRC=../src/rtl/aes_decipher_block.v
+CORE_SRC=../src/rtl/aes_core.v $(KEYMEM_SRC) $(SBOX_SRC) $(INV_SBOX_SRC) $(ENCIPHER_SRC) $(DECIPHER_SRC)
+TOP_SRC=../src/rtl/aes.v $(CORE_SRC)
+
+TB_TOP_SRC =../src/tb/tb_aes.v
+TB_CORE_SRC =../src/tb/tb_aes_core.v
+TB_KEYMEM_SRC =../src/tb/tb_aes_key_mem.v
+TB_ENCIPHER_SRC =../src/tb/tb_aes_encipher_block.v
+TB_DECIPHER_SRC =../src/tb/tb_aes_decipher_block.v
+
+CC=iverilog
+
+
+all: top.sim core.sim keymem.sim encipher.sim decipher.sim
+
+top.sim: $(TB_TOP_SRC) $(TOP_SRC)
+ $(CC) -o top.sim $(TB_TOP_SRC) $(TOP_SRC)
+
+
+core.sim: $(TB_CORE_SRC) $(CORE_SRC)
+ $(CC) -o core.sim $(TB_CORE_SRC) $(CORE_SRC)
+
+
+keymem.sim: $(TB_KEYMEM_SRC) $(KEYGEN_SRC) $(SBOX_SRC)
+ $(CC) -o keymem.sim $(TB_KEYMEM_SRC) $(KEYMEM_SRC) $(SBOX_SRC)
+
+
+encipher.sim: $(TB_ENCIPHER_SRC) $(ENCIPHER_SRC) $(SBOX_SRC)
+ $(CC) -o encipher.sim $(TB_ENCIPHER_SRC) $(ENCIPHER_SRC) $(SBOX_SRC)
+
+
+decipher.sim: $(TB_DECIPHER_SRC) $(DECIPHER_SRC) $(INV_SBOX_SRC)
+ $(CC) -o decipher.sim $(TB_DECIPHER_SRC) $(DECIPHER_SRC) $(INV_SBOX_SRC)
+
+
+sim-keymem: keymem.sim
+ ./keymem.sim
+
+
+sim-encipher: encipher.sim
+ ./encipher.sim
+
+
+sim-decipher: decipher.sim
+ ./decipher.sim
+
+
+sim-core: core.sim
+ ./core.sim
+
+
+sim-top: top.sim
+ ./top.sim
+
+
+clean:
+ rm -f decipher.sim
+ rm -f encipher.sim
+ rm -f keymem.sim
+ rm -f core.sim
+ rm -f top.sim
+
+
+help:
+ @echo "Build system for simulation of AES Verilog core"
+ @echo ""
+ @echo "Supported targets:"
+ @echo "------------------"
+ @echo "all: Build all simulation targets."
+ @echo "top.sim: Build top level simulation target."
+ @echo "core.sim: Build core level simulation target."
+ @echo "keymem.sim: Build key memory simulation target."
+ @echo "encipher.sim: Build encipher block simulation target."
+ @echo "decipher.sim: Build decipher block simulation target."
+ @echo "sim-top: Run top level simulation."
+ @echo "sim-core: Run core level simulation."
+ @echo "sim-keymem Run keymem simulation."
+ @echo "sim-encipher Run encipher block simulation."
+ @echo "sim-decipher Run decipher block simulation."
+ @echo "clean: Delete all built files."
+
+#===================================================================
+# EOF Makefile
+#===================================================================
diff --git a/cipher/chacha/LICENSE.txt b/cipher/chacha/LICENSE.txt
new file mode 100644
index 0000000..50b916a
--- /dev/null
+++ b/cipher/chacha/LICENSE.txt
@@ -0,0 +1,27 @@
+Copyright (c) 2011, NORDUnet A/S All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+- Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+- Neither the name of the NORDUnet nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cipher/chacha/README.md b/cipher/chacha/README.md
new file mode 100644
index 0000000..aced79f
--- /dev/null
+++ b/cipher/chacha/README.md
@@ -0,0 +1,49 @@
+chacha
+========
+
+Verilog 2001 implementation of the ChaCha stream cipher.
+
+## Functionality ##
+This core implements ChaCha with support for 128 and 256 bit keys. The
+number of rounds can be set from two to 32 rounds in steps of two. The
+default number of rounds is eight.
+
+The core contains an internal 64-bit block counter that is automatically
+updated for each data block.
+
+
+## Performance ##
+Each quarterround takes one cycle which means that the mininum latency
+will be 4*rounds. When the core is functionally correct we will add two
+more version with 2 and 4 parallel quarterrounds respectively. The four
+quarterounds version will achieve 1 cycle/round.
+
+
+## Implementation ##
+Implementation results using the Altera Quartus 13 design tool.
+
+### Cyclone IV GX ###
+- 6233 LEs
+- 3677 registers
+- 56.1 MHz
+- 11 cycles latency
+- 2.6 Gbps performance.
+
+
+### Cyclone V GX ###
+- 2631 ALMs for logic
+- 3677 registers
+- 54.3 MHz
+- 11 cycles latency
+- 2.5 Gbps performance.
+
+
+## Status ##
+
+(2014-09-03)
+- Added a new port in the core to allow setting of the initial value of
+the counter. The top level wrapper currently sets this value to a
+constant zero.
+
+- Added the ChaCha core to Cryptech.
+
diff --git a/cipher/chacha/src/model/python/chacha.py b/cipher/chacha/src/model/python/chacha.py
new file mode 100755
index 0000000..c48b2d0
--- /dev/null
+++ b/cipher/chacha/src/model/python/chacha.py
@@ -0,0 +1,696 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#=======================================================================
+#
+# chacha.py
+# ---------
+# Simple model of the ChaCha stream cipher. Used as a reference for
+# the HW implementation. The code follows the structure of the
+# HW implementation as much as possible.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2011, NORDUnet A/S All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# - Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# - Neither the name of the NORDUnet nor the names of its contributors may
+# be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#=======================================================================
+
+#-------------------------------------------------------------------
+# Python module imports.
+#-------------------------------------------------------------------
+import sys
+
+
+#-------------------------------------------------------------------
+# Constants.
+#-------------------------------------------------------------------
+TAU = [0x61707865, 0x3120646e, 0x79622d36, 0x6b206574]
+SIGMA = [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574]
+
+
+#-------------------------------------------------------------------
+# ChaCha()
+#-------------------------------------------------------------------
+class ChaCha():
+
+ #---------------------------------------------------------------
+ # __init__()
+ #
+ # Given the key, iv initializes the state of the cipher.
+ # The number of rounds used can be set. By default 8 rounds
+ # are used. Accepts a list of either 16 or 32 bytes as key.
+ # Accepts a list of 8 bytes as IV.
+ #---------------------------------------------------------------
+ def __init__(self, key, iv, rounds = 8, verbose = 0):
+ self.state = [0] * 16
+ self.x = [0] * 16
+ self.rounds = rounds
+ self.verbose = verbose
+ self.set_key_iv(key, iv)
+
+
+ #---------------------------------------------------------------
+ # set_key_iv()
+ #
+ # Set key and iv. Basically reinitialize the cipher.
+ # This also resets the block counter.
+ #---------------------------------------------------------------
+ def set_key_iv(self, key, iv):
+ keyword0 = self._b2w(key[0:4])
+ keyword1 = self._b2w(key[4:8])
+ keyword2 = self._b2w(key[8:12])
+ keyword3 = self._b2w(key[12:16])
+
+ if len(key) == 16:
+ self.state[0] = TAU[0]
+ self.state[1] = TAU[1]
+ self.state[2] = TAU[2]
+ self.state[3] = TAU[3]
+ self.state[4] = keyword0
+ self.state[5] = keyword1
+ self.state[6] = keyword2
+ self.state[7] = keyword3
+ self.state[8] = keyword0
+ self.state[9] = keyword1
+ self.state[10] = keyword2
+ self.state[11] = keyword3
+
+ elif len(key) == 32:
+ keyword4 = self._b2w(key[16:20])
+ keyword5 = self._b2w(key[20:24])
+ keyword6 = self._b2w(key[24:28])
+ keyword7 = self._b2w(key[28:32])
+ self.state[0] = SIGMA[0]
+ self.state[1] = SIGMA[1]
+ self.state[2] = SIGMA[2]
+ self.state[3] = SIGMA[3]
+ self.state[4] = keyword0
+ self.state[5] = keyword1
+ self.state[6] = keyword2
+ self.state[7] = keyword3
+ self.state[8] = keyword4
+ self.state[9] = keyword5
+ self.state[10] = keyword6
+ self.state[11] = keyword7
+ else:
+ print("Key length of %d bits, is not supported." % (len(key) * 8))
+
+ # Common state init for both key lengths.
+ self.block_counter = [0, 0]
+ self.state[12] = self.block_counter[0]
+ self.state[13] = self.block_counter[1]
+ self.state[14] = self._b2w(iv[0:4])
+ self.state[15] = self._b2w(iv[4:8])
+
+ if self.verbose:
+ print("State after init:")
+ self._print_state()
+
+
+ #---------------------------------------------------------------
+ # next()
+ #
+ # Encyp/decrypt the next block. This also updates the
+ # internal state and increases the block counter.
+ #---------------------------------------------------------------
+ def next(self, data_in):
+ # Copy the current internal state to the temporary state x.
+ self.x = self.state[:]
+
+ if self.verbose:
+ print("State before round processing.")
+ self._print_state()
+
+ if self.verbose:
+ print("X before round processing:")
+ self._print_x()
+
+ # Update the internal state by performing
+ # (rounds / 2) double rounds.
+ for i in range(int(self.rounds / 2)):
+ if (self.verbose > 1):
+ print("Doubleround 0x%02x:" % i)
+ self._doubleround()
+ if (self.verbose > 1):
+ print("")
+
+ if self.verbose:
+ print("X after round processing:")
+ self._print_x()
+
+ # Update the internal state by adding the elements
+ # of the temporary state to the internal state.
+ self.state = [((self.state[i] + self.x[i]) & 0xffffffff) for i in range(16)]
+
+ if self.verbose:
+ print("State after round processing.")
+ self._print_state()
+
+ bytestate = []
+ for i in self.state:
+ bytestate += self._w2b(i)
+
+ # Create the data out words.
+ data_out = [data_in[i] ^ bytestate[i] for i in range(64)]
+
+ # Update the block counter.
+ self._inc_counter()
+
+ return data_out
+
+
+ #---------------------------------------------------------------
+ # _doubleround()
+ #
+ # Perform the two complete rounds that comprises the
+ # double round.
+ #---------------------------------------------------------------
+ def _doubleround(self):
+ if (self.verbose > 0):
+ print("Start of double round processing.")
+
+ self._quarterround(0, 4, 8, 12)
+ if (self.verbose > 1):
+ print("X after QR 0")
+ self._print_x()
+ self._quarterround(1, 5, 9, 13)
+ if (self.verbose > 1):
+ print("X after QR 1")
+ self._print_x()
+ self._quarterround(2, 6, 10, 14)
+ if (self.verbose > 1):
+ print("X after QR 2")
+ self._print_x()
+ self._quarterround(3, 7, 11, 15)
+ if (self.verbose > 1):
+ print("X after QR 3")
+ self._print_x()
+
+ self._quarterround(0, 5, 10, 15)
+ if (self.verbose > 1):
+ print("X after QR 4")
+ self._print_x()
+ self._quarterround(1, 6, 11, 12)
+ if (self.verbose > 1):
+ print("X after QR 5")
+ self._print_x()
+ self._quarterround(2, 7, 8, 13)
+ if (self.verbose > 1):
+ print("X after QR 6")
+ self._print_x()
+ self._quarterround(3, 4, 9, 14)
+ if (self.verbose > 1):
+ print("X after QR 7")
+ self._print_x()
+
+ if (self.verbose > 0):
+ print("End of double round processing.")
+
+
+ #---------------------------------------------------------------
+ # _quarterround()
+ #
+ # Updates four elements in the state vector x given by
+ # their indices.
+ #---------------------------------------------------------------
+ def _quarterround(self, ai, bi, ci, di):
+ # Extract four elemenst from x using the qi tuple.
+ a, b, c, d = self.x[ai], self.x[bi], self.x[ci], self.x[di]
+
+ if (self.verbose > 1):
+ print("Indata to quarterround:")
+ print("X state indices:", ai, bi, ci, di)
+ print("a = 0x%08x, b = 0x%08x, c = 0x%08x, d = 0x%08x" %\
+ (a, b, c, d))
+ print("")
+
+ a0 = (a + b) & 0xffffffff
+ d0 = d ^ a0
+ d1 = ((d0 << 16) + (d0 >> 16)) & 0xffffffff
+ c0 = (c + d1) & 0xffffffff
+ b0 = b ^ c0
+ b1 = ((b0 << 12) + (b0 >> 20)) & 0xffffffff
+ a1 = (a0 + b1) & 0xffffffff
+ d2 = d1 ^ a1
+ d3 = ((d2 << 8) + (d2 >> 24)) & 0xffffffff
+ c1 = (c0 + d3) & 0xffffffff
+ b2 = b1 ^ c1
+ b3 = ((b2 << 7) + (b2 >> 25)) & 0xffffffff
+
+ if (self.verbose > 2):
+ print("Intermediate values:")
+ print("a0 = 0x%08x, a1 = 0x%08x" % (a0, a1))
+ print("b0 = 0x%08x, b1 = 0x%08x, b2 = 0x%08x, b3 = 0x%08x" %\
+ (b0, b1, b2, b3))
+ print("c0 = 0x%08x, c1 = 0x%08x" % (c0, c1))
+ print("d0 = 0x%08x, d1 = 0x%08x, d2 = 0x%08x, d3 = 0x%08x" %\
+ (d0, d1, d2, d3))
+ print("")
+
+ a_prim = a1
+ b_prim = b3
+ c_prim = c1
+ d_prim = d3
+
+ if (self.verbose > 1):
+ print("Outdata from quarterround:")
+ print("a_prim = 0x%08x, b_prim = 0x%08x, c_prim = 0x%08x, d_prim = 0x%08x" %\
+ (a_prim, b_prim, c_prim, d_prim))
+ print("")
+
+ # Update the four elemenst in x using the qi tuple.
+ self.x[ai], self.x[bi] = a_prim, b_prim
+ self.x[ci], self.x[di] = c_prim, d_prim
+
+
+ #---------------------------------------------------------------
+ # _inc_counter()
+ #
+ # Increase the 64 bit block counter.
+ #---------------------------------------------------------------
+ def _inc_counter(self):
+ self.block_counter[0] += 1 & 0xffffffff
+ if not (self.block_counter[0] % 0xffffffff):
+ self.block_counter[1] += 1 & 0xffffffff
+
+
+ #---------------------------------------------------------------
+ # _b2w()
+ #
+ # Given a list of four bytes returns the little endian
+ # 32 bit word representation of the bytes.
+ #---------------------------------------------------------------
+ def _b2w(self, bytes):
+ return (bytes[0] + (bytes[1] << 8)
+ + (bytes[2] << 16) + (bytes[3] << 24)) & 0xffffffff
+
+
+ #---------------------------------------------------------------
+ # _w2b()
+ #
+ # Given a 32-bit word returns a list of set of four bytes
+ # that is the little endian byte representation of the word.
+ #---------------------------------------------------------------
+ def _w2b(self, word):
+ return [(word & 0x000000ff), ((word & 0x0000ff00) >> 8),
+ ((word & 0x00ff0000) >> 16), ((word & 0xff000000) >> 24)]
+
+
+ #---------------------------------------------------------------
+ # _print_state()
+ #
+ # Print the internal state.
+ #---------------------------------------------------------------
+ def _print_state(self):
+ print(" 0: 0x%08x, 1: 0x%08x, 2: 0x%08x, 3: 0x%08x" %\
+ (self.state[0], self.state[1], self.state[2], self.state[3]))
+ print(" 4: 0x%08x, 5: 0x%08x, 6: 0x%08x, 7: 0x%08x" %\
+ (self.state[4], self.state[5], self.state[6], self.state[7]))
+ print(" 8: 0x%08x, 9: 0x%08x, 10: 0x%08x, 11: 0x%08x" %\
+ (self.state[8], self.state[9], self.state[10], self.state[11]))
+ print("12: 0x%08x, 13: 0x%08x, 14: 0x%08x, 15: 0x%08x" %\
+ (self.state[12], self.state[13], self.state[14], self.state[15]))
+ print("")
+
+
+ #---------------------------------------------------------------
+ # _print_x()
+ #
+ # Print the temporary state X.
+ #---------------------------------------------------------------
+ def _print_x(self):
+ print(" 0: 0x%08x, 1: 0x%08x, 2: 0x%08x, 3: 0x%08x" %\
+ (self.x[0], self.x[1], self.x[2], self.x[3]))
+ print(" 4: 0x%08x, 5: 0x%08x, 6: 0x%08x, 7: 0x%08x" %\
+ (self.x[4], self.x[5], self.x[6], self.x[7]))
+ print(" 8: 0x%08x, 9: 0x%08x, 10: 0x%08x, 11: 0x%08x" %\
+ (self.x[8], self.x[9], self.x[10], self.x[11]))
+ print("12: 0x%08x, 13: 0x%08x, 14: 0x%08x, 15: 0x%08x" %\
+ (self.x[12], self.x[13], self.x[14], self.x[15]))
+ print("")
+
+
+#-------------------------------------------------------------------
+# print_block()
+#
+# Print a given block (list) of bytes ordered in
+# rows of eight bytes.
+#-------------------------------------------------------------------
+def print_block(block):
+ for i in range(0, len(block), 8):
+ print("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x" %\
+ (block[i], block[i+1], block[i+2], block[i+3],
+ block[i+4], block[i+5], block[i+6], block[i+7]))
+
+
+#-------------------------------------------------------------------
+# check_block()
+#
+# Compare the result block with the expected block and print
+# if the result for the given test case was correct or not.
+#-------------------------------------------------------------------
+def check_block(result, expected, test_case):
+ if result == expected:
+ print("SUCCESS: %s was correct." % test_case)
+ else:
+ print("ERROR: %s was not correct." % test_case)
+ print("Expected:")
+ print_block(expected)
+ print("")
+ print("Result:")
+ print_block(result)
+ print("")
+
+
+#-------------------------------------------------------------------
+# main()
+#
+# If executed tests the ChaCha class using known test vectors.
+#-------------------------------------------------------------------
+def main():
+ print("Testing the ChaCha Python model.")
+ print("--------------------------------")
+ print
+
+ # Testing with TC1-128-8.
+ # All zero inputs. IV all zero. 128 bit key, 8 rounds.
+ print("TC1-128-8: All zero inputs. 128 bit key, 8 rounds.")
+ key1 = [0x00] * 16
+ iv1 = [0x00] * 8
+ expected1 = [0xe2, 0x8a, 0x5f, 0xa4, 0xa6, 0x7f, 0x8c, 0x5d,
+ 0xef, 0xed, 0x3e, 0x6f, 0xb7, 0x30, 0x34, 0x86,
+ 0xaa, 0x84, 0x27, 0xd3, 0x14, 0x19, 0xa7, 0x29,
+ 0x57, 0x2d, 0x77, 0x79, 0x53, 0x49, 0x11, 0x20,
+ 0xb6, 0x4a, 0xb8, 0xe7, 0x2b, 0x8d, 0xeb, 0x85,
+ 0xcd, 0x6a, 0xea, 0x7c, 0xb6, 0x08, 0x9a, 0x10,
+ 0x18, 0x24, 0xbe, 0xeb, 0x08, 0x81, 0x4a, 0x42,
+ 0x8a, 0xab, 0x1f, 0xa2, 0xc8, 0x16, 0x08, 0x1b]
+ block1 = [0x00] * 64
+ cipher1 = ChaCha(key1, iv1, verbose=0)
+ result1 = cipher1.next(block1)
+ check_block(result1, expected1, "TC1-128-8")
+ print
+
+
+ # Testing with TC1-128-12.
+ # All zero inputs. IV all zero. 128 bit key, 12 rounds.
+ print("TC1-128-12: All zero inputs. 128 bit key, 12 rounds.")
+ key1 = [0x00] * 16
+ iv1 = [0x00] * 8
+ expected1 = [0xe1, 0x04, 0x7b, 0xa9, 0x47, 0x6b, 0xf8, 0xff,
+ 0x31, 0x2c, 0x01, 0xb4, 0x34, 0x5a, 0x7d, 0x8c,
+ 0xa5, 0x79, 0x2b, 0x0a, 0xd4, 0x67, 0x31, 0x3f,
+ 0x1d, 0xc4, 0x12, 0xb5, 0xfd, 0xce, 0x32, 0x41,
+ 0x0d, 0xea, 0x8b, 0x68, 0xbd, 0x77, 0x4c, 0x36,
+ 0xa9, 0x20, 0xf0, 0x92, 0xa0, 0x4d, 0x3f, 0x95,
+ 0x27, 0x4f, 0xbe, 0xff, 0x97, 0xbc, 0x84, 0x91,
+ 0xfc, 0xef, 0x37, 0xf8, 0x59, 0x70, 0xb4, 0x50]
+ block1 = [0x00] * 64
+ cipher1 = ChaCha(key1, iv1, rounds = 12, verbose=0)
+ result1 = cipher1.next(block1)
+ check_block(result1, expected1, "TC1-128-12")
+ print
+
+
+ # Testing with TC1-128-20.
+ # All zero inputs. IV all zero. 128 bit key, 20 rounds.
+ print("TC1-128-20: All zero inputs. 128 bit key, 20 rounds.")
+ key1 = [0x00] * 16
+ iv1 = [0x00] * 8
+ expected1 = [0x89, 0x67, 0x09, 0x52, 0x60, 0x83, 0x64, 0xfd,
+ 0x00, 0xb2, 0xf9, 0x09, 0x36, 0xf0, 0x31, 0xc8,
+ 0xe7, 0x56, 0xe1, 0x5d, 0xba, 0x04, 0xb8, 0x49,
+ 0x3d, 0x00, 0x42, 0x92, 0x59, 0xb2, 0x0f, 0x46,
+ 0xcc, 0x04, 0xf1, 0x11, 0x24, 0x6b, 0x6c, 0x2c,
+ 0xe0, 0x66, 0xbe, 0x3b, 0xfb, 0x32, 0xd9, 0xaa,
+ 0x0f, 0xdd, 0xfb, 0xc1, 0x21, 0x23, 0xd4, 0xb9,
+ 0xe4, 0x4f, 0x34, 0xdc, 0xa0, 0x5a, 0x10, 0x3f]
+ block1 = [0x00] * 64
+ cipher1 = ChaCha(key1, iv1, rounds = 20, verbose=0)
+ result1 = cipher1.next(block1)
+ check_block(result1, expected1, "TC1-128-20")
+ print
+
+
+ # Testing with TC1-256-8.
+ # All zero inputs. IV all zero. 256 bit key, 8 rounds.
+ print("TC1-256-8: All zero inputs. 256 bit key, 8 rounds.")
+ key1 = [0x00] * 32
+ iv1 = [0x00] * 8
+ expected1 = [0x3e, 0x00, 0xef, 0x2f, 0x89, 0x5f, 0x40, 0xd6,
+ 0x7f, 0x5b, 0xb8, 0xe8, 0x1f, 0x09, 0xa5, 0xa1,
+ 0x2c, 0x84, 0x0e, 0xc3, 0xce, 0x9a, 0x7f, 0x3b,
+ 0x18, 0x1b, 0xe1, 0x88, 0xef, 0x71, 0x1a, 0x1e,
+ 0x98, 0x4c, 0xe1, 0x72, 0xb9, 0x21, 0x6f, 0x41,
+ 0x9f, 0x44, 0x53, 0x67, 0x45, 0x6d, 0x56, 0x19,
+ 0x31, 0x4a, 0x42, 0xa3, 0xda, 0x86, 0xb0, 0x01,
+ 0x38, 0x7b, 0xfd, 0xb8, 0x0e, 0x0c, 0xfe, 0x42]
+ block1 = [0x00] * 64
+ cipher1 = ChaCha(key1, iv1, verbose=0)
+ result1 = cipher1.next(block1)
+ check_block(result1, expected1, "TC1-256-8")
+ print
+
+
+ # Testing with TC1-256-12.
+ # All zero inputs. IV all zero. 256 bit key, 12 rounds.
+ print("TC1-256-12: All zero inputs. 256 bit key, 12 rounds.")
+ key1 = [0x00] * 32
+ iv1 = [0x00] * 8
+ expected1 = [0x9b, 0xf4, 0x9a, 0x6a, 0x07, 0x55, 0xf9, 0x53,
+ 0x81, 0x1f, 0xce, 0x12, 0x5f, 0x26, 0x83, 0xd5,
+ 0x04, 0x29, 0xc3, 0xbb, 0x49, 0xe0, 0x74, 0x14,
+ 0x7e, 0x00, 0x89, 0xa5, 0x2e, 0xae, 0x15, 0x5f,
+ 0x05, 0x64, 0xf8, 0x79, 0xd2, 0x7a, 0xe3, 0xc0,
+ 0x2c, 0xe8, 0x28, 0x34, 0xac, 0xfa, 0x8c, 0x79,
+ 0x3a, 0x62, 0x9f, 0x2c, 0xa0, 0xde, 0x69, 0x19,
+ 0x61, 0x0b, 0xe8, 0x2f, 0x41, 0x13, 0x26, 0xbe]
+ block1 = [0x00] * 64
+ cipher1 = ChaCha(key1, iv1, rounds = 12, verbose=0)
+ result1 = cipher1.next(block1)
+ check_block(result1, expected1, "TC1-256-12")
+ print
+
+
+ # Testing with TC1-256-20.
+ # All zero inputs. IV all zero. 256 bit key, 20 rounds.
+ print("TC1-256-20: All zero inputs. 256 bit key, 20 rounds.")
+ key1 = [0x00] * 32
+ iv1 = [0x00] * 8
+ expected1 = [0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+ 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+ 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+ 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
+ 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
+ 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
+ 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
+ 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86]
+ block1 = [0x00] * 64
+ cipher1 = ChaCha(key1, iv1, rounds = 20, verbose=0)
+ result1 = cipher1.next(block1)
+ check_block(result1, expected1, "TC1-256-20")
+ print
+
+
+ # Testing with TC2-128-8.
+ # Single bit set in key. IV all zero. 128 bit key.
+ print("TC2-128-8: One bit in key set. IV all zeros. 128 bit key, 8 rounds.")
+ key2 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+ iv2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+ expected2 = [0x03, 0xa7, 0x66, 0x98, 0x88, 0x60, 0x5a, 0x07,
+ 0x65, 0xe8, 0x35, 0x74, 0x75, 0xe5, 0x86, 0x73,
+ 0xf9, 0x4f, 0xc8, 0x16, 0x1d, 0xa7, 0x6c, 0x2a,
+ 0x3a, 0xa2, 0xf3, 0xca, 0xf9, 0xfe, 0x54, 0x49,
+ 0xe0, 0xfc, 0xf3, 0x8e, 0xb8, 0x82, 0x65, 0x6a,
+ 0xf8, 0x3d, 0x43, 0x0d, 0x41, 0x09, 0x27, 0xd5,
+ 0x5c, 0x97, 0x2a, 0xc4, 0xc9, 0x2a, 0xb9, 0xda,
+ 0x37, 0x13, 0xe1, 0x9f, 0x76, 0x1e, 0xaa, 0x14]
+ block2 = [0x00] * 64
+ cipher2 = ChaCha(key2, iv2, verbose=0)
+ result2 = cipher2.next(block2)
+ check_block(result2, expected2, "TC2-128-8")
+ print
+
+
+ # Testing with TC2-256-8.
+ # Single bit set in key. IV all zero. 256 bit key.
+ print("TC2-256-8: One bit in key set. IV all zeros. 256 bit key, 8 rounds.")
+ key2 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+ iv2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+ expected2 = [0xcf, 0x5e, 0xe9, 0xa0, 0x49, 0x4a, 0xa9, 0x61,
+ 0x3e, 0x05, 0xd5, 0xed, 0x72, 0x5b, 0x80, 0x4b,
+ 0x12, 0xf4, 0xa4, 0x65, 0xee, 0x63, 0x5a, 0xcc,
+ 0x3a, 0x31, 0x1d, 0xe8, 0x74, 0x04, 0x89, 0xea,
+ 0x28, 0x9d, 0x04, 0xf4, 0x3c, 0x75, 0x18, 0xdb,
+ 0x56, 0xeb, 0x44, 0x33, 0xe4, 0x98, 0xa1, 0x23,
+ 0x8c, 0xd8, 0x46, 0x4d, 0x37, 0x63, 0xdd, 0xbb,
+ 0x92, 0x22, 0xee, 0x3b, 0xd8, 0xfa, 0xe3, 0xc8]
+ block2 = [0x00] * 64
+ cipher2 = ChaCha(key2, iv2, verbose=0)
+ result2 = cipher2.next(block2)
+ check_block(result2, expected2, "TC2-256-8")
+ print
+
+
+ # Testing with TC3-128-8.
+ # All zero key. Single bit in IV set. 128 bit key.
+ print("TC3-128-8: All zero key. Single bit in IV set. 128 bit key, 8 rounds.")
+ key3 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+ iv3 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+ expected3 = [0x25, 0xf5, 0xbe, 0xc6, 0x68, 0x39, 0x16, 0xff,
+ 0x44, 0xbc, 0xcd, 0x12, 0xd1, 0x02, 0xe6, 0x92,
+ 0x17, 0x66, 0x63, 0xf4, 0xca, 0xc5, 0x3e, 0x71,
+ 0x95, 0x09, 0xca, 0x74, 0xb6, 0xb2, 0xee, 0xc8,
+ 0x5d, 0xa4, 0x23, 0x6f, 0xb2, 0x99, 0x02, 0x01,
+ 0x2a, 0xdc, 0x8f, 0x0d, 0x86, 0xc8, 0x18, 0x7d,
+ 0x25, 0xcd, 0x1c, 0x48, 0x69, 0x66, 0x93, 0x0d,
+ 0x02, 0x04, 0xc4, 0xee, 0x88, 0xa6, 0xab, 0x35]
+ block3 = [0x00] * 64
+ cipher3 = ChaCha(key3, iv3, verbose=0)
+ result3 = cipher3.next(block3)
+ check_block(result3, expected3, "TC3-128-8")
+ print
+
+
+ # Testing with TC4-128-8.
+ # All bits in key IV are set. 128 bit key, 8 rounds.
+ print("TC4-128-8: All bits in key IV are set. 128 bit key, 8 rounds.")
+ key4 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
+ iv4 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
+ expected4 = [0x22, 0x04, 0xd5, 0xb8, 0x1c, 0xe6, 0x62, 0x19,
+ 0x3e, 0x00, 0x96, 0x60, 0x34, 0xf9, 0x13, 0x02,
+ 0xf1, 0x4a, 0x3f, 0xb0, 0x47, 0xf5, 0x8b, 0x6e,
+ 0x6e, 0xf0, 0xd7, 0x21, 0x13, 0x23, 0x04, 0x16,
+ 0x3e, 0x0f, 0xb6, 0x40, 0xd7, 0x6f, 0xf9, 0xc3,
+ 0xb9, 0xcd, 0x99, 0x99, 0x6e, 0x6e, 0x38, 0xfa,
+ 0xd1, 0x3f, 0x0e, 0x31, 0xc8, 0x22, 0x44, 0xd3,
+ 0x3a, 0xbb, 0xc1, 0xb1, 0x1e, 0x8b, 0xf1, 0x2d]
+ block4 = [0x00] * 64
+ cipher4 = ChaCha(key4, iv4, verbose=0)
+ result4 = cipher4.next(block4)
+ check_block(result4, expected4, "TC4-128-8")
+ print
+
+
+ # Testing with TC5-128-8
+ print("TC5-128-8: Even bits set. 128 bit key, 8 rounds.")
+ key5 = [0x55] * 16
+ iv5 = [0x55] * 8
+ expected5 = [0xf0, 0xa2, 0x3b, 0xc3, 0x62, 0x70, 0xe1, 0x8e,
+ 0xd0, 0x69, 0x1d, 0xc3, 0x84, 0x37, 0x4b, 0x9b,
+ 0x2c, 0x5c, 0xb6, 0x01, 0x10, 0xa0, 0x3f, 0x56,
+ 0xfa, 0x48, 0xa9, 0xfb, 0xba, 0xd9, 0x61, 0xaa,
+ 0x6b, 0xab, 0x4d, 0x89, 0x2e, 0x96, 0x26, 0x1b,
+ 0x6f, 0x1a, 0x09, 0x19, 0x51, 0x4a, 0xe5, 0x6f,
+ 0x86, 0xe0, 0x66, 0xe1, 0x7c, 0x71, 0xa4, 0x17,
+ 0x6a, 0xc6, 0x84, 0xaf, 0x1c, 0x93, 0x19, 0x96]
+ block5 = [0x00] * 64
+ cipher5 = ChaCha(key5, iv5, verbose=0)
+ result5 = cipher5.next(block5)
+ check_block(result5, expected5, "TC5-128-8")
+ print
+
+
+ # Testing with TC6-128-8
+ print("TC6-128-8: Odd bits set. 128 bit key, 8 rounds.")
+ key6 = [0xaa] * 16
+ iv6 = [0xaa] * 8
+ expected6 = [0x31, 0x2d, 0x95, 0xc0, 0xbc, 0x38, 0xef, 0xf4,
+ 0x94, 0x2d, 0xb2, 0xd5, 0x0b, 0xdc, 0x50, 0x0a,
+ 0x30, 0x64, 0x1e, 0xf7, 0x13, 0x2d, 0xb1, 0xa8,
+ 0xae, 0x83, 0x8b, 0x3b, 0xea, 0x3a, 0x7a, 0xb0,
+ 0x38, 0x15, 0xd7, 0xa4, 0xcc, 0x09, 0xdb, 0xf5,
+ 0x88, 0x2a, 0x34, 0x33, 0xd7, 0x43, 0xac, 0xed,
+ 0x48, 0x13, 0x6e, 0xba, 0xb7, 0x32, 0x99, 0x50,
+ 0x68, 0x55, 0xc0, 0xf5, 0x43, 0x7a, 0x36, 0xc6]
+ block6 = [0x00] * 64
+ cipher6 = ChaCha(key6, iv6, verbose=0)
+ result6 = cipher6.next(block6)
+ check_block(result6, expected6, "TC6-128-8")
+ print
+
+
+ # Testing with TC7-128-8
+ print("TC7-128-8: Key and IV are increasing, decreasing patterns. 128 bit key, 8 rounds.")
+ key7 = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]
+ iv7 = [0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x59, 0x68, 0x77]
+ expected7 = [0xa7, 0xa6, 0xc8, 0x1b, 0xd8, 0xac, 0x10, 0x6e,
+ 0x8f, 0x3a, 0x46, 0xa1, 0xbc, 0x8e, 0xc7, 0x02,
+ 0xe9, 0x5d, 0x18, 0xc7, 0xe0, 0xf4, 0x24, 0x51,
+ 0x9a, 0xea, 0xfb, 0x54, 0x47, 0x1d, 0x83, 0xa2,
+ 0xbf, 0x88, 0x88, 0x61, 0x58, 0x6b, 0x73, 0xd2,
+ 0x28, 0xea, 0xaf, 0x82, 0xf9, 0x66, 0x5a, 0x5a,
+ 0x15, 0x5e, 0x86, 0x7f, 0x93, 0x73, 0x1b, 0xfb,
+ 0xe2, 0x4f, 0xab, 0x49, 0x55, 0x90, 0xb2, 0x31]
+ block7 = [0x00] * 64
+ cipher7 = ChaCha(key7, iv7, verbose=2)
+ result7 = cipher7.next(block7)
+ check_block(result7, expected7, "TC7-128-8")
+ print
+
+
+ # Testing with TC8-128-8
+ print("TC8-128-8: Random inputs. 128 bit key, 8 rounds.")
+ key8 = [0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78,
+ 0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35]
+ iv8 = [0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21]
+ expected8 = [0x6a, 0x87, 0x01, 0x08, 0x85, 0x9f, 0x67, 0x91,
+ 0x18, 0xf3, 0xe2, 0x05, 0xe2, 0xa5, 0x6a, 0x68,
+ 0x26, 0xef, 0x5a, 0x60, 0xa4, 0x10, 0x2a, 0xc8,
+ 0xd4, 0x77, 0x00, 0x59, 0xfc, 0xb7, 0xc7, 0xba,
+ 0xe0, 0x2f, 0x5c, 0xe0, 0x04, 0xa6, 0xbf, 0xbb,
+ 0xea, 0x53, 0x01, 0x4d, 0xd8, 0x21, 0x07, 0xc0,
+ 0xaa, 0x1c, 0x7c, 0xe1, 0x1b, 0x7d, 0x78, 0xf2,
+ 0xd5, 0x0b, 0xd3, 0x60, 0x2b, 0xbd, 0x25, 0x94]
+ block8 = [0x00] * 64
+ cipher8 = ChaCha(key8, iv8, verbose=0)
+ result8 = cipher8.next(block8)
+ check_block(result8, expected8, "TC8-128-8")
+ print
+
+
+#-------------------------------------------------------------------
+# __name__
+# Python thingy which allows the file to be run standalone as
+# well as parsed from within a Python interpreter.
+#-------------------------------------------------------------------
+if __name__=="__main__":
+ # Run the main function.
+ sys.exit(main())
+
+#=======================================================================
+# EOF chacha.py
+#=======================================================================
diff --git a/cipher/chacha/src/rtl/chacha.v b/cipher/chacha/src/rtl/chacha.v
new file mode 100644
index 0000000..72792aa
--- /dev/null
+++ b/cipher/chacha/src/rtl/chacha.v
@@ -0,0 +1,880 @@
+//======================================================================
+//
+// chacha.v
+// --------
+// Top level wrapper for the ChaCha stream, cipher core providing
+// a simple memory like interface with 32 bit data access.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2011, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module chacha(
+ // Clock and reset.
+ input wire clk,
+ input wire reset_n,
+
+ // Control.
+ input wire cs,
+ input wire we,
+
+ // Data ports.
+ input wire [7 : 0] address,
+ input wire [31 : 0] write_data,
+ output wire [31 : 0] read_data,
+ output wire error
+ );
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter ADDR_CTRL = 8'h00;
+ parameter CTRL_INIT_BIT = 0;
+ parameter CTRL_NEXT_BIT = 1;
+
+ parameter ADDR_STATUS = 8'h01;
+ parameter STATUS_READY_BIT = 0;
+
+ parameter ADDR_KEYLEN = 8'h08;
+ parameter KEYLEN_BIT = 0;
+ parameter ADDR_ROUNDS = 8'h09;
+ parameter ROUNDS_HIGH_BIT = 4;
+ parameter ROUNDS_LOW_BIT = 0;
+
+ parameter ADDR_KEY0 = 8'h10;
+ parameter ADDR_KEY1 = 8'h11;
+ parameter ADDR_KEY2 = 8'h12;
+ parameter ADDR_KEY3 = 8'h13;
+ parameter ADDR_KEY4 = 8'h14;
+ parameter ADDR_KEY5 = 8'h15;
+ parameter ADDR_KEY6 = 8'h16;
+ parameter ADDR_KEY7 = 8'h17;
+
+ parameter ADDR_IV0 = 8'h20;
+ parameter ADDR_IV1 = 8'h21;
+
+ parameter ADDR_DATA_IN0 = 8'h40;
+ parameter ADDR_DATA_IN1 = 8'h41;
+ parameter ADDR_DATA_IN2 = 8'h42;
+ parameter ADDR_DATA_IN3 = 8'h43;
+ parameter ADDR_DATA_IN4 = 8'h44;
+ parameter ADDR_DATA_IN5 = 8'h45;
+ parameter ADDR_DATA_IN6 = 8'h46;
+ parameter ADDR_DATA_IN7 = 8'h47;
+ parameter ADDR_DATA_IN8 = 8'h48;
+ parameter ADDR_DATA_IN9 = 8'h49;
+ parameter ADDR_DATA_IN10 = 8'h4a;
+ parameter ADDR_DATA_IN11 = 8'h4b;
+ parameter ADDR_DATA_IN12 = 8'h4c;
+ parameter ADDR_DATA_IN13 = 8'h4d;
+ parameter ADDR_DATA_IN14 = 8'h4e;
+ parameter ADDR_DATA_IN15 = 8'h4f;
+
+ parameter ADDR_DATA_OUT0 = 8'h80;
+ parameter ADDR_DATA_OUT1 = 8'h81;
+ parameter ADDR_DATA_OUT2 = 8'h82;
+ parameter ADDR_DATA_OUT3 = 8'h83;
+ parameter ADDR_DATA_OUT4 = 8'h84;
+ parameter ADDR_DATA_OUT5 = 8'h85;
+ parameter ADDR_DATA_OUT6 = 8'h86;
+ parameter ADDR_DATA_OUT7 = 8'h87;
+ parameter ADDR_DATA_OUT8 = 8'h88;
+ parameter ADDR_DATA_OUT9 = 8'h89;
+ parameter ADDR_DATA_OUT10 = 8'h8a;
+ parameter ADDR_DATA_OUT11 = 8'h8b;
+ parameter ADDR_DATA_OUT12 = 8'h8c;
+ parameter ADDR_DATA_OUT13 = 8'h8d;
+ parameter ADDR_DATA_OUT14 = 8'h8e;
+ parameter ADDR_DATA_OUT15 = 8'h8f;
+
+ parameter DEFAULT_CTR_INIT = 64'h0000000000000000;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg init_reg;
+ reg next_reg;
+ reg ctrl_we;
+
+ reg ready_reg;
+
+ reg keylen_reg;
+ reg keylen_we;
+
+ reg [4 : 0] rounds_reg;
+ reg rounds_we;
+
+ reg data_out_valid_reg;
+
+ reg [31 : 0] key0_reg;
+ reg key0_we;
+ reg [31 : 0] key1_reg;
+ reg key1_we;
+ reg [31 : 0] key2_reg;
+ reg key2_we;
+ reg [31 : 0] key3_reg;
+ reg key3_we;
+ reg [31 : 0] key4_reg;
+ reg key4_we;
+ reg [31 : 0] key5_reg;
+ reg key5_we;
+ reg [31 : 0] key6_reg;
+ reg key6_we;
+ reg [31 : 0] key7_reg;
+ reg key7_we;
+
+ reg [31 : 0] iv0_reg;
+ reg iv0_we;
+ reg [31 : 0] iv1_reg;
+ reg iv1_we;
+
+ reg [31 : 0] data_in0_reg;
+ reg data_in0_we;
+ reg [31 : 0] data_in1_reg;
+ reg data_in1_we;
+ reg [31 : 0] data_in2_reg;
+ reg data_in2_we;
+ reg [31 : 0] data_in3_reg;
+ reg data_in3_we;
+ reg [31 : 0] data_in4_reg;
+ reg data_in4_we;
+ reg [31 : 0] data_in5_reg;
+ reg data_in5_we;
+ reg [31 : 0] data_in6_reg;
+ reg data_in6_we;
+ reg [31 : 0] data_in7_reg;
+ reg data_in7_we;
+ reg [31 : 0] data_in8_reg;
+ reg data_in8_we;
+ reg [31 : 0] data_in9_reg;
+ reg data_in9_we;
+ reg [31 : 0] data_in10_reg;
+ reg data_in10_we;
+ reg [31 : 0] data_in11_reg;
+ reg data_in11_we;
+ reg [31 : 0] data_in12_reg;
+ reg data_in12_we;
+ reg [31 : 0] data_in13_reg;
+ reg data_in13_we;
+ reg [31 : 0] data_in14_reg;
+ reg data_in14_we;
+ reg [31 : 0] data_in15_reg;
+ reg data_in15_we;
+
+ reg [31 : 0] data_out0_reg;
+ reg [31 : 0] data_out1_reg;
+ reg [31 : 0] data_out2_reg;
+ reg [31 : 0] data_out3_reg;
+ reg [31 : 0] data_out4_reg;
+ reg [31 : 0] data_out5_reg;
+ reg [31 : 0] data_out6_reg;
+ reg [31 : 0] data_out7_reg;
+ reg [31 : 0] data_out8_reg;
+ reg [31 : 0] data_out9_reg;
+ reg [31 : 0] data_out10_reg;
+ reg [31 : 0] data_out11_reg;
+ reg [31 : 0] data_out12_reg;
+ reg [31 : 0] data_out13_reg;
+ reg [31 : 0] data_out14_reg;
+ reg [31 : 0] data_out15_reg;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ wire core_init;
+ wire core_next;
+ wire [255 : 0] core_key;
+ wire core_keylen;
+ wire [4 : 0] core_rounds;
+ wire [63 : 0] core_iv;
+ wire core_ready;
+ wire [511 : 0] core_data_in;
+ wire [511 : 0] core_data_out;
+ wire core_data_out_valid;
+
+ reg [31 : 0] tmp_read_data;
+ reg tmp_error;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign core_init = init_reg;
+
+ assign core_next = next_reg;
+
+ assign core_keylen = keylen_reg;
+
+ assign core_rounds = rounds_reg;
+
+ assign core_key = {key0_reg, key1_reg, key2_reg, key3_reg,
+ key4_reg, key5_reg, key6_reg, key7_reg};
+
+ assign core_iv = {iv0_reg, iv1_reg};
+
+ assign core_data_in = {data_in0_reg, data_in1_reg, data_in2_reg, data_in3_reg,
+ data_in4_reg, data_in5_reg, data_in6_reg, data_in7_reg,
+ data_in8_reg, data_in9_reg, data_in10_reg, data_in11_reg,
+ data_in12_reg, data_in13_reg, data_in14_reg, data_in15_reg};
+
+ assign read_data = tmp_read_data;
+ assign error = tmp_error;
+
+
+ //----------------------------------------------------------------
+ // core instantiation.
+ //----------------------------------------------------------------
+ chacha_core core (
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .init(core_init),
+ .next(core_next),
+
+ .key(core_key),
+ .keylen(core_keylen),
+ .iv(core_iv),
+ .ctr(DEFAULT_CTR_INIT),
+ .rounds(core_rounds),
+
+ .data_in(core_data_in),
+
+ .ready(core_ready),
+
+ .data_out(core_data_out),
+ .data_out_valid(core_data_out_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ init_reg <= 0;
+ next_reg <= 0;
+ ready_reg <= 0;
+ keylen_reg <= 0;
+ rounds_reg <= 5'b00000;
+ data_out_valid_reg <= 0;
+
+ key0_reg <= 32'h00000000;
+ key1_reg <= 32'h00000000;
+ key2_reg <= 32'h00000000;
+ key3_reg <= 32'h00000000;
+ key4_reg <= 32'h00000000;
+ key5_reg <= 32'h00000000;
+ key6_reg <= 32'h00000000;
+ key7_reg <= 32'h00000000;
+
+ iv0_reg <= 32'h00000000;
+ iv1_reg <= 32'h00000000;
+
+ data_in0_reg <= 32'h00000000;
+ data_in1_reg <= 32'h00000000;
+ data_in2_reg <= 32'h00000000;
+ data_in3_reg <= 32'h00000000;
+ data_in4_reg <= 32'h00000000;
+ data_in5_reg <= 32'h00000000;
+ data_in6_reg <= 32'h00000000;
+ data_in7_reg <= 32'h00000000;
+ data_in8_reg <= 32'h00000000;
+ data_in9_reg <= 32'h00000000;
+ data_in10_reg <= 32'h00000000;
+ data_in11_reg <= 32'h00000000;
+ data_in12_reg <= 32'h00000000;
+ data_in13_reg <= 32'h00000000;
+ data_in14_reg <= 32'h00000000;
+ data_in15_reg <= 32'h00000000;
+
+ data_out0_reg <= 32'h00000000;
+ data_out1_reg <= 32'h00000000;
+ data_out2_reg <= 32'h00000000;
+ data_out3_reg <= 32'h00000000;
+ data_out4_reg <= 32'h00000000;
+ data_out5_reg <= 32'h00000000;
+ data_out6_reg <= 32'h00000000;
+ data_out7_reg <= 32'h00000000;
+ data_out8_reg <= 32'h00000000;
+ data_out9_reg <= 32'h00000000;
+ data_out10_reg <= 32'h00000000;
+ data_out11_reg <= 32'h00000000;
+ data_out12_reg <= 32'h00000000;
+ data_out13_reg <= 32'h00000000;
+ data_out14_reg <= 32'h00000000;
+ data_out15_reg <= 32'h00000000;
+ end
+ else
+ begin
+ ready_reg <= core_ready;
+ data_out_valid_reg <= core_data_out_valid;
+
+ if (ctrl_we)
+ begin
+ init_reg <= write_data[CTRL_INIT_BIT];
+ next_reg <= write_data[CTRL_NEXT_BIT];
+ end
+
+ if (keylen_we)
+ begin
+ keylen_reg <= write_data[KEYLEN_BIT];
+ end
+
+ if (rounds_we)
+ begin
+ rounds_reg <= write_data[ROUNDS_HIGH_BIT : ROUNDS_LOW_BIT];
+ end
+
+ if (key0_we)
+ begin
+ key0_reg <= write_data;
+ end
+
+ if (key1_we)
+ begin
+ key1_reg <= write_data;
+ end
+
+ if (key2_we)
+ begin
+ key2_reg <= write_data;
+ end
+
+ if (key3_we)
+ begin
+ key3_reg <= write_data;
+ end
+
+ if (key4_we)
+ begin
+ key4_reg <= write_data;
+ end
+
+ if (key5_we)
+ begin
+ key5_reg <= write_data;
+ end
+
+ if (key6_we)
+ begin
+ key6_reg <= write_data;
+ end
+
+ if (key7_we)
+ begin
+ key7_reg <= write_data;
+ end
+
+ if (iv0_we)
+ begin
+ iv0_reg <= write_data;
+ end
+
+ if (iv1_we)
+ begin
+ iv1_reg <= write_data;
+ end
+
+ if (data_in0_we)
+ begin
+ data_in0_reg <= write_data;
+ end
+
+ if (data_in1_we)
+ begin
+ data_in1_reg <= write_data;
+ end
+
+ if (data_in2_we)
+ begin
+ data_in2_reg <= write_data;
+ end
+
+ if (data_in3_we)
+ begin
+ data_in3_reg <= write_data;
+ end
+
+ if (data_in4_we)
+ begin
+ data_in4_reg <= write_data;
+ end
+
+ if (data_in5_we)
+ begin
+ data_in5_reg <= write_data;
+ end
+
+ if (data_in6_we)
+ begin
+ data_in6_reg <= write_data;
+ end
+
+ if (data_in7_we)
+ begin
+ data_in7_reg <= write_data;
+ end
+
+ if (data_in8_we)
+ begin
+ data_in8_reg <= write_data;
+ end
+
+ if (data_in9_we)
+ begin
+ data_in9_reg <= write_data;
+ end
+
+ if (data_in10_we)
+ begin
+ data_in10_reg <= write_data;
+ end
+
+ if (data_in11_we)
+ begin
+ data_in11_reg <= write_data;
+ end
+
+ if (data_in12_we)
+ begin
+ data_in12_reg <= write_data;
+ end
+
+ if (data_in13_we)
+ begin
+ data_in13_reg <= write_data;
+ end
+
+ if (data_in14_we)
+ begin
+ data_in14_reg <= write_data;
+ end
+
+ if (data_in15_we)
+ begin
+ data_in15_reg <= write_data;
+ end
+
+ if (core_data_out_valid)
+ begin
+ data_out0_reg <= core_data_out[511 : 480];
+ data_out1_reg <= core_data_out[479 : 448];
+ data_out2_reg <= core_data_out[447 : 416];
+ data_out3_reg <= core_data_out[415 : 384];
+ data_out4_reg <= core_data_out[383 : 352];
+ data_out5_reg <= core_data_out[351 : 320];
+ data_out6_reg <= core_data_out[319 : 288];
+ data_out7_reg <= core_data_out[287 : 256];
+ data_out8_reg <= core_data_out[255 : 224];
+ data_out9_reg <= core_data_out[223 : 192];
+ data_out10_reg <= core_data_out[191 : 160];
+ data_out11_reg <= core_data_out[159 : 128];
+ data_out12_reg <= core_data_out[127 : 96];
+ data_out13_reg <= core_data_out[95 : 64];
+ data_out14_reg <= core_data_out[63 : 32];
+ data_out15_reg <= core_data_out[31 : 0];
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // Address decoder logic.
+ //----------------------------------------------------------------
+ always @*
+ begin : addr_decoder
+ ctrl_we = 0;
+ keylen_we = 0;
+ rounds_we = 0;
+
+ key0_we = 0;
+ key1_we = 0;
+ key2_we = 0;
+ key3_we = 0;
+ key4_we = 0;
+ key5_we = 0;
+ key6_we = 0;
+ key7_we = 0;
+
+ iv0_we = 0;
+ iv1_we = 0;
+
+ data_in0_we = 0;
+ data_in1_we = 0;
+ data_in2_we = 0;
+ data_in3_we = 0;
+ data_in4_we = 0;
+ data_in5_we = 0;
+ data_in6_we = 0;
+ data_in7_we = 0;
+ data_in8_we = 0;
+ data_in9_we = 0;
+ data_in10_we = 0;
+ data_in11_we = 0;
+ data_in12_we = 0;
+ data_in13_we = 0;
+ data_in14_we = 0;
+ data_in15_we = 0;
+
+ tmp_read_data = 32'h00000000;
+ tmp_error = 0;
+
+ if (cs)
+ begin
+ if (we)
+ begin
+ case (address)
+ ADDR_CTRL:
+ begin
+ ctrl_we = 1;
+ end
+
+ ADDR_KEYLEN:
+ begin
+ keylen_we = 1;
+ end
+
+ ADDR_ROUNDS:
+ begin
+ rounds_we = 1;
+ end
+
+ ADDR_KEY0:
+ begin
+ key0_we = 1;
+ end
+
+ ADDR_KEY1:
+ begin
+ key1_we = 1;
+ end
+
+ ADDR_KEY2:
+ begin
+ key2_we = 1;
+ end
+
+ ADDR_KEY3:
+ begin
+ key3_we = 1;
+ end
+
+ ADDR_KEY4:
+ begin
+ key4_we = 1;
+ end
+
+ ADDR_KEY5:
+ begin
+ key5_we = 1;
+ end
+
+ ADDR_KEY6:
+ begin
+ key6_we = 1;
+ end
+
+ ADDR_KEY7:
+ begin
+ key7_we = 1;
+ end
+
+ ADDR_IV0:
+ begin
+ iv0_we = 1;
+ end
+
+ ADDR_IV1:
+ begin
+ iv1_we = 1;
+ end
+
+ ADDR_DATA_IN0:
+ begin
+ data_in0_we = 1;
+ end
+
+ ADDR_DATA_IN1:
+ begin
+ data_in1_we = 1;
+ end
+
+ ADDR_DATA_IN2:
+ begin
+ data_in2_we = 1;
+ end
+
+ ADDR_DATA_IN3:
+ begin
+ data_in3_we = 1;
+ end
+
+ ADDR_DATA_IN4:
+ begin
+ data_in4_we = 1;
+ end
+
+ ADDR_DATA_IN5:
+ begin
+ data_in5_we = 1;
+ end
+
+ ADDR_DATA_IN6:
+ begin
+ data_in6_we = 1;
+ end
+
+ ADDR_DATA_IN7:
+ begin
+ data_in7_we = 1;
+ end
+
+ ADDR_DATA_IN8:
+ begin
+ data_in8_we = 1;
+ end
+
+ ADDR_DATA_IN9:
+ begin
+ data_in9_we = 1;
+ end
+
+ ADDR_DATA_IN10:
+ begin
+ data_in10_we = 1;
+ end
+
+ ADDR_DATA_IN11:
+ begin
+ data_in11_we = 1;
+ end
+
+ ADDR_DATA_IN12:
+ begin
+ data_in12_we = 1;
+ end
+
+ ADDR_DATA_IN13:
+ begin
+ data_in13_we = 1;
+ end
+
+ ADDR_DATA_IN14:
+ begin
+ data_in14_we = 1;
+ end
+
+ ADDR_DATA_IN15:
+ begin
+ data_in15_we = 1;
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end // if (we)
+
+ else
+ begin
+ case (address)
+ ADDR_CTRL:
+ begin
+ tmp_read_data = {28'h0000000, 2'b00, next_reg, init_reg};
+ end
+
+ ADDR_STATUS:
+ begin
+ tmp_read_data = {28'h0000000, 2'b00,
+ {data_out_valid_reg, ready_reg}};
+ end
+
+ ADDR_KEYLEN:
+ begin
+ tmp_read_data = {28'h0000000, 3'b000, keylen_reg};
+ end
+
+ ADDR_ROUNDS:
+ begin
+ tmp_read_data = {24'h000000, 3'b000, rounds_reg};
+ end
+
+ ADDR_KEY0:
+ begin
+ tmp_read_data = key0_reg;
+ end
+
+ ADDR_KEY1:
+ begin
+ tmp_read_data = key1_reg;
+ end
+
+ ADDR_KEY2:
+ begin
+ tmp_read_data = key2_reg;
+ end
+
+ ADDR_KEY3:
+ begin
+ tmp_read_data = key3_reg;
+ end
+
+ ADDR_KEY4:
+ begin
+ tmp_read_data = key4_reg;
+ end
+
+ ADDR_KEY5:
+ begin
+ tmp_read_data = key5_reg;
+ end
+
+ ADDR_KEY6:
+ begin
+ tmp_read_data = key6_reg;
+ end
+
+ ADDR_KEY7:
+ begin
+ tmp_read_data = key7_reg;
+ end
+
+ ADDR_IV0:
+ begin
+ tmp_read_data = iv0_reg;
+ end
+
+ ADDR_IV1:
+ begin
+ tmp_read_data = iv1_reg;
+ end
+
+ ADDR_DATA_OUT0:
+ begin
+ tmp_read_data = data_out0_reg;
+ end
+
+ ADDR_DATA_OUT1:
+ begin
+ tmp_read_data = data_out1_reg;
+ end
+
+ ADDR_DATA_OUT2:
+ begin
+ tmp_read_data = data_out2_reg;
+ end
+
+ ADDR_DATA_OUT3:
+ begin
+ tmp_read_data = data_out3_reg;
+ end
+
+ ADDR_DATA_OUT4:
+ begin
+ tmp_read_data = data_out4_reg;
+ end
+
+ ADDR_DATA_OUT5:
+ begin
+ tmp_read_data = data_out5_reg;
+ end
+
+ ADDR_DATA_OUT6:
+ begin
+ tmp_read_data = data_out6_reg;
+ end
+
+ ADDR_DATA_OUT7:
+ begin
+ tmp_read_data = data_out7_reg;
+ end
+
+ ADDR_DATA_OUT8:
+ begin
+ tmp_read_data = data_out8_reg;
+ end
+
+ ADDR_DATA_OUT9:
+ begin
+ tmp_read_data = data_out9_reg;
+ end
+
+ ADDR_DATA_OUT10:
+ begin
+ tmp_read_data = data_out10_reg;
+ end
+
+ ADDR_DATA_OUT11:
+ begin
+ tmp_read_data = data_out11_reg;
+ end
+
+ ADDR_DATA_OUT12:
+ begin
+ tmp_read_data = data_out12_reg;
+ end
+
+ ADDR_DATA_OUT13:
+ begin
+ tmp_read_data = data_out13_reg;
+ end
+
+ ADDR_DATA_OUT14:
+ begin
+ tmp_read_data = data_out14_reg;
+ end
+
+ ADDR_DATA_OUT15:
+ begin
+ tmp_read_data = data_out15_reg;
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end
+ end
+ end // addr_decoder
+endmodule // chacha
+
+//======================================================================
+// EOF chacha.v
+//======================================================================
diff --git a/cipher/chacha/src/rtl/chacha_core.v b/cipher/chacha/src/rtl/chacha_core.v
new file mode 100644
index 0000000..0e1158b
--- /dev/null
+++ b/cipher/chacha/src/rtl/chacha_core.v
@@ -0,0 +1,1342 @@
+//======================================================================
+//
+// chacha_core.v
+// --------------
+// Verilog 2001 implementation of the stream cipher ChaCha.
+// This is the internal core with wide interfaces.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module chacha_core(
+ input wire clk,
+ input wire reset_n,
+
+ input wire init,
+ input wire next,
+
+ input wire [255 : 0] key,
+ input wire keylen,
+ input wire [63 : 0] iv,
+ input wire [63 : 0] ctr,
+ input wire [4 : 0] rounds,
+
+ input wire [511 : 0] data_in,
+
+ output wire ready,
+
+ output wire [511 : 0] data_out,
+ output wire data_out_valid
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ // Datapath quartterround states names.
+ parameter STATE_QR0 = 1'b0;
+ parameter STATE_QR1 = 1'b1;
+
+ parameter NUM_ROUNDS = 4'h8;
+
+ parameter TAU0 = 32'h61707865;
+ parameter TAU1 = 32'h3120646e;
+ parameter TAU2 = 32'h79622d36;
+ parameter TAU3 = 32'h6b206574;
+
+ parameter SIGMA0 = 32'h61707865;
+ parameter SIGMA1 = 32'h3320646e;
+ parameter SIGMA2 = 32'h79622d32;
+ parameter SIGMA3 = 32'h6b206574;
+
+ parameter CTRL_IDLE = 3'h0;
+ parameter CTRL_INIT = 3'h1;
+ parameter CTRL_ROUNDS = 3'h2;
+ parameter CTRL_FINALIZE = 3'h3;
+ parameter CTRL_DONE = 3'h4;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] key0_reg;
+ reg [31 : 0] key0_new;
+ reg [31 : 0] key1_reg;
+ reg [31 : 0] key1_new;
+ reg [31 : 0] key2_reg;
+ reg [31 : 0] key2_new;
+ reg [31 : 0] key3_reg;
+ reg [31 : 0] key3_new;
+ reg [31 : 0] key4_reg;
+ reg [31 : 0] key4_new;
+ reg [31 : 0] key5_reg;
+ reg [31 : 0] key5_new;
+ reg [31 : 0] key6_reg;
+ reg [31 : 0] key6_new;
+ reg [31 : 0] key7_reg;
+ reg [31 : 0] key7_new;
+
+ reg keylen_reg;
+ reg keylen_new;
+
+ reg [31 : 0] iv0_reg;
+ reg [31 : 0] iv0_new;
+ reg [31 : 0] iv1_reg;
+ reg [31 : 0] iv1_new;
+
+ reg [31 : 0] state0_reg;
+ reg [31 : 0] state0_new;
+ reg [31 : 0] state1_reg;
+ reg [31 : 0] state1_new;
+ reg [31 : 0] state2_reg;
+ reg [31 : 0] state2_new;
+ reg [31 : 0] state3_reg;
+ reg [31 : 0] state3_new;
+ reg [31 : 0] state4_reg;
+ reg [31 : 0] state4_new;
+ reg [31 : 0] state5_reg;
+ reg [31 : 0] state5_new;
+ reg [31 : 0] state6_reg;
+ reg [31 : 0] state6_new;
+ reg [31 : 0] state7_reg;
+ reg [31 : 0] state7_new;
+ reg [31 : 0] state8_reg;
+ reg [31 : 0] state8_new;
+ reg [31 : 0] state9_reg;
+ reg [31 : 0] state9_new;
+ reg [31 : 0] state10_reg;
+ reg [31 : 0] state10_new;
+ reg [31 : 0] state11_reg;
+ reg [31 : 0] state11_new;
+ reg [31 : 0] state12_reg;
+ reg [31 : 0] state12_new;
+ reg [31 : 0] state13_reg;
+ reg [31 : 0] state13_new;
+ reg [31 : 0] state14_reg;
+ reg [31 : 0] state14_new;
+ reg [31 : 0] state15_reg;
+ reg [31 : 0] state15_new;
+ reg state_we;
+
+ reg [31 : 0] x0_reg;
+ reg [31 : 0] x0_new;
+ reg x0_we;
+
+ reg [31 : 0] x1_reg;
+ reg [31 : 0] x1_new;
+ reg x1_we;
+
+ reg [31 : 0] x2_reg;
+ reg [31 : 0] x2_new;
+ reg x2_we;
+
+ reg [31 : 0] x3_reg;
+ reg [31 : 0] x3_new;
+ reg x3_we;
+
+ reg [31 : 0] x4_reg;
+ reg [31 : 0] x4_new;
+ reg x4_we;
+
+ reg [31 : 0] x5_reg;
+ reg [31 : 0] x5_new;
+ reg x5_we;
+
+ reg [31 : 0] x6_reg;
+ reg [31 : 0] x6_new;
+ reg x6_we;
+
+ reg [31 : 0] x7_reg;
+ reg [31 : 0] x7_new;
+ reg x7_we;
+
+ reg [31 : 0] x8_reg;
+ reg [31 : 0] x8_new;
+ reg x8_we;
+
+ reg [31 : 0] x9_reg;
+ reg [31 : 0] x9_new;
+ reg x9_we;
+
+ reg [31 : 0] x10_reg;
+ reg [31 : 0] x10_new;
+ reg x10_we;
+
+ reg [31 : 0] x11_reg;
+ reg [31 : 0] x11_new;
+ reg x11_we;
+
+ reg [31 : 0] x12_reg;
+ reg [31 : 0] x12_new;
+ reg x12_we;
+
+ reg [31 : 0] x13_reg;
+ reg [31 : 0] x13_new;
+ reg x13_we;
+
+ reg [31 : 0] x14_reg;
+ reg [31 : 0] x14_new;
+ reg x14_we;
+
+ reg [31 : 0] x15_reg;
+ reg [31 : 0] x15_new;
+ reg x15_we;
+
+ reg [3 : 0] rounds_reg;
+ reg [3 : 0] rounds_new;
+
+ reg [511 : 0] data_in_reg;
+ reg data_in_we;
+
+ reg [511 : 0] data_out_reg;
+ reg [511 : 0] data_out_new;
+ reg data_out_we;
+
+ reg data_out_valid_reg;
+ reg data_out_valid_new;
+ reg data_out_valid_we;
+
+ reg ready_reg;
+ reg ready_new;
+ reg ready_we;
+
+ reg qr_ctr_reg;
+ reg qr_ctr_new;
+ reg qr_ctr_we;
+ reg qr_ctr_inc;
+ reg qr_ctr_rst;
+
+ reg [3 : 0] dr_ctr_reg;
+ reg [3 : 0] dr_ctr_new;
+ reg dr_ctr_we;
+ reg dr_ctr_inc;
+ reg dr_ctr_rst;
+
+ reg [31 : 0] block0_ctr_reg;
+ reg [31 : 0] block0_ctr_new;
+ reg block0_ctr_we;
+ reg [31 : 0] block1_ctr_reg;
+ reg [31 : 0] block1_ctr_new;
+ reg block1_ctr_we;
+ reg block_ctr_inc;
+ reg block_ctr_rst;
+
+ reg [2 : 0] chacha_ctrl_reg;
+ reg [2 : 0] chacha_ctrl_new;
+ reg chacha_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg sample_params;
+ reg init_state;
+ reg update_state;
+ reg update_output;
+
+ reg [31 : 0] qr0_a;
+ reg [31 : 0] qr0_b;
+ reg [31 : 0] qr0_c;
+ reg [31 : 0] qr0_d;
+ wire [31 : 0] qr0_a_prim;
+ wire [31 : 0] qr0_b_prim;
+ wire [31 : 0] qr0_c_prim;
+ wire [31 : 0] qr0_d_prim;
+
+ reg [31 : 0] qr1_a;
+ reg [31 : 0] qr1_b;
+ reg [31 : 0] qr1_c;
+ reg [31 : 0] qr1_d;
+ wire [31 : 0] qr1_a_prim;
+ wire [31 : 0] qr1_b_prim;
+ wire [31 : 0] qr1_c_prim;
+ wire [31 : 0] qr1_d_prim;
+
+ reg [31 : 0] qr2_a;
+ reg [31 : 0] qr2_b;
+ reg [31 : 0] qr2_c;
+ reg [31 : 0] qr2_d;
+ wire [31 : 0] qr2_a_prim;
+ wire [31 : 0] qr2_b_prim;
+ wire [31 : 0] qr2_c_prim;
+ wire [31 : 0] qr2_d_prim;
+
+ reg [31 : 0] qr3_a;
+ reg [31 : 0] qr3_b;
+ reg [31 : 0] qr3_c;
+ reg [31 : 0] qr3_d;
+ wire [31 : 0] qr3_a_prim;
+ wire [31 : 0] qr3_b_prim;
+ wire [31 : 0] qr3_c_prim;
+ wire [31 : 0] qr3_d_prim;
+
+
+ //----------------------------------------------------------------
+ // Instantiation of the qr modules.
+ //----------------------------------------------------------------
+ chacha_qr qr0(
+ .a(qr0_a),
+ .b(qr0_b),
+ .c(qr0_c),
+ .d(qr0_d),
+
+ .a_prim(qr0_a_prim),
+ .b_prim(qr0_b_prim),
+ .c_prim(qr0_c_prim),
+ .d_prim(qr0_d_prim)
+ );
+
+ chacha_qr qr1(
+ .a(qr1_a),
+ .b(qr1_b),
+ .c(qr1_c),
+ .d(qr1_d),
+
+ .a_prim(qr1_a_prim),
+ .b_prim(qr1_b_prim),
+ .c_prim(qr1_c_prim),
+ .d_prim(qr1_d_prim)
+ );
+
+ chacha_qr qr2(
+ .a(qr2_a),
+ .b(qr2_b),
+ .c(qr2_c),
+ .d(qr2_d),
+
+ .a_prim(qr2_a_prim),
+ .b_prim(qr2_b_prim),
+ .c_prim(qr2_c_prim),
+ .d_prim(qr2_d_prim)
+ );
+
+ chacha_qr qr3(
+ .a(qr3_a),
+ .b(qr3_b),
+ .c(qr3_c),
+ .d(qr3_d),
+
+ .a_prim(qr3_a_prim),
+ .b_prim(qr3_b_prim),
+ .c_prim(qr3_c_prim),
+ .d_prim(qr3_d_prim)
+ );
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign data_out = data_out_reg;
+
+ assign data_out_valid = data_out_valid_reg;
+
+ assign ready = ready_reg;
+
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin : reg_update
+ if (!reset_n)
+ begin
+ key0_reg <= 32'h00000000;
+ key1_reg <= 32'h00000000;
+ key2_reg <= 32'h00000000;
+ key3_reg <= 32'h00000000;
+ key4_reg <= 32'h00000000;
+ key5_reg <= 32'h00000000;
+ key6_reg <= 32'h00000000;
+ key7_reg <= 32'h00000000;
+ iv0_reg <= 32'h00000000;
+ iv1_reg <= 32'h00000000;
+ state0_reg <= 32'h00000000;
+ state1_reg <= 32'h00000000;
+ state2_reg <= 32'h00000000;
+ state3_reg <= 32'h00000000;
+ state4_reg <= 32'h00000000;
+ state5_reg <= 32'h00000000;
+ state6_reg <= 32'h00000000;
+ state7_reg <= 32'h00000000;
+ state8_reg <= 32'h00000000;
+ state9_reg <= 32'h00000000;
+ state10_reg <= 32'h00000000;
+ state11_reg <= 32'h00000000;
+ state12_reg <= 32'h00000000;
+ state13_reg <= 32'h00000000;
+ state14_reg <= 32'h00000000;
+ state15_reg <= 32'h00000000;
+ x0_reg <= 32'h00000000;
+ x1_reg <= 32'h00000000;
+ x2_reg <= 32'h00000000;
+ x3_reg <= 32'h00000000;
+ x4_reg <= 32'h00000000;
+ x5_reg <= 32'h00000000;
+ x6_reg <= 32'h00000000;
+ x7_reg <= 32'h00000000;
+ x8_reg <= 32'h00000000;
+ x9_reg <= 32'h00000000;
+ x10_reg <= 32'h00000000;
+ x11_reg <= 32'h00000000;
+ x12_reg <= 32'h00000000;
+ x13_reg <= 32'h00000000;
+ x14_reg <= 32'h00000000;
+ x15_reg <= 32'h00000000;
+ data_in_reg <= 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ data_out_reg <= 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ rounds_reg <= 4'h0;
+ ready_reg <= 1;
+ data_out_valid_reg <= 0;
+ qr_ctr_reg <= STATE_QR0;
+ dr_ctr_reg <= 0;
+ block0_ctr_reg <= 32'h00000000;
+ block1_ctr_reg <= 32'h00000000;
+ chacha_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ if (sample_params)
+ begin
+ key0_reg <= key0_new;
+ key1_reg <= key1_new;
+ key2_reg <= key2_new;
+ key3_reg <= key3_new;
+ key4_reg <= key4_new;
+ key5_reg <= key5_new;
+ key6_reg <= key6_new;
+ key7_reg <= key7_new;
+ iv0_reg <= iv0_new;
+ iv1_reg <= iv1_new;
+ rounds_reg <= rounds_new;
+ keylen_reg <= keylen_new;
+ end
+
+ if (data_in_we)
+ begin
+ data_in_reg <= data_in;
+ end
+
+ if (state_we)
+ begin
+ state0_reg <= state0_new;
+ state1_reg <= state1_new;
+ state2_reg <= state2_new;
+ state3_reg <= state3_new;
+ state4_reg <= state4_new;
+ state5_reg <= state5_new;
+ state6_reg <= state6_new;
+ state7_reg <= state7_new;
+ state8_reg <= state8_new;
+ state9_reg <= state9_new;
+ state10_reg <= state10_new;
+ state11_reg <= state11_new;
+ state12_reg <= state12_new;
+ state13_reg <= state13_new;
+ state14_reg <= state14_new;
+ state15_reg <= state15_new;
+ end
+
+ if (x0_we)
+ begin
+ x0_reg <= x0_new;
+ end
+
+ if (x1_we)
+ begin
+ x1_reg <= x1_new;
+ end
+
+ if (x2_we)
+ begin
+ x2_reg <= x2_new;
+ end
+
+ if (x3_we)
+ begin
+ x3_reg <= x3_new;
+ end
+
+ if (x4_we)
+ begin
+ x4_reg <= x4_new;
+ end
+
+ if (x5_we)
+ begin
+ x5_reg <= x5_new;
+ end
+
+ if (x6_we)
+ begin
+ x6_reg <= x6_new;
+ end
+
+ if (x7_we)
+ begin
+ x7_reg <= x7_new;
+ end
+
+ if (x8_we)
+ begin
+ x8_reg <= x8_new;
+ end
+
+ if (x9_we)
+ begin
+ x9_reg <= x9_new;
+ end
+
+ if (x10_we)
+ begin
+ x10_reg <= x10_new;
+ end
+
+ if (x11_we)
+ begin
+ x11_reg <= x11_new;
+ end
+
+ if (x12_we)
+ begin
+ x12_reg <= x12_new;
+ end
+
+ if (x13_we)
+ begin
+ x13_reg <= x13_new;
+ end
+
+ if (x14_we)
+ begin
+ x14_reg <= x14_new;
+ end
+
+ if (x15_we)
+ begin
+ x15_reg <= x15_new;
+ end
+
+ if (data_out_we)
+ begin
+ data_out_reg <= data_out_new;
+ end
+
+ if (ready_we)
+ begin
+ ready_reg <= ready_new;
+ end
+
+ if (data_out_valid_we)
+ begin
+ data_out_valid_reg <= data_out_valid_new;
+ end
+
+ if (qr_ctr_we)
+ begin
+ qr_ctr_reg <= qr_ctr_new;
+ end
+
+ if (dr_ctr_we)
+ begin
+ dr_ctr_reg <= dr_ctr_new;
+ end
+
+ if (block0_ctr_we)
+ begin
+ block0_ctr_reg <= block0_ctr_new;
+ end
+
+ if (block1_ctr_we)
+ begin
+ block1_ctr_reg <= block1_ctr_new;
+ end
+
+ if (chacha_ctrl_we)
+ begin
+ chacha_ctrl_reg <= chacha_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // data_out_logic
+ // Final output logic that combines the result from procceing
+ // with the input word. This adds a final layer of XOR gates.
+ //
+ // Note that we also remap all the words into LSB format.
+ //----------------------------------------------------------------
+ always @*
+ begin : data_out_logic
+ reg [31 : 0] msb_block_state0;
+ reg [31 : 0] msb_block_state1;
+ reg [31 : 0] msb_block_state2;
+ reg [31 : 0] msb_block_state3;
+ reg [31 : 0] msb_block_state4;
+ reg [31 : 0] msb_block_state5;
+ reg [31 : 0] msb_block_state6;
+ reg [31 : 0] msb_block_state7;
+ reg [31 : 0] msb_block_state8;
+ reg [31 : 0] msb_block_state9;
+ reg [31 : 0] msb_block_state10;
+ reg [31 : 0] msb_block_state11;
+ reg [31 : 0] msb_block_state12;
+ reg [31 : 0] msb_block_state13;
+ reg [31 : 0] msb_block_state14;
+ reg [31 : 0] msb_block_state15;
+
+ reg [31 : 0] lsb_block_state0;
+ reg [31 : 0] lsb_block_state1;
+ reg [31 : 0] lsb_block_state2;
+ reg [31 : 0] lsb_block_state3;
+ reg [31 : 0] lsb_block_state4;
+ reg [31 : 0] lsb_block_state5;
+ reg [31 : 0] lsb_block_state6;
+ reg [31 : 0] lsb_block_state7;
+ reg [31 : 0] lsb_block_state8;
+ reg [31 : 0] lsb_block_state9;
+ reg [31 : 0] lsb_block_state10;
+ reg [31 : 0] lsb_block_state11;
+ reg [31 : 0] lsb_block_state12;
+ reg [31 : 0] lsb_block_state13;
+ reg [31 : 0] lsb_block_state14;
+ reg [31 : 0] lsb_block_state15;
+
+ reg [511 : 0] lsb_block_state;
+
+ lsb_block_state = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+
+ data_out_new = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ data_out_we = 0;
+
+ if (update_output)
+ begin
+ msb_block_state0 = state0_reg + x0_reg;
+ msb_block_state1 = state1_reg + x1_reg;
+ msb_block_state2 = state2_reg + x2_reg;
+ msb_block_state3 = state3_reg + x3_reg;
+ msb_block_state4 = state4_reg + x4_reg;
+ msb_block_state5 = state5_reg + x5_reg;
+ msb_block_state6 = state6_reg + x6_reg;
+ msb_block_state7 = state7_reg + x7_reg;
+ msb_block_state8 = state8_reg + x8_reg;
+ msb_block_state9 = state9_reg + x9_reg;
+ msb_block_state10 = state10_reg + x10_reg;
+ msb_block_state11 = state11_reg + x11_reg;
+ msb_block_state12 = state12_reg + x12_reg;
+ msb_block_state13 = state13_reg + x13_reg;
+ msb_block_state14 = state14_reg + x14_reg;
+ msb_block_state15 = state15_reg + x15_reg;
+
+ lsb_block_state0 = {msb_block_state0[7 : 0],
+ msb_block_state0[15 : 8],
+ msb_block_state0[23 : 16],
+ msb_block_state0[31 : 24]};
+
+ lsb_block_state1 = {msb_block_state1[7 : 0],
+ msb_block_state1[15 : 8],
+ msb_block_state1[23 : 16],
+ msb_block_state1[31 : 24]};
+
+ lsb_block_state2 = {msb_block_state2[7 : 0],
+ msb_block_state2[15 : 8],
+ msb_block_state2[23 : 16],
+ msb_block_state2[31 : 24]};
+
+ lsb_block_state3 = {msb_block_state3[7 : 0],
+ msb_block_state3[15 : 8],
+ msb_block_state3[23 : 16],
+ msb_block_state3[31 : 24]};
+
+ lsb_block_state4 = {msb_block_state4[7 : 0],
+ msb_block_state4[15 : 8],
+ msb_block_state4[23 : 16],
+ msb_block_state4[31 : 24]};
+
+ lsb_block_state5 = {msb_block_state5[7 : 0],
+ msb_block_state5[15 : 8],
+ msb_block_state5[23 : 16],
+ msb_block_state5[31 : 24]};
+
+ lsb_block_state6 = {msb_block_state6[7 : 0],
+ msb_block_state6[15 : 8],
+ msb_block_state6[23 : 16],
+ msb_block_state6[31 : 24]};
+
+ lsb_block_state7 = {msb_block_state7[7 : 0],
+ msb_block_state7[15 : 8],
+ msb_block_state7[23 : 16],
+ msb_block_state7[31 : 24]};
+
+ lsb_block_state8 = {msb_block_state8[7 : 0],
+ msb_block_state8[15 : 8],
+ msb_block_state8[23 : 16],
+ msb_block_state8[31 : 24]};
+
+ lsb_block_state9 = {msb_block_state9[7 : 0],
+ msb_block_state9[15 : 8],
+ msb_block_state9[23 : 16],
+ msb_block_state9[31 : 24]};
+
+ lsb_block_state10 = {msb_block_state10[7 : 0],
+ msb_block_state10[15 : 8],
+ msb_block_state10[23 : 16],
+ msb_block_state10[31 : 24]};
+
+ lsb_block_state11 = {msb_block_state11[7 : 0],
+ msb_block_state11[15 : 8],
+ msb_block_state11[23 : 16],
+ msb_block_state11[31 : 24]};
+
+ lsb_block_state12 = {msb_block_state12[7 : 0],
+ msb_block_state12[15 : 8],
+ msb_block_state12[23 : 16],
+ msb_block_state12[31 : 24]};
+
+ lsb_block_state13 = {msb_block_state13[7 : 0],
+ msb_block_state13[15 : 8],
+ msb_block_state13[23 : 16],
+ msb_block_state13[31 : 24]};
+
+ lsb_block_state14 = {msb_block_state14[7 : 0],
+ msb_block_state14[15 : 8],
+ msb_block_state14[23 : 16],
+ msb_block_state14[31 : 24]};
+
+ lsb_block_state15 = {msb_block_state15[7 : 0],
+ msb_block_state15[15 : 8],
+ msb_block_state15[23 : 16],
+ msb_block_state15[31 : 24]};
+
+ lsb_block_state = {lsb_block_state0, lsb_block_state1,
+ lsb_block_state2, lsb_block_state3,
+ lsb_block_state4, lsb_block_state5,
+ lsb_block_state6, lsb_block_state7,
+ lsb_block_state8, lsb_block_state9,
+ lsb_block_state10, lsb_block_state11,
+ lsb_block_state12, lsb_block_state13,
+ lsb_block_state14, lsb_block_state15};
+
+ data_out_new = data_in_reg ^ lsb_block_state;
+ data_out_we = 1;
+ end // if (update_output)
+ end // data_out_logic
+
+
+ //----------------------------------------------------------------
+ // sample_parameters
+ // Logic (wires) that convert parameter input to appropriate
+ // format for processing.
+ //----------------------------------------------------------------
+ always @*
+ begin : sample_parameters
+ key0_new = 32'h00000000;
+ key1_new = 32'h00000000;
+ key2_new = 32'h00000000;
+ key3_new = 32'h00000000;
+ key4_new = 32'h00000000;
+ key5_new = 32'h00000000;
+ key6_new = 32'h00000000;
+ key7_new = 32'h00000000;
+ iv0_new = 32'h00000000;
+ iv1_new = 32'h00000000;
+ rounds_new = 4'h0;
+ keylen_new = 1'b0;
+
+ if (sample_params)
+ begin
+ key0_new = {key[231 : 224], key[239 : 232],
+ key[247 : 240], key[255 : 248]};
+ key1_new = {key[199 : 192], key[207 : 200],
+ key[215 : 208], key[223 : 216]};
+ key2_new = {key[167 : 160], key[175 : 168],
+ key[183 : 176], key[191 : 184]};
+ key3_new = {key[135 : 128], key[143 : 136],
+ key[151 : 144], key[159 : 152]};
+ key4_new = {key[103 : 96], key[111 : 104],
+ key[119 : 112], key[127 : 120]};
+ key5_new = {key[71 : 64], key[79 : 72],
+ key[87 : 80], key[95 : 88]};
+ key6_new = {key[39 : 32], key[47 : 40],
+ key[55 : 48], key[63 : 56]};
+ key7_new = {key[7 : 0], key[15 : 8],
+ key[23 : 16], key[31 : 24]};
+
+ iv0_new = {iv[39 : 32], iv[47 : 40],
+ iv[55 : 48], iv[63 : 56]};
+ iv1_new = {iv[7 : 0], iv[15 : 8],
+ iv[23 : 16], iv[31 : 24]};
+
+ // Div by two since we count double rounds.
+ rounds_new = rounds[4 : 1];
+
+ keylen_new = keylen;
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // state_logic
+ // Logic to init and update the internal state.
+ //----------------------------------------------------------------
+ always @*
+ begin : state_logic
+ reg [31 : 0] new_state_word0;
+ reg [31 : 0] new_state_word1;
+ reg [31 : 0] new_state_word2;
+ reg [31 : 0] new_state_word3;
+ reg [31 : 0] new_state_word4;
+ reg [31 : 0] new_state_word5;
+ reg [31 : 0] new_state_word6;
+ reg [31 : 0] new_state_word7;
+ reg [31 : 0] new_state_word8;
+ reg [31 : 0] new_state_word9;
+ reg [31 : 0] new_state_word10;
+ reg [31 : 0] new_state_word11;
+ reg [31 : 0] new_state_word12;
+ reg [31 : 0] new_state_word13;
+ reg [31 : 0] new_state_word14;
+ reg [31 : 0] new_state_word15;
+
+ new_state_word0 = 32'h00000000;
+ new_state_word1 = 32'h00000000;
+ new_state_word2 = 32'h00000000;
+ new_state_word3 = 32'h00000000;
+ new_state_word4 = 32'h00000000;
+ new_state_word5 = 32'h00000000;
+ new_state_word6 = 32'h00000000;
+ new_state_word7 = 32'h00000000;
+ new_state_word8 = 32'h00000000;
+ new_state_word9 = 32'h00000000;
+ new_state_word10 = 32'h00000000;
+ new_state_word11 = 32'h00000000;
+ new_state_word12 = 32'h00000000;
+ new_state_word13 = 32'h00000000;
+ new_state_word14 = 32'h00000000;
+ new_state_word15 = 32'h00000000;
+
+ x0_new = 32'h00000000;
+ x1_new = 32'h00000000;
+ x2_new = 32'h00000000;
+ x3_new = 32'h00000000;
+ x4_new = 32'h00000000;
+ x5_new = 32'h00000000;
+ x6_new = 32'h00000000;
+ x7_new = 32'h00000000;
+ x8_new = 32'h00000000;
+ x9_new = 32'h00000000;
+ x10_new = 32'h00000000;
+ x11_new = 32'h00000000;
+ x12_new = 32'h00000000;
+ x13_new = 32'h00000000;
+ x14_new = 32'h00000000;
+ x15_new = 32'h00000000;
+ x0_we = 0;
+ x1_we = 0;
+ x2_we = 0;
+ x3_we = 0;
+ x4_we = 0;
+ x5_we = 0;
+ x6_we = 0;
+ x7_we = 0;
+ x8_we = 0;
+ x9_we = 0;
+ x10_we = 0;
+ x11_we = 0;
+ x12_we = 0;
+ x13_we = 0;
+ x14_we = 0;
+ x15_we = 0;
+
+ state0_new = 32'h00000000;
+ state1_new = 32'h00000000;
+ state2_new = 32'h00000000;
+ state3_new = 32'h00000000;
+ state4_new = 32'h00000000;
+ state5_new = 32'h00000000;
+ state6_new = 32'h00000000;
+ state7_new = 32'h00000000;
+ state8_new = 32'h00000000;
+ state9_new = 32'h00000000;
+ state10_new = 32'h00000000;
+ state11_new = 32'h00000000;
+ state12_new = 32'h00000000;
+ state13_new = 32'h00000000;
+ state14_new = 32'h00000000;
+ state15_new = 32'h00000000;
+ state_we = 0;
+
+ if (init_state)
+ begin
+ new_state_word4 = key0_reg;
+ new_state_word5 = key1_reg;
+ new_state_word6 = key2_reg;
+ new_state_word7 = key3_reg;
+
+ new_state_word12 = block0_ctr_reg;
+ new_state_word13 = block1_ctr_reg;
+
+ new_state_word14 = iv0_reg;
+ new_state_word15 = iv1_reg;
+
+ if (keylen_reg)
+ begin
+ // 256 bit key.
+ new_state_word0 = SIGMA0;
+ new_state_word1 = SIGMA1;
+ new_state_word2 = SIGMA2;
+ new_state_word3 = SIGMA3;
+ new_state_word8 = key4_reg;
+ new_state_word9 = key5_reg;
+ new_state_word10 = key6_reg;
+ new_state_word11 = key7_reg;
+ end
+ else
+ begin
+ // 128 bit key.
+ new_state_word0 = TAU0;
+ new_state_word1 = TAU1;
+ new_state_word2 = TAU2;
+ new_state_word3 = TAU3;
+ new_state_word8 = key0_reg;
+ new_state_word9 = key1_reg;
+ new_state_word10 = key2_reg;
+ new_state_word11 = key3_reg;
+ end
+
+ x0_new = new_state_word0;
+ x1_new = new_state_word1;
+ x2_new = new_state_word2;
+ x3_new = new_state_word3;
+ x4_new = new_state_word4;
+ x5_new = new_state_word5;
+ x6_new = new_state_word6;
+ x7_new = new_state_word7;
+ x8_new = new_state_word8;
+ x9_new = new_state_word9;
+ x10_new = new_state_word10;
+ x11_new = new_state_word11;
+ x12_new = new_state_word12;
+ x13_new = new_state_word13;
+ x14_new = new_state_word14;
+ x15_new = new_state_word15;
+ x0_we = 1;
+ x1_we = 1;
+ x2_we = 1;
+ x3_we = 1;
+ x4_we = 1;
+ x5_we = 1;
+ x6_we = 1;
+ x7_we = 1;
+ x8_we = 1;
+ x9_we = 1;
+ x10_we = 1;
+ x11_we = 1;
+ x12_we = 1;
+ x13_we = 1;
+ x14_we = 1;
+ x15_we = 1;
+
+ state0_new = new_state_word0;
+ state1_new = new_state_word1;
+ state2_new = new_state_word2;
+ state3_new = new_state_word3;
+ state4_new = new_state_word4;
+ state5_new = new_state_word5;
+ state6_new = new_state_word6;
+ state7_new = new_state_word7;
+ state8_new = new_state_word8;
+ state9_new = new_state_word9;
+ state10_new = new_state_word10;
+ state11_new = new_state_word11;
+ state12_new = new_state_word12;
+ state13_new = new_state_word13;
+ state14_new = new_state_word14;
+ state15_new = new_state_word15;
+ state_we = 1;
+ end // if (init_state)
+
+ else if (update_state)
+ begin
+ case (qr_ctr_reg)
+ STATE_QR0:
+ begin
+ x0_new = qr0_a_prim;
+ x4_new = qr0_b_prim;
+ x8_new = qr0_c_prim;
+ x12_new = qr0_d_prim;
+ x0_we = 1;
+ x4_we = 1;
+ x8_we = 1;
+ x12_we = 1;
+
+ x1_new = qr1_a_prim;
+ x5_new = qr1_b_prim;
+ x9_new = qr1_c_prim;
+ x13_new = qr1_d_prim;
+ x1_we = 1;
+ x5_we = 1;
+ x9_we = 1;
+ x13_we = 1;
+
+ x2_new = qr2_a_prim;
+ x6_new = qr2_b_prim;
+ x10_new = qr2_c_prim;
+ x14_new = qr2_d_prim;
+ x2_we = 1;
+ x6_we = 1;
+ x10_we = 1;
+ x14_we = 1;
+
+ x3_new = qr3_a_prim;
+ x7_new = qr3_b_prim;
+ x11_new = qr3_c_prim;
+ x15_new = qr3_d_prim;
+ x3_we = 1;
+ x7_we = 1;
+ x11_we = 1;
+ x15_we = 1;
+ end
+
+ STATE_QR1:
+ begin
+ x0_new = qr0_a_prim;
+ x5_new = qr0_b_prim;
+ x10_new = qr0_c_prim;
+ x15_new = qr0_d_prim;
+ x0_we = 1;
+ x5_we = 1;
+ x10_we = 1;
+ x15_we = 1;
+
+ x1_new = qr1_a_prim;
+ x6_new = qr1_b_prim;
+ x11_new = qr1_c_prim;
+ x12_new = qr1_d_prim;
+ x1_we = 1;
+ x6_we = 1;
+ x11_we = 1;
+ x12_we = 1;
+
+ x2_new = qr2_a_prim;
+ x7_new = qr2_b_prim;
+ x8_new = qr2_c_prim;
+ x13_new = qr2_d_prim;
+ x2_we = 1;
+ x7_we = 1;
+ x8_we = 1;
+ x13_we = 1;
+
+ x3_new = qr3_a_prim;
+ x4_new = qr3_b_prim;
+ x9_new = qr3_c_prim;
+ x14_new = qr3_d_prim;
+ x3_we = 1;
+ x4_we = 1;
+ x9_we = 1;
+ x14_we = 1;
+ end
+ endcase // case (quarterround_select)
+ end // if (update_state)
+ end // state_logic
+
+
+ //----------------------------------------------------------------
+ // quarterround_mux
+ // Quarterround muxes that selects operands for quarterrounds.
+ //----------------------------------------------------------------
+ always @*
+ begin : quarterround_mux
+ case (qr_ctr_reg)
+ STATE_QR0:
+ begin
+ qr0_a = x0_reg;
+ qr0_b = x4_reg;
+ qr0_c = x8_reg;
+ qr0_d = x12_reg;
+
+ qr1_a = x1_reg;
+ qr1_b = x5_reg;
+ qr1_c = x9_reg;
+ qr1_d = x13_reg;
+
+ qr2_a = x2_reg;
+ qr2_b = x6_reg;
+ qr2_c = x10_reg;
+ qr2_d = x14_reg;
+
+ qr3_a = x3_reg;
+ qr3_b = x7_reg;
+ qr3_c = x11_reg;
+ qr3_d = x15_reg;
+ end
+
+ STATE_QR1:
+ begin
+ qr0_a = x0_reg;
+ qr0_b = x5_reg;
+ qr0_c = x10_reg;
+ qr0_d = x15_reg;
+
+ qr1_a = x1_reg;
+ qr1_b = x6_reg;
+ qr1_c = x11_reg;
+ qr1_d = x12_reg;
+
+ qr2_a = x2_reg;
+ qr2_b = x7_reg;
+ qr2_c = x8_reg;
+ qr2_d = x13_reg;
+
+ qr3_a = x3_reg;
+ qr3_b = x4_reg;
+ qr3_c = x9_reg;
+ qr3_d = x14_reg;
+ end
+ endcase // case (quarterround_select)
+ end // quarterround_mux
+
+
+ //----------------------------------------------------------------
+ // qr_ctr
+ // Update logic for the quarterround counter, a monotonically
+ // increasing counter with reset.
+ //----------------------------------------------------------------
+ always @*
+ begin : qr_ctr
+ qr_ctr_new = 0;
+ qr_ctr_we = 0;
+
+ if (qr_ctr_rst)
+ begin
+ qr_ctr_new = 0;
+ qr_ctr_we = 1;
+ end
+
+ if (qr_ctr_inc)
+ begin
+ qr_ctr_new = qr_ctr_reg + 1'b1;
+ qr_ctr_we = 1;
+ end
+ end // qr_ctr
+
+
+ //----------------------------------------------------------------
+ // dr_ctr
+ // Update logic for the round counter, a monotonically
+ // increasing counter with reset.
+ //----------------------------------------------------------------
+ always @*
+ begin : dr_ctr
+ dr_ctr_new = 0;
+ dr_ctr_we = 0;
+
+ if (dr_ctr_rst)
+ begin
+ dr_ctr_new = 0;
+ dr_ctr_we = 1;
+ end
+
+ if (dr_ctr_inc)
+ begin
+ dr_ctr_new = dr_ctr_reg + 1'b1;
+ dr_ctr_we = 1;
+ end
+ end // dr_ctr
+
+
+ //----------------------------------------------------------------
+ // block_ctr
+ // Update logic for the 64-bit block counter, a monotonically
+ // increasing counter with reset.
+ //----------------------------------------------------------------
+ always @*
+ begin : block_ctr
+ // Defult assignments
+ block0_ctr_new = 32'h00000000;
+ block1_ctr_new = 32'h00000000;
+ block0_ctr_we = 0;
+ block1_ctr_we = 0;
+
+ if (block_ctr_rst)
+ begin
+ block0_ctr_new = ctr[31 : 00];
+ block1_ctr_new = ctr[63 : 32];
+ block0_ctr_we = 1;
+ block1_ctr_we = 1;
+ end
+
+ if (block_ctr_inc)
+ begin
+ block0_ctr_new = block0_ctr_reg + 1;
+ block0_ctr_we = 1;
+
+ // Avoid chaining the 32-bit adders.
+ if (block0_ctr_reg == 32'hffffffff)
+ begin
+ block1_ctr_new = block1_ctr_reg + 1;
+ block1_ctr_we = 1;
+ end
+ end
+ end // block_ctr
+
+
+ //----------------------------------------------------------------
+ // chacha_ctrl_fsm
+ // Logic for the state machine controlling the core behaviour.
+ //----------------------------------------------------------------
+ always @*
+ begin : chacha_ctrl_fsm
+ init_state = 0;
+ update_state = 0;
+ sample_params = 0;
+ update_output = 0;
+
+ qr_ctr_inc = 0;
+ qr_ctr_rst = 0;
+
+ dr_ctr_inc = 0;
+ dr_ctr_rst = 0;
+
+ block_ctr_inc = 0;
+ block_ctr_rst = 0;
+
+ data_in_we = 0;
+
+ ready_new = 0;
+ ready_we = 0;
+
+ data_out_valid_new = 0;
+ data_out_valid_we = 0;
+
+ chacha_ctrl_new = CTRL_IDLE;
+ chacha_ctrl_we = 0;
+
+
+ case (chacha_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (init)
+ begin
+ ready_new = 0;
+ ready_we = 1;
+ data_in_we = 1;
+ sample_params = 1;
+ block_ctr_rst = 1;
+ chacha_ctrl_new = CTRL_INIT;
+ chacha_ctrl_we = 1;
+ end
+ end
+
+
+ CTRL_INIT:
+ begin
+ init_state = 1;
+ qr_ctr_rst = 1;
+ dr_ctr_rst = 1;
+ chacha_ctrl_new = CTRL_ROUNDS;
+ chacha_ctrl_we = 1;
+ end
+
+
+ CTRL_ROUNDS:
+ begin
+ update_state = 1;
+ qr_ctr_inc = 1;
+ if (qr_ctr_reg == STATE_QR1)
+ begin
+ dr_ctr_inc = 1;
+ if (dr_ctr_reg == (rounds_reg - 1))
+ begin
+ chacha_ctrl_new = CTRL_FINALIZE;
+ chacha_ctrl_we = 1;
+ end
+ end
+ end
+
+
+ CTRL_FINALIZE:
+ begin
+ ready_new = 1;
+ ready_we = 1;
+ update_output = 1;
+ data_out_valid_new = 1;
+ data_out_valid_we = 1;
+ chacha_ctrl_new = CTRL_DONE;
+ chacha_ctrl_we = 1;
+ end
+
+
+ CTRL_DONE:
+ begin
+ if (init)
+ begin
+ ready_new = 0;
+ ready_we = 1;
+ data_out_valid_new = 0;
+ data_out_valid_we = 1;
+ data_in_we = 1;
+ sample_params = 1;
+ block_ctr_rst = 1;
+ chacha_ctrl_new = CTRL_INIT;
+ chacha_ctrl_we = 1;
+ end
+ else if (next)
+ begin
+ ready_new = 0;
+ ready_we = 1;
+ data_out_valid_new = 0;
+ data_out_valid_we = 1;
+ data_in_we = 1;
+ block_ctr_inc = 1;
+ chacha_ctrl_new = CTRL_INIT;
+ chacha_ctrl_we = 1;
+ end
+ end
+
+
+ default:
+ begin
+
+ end
+ endcase // case (chacha_ctrl_reg)
+ end // chacha_ctrl_fsm
+endmodule // chacha_core
+
+//======================================================================
+// EOF chacha_core.v
+//======================================================================
diff --git a/cipher/chacha/src/rtl/chacha_qr.v b/cipher/chacha/src/rtl/chacha_qr.v
new file mode 100644
index 0000000..42e644c
--- /dev/null
+++ b/cipher/chacha/src/rtl/chacha_qr.v
@@ -0,0 +1,117 @@
+//======================================================================
+//
+// chacha_qr.v
+// -----------
+// Verilog 2001 implementation of the stream cipher ChaCha.
+// This is the combinational QR logic as a separade module to allow
+// us to build versions of the cipher with 1, 2, 4 and even 8
+// parallel qr functions.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2011, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module chacha_qr(
+ input wire [31 : 0] a,
+ input wire [31 : 0] b,
+ input wire [31 : 0] c,
+ input wire [31 : 0] d,
+
+ output wire [31 : 0] a_prim,
+ output wire [31 : 0] b_prim,
+ output wire [31 : 0] c_prim,
+ output wire [31 : 0] d_prim
+ );
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] internal_a_prim;
+ reg [31 : 0] internal_b_prim;
+ reg [31 : 0] internal_c_prim;
+ reg [31 : 0] internal_d_prim;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports.
+ //----------------------------------------------------------------
+ assign a_prim = internal_a_prim;
+ assign b_prim = internal_b_prim;
+ assign c_prim = internal_c_prim;
+ assign d_prim = internal_d_prim;
+
+
+ //----------------------------------------------------------------
+ // qr
+ //
+ // The actual quarterround function.
+ //----------------------------------------------------------------
+ always @*
+ begin : qr
+ reg [31 : 0] a0;
+ reg [31 : 0] a1;
+
+ reg [31 : 0] b0;
+ reg [31 : 0] b1;
+ reg [31 : 0] b2;
+ reg [31 : 0] b3;
+
+ reg [31 : 0] c0;
+ reg [31 : 0] c1;
+
+ reg [31 : 0] d0;
+ reg [31 : 0] d1;
+ reg [31 : 0] d2;
+ reg [31 : 0] d3;
+
+ a0 = a + b;
+ d0 = d ^ a0;
+ d1 = {d0[15 : 0], d0[31 : 16]};
+ c0 = c + d1;
+ b0 = b ^ c0;
+ b1 = {b0[19 : 0], b0[31 : 20]};
+ a1 = a0 + b1;
+ d2 = d1 ^ a1;
+ d3 = {d2[23 : 0], d2[31 : 24]};
+ c1 = c0 + d3;
+ b2 = b1 ^ c1;
+ b3 = {b2[24 : 0], b2[31 : 25]};
+
+ internal_a_prim = a1;
+ internal_b_prim = b3;
+ internal_c_prim = c1;
+ internal_d_prim = d3;
+ end // qr
+endmodule // chacha_qr
+
+//======================================================================
+// EOF chacha_qr.v
+//======================================================================
diff --git a/cipher/chacha/src/tb/tb_chacha.v b/cipher/chacha/src/tb/tb_chacha.v
new file mode 100644
index 0000000..4322334
--- /dev/null
+++ b/cipher/chacha/src/tb/tb_chacha.v
@@ -0,0 +1,761 @@
+//======================================================================
+//
+// tb_chacha.v
+// -----------
+// Testbench for the Chacha top level wrapper.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2011, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+module tb_chacha();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_HALF_PERIOD = 2;
+
+ parameter TC1 = 1;
+ parameter TC2 = 2;
+ parameter TC3 = 3;
+ parameter TC4 = 4;
+ parameter TC5 = 5;
+ parameter TC6 = 6;
+ parameter TC7 = 7;
+ parameter TC8 = 8;
+ parameter TC9 = 9;
+ parameter TC10 = 10;
+
+ parameter ONE = 1;
+ parameter TWO = 2;
+ parameter THREE = 3;
+ parameter FOUR = 4;
+ parameter FIVE = 5;
+ parameter SIX = 6;
+ parameter SEVEN = 7;
+ parameter EIGHT = 8;
+
+ parameter KEY_128_BITS = 0;
+ parameter KEY_256_BITS = 1;
+
+ parameter EIGHT_ROUNDS = 8;
+ parameter TWELWE_ROUNDS = 12;
+ parameter TWENTY_ROUNDS = 20;
+
+ parameter DISABLE = 0;
+ parameter ENABLE = 1;
+
+ // API for the dut.
+ parameter ADDR_CTRL = 8'h00;
+ parameter CTRL_INIT_BIT = 0;
+ parameter CTRL_NEXT_BIT = 1;
+
+ parameter ADDR_STATUS = 8'h01;
+ parameter STATUS_READY_BIT = 0;
+
+ parameter ADDR_KEYLEN = 8'h08;
+ parameter KEYLEN_BIT = 0;
+ parameter ADDR_ROUNDS = 8'h09;
+ parameter ROUNDS_HIGH_BIT = 4;
+ parameter ROUNDS_LOW_BIT = 0;
+
+ parameter ADDR_KEY0 = 8'h10;
+ parameter ADDR_KEY1 = 8'h11;
+ parameter ADDR_KEY2 = 8'h12;
+ parameter ADDR_KEY3 = 8'h13;
+ parameter ADDR_KEY4 = 8'h14;
+ parameter ADDR_KEY5 = 8'h15;
+ parameter ADDR_KEY6 = 8'h16;
+ parameter ADDR_KEY7 = 8'h17;
+
+ parameter ADDR_IV0 = 8'h20;
+ parameter ADDR_IV1 = 8'h21;
+
+ parameter ADDR_DATA_IN0 = 8'h40;
+ parameter ADDR_DATA_IN1 = 8'h41;
+ parameter ADDR_DATA_IN2 = 8'h42;
+ parameter ADDR_DATA_IN3 = 8'h43;
+ parameter ADDR_DATA_IN4 = 8'h44;
+ parameter ADDR_DATA_IN5 = 8'h45;
+ parameter ADDR_DATA_IN6 = 8'h46;
+ parameter ADDR_DATA_IN7 = 8'h47;
+ parameter ADDR_DATA_IN8 = 8'h48;
+ parameter ADDR_DATA_IN9 = 8'h49;
+ parameter ADDR_DATA_IN10 = 8'h4a;
+ parameter ADDR_DATA_IN11 = 8'h4b;
+ parameter ADDR_DATA_IN12 = 8'h4c;
+ parameter ADDR_DATA_IN13 = 8'h4d;
+ parameter ADDR_DATA_IN14 = 8'h4e;
+ parameter ADDR_DATA_IN15 = 8'h4f;
+
+ parameter ADDR_DATA_OUT0 = 8'h80;
+ parameter ADDR_DATA_OUT1 = 8'h81;
+ parameter ADDR_DATA_OUT2 = 8'h82;
+ parameter ADDR_DATA_OUT3 = 8'h83;
+ parameter ADDR_DATA_OUT4 = 8'h84;
+ parameter ADDR_DATA_OUT5 = 8'h85;
+ parameter ADDR_DATA_OUT6 = 8'h86;
+ parameter ADDR_DATA_OUT7 = 8'h87;
+ parameter ADDR_DATA_OUT8 = 8'h88;
+ parameter ADDR_DATA_OUT9 = 8'h89;
+ parameter ADDR_DATA_OUT10 = 8'h8a;
+ parameter ADDR_DATA_OUT11 = 8'h8b;
+ parameter ADDR_DATA_OUT12 = 8'h8c;
+ parameter ADDR_DATA_OUT13 = 8'h8d;
+ parameter ADDR_DATA_OUT14 = 8'h8e;
+ parameter ADDR_DATA_OUT15 = 8'h8f;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg tb_clk;
+ reg tb_reset_n;
+
+ reg tb_cs;
+ reg tb_write_read;
+
+ reg [7 : 0] tb_address;
+ reg [31 : 0] tb_data_in;
+ wire [31 : 0] tb_data_out;
+ wire tb_error;
+
+ reg [63 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg error_found;
+ reg [31 : 0] read_data;
+
+ reg [511 : 0] extracted_data;
+
+ reg display_cycle_ctr;
+ reg display_read_write;
+
+
+ //----------------------------------------------------------------
+ // Chacha device under test.
+ //----------------------------------------------------------------
+ chacha dut(
+ // Clock and reset.
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ // Control.
+ .cs(tb_cs),
+ .we(tb_write_read),
+
+ // Data ports.
+ .address(tb_address),
+ .write_data(tb_data_in),
+ .read_data(tb_data_out),
+ .error(tb_error)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //--------------------------------------------------------------------
+ // dut_monitor
+ //
+ // Monitor displaying information every cycle.
+ // Includes the cycle counter.
+ //--------------------------------------------------------------------
+ always @ (posedge tb_clk)
+ begin : dut_monitor
+ cycle_ctr = cycle_ctr + 1;
+
+ if (display_cycle_ctr)
+ begin
+ $display("cycle = %016x:", cycle_ctr);
+ end
+
+ if (display_read_write)
+ begin
+
+ if (dut.cs)
+ begin
+ if (dut.we)
+ begin
+ $display("*** Write acess: addr 0x%02x = 0x%08x", dut.address, dut.write_data);
+ end
+ else
+ begin
+ $display("*** Read acess: addr 0x%02x = 0x%08x", dut.address, dut.read_data);
+ end
+ end
+ end
+
+ end // dut_monitor
+
+
+ //----------------------------------------------------------------
+ // set_display_prefs()
+ //
+ // Set the different monitor displays we want to see during
+ // simulation.
+ //----------------------------------------------------------------
+ task set_display_prefs(
+ input cycles,
+ input read_write);
+ begin
+ display_cycle_ctr = cycles;
+ display_read_write = read_write;
+ end
+ endtask // set_display_prefs
+
+
+ //----------------------------------------------------------------
+ // reset_dut
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ tb_reset_n = 0;
+ #(4 * CLK_HALF_PERIOD);
+ tb_reset_n = 1;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // read_reg
+ //
+ // Task that reads and display the value of
+ // a register in the dut.
+ //----------------------------------------------------------------
+ task read_reg(input [7 : 0] addr);
+ begin
+ tb_cs = 1;
+ tb_write_read = 0;
+ tb_address = addr;
+ #(2 * CLK_HALF_PERIOD);
+ tb_cs = 0;
+ tb_write_read = 0;
+ tb_address = 8'h00;
+ tb_data_in = 32'h00000000;
+ end
+ endtask // read_reg
+
+
+ //----------------------------------------------------------------
+ // write_reg
+ //
+ // Task that writes to a register in the dut.
+ //----------------------------------------------------------------
+ task write_reg(input [7 : 0] addr, input [31 : 0] data);
+ begin
+ tb_cs = 1;
+ tb_write_read = 1;
+ tb_address = addr;
+ tb_data_in = data;
+ #(2 * CLK_HALF_PERIOD);
+ tb_cs = 0;
+ tb_write_read = 0;
+ tb_address = 8'h00;
+ tb_data_in = 32'h00000000;
+ end
+ endtask // write_reg
+
+
+ //----------------------------------------------------------------
+ // dump_top_state
+ //
+ // Dump the internal state of the top to std out.
+ //----------------------------------------------------------------
+ task dump_top_state();
+ begin
+ $display("");
+ $display("Top internal state");
+ $display("------------------");
+ $display("init_reg = %01x", dut.init_reg);
+ $display("next_reg = %01x", dut.next_reg);
+ $display("ready_reg = %01x", dut.ready_reg);
+ $display("keylen_reg = %01x", dut.keylen_reg);
+ $display("rounds_reg = %01x", dut.rounds_reg);
+ $display("");
+
+ $display("key0_reg = %08x, key1_reg = %08x, key2_reg = %08x, key3_reg = %08x", dut.key0_reg, dut.key1_reg, dut.key2_reg, dut.key3_reg);
+ $display("key4_reg = %08x, key5_reg = %08x, key6_reg = %08x, key7_reg = %08x", dut.key4_reg, dut.key5_reg, dut.key6_reg, dut.key7_reg);
+ $display("");
+
+ $display("iv0_reg = %08x, iv1_reg = %08x", dut.iv0_reg, dut.iv1_reg);
+ $display("");
+
+ $display("data_in0_reg = %08x, data_in1_reg = %08x, data_in2_reg = %08x, data_in3_reg = %08x", dut.data_in0_reg, dut.data_in1_reg, dut.data_in2_reg, dut.data_in3_reg);
+ $display("data_in4_reg = %08x, data_in5_reg = %08x, data_in6_reg = %08x, data_in7_reg = %08x", dut.data_in4_reg, dut.data_in5_reg, dut.data_in6_reg, dut.data_in7_reg);
+ $display("data_in8_reg = %08x, data_in9_reg = %08x, data_in10_reg = %08x, data_in11_reg = %08x", dut.data_in8_reg, dut.data_in9_reg, dut.data_in10_reg, dut.data_in11_reg);
+ $display("data_in12_reg = %08x, data_in13_reg = %08x, data_in14_reg = %08x, data_in15_reg = %08x", dut.data_in12_reg, dut.data_in13_reg, dut.data_in14_reg, dut.data_in15_reg);
+ $display("");
+
+ $display("data_out_valid_reg = %01x", dut.data_out_valid_reg);
+ $display("data_out0_reg = %08x, data_out1_reg = %08x, data_out2_reg = %08x, data_out3_reg = %08x", dut.data_out0_reg, dut.data_out1_reg, dut.data_out2_reg, dut.data_out3_reg);
+ $display("data_out4_reg = %08x, data_out5_reg = %08x, data_out6_reg = %08x, data_out7_reg = %08x", dut.data_out4_reg, dut.data_out5_reg, dut.data_out6_reg, dut.data_out7_reg);
+ $display("data_out8_reg = %08x, data_out9_reg = %08x, data_out10_reg = %08x, data_out11_reg = %08x", dut.data_out8_reg, dut.data_out9_reg, dut.data_out10_reg, dut.data_out11_reg);
+ $display("data_out12_reg = %08x, data_out13_reg = %08x, data_out14_reg = %08x, data_out15_reg = %08x", dut.data_out12_reg, dut.data_out13_reg, dut.data_out14_reg, dut.data_out15_reg);
+ $display("");
+ end
+ endtask // dump_top_state
+
+
+ //----------------------------------------------------------------
+ // dump_core_state
+ //
+ // Dump the internal state of the core to std out.
+ //----------------------------------------------------------------
+ task dump_core_state();
+ begin
+ $display("");
+ $display("Core internal state");
+ $display("-------------------");
+// $display("Internal data state vector:");
+// $display("0x%064x", dut.core.state_reg);
+ $display("");
+
+ $display("Round state X:");
+ $display("x0_reg = %08x, x1_reg = %08x", dut.core.x0_reg, dut.core.x1_reg);
+ $display("x2_reg = %08x, x3_reg = %08x", dut.core.x2_reg, dut.core.x3_reg);
+ $display("x4_reg = %08x, x5_reg = %08x", dut.core.x4_reg, dut.core.x5_reg);
+ $display("x6_reg = %08x, x7_reg = %08x", dut.core.x6_reg, dut.core.x7_reg);
+ $display("x8_reg = %08x, x9_reg = %08x", dut.core.x8_reg, dut.core.x9_reg);
+ $display("x10_reg = %08x, x11_reg = %08x", dut.core.x10_reg, dut.core.x11_reg);
+ $display("x12_reg = %08x, x13_reg = %08x", dut.core.x12_reg, dut.core.x13_reg);
+ $display("x14_reg = %08x, x15_reg = %08x", dut.core.x14_reg, dut.core.x15_reg);
+ $display("");
+
+ $display("rounds_reg = %01x", dut.core.rounds_reg);
+ $display("qr_ctr_reg = %01x, dr_ctr_reg = %01x", dut.core.qr_ctr_reg, dut.core.dr_ctr_reg);
+ $display("block0_ctr_reg = %08x, block1_ctr_reg = %08x", dut.core.block0_ctr_reg, dut.core.block1_ctr_reg);
+
+ $display("");
+
+ $display("chacha_ctrl_reg = %02x", dut.core.chacha_ctrl_reg);
+ $display("");
+
+ $display("data_in_reg = %064x", dut.core.data_in_reg);
+ $display("data_out_valid_reg = %01x", dut.core.data_out_valid_reg);
+ $display("");
+
+ $display("qr0_a_prim = %08x, qr0_b_prim = %08x", dut.core.qr0_a_prim, dut.core.qr0_b_prim);
+ $display("qr0_c_prim = %08x, qr0_d_prim = %08x", dut.core.qr0_c_prim, dut.core.qr0_d_prim);
+ $display("");
+ end
+ endtask // dump_core_state
+
+
+ //----------------------------------------------------------------
+ // display_test_result()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_result();
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %02d test cases completed successfully", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d test cases did not complete successfully.", error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // init_dut()
+ //
+ // Set the input to the DUT to defined values.
+ //----------------------------------------------------------------
+ task init_dut();
+ begin
+ // Set clock, reset and DUT input signals to
+ // defined values at simulation start.
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+ tb_clk = 0;
+ tb_reset_n = 0;
+ tb_cs = 0;
+ tb_write_read = 0;
+ tb_address = 8'h00;
+ tb_data_in = 32'h00000000;
+ end
+ endtask // init_dut
+
+
+ //----------------------------------------------------------------
+ // read_write_test()
+ //
+ // Simple test case that tries to read and write to the
+ // registers in the dut.
+ //
+ // Note: Currently not self testing. No expected values.
+ //----------------------------------------------------------------
+ task read_write_test();
+ begin
+ tc_ctr = tc_ctr + 1;
+
+ write_reg(ADDR_KEY0, 32'h55555555);
+ read_reg(ADDR_KEY0);
+ write_reg(ADDR_KEY1, 32'haaaaaaaa);
+ read_reg(ADDR_KEY1);
+ read_reg(ADDR_CTRL);
+ read_reg(ADDR_STATUS);
+ read_reg(ADDR_KEYLEN);
+ read_reg(ADDR_ROUNDS);
+
+ read_reg(ADDR_KEY0);
+ read_reg(ADDR_KEY1);
+ read_reg(ADDR_KEY2);
+ read_reg(ADDR_KEY3);
+ read_reg(ADDR_KEY4);
+ read_reg(ADDR_KEY5);
+ read_reg(ADDR_KEY6);
+ read_reg(ADDR_KEY7);
+ end
+ endtask // read_write_test
+
+
+ //----------------------------------------------------------------
+ // write_parameters()
+ //
+ // Write key, iv and other parameters to the dut.
+ //----------------------------------------------------------------
+ task write_parameters(input [256 : 0] key,
+ input key_length,
+ input [64 : 0] iv,
+ input [4 : 0] rounds);
+ begin
+ write_reg(ADDR_KEY0, key[255 : 224]);
+ write_reg(ADDR_KEY1, key[223 : 192]);
+ write_reg(ADDR_KEY2, key[191 : 160]);
+ write_reg(ADDR_KEY3, key[159 : 128]);
+ write_reg(ADDR_KEY4, key[127 : 96]);
+ write_reg(ADDR_KEY5, key[95 : 64]);
+ write_reg(ADDR_KEY6, key[63 : 32]);
+ write_reg(ADDR_KEY7, key[31 : 0]);
+ write_reg(ADDR_IV0, iv[63 : 32]);
+ write_reg(ADDR_IV1, iv[31 : 0]);
+ write_reg(ADDR_KEYLEN, {{31'b0000000000000000000000000000000}, key_length});
+ write_reg(ADDR_ROUNDS, {{27'b000000000000000000000000000}, rounds});
+ end
+ endtask // write_parameters
+
+
+ //----------------------------------------------------------------
+ // start_init_block()
+ //
+ // Toggle the init signal in the dut to make it start processing
+ // the first block available in the data in registers.
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is ready to react on the init signal.
+ //----------------------------------------------------------------
+ task start_init_block();
+ begin
+ write_reg(ADDR_CTRL, 32'h00000001);
+ #(4 * CLK_HALF_PERIOD);
+ write_reg(ADDR_CTRL, 32'h00000000);
+ end
+ endtask // start_init_block
+
+
+ //----------------------------------------------------------------
+ // start_next_block()
+ //
+ // Toggle the next signal in the dut to make it start processing
+ // the next block available in the data in registers.
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is ready to react on the next signal.
+ //----------------------------------------------------------------
+ task start_next_block();
+ begin
+ write_reg(ADDR_CTRL, 32'h00000002);
+ #(4 * CLK_HALF_PERIOD);
+ write_reg(ADDR_CTRL, 32'h00000000);
+
+ if (DEBUG)
+ begin
+ $display("Debug of next state.");
+ dump_core_state();
+ #(4 * CLK_HALF_PERIOD);
+ dump_core_state();
+ end
+ end
+ endtask // start_next_block
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is actively processing and will in fact at some
+ // point set the flag.
+ //----------------------------------------------------------------
+ task wait_ready();
+ begin
+ while (!tb_data_out[STATUS_READY_BIT])
+ begin
+ read_reg(ADDR_STATUS);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // extract_data()
+ //
+ // Extracts all 16 data out words and combine them into the
+ // global extracted_data.
+ //----------------------------------------------------------------
+ task extract_data();
+ begin
+ read_reg(ADDR_DATA_OUT0);
+ extracted_data[511 : 480] = tb_data_out;
+ read_reg(ADDR_DATA_OUT1);
+ extracted_data[479 : 448] = tb_data_out;
+ read_reg(ADDR_DATA_OUT2);
+ extracted_data[447 : 416] = tb_data_out;
+ read_reg(ADDR_DATA_OUT3);
+ extracted_data[415 : 384] = tb_data_out;
+ read_reg(ADDR_DATA_OUT4);
+ extracted_data[383 : 352] = tb_data_out;
+ read_reg(ADDR_DATA_OUT5);
+ extracted_data[351 : 320] = tb_data_out;
+ read_reg(ADDR_DATA_OUT6);
+ extracted_data[319 : 288] = tb_data_out;
+ read_reg(ADDR_DATA_OUT7);
+ extracted_data[287 : 256] = tb_data_out;
+ read_reg(ADDR_DATA_OUT8);
+ extracted_data[255 : 224] = tb_data_out;
+ read_reg(ADDR_DATA_OUT9);
+ extracted_data[223 : 192] = tb_data_out;
+ read_reg(ADDR_DATA_OUT10);
+ extracted_data[191 : 160] = tb_data_out;
+ read_reg(ADDR_DATA_OUT11);
+ extracted_data[159 : 128] = tb_data_out;
+ read_reg(ADDR_DATA_OUT12);
+ extracted_data[127 : 96] = tb_data_out;
+ read_reg(ADDR_DATA_OUT13);
+ extracted_data[95 : 64] = tb_data_out;
+ read_reg(ADDR_DATA_OUT14);
+ extracted_data[63 : 32] = tb_data_out;
+ read_reg(ADDR_DATA_OUT15);
+ extracted_data[31 : 0] = tb_data_out;
+ end
+ endtask // extract_data
+
+
+ //----------------------------------------------------------------
+ // run_two_blocks_test_vector()
+ //
+ // Runs a test case with two blocks based on the given
+ // test vector. Only the final block is compared.
+ //----------------------------------------------------------------
+ task run_two_blocks_test_vector(input [7 : 0] major,
+ input [7 : 0] minor,
+ input [256 : 0] key,
+ input key_length,
+ input [64 : 0] iv,
+ input [4 : 0] rounds,
+ input [511 : 0] expected);
+ begin
+ tc_ctr = tc_ctr + 1;
+
+ $display("***TC%2d-%2d started", major, minor);
+ $display("***-----------------");
+ write_parameters(key, key_length, iv, rounds);
+
+ start_init_block();
+ wait_ready();
+ extract_data();
+
+ if (DEBUG)
+ begin
+ $display("State after first block:");
+ dump_core_state();
+
+ $display("First block:");
+ $display("0x%064x", extracted_data);
+ end
+
+ start_next_block();
+
+ if (DEBUG)
+ begin
+ $display("State after init of second block:");
+ dump_core_state();
+ end
+
+ wait_ready();
+ extract_data();
+
+ if (DEBUG)
+ begin
+ $display("State after init of second block:");
+ dump_core_state();
+
+ $display("Second block:");
+ $display("0x%064x", extracted_data);
+ end
+
+ if (extracted_data != expected)
+ begin
+ error_ctr = error_ctr + 1;
+ $display("***TC%2d-%2d - ERROR", major, minor);
+ $display("***-----------------");
+ $display("Expected:");
+ $display("0x%064x", expected);
+ $display("Got:");
+ $display("0x%064x", extracted_data);
+ end
+ else
+ begin
+ $display("***TC%2d-%2d - SUCCESS", major, minor);
+ $display("***-------------------");
+ end
+ $display("");
+ end
+ endtask // run_two_blocks_test_vector
+
+
+ //----------------------------------------------------------------
+ // run_test_vector()
+ //
+ // Runs a test case based on the given test vector.
+ //----------------------------------------------------------------
+ task run_test_vector(input [7 : 0] major,
+ input [7 : 0] minor,
+ input [256 : 0] key,
+ input key_length,
+ input [64 : 0] iv,
+ input [4 : 0] rounds,
+ input [511 : 0] expected);
+ begin
+ tc_ctr = tc_ctr + 1;
+
+ $display("***TC%2d-%2d started", major, minor);
+ $display("***-----------------");
+ write_parameters(key, key_length, iv, rounds);
+
+ start_init_block();
+ wait_ready();
+ extract_data();
+
+ if (extracted_data != expected)
+ begin
+ error_ctr = error_ctr + 1;
+ $display("***TC%2d-%2d - ERROR", major, minor);
+ $display("***-----------------");
+ $display("Expected:");
+ $display("0x%064x", expected);
+ $display("Got:");
+ $display("0x%064x", extracted_data);
+ end
+ else
+ begin
+ $display("***TC%2d-%2d - SUCCESS", major, minor);
+ $display("***-------------------");
+ end
+ $display("");
+ end
+ endtask // run_test_vector
+
+
+ //----------------------------------------------------------------
+ // chacha_test
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : chacha_test
+ $display(" -- Testbench for chacha started --");
+ init_dut();
+ set_display_prefs(0, 0);
+ reset_dut();
+
+ $display("State at init after reset:");
+ dump_top_state();
+
+ $display("TC1-1: All zero inputs. 128 bit key, 8 rounds.");
+ run_test_vector(TC1, ONE,
+ 256'h0000000000000000000000000000000000000000000000000000000000000000,
+ KEY_128_BITS,
+ 64'h0000000000000000,
+ EIGHT_ROUNDS,
+ 512'he28a5fa4a67f8c5defed3e6fb7303486aa8427d31419a729572d777953491120b64ab8e72b8deb85cd6aea7cb6089a101824beeb08814a428aab1fa2c816081b);
+
+ $display("TC7-2: Increasing, decreasing sequences in key and IV. 256 bit key, 8 rounds.");
+ run_test_vector(TC7, TWO,
+ 256'h00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100,
+ KEY_256_BITS,
+ 64'h0f1e2d3c4b596877,
+ EIGHT_ROUNDS,
+ 512'h60fdedbd1a280cb741d0593b6ea0309010acf18e1471f68968f4c9e311dca149b8e027b47c81e0353db013891aa5f68ea3b13dd2f3b8dd0873bf3746e7d6c567);
+
+
+ $display("TC7-3: Increasing, decreasing sequences in key and IV. 256 bit key, 8 rounds.");
+ $display("TC7-3: Testing correct second block.");
+ run_two_blocks_test_vector(TC7, THREE,
+ 256'h00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100,
+ KEY_256_BITS,
+ 64'h0f1e2d3c4b596877,
+ EIGHT_ROUNDS,
+ 512'hfe882395601ce8aded444867fe62ed8741420002e5d28bb573113a418c1f4008e954c188f38ec4f26bb8555e2b7c92bf4380e2ea9e553187fdd42821794416de);
+
+
+ display_test_result();
+ $display("*** chacha simulation done.");
+ $finish;
+ end // chacha_test
+endmodule // tb_chacha
+
+//======================================================================
+// EOF tb_chacha.v
+//======================================================================
diff --git a/cipher/chacha/src/tb/tb_chacha_core.v b/cipher/chacha/src/tb/tb_chacha_core.v
new file mode 100644
index 0000000..a1ddfdc
--- /dev/null
+++ b/cipher/chacha/src/tb/tb_chacha_core.v
@@ -0,0 +1,689 @@
+//======================================================================
+//
+// tb_chacha_core.v
+// -----------------
+// Testbench for the Chacha stream cipher core.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2011, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+module tb_chacha_core();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter CLK_HALF_PERIOD = 2;
+
+ parameter TC1 = 1;
+ parameter TC2 = 2;
+ parameter TC3 = 3;
+ parameter TC4 = 4;
+ parameter TC5 = 5;
+ parameter TC6 = 6;
+ parameter TC7 = 7;
+ parameter TC8 = 8;
+ parameter TC9 = 9;
+ parameter TC10 = 10;
+
+ parameter ONE = 1;
+ parameter TWO = 2;
+ parameter THREE = 3;
+ parameter FOUR = 4;
+ parameter FIVE = 5;
+ parameter SIX = 6;
+ parameter SEVEN = 7;
+ parameter EIGHT = 8;
+
+ parameter KEY_128_BITS = 0;
+ parameter KEY_256_BITS = 1;
+
+ parameter EIGHT_ROUNDS = 8;
+ parameter TWELWE_ROUNDS = 12;
+ parameter TWENTY_ROUNDS = 20;
+
+ parameter DISABLE = 0;
+ parameter ENABLE = 1;
+
+ parameter DEFAULT_CTR_INIT = 64'h0000000000000000;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg tb_clk;
+ reg tb_reset_n;
+
+ reg tb_core_init;
+ reg tb_core_next;
+ reg [255 : 0] tb_core_key;
+ reg tb_core_keylen;
+ reg [4 : 0] tb_core_rounds;
+ reg [63 : 0] tb_core_iv;
+ wire tb_core_ready;
+ reg [0 : 511] tb_core_data_in;
+ wire [0 : 511] tb_core_data_out;
+
+ reg display_cycle_ctr;
+ reg display_ctrl_and_ctrs;
+ reg display_qround;
+ reg display_state;
+ reg display_x_state;
+
+
+ //----------------------------------------------------------------
+ // chacha_core device under test.
+ //----------------------------------------------------------------
+ chacha_core dut(
+ // Clock and reset.
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ // Control.
+ .init(tb_core_init),
+ .next(tb_core_next),
+
+ // Parameters.
+ .key(tb_core_key),
+ .keylen(tb_core_keylen),
+ .iv(tb_core_iv),
+ .ctr(DEFAULT_CTR_INIT),
+ .rounds(tb_core_rounds),
+
+ // Data input.
+ .data_in(tb_core_data_in),
+
+ // Status output.
+ .ready(tb_core_ready),
+
+ // Data out with valid signal.
+ .data_out(tb_core_data_out),
+ .data_out_valid(tb_core_data_out_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //--------------------------------------------------------------------
+ // dut_monitor
+ //
+ // Monitor that displays different types of information
+ // every cycle depending on what flags test cases enable.
+ //
+ // The monitor includes a cycle counter for the testbench.
+ //--------------------------------------------------------------------
+ always @ (posedge tb_clk)
+ begin : dut_monitor
+ cycle_ctr = cycle_ctr + 1;
+
+ // Display cycle counter.
+ if (display_cycle_ctr)
+ begin
+ $display("cycle = %08x:", cycle_ctr);
+ $display("");
+ end
+
+ // Display FSM control state and QR, DR counters.
+ if (display_ctrl_and_ctrs)
+ begin
+ $display("chacha_ctrl_reg = %01x", dut.chacha_ctrl_reg);
+ $display("qr_ctr_reg = %01x, dr_ctr_reg = %01x", dut.qr_ctr_reg, dut.dr_ctr_reg);
+ $display("");
+ end
+
+ // Display the internal state register.
+ if (display_state)
+ begin
+// $display("Internal state:");
+// $display("0x%064x", dut.state_reg);
+// $display("");
+ end
+
+ // Display the round processing state register X.
+ if (display_x_state)
+ begin
+ $display("Round state X:");
+ $display("x0_reg = 0x%08x, x0_new = 0x%08x, x0_we = 0x%01x", dut.x0_reg, dut.x0_new, dut.x0_we);
+ $display("x1_reg = 0x%08x, x1_new = 0x%08x, x1_we = 0x%01x", dut.x1_reg, dut.x1_new, dut.x1_we);
+ $display("x2_reg = 0x%08x, x2_new = 0x%08x, x2_we = 0x%01x", dut.x2_reg, dut.x2_new, dut.x2_we);
+ $display("x3_reg = 0x%08x, x3_new = 0x%08x, x3_we = 0x%01x", dut.x3_reg, dut.x3_new, dut.x3_we);
+ $display("x4_reg = 0x%08x, x4_new = 0x%08x, x4_we = 0x%01x", dut.x4_reg, dut.x4_new, dut.x4_we);
+ $display("x5_reg = 0x%08x, x5_new = 0x%08x, x5_we = 0x%01x", dut.x5_reg, dut.x5_new, dut.x5_we);
+ $display("x6_reg = 0x%08x, x6_new = 0x%08x, x6_we = 0x%01x", dut.x6_reg, dut.x6_new, dut.x6_we);
+ $display("x7_reg = 0x%08x, x7_new = 0x%08x, x7_we = 0x%01x", dut.x7_reg, dut.x7_new, dut.x7_we);
+ $display("x8_reg = 0x%08x, x8_new = 0x%08x, x8_we = 0x%01x", dut.x8_reg, dut.x8_new, dut.x8_we);
+ $display("x9_reg = 0x%08x, x9_new = 0x%08x, x9_we = 0x%01x", dut.x9_reg, dut.x9_new, dut.x9_we);
+ $display("x10_reg = 0x%08x, x10_new = 0x%08x, x10_we = 0x%01x", dut.x10_reg, dut.x10_new, dut.x10_we);
+ $display("x11_reg = 0x%08x, x11_new = 0x%08x, x11_we = 0x%01x", dut.x11_reg, dut.x11_new, dut.x11_we);
+ $display("x12_reg = 0x%08x, x12_new = 0x%08x, x12_we = 0x%01x", dut.x12_reg, dut.x12_new, dut.x12_we);
+ $display("x13_reg = 0x%08x, x13_new = 0x%08x, x13_we = 0x%01x", dut.x13_reg, dut.x13_new, dut.x13_we);
+ $display("x14_reg = 0x%08x, x14_new = 0x%08x, x14_we = 0x%01x", dut.x14_reg, dut.x14_new, dut.x14_we);
+ $display("x15_reg = 0x%08x, x15_new = 0x%08x, x15_we = 0x%01x", dut.x15_reg, dut.x15_new, dut.x15_we);
+ $display("");
+ end
+
+ // Display the qround input and outputs.
+ if (display_qround)
+ begin
+ $display("a = %08x, b = %08x, c = %08x, d = %08x", dut.qr0_a, dut.qr0_b, dut.qr0_c, dut.qr0_d);
+ $display("qr0_a_prim = %08x, qr0_b_prim = %08x, qr0_c_prim = %08x, qr0_d_prim = %08x", dut.qr0_a_prim, dut.qr0_b_prim, dut.qr0_c_prim, dut.qr0_d_prim);
+ $display("");
+ end
+
+ end // dut_monitor
+
+
+ //----------------------------------------------------------------
+ // dump_state()
+ // Dump the internal CHACHA state to std out.
+ //----------------------------------------------------------------
+ task dump_state();
+ begin
+ $display("");
+ $display("Internal state:");
+ $display("---------------");
+// $display("0x%064x", dut.state_reg);
+// $display("");
+
+ $display("Round state X::");
+ $display("x0_reg = %08x, x1_reg = %08x", dut.x0_reg, dut.x1_reg);
+ $display("x2_reg = %08x, x3_reg = %08x", dut.x2_reg, dut.x3_reg);
+ $display("x4_reg = %08x, x5_reg = %08x", dut.x4_reg, dut.x5_reg);
+ $display("x6_reg = %08x, x7_reg = %08x", dut.x6_reg, dut.x7_reg);
+ $display("x8_reg = %08x, x9_reg = %08x", dut.x8_reg, dut.x9_reg);
+ $display("x10_reg = %08x, x11_reg = %08x", dut.x10_reg, dut.x11_reg);
+ $display("x12_reg = %08x, x13_reg = %08x", dut.x12_reg, dut.x13_reg);
+ $display("x14_reg = %08x, x15_reg = %08x", dut.x14_reg, dut.x15_reg);
+ $display("");
+
+ $display("rounds_reg = %01x", dut.rounds_reg);
+ $display("qr_ctr_reg = %01x, dr_ctr_reg = %01x", dut.qr_ctr_reg, dut.dr_ctr_reg);
+ $display("block0_ctr_reg = %08x, block1_ctr_reg = %08x", dut.block0_ctr_reg, dut.block1_ctr_reg);
+
+ $display("");
+
+ $display("chacha_ctrl_reg = %02x", dut.chacha_ctrl_reg);
+ $display("");
+
+ $display("data_in_reg = %064x", dut.data_in_reg);
+ $display("data_out_valid_reg = %01x", dut.data_out_valid_reg);
+ $display("");
+
+ $display("qr0_a_prim = %08x, qr0_b_prim = %08x", dut.qr0_a_prim, dut.qr0_b_prim);
+ $display("qr0_c_prim = %08x, qr0_d_prim = %08x", dut.qr0_c_prim, dut.qr0_d_prim);
+ $display("");
+ end
+ endtask // dump_state
+
+
+ //----------------------------------------------------------------
+ // dump_inout()
+ // Dump the status for input and output ports.
+ //----------------------------------------------------------------
+ task dump_inout();
+ begin
+ $display("");
+ $display("State for input and output ports:");
+ $display("---------------------------------");
+
+ $display("init = %01x", dut.init);
+ $display("next = %01x", dut.next);
+ $display("keylen = %01x", dut.keylen);
+ $display("");
+
+ $display("key = %032x", dut.key);
+ $display("iv = %016x", dut.iv);
+ $display("");
+
+ $display("ready = %01x", dut.ready);
+ $display("data_in = %064x", dut.data_in);
+ $display("data_out = %064x", dut.data_out);
+ $display("data_out_valid = %01x", dut.data_out_valid);
+ $display("");
+ end
+ endtask // dump_inout
+
+
+ //----------------------------------------------------------------
+ // test_quarterround()
+ //
+ // Test the quarterround by forcing the inputs of the logic
+ // to known given values and observing the result.
+ //----------------------------------------------------------------
+ task test_quarterround(input [31 : 0] a, input [31 : 0] b,
+ input [31 : 0] c, input [31 : 0] d);
+ begin
+ $display("Test of quarterround.");
+ $display("a = 0x%08x, b = 0x%08x", a, b);
+ $display("c = 0x%08x, d = 0x%08x", c, d);
+ $display("");
+
+ dut.qr0_a = a;
+ dut.qr0_b = b;
+ dut.qr0_c = c;
+ dut.qr0_d = d;
+ #(2 * CLK_HALF_PERIOD);
+
+ $display("a0 = 0x%08x, a1 = 0x%08x", dut.qr0.qr.a0, dut.qr0.qr.a1);
+ $display("b0 = 0x%08x, b1 = 0x%08x", dut.qr0.qr.b0, dut.qr0.qr.b1);
+ $display("b2 = 0x%08x, b3 = 0x%08x", dut.qr0.qr.b2, dut.qr0.qr.b3);
+ $display("c0 = 0x%08x, c1 = 0x%08x", dut.qr0.qr.c0, dut.qr0.qr.c1);
+ $display("d0 = 0x%08x, d1 = 0x%08x", dut.qr0.qr.d0, dut.qr0.qr.d1);
+ $display("d2 = 0x%08x, d3 = 0x%08x", dut.qr0.qr.d2, dut.qr0.qr.d3);
+ $display("");
+
+ $display("a_prim = 0x%08x, b_prim = 0x%08x", dut.qr0_a_prim, dut.qr0_b_prim);
+ $display("c_prim = 0x%08x, d_prim = 0x%08x", dut.qr0_c_prim, dut.qr0_d_prim);
+ $display("");
+ end
+ endtask // test_quarterround
+
+
+ //----------------------------------------------------------------
+ // qr_tests()
+ //
+ // Run some simple test on the qr logic.
+ // Note: Not self testing. No expected value used.
+ //----------------------------------------------------------------
+ task qr_tests();
+ begin
+ $display("*** Test of Quarterround:");
+ $display("");
+ test_quarterround(32'h11223344, 32'h11223344, 32'h11223344, 32'h11223344);
+ test_quarterround(32'h55555555, 32'h55555555, 32'h55555555, 32'h55555555);
+ end
+ endtask // qr_tests
+
+
+ //----------------------------------------------------------------
+ // set_core_init()
+ //
+ // Set core init flag to given value.
+ //----------------------------------------------------------------
+ task set_core_init(input value);
+ begin
+ tb_core_init = value;
+ end
+ endtask // set_core_init
+
+
+ //----------------------------------------------------------------
+ // set_core_next()
+ //
+ // Set code next flag to given value.
+ //----------------------------------------------------------------
+ task set_core_next(input value);
+ begin
+ tb_core_next = value;
+ end
+ endtask // set_core_next
+
+
+ //----------------------------------------------------------------
+ // set_core_key_iv_rounds()
+ //
+ // Sets the core key, iv and rounds indata ports
+ // to the given values.
+ //----------------------------------------------------------------
+ task set_core_key_iv_rounds(input [255 : 0] key,
+ input key_length,
+ input [63 : 0] iv,
+ input [4 : 0] rounds);
+ begin
+ tb_core_key = key;
+ tb_core_keylen = key_length;
+ tb_core_iv = iv;
+ tb_core_rounds = rounds;
+ end
+ endtask // set_core_key_iv
+
+
+ //----------------------------------------------------------------
+ // cycle_reset()
+ //
+ // Cycles the reset signal on the dut.
+ //----------------------------------------------------------------
+ task cycle_reset();
+ begin
+ tb_reset_n = 0;
+ #(2 * CLK_HALF_PERIOD);
+
+ @(negedge tb_clk)
+
+ tb_reset_n = 1;
+ #(2 * CLK_HALF_PERIOD);
+ end
+ endtask // cycle_reset
+
+
+ //----------------------------------------------------------------
+ // run_test_case
+ //
+ // Runs a test case based on the given key, keylenght, IV and
+ // expected data out from the DUT.
+ //----------------------------------------------------------------
+ task run_test_case(input [7 : 0] major,
+ input [7 : 0] minor,
+ input [255 : 0] key,
+ input key_length,
+ input [63 : 0] iv,
+ input [4 : 0] rounds,
+ input [511 : 0] expected);
+ begin
+ $display("*** TC %0d-%0d started.", major, minor);
+ $display("");
+
+ tc_ctr = tc_ctr + 1;
+
+ cycle_reset();
+ set_core_key_iv_rounds(key, key_length, iv, rounds);
+ set_core_init(1);
+
+ #(2 * CLK_HALF_PERIOD);
+ set_core_init(0);
+ dump_state();
+
+ // Wait for valid flag and check results.
+ @(posedge dut.data_out_valid);
+ dump_state();
+
+ if (tb_core_data_out == expected)
+ begin
+ $display("*** TC %0d-%0d successful", major, minor);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d-%0d not successful", major, minor);
+ $display("Expected: 0x%064x", expected);
+ $display("Got: 0x%064x", tb_core_data_out);
+ $display("");
+
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // run_test_case
+
+
+ //----------------------------------------------------------------
+ // display_test_result()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_result();
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %d test cases completed successfully", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d test cases did not complete successfully.", error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // init_dut()
+ //
+ // Set the input to the DUT to defined values.
+ //----------------------------------------------------------------
+ task init_dut();
+ begin
+ cycle_ctr = 0;
+ tb_clk = 0;
+ tb_reset_n = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+ set_core_key_iv_rounds(256'h0000000000000001000000000000000100000000000000010000000000000001,
+ 1'b0,
+ 64'h0000000000000001,
+ 5'b01000);
+
+ tb_core_init = 0;
+ tb_core_next = 0;
+ tb_core_data_in = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ end
+ endtask // init_dut
+
+
+ //----------------------------------------------------------------
+ // set_display_prefs()
+ //
+ // Set the different monitor displays we want to see during
+ // simulation.
+ //----------------------------------------------------------------
+ task set_display_prefs(
+ input cycles,
+ input ctrl_ctr,
+ input state,
+ input x_state,
+ input qround);
+ begin
+ display_cycle_ctr = cycles;
+ display_ctrl_and_ctrs = ctrl_ctr;
+ display_state = state;
+ display_x_state = x_state;
+ display_qround = qround;
+ end
+ endtask // set_display_prefs
+
+
+ //----------------------------------------------------------------
+ // chacha_core_test
+ //
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : chacha_core_test
+ $display(" -- Testbench for chacha_core started --");
+ $display("");
+
+ set_display_prefs(0, 0, 1, 1, 0);
+ qr_tests();
+ init_dut();
+ $display("*** State at init:");
+ $display("");
+ dump_state();
+
+ #(4 * CLK_HALF_PERIOD);
+ @(negedge tb_clk)
+ tb_reset_n = 1;
+ #(2 * CLK_HALF_PERIOD);
+ $display("*** State after release of reset:");
+ $display("");
+ dump_state();
+
+ $display("TC1-1: All zero inputs. 128 bit key, 8 rounds.");
+ run_test_case(TC1, ONE,
+ 256'h0000000000000000000000000000000000000000000000000000000000000000,
+ KEY_128_BITS,
+ 64'h0000000000000000,
+ EIGHT_ROUNDS,
+ 512'he28a5fa4a67f8c5defed3e6fb7303486aa8427d31419a729572d777953491120b64ab8e72b8deb85cd6aea7cb6089a101824beeb08814a428aab1fa2c816081b);
+
+
+ $display("TC1-2: All zero inputs. 128 bit key, 12 rounds.");
+ run_test_case(TC1, TWO,
+ 256'h0000000000000000000000000000000000000000000000000000000000000000,
+ KEY_128_BITS,
+ 64'h0000000000000000,
+ TWELWE_ROUNDS,
+ 512'he1047ba9476bf8ff312c01b4345a7d8ca5792b0ad467313f1dc412b5fdce32410dea8b68bd774c36a920f092a04d3f95274fbeff97bc8491fcef37f85970b450);
+
+
+ $display("TC1-3: All zero inputs. 128 bit key, 20 rounds.");
+ run_test_case(TC1, THREE,
+ 256'h0000000000000000000000000000000000000000000000000000000000000000,
+ KEY_128_BITS,
+ 64'h0000000000000000,
+ TWENTY_ROUNDS,
+ 512'h89670952608364fd00b2f90936f031c8e756e15dba04b8493d00429259b20f46cc04f111246b6c2ce066be3bfb32d9aa0fddfbc12123d4b9e44f34dca05a103f);
+
+
+ $display("TC1-4: All zero inputs. 256 bit key, 8 rounds.");
+ run_test_case(TC1, FOUR,
+ 256'h0000000000000000000000000000000000000000000000000000000000000000,
+ KEY_256_BITS,
+ 64'h0000000000000000,
+ EIGHT_ROUNDS,
+ 512'h3e00ef2f895f40d67f5bb8e81f09a5a12c840ec3ce9a7f3b181be188ef711a1e984ce172b9216f419f445367456d5619314a42a3da86b001387bfdb80e0cfe42);
+
+
+ $display("TC1-5: All zero inputs. 256 bit key, 12 rounds.");
+ run_test_case(TC1, FIVE,
+ 256'h0000000000000000000000000000000000000000000000000000000000000000,
+ KEY_256_BITS,
+ 64'h0000000000000000,
+ TWELWE_ROUNDS,
+ 512'h9bf49a6a0755f953811fce125f2683d50429c3bb49e074147e0089a52eae155f0564f879d27ae3c02ce82834acfa8c793a629f2ca0de6919610be82f411326be);
+
+
+ $display("TC1-6: All zero inputs. 256 bit key, 20 rounds.");
+ run_test_case(TC1, SIX,
+ 256'h0000000000000000000000000000000000000000000000000000000000000000,
+ KEY_256_BITS,
+ 64'h0000000000000000,
+ TWENTY_ROUNDS,
+ 512'h76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586);
+
+
+ $display("TC2-1: One bit in key set, all zero IV. 128 bit key, 8 rounds.");
+ run_test_case(TC2, ONE,
+ 256'h0100000000000000000000000000000000000000000000000000000000000000,
+ KEY_128_BITS,
+ 64'h0000000000000000,
+ EIGHT_ROUNDS,
+ 512'h03a7669888605a0765e8357475e58673f94fc8161da76c2a3aa2f3caf9fe5449e0fcf38eb882656af83d430d410927d55c972ac4c92ab9da3713e19f761eaa14);
+
+
+ $display("TC2-2: One bit in key set, all zero IV. 256 bit key, 8 rounds.");
+ run_test_case(TC2, ONE,
+ 256'h0100000000000000000000000000000000000000000000000000000000000000,
+ KEY_256_BITS,
+ 64'h0000000000000000,
+ EIGHT_ROUNDS,
+ 512'hcf5ee9a0494aa9613e05d5ed725b804b12f4a465ee635acc3a311de8740489ea289d04f43c7518db56eb4433e498a1238cd8464d3763ddbb9222ee3bd8fae3c8);
+
+
+ $display("TC3-1: All zero key, one bit in IV set. 128 bit key, 8 rounds.");
+ run_test_case(TC3, ONE,
+ 256'h0000000000000000000000000000000000000000000000000000000000000000,
+ KEY_128_BITS,
+ 64'h0100000000000000,
+ EIGHT_ROUNDS,
+ 512'h25f5bec6683916ff44bccd12d102e692176663f4cac53e719509ca74b6b2eec85da4236fb29902012adc8f0d86c8187d25cd1c486966930d0204c4ee88a6ab35);
+
+
+ $display("TC4-1: All bits in key and IV are set. 128 bit key, 8 rounds.");
+ run_test_case(TC4, ONE,
+ 256'hffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff,
+ KEY_128_BITS,
+ 64'hffffffffffffffff,
+ EIGHT_ROUNDS,
+ 512'h2204d5b81ce662193e00966034f91302f14a3fb047f58b6e6ef0d721132304163e0fb640d76ff9c3b9cd99996e6e38fad13f0e31c82244d33abbc1b11e8bf12d);
+
+
+ $display("TC5-1: Even bits in key, IV are set. 128 bit key, 8 rounds.");
+ run_test_case(TC5, ONE,
+ 256'h5555555555555555555555555555555555555555555555555555555555555555,
+ KEY_128_BITS,
+ 64'h5555555555555555,
+ EIGHT_ROUNDS,
+ 512'hf0a23bc36270e18ed0691dc384374b9b2c5cb60110a03f56fa48a9fbbad961aa6bab4d892e96261b6f1a0919514ae56f86e066e17c71a4176ac684af1c931996);
+
+
+ $display("TC6-1: Odd bits in key, IV are set. 128 bit key, 8 rounds.");
+ run_test_case(TC6, ONE,
+ 256'haaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
+ KEY_128_BITS,
+ 64'haaaaaaaaaaaaaaaa,
+ EIGHT_ROUNDS,
+ 512'h312d95c0bc38eff4942db2d50bdc500a30641ef7132db1a8ae838b3bea3a7ab03815d7a4cc09dbf5882a3433d743aced48136ebab73299506855c0f5437a36c6);
+
+
+ $display("TC7-1: Increasing, decreasing sequences in key and IV. 128 bit key, 8 rounds");
+ run_test_case(TC7, ONE,
+ 256'h00112233445566778899aabbccddeeff00000000000000000000000000000000,
+ KEY_128_BITS,
+ 64'h0f1e2d3c4b596877,
+ EIGHT_ROUNDS,
+ 512'ha7a6c81bd8ac106e8f3a46a1bc8ec702e95d18c7e0f424519aeafb54471d83a2bf888861586b73d228eaaf82f9665a5a155e867f93731bfbe24fab495590b231);
+
+
+ $display("TC7-2: Increasing, decreasing sequences in key and IV. 256 bit key, 8 rounds.");
+ run_test_case(TC7, TWO,
+ 256'h00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100,
+ KEY_256_BITS,
+ 64'h0f1e2d3c4b596877,
+ EIGHT_ROUNDS,
+ 512'h60fdedbd1a280cb741d0593b6ea0309010acf18e1471f68968f4c9e311dca149b8e027b47c81e0353db013891aa5f68ea3b13dd2f3b8dd0873bf3746e7d6c567);
+
+
+ $display("TC8-128-8: Random inputs. 128 bit key, 8 rounds.");
+ run_test_case(TC8, ONE,
+ 256'hc46ec1b18ce8a878725a37e780dfb73500000000000000000000000000000000,
+ KEY_128_BITS,
+ 64'h1ada31d5cf688221,
+ EIGHT_ROUNDS,
+ 512'h6a870108859f679118f3e205e2a56a6826ef5a60a4102ac8d4770059fcb7c7bae02f5ce004a6bfbbea53014dd82107c0aa1c7ce11b7d78f2d50bd3602bbd2594);
+
+
+ // Finish in style.
+ $display("*** chacha_core simulation done ***");
+ display_test_result();
+ $finish;
+ end // chacha_core_test
+
+endmodule // tb_chacha_core
+
+//======================================================================
+// EOF tb_chacha_core.v
+//======================================================================
diff --git a/cipher/chacha/toolruns/Makefile b/cipher/chacha/toolruns/Makefile
new file mode 100755
index 0000000..6f94769
--- /dev/null
+++ b/cipher/chacha/toolruns/Makefile
@@ -0,0 +1,84 @@
+#===================================================================
+#
+# Makefile
+# --------
+# Makefile for building core and top simulation.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2011, NORDUnet A/S All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# - Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# - Neither the name of the NORDUnet nor the names of its contributors may
+# be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#===================================================================
+
+CORE_SRC=../src/rtl/chacha_core.v ../src/rtl/chacha_qr.v
+CORE_TB_SRC=../src/tb/tb_chacha_core.v
+
+TOP_SRC=../src/rtl/chacha.v $(CORE_SRC)
+TOP_TB_SRC=../src/tb/tb_chacha.v
+
+CC=iverilog
+
+
+all: top core
+
+
+top: $(TOP_TB_SRC) $(TOP_SRC)
+ $(CC) -o top.sim $(TOP_TB_SRC) $(TOP_SRC)
+
+
+core: $(CORE_TB_SRC) $(CORE_SRC)
+ $(CC) -o core.sim $(CORE_SRC) $(CORE_TB_SRC)
+
+
+sim-core: core.sim
+ ./core.sim
+
+
+sim-top: top.sim
+ ./top.sim
+
+
+help:
+ @echo "Supported targets:"
+ @echo "------------------"
+ @echo "all: Build all simulation targets."
+ @echo "top: Build the top simulation target."
+ @echo "core: Build the top simulation target."
+ @echo "sim-top: Run top level simulation."
+ @echo "sim-core: Run core level simulation."
+ @echo "debug: Print the internal varibles."
+
+clean:
+ rm -f core.sim
+ rm -f top.sim
+
+#===================================================================
+# EOF Makefile
+#===================================================================
+
diff --git a/coretest/LICENSE b/comm/coretest/LICENSE
similarity index 100%
rename from coretest/LICENSE
rename to comm/coretest/LICENSE
diff --git a/coretest/README.md b/comm/coretest/README.md
similarity index 100%
rename from coretest/README.md
rename to comm/coretest/README.md
diff --git a/coretest/src/rtl/coretest.v b/comm/coretest/src/rtl/coretest.v
similarity index 100%
rename from coretest/src/rtl/coretest.v
rename to comm/coretest/src/rtl/coretest.v
diff --git a/coretest/src/sw/seriedebug.py b/comm/coretest/src/sw/seriedebug.py
similarity index 100%
rename from coretest/src/sw/seriedebug.py
rename to comm/coretest/src/sw/seriedebug.py
diff --git a/coretest/src/tb/tb_coretest.v b/comm/coretest/src/tb/tb_coretest.v
similarity index 100%
rename from coretest/src/tb/tb_coretest.v
rename to comm/coretest/src/tb/tb_coretest.v
diff --git a/coretest/toolruns/Makefile b/comm/coretest/toolruns/Makefile
similarity index 100%
rename from coretest/toolruns/Makefile
rename to comm/coretest/toolruns/Makefile
diff --git a/coretest/toolruns/modelsim/coretest_wave.do b/comm/coretest/toolruns/modelsim/coretest_wave.do
similarity index 100%
rename from coretest/toolruns/modelsim/coretest_wave.do
rename to comm/coretest/toolruns/modelsim/coretest_wave.do
diff --git a/eim/src/rtl/cdc_bus_pulse.v b/comm/eim/src/rtl/cdc_bus_pulse.v
similarity index 100%
rename from eim/src/rtl/cdc_bus_pulse.v
rename to comm/eim/src/rtl/cdc_bus_pulse.v
diff --git a/eim/src/rtl/eim.v b/comm/eim/src/rtl/eim.v
similarity index 100%
rename from eim/src/rtl/eim.v
rename to comm/eim/src/rtl/eim.v
diff --git a/eim/src/rtl/eim_arbiter.v b/comm/eim/src/rtl/eim_arbiter.v
similarity index 100%
rename from eim/src/rtl/eim_arbiter.v
rename to comm/eim/src/rtl/eim_arbiter.v
diff --git a/eim/src/rtl/eim_arbiter_cdc.v b/comm/eim/src/rtl/eim_arbiter_cdc.v
similarity index 100%
rename from eim/src/rtl/eim_arbiter_cdc.v
rename to comm/eim/src/rtl/eim_arbiter_cdc.v
diff --git a/eim/src/rtl/eim_da_phy.v b/comm/eim/src/rtl/eim_da_phy.v
similarity index 100%
rename from eim/src/rtl/eim_da_phy.v
rename to comm/eim/src/rtl/eim_da_phy.v
diff --git a/eim/src/rtl/eim_indicator.v b/comm/eim/src/rtl/eim_indicator.v
similarity index 100%
copy from eim/src/rtl/eim_indicator.v
copy to comm/eim/src/rtl/eim_indicator.v
diff --git a/eim/src/rtl/eim_regs.v b/comm/eim/src/rtl/eim_regs.v
similarity index 100%
rename from eim/src/rtl/eim_regs.v
rename to comm/eim/src/rtl/eim_regs.v
diff --git a/eim/src/sw/Makefile b/comm/eim/src/sw/Makefile
similarity index 100%
rename from eim/src/sw/Makefile
rename to comm/eim/src/sw/Makefile
diff --git a/eim/src/sw/hash_tester_eim.c b/comm/eim/src/sw/hash_tester_eim.c
similarity index 100%
rename from eim/src/sw/hash_tester_eim.c
rename to comm/eim/src/sw/hash_tester_eim.c
diff --git a/eim/src/sw/novena-eim.c b/comm/eim/src/sw/novena-eim.c
similarity index 100%
rename from eim/src/sw/novena-eim.c
rename to comm/eim/src/sw/novena-eim.c
diff --git a/eim/src/sw/novena-eim.h b/comm/eim/src/sw/novena-eim.h
similarity index 100%
rename from eim/src/sw/novena-eim.h
rename to comm/eim/src/sw/novena-eim.h
diff --git a/sha512/LICENSE b/comm/i2c/LICENSE
similarity index 100%
rename from sha512/LICENSE
rename to comm/i2c/LICENSE
diff --git a/i2c/README.md b/comm/i2c/README.md
similarity index 100%
rename from i2c/README.md
rename to comm/i2c/README.md
diff --git a/i2c/src/rtl/i2c_core.v b/comm/i2c/src/rtl/i2c_core.v
similarity index 100%
rename from i2c/src/rtl/i2c_core.v
rename to comm/i2c/src/rtl/i2c_core.v
diff --git a/i2c/src/rtl/i2c_regs.v b/comm/i2c/src/rtl/i2c_regs.v
similarity index 100%
rename from i2c/src/rtl/i2c_regs.v
rename to comm/i2c/src/rtl/i2c_regs.v
diff --git a/i2c/src/sw/Makefile b/comm/i2c/src/sw/Makefile
similarity index 100%
rename from i2c/src/sw/Makefile
rename to comm/i2c/src/sw/Makefile
diff --git a/i2c/src/sw/hash_tester_i2c.c b/comm/i2c/src/sw/hash_tester_i2c.c
similarity index 100%
rename from i2c/src/sw/hash_tester_i2c.c
rename to comm/i2c/src/sw/hash_tester_i2c.c
diff --git a/i2c/LICENSE b/comm/uart/LICENSE
similarity index 100%
rename from i2c/LICENSE
rename to comm/uart/LICENSE
diff --git a/uart/README.md b/comm/uart/README.md
similarity index 100%
rename from uart/README.md
rename to comm/uart/README.md
diff --git a/uart/src/rtl/uart_core.v b/comm/uart/src/rtl/uart_core.v
similarity index 100%
rename from uart/src/rtl/uart_core.v
rename to comm/uart/src/rtl/uart_core.v
diff --git a/uart/src/rtl/uart_regs.v b/comm/uart/src/rtl/uart_regs.v
similarity index 100%
rename from uart/src/rtl/uart_regs.v
rename to comm/uart/src/rtl/uart_regs.v
diff --git a/uart/src/sw/seriedebug.py b/comm/uart/src/sw/seriedebug.py
similarity index 100%
rename from uart/src/sw/seriedebug.py
rename to comm/uart/src/sw/seriedebug.py
diff --git a/uart/src/tb/tb_uart.v b/comm/uart/src/tb/tb_uart.v
similarity index 100%
rename from uart/src/tb/tb_uart.v
rename to comm/uart/src/tb/tb_uart.v
diff --git a/uart/toolruns/Makefile b/comm/uart/toolruns/Makefile
similarity index 100%
rename from uart/toolruns/Makefile
rename to comm/uart/toolruns/Makefile
diff --git a/sha256/LICENSE.txt b/hash/sha1/LICENSE.txt
similarity index 100%
rename from sha256/LICENSE.txt
rename to hash/sha1/LICENSE.txt
diff --git a/sha1/README.md b/hash/sha1/README.md
similarity index 100%
rename from sha1/README.md
rename to hash/sha1/README.md
diff --git a/sha1/src/model/python/sha1.py b/hash/sha1/src/model/python/sha1.py
similarity index 100%
rename from sha1/src/model/python/sha1.py
rename to hash/sha1/src/model/python/sha1.py
diff --git a/sha1/src/rtl/sha1.v b/hash/sha1/src/rtl/sha1.v
similarity index 100%
rename from sha1/src/rtl/sha1.v
rename to hash/sha1/src/rtl/sha1.v
diff --git a/sha1/src/rtl/sha1_core.v b/hash/sha1/src/rtl/sha1_core.v
similarity index 100%
rename from sha1/src/rtl/sha1_core.v
rename to hash/sha1/src/rtl/sha1_core.v
diff --git a/sha1/src/rtl/sha1_w_mem.v b/hash/sha1/src/rtl/sha1_w_mem.v
similarity index 100%
rename from sha1/src/rtl/sha1_w_mem.v
rename to hash/sha1/src/rtl/sha1_w_mem.v
diff --git a/sha1/src/tb/tb_sha1.v b/hash/sha1/src/tb/tb_sha1.v
similarity index 100%
rename from sha1/src/tb/tb_sha1.v
rename to hash/sha1/src/tb/tb_sha1.v
diff --git a/sha1/src/tb/tb_sha1_core.v b/hash/sha1/src/tb/tb_sha1_core.v
similarity index 100%
rename from sha1/src/tb/tb_sha1_core.v
rename to hash/sha1/src/tb/tb_sha1_core.v
diff --git a/sha1/src/tb/tb_sha1_w_mem.v b/hash/sha1/src/tb/tb_sha1_w_mem.v
similarity index 100%
rename from sha1/src/tb/tb_sha1_w_mem.v
rename to hash/sha1/src/tb/tb_sha1_w_mem.v
diff --git a/sha1/toolruns/Makefile b/hash/sha1/toolruns/Makefile
similarity index 100%
rename from sha1/toolruns/Makefile
rename to hash/sha1/toolruns/Makefile
diff --git a/sha1/LICENSE.txt b/hash/sha256/LICENSE.txt
similarity index 100%
rename from sha1/LICENSE.txt
rename to hash/sha256/LICENSE.txt
diff --git a/sha256/README.md b/hash/sha256/README.md
similarity index 100%
rename from sha256/README.md
rename to hash/sha256/README.md
diff --git a/sha256/src/model/sha256.py b/hash/sha256/src/model/sha256.py
similarity index 100%
rename from sha256/src/model/sha256.py
rename to hash/sha256/src/model/sha256.py
diff --git a/sha256/src/rtl/sha256.v b/hash/sha256/src/rtl/sha256.v
similarity index 100%
rename from sha256/src/rtl/sha256.v
rename to hash/sha256/src/rtl/sha256.v
diff --git a/sha256/src/rtl/sha256_core.v b/hash/sha256/src/rtl/sha256_core.v
similarity index 100%
rename from sha256/src/rtl/sha256_core.v
rename to hash/sha256/src/rtl/sha256_core.v
diff --git a/sha256/src/rtl/sha256_k_constants.v b/hash/sha256/src/rtl/sha256_k_constants.v
similarity index 100%
rename from sha256/src/rtl/sha256_k_constants.v
rename to hash/sha256/src/rtl/sha256_k_constants.v
diff --git a/sha256/src/rtl/sha256_w_mem.v b/hash/sha256/src/rtl/sha256_w_mem.v
similarity index 100%
rename from sha256/src/rtl/sha256_w_mem.v
rename to hash/sha256/src/rtl/sha256_w_mem.v
diff --git a/sha256/src/rtl/wb_sha256.v b/hash/sha256/src/rtl/wb_sha256.v
similarity index 100%
rename from sha256/src/rtl/wb_sha256.v
rename to hash/sha256/src/rtl/wb_sha256.v
diff --git a/sha256/src/tb/tb_sha256.v b/hash/sha256/src/tb/tb_sha256.v
similarity index 100%
rename from sha256/src/tb/tb_sha256.v
rename to hash/sha256/src/tb/tb_sha256.v
diff --git a/sha256/src/tb/tb_sha256_core.v b/hash/sha256/src/tb/tb_sha256_core.v
similarity index 100%
rename from sha256/src/tb/tb_sha256_core.v
rename to hash/sha256/src/tb/tb_sha256_core.v
diff --git a/sha256/src/tb/tb_sha256_w_mem.v b/hash/sha256/src/tb/tb_sha256_w_mem.v
similarity index 100%
rename from sha256/src/tb/tb_sha256_w_mem.v
rename to hash/sha256/src/tb/tb_sha256_w_mem.v
diff --git a/sha256/src/tb/tb_wb_sha256.v b/hash/sha256/src/tb/tb_wb_sha256.v
similarity index 100%
rename from sha256/src/tb/tb_wb_sha256.v
rename to hash/sha256/src/tb/tb_wb_sha256.v
diff --git a/sha256/toolruns/Makefile b/hash/sha256/toolruns/Makefile
similarity index 100%
rename from sha256/toolruns/Makefile
rename to hash/sha256/toolruns/Makefile
diff --git a/uart/LICENSE b/hash/sha512/LICENSE
similarity index 100%
rename from uart/LICENSE
rename to hash/sha512/LICENSE
diff --git a/sha512/README.md b/hash/sha512/README.md
similarity index 100%
rename from sha512/README.md
rename to hash/sha512/README.md
diff --git a/sha512/src/model/python/sha512.py b/hash/sha512/src/model/python/sha512.py
similarity index 100%
rename from sha512/src/model/python/sha512.py
rename to hash/sha512/src/model/python/sha512.py
diff --git a/sha512/src/rtl/sha512.v b/hash/sha512/src/rtl/sha512.v
similarity index 100%
rename from sha512/src/rtl/sha512.v
rename to hash/sha512/src/rtl/sha512.v
diff --git a/sha512/src/rtl/sha512_core.v b/hash/sha512/src/rtl/sha512_core.v
similarity index 100%
rename from sha512/src/rtl/sha512_core.v
rename to hash/sha512/src/rtl/sha512_core.v
diff --git a/sha512/src/rtl/sha512_h_constants.v b/hash/sha512/src/rtl/sha512_h_constants.v
similarity index 100%
rename from sha512/src/rtl/sha512_h_constants.v
rename to hash/sha512/src/rtl/sha512_h_constants.v
diff --git a/sha512/src/rtl/sha512_k_constants.v b/hash/sha512/src/rtl/sha512_k_constants.v
similarity index 100%
rename from sha512/src/rtl/sha512_k_constants.v
rename to hash/sha512/src/rtl/sha512_k_constants.v
diff --git a/sha512/src/rtl/sha512_w_mem.v b/hash/sha512/src/rtl/sha512_w_mem.v
similarity index 100%
rename from sha512/src/rtl/sha512_w_mem.v
rename to hash/sha512/src/rtl/sha512_w_mem.v
diff --git a/sha512/src/tb/tb_sha512.v b/hash/sha512/src/tb/tb_sha512.v
similarity index 100%
rename from sha512/src/tb/tb_sha512.v
rename to hash/sha512/src/tb/tb_sha512.v
diff --git a/sha512/src/tb/tb_sha512_core.v b/hash/sha512/src/tb/tb_sha512_core.v
similarity index 100%
rename from sha512/src/tb/tb_sha512_core.v
rename to hash/sha512/src/tb/tb_sha512_core.v
diff --git a/sha512/toolruns/Makefile b/hash/sha512/toolruns/Makefile
similarity index 100%
rename from sha512/toolruns/Makefile
rename to hash/sha512/toolruns/Makefile
diff --git a/core_selector/src/rtl/cipher_selector.v b/platform/common/core_selector/src/rtl/cipher_selector.v
similarity index 100%
rename from core_selector/src/rtl/cipher_selector.v
rename to platform/common/core_selector/src/rtl/cipher_selector.v
diff --git a/core_selector/src/rtl/core_selector.v b/platform/common/core_selector/src/rtl/core_selector.v
similarity index 100%
rename from core_selector/src/rtl/core_selector.v
rename to platform/common/core_selector/src/rtl/core_selector.v
diff --git a/core_selector/src/rtl/hash_selector.v b/platform/common/core_selector/src/rtl/hash_selector.v
similarity index 100%
rename from core_selector/src/rtl/hash_selector.v
rename to platform/common/core_selector/src/rtl/hash_selector.v
diff --git a/core_selector/src/rtl/rng_selector.v b/platform/common/core_selector/src/rtl/rng_selector.v
similarity index 100%
rename from core_selector/src/rtl/rng_selector.v
rename to platform/common/core_selector/src/rtl/rng_selector.v
diff --git a/i2c/toolruns/xilinx/novena/build/.gitignore b/platform/novena/eim/build/.gitignore
similarity index 100%
rename from i2c/toolruns/xilinx/novena/build/.gitignore
rename to platform/novena/eim/build/.gitignore
diff --git a/eim/toolruns/xilinx/novena/build/Makefile b/platform/novena/eim/build/Makefile
similarity index 100%
rename from eim/toolruns/xilinx/novena/build/Makefile
rename to platform/novena/eim/build/Makefile
diff --git a/i2c/toolruns/xilinx/novena/build/xilinx.mk b/platform/novena/eim/build/xilinx.mk
similarity index 100%
rename from i2c/toolruns/xilinx/novena/build/xilinx.mk
rename to platform/novena/eim/build/xilinx.mk
diff --git a/i2c/toolruns/xilinx/novena/build/xilinx.opt b/platform/novena/eim/build/xilinx.opt
similarity index 100%
rename from i2c/toolruns/xilinx/novena/build/xilinx.opt
rename to platform/novena/eim/build/xilinx.opt
diff --git a/platform/novena/eim/iseconfig/.gitignore b/platform/novena/eim/iseconfig/.gitignore
new file mode 100644
index 0000000..91e8e2b
--- /dev/null
+++ b/platform/novena/eim/iseconfig/.gitignore
@@ -0,0 +1,48 @@
+iseconfig
+_ngo
+*.bgn
+*_bitgen.xwbt
+*.bld
+*.cmd_log
+*.drc
+*_envsettings.html
+*_guide.ncd
+*.lso
+*_map.map
+*_map.mrp
+*_map.ncd
+*_map.ngm
+*_map.xrpt
+*.ncd
+*.ngc
+*.ngd
+*_ngdbuild.xrpt
+*.ngr
+*.pad
+*_pad.csv
+*_pad.txt
+*.par
+*_par.xrpt
+*.pcf
+*.prj
+*.ptwx
+*.stx
+*_summary.html
+*_summary.xml
+*.syr
+*.twr
+*.twx
+*.unroutes
+*_usage.xml
+*.ut
+*.xpi
+*.xst
+*_xst.xrpt
+*.gise
+par_usage_statistics.html
+usage_statistics_webtalk.html
+webtalk.log
+webtalk_pn.xml
+xlnx_auto_0_xdb
+_xmsgs
+xst
diff --git a/eim/toolruns/xilinx/novena/iseconfig/novena_reorg_eim.xise b/platform/novena/eim/iseconfig/novena_reorg_eim.xise
similarity index 100%
rename from eim/toolruns/xilinx/novena/iseconfig/novena_reorg_eim.xise
rename to platform/novena/eim/iseconfig/novena_reorg_eim.xise
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/_xmsgs/cg.xmsgs b/platform/novena/eim/rtl/ipcore/_xmsgs/cg.xmsgs
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/_xmsgs/cg.xmsgs
rename to platform/novena/eim/rtl/ipcore/_xmsgs/cg.xmsgs
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/_xmsgs/pn_parser.xmsgs b/platform/novena/eim/rtl/ipcore/_xmsgs/pn_parser.xmsgs
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/_xmsgs/pn_parser.xmsgs
rename to platform/novena/eim/rtl/ipcore/_xmsgs/pn_parser.xmsgs
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.asy b/platform/novena/eim/rtl/ipcore/clkmgr_dcm.asy
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.asy
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm.asy
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.gise b/platform/novena/eim/rtl/ipcore/clkmgr_dcm.gise
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.gise
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm.gise
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.ncf b/platform/novena/eim/rtl/ipcore/clkmgr_dcm.ncf
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.ncf
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm.ncf
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.sym b/platform/novena/eim/rtl/ipcore/clkmgr_dcm.sym
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.sym
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm.sym
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.ucf b/platform/novena/eim/rtl/ipcore/clkmgr_dcm.ucf
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.ucf
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm.ucf
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.v b/platform/novena/eim/rtl/ipcore/clkmgr_dcm.v
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.v
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm.v
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.veo b/platform/novena/eim/rtl/ipcore/clkmgr_dcm.veo
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.veo
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm.veo
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.xco b/platform/novena/eim/rtl/ipcore/clkmgr_dcm.xco
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.xco
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm.xco
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.xdc b/platform/novena/eim/rtl/ipcore/clkmgr_dcm.xdc
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.xdc
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm.xdc
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.xise b/platform/novena/eim/rtl/ipcore/clkmgr_dcm.xise
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm.xise
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm.xise
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_readme.txt b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/clk_wiz_v3_6_readme.txt
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_readme.txt
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/clk_wiz_v3_6_readme.txt
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/clk_wiz_v3_6_readme.txt b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_readme.txt
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/clk_wiz_v3_6_readme.txt
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_readme.txt
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_vinfo.html b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_vinfo.html
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_vinfo.html
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_vinfo.html
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/doc/pg065_clk_wiz.pdf b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/doc/pg065_clk_wiz.pdf
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/doc/pg065_clk_wiz.pdf
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/doc/pg065_clk_wiz.pdf
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.ucf b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.ucf
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.ucf
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.ucf
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.v b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.v
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.v
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.v
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.xdc b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.xdc
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.xdc
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.xdc
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/implement.bat b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/implement.bat
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/implement.bat
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/implement.bat
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/implement.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/implement.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/implement.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/implement.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.bat b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.bat
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.bat
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.bat
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.tcl b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.tcl
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.tcl
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.tcl
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.bat b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.bat
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.bat
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.bat
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.tcl b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.tcl
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.tcl
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.tcl
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/xst.prj b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/xst.prj
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/xst.prj
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/xst.prj
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/xst.scr b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/xst.scr
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/implement/xst.scr
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/implement/xst.scr
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/clkmgr_dcm_tb.v b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/clkmgr_dcm_tb.v
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/clkmgr_dcm_tb.v
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/clkmgr_dcm_tb.v
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simcmds.tcl b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simcmds.tcl
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simcmds.tcl
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simcmds.tcl
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.bat b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.bat
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.bat
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.bat
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.bat b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.bat
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.bat
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.bat
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.do b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.do
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.do
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.do
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_ncsim.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_ncsim.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_ncsim.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_ncsim.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_vcs.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_vcs.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_vcs.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_vcs.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/ucli_commands.key b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/ucli_commands.key
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/ucli_commands.key
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/ucli_commands.key
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/vcs_session.tcl b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/vcs_session.tcl
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/vcs_session.tcl
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/vcs_session.tcl
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.do b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.do
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.do
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.do
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.sv b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.sv
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.sv
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.sv
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/clkmgr_dcm_tb.v b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/clkmgr_dcm_tb.v
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/clkmgr_dcm_tb.v
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/clkmgr_dcm_tb.v
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/sdf_cmd_file b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/sdf_cmd_file
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/sdf_cmd_file
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/sdf_cmd_file
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simcmds.tcl b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simcmds.tcl
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simcmds.tcl
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simcmds.tcl
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_isim.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_isim.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_isim.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_isim.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.bat b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.bat
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.bat
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.bat
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.do b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.do
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.do
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.do
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_ncsim.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_ncsim.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_ncsim.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_ncsim.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_vcs.sh b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_vcs.sh
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_vcs.sh
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_vcs.sh
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/ucli_commands.key b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/ucli_commands.key
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/ucli_commands.key
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/ucli_commands.key
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/vcs_session.tcl b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/vcs_session.tcl
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/vcs_session.tcl
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/vcs_session.tcl
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/wave.do b/platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/wave.do
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm/simulation/timing/wave.do
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm/simulation/timing/wave.do
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm_flist.txt b/platform/novena/eim/rtl/ipcore/clkmgr_dcm_flist.txt
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm_flist.txt
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm_flist.txt
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm_xmdf.tcl b/platform/novena/eim/rtl/ipcore/clkmgr_dcm_xmdf.tcl
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/clkmgr_dcm_xmdf.tcl
rename to platform/novena/eim/rtl/ipcore/clkmgr_dcm_xmdf.tcl
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/coregen.cgp b/platform/novena/eim/rtl/ipcore/coregen.cgp
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/coregen.cgp
rename to platform/novena/eim/rtl/ipcore/coregen.cgp
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/create_clkmgr_dcm.tcl b/platform/novena/eim/rtl/ipcore/create_clkmgr_dcm.tcl
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/create_clkmgr_dcm.tcl
rename to platform/novena/eim/rtl/ipcore/create_clkmgr_dcm.tcl
diff --git a/eim/toolruns/xilinx/novena/rtl/ipcore/edit_clkmgr_dcm.tcl b/platform/novena/eim/rtl/ipcore/edit_clkmgr_dcm.tcl
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/ipcore/edit_clkmgr_dcm.tcl
rename to platform/novena/eim/rtl/ipcore/edit_clkmgr_dcm.tcl
diff --git a/eim/toolruns/xilinx/novena/rtl/novena_clkmgr.v b/platform/novena/eim/rtl/novena_clkmgr.v
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/novena_clkmgr.v
rename to platform/novena/eim/rtl/novena_clkmgr.v
diff --git a/eim/toolruns/xilinx/novena/rtl/novena_eim.v b/platform/novena/eim/rtl/novena_eim.v
similarity index 100%
rename from eim/toolruns/xilinx/novena/rtl/novena_eim.v
rename to platform/novena/eim/rtl/novena_eim.v
diff --git a/eim/toolruns/xilinx/novena/ucf/novena_eim.ucf b/platform/novena/eim/ucf/novena_eim.ucf
similarity index 100%
rename from eim/toolruns/xilinx/novena/ucf/novena_eim.ucf
rename to platform/novena/eim/ucf/novena_eim.ucf
diff --git a/eim/toolruns/xilinx/novena/build/.gitignore b/platform/novena/i2c/build/.gitignore
similarity index 100%
rename from eim/toolruns/xilinx/novena/build/.gitignore
rename to platform/novena/i2c/build/.gitignore
diff --git a/i2c/toolruns/xilinx/novena/build/Makefile b/platform/novena/i2c/build/Makefile
similarity index 100%
rename from i2c/toolruns/xilinx/novena/build/Makefile
rename to platform/novena/i2c/build/Makefile
diff --git a/eim/toolruns/xilinx/novena/build/xilinx.mk b/platform/novena/i2c/build/xilinx.mk
similarity index 100%
rename from eim/toolruns/xilinx/novena/build/xilinx.mk
rename to platform/novena/i2c/build/xilinx.mk
diff --git a/eim/toolruns/xilinx/novena/build/xilinx.opt b/platform/novena/i2c/build/xilinx.opt
similarity index 100%
rename from eim/toolruns/xilinx/novena/build/xilinx.opt
rename to platform/novena/i2c/build/xilinx.opt
diff --git a/platform/novena/i2c/iseconfig/.gitignore b/platform/novena/i2c/iseconfig/.gitignore
new file mode 100644
index 0000000..91e8e2b
--- /dev/null
+++ b/platform/novena/i2c/iseconfig/.gitignore
@@ -0,0 +1,48 @@
+iseconfig
+_ngo
+*.bgn
+*_bitgen.xwbt
+*.bld
+*.cmd_log
+*.drc
+*_envsettings.html
+*_guide.ncd
+*.lso
+*_map.map
+*_map.mrp
+*_map.ncd
+*_map.ngm
+*_map.xrpt
+*.ncd
+*.ngc
+*.ngd
+*_ngdbuild.xrpt
+*.ngr
+*.pad
+*_pad.csv
+*_pad.txt
+*.par
+*_par.xrpt
+*.pcf
+*.prj
+*.ptwx
+*.stx
+*_summary.html
+*_summary.xml
+*.syr
+*.twr
+*.twx
+*.unroutes
+*_usage.xml
+*.ut
+*.xpi
+*.xst
+*_xst.xrpt
+*.gise
+par_usage_statistics.html
+usage_statistics_webtalk.html
+webtalk.log
+webtalk_pn.xml
+xlnx_auto_0_xdb
+_xmsgs
+xst
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/_xmsgs/pn_parser.xmsgs b/platform/novena/i2c/iseconfig/_xmsgs/pn_parser.xmsgs
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/_xmsgs/pn_parser.xmsgs
rename to platform/novena/i2c/iseconfig/_xmsgs/pn_parser.xmsgs
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/_xmsgs/xst.xmsgs b/platform/novena/i2c/iseconfig/_xmsgs/xst.xmsgs
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/_xmsgs/xst.xmsgs
rename to platform/novena/i2c/iseconfig/_xmsgs/xst.xmsgs
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/iseconfig/novena_baseline_top.xreport b/platform/novena/i2c/iseconfig/iseconfig/novena_baseline_top.xreport
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/iseconfig/novena_baseline_top.xreport
rename to platform/novena/i2c/iseconfig/iseconfig/novena_baseline_top.xreport
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/iseconfig/novena_reorg_i2c.projectmgr b/platform/novena/i2c/iseconfig/iseconfig/novena_reorg_i2c.projectmgr
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/iseconfig/novena_reorg_i2c.projectmgr
rename to platform/novena/i2c/iseconfig/iseconfig/novena_reorg_i2c.projectmgr
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top.cmd_log b/platform/novena/i2c/iseconfig/novena_baseline_top.cmd_log
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top.cmd_log
rename to platform/novena/i2c/iseconfig/novena_baseline_top.cmd_log
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top.lso b/platform/novena/i2c/iseconfig/novena_baseline_top.lso
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top.lso
rename to platform/novena/i2c/iseconfig/novena_baseline_top.lso
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top.prj b/platform/novena/i2c/iseconfig/novena_baseline_top.prj
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top.prj
rename to platform/novena/i2c/iseconfig/novena_baseline_top.prj
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top.syr b/platform/novena/i2c/iseconfig/novena_baseline_top.syr
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top.syr
rename to platform/novena/i2c/iseconfig/novena_baseline_top.syr
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top.xst b/platform/novena/i2c/iseconfig/novena_baseline_top.xst
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top.xst
rename to platform/novena/i2c/iseconfig/novena_baseline_top.xst
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top_summary.html b/platform/novena/i2c/iseconfig/novena_baseline_top_summary.html
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/novena_baseline_top_summary.html
rename to platform/novena/i2c/iseconfig/novena_baseline_top_summary.html
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/novena_reorg_i2c.gise b/platform/novena/i2c/iseconfig/novena_reorg_i2c.gise
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/novena_reorg_i2c.gise
rename to platform/novena/i2c/iseconfig/novena_reorg_i2c.gise
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/novena_reorg_i2c.xise b/platform/novena/i2c/iseconfig/novena_reorg_i2c.xise
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/novena_reorg_i2c.xise
rename to platform/novena/i2c/iseconfig/novena_reorg_i2c.xise
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/webtalk_pn.xml b/platform/novena/i2c/iseconfig/webtalk_pn.xml
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/webtalk_pn.xml
rename to platform/novena/i2c/iseconfig/webtalk_pn.xml
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/xst/work/work.sdbl b/platform/novena/i2c/iseconfig/xst/work/work.sdbl
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/xst/work/work.sdbl
rename to platform/novena/i2c/iseconfig/xst/work/work.sdbl
diff --git a/i2c/toolruns/xilinx/novena/iseconfig/xst/work/work.sdbx b/platform/novena/i2c/iseconfig/xst/work/work.sdbx
similarity index 100%
rename from i2c/toolruns/xilinx/novena/iseconfig/xst/work/work.sdbx
rename to platform/novena/i2c/iseconfig/xst/work/work.sdbx
diff --git a/i2c/toolruns/xilinx/novena/rtl/novena_i2c.v b/platform/novena/i2c/rtl/novena_i2c.v
similarity index 100%
rename from i2c/toolruns/xilinx/novena/rtl/novena_i2c.v
rename to platform/novena/i2c/rtl/novena_i2c.v
diff --git a/i2c/toolruns/xilinx/novena/ucf/novena_i2c.ucf b/platform/novena/i2c/ucf/novena_i2c.ucf
similarity index 100%
rename from i2c/toolruns/xilinx/novena/ucf/novena_i2c.ucf
rename to platform/novena/i2c/ucf/novena_i2c.ucf
diff --git a/platform/terasic_c5g/.gitignore b/platform/terasic_c5g/.gitignore
new file mode 100644
index 0000000..8b46186
--- /dev/null
+++ b/platform/terasic_c5g/.gitignore
@@ -0,0 +1,5 @@
+c5_pin_model_dump.txt
+db
+incremental_db
+output_files
+*.qws
diff --git a/uart/toolruns/quartus/terasic_c5g/c5_pin_model_dump.txt b/platform/terasic_c5g/c5_pin_model_dump.txt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/c5_pin_model_dump.txt
rename to platform/terasic_c5g/c5_pin_model_dump.txt
diff --git a/uart/toolruns/quartus/terasic_c5g/db/.cmp.kpt b/platform/terasic_c5g/db/.cmp.kpt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/.cmp.kpt
rename to platform/terasic_c5g/db/.cmp.kpt
diff --git a/uart/toolruns/quartus/terasic_c5g/db/coretest_hashes.quiproj.13348.rdr.flock b/platform/terasic_c5g/db/coretest_hashes.quiproj.13348.rdr.flock
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/coretest_hashes.quiproj.13348.rdr.flock
rename to platform/terasic_c5g/db/coretest_hashes.quiproj.13348.rdr.flock
diff --git a/uart/toolruns/quartus/terasic_c5g/db/coretest_hashes.smp_dump.txt b/platform/terasic_c5g/db/coretest_hashes.smp_dump.txt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/coretest_hashes.smp_dump.txt
rename to platform/terasic_c5g/db/coretest_hashes.smp_dump.txt
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(0).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(0).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(0).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(0).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(0).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(0).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(0).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(0).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(1).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(1).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(1).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(1).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(1).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(1).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(1).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(1).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(10).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(10).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(10).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(10).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(10).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(10).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(10).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(10).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(11).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(11).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(11).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(11).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(11).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(11).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(11).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(11).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(12).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(12).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(12).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(12).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(12).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(12).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(12).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(12).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(13).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(13).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(13).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(13).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(13).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(13).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(13).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(13).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(14).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(14).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(14).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(14).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(14).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(14).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(14).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(14).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(15).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(15).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(15).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(15).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(15).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(15).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(15).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(15).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(16).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(16).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(16).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(16).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(16).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(16).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(16).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(16).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(17).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(17).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(17).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(17).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(17).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(17).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(17).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(17).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(18).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(18).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(18).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(18).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(18).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(18).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(18).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(18).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(19).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(19).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(19).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(19).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(19).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(19).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(19).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(19).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(2).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(2).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(2).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(2).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(2).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(2).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(2).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(2).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(3).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(3).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(3).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(3).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(3).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(3).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(3).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(3).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(4).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(4).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(4).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(4).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(4).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(4).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(4).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(4).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(5).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(5).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(5).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(5).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(5).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(5).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(5).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(5).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(6).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(6).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(6).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(6).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(6).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(6).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(6).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(6).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(7).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(7).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(7).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(7).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(7).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(7).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(7).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(7).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(8).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(8).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(8).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(8).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(8).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(8).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(8).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(8).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(9).cnf.cdb b/platform/terasic_c5g/db/terasic_top.(9).cnf.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(9).cnf.cdb
rename to platform/terasic_c5g/db/terasic_top.(9).cnf.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.(9).cnf.hdb b/platform/terasic_c5g/db/terasic_top.(9).cnf.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.(9).cnf.hdb
rename to platform/terasic_c5g/db/terasic_top.(9).cnf.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.asm.qmsg b/platform/terasic_c5g/db/terasic_top.asm.qmsg
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.asm.qmsg
rename to platform/terasic_c5g/db/terasic_top.asm.qmsg
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.asm.rdb b/platform/terasic_c5g/db/terasic_top.asm.rdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.asm.rdb
rename to platform/terasic_c5g/db/terasic_top.asm.rdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cbx.xml b/platform/terasic_c5g/db/terasic_top.cbx.xml
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cbx.xml
rename to platform/terasic_c5g/db/terasic_top.cbx.xml
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.bpm b/platform/terasic_c5g/db/terasic_top.cmp.bpm
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.bpm
rename to platform/terasic_c5g/db/terasic_top.cmp.bpm
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.cdb b/platform/terasic_c5g/db/terasic_top.cmp.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.cdb
rename to platform/terasic_c5g/db/terasic_top.cmp.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.hdb b/platform/terasic_c5g/db/terasic_top.cmp.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.hdb
rename to platform/terasic_c5g/db/terasic_top.cmp.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.idb b/platform/terasic_c5g/db/terasic_top.cmp.idb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.idb
rename to platform/terasic_c5g/db/terasic_top.cmp.idb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.logdb b/platform/terasic_c5g/db/terasic_top.cmp.logdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.logdb
rename to platform/terasic_c5g/db/terasic_top.cmp.logdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.rdb b/platform/terasic_c5g/db/terasic_top.cmp.rdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp.rdb
rename to platform/terasic_c5g/db/terasic_top.cmp.rdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp_merge.kpt b/platform/terasic_c5g/db/terasic_top.cmp_merge.kpt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cmp_merge.kpt
rename to platform/terasic_c5g/db/terasic_top.cmp_merge.kpt
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ff_0c_fast.hsd b/platform/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ff_0c_fast.hsd
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ff_0c_fast.hsd
rename to platform/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ff_0c_fast.hsd
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ff_85c_fast.hsd b/platform/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ff_85c_fast.hsd
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ff_85c_fast.hsd
rename to platform/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ff_85c_fast.hsd
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ii_0c_slow.hsd b/platform/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ii_0c_slow.hsd
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ii_0c_slow.hsd
rename to platform/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ii_0c_slow.hsd
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ii_85c_slow.hsd b/platform/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ii_85c_slow.hsd
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ii_85c_slow.hsd
rename to platform/terasic_c5g/db/terasic_top.cyclonev_io_sim_cache.ii_85c_slow.hsd
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.db_info b/platform/terasic_c5g/db/terasic_top.db_info
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.db_info
rename to platform/terasic_c5g/db/terasic_top.db_info
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.fit.qmsg b/platform/terasic_c5g/db/terasic_top.fit.qmsg
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.fit.qmsg
rename to platform/terasic_c5g/db/terasic_top.fit.qmsg
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.hier_info b/platform/terasic_c5g/db/terasic_top.hier_info
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.hier_info
rename to platform/terasic_c5g/db/terasic_top.hier_info
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.hif b/platform/terasic_c5g/db/terasic_top.hif
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.hif
rename to platform/terasic_c5g/db/terasic_top.hif
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.logic_util_heuristic.dat b/platform/terasic_c5g/db/terasic_top.logic_util_heuristic.dat
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.logic_util_heuristic.dat
rename to platform/terasic_c5g/db/terasic_top.logic_util_heuristic.dat
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.lpc.html b/platform/terasic_c5g/db/terasic_top.lpc.html
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.lpc.html
rename to platform/terasic_c5g/db/terasic_top.lpc.html
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.lpc.rdb b/platform/terasic_c5g/db/terasic_top.lpc.rdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.lpc.rdb
rename to platform/terasic_c5g/db/terasic_top.lpc.rdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.lpc.txt b/platform/terasic_c5g/db/terasic_top.lpc.txt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.lpc.txt
rename to platform/terasic_c5g/db/terasic_top.lpc.txt
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.ammdb b/platform/terasic_c5g/db/terasic_top.map.ammdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.ammdb
rename to platform/terasic_c5g/db/terasic_top.map.ammdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.bpm b/platform/terasic_c5g/db/terasic_top.map.bpm
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.bpm
rename to platform/terasic_c5g/db/terasic_top.map.bpm
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.cdb b/platform/terasic_c5g/db/terasic_top.map.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.cdb
rename to platform/terasic_c5g/db/terasic_top.map.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.hdb b/platform/terasic_c5g/db/terasic_top.map.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.hdb
rename to platform/terasic_c5g/db/terasic_top.map.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.kpt b/platform/terasic_c5g/db/terasic_top.map.kpt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.kpt
rename to platform/terasic_c5g/db/terasic_top.map.kpt
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.qmsg b/platform/terasic_c5g/db/terasic_top.map.qmsg
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.qmsg
rename to platform/terasic_c5g/db/terasic_top.map.qmsg
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.rdb b/platform/terasic_c5g/db/terasic_top.map.rdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.map.rdb
rename to platform/terasic_c5g/db/terasic_top.map.rdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.map_bb.cdb b/platform/terasic_c5g/db/terasic_top.map_bb.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.map_bb.cdb
rename to platform/terasic_c5g/db/terasic_top.map_bb.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.map_bb.hdb b/platform/terasic_c5g/db/terasic_top.map_bb.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.map_bb.hdb
rename to platform/terasic_c5g/db/terasic_top.map_bb.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.pre_map.hdb b/platform/terasic_c5g/db/terasic_top.pre_map.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.pre_map.hdb
rename to platform/terasic_c5g/db/terasic_top.pre_map.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.pti_db_list.ddb b/platform/terasic_c5g/db/terasic_top.pti_db_list.ddb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.pti_db_list.ddb
rename to platform/terasic_c5g/db/terasic_top.pti_db_list.ddb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.rom0_sha256_k_constants_e63d9e28.hdl.mif b/platform/terasic_c5g/db/terasic_top.rom0_sha256_k_constants_e63d9e28.hdl.mif
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.rom0_sha256_k_constants_e63d9e28.hdl.mif
rename to platform/terasic_c5g/db/terasic_top.rom0_sha256_k_constants_e63d9e28.hdl.mif
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.root_partition.map.reg_db.cdb b/platform/terasic_c5g/db/terasic_top.root_partition.map.reg_db.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.root_partition.map.reg_db.cdb
rename to platform/terasic_c5g/db/terasic_top.root_partition.map.reg_db.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.routing.rdb b/platform/terasic_c5g/db/terasic_top.routing.rdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.routing.rdb
rename to platform/terasic_c5g/db/terasic_top.routing.rdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.rtlv.hdb b/platform/terasic_c5g/db/terasic_top.rtlv.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.rtlv.hdb
rename to platform/terasic_c5g/db/terasic_top.rtlv.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.rtlv_sg.cdb b/platform/terasic_c5g/db/terasic_top.rtlv_sg.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.rtlv_sg.cdb
rename to platform/terasic_c5g/db/terasic_top.rtlv_sg.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.rtlv_sg_swap.cdb b/platform/terasic_c5g/db/terasic_top.rtlv_sg_swap.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.rtlv_sg_swap.cdb
rename to platform/terasic_c5g/db/terasic_top.rtlv_sg_swap.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.sld_design_entry.sci b/platform/terasic_c5g/db/terasic_top.sld_design_entry.sci
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.sld_design_entry.sci
rename to platform/terasic_c5g/db/terasic_top.sld_design_entry.sci
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.sld_design_entry_dsc.sci b/platform/terasic_c5g/db/terasic_top.sld_design_entry_dsc.sci
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.sld_design_entry_dsc.sci
rename to platform/terasic_c5g/db/terasic_top.sld_design_entry_dsc.sci
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.smart_action.txt b/platform/terasic_c5g/db/terasic_top.smart_action.txt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.smart_action.txt
rename to platform/terasic_c5g/db/terasic_top.smart_action.txt
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.sta.qmsg b/platform/terasic_c5g/db/terasic_top.sta.qmsg
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.sta.qmsg
rename to platform/terasic_c5g/db/terasic_top.sta.qmsg
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.sta.rdb b/platform/terasic_c5g/db/terasic_top.sta.rdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.sta.rdb
rename to platform/terasic_c5g/db/terasic_top.sta.rdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.sta_cmp.7_H6_slow_1100mv_85c.tdb b/platform/terasic_c5g/db/terasic_top.sta_cmp.7_H6_slow_1100mv_85c.tdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.sta_cmp.7_H6_slow_1100mv_85c.tdb
rename to platform/terasic_c5g/db/terasic_top.sta_cmp.7_H6_slow_1100mv_85c.tdb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.tis_db_list.ddb b/platform/terasic_c5g/db/terasic_top.tis_db_list.ddb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.tis_db_list.ddb
rename to platform/terasic_c5g/db/terasic_top.tis_db_list.ddb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.fast_1100mv_0c.ddb b/platform/terasic_c5g/db/terasic_top.tiscmp.fast_1100mv_0c.ddb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.fast_1100mv_0c.ddb
rename to platform/terasic_c5g/db/terasic_top.tiscmp.fast_1100mv_0c.ddb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.fast_1100mv_85c.ddb b/platform/terasic_c5g/db/terasic_top.tiscmp.fast_1100mv_85c.ddb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.fast_1100mv_85c.ddb
rename to platform/terasic_c5g/db/terasic_top.tiscmp.fast_1100mv_85c.ddb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.fastest_slow_1100mv_0c.ddb b/platform/terasic_c5g/db/terasic_top.tiscmp.fastest_slow_1100mv_0c.ddb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.fastest_slow_1100mv_0c.ddb
rename to platform/terasic_c5g/db/terasic_top.tiscmp.fastest_slow_1100mv_0c.ddb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.fastest_slow_1100mv_85c.ddb b/platform/terasic_c5g/db/terasic_top.tiscmp.fastest_slow_1100mv_85c.ddb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.fastest_slow_1100mv_85c.ddb
rename to platform/terasic_c5g/db/terasic_top.tiscmp.fastest_slow_1100mv_85c.ddb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.slow_1100mv_0c.ddb b/platform/terasic_c5g/db/terasic_top.tiscmp.slow_1100mv_0c.ddb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.slow_1100mv_0c.ddb
rename to platform/terasic_c5g/db/terasic_top.tiscmp.slow_1100mv_0c.ddb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.slow_1100mv_85c.ddb b/platform/terasic_c5g/db/terasic_top.tiscmp.slow_1100mv_85c.ddb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.tiscmp.slow_1100mv_85c.ddb
rename to platform/terasic_c5g/db/terasic_top.tiscmp.slow_1100mv_85c.ddb
diff --git a/uart/toolruns/quartus/terasic_c5g/db/terasic_top.vpr.ammdb b/platform/terasic_c5g/db/terasic_top.vpr.ammdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/db/terasic_top.vpr.ammdb
rename to platform/terasic_c5g/db/terasic_top.vpr.ammdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/README b/platform/terasic_c5g/incremental_db/README
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/README
rename to platform/terasic_c5g/incremental_db/README
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.db_info b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.db_info
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.db_info
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.db_info
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.ammdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.ammdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.ammdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.ammdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.cdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.cdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.dfp b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.dfp
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.dfp
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.dfp
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.cdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.cdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.hdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.hdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.sig b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.sig
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.sig
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hbdb.sig
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.logdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.logdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.logdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.logdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.rcfdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.rcfdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.rcfdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.cmp.rcfdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.cdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.cdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.dpi b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.dpi
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.dpi
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.dpi
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.cdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.cdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.hb_info b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.hb_info
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.hb_info
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.hb_info
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.hdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.hdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.sig b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.sig
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.sig
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hbdb.sig
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.kpt b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.kpt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.kpt
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.root_partition.map.kpt
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.rrp.hdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.rrp.hdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.rrp.hdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.rrp.hdb
diff --git a/uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.rrs.cdb b/platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.rrs.cdb
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/incremental_db/compiled_partitions/terasic_top.rrs.cdb
rename to platform/terasic_c5g/incremental_db/compiled_partitions/terasic_top.rrs.cdb
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.asm.rpt b/platform/terasic_c5g/output_files/terasic_top.asm.rpt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.asm.rpt
rename to platform/terasic_c5g/output_files/terasic_top.asm.rpt
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.done b/platform/terasic_c5g/output_files/terasic_top.done
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.done
rename to platform/terasic_c5g/output_files/terasic_top.done
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.fit.rpt b/platform/terasic_c5g/output_files/terasic_top.fit.rpt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.fit.rpt
rename to platform/terasic_c5g/output_files/terasic_top.fit.rpt
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.fit.smsg b/platform/terasic_c5g/output_files/terasic_top.fit.smsg
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.fit.smsg
rename to platform/terasic_c5g/output_files/terasic_top.fit.smsg
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.fit.summary b/platform/terasic_c5g/output_files/terasic_top.fit.summary
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.fit.summary
rename to platform/terasic_c5g/output_files/terasic_top.fit.summary
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.flow.rpt b/platform/terasic_c5g/output_files/terasic_top.flow.rpt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.flow.rpt
rename to platform/terasic_c5g/output_files/terasic_top.flow.rpt
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.jdi b/platform/terasic_c5g/output_files/terasic_top.jdi
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.jdi
rename to platform/terasic_c5g/output_files/terasic_top.jdi
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.map.rpt b/platform/terasic_c5g/output_files/terasic_top.map.rpt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.map.rpt
rename to platform/terasic_c5g/output_files/terasic_top.map.rpt
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.map.smsg b/platform/terasic_c5g/output_files/terasic_top.map.smsg
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.map.smsg
rename to platform/terasic_c5g/output_files/terasic_top.map.smsg
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.map.summary b/platform/terasic_c5g/output_files/terasic_top.map.summary
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.map.summary
rename to platform/terasic_c5g/output_files/terasic_top.map.summary
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.pin b/platform/terasic_c5g/output_files/terasic_top.pin
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.pin
rename to platform/terasic_c5g/output_files/terasic_top.pin
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.sof b/platform/terasic_c5g/output_files/terasic_top.sof
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.sof
rename to platform/terasic_c5g/output_files/terasic_top.sof
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.sta.rpt b/platform/terasic_c5g/output_files/terasic_top.sta.rpt
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.sta.rpt
rename to platform/terasic_c5g/output_files/terasic_top.sta.rpt
diff --git a/uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.sta.summary b/platform/terasic_c5g/output_files/terasic_top.sta.summary
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/output_files/terasic_top.sta.summary
rename to platform/terasic_c5g/output_files/terasic_top.sta.summary
diff --git a/uart/toolruns/quartus/terasic_c5g/coretest_hashes.qpf b/platform/terasic_c5g/terasic_top.qpf
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/coretest_hashes.qpf
rename to platform/terasic_c5g/terasic_top.qpf
diff --git a/uart/toolruns/quartus/terasic_c5g/terasic_top.qsf b/platform/terasic_c5g/terasic_top.qsf
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/terasic_top.qsf
rename to platform/terasic_c5g/terasic_top.qsf
diff --git a/platform/terasic_c5g/terasic_top.sdc b/platform/terasic_c5g/terasic_top.sdc
new file mode 100644
index 0000000..93e1282
--- /dev/null
+++ b/platform/terasic_c5g/terasic_top.sdc
@@ -0,0 +1,40 @@
+#************************************************************
+# THIS IS A WIZARD-GENERATED FILE.
+#
+# Version 13.1.2 Build 173 01/15/2014 SJ Web Edition
+#
+#************************************************************
+
+# Copyright (C) 1991-2014 Altera Corporation
+# Your use of Altera Corporation's design tools, logic functions
+# and other software and tools, and its AMPP partner logic
+# functions, and any output files from any of the foregoing
+# (including device programming or simulation files), and any
+# associated documentation or information are expressly subject
+# to the terms and conditions of the Altera Program License
+# Subscription Agreement, Altera MegaCore Function License
+# Agreement, or other applicable license agreement, including,
+# without limitation, that your use is for the sole purpose of
+# programming logic devices manufactured by Altera and sold by
+# Altera or its authorized distributors. Please refer to the
+# applicable agreement for further details.
+
+
+
+# Clock constraints
+
+create_clock -name "clk" -period 20.000ns [get_ports {clk}]
+
+
+# Automatically constrain PLL and other generated clocks
+derive_pll_clocks -create_base_clocks
+
+# Automatically calculate clock uncertainty to jitter and other effects.
+derive_clock_uncertainty
+
+# tsu/th constraints
+
+# tco constraints
+
+# tpd constraints
+
diff --git a/uart/toolruns/quartus/terasic_c5g/terasic_top.v b/platform/terasic_c5g/terasic_top.v
similarity index 100%
rename from uart/toolruns/quartus/terasic_c5g/terasic_top.v
rename to platform/terasic_c5g/terasic_top.v
diff --git a/rng/rosc_entropy/LICENSE.txt b/rng/rosc_entropy/LICENSE.txt
new file mode 100644
index 0000000..b70e7ad
--- /dev/null
+++ b/rng/rosc_entropy/LICENSE.txt
@@ -0,0 +1,27 @@
+Copyright (c) 2014, NORDUnet A/S All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+- Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+- Neither the name of the NORDUnet nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/rng/rosc_entropy/README.md b/rng/rosc_entropy/README.md
new file mode 100644
index 0000000..8118da6
--- /dev/null
+++ b/rng/rosc_entropy/README.md
@@ -0,0 +1,4 @@
+rosc_entropy
+============
+
+Entropy source based on jitter between multiple, digital ring oscillators.
diff --git a/rng/rosc_entropy/src/rtl/rosc.v b/rng/rosc_entropy/src/rtl/rosc.v
new file mode 100644
index 0000000..522cac6
--- /dev/null
+++ b/rng/rosc_entropy/src/rtl/rosc.v
@@ -0,0 +1,107 @@
+//======================================================================
+//
+// rosc.v
+// ------
+// Digital ring oscillator used as entropy source. Based on the
+// idea of using carry chain in adders as inverter by Bernd Paysan.
+//
+//
+//
+// Author: Bernd Paysan, Joachim Strombergson
+// Copyright (c) 2014, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module rosc #(parameter WIDTH = 2)
+ (
+ input wire clk,
+ input wire reset_n,
+
+ input wire we,
+
+ input wire [(WIDTH - 1) : 0] opa,
+ input wire [(WIDTH - 1) : 0] opb,
+
+ output wire dout
+ );
+
+ //----------------------------------------------------------------
+ // Registers.
+ //----------------------------------------------------------------
+ reg dout_reg;
+ reg dout_new;
+
+
+ //----------------------------------------------------------------
+ // Concurrent assignment.
+ //----------------------------------------------------------------
+ assign dout = dout_reg;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ dout_reg <= 1'b0;
+ end
+ else
+ begin
+ if (we)
+ begin
+ dout_reg <= dout_new;
+ end
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // adder_osc
+ //
+ // Adder logic that generates the oscillator.
+ //
+ // NOTE: This logic contains a combinational loop and does
+ // not play well with an event driven simulator.
+ //----------------------------------------------------------------
+ always @*
+ begin: adder_osc
+ reg [WIDTH : 0] sum;
+ reg cin;
+
+ cin = ~sum[WIDTH];
+ sum = opa + opb + cin;
+ dout_new = sum[WIDTH];
+ end
+endmodule // rosc
+
+//======================================================================
+// EOF rosc.v
+//======================================================================
diff --git a/rng/rosc_entropy/src/rtl/rosc_entropy.v b/rng/rosc_entropy/src/rtl/rosc_entropy.v
new file mode 100644
index 0000000..0a7e60b
--- /dev/null
+++ b/rng/rosc_entropy/src/rtl/rosc_entropy.v
@@ -0,0 +1,311 @@
+//======================================================================
+//
+// rosc_entropy.v
+// --------------
+// Top level wrapper for the ring oscillator entropy core.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module rosc_entropy(
+ input wire clk,
+ input wire reset_n,
+
+ input wire cs,
+ input wire we,
+ input wire [7 : 0] address,
+ input wire [31 : 0] write_data,
+ output wire [31 : 0] read_data,
+ output wire error,
+
+ input wire discard,
+ input wire test_mode,
+ output wire security_error,
+
+ output wire entropy_enabled,
+ output wire [31 : 0] entropy_data,
+ output wire entropy_valid,
+ input wire entropy_ack,
+
+ output wire [7 : 0] debug,
+ input wire debug_update
+ );
+
+
+ //----------------------------------------------------------------
+ // Parameters.
+ //----------------------------------------------------------------
+ parameter ADDR_NAME0 = 8'h00;
+ parameter ADDR_NAME1 = 8'h01;
+ parameter ADDR_VERSION = 8'h02;
+
+ parameter ADDR_CTRL = 8'h10;
+ parameter CTRL_ENABLE_BIT = 0;
+
+ parameter ADDR_STATUS = 8'h11;
+ parameter STATUS_ENTROPY_VALID_BIT = 0;
+
+ parameter ADDR_OP_A = 8'h18;
+ parameter ADDR_OP_B = 8'h19;
+
+ parameter ADDR_ENTROPY = 8'h20;
+ parameter ADDR_RAW = 8'h21;
+ parameter ADDR_ROSC_OUTPUTS = 8'h22;
+
+ parameter DEFAULT_OP_A = 32'haaaaaaaa;
+ parameter DEFAULT_OP_B = ~DEFAULT_OP_A;
+
+ parameter CORE_NAME0 = 32'h726f7363; // "rosc"
+ parameter CORE_NAME1 = 32'h20656e74; // " ent"
+ parameter CORE_VERSION = 32'h302e3130; // "0.10"
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg enable_reg;
+ reg enable_new;
+ reg enable_we;
+
+ reg [31 : 0] op_a_reg;
+ reg [31 : 0] op_a_new;
+ reg op_a_we;
+
+ reg [31 : 0] op_b_reg;
+ reg [31 : 0] op_b_new;
+ reg op_b_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ wire [31 : 0] raw_entropy;
+ wire [31 : 0] rosc_outputs;
+
+ wire [31 : 0] internal_entropy_data;
+ wire internal_entropy_valid;
+ wire internal_entropy_ack;
+ reg api_entropy_ack;
+
+
+ reg [31 : 0] tmp_read_data;
+ reg tmp_error;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign read_data = tmp_read_data;
+ assign error = tmp_error;
+ assign security_error = 0;
+
+ assign entropy_enabled = enable_reg;
+ assign entropy_data = internal_entropy_data;
+ assign entropy_valid = internal_entropy_valid;
+ assign internal_entropy_ack = api_entropy_ack | entropy_ack;
+
+
+ //----------------------------------------------------------------
+ // module instantiations.
+ //----------------------------------------------------------------
+ rosc_entropy_core core(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .en(enable_reg),
+
+ .opa(op_a_reg),
+ .opb(op_b_reg),
+
+ .raw_entropy(raw_entropy),
+ .rosc_outputs(rosc_outputs),
+
+ .entropy_data(internal_entropy_data),
+ .entropy_valid(internal_entropy_valid),
+ .entropy_ack(internal_entropy_ack),
+
+ .debug(debug),
+ .debug_update(debug_update)
+ );
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ enable_reg <= 1;
+ op_a_reg <= DEFAULT_OP_A;
+ op_b_reg <= DEFAULT_OP_B;
+ end
+ else
+ begin
+ if (enable_we)
+ begin
+ enable_reg <= enable_new;
+ end
+
+ if (op_a_we)
+ begin
+ op_a_reg <= op_a_new;
+ end
+
+ if (op_b_we)
+ begin
+ op_b_reg <= op_b_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // api_logic
+ //
+ // Implementation of the api logic. If cs is enabled will either
+ // try to write to or read from the internal registers.
+ //----------------------------------------------------------------
+ always @*
+ begin : api_logic
+ enable_new = 0;
+ enable_we = 0;
+ op_a_new = 0;
+ op_a_we = 0;
+ op_b_new = 0;
+ op_b_we = 0;
+ api_entropy_ack = 0;
+ tmp_read_data = 32'h00000000;
+ tmp_error = 0;
+
+ if (cs)
+ begin
+ if (we)
+ begin
+ case (address)
+ // Write operations.
+ ADDR_CTRL:
+ begin
+ enable_new = write_data[CTRL_ENABLE_BIT];
+ enable_we = 1;
+ end
+
+ ADDR_OP_A:
+ begin
+ op_a_new = write_data;
+ op_a_we = 1;
+ end
+
+ ADDR_OP_B:
+ begin
+ op_b_new = write_data;
+ op_b_we = 1;
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end
+ else
+ begin
+ case (address)
+ ADDR_NAME0:
+ begin
+ tmp_read_data = CORE_NAME0;
+ end
+
+ ADDR_NAME1:
+ begin
+ tmp_read_data = CORE_NAME1;
+ end
+
+ ADDR_VERSION:
+ begin
+ tmp_read_data = CORE_VERSION;
+ end
+
+ ADDR_CTRL:
+ begin
+ tmp_read_data[CTRL_ENABLE_BIT] = enable_reg;
+ end
+
+ ADDR_STATUS:
+ begin
+ tmp_read_data[STATUS_ENTROPY_VALID_BIT] = internal_entropy_valid;
+ end
+
+ ADDR_OP_A:
+ begin
+ tmp_read_data = op_a_reg;
+ end
+
+ ADDR_OP_B:
+ begin
+ tmp_read_data = op_b_reg;
+ end
+
+ ADDR_ENTROPY:
+ begin
+ tmp_read_data = entropy_data;
+ api_entropy_ack = 1;
+ end
+
+ ADDR_RAW:
+ begin
+ tmp_read_data = raw_entropy;
+ end
+
+ ADDR_ROSC_OUTPUTS:
+ begin
+ tmp_read_data = rosc_outputs;
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end
+ end
+ end
+
+endmodule // rosc_entropy_core
+
+//======================================================================
+// EOF rosc_entropy_core.v
+//======================================================================
diff --git a/rng/rosc_entropy/src/rtl/rosc_entropy_core.v b/rng/rosc_entropy/src/rtl/rosc_entropy_core.v
new file mode 100644
index 0000000..eb9dd6e
--- /dev/null
+++ b/rng/rosc_entropy/src/rtl/rosc_entropy_core.v
@@ -0,0 +1,301 @@
+//======================================================================
+//
+// rosc_entropy_core.v
+// -------------------
+// Digitial ring oscillator based entropy generation core.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module rosc_entropy_core(
+ input wire clk,
+ input wire reset_n,
+
+ input wire en,
+
+ input wire [31 : 0] opa,
+ input wire [31 : 0] opb,
+
+ output wire [31 : 0] raw_entropy,
+ output wire [31 : 0] rosc_outputs,
+
+ output wire [31 : 0] entropy_data,
+ output wire entropy_valid,
+ input wire entropy_ack,
+
+ output wire [7 : 0] debug,
+ input wire debug_update
+ );
+
+
+ //----------------------------------------------------------------
+ // Parameters.
+ //----------------------------------------------------------------
+ parameter DEBUG_DELAY = 32'h002c4b40;
+ parameter NUM_SHIFT_BITS = 8'h20;
+ parameter SAMPLE_CLK_CYCLES = 8'hff;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] ent_shift_reg;
+ reg [31 : 0] ent_shift_new;
+ reg ent_shift_we;
+
+ reg [31 : 0] entropy_reg;
+ reg entropy_we;
+
+ reg entropy_valid_reg;
+ reg entropy_valid_new;
+ reg entropy_valid_we;
+
+ reg bit_we_reg;
+ reg bit_we_new;
+
+ reg [7 : 0] bit_ctr_reg;
+ reg [7 : 0] bit_ctr_new;
+ reg bit_ctr_inc;
+ reg bit_ctr_we;
+
+ reg [7 : 0] sample_ctr_reg;
+ reg [7 : 0] sample_ctr_new;
+
+ reg [31 : 0] debug_delay_ctr_reg;
+ reg [31 : 0] debug_delay_ctr_new;
+ reg debug_delay_ctr_we;
+
+ reg [7 : 0] debug_reg;
+ reg debug_we;
+
+ reg debug_update_reg;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg rosc_we;
+
+ // Ugly in-line Xilinx attribute to preserve the registers.
+ (* equivalent_register_removal = "no" *)
+ wire [31 : 0] rosc_dout;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign rosc_outputs = rosc_dout;
+ assign raw_entropy = ent_shift_reg;
+ assign entropy_data = entropy_reg;
+ assign entropy_valid = entropy_valid_reg;
+ assign debug = debug_reg;
+
+
+ //----------------------------------------------------------------
+ // module instantiations.
+ //
+ // 32 1-bit wide oscillators. We want them to run as fast as
+ // possible to maximize differences over time.
+ //----------------------------------------------------------------
+ genvar i;
+ generate
+ for(i = 0 ; i < 32 ; i = i + 1)
+ begin: oscillators
+ rosc #(.WIDTH(1)) rosc_array(.clk(clk),
+ .we(rosc_we),
+ .reset_n(reset_n),
+ .opa(opa),
+ .opb(opb),
+ .dout(rosc_dout[i])
+ );
+ end
+ endgenerate
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ ent_shift_reg <= 32'h00000000;
+ entropy_reg <= 32'h00000000;
+ entropy_valid_reg <= 0;
+ bit_ctr_reg <= 8'h00;
+ sample_ctr_reg <= 8'h00;
+ debug_delay_ctr_reg <= 32'h00000000;
+ debug_reg <= 8'h00;
+ debug_update_reg <= 0;
+ end
+ else
+ begin
+ sample_ctr_reg <= sample_ctr_new;
+ debug_update_reg <= debug_update;
+
+ if (ent_shift_we)
+ begin
+ ent_shift_reg <= ent_shift_new;
+ end
+
+ if (bit_ctr_we)
+ begin
+ bit_ctr_reg <= bit_ctr_new;
+ end
+
+ if (entropy_we)
+ begin
+ entropy_reg <= ent_shift_reg;
+ end
+
+ if (entropy_valid_we)
+ begin
+ entropy_valid_reg <= entropy_valid_new;
+ end
+
+ if (debug_delay_ctr_we)
+ begin
+ debug_delay_ctr_reg <= debug_delay_ctr_new;
+ end
+
+ if (debug_we)
+ begin
+ debug_reg <= ent_shift_reg[7 : 0];
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // debug_out
+ //
+ // Logic that updates the debug port.
+ //----------------------------------------------------------------
+ always @*
+ begin : debug_out
+ debug_delay_ctr_new = 32'h00000000;
+ debug_delay_ctr_we = 0;
+ debug_we = 0;
+
+ if (debug_update_reg)
+ begin
+ debug_delay_ctr_new = debug_delay_ctr_reg + 1'b1;
+ debug_delay_ctr_we = 1;
+ end
+
+ if (debug_delay_ctr_reg == DEBUG_DELAY)
+ begin
+ debug_delay_ctr_new = 32'h00000000;
+ debug_delay_ctr_we = 1;
+ debug_we = 1;
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // entropy_out
+ //
+ // Logic that implements the random output control. If we have
+ // added more than NUM_SHIFT_BITS we raise the entropy_valid flag.
+ // When we detect and ACK, the valid flag is dropped.
+ //----------------------------------------------------------------
+ always @*
+ begin : entropy_out
+ bit_ctr_new = 8'h00;
+ bit_ctr_we = 0;
+ entropy_we = 0;
+ entropy_valid_new = 0;
+ entropy_valid_we = 0;
+
+ if (bit_ctr_inc)
+ begin
+
+ if (bit_ctr_reg < NUM_SHIFT_BITS)
+ begin
+ bit_ctr_new = bit_ctr_reg + 1'b1;
+ bit_ctr_we = 1;
+ end
+ else
+ begin
+ entropy_we = 1;
+ entropy_valid_new = 1;
+ entropy_valid_we = 1;
+ end
+ end
+
+ if (entropy_ack)
+ begin
+ bit_ctr_new = 8'h00;
+ bit_ctr_we = 1;
+ entropy_valid_new = 0;
+ entropy_valid_we = 1;
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // entropy_gen
+ //
+ // Logic that implements the actual entropy bit value generator
+ // by XOR mixing the oscillator outputs. These outputs are
+ // sampled once every SAMPLE_CLK_CYCLES.
+ //----------------------------------------------------------------
+ always @*
+ begin : entropy_gen
+ reg ent_bit;
+
+ bit_ctr_inc = 0;
+ rosc_we = 0;
+ ent_shift_we = 0;
+
+ ent_bit = ^rosc_dout;
+ ent_shift_new = {ent_shift_reg[30 : 0], ent_bit};
+
+ sample_ctr_new = sample_ctr_reg + 1'b1;
+
+ if (en && (sample_ctr_reg == SAMPLE_CLK_CYCLES))
+ begin
+ sample_ctr_new = 8'h00;
+ bit_ctr_inc = 1;
+ rosc_we = 1;
+ ent_shift_we = 1;
+ end
+ end
+endmodule // rosc_entropy_core
+
+//======================================================================
+// EOF rosc_entropy_core.v
+//======================================================================
diff --git a/rng/trng/LICENSE.txt b/rng/trng/LICENSE.txt
new file mode 100644
index 0000000..b70e7ad
--- /dev/null
+++ b/rng/trng/LICENSE.txt
@@ -0,0 +1,27 @@
+Copyright (c) 2014, NORDUnet A/S All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+- Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+- Neither the name of the NORDUnet nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/rng/trng/README.md b/rng/trng/README.md
new file mode 100644
index 0000000..117a972
--- /dev/null
+++ b/rng/trng/README.md
@@ -0,0 +1,175 @@
+trng
+====
+
+True Random Number Generator core implemented in Verilog.
+
+## Introduction ##
+This repo contains the design of a True Random Number Generator (TRNG)
+for the [Cryptech OpenHSM](http://cryptech.is/) project.
+
+
+## Design inspiration, ideas and principles ##
+
+The TRNG **MUST** be a really good one. Furthermore it must be trustable
+by its users. That means it should not do wild and crazy stuff. And
+users should be able to verify that the TRNG works as expected.
+
+* Follow best practice
+* Be conservative - No big untested ideas.
+* Support transparency - The parts should be testable.
+
+
+Some of our inspiration comes from:
+* The Fortuna RNG by Ferguson and Schneier as described in Cryptography
+Engineering.
+
+* /dev/random in OpenBSD
+
+
+## System description ##
+
+The TRNG consists of a chain with three main subsystems
+
+* Entropy generation
+* Entropy mixing
+* Random generation
+
+
+### Entropy generation ###
+
+The entropy generation subsystems consists of at least two separate entropy
+generators. Each generator collects entropy from an independent physical
+process. The entropy sources MUST be of different types. For example
+avalance noise from a reversed bias P/N junction as one source and RSSI
+LSB from a receiver.
+
+The reason for having multiple entropy sources is both to provide
+reduncancy as well as making it harder for an attacker to affect the
+entropy collection by forcing the attacker to try and affect different
+physical processes simultaneously.
+
+A given entropy generator is responsible for collecting the entropy
+(possibly including A/D conversion.). The entropy generator MUST
+implement some on-line testing of the physical entropy source based on
+the entropy collected. The tests shall be described in detail here but
+will at least include tests for:
+
+* No long run lengths in generated values.
+* Variance that exceeds a given threshhold.
+* Mean value that don't deviate from expected mean.
+* Frequency for all possible values are within expected variance.
+
+If the tests fails over a period of generated values the entropy source
+MUST raise an error flag. And MAY also block access to the entropy it
+otherwise provides.
+
+There shall also be possible to read out the raw entropy collected from
+a given entropy generator. This MUST ONLY be possible in a specific
+debug mode when no random generation is allowed. Also the entropy
+provided in debug mode MUST NOT be used for later random number
+generation.
+
+The entropy generator SHALL perform whitening on the collected entropy
+before providing it as 32-bit values to the entropy accumulator.
+
+
+
+### Entropy mixing ###
+
+The entropy mixer subsystems reads 32-bit words from the entropy
+generators to build a block of bits to be mixed.
+
+When 1024 bits of mixed entropy has been collected the entropy is used
+as a message block which is fed into a hash function.
+
+The hash function used is SHA-512 (NIST FIPS 180-4).
+
+The digest is then extracted and provided to the random generation as as
+a seed.
+
+
+### Random generation ###
+
+The random generation consists of a cryptographically safe pseudo random
+number generator (CSPRNG). The CSPRNG used in the trng is the strea
+cipher ChaCHa.
+
+ChaCha is seeded with:
+- 512 bits block
+- 256 bits key
+- 64 bits IV
+- 64 bits counter
+
+In total the seed used is: 896 bits. This requires getting two seed
+blocks of 512 bits from the mixer.
+
+The number of rounds used in ChaCha is conservatively
+selected. We propose that the number of rounds shall be at least 24
+rounds. Possibly 32 rounds. Given the performance in HW for ChaCha and
+the size of the keystream block, the TRNG should be able to generate
+plentiful of random values even with 32 rounds.
+
+The random generator shall support the ability to test its functionality
+by seeding it with a user supplied value and then generate a number of
+values in a specific debug mode. The normal access to generated random
+values MUST NOT be allowed during the debug mode. The random generator
+MUST also set an error flag during debug mode. Finally, when exiting the
+debug mode, reseeding MUST be done.
+
+Finally the random generator provides random numbers as 32-bit
+values. the 512 bit keystream blocks from ChaCha are divided into 16
+32-bit words and provided in sequence.
+
+
+## Implementation details ##
+
+The core supports multpiple entropy sources as well as a CSPRNG. For
+each entropy source there are some estimators that checks that the
+sources are not broken.
+
+There are also an ability to extract raw entropy as well as inject test
+data into the CSPRNG to verify the functionality.
+
+The core will include one FPGA based entropy source but expects the
+other entropy source(s) to be connected on external ports. It is up to
+the user/system implementer to provide physical entropy souces. We will
+suggest and provide info on how to design at least one such source.
+
+For simulation there are simplistic fake entropy sources that can be
+found in the tb/fake_modules directory. This modules SHOULD NOT be used
+as real sources.
+
+For synthesis there are wrappers for the real entropy source cores to
+adapt their interfaces to what we need in the trng. These wrappers
+should not be included during simulation.
+
+
+
+## API ##
+
+Normal operation:
+* Extract 32-bit random words.
+
+
+Config parameters:
+* Number of blocks in warm-up.
+* Number of keystream blocks before reseeding.
+
+
+Debug access
+* Enable/disable entropy generator X
+* Check health of entropy generator X
+* Read raw entropy from entropy generator X as 32-bit word.
+* Write 256 bit seed value as 8 32-bit words
+* Read out one or more 512 bit keystream blocks as 32-bit words.
+
+
+
+## Status ##
+
+*** (2014-09-11) ***
+
+The first version of the CSPRNG is debugged and completed. This version
+supports automatic reseeding and an output fifo.
+
+
diff --git a/rng/trng/src/rtl/trng.v b/rng/trng/src/rtl/trng.v
new file mode 100644
index 0000000..7a63f50
--- /dev/null
+++ b/rng/trng/src/rtl/trng.v
@@ -0,0 +1,614 @@
+ //======================================================================
+//
+// trng.v
+// --------
+// Top level wrapper for the True Random Number Generator.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module trng(
+ // Clock and reset.
+ input wire clk,
+ input wire reset_n,
+
+ input wire avalanche_noise,
+
+ input wire cs,
+ input wire we,
+ input wire [11 : 0] address,
+ input wire [31 : 0] write_data,
+ output wire [31 : 0] read_data,
+ output wire error,
+
+ output wire [7 : 0] debug,
+ input wire debug_update,
+
+ output wire security_error
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter TRNG_PREFIX = 4'h0;
+ parameter ENTROPY1_PREFIX = 4'h5;
+ parameter ENTROPY2_PREFIX = 4'h6;
+ parameter MIXER_PREFIX = 4'ha;
+ parameter CSPRNG_PREFIX = 4'hb;
+
+ parameter DEBUG_ENTROPY0 = 3'h0;
+ parameter DEBUG_ENTROPY1 = 3'h1;
+ parameter DEBUG_ENTROPY2 = 3'h2;
+ parameter DEBUG_MIXER = 3'h3;
+ parameter DEBUG_CSPRNG = 3'h4;
+
+ parameter ADDR_NAME0 = 8'h00;
+ parameter ADDR_NAME1 = 8'h01;
+ parameter ADDR_VERSION = 8'h02;
+
+ parameter ADDR_TRNG_CTRL = 8'h10;
+ parameter TRNG_CTRL_DISCARD_BIT = 0;
+ parameter TRNG_CTRL_TEST_MODE_BIT = 1;
+
+ parameter ADDR_TRNG_STATUS = 8'h11;
+ parameter ADDR_DEBUG_CTRL = 8'h12;
+ parameter ADDR_DEBUG_DELAY = 8'h13;
+
+ parameter TRNG_NAME0 = 32'h74726e67; // "trng"
+ parameter TRNG_NAME1 = 32'h20202020; // " "
+ parameter TRNG_VERSION = 32'h302e3031; // "0.01"
+
+ // 20x/s @ 50 MHz.
+ parameter DEFAULT_DEBUG_DELAY = 32'h002625a0;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg discard_reg;
+ reg discard_new;
+
+ reg test_mode_reg;
+ reg test_mode_new;
+ reg test_mode_we;
+
+ reg [7 : 0] debug_out_reg;
+ reg debug_out_we;
+
+ reg [2 : 0] debug_mux_reg;
+ reg [2 : 0] debug_mux_new;
+ reg debug_mux_we;
+
+ reg [31 : 0] debug_delay_ctr_reg;
+ reg [31 : 0] debug_delay_ctr_new;
+ reg debug_delay_ctr_we;
+
+ reg [31 : 0] debug_delay_reg;
+ reg [31 : 0] debug_delay_new;
+ reg debug_delay_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg trng_api_cs;
+ reg trng_api_we;
+ reg [31 : 0] trng_api_read_data;
+ reg trng_api_error;
+
+ wire mixer_more_seed;
+ wire [511 : 0] mixer_seed_data;
+ wire mixer_seed_syn;
+ wire mixer_seed_ack;
+ reg mixer_api_cs;
+ reg mixer_api_we;
+ wire [31 : 0] mixer_api_read_data;
+ wire mixer_api_error;
+ wire mixer_security_error;
+ wire [7 : 0] mixer_debug;
+ reg mixer_debug_update;
+
+ wire csprng_more_seed;
+ wire csprng_seed_ack;
+ reg csprng_api_cs;
+ reg csprng_api_we;
+ wire [31 : 0] csprng_api_read_data;
+ wire csprng_api_error;
+ wire [7 : 0] csprng_debug;
+ reg csprng_debug_update;
+ wire csprng_security_error;
+
+ wire entropy0_entropy_enabled;
+ wire [31 : 0] entropy0_entropy_data;
+ wire entropy0_entropy_syn;
+ wire entropy0_entropy_ack;
+
+ reg entropy1_api_cs;
+ reg entropy1_api_we;
+ wire [31 : 0] entropy1_api_read_data;
+ wire entropy1_api_error;
+ wire entropy1_entropy_enabled;
+ wire [31 : 0] entropy1_entropy_data;
+ wire entropy1_entropy_syn;
+ wire entropy1_entropy_ack;
+ wire entropy1_test_mode;
+ wire [7 : 0] entropy1_debug;
+ reg entropy1_debug_update;
+ wire entropy1_security_error;
+
+ reg entropy2_api_cs;
+ reg entropy2_api_we;
+ wire [31 : 0] entropy2_api_read_data;
+ wire entropy2_api_error;
+ wire entropy2_entropy_enabled;
+ wire [31 : 0] entropy2_entropy_data;
+ wire entropy2_entropy_syn;
+ wire entropy2_entropy_ack;
+ wire entropy2_test_mode;
+ wire [7 : 0] entropy2_debug;
+ reg entropy2_debug_update;
+ wire entropy2_security_error;
+
+ reg [7 : 0] api_address;
+ reg [31 : 0] tmp_read_data;
+ reg tmp_error;
+ reg [7 : 0] tmp_debug;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign read_data = tmp_read_data;
+ assign error = tmp_error;
+ assign security_error = entropy1_security_error | entropy2_security_error;
+ assign debug = debug_out_reg;
+
+ // Patches to get our first version to work.
+ assign entropy0_entropy_enabled = 0;
+ assign entropy0_entropy_syn = 0;
+ assign entropy0_entropy_data = 32'h00000000;
+
+
+ //----------------------------------------------------------------
+ // core instantiations.
+ //----------------------------------------------------------------
+ trng_mixer mixer_inst(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .cs(mixer_api_cs),
+ .we(mixer_api_we),
+ .address(api_address),
+ .write_data(write_data),
+ .read_data(mixer_api_read_data),
+ .error(mixer_api_error),
+
+ .discard(discard_reg),
+ .test_mode(test_mode_reg),
+ .security_error(mixer_security_error),
+
+ .more_seed(csprng_more_seed),
+
+ .entropy0_enabled(entropy0_entropy_enabled),
+ .entropy0_syn(entropy0_entropy_syn),
+ .entropy0_data(entropy0_entropy_data),
+ .entropy0_ack(entropy0_entropy_ack),
+
+ .entropy1_enabled(entropy1_entropy_enabled),
+ .entropy1_syn(entropy1_entropy_syn),
+ .entropy1_data(entropy1_entropy_data),
+ .entropy1_ack(entropy1_entropy_ack),
+
+ .entropy2_enabled(entropy2_entropy_enabled),
+ .entropy2_syn(entropy2_entropy_syn),
+ .entropy2_data(entropy2_entropy_data),
+ .entropy2_ack(entropy2_entropy_ack),
+
+ .seed_data(mixer_seed_data),
+ .seed_syn(mixer_seed_syn),
+ .seed_ack(csprng_seed_ack),
+
+ .debug(mixer_debug),
+ .debug_update(mixer_debug_update)
+ );
+
+ trng_csprng csprng_inst(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .cs(csprng_api_cs),
+ .we(csprng_api_we),
+ .address(api_address),
+ .write_data(write_data),
+ .read_data(csprng_api_read_data),
+ .error(csprng_api_error),
+
+ .discard(discard_reg),
+ .test_mode(test_mode_reg),
+ .security_error(csprng_security_error),
+
+ .more_seed(csprng_more_seed),
+
+ .seed_data(mixer_seed_data),
+ .seed_syn(mixer_seed_syn),
+ .seed_ack(csprng_seed_ack),
+
+ .debug(csprng_debug),
+ .debug_update(csprng_debug_update)
+ );
+
+ avalanche_entropy entropy1(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .noise(avalanche_noise),
+
+ .cs(entropy1_api_cs),
+ .we(entropy1_api_we),
+ .address(api_address),
+ .write_data(write_data),
+ .read_data(entropy1_api_read_data),
+ .error(entropy1_api_error),
+
+ .discard(discard_reg),
+ .test_mode(test_mode_reg),
+ .security_error(entropy1_security_error),
+
+ .entropy_enabled(entropy1_entropy_enabled),
+ .entropy_data(entropy1_entropy_data),
+ .entropy_valid(entropy1_entropy_syn),
+ .entropy_ack(entropy1_entropy_ack),
+
+ .debug(entropy1_debug),
+ .debug_update(entropy1_debug_update)
+ );
+
+ rosc_entropy entropy2(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .cs(entropy2_api_cs),
+ .we(entropy2_api_we),
+ .address(api_address),
+ .write_data(write_data),
+ .read_data(entropy2_api_read_data),
+ .error(entropy2_api_error),
+
+ .discard(discard_reg),
+ .test_mode(test_mode_reg),
+ .security_error(entropy2_security_error),
+
+ .entropy_enabled(entropy2_entropy_enabled),
+ .entropy_data(entropy2_entropy_data),
+ .entropy_valid(entropy2_entropy_syn),
+ .entropy_ack(entropy2_entropy_ack),
+
+ .debug(entropy2_debug),
+ .debug_update(entropy2_debug_update)
+ );
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ discard_reg <= 0;
+ test_mode_reg <= 0;
+ debug_mux_reg <= DEBUG_CSPRNG;
+ debug_delay_reg <= DEFAULT_DEBUG_DELAY;
+ debug_delay_ctr_reg <= 32'h00000000;
+ debug_out_reg <= 8'h00;
+ end
+ else
+ begin
+ discard_reg <= discard_new;
+ debug_delay_ctr_reg <= debug_delay_ctr_new;
+
+ if (debug_out_we)
+ begin
+ debug_out_reg <= tmp_debug;
+ end
+
+ if (test_mode_we)
+ begin
+ test_mode_reg <= test_mode_new;
+ end
+
+ if (debug_mux_we)
+ begin
+ debug_mux_reg <= debug_mux_new;
+ end
+
+ if (debug_delay_we)
+ begin
+ debug_delay_reg <= debug_delay_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // debug_update_logic
+ //
+ // Debug update counter and update logic.
+ //----------------------------------------------------------------
+ always @*
+ begin : debug_update_logic
+ if (debug_delay_ctr_reg == debug_delay_reg)
+ begin
+ debug_out_we = 1;
+ debug_delay_ctr_new = 32'h00000000;
+ end
+ else
+ begin
+ debug_out_we = 0;
+ debug_delay_ctr_new = debug_delay_ctr_reg + 1'b1;
+ end
+ end // debug_update
+
+
+ //----------------------------------------------------------------
+ // debug_mux
+ //
+ // Select which of the sub modules that are connected to
+ // the debug port.
+ //----------------------------------------------------------------
+ always @*
+ begin : debug_mux
+ entropy1_debug_update = 0;
+ entropy2_debug_update = 0;
+ mixer_debug_update = 0;
+ csprng_debug_update = 0;
+
+ tmp_debug = 8'h00;
+
+ case(debug_mux_reg)
+ DEBUG_ENTROPY1:
+ begin
+ entropy1_debug_update = debug_update;
+ tmp_debug = entropy1_debug;
+ end
+
+ DEBUG_ENTROPY2:
+ begin
+ entropy2_debug_update = debug_update;
+ tmp_debug = entropy2_debug;
+ end
+
+ DEBUG_MIXER:
+ begin
+ mixer_debug_update = debug_update;
+ tmp_debug = mixer_debug;
+ end
+
+ DEBUG_CSPRNG:
+ begin
+ csprng_debug_update = debug_update;
+ tmp_debug = csprng_debug;
+ end
+
+ default:
+ begin
+
+ end
+ endcase // case (debug_mux_reg)
+ end // debug_mux
+
+
+ //----------------------------------------------------------------
+ // api_mux
+ //
+ // This is a simple decoder that looks at the top 4 bits of
+ // the given api address and selects which of the sub modules
+ // or the top level mux that gets to handle any API
+ // operations.
+ //----------------------------------------------------------------
+ always @*
+ begin : api_mux
+ trng_api_cs = 0;
+ trng_api_we = 0;
+
+ entropy1_api_cs = 0;
+ entropy1_api_we = 0;
+
+ entropy2_api_cs = 0;
+ entropy2_api_we = 0;
+
+ mixer_api_cs = 0;
+ mixer_api_we = 0;
+
+ csprng_api_cs = 0;
+ csprng_api_we = 0;
+
+ api_address = address[7 : 0];
+ tmp_read_data = 32'h00000000;
+ tmp_error = 0;
+
+ case (address[11 : 8])
+ TRNG_PREFIX:
+ begin
+ trng_api_cs = cs;
+ trng_api_we = we;
+ tmp_read_data = trng_api_read_data;
+ tmp_error = trng_api_error;
+ end
+
+ ENTROPY1_PREFIX:
+ begin
+ entropy1_api_cs = cs;
+ entropy1_api_we = we;
+ tmp_read_data = entropy1_api_read_data;
+ tmp_error = entropy1_api_error;
+ end
+
+ ENTROPY2_PREFIX:
+ begin
+ entropy2_api_cs = cs;
+ entropy2_api_we = we;
+ tmp_read_data = entropy2_api_read_data;
+ tmp_error = entropy2_api_error;
+ end
+
+ MIXER_PREFIX:
+ begin
+ mixer_api_cs = cs;
+ mixer_api_we = we;
+ tmp_read_data = mixer_api_read_data;
+ tmp_error = mixer_api_error;
+ end
+
+ CSPRNG_PREFIX:
+ begin
+ csprng_api_cs = cs;
+ csprng_api_we = we;
+ tmp_read_data = csprng_api_read_data;
+ tmp_error = csprng_api_error;
+ end
+
+ default:
+ begin
+
+ end
+ endcase // case (address[11 : 8])
+ end // api_mux
+
+
+ //----------------------------------------------------------------
+ // trng_api_logic
+ //
+ // Implementation of the top level api logic.
+ //----------------------------------------------------------------
+ always @*
+ begin : trng_api_logic
+ discard_new = 0;
+ test_mode_new = 0;
+ test_mode_we = 0;
+ debug_mux_new = 3'h0;
+ debug_mux_we = 0;
+ debug_delay_new = 32'h00000000;
+ debug_delay_we = 0;
+ trng_api_read_data = 32'h00000000;
+ trng_api_error = 0;
+
+ if (trng_api_cs)
+ begin
+ if (trng_api_we)
+ begin
+ // Write operations.
+ case (api_address)
+ // Write operations.
+ ADDR_TRNG_CTRL:
+ begin
+ discard_new = write_data[TRNG_CTRL_DISCARD_BIT];
+ test_mode_new = write_data[TRNG_CTRL_TEST_MODE_BIT];
+ test_mode_we = 1;
+ end
+
+ ADDR_DEBUG_CTRL:
+ begin
+ debug_mux_new = write_data[2 : 0];
+ debug_mux_we = 1;
+ end
+
+ ADDR_DEBUG_DELAY:
+ begin
+ debug_delay_new = write_data;
+ debug_delay_we = 1;
+ end
+
+ default:
+ begin
+ trng_api_error = 1;
+ end
+ endcase // case (address)
+ end // if (we)
+
+ else
+ begin
+ // Read operations.
+ case (api_address)
+ // Read operations.
+ ADDR_NAME0:
+ begin
+ trng_api_read_data = TRNG_NAME0;
+ end
+
+ ADDR_NAME1:
+ begin
+ trng_api_read_data = TRNG_NAME1;
+ end
+
+ ADDR_VERSION:
+ begin
+ trng_api_read_data = TRNG_VERSION;
+ end
+
+ ADDR_TRNG_CTRL:
+ begin
+ end
+
+ ADDR_TRNG_STATUS:
+ begin
+
+ end
+
+ ADDR_DEBUG_CTRL:
+ begin
+ trng_api_read_data = debug_mux_new;
+ end
+
+ ADDR_DEBUG_DELAY:
+ begin
+ trng_api_read_data = debug_delay_reg;
+ end
+
+ default:
+ begin
+ trng_api_error = 1;
+ end
+ endcase // case (address)
+ end
+ end
+ end // trng_api_logic
+endmodule // trng
+
+//======================================================================
+// EOF trng.v
+//======================================================================
diff --git a/rng/trng/src/rtl/trng_csprng.v b/rng/trng/src/rtl/trng_csprng.v
new file mode 100644
index 0000000..f985be4
--- /dev/null
+++ b/rng/trng/src/rtl/trng_csprng.v
@@ -0,0 +1,673 @@
+//======================================================================
+//
+// trng_csprng.v
+// -------------
+// CSPRNG for the TRNG.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module trng_csprng(
+ // Clock and reset.
+ input wire clk,
+ input wire reset_n,
+
+ input wire cs,
+ input wire we,
+ input wire [7 : 0] address,
+ input wire [31 : 0] write_data,
+ output wire [31 : 0] read_data,
+ output wire error,
+
+ input wire discard,
+ input test_mode,
+ output wire more_seed,
+ output wire security_error,
+
+ input [511 : 0] seed_data,
+ input wire seed_syn,
+ output wire seed_ack,
+
+ output wire [7 : 0] debug,
+ input wire debug_update
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter ADDR_CTRL = 8'h10;
+ parameter CTRL_ENABLE_BIT = 0;
+ parameter CTRL_SEED_BIT = 1;
+
+ parameter ADDR_STATUS = 8'h11;
+ parameter STATUS_RND_VALID_BIT = 0;
+
+ parameter ADDR_RND_DATA = 8'h20;
+
+ parameter ADDR_NUM_ROUNDS = 8'h40;
+ parameter ADDR_NUM_BLOCKS_LOW = 8'h41;
+ parameter ADDR_NUM_BLOCKS_HIGH = 8'h42;
+
+ parameter CIPHER_KEYLEN256 = 1'b1; // 256 bit key.
+ parameter CIPHER_MAX_BLOCKS = 64'h1000000000000000;
+
+ parameter CTRL_IDLE = 4'h0;
+ parameter CTRL_SEED0 = 4'h1;
+ parameter CTRL_NSYN = 4'h2;
+ parameter CTRL_SEED1 = 4'h3;
+ parameter CTRL_INIT0 = 4'h4;
+ parameter CTRL_INIT1 = 4'h5;
+ parameter CTRL_NEXT0 = 4'h6;
+ parameter CTRL_NEXT1 = 4'h7;
+ parameter CTRL_MORE = 4'h8;
+ parameter CTRL_CANCEL = 4'hf;
+
+ parameter DEFAULT_NUM_ROUNDS = 5'h18;
+ parameter DEFAULT_NUM_BLOCKS = 64'h1000000000000000;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [255 : 0] cipher_key_reg;
+ reg [255 : 0] cipher_key_new;
+ reg cipher_key_we;
+
+ reg [63 : 0] cipher_iv_reg;
+ reg [63 : 0] cipher_iv_new;
+ reg cipher_iv_we;
+
+ reg [63 : 0] cipher_ctr_reg;
+ reg [63 : 0] cipher_ctr_new;
+ reg cipher_ctr_we;
+
+ reg [511 : 0] cipher_block_reg;
+ reg [511 : 0] cipher_block_new;
+ reg cipher_block_we;
+
+ reg [63 : 0] block_ctr_reg;
+ reg [63 : 0] block_ctr_new;
+ reg block_ctr_inc;
+ reg block_ctr_rst;
+ reg block_ctr_we;
+ reg block_ctr_max;
+
+ reg ready_reg;
+ reg ready_new;
+ reg ready_we;
+
+ reg more_seed_reg;
+ reg more_seed_new;
+
+ reg seed_ack_reg;
+ reg seed_ack_new;
+
+ reg enable_reg;
+ reg enable_new;
+ reg enable_we;
+
+ reg seed_reg;
+ reg seed_new;
+
+ reg [4 : 0] num_rounds_reg;
+ reg [4 : 0] num_rounds_new;
+ reg num_rounds_we;
+
+ reg [31 : 0] num_blocks_low_reg;
+ reg [31 : 0] num_blocks_low_new;
+ reg num_blocks_low_we;
+
+ reg [31 : 0] num_blocks_high_reg;
+ reg [31 : 0] num_blocks_high_new;
+ reg num_blocks_high_we;
+
+ reg [3 : 0] csprng_ctrl_reg;
+ reg [3 : 0] csprng_ctrl_new;
+ reg csprng_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] tmp_read_data;
+ reg tmp_error;
+
+ reg cipher_init;
+ reg cipher_next;
+
+ wire [511 : 0] cipher_data_out;
+ wire cipher_data_out_valid;
+ wire cipher_ready;
+
+ wire fifo_more_data;
+ reg fifo_discard;
+ wire rnd_syn;
+ wire [31 : 0] rnd_data;
+ reg rnd_ack;
+ reg fifo_cipher_data_valid;
+
+ wire [63 : 0] num_blocks;
+
+ wire muxed_rnd_ack;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign read_data = tmp_read_data;
+ assign error = tmp_error;
+ assign seed_ack = seed_ack_reg;
+ assign more_seed = more_seed_reg;
+ assign debug = rnd_data[7 : 0];
+ assign security_error = 0;
+
+ assign num_blocks = {num_blocks_high_reg, num_blocks_low_reg};
+ assign muxed_rnd_ack = rnd_ack | debug_update;
+
+
+ //----------------------------------------------------------------
+ // core instantiation.
+ //----------------------------------------------------------------
+ chacha_core cipher_inst(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .init(cipher_init),
+ .next(cipher_next),
+
+ .key(cipher_key_reg),
+ .keylen(CIPHER_KEYLEN256),
+ .iv(cipher_iv_reg),
+ .ctr(cipher_ctr_reg),
+ .rounds(num_rounds_reg),
+
+ .data_in(cipher_block_reg),
+ .ready(cipher_ready),
+
+ .data_out(cipher_data_out),
+ .data_out_valid(cipher_data_out_valid)
+ );
+
+
+ trng_csprng_fifo fifo_inst(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .csprng_data(cipher_data_out),
+ .csprng_data_valid(fifo_cipher_data_valid),
+ .discard(fifo_discard),
+ .more_data(fifo_more_data),
+
+ .rnd_syn(rnd_syn),
+ .rnd_data(rnd_data),
+ .rnd_ack(muxed_rnd_ack)
+ );
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with synchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ cipher_key_reg <= {8{32'h00000000}};
+ cipher_iv_reg <= {2{32'h00000000}};
+ cipher_ctr_reg <= {2{32'h00000000}};
+ cipher_block_reg <= {16{32'h00000000}};
+ block_ctr_reg <= {2{32'h00000000}};
+ more_seed_reg <= 0;
+ seed_ack_reg <= 0;
+ ready_reg <= 0;
+ enable_reg <= 1;
+ seed_reg <= 0;
+ num_rounds_reg <= DEFAULT_NUM_ROUNDS;
+ num_blocks_low_reg <= DEFAULT_NUM_BLOCKS[31 : 0];
+ num_blocks_high_reg <= DEFAULT_NUM_BLOCKS[63 : 32];
+ csprng_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ more_seed_reg <= more_seed_new;
+ seed_ack_reg <= seed_ack_new;
+ seed_reg <= seed_new;
+
+ if (enable_we)
+ begin
+ enable_reg <= enable_new;
+ end
+
+ if (cipher_key_we)
+ begin
+ cipher_key_reg <= cipher_key_new;
+ end
+
+ if (cipher_iv_we)
+ begin
+ cipher_iv_reg <= cipher_iv_new;
+ end
+
+ if (cipher_ctr_we)
+ begin
+ cipher_ctr_reg <= cipher_ctr_new;
+ end
+
+ if (cipher_block_we)
+ begin
+ cipher_block_reg <= cipher_block_new;
+ end
+
+ if (block_ctr_we)
+ begin
+ block_ctr_reg <= block_ctr_new;
+ end
+
+ if (ready_we)
+ begin
+ ready_reg <= ready_new;
+ end
+
+ if (csprng_ctrl_we)
+ begin
+ csprng_ctrl_reg <= csprng_ctrl_new;
+ end
+
+ if (num_rounds_we)
+ begin
+ num_rounds_reg <= num_rounds_new;
+ end
+
+ if (num_blocks_low_we)
+ begin
+ num_blocks_low_reg <= num_blocks_low_new;
+ end
+
+ if (num_blocks_high_we)
+ begin
+ num_blocks_high_reg <= num_blocks_high_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // csprng_api_logic
+ //----------------------------------------------------------------
+ always @*
+ begin : csprng_api_logic
+ enable_new = 0;
+ enable_we = 0;
+ seed_new = 0;
+
+ num_rounds_new = 5'h00;
+ num_rounds_we = 0;
+
+ num_blocks_low_new = 32'h00000000;
+ num_blocks_low_we = 0;
+ num_blocks_high_new = 32'h00000000;
+ num_blocks_high_we = 0;
+
+ rnd_ack = 0;
+
+ tmp_read_data = 32'h00000000;
+ tmp_error = 0;
+
+ if (cs)
+ begin
+ if (we)
+ begin
+ // Write operations.
+ case (address)
+ // Write operations.
+ ADDR_CTRL:
+ begin
+ enable_new = write_data[CTRL_ENABLE_BIT];
+ enable_we = 1;
+ seed_new = write_data[CTRL_SEED_BIT];
+ end
+
+ ADDR_NUM_ROUNDS:
+ begin
+ num_rounds_new = write_data[4 : 0];
+ num_rounds_we = 1;
+ end
+
+ ADDR_NUM_BLOCKS_LOW:
+ begin
+ num_blocks_low_new = write_data;
+ num_blocks_low_we = 1;
+ end
+
+ ADDR_NUM_BLOCKS_HIGH:
+ begin
+ num_blocks_high_new = write_data;
+ num_blocks_high_we = 1;
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end // if (we)
+
+ else
+ begin
+ // Read operations.
+ case (address)
+ // Read operations.
+ ADDR_CTRL:
+ begin
+ tmp_read_data = {30'h00000000, seed_reg, enable_reg};
+ end
+
+ ADDR_STATUS:
+ begin
+ tmp_read_data = {30'h00000000, ready_reg, rnd_syn};
+ end
+
+ ADDR_RND_DATA:
+ begin
+ tmp_read_data = rnd_data;
+ rnd_ack = 1;
+ end
+
+ ADDR_NUM_ROUNDS:
+ begin
+ tmp_read_data = {27'h0000000, num_rounds_reg};
+ end
+
+ ADDR_NUM_BLOCKS_LOW:
+ begin
+ tmp_read_data = num_blocks_low_reg;
+ end
+
+ ADDR_NUM_BLOCKS_HIGH:
+ begin
+ tmp_read_data = num_blocks_high_reg;
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end
+ end
+ end // cspng_api_logic
+
+
+ //----------------------------------------------------------------
+ // block_ctr
+ //
+ // Logic to implement the block counter. This includes the
+ // ability to detect that maximum allowed number of blocks
+ // has been reached. Either as defined by the application
+ // or the hard coded CIPHER_MAX_BLOCKS value.
+ //----------------------------------------------------------------
+ always @*
+ begin : block_ctr
+ block_ctr_new = 64'h0000000000000000;
+ block_ctr_we = 0;
+ block_ctr_max = 0;
+
+ if (block_ctr_rst)
+ begin
+ block_ctr_new = 64'h0000000000000000;
+ block_ctr_we = 1;
+ end
+
+ if (block_ctr_inc)
+ begin
+ block_ctr_new = block_ctr_reg + 1'b1;
+ block_ctr_we = 1;
+ end
+
+ if ((block_ctr_reg == num_blocks) || (block_ctr_reg == CIPHER_MAX_BLOCKS))
+ begin
+ block_ctr_max = 1;
+ end
+ end // block_ctr
+
+
+ //----------------------------------------------------------------
+ // csprng_ctrl_fsm
+ //
+ // Control FSM for the CSPRNG.
+ //----------------------------------------------------------------
+ always @*
+ begin : csprng_ctrl_fsm
+ cipher_key_new = {8{32'h00000000}};
+ cipher_key_we = 0;
+ cipher_iv_new = {2{32'h00000000}};
+ cipher_iv_we = 0;
+ cipher_ctr_new = {2{32'h00000000}};
+ cipher_ctr_we = 0;
+ cipher_block_new = {16{32'h00000000}};
+ cipher_block_we = 0;
+ cipher_init = 0;
+ cipher_next = 0;
+ block_ctr_rst = 0;
+ block_ctr_inc = 0;
+ ready_new = 0;
+ ready_we = 0;
+ seed_ack_new = 0;
+ more_seed_new = 0;
+ fifo_discard = 0;
+ fifo_cipher_data_valid = 0;
+ csprng_ctrl_new = CTRL_IDLE;
+ csprng_ctrl_we = 0;
+
+ case (csprng_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (!enable_reg)
+ begin
+ csprng_ctrl_new = CTRL_CANCEL;
+ csprng_ctrl_we = 1;
+ end
+ else if (fifo_more_data)
+ begin
+ more_seed_new = 1;
+ csprng_ctrl_new = CTRL_SEED0;
+ csprng_ctrl_we = 1;
+ end
+ end
+
+ CTRL_SEED0:
+ begin
+ if ((!enable_reg) || (seed_reg))
+ begin
+ csprng_ctrl_new = CTRL_CANCEL;
+ csprng_ctrl_we = 1;
+ end
+ else if (seed_syn)
+ begin
+ seed_ack_new = 1;
+ cipher_block_new = seed_data;
+ cipher_block_we = 1;
+ csprng_ctrl_new = CTRL_NSYN;
+ csprng_ctrl_we = 1;
+ end
+ end
+
+ CTRL_NSYN:
+ begin
+ if ((!enable_reg) || (seed_reg))
+ begin
+ csprng_ctrl_new = CTRL_CANCEL;
+ csprng_ctrl_we = 1;
+ end
+ else
+ begin
+ more_seed_new = 1;
+ csprng_ctrl_new = CTRL_SEED1;
+ csprng_ctrl_we = 1;
+ end
+ end
+
+ CTRL_SEED1:
+ begin
+ if ((!enable_reg) || (seed_reg))
+ begin
+ csprng_ctrl_new = CTRL_CANCEL;
+ csprng_ctrl_we = 1;
+ end
+ else if (seed_syn)
+ begin
+ seed_ack_new = 1;
+ cipher_key_new = seed_data[255 : 0];
+ cipher_key_we = 1;
+ cipher_iv_new = seed_data[319 : 256];
+ cipher_iv_we = 1;
+ cipher_ctr_new = seed_data[383 : 320];
+ cipher_ctr_we = 1;
+ csprng_ctrl_new = CTRL_INIT0;
+ csprng_ctrl_we = 1;
+ end
+ else
+ begin
+ more_seed_new = 1;
+ end
+ end
+
+ CTRL_INIT0:
+ begin
+ if ((!enable_reg) || (seed_reg))
+ begin
+ csprng_ctrl_new = CTRL_CANCEL;
+ csprng_ctrl_we = 1;
+ end
+ else
+ begin
+ cipher_init = 1;
+ block_ctr_rst = 1;
+ csprng_ctrl_new = CTRL_INIT1;
+ csprng_ctrl_we = 1;
+ end
+ end
+
+ CTRL_INIT1:
+ begin
+ if ((!enable_reg) || (seed_reg))
+ begin
+ csprng_ctrl_new = CTRL_CANCEL;
+ csprng_ctrl_we = 1;
+ end
+ else if (cipher_ready)
+ begin
+ csprng_ctrl_new = CTRL_NEXT0;
+ csprng_ctrl_we = 1;
+ end
+ end
+
+ CTRL_NEXT0:
+ begin
+ if ((!enable_reg) || (seed_reg))
+ begin
+ csprng_ctrl_new = CTRL_CANCEL;
+ csprng_ctrl_we = 1;
+ end
+ else
+ begin
+ cipher_next = 1;
+ csprng_ctrl_new = CTRL_NEXT1;
+ csprng_ctrl_we = 1;
+ end
+ end
+
+ CTRL_NEXT1:
+ if ((!enable_reg) || (seed_reg))
+ begin
+ csprng_ctrl_new = CTRL_CANCEL;
+ csprng_ctrl_we = 1;
+ end
+ else if (cipher_ready)
+ begin
+ block_ctr_inc = 1;
+ fifo_cipher_data_valid = 1;
+ csprng_ctrl_new = CTRL_MORE;
+ csprng_ctrl_we = 1;
+ end
+
+ CTRL_MORE:
+ begin
+ if ((!enable_reg) || (seed_reg))
+ begin
+ csprng_ctrl_new = CTRL_CANCEL;
+ csprng_ctrl_we = 1;
+ end
+ else if (fifo_more_data)
+ begin
+ if (block_ctr_max)
+ begin
+ more_seed_new = 1;
+ csprng_ctrl_new = CTRL_SEED0;
+ csprng_ctrl_we = 1;
+ end
+ else
+ begin
+ csprng_ctrl_new = CTRL_NEXT0;
+ csprng_ctrl_we = 1;
+ end
+ end
+ end
+
+ CTRL_CANCEL:
+ begin
+ fifo_discard = 1;
+ cipher_key_new = {8{32'h00000000}};
+ cipher_key_we = 1;
+ cipher_iv_new = {2{32'h00000000}};
+ cipher_iv_we = 1;
+ cipher_ctr_new = {2{32'h00000000}};
+ cipher_ctr_we = 1;
+ cipher_block_new = {16{32'h00000000}};
+ cipher_block_we = 1;
+ block_ctr_rst = 1;
+ csprng_ctrl_new = CTRL_IDLE;
+ csprng_ctrl_we = 1;
+ end
+
+ endcase // case (cspng_ctrl_reg)
+ end // csprng_ctrl_fsm
+
+endmodule // trng_csprng
+
+//======================================================================
+// EOF trng_csprng.v
+//======================================================================
diff --git a/rng/trng/src/rtl/trng_csprng_fifo.v b/rng/trng/src/rtl/trng_csprng_fifo.v
new file mode 100644
index 0000000..b6ff2c1
--- /dev/null
+++ b/rng/trng/src/rtl/trng_csprng_fifo.v
@@ -0,0 +1,507 @@
+//======================================================================
+//
+// trng_csprng_fifo.v
+// ------------------
+// Output FIFO for the CSPRNG in the TRNG.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module trng_csprng_fifo(
+ // Clock and reset.
+ input wire clk,
+ input wire reset_n,
+
+ input wire [511 : 0] csprng_data,
+ input wire csprng_data_valid,
+ input wire discard,
+ output wire more_data,
+
+ output wire rnd_syn,
+ output wire [31 : 0] rnd_data,
+ input wire rnd_ack
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter FIFO_DEPTH = 4;
+ parameter FIFO_MAX = FIFO_DEPTH - 1;
+
+ parameter WR_IDLE = 0;
+ parameter WR_WAIT = 1;
+ parameter WR_WRITE = 2;
+ parameter WR_DISCARD = 7;
+
+ parameter RD_IDLE = 0;
+ parameter RD_ACK = 1;
+ parameter RD_DISCARD = 7;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [511 : 0] fifo_mem [0 : FIFO_MAX];
+ reg fifo_mem_we;
+
+ reg [3 : 0] mux_data_ptr_reg;
+ reg [3 : 0] mux_data_ptr_new;
+ reg mux_data_ptr_inc;
+ reg mux_data_ptr_rst;
+ reg mux_data_ptr_we;
+
+ reg [2 : 0] wr_ptr_reg;
+ reg [2 : 0] wr_ptr_new;
+ reg wr_ptr_inc;
+ reg wr_ptr_rst;
+ reg wr_ptr_we;
+
+ reg [2 : 0] rd_ptr_reg;
+ reg [2 : 0] rd_ptr_new;
+ reg rd_ptr_inc;
+ reg rd_ptr_rst;
+ reg rd_ptr_we;
+
+ reg [31 : 0] rnd_data_reg;
+
+ reg rnd_syn_reg;
+ reg rnd_syn_new;
+ reg rnd_syn_we;
+
+ reg [2 : 0] wr_ctrl_reg;
+ reg [2 : 0] wr_ctrl_new;
+ reg wr_ctrl_we;
+
+ reg [2 : 0] rd_ctrl_reg;
+ reg [2 : 0] rd_ctrl_new;
+ reg rd_ctrl_we;
+
+ reg [2 : 0] fifo_ctr_reg;
+ reg [2 : 0] fifo_ctr_new;
+ reg fifo_ctr_inc;
+ reg fifo_ctr_dec;
+ reg fifo_ctr_rst;
+ reg fifo_ctr_we;
+ reg fifo_empty;
+ reg fifo_full;
+
+ reg more_data_reg;
+ reg more_data_new;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] muxed_data;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign rnd_data = rnd_data_reg;
+ assign rnd_syn = rnd_syn_reg;
+ assign more_data = more_data_reg;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Register update. All registers have asynchronous reset.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ fifo_mem[00] <= {16{32'h00000000}};
+ fifo_mem[01] <= {16{32'h00000000}};
+ fifo_mem[02] <= {16{32'h00000000}};
+ fifo_mem[03] <= {16{32'h00000000}};
+ mux_data_ptr_reg <= 4'h0;
+ wr_ptr_reg <= 3'h0;
+ rd_ptr_reg <= 3'h0;
+ fifo_ctr_reg <= 3'h0;
+ rnd_data_reg <= 32'h00000000;
+ rnd_syn_reg <= 0;
+ more_data_reg <= 0;
+ wr_ctrl_reg <= WR_IDLE;
+ rd_ctrl_reg <= RD_IDLE;
+ end
+ else
+ begin
+ rnd_data_reg <= muxed_data;
+ more_data_reg <= more_data_new;
+
+ if (rnd_syn_we)
+ begin
+ rnd_syn_reg <= rnd_syn_new;
+ end
+
+ if (fifo_mem_we)
+ begin
+ fifo_mem[wr_ptr_reg] <= csprng_data;
+ end
+
+ if (mux_data_ptr_we)
+ begin
+ mux_data_ptr_reg <= mux_data_ptr_new;
+ end
+
+ if (wr_ptr_we)
+ begin
+ wr_ptr_reg <= wr_ptr_new;
+ end
+
+ if (rd_ptr_we)
+ begin
+ rd_ptr_reg <= rd_ptr_new;
+ end
+
+ if (fifo_ctr_we)
+ begin
+ fifo_ctr_reg <= fifo_ctr_new;
+ end
+
+ if (rd_ctrl_we)
+ begin
+ rd_ctrl_reg <= rd_ctrl_new;
+ end
+
+ if (wr_ctrl_we)
+ begin
+ wr_ctrl_reg <= wr_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // output_data_mux
+ //
+ // Logic that reads out a 512 bit word from the fifo memory
+ // and then selects a 32-bit word as output data.
+ //----------------------------------------------------------------
+ always @*
+ begin : output_data_mux
+ reg [511 : 0] fifo_rd_data;
+
+ fifo_rd_data = fifo_mem[rd_ptr_reg];
+
+ case(mux_data_ptr_reg)
+ 00: muxed_data = fifo_rd_data[031 : 000];
+ 01: muxed_data = fifo_rd_data[063 : 032];
+ 02: muxed_data = fifo_rd_data[095 : 064];
+ 03: muxed_data = fifo_rd_data[127 : 096];
+ 04: muxed_data = fifo_rd_data[159 : 128];
+ 05: muxed_data = fifo_rd_data[191 : 160];
+ 06: muxed_data = fifo_rd_data[223 : 192];
+ 07: muxed_data = fifo_rd_data[255 : 224];
+ 08: muxed_data = fifo_rd_data[287 : 256];
+ 09: muxed_data = fifo_rd_data[313 : 282];
+ 10: muxed_data = fifo_rd_data[351 : 320];
+ 11: muxed_data = fifo_rd_data[383 : 352];
+ 12: muxed_data = fifo_rd_data[415 : 384];
+ 13: muxed_data = fifo_rd_data[447 : 416];
+ 14: muxed_data = fifo_rd_data[479 : 448];
+ 15: muxed_data = fifo_rd_data[511 : 480];
+ endcase // case (mux_data_ptr_reg)
+ end // output_data_mux
+
+
+ //----------------------------------------------------------------
+ // mux_data_ptr
+ //
+ // Pointer for selecting output data word from the 512 bit
+ // word currently being read in the FIFO.
+ //----------------------------------------------------------------
+ always @*
+ begin : mux_data_ptr
+ mux_data_ptr_new = 4'h0;
+ mux_data_ptr_we = 0;
+
+ if (mux_data_ptr_rst)
+ begin
+ mux_data_ptr_new = 4'h0;
+ mux_data_ptr_we = 1;
+ end
+
+ if (mux_data_ptr_inc)
+ begin
+ mux_data_ptr_new = mux_data_ptr_reg + 1'b1;
+ mux_data_ptr_we = 1;
+ end
+ end // mux_data_ptr
+
+
+ //----------------------------------------------------------------
+ // fifo_rd_ptr
+ //
+ // Pointer that selects the current 512 bit word in the FIFO
+ // to extract data from.
+ //----------------------------------------------------------------
+ always @*
+ begin : fifo_rd_ptr
+ rd_ptr_new = 3'h0;
+ rd_ptr_we = 0;
+ fifo_ctr_dec = 0;
+
+ if (rd_ptr_rst)
+ begin
+ rd_ptr_new = 3'h0;
+ rd_ptr_we = 1;
+ end
+
+ if (rd_ptr_inc)
+ begin
+ fifo_ctr_dec = 1;
+ if (rd_ptr_reg == FIFO_MAX)
+ begin
+ rd_ptr_new = 3'h0;
+ rd_ptr_we = 1;
+ end
+ else
+ begin
+ rd_ptr_new = rd_ptr_reg + 1'b1;
+ rd_ptr_we = 1;
+ end
+ end
+ end // fifo_rd_ptr
+
+
+ //----------------------------------------------------------------
+ // fifo_wr_ptr
+ //
+ // Pointer to where to store a new 512 bit word in the FIFO.
+ //----------------------------------------------------------------
+ always @*
+ begin : fifo_wr_ptr
+ wr_ptr_new = 3'h0;
+ wr_ptr_we = 0;
+
+ if (wr_ptr_rst)
+ begin
+ wr_ptr_new = 3'h0;
+ wr_ptr_we = 1;
+ end
+
+ if (wr_ptr_inc)
+ begin
+ if (wr_ptr_reg == FIFO_MAX)
+ begin
+ wr_ptr_new = 3'h0;
+ wr_ptr_we = 1;
+ end
+ else
+ begin
+ wr_ptr_new = wr_ptr_reg + 1'b1;
+ wr_ptr_we = 1;
+ end
+ end
+ end // fifo_wr_ptr
+
+
+ //----------------------------------------------------------------
+ // fifo_ctr
+ //
+ // fifo counter tracks the number of elements and also signals
+ // the csprng when more data is needed as well as applications
+ // that random numbers are available.
+ //----------------------------------------------------------------
+ always @*
+ begin : fifo_ctr
+ fifo_ctr_new = 3'h0;
+ fifo_ctr_we = 0;
+ fifo_empty = 0;
+ fifo_full = 0;
+
+ if (fifo_ctr_reg == 3'h0)
+ begin
+ fifo_empty = 1;
+ end
+
+ if (fifo_ctr_reg == FIFO_MAX)
+ begin
+ fifo_full = 1;
+ end
+
+ if ((fifo_ctr_inc) && (fifo_ctr_reg < FIFO_MAX))
+ begin
+ fifo_ctr_new = fifo_ctr_reg + 1'b1;
+ fifo_ctr_we = 1;
+ end
+
+ if ((fifo_ctr_dec) && (fifo_ctr_reg > 3'h0))
+ begin
+ fifo_ctr_new = fifo_ctr_reg - 1'b1;
+ fifo_ctr_we = 1;
+ end
+
+ if (fifo_ctr_rst)
+ begin
+ fifo_ctr_new = 3'h0;
+ fifo_ctr_we = 1;
+ end
+ end // fifo_ctr
+
+
+ //----------------------------------------------------------------
+ // rd_ctrl
+ //
+ // Control FSM for reading data as requested by the consumers.
+ //----------------------------------------------------------------
+ always @*
+ begin : rd_ctrl
+ mux_data_ptr_rst = 0;
+ mux_data_ptr_inc = 0;
+ rnd_syn_new = 0;
+ rnd_syn_we = 0;
+ rd_ptr_inc = 0;
+ rd_ptr_rst = 0;
+ rd_ctrl_new = RD_IDLE;
+ rd_ctrl_we = 0;
+
+ case (rd_ctrl_reg)
+ RD_IDLE:
+ begin
+ if (discard)
+ begin
+ rd_ctrl_new = RD_DISCARD;
+ rd_ctrl_we = 1;
+ end
+ else
+ begin
+ if (!fifo_empty)
+ begin
+ rnd_syn_new = 1;
+ rnd_syn_we = 1;
+ rd_ctrl_new = RD_ACK;
+ rd_ctrl_we = 1;
+ end
+ end
+ end
+
+ RD_ACK:
+ begin
+ if (discard)
+ begin
+ rd_ctrl_new = RD_DISCARD;
+ rd_ctrl_we = 1;
+ end
+ else
+ begin
+ if (rnd_ack)
+ begin
+ if (mux_data_ptr_reg == 4'hf)
+ begin
+ rd_ptr_inc = 1;
+ mux_data_ptr_rst = 1;
+ end
+ else
+ begin
+ mux_data_ptr_inc = 1;
+ end
+ rnd_syn_new = 0;
+ rnd_syn_we = 1;
+ rd_ctrl_new = RD_IDLE;
+ rd_ctrl_we = 1;
+ end
+ end
+ end
+
+ RD_DISCARD:
+ begin
+ rnd_syn_new = 0;
+ rnd_syn_we = 1;
+ rd_ptr_rst = 1;
+ rd_ctrl_new = RD_IDLE;
+ rd_ctrl_we = 1;
+ end
+
+ endcase // case (rd_ctrl_reg)
+ end // rd_ctrl
+
+
+ //----------------------------------------------------------------
+ // wr_ctrl
+ //
+ // FSM for requesting data and writing new data to the fifo.
+ //----------------------------------------------------------------
+ always @*
+ begin : wr_ctrl
+ wr_ptr_inc = 0;
+ wr_ptr_rst = 0;
+ fifo_mem_we = 0;
+ fifo_ctr_inc = 0;
+ fifo_ctr_rst = 0;
+ more_data_new = 0;
+ wr_ctrl_new = WR_IDLE;
+ wr_ctrl_we = 0;
+
+ case (wr_ctrl_reg)
+ WR_IDLE:
+ begin
+ if (discard)
+ begin
+ wr_ctrl_new = WR_DISCARD;
+ wr_ctrl_we = 1;
+ end
+ else
+ begin
+ if (!fifo_full)
+ begin
+ more_data_new = 1;
+ end
+
+ if (csprng_data_valid)
+ begin
+ fifo_mem_we = 1;
+ wr_ptr_inc = 1;
+ fifo_ctr_inc = 1;
+ end
+ end
+ end
+
+ WR_DISCARD:
+ begin
+ fifo_ctr_rst = 1;
+ wr_ptr_rst = 1;
+ wr_ctrl_new = WR_IDLE;
+ wr_ctrl_we = 1;
+ end
+ endcase // case (wr_ctrl_reg)
+ end // wr_ctrl
+
+endmodule // trng_csprng_fifo
+
+//======================================================================
+// EOF trng_csprng_fifo.v
+//======================================================================
diff --git a/rng/trng/src/rtl/trng_mixer.v b/rng/trng/src/rtl/trng_mixer.v
new file mode 100644
index 0000000..de57fe0
--- /dev/null
+++ b/rng/trng/src/rtl/trng_mixer.v
@@ -0,0 +1,1125 @@
+//======================================================================
+//
+// trng_mixer.v
+// ------------
+// Mixer for the TRNG.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module trng_mixer(
+ input wire clk,
+ input wire reset_n,
+
+ input wire cs,
+ input wire we,
+ input wire [7 : 0] address,
+ input wire [31 : 0] write_data,
+ output wire [31 : 0] read_data,
+ output wire error,
+
+ input wire discard,
+ input wire test_mode,
+ output wire security_error,
+
+ input wire more_seed,
+
+ input wire entropy0_enabled,
+ input wire entropy0_syn,
+ input wire [31 : 0] entropy0_data,
+ output wire entropy0_ack,
+
+ input wire entropy1_enabled,
+ input wire entropy1_syn,
+ input wire [31 : 0] entropy1_data,
+ output wire entropy1_ack,
+
+ input wire entropy2_enabled,
+ input wire entropy2_syn,
+ input wire [31 : 0] entropy2_data,
+ output wire entropy2_ack,
+
+ output wire [511 : 0] seed_data,
+ output wire seed_syn,
+ input wire seed_ack,
+
+ output wire [7 : 0] debug,
+ input wire debug_update
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter MODE_SHA_512 = 2'h3;
+
+ parameter ENTROPY_IDLE = 4'h0;
+ parameter ENTROPY_SRC0 = 4'h1;
+ parameter ENTROPY_SRC0_ACK = 4'h2;
+ parameter ENTROPY_SRC1 = 4'h3;
+ parameter ENTROPY_SRC1_ACK = 4'h4;
+ parameter ENTROPY_SRC2 = 4'h5;
+ parameter ENTROPY_SRC2_ACK = 4'h6;
+
+ parameter CTRL_IDLE = 4'h0;
+ parameter CTRL_COLLECT = 4'h1;
+ parameter CTRL_MIX = 4'h2;
+ parameter CTRL_SYN = 4'h3;
+ parameter CTRL_ACK = 4'h4;
+ parameter CTRL_NEXT = 4'h5;
+
+ parameter ADDR_MIXER_CTRL = 8'h10;
+ parameter MIXER_CTRL_ENABLE_BIT = 0;
+ parameter MIXER_CTRL_RESTART_BIT = 1;
+ parameter ADDR_MIXER_STATUS = 8'h11;
+ parameter ADDR_MIXER_TIMEOUT = 8'h20;
+
+ parameter DEFAULT_ENTROPY_TIMEOUT = 24'h100000;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] block00_reg;
+ reg block00_we;
+ reg [31 : 0] block01_reg;
+ reg block01_we;
+ reg [31 : 0] block02_reg;
+ reg block02_we;
+ reg [31 : 0] block03_reg;
+ reg block03_we;
+ reg [31 : 0] block04_reg;
+ reg block04_we;
+ reg [31 : 0] block05_reg;
+ reg block05_we;
+ reg [31 : 0] block06_reg;
+ reg block06_we;
+ reg [31 : 0] block07_reg;
+ reg block07_we;
+ reg [31 : 0] block08_reg;
+ reg block08_we;
+ reg [31 : 0] block09_reg;
+ reg block09_we;
+ reg [31 : 0] block10_reg;
+ reg block10_we;
+ reg [31 : 0] block11_reg;
+ reg block11_we;
+ reg [31 : 0] block12_reg;
+ reg block12_we;
+ reg [31 : 0] block13_reg;
+ reg block13_we;
+ reg [31 : 0] block14_reg;
+ reg block14_we;
+ reg [31 : 0] block15_reg;
+ reg block15_we;
+ reg [31 : 0] block16_reg;
+ reg block16_we;
+ reg [31 : 0] block17_reg;
+ reg block17_we;
+ reg [31 : 0] block18_reg;
+ reg block18_we;
+ reg [31 : 0] block19_reg;
+ reg block19_we;
+ reg [31 : 0] block20_reg;
+ reg block20_we;
+ reg [31 : 0] block21_reg;
+ reg block21_we;
+ reg [31 : 0] block22_reg;
+ reg block22_we;
+ reg [31 : 0] block23_reg;
+ reg block23_we;
+ reg [31 : 0] block24_reg;
+ reg block24_we;
+ reg [31 : 0] block25_reg;
+ reg block25_we;
+ reg [31 : 0] block26_reg;
+ reg block26_we;
+ reg [31 : 0] block27_reg;
+ reg block27_we;
+ reg [31 : 0] block28_reg;
+ reg block28_we;
+ reg [31 : 0] block29_reg;
+ reg block29_we;
+ reg [31 : 0] block30_reg;
+ reg block30_we;
+ reg [31 : 0] block31_reg;
+ reg block31_we;
+
+ reg [4 : 0] word_ctr_reg;
+ reg [4 : 0] word_ctr_new;
+ reg word_ctr_inc;
+ reg word_ctr_rst;
+ reg word_ctr_we;
+
+ reg [3 : 0] entropy_collect_ctrl_reg;
+ reg [3 : 0] entropy_collect_ctrl_new;
+ reg entropy_collect_ctrl_we;
+
+ reg [23 : 0] entropy_timeout_ctr_reg;
+ reg [23 : 0] entropy_timeout_ctr_new;
+ reg entropy_timeout_ctr_inc;
+ reg entropy_timeout_ctr_rst;
+ reg entropy_timeout_ctr_we;
+ reg entropy_timeout;
+
+ reg [23 : 0] entropy_timeout_reg;
+ reg [23 : 0] entropy_timeout_new;
+ reg entropy_timeout_we;
+
+ reg [3 : 0] mixer_ctrl_reg;
+ reg [3 : 0] mixer_ctrl_new;
+ reg mixer_ctrl_we;
+
+ reg seed_syn_reg;
+ reg seed_syn_new;
+ reg seed_syn_we;
+
+ reg init_done_reg;
+ reg init_done_new;
+ reg init_done_we;
+
+ reg enable_reg;
+ reg enable_new;
+ reg enable_we;
+
+ reg restart_reg;
+ reg restart_new;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] muxed_entropy;
+ reg collect_block;
+ reg update_block;
+ reg block_done;
+
+ reg hash_init;
+ reg hash_next;
+
+ wire hash_work_factor;
+ wire [31 : 0] hash_work_factor_num;
+
+
+ wire [1023 : 0] hash_block;
+ wire hash_ready;
+ wire [511 : 0] hash_digest;
+ wire hash_digest_valid;
+
+ reg tmp_entropy0_ack;
+ reg tmp_entropy1_ack;
+ reg tmp_entropy2_ack;
+
+ reg [31 : 0] tmp_read_data;
+ reg tmp_error;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign read_data = tmp_read_data;
+ assign error = tmp_error;
+ assign security_error = 0;
+
+ assign seed_syn = seed_syn_reg;
+ assign seed_data = hash_digest;
+
+ assign hash_block = {block00_reg, block01_reg, block02_reg, block03_reg,
+ block04_reg, block05_reg, block06_reg, block07_reg,
+ block08_reg, block09_reg,
+ block10_reg, block11_reg, block12_reg, block13_reg,
+ block14_reg, block15_reg, block16_reg, block17_reg,
+ block18_reg, block19_reg,
+ block20_reg, block21_reg, block22_reg, block23_reg,
+ block24_reg, block25_reg, block26_reg, block27_reg,
+ block28_reg, block29_reg,
+ block30_reg, block31_reg};
+
+ assign hash_work_factor = 0;
+ assign hash_work_factor_num = 32'h00000000;
+
+ assign entropy0_ack = tmp_entropy0_ack;
+ assign entropy1_ack = tmp_entropy1_ack;
+ assign entropy2_ack = tmp_entropy2_ack;
+
+ assign debug = 8'h55;
+
+
+ //----------------------------------------------------------------
+ // core instantiation.
+ //----------------------------------------------------------------
+ sha512_core hash_inst(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .init(hash_init),
+ .next(hash_next),
+ .mode(MODE_SHA_512),
+
+ .work_factor(hash_work_factor),
+ .work_factor_num(hash_work_factor_num),
+
+ .block(hash_block),
+
+ .ready(hash_ready),
+ .digest(hash_digest),
+ .digest_valid(hash_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ block00_reg <= 32'h00000000;
+ block01_reg <= 32'h00000000;
+ block02_reg <= 32'h00000000;
+ block03_reg <= 32'h00000000;
+ block04_reg <= 32'h00000000;
+ block05_reg <= 32'h00000000;
+ block06_reg <= 32'h00000000;
+ block07_reg <= 32'h00000000;
+ block08_reg <= 32'h00000000;
+ block09_reg <= 32'h00000000;
+ block10_reg <= 32'h00000000;
+ block11_reg <= 32'h00000000;
+ block12_reg <= 32'h00000000;
+ block13_reg <= 32'h00000000;
+ block14_reg <= 32'h00000000;
+ block15_reg <= 32'h00000000;
+ block16_reg <= 32'h00000000;
+ block17_reg <= 32'h00000000;
+ block18_reg <= 32'h00000000;
+ block19_reg <= 32'h00000000;
+ block20_reg <= 32'h00000000;
+ block21_reg <= 32'h00000000;
+ block22_reg <= 32'h00000000;
+ block23_reg <= 32'h00000000;
+ block24_reg <= 32'h00000000;
+ block25_reg <= 32'h00000000;
+ block26_reg <= 32'h00000000;
+ block27_reg <= 32'h00000000;
+ block28_reg <= 32'h00000000;
+ block29_reg <= 32'h00000000;
+ block30_reg <= 32'h00000000;
+ block31_reg <= 32'h00000000;
+ init_done_reg <= 0;
+ word_ctr_reg <= 5'h00;
+ seed_syn_reg <= 0;
+ enable_reg <= 1;
+ restart_reg <= 0;
+ entropy_timeout_reg <= DEFAULT_ENTROPY_TIMEOUT;
+ entropy_timeout_ctr_reg <= 24'h000000;
+ entropy_collect_ctrl_reg <= CTRL_IDLE;
+ mixer_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ restart_reg <= restart_new;
+
+ if (block00_we)
+ begin
+ block00_reg <= muxed_entropy;
+ end
+
+ if (block01_we)
+ begin
+ block01_reg <= muxed_entropy;
+ end
+
+ if (block02_we)
+ begin
+ block02_reg <= muxed_entropy;
+ end
+
+ if (block03_we)
+ begin
+ block03_reg <= muxed_entropy;
+ end
+
+ if (block04_we)
+ begin
+ block04_reg <= muxed_entropy;
+ end
+
+ if (block05_we)
+ begin
+ block05_reg <= muxed_entropy;
+ end
+
+ if (block06_we)
+ begin
+ block06_reg <= muxed_entropy;
+ end
+
+ if (block07_we)
+ begin
+ block07_reg <= muxed_entropy;
+ end
+
+ if (block08_we)
+ begin
+ block08_reg <= muxed_entropy;
+ end
+
+ if (block09_we)
+ begin
+ block09_reg <= muxed_entropy;
+ end
+
+ if (block10_we)
+ begin
+ block10_reg <= muxed_entropy;
+ end
+
+ if (block11_we)
+ begin
+ block11_reg <= muxed_entropy;
+ end
+
+ if (block12_we)
+ begin
+ block12_reg <= muxed_entropy;
+ end
+
+ if (block13_we)
+ begin
+ block13_reg <= muxed_entropy;
+ end
+
+ if (block14_we)
+ begin
+ block14_reg <= muxed_entropy;
+ end
+
+ if (block15_we)
+ begin
+ block15_reg <= muxed_entropy;
+ end
+
+ if (block16_we)
+ begin
+ block16_reg <= muxed_entropy;
+ end
+
+ if (block17_we)
+ begin
+ block17_reg <= muxed_entropy;
+ end
+
+ if (block18_we)
+ begin
+ block18_reg <= muxed_entropy;
+ end
+
+ if (block19_we)
+ begin
+ block19_reg <= muxed_entropy;
+ end
+
+ if (block20_we)
+ begin
+ block20_reg <= muxed_entropy;
+ end
+
+ if (block21_we)
+ begin
+ block21_reg <= muxed_entropy;
+ end
+
+ if (block22_we)
+ begin
+ block22_reg <= muxed_entropy;
+ end
+
+ if (block23_we)
+ begin
+ block23_reg <= muxed_entropy;
+ end
+
+ if (block24_we)
+ begin
+ block24_reg <= muxed_entropy;
+ end
+
+ if (block25_we)
+ begin
+ block25_reg <= muxed_entropy;
+ end
+
+ if (block26_we)
+ begin
+ block26_reg <= muxed_entropy;
+ end
+
+ if (block27_we)
+ begin
+ block27_reg <= muxed_entropy;
+ end
+
+ if (block28_we)
+ begin
+ block28_reg <= muxed_entropy;
+ end
+
+ if (block29_we)
+ begin
+ block29_reg <= muxed_entropy;
+ end
+
+ if (block30_we)
+ begin
+ block30_reg <= muxed_entropy;
+ end
+
+ if (block31_we)
+ begin
+ block31_reg <= muxed_entropy;
+ end
+
+ if (init_done_we)
+ begin
+ init_done_reg <= init_done_new;
+ end
+
+ if (word_ctr_we)
+ begin
+ word_ctr_reg <= word_ctr_new;
+ end
+
+ if (seed_syn_we)
+ begin
+ seed_syn_reg <= seed_syn_new;
+ end
+
+ if (entropy_collect_ctrl_we)
+ begin
+ entropy_collect_ctrl_reg <= entropy_collect_ctrl_new;
+ end
+
+ if (enable_we)
+ begin
+ enable_reg <= enable_new;
+ end
+
+ if (mixer_ctrl_we)
+ begin
+ mixer_ctrl_reg <= mixer_ctrl_new;
+ end
+
+ if (entropy_timeout_we)
+ begin
+ entropy_timeout_reg <= entropy_timeout_new;
+ end
+
+ if (entropy_timeout_ctr_we)
+ begin
+ entropy_timeout_ctr_reg <= entropy_timeout_ctr_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // mixer_api_logic
+ //----------------------------------------------------------------
+ always @*
+ begin : mixer_api_logic
+ enable_new = 0;
+ enable_we = 0;
+ restart_reg = 0;
+ restart_new = 0;
+ entropy_timeout_new = 24'h000000;
+ entropy_timeout_we = 0;
+ tmp_read_data = 32'h00000000;
+ tmp_error = 0;
+
+ if (cs)
+ begin
+ if (we)
+ begin
+ // Write operations.
+ case (address)
+ // Write operations.
+ ADDR_MIXER_CTRL:
+ begin
+ enable_new = write_data[MIXER_CTRL_ENABLE_BIT];
+ enable_we = 1;
+ restart_new = write_data[MIXER_CTRL_RESTART_BIT];
+ end
+
+ ADDR_MIXER_TIMEOUT:
+ begin
+ entropy_timeout_new = write_data[23 : 0];
+ entropy_timeout_we = 1;
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end // if (we)
+
+ else
+ begin
+ // Read operations.
+ case (address)
+ // Read operations.
+ ADDR_MIXER_CTRL:
+ begin
+ tmp_read_data = {30'h00000000, restart_reg, enable_reg};
+ end
+
+ ADDR_MIXER_STATUS:
+ begin
+ tmp_read_data = 32'h00000000;
+ end
+
+ ADDR_MIXER_TIMEOUT:
+ begin
+ tmp_read_data = {8'h00, entropy_timeout_reg};
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end
+ end
+ end // mixer_api_logic
+
+
+ //----------------------------------------------------------------
+ // entropy_collect_ctrl
+ //
+ // This FSM implements a round-robin mux for signals from the
+ // entropy sources and updates the block until a block has
+ // been filled.
+ //----------------------------------------------------------------
+ always @*
+ begin : entropy_mux
+ tmp_entropy0_ack = 0;
+ tmp_entropy1_ack = 0;
+ tmp_entropy2_ack = 0;
+ word_ctr_inc = 0;
+ word_ctr_rst = 0;
+ update_block = 0;
+ block_done = 0;
+ muxed_entropy = 32'h00000000;
+ entropy_timeout_ctr_inc = 0;
+ entropy_timeout_ctr_rst = 0;
+ entropy_collect_ctrl_new = ENTROPY_IDLE;
+ entropy_collect_ctrl_we = 0;
+
+ case (entropy_collect_ctrl_reg)
+ ENTROPY_IDLE:
+ begin
+ if (collect_block)
+ begin
+ word_ctr_rst = 1;
+ entropy_timeout_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC0;
+ entropy_collect_ctrl_we = 1;
+ end
+ end
+
+ ENTROPY_SRC0:
+ begin
+ if (!enable_reg)
+ begin
+ word_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_IDLE;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ if (entropy0_enabled)
+ begin
+ if (entropy0_syn)
+ begin
+ muxed_entropy = entropy0_data;
+ update_block = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC0_ACK;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ if (entropy_timeout)
+ begin
+ entropy_timeout_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC1;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ entropy_timeout_ctr_inc = 1;
+ end
+ end
+ else
+ begin
+ entropy_timeout_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC1;
+ entropy_collect_ctrl_we = 1;
+ end
+ end
+ end
+
+ ENTROPY_SRC0_ACK:
+ begin
+ tmp_entropy0_ack = 1;
+ if (!enable_reg)
+ begin
+ word_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_IDLE;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ if (word_ctr_reg == 5'h1f)
+ begin
+ block_done = 1;
+ entropy_collect_ctrl_new = ENTROPY_IDLE;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ word_ctr_inc = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC1;
+ entropy_collect_ctrl_we = 1;
+ end
+ end
+ end
+
+
+ ENTROPY_SRC1:
+ begin
+ if (!enable_reg)
+ begin
+ word_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_IDLE;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ if (entropy1_enabled)
+ begin
+ if (entropy1_syn)
+ begin
+ muxed_entropy = entropy1_data;
+ update_block = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC1_ACK;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ if (entropy_timeout)
+ begin
+ entropy_timeout_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC2;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ entropy_timeout_ctr_inc = 1;
+ end
+ end
+ else
+ begin
+ entropy_collect_ctrl_new = ENTROPY_SRC2;
+ entropy_collect_ctrl_we = 1;
+ end
+ end
+ end
+
+ ENTROPY_SRC1_ACK:
+ begin
+ tmp_entropy1_ack = 1;
+ if (!enable_reg)
+ begin
+ word_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_IDLE;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ if (word_ctr_reg == 5'h1f)
+ begin
+ block_done = 1;
+ entropy_collect_ctrl_new = ENTROPY_IDLE;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ word_ctr_inc = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC2;
+ entropy_collect_ctrl_we = 1;
+ end
+ end
+ end
+
+ ENTROPY_SRC2:
+ begin
+ if (!enable_reg)
+ begin
+ word_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_IDLE;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ if (entropy2_enabled)
+ begin
+ if (entropy2_syn)
+ begin
+ muxed_entropy = entropy2_data;
+ update_block = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC2_ACK;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ if (entropy_timeout)
+ begin
+ entropy_timeout_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC0;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ entropy_timeout_ctr_inc = 1;
+ end
+ end
+ else
+ begin
+ entropy_collect_ctrl_new = ENTROPY_SRC0;
+ entropy_collect_ctrl_we = 1;
+ end
+ end
+ end
+
+ ENTROPY_SRC2_ACK:
+ begin
+ tmp_entropy2_ack = 1;
+ if (!enable_reg)
+ begin
+ word_ctr_rst = 1;
+ entropy_collect_ctrl_new = ENTROPY_IDLE;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ if (word_ctr_reg == 5'h1f)
+ begin
+ block_done = 1;
+ entropy_collect_ctrl_new = ENTROPY_IDLE;
+ entropy_collect_ctrl_we = 1;
+ end
+ else
+ begin
+ word_ctr_inc = 1;
+ entropy_collect_ctrl_new = ENTROPY_SRC0;
+ entropy_collect_ctrl_we = 1;
+ end
+ end
+ end
+
+ endcase // case (entropy_collect_ctrl_reg)
+ end // entropy_mux
+
+
+ //----------------------------------------------------------------
+ // word_mux
+ //----------------------------------------------------------------
+ always @*
+ begin : word_mux
+ block00_we = 0;
+ block01_we = 0;
+ block02_we = 0;
+ block03_we = 0;
+ block04_we = 0;
+ block05_we = 0;
+ block06_we = 0;
+ block07_we = 0;
+ block08_we = 0;
+ block09_we = 0;
+ block10_we = 0;
+ block11_we = 0;
+ block12_we = 0;
+ block13_we = 0;
+ block14_we = 0;
+ block15_we = 0;
+ block16_we = 0;
+ block17_we = 0;
+ block18_we = 0;
+ block19_we = 0;
+ block20_we = 0;
+ block21_we = 0;
+ block22_we = 0;
+ block23_we = 0;
+ block24_we = 0;
+ block25_we = 0;
+ block26_we = 0;
+ block27_we = 0;
+ block28_we = 0;
+ block29_we = 0;
+ block30_we = 0;
+ block31_we = 0;
+
+ if (update_block)
+ begin
+ case (word_ctr_reg)
+ 00 : block00_we = 1;
+ 01 : block01_we = 1;
+ 02 : block02_we = 1;
+ 03 : block03_we = 1;
+ 04 : block04_we = 1;
+ 05 : block05_we = 1;
+ 06 : block06_we = 1;
+ 07 : block07_we = 1;
+ 08 : block08_we = 1;
+ 09 : block09_we = 1;
+ 10 : block10_we = 1;
+ 11 : block11_we = 1;
+ 12 : block12_we = 1;
+ 13 : block13_we = 1;
+ 14 : block14_we = 1;
+ 15 : block15_we = 1;
+ 16 : block16_we = 1;
+ 17 : block17_we = 1;
+ 18 : block18_we = 1;
+ 19 : block19_we = 1;
+ 20 : block20_we = 1;
+ 21 : block21_we = 1;
+ 22 : block22_we = 1;
+ 23 : block23_we = 1;
+ 24 : block24_we = 1;
+ 25 : block25_we = 1;
+ 26 : block26_we = 1;
+ 27 : block27_we = 1;
+ 28 : block28_we = 1;
+ 29 : block29_we = 1;
+ 30 : block30_we = 1;
+ 31 : block31_we = 1;
+ endcase // case (word_ctr_reg)
+ end
+ end // word_mux
+
+
+ //----------------------------------------------------------------
+ // entropy_timeout_logic
+ //
+ // Logic that updates the entropy timeout counter and signals
+ // when the wait for antropy from a provider has exceeded
+ // acceptable time.
+ //----------------------------------------------------------------
+ always @*
+ begin : entropy_timeout_logic
+ entropy_timeout_ctr_new = 24'h000000;
+ entropy_timeout_ctr_we = 0;
+ entropy_timeout = 0;
+
+ if (entropy_timeout_ctr_reg == entropy_timeout_reg)
+ begin
+ entropy_timeout = 1;
+ entropy_timeout_ctr_new = 24'h000000;
+ entropy_timeout_ctr_we = 1;
+ end
+
+ if (entropy_timeout_ctr_rst)
+ begin
+ entropy_timeout_ctr_new = 24'h000000;
+ entropy_timeout_ctr_we = 1;
+ end
+
+ if (entropy_timeout_ctr_inc)
+ begin
+ entropy_timeout_ctr_new = entropy_timeout_ctr_reg + 1'b1;
+ entropy_timeout_ctr_we = 1;
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // word_ctr
+ //----------------------------------------------------------------
+ always @*
+ begin : word_ctr
+ word_ctr_new = 5'h00;
+ word_ctr_we = 0;
+
+ if (word_ctr_rst)
+ begin
+ word_ctr_new = 5'h00;
+ word_ctr_we = 1;
+ end
+
+ if (word_ctr_inc)
+ begin
+ word_ctr_new = word_ctr_reg + 1'b1;
+ word_ctr_we = 1;
+ end
+ end // word_ctr
+
+
+ //----------------------------------------------------------------
+ // mixer_ctrl_fsm
+ //
+ // Control FSM for the mixer.
+ //----------------------------------------------------------------
+ always @*
+ begin : mixer_ctrl_fsm
+ seed_syn_new = 0;
+ seed_syn_we = 0;
+ init_done_new = 0;
+ init_done_we = 0;
+ hash_init = 0;
+ hash_next = 0;
+ collect_block = 0;
+ mixer_ctrl_new = CTRL_IDLE;
+ mixer_ctrl_we = 0;
+
+ case (mixer_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (more_seed)
+ begin
+ collect_block = 1;
+ init_done_new = 0;
+ init_done_we = 1;
+ mixer_ctrl_new = CTRL_COLLECT;
+ mixer_ctrl_we = 1;
+ end
+ end
+
+ CTRL_COLLECT:
+ begin
+ if ((discard))
+ begin
+ mixer_ctrl_new = CTRL_IDLE;
+ mixer_ctrl_we = 1;
+ end
+ else
+ begin
+ if (block_done)
+ begin
+ mixer_ctrl_new = CTRL_MIX;
+ mixer_ctrl_we = 1;
+ end
+ end
+ end
+
+ CTRL_MIX:
+ begin
+ if ((discard))
+ begin
+ mixer_ctrl_new = CTRL_IDLE;
+ mixer_ctrl_we = 1;
+ end
+ else
+ begin
+ if (init_done_reg)
+ begin
+ hash_next = 1;
+ end
+ else
+ begin
+ hash_init = 1;
+ end
+ mixer_ctrl_new = CTRL_SYN;
+ mixer_ctrl_we = 1;
+ end
+ end
+
+ CTRL_SYN:
+ begin
+ if ((discard))
+ begin
+ mixer_ctrl_new = CTRL_IDLE;
+ mixer_ctrl_we = 1;
+ end
+ else if (hash_ready)
+ begin
+ seed_syn_new = 1;
+ seed_syn_we = 1;
+ mixer_ctrl_new = CTRL_ACK;
+ mixer_ctrl_we = 1;
+ end
+
+ end
+
+ CTRL_ACK:
+ begin
+ if ((discard))
+ begin
+ mixer_ctrl_new = CTRL_IDLE;
+ mixer_ctrl_we = 1;
+ end
+ else if (seed_ack)
+ begin
+ seed_syn_new = 0;
+ seed_syn_we = 1;
+ mixer_ctrl_new = CTRL_NEXT;
+ mixer_ctrl_we = 1;
+ end
+ end
+
+ CTRL_NEXT:
+ begin
+ if ((discard))
+ begin
+ mixer_ctrl_new = CTRL_IDLE;
+ mixer_ctrl_we = 1;
+ end
+ else if (more_seed)
+ begin
+ collect_block = 1;
+ init_done_new = 1;
+ init_done_we = 1;
+ mixer_ctrl_new = CTRL_COLLECT;
+ mixer_ctrl_we = 1;
+ end
+ end
+
+ endcase // case (cspng_ctrl_reg)
+ end // mixer_ctrl_fsm
+
+endmodule // trng_mixer
+
+//======================================================================
+// EOF trng_mixer.v
+//======================================================================
diff --git a/eim/src/rtl/eim_indicator.v b/rng/trng/src/tb/fake_modules/pseudo_entropy.v
similarity index 54%
rename from eim/src/rtl/eim_indicator.v
rename to rng/trng/src/tb/fake_modules/pseudo_entropy.v
index cf9751d..bd7528b 100644
--- a/eim/src/rtl/eim_indicator.v
+++ b/rng/trng/src/tb/fake_modules/pseudo_entropy.v
@@ -1,18 +1,20 @@
//======================================================================
//
-// eim_indicator.v
-// ---------------
-// A simple LED indicator to show that the EIM is alive.
+// pseudo_entropy.v
+// ----------------
+// Fake pseudo entropy source. This module SHOULD ONLY be used
+// during simulation of the Cryptech True Random Number Generator
+// (trng). The module DOES NOT provide any real entropy.
//
//
-// Author: Pavel Shatov
-// Copyright (c) 2015, NORDUnet A/S All rights reserved.
+// Author: Joachim Strombergson
+// Copyright (c) 2014, NORDUnet A/S All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-// - Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
@@ -36,34 +38,35 @@
//
//======================================================================
-module eim_indicator
- (
- input wire sys_clk,
- input wire sys_rst,
- input wire eim_active,
- output wire led_out
- );
+module pseudo_entropy(
+ input wire clk,
+ input wire reset_n,
- //
- // Parameters
- //
- localparam CNT_BITS = 24; // led will be dim for 2**(24-1) = 8388608 ticks, which is ~100 ms @ 80 MHz.
+ input wire enable,
- //
- // Counter
- //
- reg [CNT_BITS-1:0] cnt;
+ output wire [31 : 0] raw_entropy,
+ output wire [31 : 0] stats,
- always @(posedge sys_clk)
- //
- if (sys_rst) cnt <= {CNT_BITS{1'b0}};
- else if (cnt > {CNT_BITS{1'b0}}) cnt <= cnt - 1'b1;
- else if (eim_active) cnt <= {CNT_BITS{1'b1}};
+ output wire enabled,
+ output wire entropy_syn,
+ output wire [31 : 0] entropy_data,
+ input wire entropy_ack
+ );
- assign led_out = ~cnt[CNT_BITS-1];
-endmodule
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign enabled = enable;
+
+ assign raw_entropy = enable ? 32'h00ff00ff : 32'h00000000;
+ assign stats = enable ? 32'hff00ff00 : 32'h00000000;
+
+ assign entropy_syn = enable;
+ assign entropy_data = enable ? 32'hf1e2d3c4 : 32'h00000000;
+
+endmodule // pseudo_entropy
//======================================================================
-// EOF eim_indicator.v
+// EOF pseudo_entropy.v
//======================================================================
diff --git a/rng/trng/src/tb/tb_csprng.v b/rng/trng/src/tb/tb_csprng.v
new file mode 100644
index 0000000..f860258
--- /dev/null
+++ b/rng/trng/src/tb/tb_csprng.v
@@ -0,0 +1,371 @@
+//======================================================================
+//
+// tb_csprng.v
+// -----------
+// Testbench for the csprng module in the trng.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_csprng();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 1;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg tb_clk;
+ reg tb_reset_n;
+
+ reg tb_cs;
+ reg tb_we;
+ reg [7 : 0] tb_address;
+ reg [31 : 0] tb_write_data;
+ wire [31 : 0] tb_read_data;
+ wire tb_error;
+
+ reg tb_discard;
+ reg tb_test_mode;
+
+ wire tb_ready;
+ wire tb_more_seed;
+ wire tb_security_error;
+ reg tb_seed_syn;
+ reg [511 : 0] tb_seed_data;
+ wire tb_seed_ack;
+ wire [31: 0] tb_rnd_data;
+ wire tb_rnd_syn;
+ reg tb_rnd_ack;
+
+ wire [7 : 0] tb_debug;
+ reg tb_debug_update;
+
+ reg [31 : 0] read_data;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ trng_csprng dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .cs(tb_cs),
+ .we(tb_we),
+ .address(tb_address),
+ .write_data(tb_write_data),
+ .read_data(tb_read_data),
+ .error(tb_error),
+
+ .discard(tb_discard),
+ .test_mode(tb_test_mode),
+
+ .more_seed(tb_more_seed),
+ .security_error(tb_security_error),
+
+ .seed_data(tb_seed_data),
+ .seed_syn(tb_seed_syn),
+ .seed_ack(tb_seed_ack),
+
+ .debug(tb_debug),
+ .debug_update(tb_debug_update)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Always running clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD;
+ tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor()
+ //
+ // An always running process that creates a cycle counter and
+ // conditionally displays information about the DUT.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ cycle_ctr = cycle_ctr + 1;
+
+ #(CLK_PERIOD);
+
+ if (DEBUG)
+ begin
+ dump_dut_state();
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state();
+ begin
+ $display("cycle: 0x%016x", cycle_ctr);
+ $display("State of DUT");
+ $display("------------");
+ $display("Inputs:");
+ $display("test_mode = 0x%01x, seed = 0x%01x, enable = 0x%01x",
+ dut.test_mode, dut.seed_reg, dut.enable_reg);
+ $display("num_rounds = 0x%02x, num_blocks = 0x%016x",
+ dut.num_rounds_reg, dut.num_blocks);
+ $display("seed_syn = 0x%01x, seed_ack = 0x%01x, seed_data = 0x%064x",
+ dut.seed_syn, dut.seed_ack, dut.seed_data);
+ $display("");
+
+ $display("Internal states:");
+ $display("cipher_key = 0x%032x", dut.cipher_key_reg);
+ $display("cipher_iv = 0x%08x, cipher_ctr = 0x%08x",
+ dut.cipher_iv_reg, dut.cipher_ctr_reg);
+ $display("cipher_block = 0x%064x", dut.cipher_block_reg);
+ $display("csprng_ctrl = 0x%02x", dut.csprng_ctrl_reg);
+ $display("");
+
+ $display("Cipher states:");
+ $display("cipher init: 0x%01x, cipher next: 0x%01x",
+ dut.cipher_inst.init, dut.cipher_inst.next);
+ $display("cipher ctrl: 0x%01x, qr ctr: 0x%01x, dr ctr: 0x%02x",
+ dut.cipher_inst.chacha_ctrl_reg, dut.cipher_inst.qr_ctr_reg,
+ dut.cipher_inst.dr_ctr_reg);
+ $display("cipher ready: 0x%01x, cipher data out valid: 0x%01x",
+ dut.cipher_inst.ready, dut.cipher_inst.data_out_valid);
+ $display("cipher data out: 0x%064x", dut.cipher_inst.data_out);
+ $display("");
+
+ $display("Outputs:");
+ $display("rnd_syn = 0x%01x, rnd_ack = 0x%01x, rnd_data = 0x%08x",
+ dut.rnd_syn, dut.rnd_ack, dut.rnd_data);
+ $display("");
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [11 : 0] address,
+ input [31 : 0] word);
+ begin
+ if (DEBUG)
+ begin
+ $display("*** Writing 0x%08x to 0x%02x.", word, address);
+ $display("");
+ end
+
+ tb_address = address;
+ tb_write_data = word;
+ tb_cs = 1;
+ tb_we = 1;
+ #(2 * CLK_PERIOD);
+ tb_cs = 0;
+ tb_we = 0;
+ end
+ endtask // write_word
+
+
+ //----------------------------------------------------------------
+ // read_word()
+ //
+ // Read a data word from the given address in the DUT.
+ // the word read will be available in the global variable
+ // read_data.
+ //----------------------------------------------------------------
+ task read_word(input [11 : 0] address);
+ begin
+ tb_address = address;
+ tb_cs = 1;
+ tb_we = 0;
+ #(CLK_PERIOD);
+ read_data = tb_read_data;
+ tb_cs = 0;
+
+ if (DEBUG)
+ begin
+ $display("*** Reading 0x%08x from 0x%02x.", read_data, address);
+ $display("");
+ end
+ end
+ endtask // read_word
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggle reset to put the DUT into a well known state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+
+ #(2 * CLK_PERIOD);
+ tb_reset_n = 1;
+ $display("");
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // display_test_results()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_results();
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %02d test cases completed successfully", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d tests completed - %02d test cases did not complete successfully.",
+ tc_ctr, error_ctr);
+ end
+ end
+ endtask // display_test_results
+
+
+ //----------------------------------------------------------------
+ // init_sim()
+ //
+ // Initialize all counters and testbed functionality as well
+ // as setting the DUT inputs to defined values.
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+
+ tb_cs = 0;
+ tb_we = 0;
+ tb_address = 8'h00;
+ tb_write_data = 32'h00000000;
+
+ tb_discard = 0;
+ tb_test_mode = 0;
+
+ tb_seed_syn = 0;
+ tb_seed_data = {16{32'h00000000}};
+ tb_rnd_ack = 0;
+ tb_debug_update = 0;
+ end
+ endtask // init_sim
+
+
+ //----------------------------------------------------------------
+ // tc1_test_init_cipher()
+ //
+ // TC1: Test that the DUT automatically starts initialize when
+ // enable is set.
+ //----------------------------------------------------------------
+ task tc1_test_init_cipher();
+ begin
+ $display("*** TC1: Test automatic init of cipher started.");
+ // tb_num_blocks = 64'h0000000000000004;
+ tb_seed_data = {8{64'haaaaaaaa55555555}};
+ // tb_num_rounds = 5'h08;
+ tb_rnd_ack = 1;
+
+ #(2000 * CLK_PERIOD);
+
+ $display("*** TC1: Test automatic init of cipher done.");
+
+ end
+ endtask // tc1_test_init_cipher
+
+
+ //----------------------------------------------------------------
+ // csprng_test
+ //
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : csprng_test
+
+ $display(" -= Testbench for csprng started =-");
+ $display(" ================================");
+ $display("");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+ // Test code goes here.
+ tc1_test_init_cipher();
+
+ display_test_results();
+
+ $display("");
+ $display("*** CSPRNG simulation done. ***");
+ $finish;
+ end // csprng_test
+endmodule // tb_csprng
+
+//======================================================================
+// EOF tb_csprng.v
+//======================================================================
diff --git a/rng/trng/src/tb/tb_mixer.v b/rng/trng/src/tb/tb_mixer.v
new file mode 100644
index 0000000..3964197
--- /dev/null
+++ b/rng/trng/src/tb/tb_mixer.v
@@ -0,0 +1,374 @@
+//======================================================================
+//
+// tb_mixer.v
+// -----------
+// Testbench for the mixer module in the trng.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_mixer();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 1;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg tb_clk;
+ reg tb_reset_n;
+ reg tb_enable;
+
+ reg tb_cs;
+ reg tb_we;
+ reg [7 : 0] tb_address;
+ reg [31 : 0] tb_write_data;
+ wire [31 : 0] tb_read_data;
+ wire tb_error;
+
+ reg tb_discard;
+ reg tb_test_mode;
+ reg tb_more_seed;
+ wire tb_security_error;
+
+ reg tb_entropy0_enabled;
+ reg tb_entropy0_syn;
+ reg [31 : 0] tb_entropy0_data;
+ wire tb_entropy0_ack;
+
+ reg tb_entropy1_enabled;
+ reg tb_entropy1_syn;
+ reg [31 : 0] tb_entropy1_data;
+ wire tb_entropy1_ack;
+
+ reg tb_entropy2_enabled;
+ reg tb_entropy2_syn;
+ reg [31 : 0] tb_entropy2_data;
+ wire tb_entropy2_ack;
+
+ wire [511 : 0] tb_seed_data;
+ wire tb_syn;
+ reg tb_ack;
+
+ reg [31 : 0] read_data;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ trng_mixer dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .cs(tb_cs),
+ .we(tb_we),
+ .address(tb_address),
+ .write_data(tb_write_data),
+ .read_data(tb_read_data),
+ .error(tb_error),
+
+ .discard(tb_discard),
+ .test_mode(tb_test_mode),
+ .security_error(tb_security_error),
+
+ .more_seed(tb_more_seed),
+
+ .entropy0_enabled(tb_entropy0_enabled),
+ .entropy0_syn(tb_entropy0_syn),
+ .entropy0_data(tb_entropy0_data),
+ .entropy0_ack(tb_entropy0_ack),
+
+ .entropy1_enabled(tb_entropy1_enabled),
+ .entropy1_syn(tb_entropy1_syn),
+ .entropy1_data(tb_entropy1_data),
+ .entropy1_ack(tb_entropy1_ack),
+
+ .entropy2_enabled(tb_entropy2_enabled),
+ .entropy2_syn(tb_entropy2_syn),
+ .entropy2_data(tb_entropy2_data),
+ .entropy2_ack(tb_entropy2_ack),
+
+ .seed_data(tb_seed_data),
+ .seed_syn(tb_syn),
+ .seed_ack(tb_ack)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Always running clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD;
+ tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor()
+ //
+ // An always running process that creates a cycle counter and
+ // conditionally displays information about the DUT.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ cycle_ctr = cycle_ctr + 1;
+
+ #(CLK_PERIOD);
+
+ if (DEBUG)
+ begin
+ dump_dut_state();
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state();
+ begin
+ $display("cycle: 0x%016x", cycle_ctr);
+ $display("State of DUT");
+ $display("------------");
+ $display("");
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [11 : 0] address,
+ input [31 : 0] word);
+ begin
+ if (DEBUG)
+ begin
+ $display("*** Writing 0x%08x to 0x%02x.", word, address);
+ $display("");
+ end
+
+ tb_address = address;
+ tb_write_data = word;
+ tb_cs = 1;
+ tb_we = 1;
+ #(2 * CLK_PERIOD);
+ tb_cs = 0;
+ tb_we = 0;
+ end
+ endtask // write_word
+
+
+ //----------------------------------------------------------------
+ // read_word()
+ //
+ // Read a data word from the given address in the DUT.
+ // the word read will be available in the global variable
+ // read_data.
+ //----------------------------------------------------------------
+ task read_word(input [11 : 0] address);
+ begin
+ tb_address = address;
+ tb_cs = 1;
+ tb_we = 0;
+ #(CLK_PERIOD);
+ read_data = tb_read_data;
+ tb_cs = 0;
+
+ if (DEBUG)
+ begin
+ $display("*** Reading 0x%08x from 0x%02x.", read_data, address);
+ $display("");
+ end
+ end
+ endtask // read_word
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggle reset to put the DUT into a well known state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+
+ #(2 * CLK_PERIOD);
+ tb_reset_n = 1;
+ $display("");
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // display_test_results()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_results();
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %02d test cases completed successfully", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d tests completed - %02d test cases did not complete successfully.",
+ tc_ctr, error_ctr);
+ end
+ end
+ endtask // display_test_results
+
+
+ //----------------------------------------------------------------
+ // init_sim()
+ //
+ // Initialize all counters and testbed functionality as well
+ // as setting the DUT inputs to defined values.
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+ tb_cs = 0;
+ tb_we = 0;
+ tb_address = 8'h00;
+ tb_write_data = 32'h00000000;
+
+ tb_discard = 0;
+ tb_test_mode = 0;
+ tb_more_seed = 0;
+
+ tb_entropy0_enabled = 0;
+ tb_entropy0_syn = 0;
+ tb_entropy0_data = 32'h00000000;
+
+ tb_entropy1_enabled = 0;
+ tb_entropy1_syn = 0;
+ tb_entropy1_data = 32'h00000000;
+
+ tb_entropy2_enabled = 0;
+ tb_entropy2_syn = 0;
+ tb_entropy2_data = 32'h00000000;
+
+ tb_ack = 0;
+ end
+ endtask // init_sim
+
+
+ //----------------------------------------------------------------
+ // tc1_gen_seeds()
+ //
+ // A simple first testcase that tries to make the DUT generate
+ // a number of seeds based on entropy from source 0 and 2.
+ //----------------------------------------------------------------
+ task tc1_gen_seeds();
+ begin
+ $display("*** Starting TC1: Setting continious seed generation.");
+ tb_entropy0_enabled = 1;
+ tb_entropy0_syn = 1;
+ tb_entropy0_data = 32'h01010202;
+
+ tb_entropy2_enabled = 1;
+ tb_entropy2_syn = 1;
+ tb_entropy2_data = 32'haa55aa55;
+
+ tb_enable = 1;
+ tb_more_seed = 1;
+ tb_ack = 1;
+
+ #(50000 * CLK_PERIOD);
+ $display("*** TC1 done.");
+ end
+ endtask // tc1_gen_seeds
+
+
+ //----------------------------------------------------------------
+ // mixer_test
+ //
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : mixer_test
+
+ $display(" -= Testbench for mixer started =-");
+ $display(" ================================");
+ $display("");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+ tc1_gen_seeds();
+
+ display_test_results();
+
+ $display("");
+ $display("*** Mixer simulation done. ***");
+ $finish;
+ end // mixer_test
+endmodule // tb_mixer
+
+//======================================================================
+// EOF tb_mixer.v
+//======================================================================
diff --git a/rng/trng/src/tb/tb_trng.v b/rng/trng/src/tb/tb_trng.v
new file mode 100644
index 0000000..38d2559
--- /dev/null
+++ b/rng/trng/src/tb/tb_trng.v
@@ -0,0 +1,377 @@
+//======================================================================
+//
+// tb_trng.v
+// -----------
+// Testbench for the trng module in the trng.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_trng();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 1;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+ // The DUT address map.
+ parameter TRNG_PREFIX = 4'h0;
+ parameter ENTROPY1_PREFIX = 4'h5;
+ parameter ENTROPY2_PREFIX = 4'h6;
+ parameter MIXER_PREFIX = 4'ha;
+ parameter CSPRNG_PREFIX = 4'hb;
+
+ parameter ADDR_TRNG_CTRL = 8'h10;
+ parameter TRNG_CTRL_ENABLE_BIT = 0;
+ parameter TRNG_CTRL_ENT0_ENABLE_BIT = 1;
+ parameter TRNG_CTRL_ENT1_ENABLE_BIT = 2;
+ parameter TRNG_CTRL_ENT2_ENABLE_BIT = 3;
+ parameter TRNG_CTRL_SEED_BIT = 8;
+
+ parameter ADDR_TRNG_STATUS = 8'h11;
+
+ parameter ADDR_TRNG_RND_DATA = 8'h20;
+ parameter ADDR_TRNG_RND_DATA_VALID = 8'h21;
+ parameter TRNG_RND_VALID_BIT = 0;
+
+ parameter ADDR_CSPRNG_CTRL = 8'h10;
+ parameter CSPRNG_CTRL_ENABLE_BIT = 0;
+ parameter CSPRNG_CTRL_SEED_BIT = 1;
+
+ parameter ADDR_CSPRNG_STATUS = 8'h11;
+ parameter CSPRNG_STATUS_RND_VALID_BIT = 0;
+
+ parameter ADDR_CSPRNG_NUM_ROUNDS = 8'h40;
+ parameter ADDR_CSPRNG_NUM_BLOCKS_LOW = 8'h41;
+ parameter ADDR_CSPRNG_NUM_BLOCKS_HIGH = 8'h42;
+
+ parameter ADDR_ENTROPY0_RAW = 8'h40;
+ parameter ADDR_ENTROPY0_STATS = 8'h41;
+
+ parameter ADDR_ENTROPY1_RAW = 8'h50;
+ parameter ADDR_ENTROPY1_STATS = 8'h51;
+
+ parameter ADDR_ENTROPY2_RAW = 8'h60;
+ parameter ADDR_ENTROPY2_STATS = 8'h61;
+
+ parameter ADDR_MIXER_CTRL = 8'h10;
+ parameter MIXER_CTRL_ENABLE_BIT = 0;
+ parameter MIXER_CTRL_RESTART_BIT = 1;
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg [31 : 0] read_data;
+
+ reg tb_clk;
+ reg tb_reset_n;
+ reg tb_avalanche_noise;
+ reg tb_cs;
+ reg tb_we;
+ reg [11 : 0] tb_address;
+ reg [31 : 0] tb_write_data;
+ wire [31 : 0] tb_read_data;
+ wire [7 : 0] tb_debug;
+ reg tb_debug_update;
+ wire tb_error;
+ wire tb_security_error;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ trng dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+ .avalanche_noise(tb_avalanche_noise),
+ .cs(tb_cs),
+ .we(tb_we),
+ .address(tb_address),
+ .write_data(tb_write_data),
+ .read_data(tb_read_data),
+ .error(tb_error),
+ .debug(tb_debug),
+ .debug_update(tb_debug_update),
+ .security_error(tb_security_error)
+ );
+
+
+ //----------------------------------------------------------------
+ // Concurrent assignments.
+ //----------------------------------------------------------------
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Always running clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD;
+ tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor()
+ //
+ // An always running process that creates a cycle counter and
+ // conditionally displays information about the DUT.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ cycle_ctr = cycle_ctr + 1;
+
+ #(CLK_PERIOD);
+
+ if (DEBUG)
+ begin
+ dump_dut_state();
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state();
+ begin
+ $display("cycle: 0x%016x", cycle_ctr);
+ $display("State of DUT");
+ $display("------------");
+ $display("");
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [11 : 0] address,
+ input [31 : 0] word);
+ begin
+ if (DEBUG)
+ begin
+ $display("*** Writing 0x%08x to 0x%02x.", word, address);
+ $display("");
+ end
+
+ tb_address = address;
+ tb_write_data = word;
+ tb_cs = 1;
+ tb_we = 1;
+ #(2 * CLK_PERIOD);
+ tb_cs = 0;
+ tb_we = 0;
+ end
+ endtask // write_word
+
+
+ //----------------------------------------------------------------
+ // read_word()
+ //
+ // Read a data word from the given address in the DUT.
+ // the word read will be available in the global variable
+ // read_data.
+ //----------------------------------------------------------------
+ task read_word(input [11 : 0] address);
+ begin
+ tb_address = address;
+ tb_cs = 1;
+ tb_we = 0;
+ #(CLK_PERIOD);
+ read_data = tb_read_data;
+ tb_cs = 0;
+
+ if (DEBUG)
+ begin
+ $display("*** Reading 0x%08x from 0x%02x.", read_data, address);
+ $display("");
+ end
+ end
+ endtask // read_word
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggle reset to put the DUT into a well known state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+
+ #(2 * CLK_PERIOD);
+ tb_reset_n = 1;
+ $display("");
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // display_test_results()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_results();
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %02d test cases completed successfully", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d tests completed - %02d test cases did not complete successfully.",
+ tc_ctr, error_ctr);
+ end
+ end
+ endtask // display_test_results
+
+
+ //----------------------------------------------------------------
+ // init_sim()
+ //
+ // Initialize all counters and testbed functionality as well
+ // as setting the DUT inputs to defined values.
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+
+ tb_avalanche_noise = 0;
+ tb_cs = 0;
+ tb_we = 0;
+ tb_address = 12'h000;
+ tb_write_data = 32'h00000000;
+ tb_debug_update = 0;
+ end
+ endtask // init_sim
+
+
+ //----------------------------------------------------------------
+ // tc1_gen_rnd()
+ //
+ // A simple first testcase that tries to make the DUT generate
+ // a number of random values.
+ //----------------------------------------------------------------
+ task tc1_gen_rnd();
+ reg [31 : 0] i;
+
+ begin
+ $display("*** Starting TC1: Generating random values from entropy.");
+
+ tb_debug_update = 1;
+
+ #(10 * CLK_PERIOD);
+
+ // Enable the csprng and the mixer
+ write_word({CSPRNG_PREFIX, ADDR_CSPRNG_CTRL}, 32'h00000001);
+ write_word({MIXER_PREFIX, ADDR_MIXER_CTRL}, 32'h00000001);
+
+
+ // We try to change number of blocks to a low value to force reseeding.
+ write_word({CSPRNG_PREFIX, ADDR_CSPRNG_NUM_BLOCKS_LOW}, 32'h00000002);
+ write_word({CSPRNG_PREFIX, ADDR_CSPRNG_NUM_BLOCKS_HIGH}, 32'h00000000);
+
+ #(100 * CLK_PERIOD);
+
+ i = 0;
+ while (i < 100000)
+ begin
+ $display("Reading rnd word %08x.", i);
+ i = i + 1;
+ read_word({CSPRNG_PREFIX, ADDR_TRNG_RND_DATA});
+ #(2 * CLK_PERIOD);
+ end
+
+ $display("*** TC1 done.");
+ end
+ endtask // tc1_gen_seeds
+
+
+ //----------------------------------------------------------------
+ // trng_test
+ //
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : trng_test
+
+ $display(" -= Testbench for TRNG started =-");
+ $display(" ===============================");
+ $display("");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+ tc1_gen_rnd();
+
+ display_test_results();
+
+ $display("");
+ $display("*** TRNG simulation done. ***");
+ $finish;
+ end // trng_test
+endmodule // tb_trng
+
+//======================================================================
+// EOF tb_trng.v
+//======================================================================
diff --git a/rng/trng/toolruns/Makefile b/rng/trng/toolruns/Makefile
new file mode 100644
index 0000000..92f2f20
--- /dev/null
+++ b/rng/trng/toolruns/Makefile
@@ -0,0 +1,103 @@
+#===================================================================
+#
+# Makefile
+# --------
+# Makefile for building the TRNG modules and and top simulations.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2014, NORDUnet A/S All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# - Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# - Neither the name of the NORDUnet nor the names of its contributors may
+# be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#===================================================================
+
+CHACHA_SRC=../../chacha/src/rtl/chacha_core.v ../../chacha/src/rtl/chacha_qr.v
+CSPRNG_SRC=../src/rtl/trng_csprng.v ../src/rtl/trng_csprng_fifo.v
+TB_CSPRNG_SRC=../src/tb/tb_csprng.v
+
+SHA512_SRC=../../sha512/src/rtl/sha512_core.v ../../sha512/src/rtl/sha512_h_constants.v ../../sha512/src/rtl/sha512_k_constants.v ../../sha512/src/rtl/sha512_w_mem.v
+MIXER_SRC=../src/rtl/trng_mixer.v
+TB_MIXER_SRC=../src/tb/tb_mixer.v
+
+TRNG_SRC=../src/rtl/trng.v $(MIXER_SRC) $(SHA512_SRC) $(CSPRNG_SRC) $(CHACHA_SRC)
+TB_TRNG_SRC=../src/tb/tb_trng.v
+FAKE_ENTROPY_SRC=../src/tb/fake_modules/avalanche_entropy.v ../src/tb/fake_modules/pseudo_entropy.v ../src/tb/fake_modules/rosc_entropy.v
+
+CC=iverilog
+
+
+all: trng.sim mixer.sim csprng.sim
+
+
+csprng.sim: $(TB_CSPRNG_SRC) $(CSPRNG_SRC) $(CHACHA_SRC)
+ $(CC) -o csprng.sim $(TB_CSPRNG_SRC) $(CSPRNG_SRC) $(CHACHA_SRC)
+
+
+mixer.sim: $(TB_MIXER_SRC) $(MIXER_SRC) $(SHA512_SRC)
+ $(CC) -o mixer.sim $(TB_MIXER_SRC) $(MIXER_SRC) $(SHA512_SRC)
+
+
+trng.sim: $(TRNG_SRC) $(FAKE_ENTROPY_SRC)
+ $(CC) -o trng.sim $(TB_TRNG_SRC) $(TRNG_SRC) $(FAKE_ENTROPY_SRC)
+
+
+sim-csprng: csprng.sim
+ ./csprng.sim
+
+
+sim-mixer: mixer.sim
+ ./mixer.sim
+
+
+sim-trng: trng.sim
+ ./trng.sim
+
+
+clean:
+ rm -f csprng.sim
+ rm -f mixer.sim
+ rm -f trng.sim
+
+
+help:
+ @echo "Build system for simulation of TRNG core"
+ @echo ""
+ @echo "Supported targets:"
+ @echo "------------------"
+ @echo "all: Build all simulation targets."
+ @echo "csprng.sim: Build the csprng simulation target."
+ @echo "mixer.sim: Build the mixer simulation target."
+ @echo "trng.sim: Build the trng simulation target."
+ @echo "sim-csprng: Run cprng simulation."
+ @echo "sim-mixer: Run mixer simulation."
+ @echo "sim-trng: Run trng simulation."
+ @echo "clean: Delete all built files."
+
+#===================================================================
+# EOF Makefile
+#===================================================================
diff --git a/rng/trng/toolruns/quartus/terasic_de0_nano/trng.qpf b/rng/trng/toolruns/quartus/terasic_de0_nano/trng.qpf
new file mode 100644
index 0000000..1902c4f
--- /dev/null
+++ b/rng/trng/toolruns/quartus/terasic_de0_nano/trng.qpf
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+#
+# Copyright (C) 1991-2014 Altera Corporation
+# Your use of Altera Corporation's design tools, logic functions
+# and other software and tools, and its AMPP partner logic
+# functions, and any output files from any of the foregoing
+# (including device programming or simulation files), and any
+# associated documentation or information are expressly subject
+# to the terms and conditions of the Altera Program License
+# Subscription Agreement, Altera MegaCore Function License
+# Agreement, or other applicable license agreement, including,
+# without limitation, that your use is for the sole purpose of
+# programming logic devices manufactured by Altera and sold by
+# Altera or its authorized distributors. Please refer to the
+# applicable agreement for further details.
+#
+# -------------------------------------------------------------------------- #
+#
+# Quartus II 64-Bit
+# Version 13.1.2 Build 173 01/15/2014 SJ Web Edition
+# Date created = 14:45:00 September 18, 2014
+#
+# -------------------------------------------------------------------------- #
+
+QUARTUS_VERSION = "13.1"
+DATE = "14:45:00 September 18, 2014"
+
+# Revisions
+
+PROJECT_REVISION = "trng"
diff --git a/rng/trng/toolruns/quartus/terasic_de0_nano/trng.qsf b/rng/trng/toolruns/quartus/terasic_de0_nano/trng.qsf
new file mode 100644
index 0000000..f1767e0
--- /dev/null
+++ b/rng/trng/toolruns/quartus/terasic_de0_nano/trng.qsf
@@ -0,0 +1,90 @@
+# -------------------------------------------------------------------------- #
+#
+# Copyright (C) 1991-2014 Altera Corporation
+# Your use of Altera Corporation's design tools, logic functions
+# and other software and tools, and its AMPP partner logic
+# functions, and any output files from any of the foregoing
+# (including device programming or simulation files), and any
+# associated documentation or information are expressly subject
+# to the terms and conditions of the Altera Program License
+# Subscription Agreement, Altera MegaCore Function License
+# Agreement, or other applicable license agreement, including,
+# without limitation, that your use is for the sole purpose of
+# programming logic devices manufactured by Altera and sold by
+# Altera or its authorized distributors. Please refer to the
+# applicable agreement for further details.
+#
+# -------------------------------------------------------------------------- #
+#
+# Quartus II 64-Bit
+# Version 13.1.2 Build 173 01/15/2014 SJ Web Edition
+# Date created = 14:45:00 September 18, 2014
+#
+# -------------------------------------------------------------------------- #
+#
+# Notes:
+#
+# 1) The default values for assignments are stored in the file:
+# trng_assignment_defaults.qdf
+# If this file doesn't exist, see file:
+# assignment_defaults.qdf
+#
+# 2) Altera recommends that you do not modify this file. This
+# file is updated automatically by the Quartus II software
+# and any changes you make may be lost or overwritten.
+#
+# -------------------------------------------------------------------------- #
+
+
+set_global_assignment -name FAMILY "Cyclone IV E"
+set_global_assignment -name DEVICE EP4CE22F17C6
+set_global_assignment -name TOP_LEVEL_ENTITY trng
+set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
+set_global_assignment -name PROJECT_CREATION_TIME_DATE "14:45:00 SEPTEMBER 18, 2014"
+set_global_assignment -name LAST_QUARTUS_VERSION 13.1
+set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
+set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
+set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
+set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
+set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
+set_instance_assignment -name IO_STANDARD "2.5 V" -to clk
+set_location_assignment PIN_R8 -to clk
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to reset_n
+set_location_assignment PIN_J15 -to reset_n
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to debug[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to debug[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to debug[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to debug[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to debug[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to debug[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to debug[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to debug[7]
+set_location_assignment PIN_A15 -to debug[0]
+set_location_assignment PIN_A13 -to debug[1]
+set_location_assignment PIN_B13 -to debug[2]
+set_location_assignment PIN_A11 -to debug[3]
+set_location_assignment PIN_D1 -to debug[4]
+set_location_assignment PIN_F3 -to debug[5]
+set_location_assignment PIN_B1 -to debug[6]
+set_location_assignment PIN_L3 -to debug[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to debug_update
+set_location_assignment PIN_E1 -to debug_update
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to avalanche_noise
+set_location_assignment PIN_D3 -to avalanche_noise
+set_global_assignment -name VERILOG_FILE ../../../../avalanche_entropy/src/rtl/avalanche_entropy_core.v
+set_global_assignment -name VERILOG_FILE ../../../../avalanche_entropy/src/rtl/avalanche_entropy.v
+set_global_assignment -name VERILOG_FILE ../../../../rosc_entropy/src/rtl/rosc_entropy.v
+set_global_assignment -name VERILOG_FILE ../../../../rosc_entropy/src/rtl/rosc.v
+set_global_assignment -name VERILOG_FILE ../../../../rosc_entropy/src/rtl/rosc_entropy_core.v
+set_global_assignment -name VERILOG_FILE ../../../../sha512/src/rtl/sha512_w_mem.v
+set_global_assignment -name VERILOG_FILE ../../../../sha512/src/rtl/sha512_k_constants.v
+set_global_assignment -name VERILOG_FILE ../../../../sha512/src/rtl/sha512_h_constants.v
+set_global_assignment -name VERILOG_FILE ../../../../sha512/src/rtl/sha512_core.v
+set_global_assignment -name VERILOG_FILE ../../../../chacha/src/rtl/chacha_qr.v
+set_global_assignment -name VERILOG_FILE ../../../../chacha/src/rtl/chacha_core.v
+set_global_assignment -name VERILOG_FILE ../../../src/rtl/trng_mixer.v
+set_global_assignment -name VERILOG_FILE ../../../src/rtl/trng_csprng_fifo.v
+set_global_assignment -name VERILOG_FILE ../../../src/rtl/trng_csprng.v
+set_global_assignment -name VERILOG_FILE ../../../src/rtl/trng.v
+set_global_assignment -name SDC_FILE trng.sdc
+set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
\ No newline at end of file
diff --git a/rng/trng/toolruns/quartus/terasic_de0_nano/trng.sdc b/rng/trng/toolruns/quartus/terasic_de0_nano/trng.sdc
new file mode 100644
index 0000000..eac8536
--- /dev/null
+++ b/rng/trng/toolruns/quartus/terasic_de0_nano/trng.sdc
@@ -0,0 +1,40 @@
+#************************************************************
+# THIS IS A WIZARD-GENERATED FILE.
+#
+# Version 13.1.2 Build 173 01/15/2014 SJ Web Edition
+#
+#************************************************************
+
+# Copyright (C) 1991-2014 Altera Corporation
+# Your use of Altera Corporation's design tools, logic functions
+# and other software and tools, and its AMPP partner logic
+# functions, and any output files from any of the foregoing
+# (including device programming or simulation files), and any
+# associated documentation or information are expressly subject
+# to the terms and conditions of the Altera Program License
+# Subscription Agreement, Altera MegaCore Function License
+# Agreement, or other applicable license agreement, including,
+# without limitation, that your use is for the sole purpose of
+# programming logic devices manufactured by Altera and sold by
+# Altera or its authorized distributors. Please refer to the
+# applicable agreement for further details.
+
+
+
+# Clock constraints
+
+create_clock -name "clk" -period 20.000ns [get_ports {clk}] -waveform {0.000 10.000}
+
+
+# Automatically constrain PLL and other generated clocks
+derive_pll_clocks -create_base_clocks
+
+# Automatically calculate clock uncertainty to jitter and other effects.
+derive_clock_uncertainty
+
+# tsu/th constraints
+
+# tco constraints
+
+# tpd constraints
+
diff --git a/rng/trng/toolruns/quartus/terasic_de0_nano/trng.sof b/rng/trng/toolruns/quartus/terasic_de0_nano/trng.sof
new file mode 100644
index 0000000..b4b39d9
Binary files /dev/null and b/rng/trng/toolruns/quartus/terasic_de0_nano/trng.sof differ
diff --git a/rng/vndecorrelator/LICENSE.txt b/rng/vndecorrelator/LICENSE.txt
new file mode 100644
index 0000000..b70e7ad
--- /dev/null
+++ b/rng/vndecorrelator/LICENSE.txt
@@ -0,0 +1,27 @@
+Copyright (c) 2014, NORDUnet A/S All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+- Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+- Neither the name of the NORDUnet nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/rng/vndecorrelator/README.md b/rng/vndecorrelator/README.md
new file mode 100644
index 0000000..33d20aa
--- /dev/null
+++ b/rng/vndecorrelator/README.md
@@ -0,0 +1,20 @@
+vndecorrelator
+==============
+
+A Verilog implementation of a von Neumann decorrelator.
+
+This tiny module consumes pairs of bits and generates decorrelated
+bits. Basically given a sequence of two bits, the decorrelator will:
+
+0, 1: Emit 1
+1, 0: Emit 0
+0, 0: Emit nothing
+1, 1: Emit nothing
+
+The rate of bits emitted is thus at most half of the bitrate on the
+input.
+
+The module is synchronous, but bits may arrive a number of cycles
+between eachother. The module will set the syn_out flag during one cycle
+to signal that the value in data_out is a valid bit.
+
diff --git a/rng/vndecorrelator/src/rtl/vndecorrelator.v b/rng/vndecorrelator/src/rtl/vndecorrelator.v
new file mode 100644
index 0000000..a327fb9
--- /dev/null
+++ b/rng/vndecorrelator/src/rtl/vndecorrelator.v
@@ -0,0 +1,164 @@
+//======================================================================
+//
+// vndecorrelator.v
+// ----------------
+// von Neumann decorrelator for bits. The module consumes bits
+// and for every two bits consume will either emit zero or one bits.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module vndecorrelator(
+ input wire clk,
+ input wire reset_n,
+
+ input wire data_in,
+ input wire syn_in,
+
+ output wire data_out,
+ output wire syn_out
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter CTRL_IDLE = 1'b0;
+ parameter CTRL_BITS = 1'b1;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg data_in_reg;
+ reg data_in_we;
+
+ reg data_out_reg;
+ reg data_out_we;
+
+ reg syn_out_reg;
+ reg syn_out_new;
+
+ reg vndecorr_ctrl_reg;
+ reg vndecorr_ctrl_new;
+ reg vndecorr_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign data_out = data_out_reg;
+ assign syn_out = syn_out_reg;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ data_in_reg <= 1'b0;
+ data_out_reg <= 1'b0;
+ syn_out_reg <= 1'b0;
+ vndecorr_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ syn_out_reg <= syn_out_new;
+
+ if (data_in_we)
+ begin
+ data_in_reg <= data_in;
+ end
+
+ if (data_out_we)
+ begin
+ data_out_reg <= data_in;
+ end
+
+ if (vndecorr_ctrl_we)
+ begin
+ vndecorr_ctrl_reg <= vndecorr_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // vndecorr_logic
+ //
+ // The logic implementing the von Neumann decorrelator by waiting
+ // for subsequent bits and comparing them to determine if both
+ // bits should just be discarded or one of them also emitted.
+ //----------------------------------------------------------------
+ always @*
+ begin : vndecorr_logic
+ data_in_we = 1'b0;
+ data_out_we = 1'b0;
+ syn_out_new = 1'b0;
+ vndecorr_ctrl_new = CTRL_IDLE;
+ vndecorr_ctrl_we = 1'b0;
+
+ case (vndecorr_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (syn_in)
+ begin
+ data_in_we = 1'b1;
+ vndecorr_ctrl_new = CTRL_BITS;
+ vndecorr_ctrl_we = 1'b1;
+ end
+ end
+
+ CTRL_BITS:
+ begin
+ if (syn_in)
+ begin
+ if (data_in != data_in_reg)
+ begin
+ data_out_we = 1'b1;
+ syn_out_new = 1'b1;
+ end
+
+ vndecorr_ctrl_new = CTRL_IDLE;
+ vndecorr_ctrl_we = 1'b1;
+ end
+ end
+ endcase // case (vndecorr_ctrl_reg)
+ end // vndecorr_logic
+
+endmodule // vndecorrelator
+
+//======================================================================
+// EOF vndecorrelator.v
+//======================================================================
diff --git a/rng/vndecorrelator/src/tb/tb_vndecorrelator.v b/rng/vndecorrelator/src/tb/tb_vndecorrelator.v
new file mode 100644
index 0000000..742476a
--- /dev/null
+++ b/rng/vndecorrelator/src/tb/tb_vndecorrelator.v
@@ -0,0 +1,277 @@
+//======================================================================
+//
+// tb_vndecorrelator.v
+// -------------------
+// Testbench for the von Neumann decorrelator.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_vndecorrelator();
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 1;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg tb_clk;
+ reg tb_reset_n;
+ reg tb_data_in;
+ reg tb_syn_in;
+ wire tb_data_out;
+ wire tb_syn_out;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ vndecorrelator dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .data_in(tb_data_in),
+ .syn_in(tb_syn_in),
+
+ .data_out(tb_data_out),
+ .syn_out(tb_syn_out)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Always running clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD;
+ tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //--------------------------------------------------------------------
+ // dut_monitor
+ //
+ // Monitor displaying information every cycle.
+ // Includes the cycle counter.
+ //--------------------------------------------------------------------
+ always @ (posedge tb_clk)
+ begin : dut_monitor
+ cycle_ctr = cycle_ctr + 1;
+
+ if (DEBUG)
+ begin
+ $display("cycle = %016x:", cycle_ctr);
+ $display("reset_n = 0x%01x", dut.reset_n);
+ $display("data_in = 0x%01x, syn_in = 0x%01x", dut.data_in, dut.syn_in);
+ $display("data_out = 0x%01x, syn_out = 0x%01x", dut.data_out, dut.syn_out);
+ $display("ctrl = 0x%01x", dut.vndecorr_ctrl_reg);
+ $display("");
+ end
+ end // dut_monitor
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggle reset to put the DUT into a well known state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(2 * CLK_PERIOD);
+ tb_reset_n = 1;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // init_sim()
+ //
+ // Initialize all counters and testbed functionality as well
+ // as setting the DUT inputs to defined values.
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+ tb_data_in = 0;
+ tb_syn_in = 0;
+ end
+ endtask // init_sim
+
+
+ //----------------------------------------------------------------
+ // decorrelation_test
+ //
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : decorrelation_test
+ $display(" -= Testbench for the vpn Neumann decorrelator =-");
+ $display(" ===============================================");
+ $display("");
+
+ init_sim();
+ reset_dut();
+
+ // TC1: 1, 0 directly after eachother. Should emit 0.
+ #(10 *CLK_PERIOD);
+ $display("TC1: 1 directly followed by 0. Should emit 0.");
+ tb_data_in = 1;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_data_in = 0;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+
+ // TC2: 0, 1 directly after eachother. Should generate 1.
+ #(10 *CLK_PERIOD);
+ $display("TC2: 0 directly followed by 1. Should emit 1.");
+ tb_data_in = 0;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_data_in = 1;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+
+ // TC3: 0, 0 directly after eachother. Should emit nothing.
+ #(10 *CLK_PERIOD);
+ $display("TC3: 0 directly followed by 0. Should emit nothing.");
+ tb_data_in = 0;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_data_in = 0;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+
+ // TC4: 1, 1 directly after eachother. Should enmit nothing.
+ #(10 *CLK_PERIOD);
+ $display("TC4: 1 directly followed by 1. Should emit nothing.");
+ tb_data_in = 1;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_data_in = 1;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+
+ // TC5: 1, 0 with 10 cycles in between. Should emit 0.
+ #(10 *CLK_PERIOD);
+ $display("TC5: 1 and later 0. Should emit 0.");
+ tb_data_in = 1;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+ #(10 *CLK_PERIOD);
+ tb_data_in = 0;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+
+ // TC6: 0, 1 with 10 cycles in between. Should emit 1.
+ #(10 *CLK_PERIOD);
+ $display("TC6: 0 and later 1. Should emit 1.");
+ tb_data_in = 0;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+ #(10 *CLK_PERIOD);
+ tb_data_in = 1;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+
+ // TC7: 0, 0 with 10 cycles in between. Should emit nothing.
+ #(10 *CLK_PERIOD);
+ $display("TC7: 0 and later 0. Should emit nothing.");
+ tb_data_in = 0;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+ #(10 *CLK_PERIOD);
+ tb_data_in = 0;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+
+ // TC8: 1, 1 with 10 cycles in between. Should emit nothing.
+ #(10 *CLK_PERIOD);
+ $display("TC8: 1 and later 1. Should emit nothing.");
+ tb_data_in = 1;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+ #(10 *CLK_PERIOD);
+ tb_data_in = 1;
+ tb_syn_in = 1;
+ #(CLK_PERIOD);
+ tb_syn_in = 0;
+
+ $display("");
+ $display("*** von Neumann decorrelation simulation done. ***");
+ $finish;
+ end // decorrelation_test
+endmodule // tb_vndecorrelator
+
+//======================================================================
+// EOF tb_vndecorrelator.v
+//======================================================================
diff --git a/rng/vndecorrelator/toolruns/Makefile b/rng/vndecorrelator/toolruns/Makefile
new file mode 100644
index 0000000..b966ccf
--- /dev/null
+++ b/rng/vndecorrelator/toolruns/Makefile
@@ -0,0 +1,69 @@
+#===================================================================
+#
+# Makefile
+# --------
+# Makefile for building von Neumann decorrelation simulation.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2014, NORDUnet A/S All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# - Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# - Neither the name of the NORDUnet nor the names of its contributors may
+# be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#===================================================================
+
+CORE_SRC=../src/rtl/vndecorrelator.v
+TB_SRC=../src/tb/tb_vndecorrelator.v
+
+CC=iverilog
+
+
+all: vntest.sim
+
+
+vntest.sim: $(TB_SRC) $(CORE_SRC)
+ $(CC) -o vntest.sim $(TB_SRC) $(CORE_SRC)
+
+
+sim-core: vntest.sim
+ ./vntest.sim
+
+
+help:
+ @echo "Supported targets:"
+ @echo "------------------"
+ @echo "all: Build all simulation targets."
+ @echo "vntest.sim Build the core simulation target."
+ @echo "sim-core: Run core level simulation."
+
+clean:
+ rm vntest.sim
+
+
+#===================================================================
+# EOF Makefile
+#===================================================================
More information about the Commits
mailing list