[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