[Cryptech-Commits] [user/paul/core] 01/01: Reorganize 'core' source tree.
git at cryptech.is
git at cryptech.is
Wed Feb 18 19:21:09 UTC 2015
This is an automated email from the git hooks/post-receive script.
paul at psgd.org pushed a commit to branch master
in repository user/paul/core.
commit f117851934d38aae0862ec05c10a4c101fc7fbf5
Author: Paul Selkirk <paul at psgd.org>
Date: Wed Feb 18 14:19:35 2015 -0500
Reorganize 'core' source tree.
- Promote eim to top level, along with uart and i2c.
- Put all the Novena specifics in novena repo (eim is generic-ish),
and build both i2c and eim bitfiles and testers out of novena.
- Replace coretest_hashes with Pavel's core_selector.
- Replace Joachim's sha wrappers with my test versions.
---
core_selector/src/rtl/cipher_selector.v | 117 ++
core_selector/src/rtl/core_selector.v | 182 +++
core_selector/src/rtl/hash_selector.v | 264 +++++
core_selector/src/rtl/rng_selector.v | 112 ++
coretest/LICENSE | 24 +
coretest/README.md | 176 +++
coretest/src/rtl/coretest.v | 1209 ++++++++++++++++++++
coretest/src/sw/seriedebug.py | 118 ++
coretest/src/tb/tb_coretest.v | 492 ++++++++
coretest/toolruns/Makefile | 75 ++
coretest/toolruns/modelsim/coretest_wave.do | 80 ++
eim/src/rtl/cdc_bus_pulse.v | 145 +++
eim/src/rtl/eim.v | 75 ++
eim/src/rtl/eim_arbiter.v | 309 +++++
eim/src/rtl/eim_arbiter_cdc.v | 143 +++
eim/src/rtl/eim_da_phy.v | 77 ++
eim/src/rtl/eim_indicator.v | 69 ++
i2c/LICENSE | 24 +
i2c/README.md | 7 +
i2c/src/rtl/i2c.v | 217 ++++
i2c/src/rtl/i2c_core.v | 580 ++++++++++
novena/build/.gitignore | 52 +
novena/build/Makefile.eim | 39 +
novena/build/Makefile.i2c | 36 +
novena/build/xilinx.mk | 174 +++
novena/build/xilinx.opt | 42 +
.../novena_reorg_eim/novena_reorg_eim.xise | 466 ++++++++
.../novena_reorg_i2c/novena_reorg_i2c.xise | 438 +++++++
novena/src/rtl/ipcore/_xmsgs/cg.xmsgs | 27 +
novena/src/rtl/ipcore/_xmsgs/pn_parser.xmsgs | 15 +
novena/src/rtl/ipcore/clkmgr_dcm.asy | 25 +
novena/src/rtl/ipcore/clkmgr_dcm.gise | 31 +
novena/src/rtl/ipcore/clkmgr_dcm.ncf | 60 +
novena/src/rtl/ipcore/clkmgr_dcm.sym | 24 +
novena/src/rtl/ipcore/clkmgr_dcm.ucf | 59 +
novena/src/rtl/ipcore/clkmgr_dcm.v | 148 +++
novena/src/rtl/ipcore/clkmgr_dcm.veo | 79 ++
novena/src/rtl/ipcore/clkmgr_dcm.xco | 269 +++++
novena/src/rtl/ipcore/clkmgr_dcm.xdc | 67 ++
novena/src/rtl/ipcore/clkmgr_dcm.xise | 74 ++
.../rtl/ipcore/clkmgr_dcm/clk_wiz_v3_6_readme.txt | 184 +++
.../ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_readme.txt | 184 +++
.../ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_vinfo.html | 195 ++++
.../rtl/ipcore/clkmgr_dcm/doc/pg065_clk_wiz.pdf | Bin 0 -> 42657 bytes
.../clkmgr_dcm/example_design/clkmgr_dcm_exdes.ucf | 60 +
.../clkmgr_dcm/example_design/clkmgr_dcm_exdes.v | 164 +++
.../clkmgr_dcm/example_design/clkmgr_dcm_exdes.xdc | 69 ++
.../rtl/ipcore/clkmgr_dcm/implement/implement.bat | 90 ++
.../rtl/ipcore/clkmgr_dcm/implement/implement.sh | 91 ++
.../ipcore/clkmgr_dcm/implement/planAhead_ise.bat | 58 +
.../ipcore/clkmgr_dcm/implement/planAhead_ise.sh | 59 +
.../ipcore/clkmgr_dcm/implement/planAhead_ise.tcl | 78 ++
.../ipcore/clkmgr_dcm/implement/planAhead_rdn.bat | 58 +
.../ipcore/clkmgr_dcm/implement/planAhead_rdn.sh | 57 +
.../ipcore/clkmgr_dcm/implement/planAhead_rdn.tcl | 69 ++
novena/src/rtl/ipcore/clkmgr_dcm/implement/xst.prj | 2 +
novena/src/rtl/ipcore/clkmgr_dcm/implement/xst.scr | 9 +
.../ipcore/clkmgr_dcm/simulation/clkmgr_dcm_tb.v | 145 +++
.../clkmgr_dcm/simulation/functional/simcmds.tcl | 8 +
.../simulation/functional/simulate_isim.bat | 59 +
.../simulation/functional/simulate_isim.sh | 61 +
.../simulation/functional/simulate_mti.bat | 61 +
.../simulation/functional/simulate_mti.do | 65 ++
.../simulation/functional/simulate_mti.sh | 61 +
.../simulation/functional/simulate_ncsim.sh | 62 +
.../simulation/functional/simulate_vcs.sh | 72 ++
.../simulation/functional/ucli_commands.key | 5 +
.../simulation/functional/vcs_session.tcl | 18 +
.../clkmgr_dcm/simulation/functional/wave.do | 60 +
.../clkmgr_dcm/simulation/functional/wave.sv | 118 ++
.../clkmgr_dcm/simulation/timing/clkmgr_dcm_tb.v | 149 +++
.../clkmgr_dcm/simulation/timing/sdf_cmd_file | 2 +
.../clkmgr_dcm/simulation/timing/simcmds.tcl | 9 +
.../clkmgr_dcm/simulation/timing/simulate_isim.sh | 62 +
.../clkmgr_dcm/simulation/timing/simulate_mti.bat | 59 +
.../clkmgr_dcm/simulation/timing/simulate_mti.do | 65 ++
.../clkmgr_dcm/simulation/timing/simulate_mti.sh | 61 +
.../clkmgr_dcm/simulation/timing/simulate_ncsim.sh | 64 ++
.../clkmgr_dcm/simulation/timing/simulate_vcs.sh | 72 ++
.../clkmgr_dcm/simulation/timing/ucli_commands.key | 5 +
.../clkmgr_dcm/simulation/timing/vcs_session.tcl | 1 +
.../ipcore/clkmgr_dcm/simulation/timing/wave.do | 71 ++
novena/src/rtl/ipcore/clkmgr_dcm_flist.txt | 54 +
novena/src/rtl/ipcore/clkmgr_dcm_xmdf.tcl | 140 +++
novena/src/rtl/ipcore/coregen.cgp | 9 +
novena/src/rtl/ipcore/create_clkmgr_dcm.tcl | 37 +
novena/src/rtl/ipcore/edit_clkmgr_dcm.tcl | 37 +
novena/src/rtl/novena_clkmgr.v | 143 +++
novena/src/rtl/novena_eim.v | 175 +++
novena/src/rtl/novena_i2c.v | 218 ++++
novena/src/rtl/novena_regs.v | 126 ++
novena/src/sw/Makefile | 17 +
novena/src/sw/hash_tester_eim.c | 876 ++++++++++++++
novena/src/sw/hash_tester_i2c.c | 1013 ++++++++++++++++
novena/src/sw/novena-eim.c | 708 ++++++++++++
novena/src/sw/novena-eim.h | 52 +
novena/src/ucf/novena_eim.ucf | 152 +++
novena/src/ucf/novena_i2c.ucf | 82 ++
sha1/LICENSE.txt | 24 +
sha1/README.md | 125 ++
sha1/src/model/python/sha1.py | 269 +++++
sha1/src/rtl/sha1.v | 204 ++++
sha1/src/rtl/sha1_core.v | 443 +++++++
sha1/src/rtl/sha1_w_mem.v | 343 ++++++
sha1/src/tb/tb_sha1.v | 589 ++++++++++
sha1/src/tb/tb_sha1_core.v | 388 +++++++
sha1/src/tb/tb_sha1_w_mem.v | 287 +++++
sha1/toolruns/Makefile | 102 ++
sha256/LICENSE.txt | 24 +
sha256/README.md | 113 ++
sha256/src/model/sha256.py | 344 ++++++
sha256/src/rtl/sha256.v | 204 ++++
sha256/src/rtl/sha256_core.v | 519 +++++++++
sha256/src/rtl/sha256_k_constants.v | 387 +++++++
sha256/src/rtl/sha256_w_mem.v | 345 ++++++
sha256/src/rtl/wb_sha256.v | 674 +++++++++++
sha256/src/tb/tb_sha256.v | 556 +++++++++
sha256/src/tb/tb_sha256_core.v | 406 +++++++
sha256/src/tb/tb_sha256_w_mem.v | 222 ++++
sha256/src/tb/tb_wb_sha256.v | 556 +++++++++
sha256/toolruns/Makefile | 117 ++
sha512/LICENSE | 24 +
sha512/README.md | 41 +
sha512/src/model/python/sha512.py | 345 ++++++
sha512/src/rtl/sha512.v | 241 ++++
sha512/src/rtl/sha512_core.v | 607 ++++++++++
sha512/src/rtl/sha512_h_constants.v | 143 +++
sha512/src/rtl/sha512_k_constants.v | 472 ++++++++
sha512/src/rtl/sha512_w_mem.v | 346 ++++++
sha512/src/tb/tb_sha512.v | 798 +++++++++++++
sha512/src/tb/tb_sha512_core.v | 535 +++++++++
sha512/toolruns/Makefile | 96 ++
132 files changed, 24190 insertions(+)
diff --git a/core_selector/src/rtl/cipher_selector.v b/core_selector/src/rtl/cipher_selector.v
new file mode 100644
index 0000000..ea18e14
--- /dev/null
+++ b/core_selector/src/rtl/cipher_selector.v
@@ -0,0 +1,117 @@
+//======================================================================
+//
+// cipher_selector.v
+// -----------------
+// Top level wrapper that creates the Cryptech coretest system.
+// The wrapper contains instances of external interface, coretest
+// and the core to be tested. And if more than one core is
+// present the wrapper also includes address and data muxes.
+//
+//
+// Authors: Joachim Strombergson, Paul Selkirk, Pavel Shatov
+// Copyright (c) 2014-2015, 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 cipher_selector
+ (
+ input wire sys_clk,
+ input wire sys_rst,
+ input wire sys_ena,
+
+ input wire [13: 0] sys_eim_addr,
+ input wire sys_eim_wr,
+ input wire sys_eim_rd,
+ output wire [31 : 0] sys_read_data,
+ input wire [31 : 0] sys_write_data
+ );
+
+
+ //
+ // Output Register
+ //
+ reg [31: 0] tmp_read_data;
+ assign sys_read_data = tmp_read_data;
+
+
+ /* So far we have no CIPHER cores, let's make some dummy 32-bit registers here
+ * to prevent ISE from complaining that we don't use input ports.
+ */
+
+ reg [31: 0] reg_dummy_first;
+ reg [31: 0] reg_dummy_second;
+ reg [31: 0] reg_dummy_third;
+
+ always @(posedge sys_clk)
+ //
+ if (sys_rst)
+ begin
+ reg_dummy_first <= {8{4'hD}};
+ reg_dummy_second <= {8{4'hE}};
+ reg_dummy_third <= {8{4'hF}};
+ end
+ else if (sys_ena)
+ begin
+ //
+ if (sys_eim_wr)
+ begin
+ //
+ // WRITE handler
+ //
+ case (sys_eim_addr)
+ 14'd0: reg_dummy_first <= sys_write_data;
+ 14'd1: reg_dummy_second <= sys_write_data;
+ 14'd2: reg_dummy_third <= sys_write_data;
+ endcase
+ //
+ end
+ //
+ if (sys_eim_rd)
+ begin
+ //
+ // READ handler
+ //
+ case (sys_eim_addr)
+ 14'd0: tmp_read_data <= reg_dummy_first;
+ 14'd1: tmp_read_data <= reg_dummy_second;
+ 14'd2: tmp_read_data <= reg_dummy_third;
+ //
+ default: tmp_read_data <= {32{1'b0}}; // read non-existent locations as zeroes
+ endcase
+ //
+ end
+ //
+ end
+
+
+endmodule
+
+//======================================================================
+// EOF core_selector.v
+//======================================================================
diff --git a/core_selector/src/rtl/core_selector.v b/core_selector/src/rtl/core_selector.v
new file mode 100644
index 0000000..4200b15
--- /dev/null
+++ b/core_selector/src/rtl/core_selector.v
@@ -0,0 +1,182 @@
+//======================================================================
+//
+// coretest_hashes.v
+// -----------------
+// Top level wrapper that creates the Cryptech coretest system.
+// The wrapper contains instances of external interface, coretest
+// and the core to be tested. And if more than one core is
+// present the wrapper also includes address and data muxes.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2014-2015, 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 core_selector
+ (
+ input wire sys_clk,
+ input wire sys_rst,
+
+ input wire [16: 0] sys_eim_addr,
+ input wire sys_eim_wr,
+ input wire sys_eim_rd,
+ output wire [31: 0] sys_read_data,
+ input wire [31: 0] sys_write_data
+ );
+
+
+ /* Three upper bits of address [16:14] are used to select memory segment.
+ * There can be eight segments. So far segment 0 is used for hashes,
+ * segment 1 is reserved for random number generators, segment 2 is reserved
+ * for chiphers. Other segments are not used so far.
+ */
+
+ /* Every segment has its own memory map, take at look at corresponding
+ * selectors for more information.
+ */
+
+ //----------------------------------------------------------------
+ // Segment Decoder
+ //----------------------------------------------------------------
+ localparam SEGMENT_ADDR_HASHES = 3'd0;
+ localparam SEGMENT_ADDR_RNGS = 3'd1;
+ localparam SEGMENT_ADDR_CIPHERS = 3'd2;
+
+ wire [ 2: 0] addr_segment = sys_eim_addr[16:14]; // 3 upper bits are decoded here
+ wire [13: 0] addr_segment_int = sys_eim_addr[13: 0]; // 14 lower bits are decoded individually
+ // in corresponding segment selectors
+
+ wire [31: 0] segment_hashes_read_data; // data read from HASHES segment
+ wire [31: 0] segment_rngs_read_data; // data read from RNGS segment
+ wire [31: 0] segment_ciphers_read_data; // data read from CIPHERS segment
+
+ wire segment_enable_hashes = (addr_segment == SEGMENT_ADDR_HASHES) ? 1'b1 : 1'b0; // HASHES segment is being addressed
+ wire segment_enable_rngs = (addr_segment == SEGMENT_ADDR_RNGS) ? 1'b1 : 1'b0; // RNGS segment is being addressed
+ wire segment_enable_ciphers = (addr_segment == SEGMENT_ADDR_CIPHERS) ? 1'b1 : 1'b0; // CIPHERS segment is being addressed
+
+
+ //----------------------------------------------------------------
+ // Output (Read Data) Bus
+ //----------------------------------------------------------------
+ reg [31: 0] sys_read_data_reg;
+ assign sys_read_data = sys_read_data_reg;
+
+ always @*
+ //
+ case (addr_segment)
+ SEGMENT_ADDR_HASHES: sys_read_data_reg = segment_hashes_read_data;
+ SEGMENT_ADDR_RNGS: sys_read_data_reg = segment_rngs_read_data;
+ SEGMENT_ADDR_CIPHERS: sys_read_data_reg = segment_ciphers_read_data;
+ default: sys_read_data_reg = {32{1'b0}};
+ endcase
+
+
+
+ //----------------------------------------------------------------
+ // HASH Core Selector
+ //
+ // This selector is used to map core registers into
+ // EIM address space and select which core to send EIM read and
+ // write operations to.
+ //----------------------------------------------------------------
+ hash_selector segment_hashes
+ (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .sys_ena(segment_enable_hashes), // only enable active selector
+
+ .sys_eim_addr(addr_segment_int), // we only connect 14 lower bits of address here,
+ // because we have already decoded 3 upper bits earlier,
+ // every segment can have its own address decoder.
+ .sys_eim_wr(sys_eim_wr),
+ .sys_eim_rd(sys_eim_rd),
+
+ .sys_write_data(sys_write_data),
+ .sys_read_data(segment_hashes_read_data) // output from HASHES segment
+ );
+
+
+ //----------------------------------------------------------------
+ // RNG Selector
+ //
+ // This selector is used to map random number generator registers into
+ // EIM address space and select which RNG to send EIM read and
+ // write operations to. So far there are no RNG cores.
+ //----------------------------------------------------------------
+ rng_selector segment_rngs
+ (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .sys_ena(segment_enable_rngs), // only enable active selector
+
+ .sys_eim_addr(addr_segment_int), // we only connect 14 lower bits of address here,
+ // because we have already decoded 3 upper bits earlier,
+ // every segment can have its own address decoder.
+ .sys_eim_wr(sys_eim_wr),
+ .sys_eim_rd(sys_eim_rd),
+
+ .sys_write_data(sys_write_data),
+ .sys_read_data(segment_rngs_read_data) // output from RNGS segment
+ );
+
+
+ //----------------------------------------------------------------
+ // CIPHER Selector
+ //
+ // This selector is used to map cipher registers into
+ // EIM address space and select which CIPHER to send EIM read and
+ // write operations to. So far there are no CIPHER cores.
+ //----------------------------------------------------------------
+ cipher_selector segment_ciphers
+ (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .sys_ena(segment_enable_ciphers), // only enable active selector
+
+ .sys_eim_addr(addr_segment_int), // we only connect 14 lower bits of address here,
+ // because we have already decoded 3 upper bits earlier,
+ // every segment can have its own address decoder.
+ .sys_eim_wr(sys_eim_wr),
+ .sys_eim_rd(sys_eim_rd),
+
+ .sys_write_data(sys_write_data),
+ .sys_read_data(segment_ciphers_read_data) // output from CIPHERS segment
+ );
+
+
+endmodule
+
+
+//======================================================================
+// EOF eim_memory.v
+//======================================================================
diff --git a/core_selector/src/rtl/hash_selector.v b/core_selector/src/rtl/hash_selector.v
new file mode 100644
index 0000000..4698078
--- /dev/null
+++ b/core_selector/src/rtl/hash_selector.v
@@ -0,0 +1,264 @@
+//======================================================================
+//
+// hash_selector.v
+// ---------------
+// Top level wrapper that creates the Cryptech coretest system.
+// The wrapper contains instances of external interface, coretest
+// and the core to be tested. And if more than one core is
+// present the wrapper also includes address and data muxes.
+//
+//
+// Authors: Joachim Strombergson, Paul Selkirk, Pavel Shatov
+// Copyright (c) 2014-2015, 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 hash_selector
+ (
+ input wire sys_clk,
+ input wire sys_rst,
+ input wire sys_ena,
+
+ input wire [13 : 0] sys_eim_addr,
+ input wire sys_eim_wr,
+ input wire sys_eim_rd,
+ output wire [31 : 0] sys_read_data,
+ input wire [31 : 0] sys_write_data
+ );
+
+ /* In this memory segment (HASHES) we have 14 address bits. Every core has
+ * 8-bit internal address space, so we can have up to 2^(14-8) = 64 cores here.
+ *
+ * Core #0 is not an actual HASH core, but a set of board-level (global)
+ * registers, that can be used to get information about hardware (board
+ * type, bitstream version and so on).
+ *
+ * So far we have three cores: SHA-1, SHA-256 and SHA-512.
+ */
+
+ /*********************************************************
+ * To add new HASH core named XXX follow the steps below *
+ *********************************************************
+ *
+ * 1. Add corresponding `define under "List of Available Cores", this will
+ * allow users to exclude your core from implementation to save some
+ * slices in case they don't need it.
+ *
+ * `define USE_CORE_XXX
+XXX define in wrapper core
+ *
+ *
+ * 2. Choose address of your new core and add corresponding line under
+ * "Core Address Table". Core addresses can be in the range from 1 to 63
+ * inclusively. Core address 0 is reserved for a page of global
+ * registers and must not be used.
+ *
+ * localparam CORE_ADDR_XXX = 6'dN;
+XXX move to `define in wrapper core??
+ *
+ *
+ * 3. Add instantiation of your new core after all existing cores
+ * surrounded by conditional synthesis directives.
+ * You also need a 32-bit output (read data) bus for your core and an
+ * enable flag. Note that sys_rst in an active-high sync reset signal.
+ *
+ * `ifdef USE_CORE_XXX
+ * wire [31: 0] read_data_xxx;
+ * wire enable_xxx = sys_ena && (addr_core_num == CORE_ADDR_XXX);
+ * xxx xxx_inst
+ * (
+ * .clk(sys_clk),
+ * .reset_n(~sys_rst),
+ * .cs(enable_xxx & (sys_eim_rd | sys_eim_wr)),
+ * .we(sys_eim_wr),
+ * .address(addr_core_reg),
+ * .write_data(sys_write_data),
+ * .read_data(read_data_xxx),
+ * .error()
+ * );
+ * `endif
+ *
+ *
+ * 4. Add previously created data bus to "Output (Read Data) Multiplexor"
+ * in the end of this file.
+ *
+ * `ifdef USE_CORE_XXX
+ * CORE_ADDR_XXX:
+ * sys_read_data_mux = read_data_xxx;
+ * `endif
+ *
+ */
+
+
+ //----------------------------------------------------------------
+ // Address Decoder
+ //----------------------------------------------------------------
+ wire [ 5: 0] addr_core_num = sys_eim_addr[13: 8]; // upper 6 bits specify core being addressed
+ wire [ 7: 0] addr_core_reg = sys_eim_addr[ 7: 0]; // lower 8 bits specify register offset in core
+
+
+ /* We can comment following lines to exclude cores from implementation
+ * in case we run out of slices.
+ */
+
+ //----------------------------------------------------------------
+ // List of Available Cores
+ //----------------------------------------------------------------
+ `define USE_CORE_SHA1
+ `define USE_CORE_SHA256
+ `define USE_CORE_SHA512
+
+
+ //----------------------------------------------------------------
+ // Core Address Table
+ //----------------------------------------------------------------
+ localparam CORE_ADDR_GLOBAL_REGS = 6'd0;
+ localparam CORE_ADDR_SHA1 = 6'd1;
+ localparam CORE_ADDR_SHA256 = 6'd2;
+ localparam CORE_ADDR_SHA512 = 6'd3;
+
+
+ //----------------------------------------------------------------
+ // Global Registers
+ //----------------------------------------------------------------
+ wire [31: 0] read_data_global;
+ wire enable_global = sys_ena && (addr_core_num == CORE_ADDR_GLOBAL_REGS);
+ novena_regs novena_regs_inst
+ (
+ .clk(sys_clk),
+ .rst(sys_rst),
+
+ .cs(enable_global & (sys_eim_rd | sys_eim_wr)),
+ .we(sys_eim_wr),
+
+ .address(addr_core_reg),
+ .write_data(sys_write_data),
+ .read_data(read_data_global)
+ );
+
+
+ //----------------------------------------------------------------
+ // SHA-1
+ //----------------------------------------------------------------
+ `ifdef USE_CORE_SHA1
+ wire [31: 0] read_data_sha1;
+ wire enable_sha1 = sys_ena && (addr_core_num == CORE_ADDR_SHA1);
+ sha1 sha1_inst
+ (
+ .clk(sys_clk),
+ .reset_n(~sys_rst),
+
+ .cs(enable_sha1 & (sys_eim_rd | sys_eim_wr)),
+ .we(sys_eim_wr),
+
+ .address(addr_core_reg),
+ .write_data(sys_write_data),
+ .read_data(read_data_sha1)
+ );
+ `endif
+
+
+ //----------------------------------------------------------------
+ // SHA-256
+ //----------------------------------------------------------------
+ `ifdef USE_CORE_SHA256
+ wire [31: 0] read_data_sha256;
+ wire enable_sha256 = sys_ena && (addr_core_num == CORE_ADDR_SHA256);
+ sha256 sha256_inst
+ (
+ .clk(sys_clk),
+ .reset_n(~sys_rst),
+
+ .cs(enable_sha256 & (sys_eim_rd | sys_eim_wr)),
+ .we(sys_eim_wr),
+
+ .address(addr_core_reg),
+ .write_data(sys_write_data),
+ .read_data(read_data_sha256)
+ );
+ `endif
+
+
+ //----------------------------------------------------------------
+ // SHA-512
+ //----------------------------------------------------------------
+ `ifdef USE_CORE_SHA512
+ wire [31: 0] read_data_sha512;
+ wire enable_sha512 = sys_ena && (addr_core_num == CORE_ADDR_SHA512);
+ sha512 sha512_inst
+ (
+ .clk(sys_clk),
+ .reset_n(~sys_rst),
+
+ .cs(enable_sha512 & (sys_eim_rd | sys_eim_wr)),
+ .we(sys_eim_wr),
+
+ .address(addr_core_reg),
+ .write_data(sys_write_data),
+ .read_data(read_data_sha512)
+ );
+ `endif
+
+
+ //----------------------------------------------------------------
+ // Output (Read Data) Multiplexor
+ //----------------------------------------------------------------
+ reg [31: 0] sys_read_data_mux;
+ assign sys_read_data = sys_read_data_mux;
+
+ always @*
+ //
+ case (addr_core_num)
+ //
+ CORE_ADDR_GLOBAL_REGS:
+ sys_read_data_mux = read_data_global;
+ `ifdef USE_CORE_SHA1
+ CORE_ADDR_SHA1:
+ sys_read_data_mux = read_data_sha1;
+ `endif
+ `ifdef USE_CORE_SHA256
+ CORE_ADDR_SHA256:
+ sys_read_data_mux = read_data_sha256;
+ `endif
+ `ifdef USE_CORE_SHA512
+ CORE_ADDR_SHA512:
+ sys_read_data_mux = read_data_sha512;
+ `endif
+ //
+ default:
+ sys_read_data_mux = {32{1'b0}};
+ //
+ endcase
+
+
+endmodule
+
+//======================================================================
+// EOF hash_selector.v
+//======================================================================
diff --git a/core_selector/src/rtl/rng_selector.v b/core_selector/src/rtl/rng_selector.v
new file mode 100644
index 0000000..f86b3e9
--- /dev/null
+++ b/core_selector/src/rtl/rng_selector.v
@@ -0,0 +1,112 @@
+//======================================================================
+//
+// rng_selector.v
+// -----------------
+// Top level wrapper that creates the Cryptech coretest system.
+// The wrapper contains instances of external interface, coretest
+// and the core to be tested. And if more than one core is
+// present the wrapper also includes address and data muxes.
+//
+//
+// Authors: Joachim Strombergson, Paul Selkirk, Pavel Shatov
+// Copyright (c) 2014-2015, 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 rng_selector
+ (
+ input wire sys_clk,
+ input wire sys_rst,
+ input wire sys_ena,
+
+ input wire [13: 0] sys_eim_addr,
+ input wire sys_eim_wr,
+ input wire sys_eim_rd,
+ output wire [31 : 0] sys_read_data,
+ input wire [31 : 0] sys_write_data
+ );
+
+
+ //
+ // Output Register
+ //
+ reg [31: 0] tmp_read_data;
+ assign sys_read_data = tmp_read_data;
+
+
+ /* So far we have no RNG cores, let's make some dummy 32-bit registers here
+ * to prevent ISE from complaining that we don't use input ports.
+ */
+
+ reg [31: 0] reg_dummy_first;
+ reg [31: 0] reg_dummy_second;
+ reg [31: 0] reg_dummy_third;
+
+ always @(posedge sys_clk)
+ //
+ if (sys_rst) begin
+ reg_dummy_first <= {8{4'hA}};
+ reg_dummy_second <= {8{4'hB}};
+ reg_dummy_third <= {8{4'hC}};
+ end else if (sys_ena) begin
+ //
+ if (sys_eim_wr) begin
+ //
+ // WRITE handler
+ //
+ case (sys_eim_addr)
+ 14'd0: reg_dummy_first <= sys_write_data;
+ 14'd1: reg_dummy_second <= sys_write_data;
+ 14'd2: reg_dummy_third <= sys_write_data;
+ endcase
+ //
+ end
+ //
+ if (sys_eim_rd) begin
+ //
+ // READ handler
+ //
+ case (sys_eim_addr)
+ 14'd0: tmp_read_data <= reg_dummy_first;
+ 14'd1: tmp_read_data <= reg_dummy_second;
+ 14'd2: tmp_read_data <= reg_dummy_third;
+ //
+ default:
+ tmp_read_data <= {32{1'b0}}; // read non-existent locations as zeroes
+ endcase
+ //
+ end
+ //
+ end
+
+endmodule
+
+//======================================================================
+// EOF core_selector.v
+//======================================================================
diff --git a/coretest/LICENSE b/coretest/LICENSE
new file mode 100644
index 0000000..9a95faa
--- /dev/null
+++ b/coretest/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2014, SUNET
+Joachim Strömbergson
+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.
+
+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/coretest/README.md b/coretest/README.md
new file mode 100644
index 0000000..2c38361
--- /dev/null
+++ b/coretest/README.md
@@ -0,0 +1,176 @@
+# coretest #
+Test platform for the [Cryptech Open HSM project](https://cryptech.is/).
+
+(_Note:The Cryptech certificate is by choice not from a CA and therefore
+not in your brower trust store._)
+
+
+## Description ##
+This platform and hardware design is used to functionally verfiy cores
+developed in the Cryptech Open HSM project. The test core itself
+contains just enough functionality to be able to verify that the SW in
+the host computer can talk to the core in the FPGA by reading and
+writing 32 bit data words to given addresses.
+
+This project includes cores in Verilog, a testbench as well as host SW
+to talk to the core.
+
+
+## Architecture ##
+The coretest consists of three state machines:
+
+### rx_engine ###
+Handles receiving command messages from the host. Awaits SYN signals from
+the host interface and reads bytes when SYN is asserted. For each byte
+the rx_engine assetts and ACK and waits for the SYN to be asserted. When
+a EOC byte has been detected the rx_engine signals the test_engine that
+there is a new command available in the rx_buffer.
+
+
+### tx_engine ###
+Handles transmitting response messages to the host. When the test_engine
+signals that there is a new response in the tx_buffer the tx_engine will
+start transmitting all bytes up to and including the EOR byte it is
+expecting in the tx_buffer. The transmission is done by asserting SYN
+awaiting ACK, deasserting SYN and moving to the next byte before
+asserting SYN again. This process is repeated until all bytes has been
+transmitted.
+
+
+### test_engine ###
+Performs the parsing of commands from the host. Known read or write
+commands are used to test the core to be tested. The response from the
+core is collected and the appropriate response is stored in the
+tx_buffer. The test_engine then signals the tx_engine that there is a
+new response message to be transmitted.
+
+## Interfaces ##
+The host communication interface is a byte wide data interface with
+SYN-ACK handshake for each byte.
+
+The interface to the core to be tested is a memory like
+interface with chip select and write enable. The data width is 32-bits
+and the address is 16-bits.
+
+
+## Core under test ##
+The core under test is expected to have a simple memory like interface
+with chip select (cs), write enable (we) signal ports, 16-bit address
+port and separate 32-bit data ports for read and write data. The core is
+also expected to have an error signal port that informs the master if
+any read or write commands given cannot be performed by the core.
+
+***Note:***
+The core reset signal is expected to by active high. The
+core reset signal should be connected to the coretest core_reset
+port, not to system reset.
+
+
+## Protocol ##
+Coretest uses a simple command-response protocol to allow a host to
+control the test functionality.
+
+The command messages are sent as a sequence of bytes with a command byte
+followed by zero or more arguments. The response consists of a response
+code byte followed by zero or more data fields.
+
+The start of a command is signalled by a Start of Command (SOC)
+byte. The end of a command is signalled by a End of Command (EOC)
+byte. These bytes are:
+ - SOC: 0x55
+ - EOC: 0xaa
+
+The start of a response is signalled by a Start of Response (SOR)
+byte. The end of a response is signalled by a End of Respons (EOC)
+byte. These bytes are:
+ - SOR: 0xaa
+ - EOR: 0x55
+
+***The commands accepted are:***
+ - RESET_CMD. Reset the core being tested. Message length is 3 bytes
+ including SOC and EOC.
+ - SOC
+ - 0x01 opcode
+ - EOC
+
+
+ - READ_CMD. Read a 32-bit data word from a given address. Message
+ length is 5 bytes including SOC and EOC.
+ - SOC
+ - 0x10 opcode
+ - 16-bit address in MSB format
+ - EOC
+
+
+ - WRITE_CMD. Write a given data word to a given address. Message
+ length is 9 bytes including SOC and EOC.
+ - SOC
+ - 0x11 opcode
+ - 16-bit address in MSB format
+ - 32-bit data in MSB format
+ - EOC
+
+
+***The possible responses are:***
+ - UNKNOWN. Unknown command received. Message length is 4 bytes
+ including SOR and EOR.
+ - SOR
+ - 0xfe response code
+ - Received command
+ - EOR
+
+
+ - ERROR. Known but unsuccessful command as signalled by the
+ core. Caused for example by a write command to read only
+ register. Message length is 4 bytes including SOR and EOR.
+ - SOR
+ - 0xfd response code
+ - command received
+ - EOR
+
+
+ - READ_OK. Sent after successful read operation. Message length is 9
+ bytes including SOR and EOR .
+ - SOR
+ - 0x7f response code
+ - 16-bit address in MSB format
+ - 32-bit data in MSB format
+ - EOR
+
+
+ - WRITE_OK. Sent after successful write operation. Message length is 5
+ bytes including SOR and EOR
+ - SOR
+ - 0x7e response code
+ - 16-bit address in MSB format
+ - EOR
+
+
+ - RESET_OK. Sent after successful reset operation. Message length is 3
+ bytes including SOR and EOR.
+ - SOR
+ - 0x7d response code
+ - EOR
+
+## Status ##
+***(2014-02-11):***
+
+Added information about the architecture and protocols. Updated the
+command and response with explicit read and write ok responses. Some
+cleanup of the description.
+
+Completed first draft of the RTL for coretest. The RTL is not debugged
+and has not been synthesized. We need to add a testbench and a simple
+test core.
+
+Added a simple test core.
+Adding initial version of UART core that will be used for the host
+interface.
+
+
+***(2014-02-10):***
+
+Initial version of the project. Based on previous cttest project but
+renamed and with new (ideas) about the test architecture. Specified
+command and response protocol.
+
diff --git a/coretest/src/rtl/coretest.v b/coretest/src/rtl/coretest.v
new file mode 100644
index 0000000..918312d
--- /dev/null
+++ b/coretest/src/rtl/coretest.v
@@ -0,0 +1,1209 @@
+//======================================================================
+//
+// coretest.v
+// ----------
+// The Cryptech coretest testing module. Combined with an external
+// interface that sends and receives bytes using a SYN-ACK
+// handshake and a core to be tested, coretest can parse read
+// and write commands needed to test the connected core.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+//
+// 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 coretest(
+ input wire clk,
+ input wire reset_n,
+
+ // Interface to communication core
+ input wire rx_syn,
+ input wire [7 : 0] rx_data,
+ output wire rx_ack,
+
+ output wire tx_syn,
+ output wire [7 : 0] tx_data,
+ input wire tx_ack,
+
+ // Interface to the core being tested.
+ output wire core_reset_n,
+ output wire core_cs,
+ output wire core_we,
+ output wire [15 : 0] core_address,
+ output wire [31 : 0] core_write_data,
+ input wire [31 : 0] core_read_data,
+ input wire core_error
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ // Max elements in read and write buffers.
+ parameter BUFFER_MAX = 4'hf;
+
+ // Command constants.
+ parameter SOC = 8'h55;
+ parameter EOC = 8'haa;
+ parameter RESET_CMD = 8'h01;
+ parameter READ_CMD = 8'h10;
+ parameter WRITE_CMD = 8'h11;
+
+ // Response constants.
+ parameter SOR = 8'haa;
+ parameter EOR = 8'h55;
+ parameter UNKNOWN = 8'hfe;
+ parameter ERROR = 8'hfd;
+ parameter READ_OK = 8'h7f;
+ parameter WRITE_OK = 8'h7e;
+ parameter RESET_OK = 8'h7d;
+
+ // rx_engine states.
+ parameter RX_IDLE = 3'h0;
+ parameter RX_ACK = 3'h1;
+ parameter RX_NSYN = 3'h2;
+
+ // tx_engine states.
+ parameter TX_IDLE = 3'h0;
+ parameter TX_SYN = 3'h1;
+ parameter TX_NOACK = 3'h2;
+ parameter TX_NEXT = 3'h3;
+ parameter TX_SENT = 3'h4;
+ parameter TX_DONE = 3'h5;
+
+ // test_engine states.
+ parameter TEST_IDLE = 8'h00;
+ parameter TEST_GET_CMD = 8'h10;
+ parameter TEST_PARSE_CMD = 8'h11;
+ parameter TEST_GET_ADDR0 = 8'h20;
+ parameter TEST_GET_ADDR1 = 8'h21;
+ parameter TEST_GET_DATA0 = 8'h24;
+ parameter TEST_GET_DATA1 = 8'h25;
+ parameter TEST_GET_DATA2 = 8'h26;
+ parameter TEST_GET_DATA3 = 8'h27;
+ parameter TEST_GET_EOC = 8'h28;
+ parameter TEST_RST_START = 8'h30;
+ parameter TEST_RST_WAIT = 8'h31;
+ parameter TEST_RST_END = 8'h32;
+ parameter TEST_RD_START = 8'h50;
+ parameter TEST_RD_WAIT = 8'h51;
+ parameter TEST_RD_WAIT2 = 8'h52;
+ parameter TEST_RD_END = 8'h53;
+ parameter TEST_WR_START = 8'h60;
+ parameter TEST_WR_WAIT = 8'h61;
+ parameter TEST_WR_END = 8'h62;
+ parameter TEST_CMD_UNKNOWN = 8'h80;
+ parameter TEST_CMD_ERROR = 8'h81;
+ parameter TEST_SEND_RESPONSE = 8'hc0;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg rx_syn_reg;
+
+ reg rx_ack_reg;
+ reg rx_ack_new;
+ reg rx_ack_we;
+
+ reg tx_syn_reg;
+ reg tx_syn_new;
+ reg tx_syn_we;
+
+ reg tx_ack_reg;
+
+ reg core_reset_n_reg;
+ reg core_reset_n_new;
+ reg core_reset_n_we;
+
+ reg core_cs_reg;
+ reg core_cs_new;
+ reg core_cs_we;
+
+ reg core_we_reg;
+ reg core_we_new;
+ reg core_we_we;
+
+ reg send_response_reg;
+ reg send_response_new;
+ reg send_response_we;
+
+ reg response_sent_reg;
+ reg response_sent_new;
+ reg response_sent_we;
+
+ reg [7 : 0] cmd_reg;
+ reg cmd_we;
+
+ reg [7 : 0] core_addr_byte0_reg;
+ reg core_addr_byte0_we;
+ reg [7 : 0] core_addr_byte1_reg;
+ reg core_addr_byte1_we;
+
+ reg [7 : 0] core_wr_data_byte0_reg;
+ reg core_wr_data_byte0_we;
+ reg [7 : 0] core_wr_data_byte1_reg;
+ reg core_wr_data_byte1_we;
+ reg [7 : 0] core_wr_data_byte2_reg;
+ reg core_wr_data_byte2_we;
+ reg [7 : 0] core_wr_data_byte3_reg;
+ reg core_wr_data_byte3_we;
+
+ reg [31 : 0] core_read_data_reg;
+ reg core_error_reg;
+ reg sample_core_output;
+
+ reg [3 : 0] rx_buffer_rd_ptr_reg;
+ reg [3 : 0] rx_buffer_rd_ptr_new;
+ reg rx_buffer_rd_ptr_we;
+ reg rx_buffer_rd_ptr_inc;
+
+ reg [3 : 0] rx_buffer_wr_ptr_reg;
+ reg [3 : 0] rx_buffer_wr_ptr_new;
+ reg rx_buffer_wr_ptr_we;
+ reg rx_buffer_wr_ptr_inc;
+
+ reg [3 : 0] rx_buffer_ctr_reg;
+ reg [3 : 0] rx_buffer_ctr_new;
+ reg rx_buffer_ctr_we;
+ reg rx_buffer_ctr_inc;
+ reg rx_buffer_ctr_dec;
+ reg rx_buffer_full;
+ reg rx_buffer_empty;
+
+ reg [7 : 0] rx_buffer [0 : 15];
+ reg rx_buffer_we;
+
+ reg [3 : 0] tx_buffer_ptr_reg;
+ reg [3 : 0] tx_buffer_ptr_new;
+ reg tx_buffer_ptr_we;
+ reg tx_buffer_ptr_inc;
+ reg tx_buffer_ptr_rst;
+
+ reg [7 : 0] tx_buffer [0 : 8];
+ reg tx_buffer_we;
+
+ reg [3 : 0] tx_msg_len_reg;
+ reg [3 : 0] tx_msg_len_new;
+ reg tx_msg_len_we;
+
+ reg [2 : 0] rx_engine_reg;
+ reg [2 : 0] rx_engine_new;
+ reg rx_engine_we;
+
+ reg [2 : 0] tx_engine_reg;
+ reg [2 : 0] tx_engine_new;
+ reg tx_engine_we;
+
+ reg [7 : 0] test_engine_reg;
+ reg [7 : 0] test_engine_new;
+ reg test_engine_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [7 : 0] tx_buffer_muxed0;
+ reg [7 : 0] tx_buffer_muxed1;
+ reg [7 : 0] tx_buffer_muxed2;
+ reg [7 : 0] tx_buffer_muxed3;
+ reg [7 : 0] tx_buffer_muxed4;
+ reg [7 : 0] tx_buffer_muxed5;
+ reg [7 : 0] tx_buffer_muxed6;
+ reg [7 : 0] tx_buffer_muxed7;
+ reg [7 : 0] tx_buffer_muxed8;
+
+ reg update_tx_buffer;
+ reg [7 : 0] response_type;
+
+ reg [7 : 0] rx_byte;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign rx_ack = rx_ack_reg;
+
+ assign tx_syn = tx_syn_reg;
+ assign tx_data = tx_buffer[tx_buffer_ptr_reg];
+
+ assign core_reset_n = core_reset_n_reg & reset_n;
+ assign core_cs = core_cs_reg;
+ assign core_we = core_we_reg;
+ assign core_address = {core_addr_byte0_reg, core_addr_byte1_reg};
+ assign core_write_data = {core_wr_data_byte0_reg, core_wr_data_byte1_reg,
+ core_wr_data_byte2_reg, core_wr_data_byte3_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)
+ begin: reg_update
+ if (!reset_n)
+ begin
+ rx_buffer[0] <= 8'h00;
+ rx_buffer[1] <= 8'h00;
+ rx_buffer[2] <= 8'h00;
+ rx_buffer[3] <= 8'h00;
+ rx_buffer[4] <= 8'h00;
+ rx_buffer[5] <= 8'h00;
+ rx_buffer[6] <= 8'h00;
+ rx_buffer[7] <= 8'h00;
+ rx_buffer[8] <= 8'h00;
+ rx_buffer[9] <= 8'h00;
+ rx_buffer[10] <= 8'h00;
+ rx_buffer[11] <= 8'h00;
+ rx_buffer[12] <= 8'h00;
+ rx_buffer[13] <= 8'h00;
+ rx_buffer[14] <= 8'h00;
+ rx_buffer[15] <= 8'h00;
+
+ tx_buffer[0] <= 8'h00;
+ tx_buffer[1] <= 8'h00;
+ tx_buffer[2] <= 8'h00;
+ tx_buffer[3] <= 8'h00;
+ tx_buffer[4] <= 8'h00;
+ tx_buffer[5] <= 8'h00;
+ tx_buffer[6] <= 8'h00;
+ tx_buffer[7] <= 8'h00;
+ tx_buffer[8] <= 8'h00;
+
+ rx_syn_reg <= 0;
+ rx_ack_reg <= 0;
+ tx_ack_reg <= 0;
+ tx_syn_reg <= 0;
+
+ rx_buffer_rd_ptr_reg <= 4'h0;
+ rx_buffer_wr_ptr_reg <= 4'h0;
+ rx_buffer_ctr_reg <= 4'h0;
+
+ tx_buffer_ptr_reg <= 4'h0;
+ tx_msg_len_reg <= 4'h0;
+
+ send_response_reg <= 0;
+ response_sent_reg <= 0;
+
+ cmd_reg <= 8'h00;
+ core_addr_byte0_reg <= 8'h00;
+ core_addr_byte1_reg <= 8'h00;
+ core_wr_data_byte0_reg <= 8'h00;
+ core_wr_data_byte1_reg <= 8'h00;
+ core_wr_data_byte2_reg <= 8'h00;
+ core_wr_data_byte3_reg <= 8'h00;
+
+ core_reset_n_reg <= 1;
+ core_cs_reg <= 0;
+ core_we_reg <= 0;
+ core_error_reg <= 0;
+ core_read_data_reg <= 32'h00000000;
+
+ rx_engine_reg <= RX_IDLE;
+ tx_engine_reg <= TX_IDLE;
+ test_engine_reg <= TEST_IDLE;
+ end
+ else
+ begin
+ rx_syn_reg <= rx_syn;
+ tx_ack_reg <= tx_ack;
+
+ if (rx_ack_we)
+ begin
+ rx_ack_reg <= rx_ack_new;
+ end
+
+ if (tx_syn_we)
+ begin
+ tx_syn_reg <= tx_syn_new;
+ end
+
+ if (rx_buffer_we)
+ begin
+ rx_buffer[rx_buffer_wr_ptr_reg] <= rx_data;
+ end
+
+ if (tx_buffer_we)
+ begin
+ tx_buffer[0] <= tx_buffer_muxed0;
+ tx_buffer[1] <= tx_buffer_muxed1;
+ tx_buffer[2] <= tx_buffer_muxed2;
+ tx_buffer[3] <= tx_buffer_muxed3;
+ tx_buffer[4] <= tx_buffer_muxed4;
+ tx_buffer[5] <= tx_buffer_muxed5;
+ tx_buffer[6] <= tx_buffer_muxed6;
+ tx_buffer[7] <= tx_buffer_muxed7;
+ tx_buffer[8] <= tx_buffer_muxed8;
+ end
+
+ if (cmd_we)
+ begin
+ cmd_reg <= rx_byte;
+ end
+
+ if (core_addr_byte0_we)
+ begin
+ core_addr_byte0_reg <= rx_byte;
+ end
+
+ if (core_addr_byte1_we)
+ begin
+ core_addr_byte1_reg <= rx_byte;
+ end
+
+ if (core_wr_data_byte0_we)
+ begin
+ core_wr_data_byte0_reg <= rx_byte;
+ end
+
+ if (core_wr_data_byte1_we)
+ begin
+ core_wr_data_byte1_reg <= rx_byte;
+ end
+
+ if (core_wr_data_byte2_we)
+ begin
+ core_wr_data_byte2_reg <= rx_byte;
+ end
+
+ if (core_wr_data_byte3_we)
+ begin
+ core_wr_data_byte3_reg <= rx_byte;
+ end
+
+ if (rx_buffer_rd_ptr_we)
+ begin
+ rx_buffer_rd_ptr_reg <= rx_buffer_rd_ptr_new;
+ end
+
+ if (rx_buffer_wr_ptr_we)
+ begin
+ rx_buffer_wr_ptr_reg <= rx_buffer_wr_ptr_new;
+ end
+
+ if (rx_buffer_ctr_we)
+ begin
+ rx_buffer_ctr_reg <= rx_buffer_ctr_new;
+ end
+
+ if (tx_buffer_ptr_we)
+ begin
+ tx_buffer_ptr_reg <= tx_buffer_ptr_new;
+ end
+
+ if (tx_msg_len_we)
+ begin
+ tx_msg_len_reg <= tx_msg_len_new;
+ end
+
+ if (core_reset_n_we)
+ begin
+ core_reset_n_reg <= core_reset_n_new;
+ end
+
+ if (core_cs_we)
+ begin
+ core_cs_reg <= core_cs_new;
+ end
+
+ if (core_we_we)
+ begin
+ core_we_reg <= core_we_new;
+ end
+
+ if (send_response_we)
+ begin
+ send_response_reg <= send_response_new;
+ end
+
+ if (response_sent_we)
+ begin
+ response_sent_reg <= response_sent_new;
+ end
+
+ if (sample_core_output)
+ begin
+ core_error_reg <= core_error;
+ core_read_data_reg <= core_read_data;
+ end
+
+ if (rx_engine_we)
+ begin
+ rx_engine_reg <= rx_engine_new;
+ end
+
+ if (tx_engine_we)
+ begin
+ tx_engine_reg <= tx_engine_new;
+ end
+
+ if (test_engine_we)
+ begin
+ test_engine_reg <= test_engine_new;
+ end
+ end
+ end // reg_update
+
+
+ //---------------------------------------------------------------
+ // read_rx_buffer
+ // Combinatinal read mux for the rx_buffer.
+ //---------------------------------------------------------------
+ always @*
+ begin : read_rx_buffer
+ rx_byte = rx_buffer[rx_buffer_rd_ptr_reg];
+ end // read_rx_buffer
+
+
+ //---------------------------------------------------------------
+ // tx_buffer_logic
+ //
+ // Update logic for the tx-buffer. Given the response type and
+ // the correct contents of the tx_buffer is assembled when
+ // and update is signalled by the test engine.
+ //---------------------------------------------------------------
+ always @*
+ begin: tx_buffer_logic
+ // Defafult assignments
+ tx_buffer_muxed0 = 8'h00;
+ tx_buffer_muxed1 = 8'h00;
+ tx_buffer_muxed2 = 8'h00;
+ tx_buffer_muxed3 = 8'h00;
+ tx_buffer_muxed4 = 8'h00;
+ tx_buffer_muxed5 = 8'h00;
+ tx_buffer_muxed6 = 8'h00;
+ tx_buffer_muxed7 = 8'h00;
+ tx_buffer_muxed8 = 8'h00;
+ tx_msg_len_new = 4'h0;
+ tx_msg_len_we = 0;
+ tx_buffer_we = 0;
+
+ if (update_tx_buffer)
+ begin
+ tx_buffer_we = 1;
+ tx_buffer_muxed0 = SOR;
+
+ case (response_type)
+ READ_OK:
+ begin
+ tx_buffer_muxed1 = READ_OK;
+ tx_buffer_muxed2 = core_addr_byte0_reg;
+ tx_buffer_muxed3 = core_addr_byte1_reg;
+ tx_buffer_muxed4 = core_read_data_reg[31 : 24];
+ tx_buffer_muxed5 = core_read_data_reg[23 : 16];
+ tx_buffer_muxed6 = core_read_data_reg[15 : 8];
+ tx_buffer_muxed7 = core_read_data_reg[7 : 0];
+ tx_buffer_muxed8 = EOR;
+ tx_msg_len_new = 4'h8;
+ tx_msg_len_we = 1;
+ end
+
+ WRITE_OK:
+ begin
+ tx_buffer_muxed1 = WRITE_OK;
+ tx_buffer_muxed2 = core_addr_byte0_reg;
+ tx_buffer_muxed3 = core_addr_byte1_reg;
+ tx_buffer_muxed4 = EOR;
+ tx_msg_len_new = 4'h4;
+ tx_msg_len_we = 1;
+ end
+
+ RESET_OK:
+ begin
+ tx_buffer_muxed1 = RESET_OK;
+ tx_buffer_muxed2 = EOR;
+ tx_msg_len_new = 4'h2;
+ tx_msg_len_we = 1;
+ end
+
+ ERROR:
+ begin
+ tx_buffer_muxed1 = ERROR;
+ tx_buffer_muxed2 = cmd_reg;
+ tx_buffer_muxed3 = EOR;
+ tx_msg_len_new = 4'h3;
+ tx_msg_len_we = 1;
+ end
+
+ default:
+ begin
+ // Any response type not explicitly defined is treated as UNKNOWN.
+ tx_buffer_muxed1 = UNKNOWN;
+ tx_buffer_muxed2 = cmd_reg;
+ tx_buffer_muxed3 = EOR;
+ tx_msg_len_new = 4'h3;
+ tx_msg_len_we = 1;
+ end
+ endcase // case (response_type)
+ end
+ end // tx_buffer_logic
+
+
+ //----------------------------------------------------------------
+ // rx_buffer_rd_ptr
+ //
+ // Logic for the rx buffer read pointer.
+ //----------------------------------------------------------------
+ always @*
+ begin: rx_buffer_rd_ptr
+ // Default assignments
+ rx_buffer_rd_ptr_new = 4'h0;
+ rx_buffer_rd_ptr_we = 1'b0;
+ rx_buffer_ctr_dec = 0;
+
+ if (rx_buffer_rd_ptr_inc)
+ begin
+ rx_buffer_ctr_dec = 1;
+ rx_buffer_rd_ptr_new = rx_buffer_rd_ptr_reg + 1'b1;
+ rx_buffer_rd_ptr_we = 1'b1;
+ end
+ end // rx_buffer_rd_ptr
+
+
+ //----------------------------------------------------------------
+ // rx_buffer_wr_ptr
+ //
+ // Logic for the rx buffer write pointer.
+ //----------------------------------------------------------------
+ always @*
+ begin: rx_buffer_wr_ptr
+ // Default assignments
+ rx_buffer_wr_ptr_new = 4'h0;
+ rx_buffer_wr_ptr_we = 1'b0;
+ rx_buffer_ctr_inc = 0;
+
+ if (rx_buffer_wr_ptr_inc)
+ begin
+ rx_buffer_ctr_inc = 1;
+ rx_buffer_wr_ptr_new = rx_buffer_wr_ptr_reg + 1'b1;
+ rx_buffer_wr_ptr_we = 1'b1;
+ end
+ end // rx_buffer_wr_ptr
+
+
+ //----------------------------------------------------------------
+ // rx_buffer_ctr
+ //
+ // Logic for the rx buffer element counter.
+ //----------------------------------------------------------------
+ always @*
+ begin: rx_buffer_ctr
+ // Default assignments
+ rx_buffer_ctr_new = 4'h0;
+ rx_buffer_ctr_we = 1'b0;
+ rx_buffer_empty = 1'b0;
+ rx_buffer_full = 1'b0;
+
+ if (rx_buffer_ctr_inc)
+ begin
+ rx_buffer_ctr_new = rx_buffer_ctr_reg + 1'b1;
+ rx_buffer_ctr_we = 1'b1;
+ end
+ else if (rx_buffer_ctr_dec)
+ begin
+ rx_buffer_ctr_new = rx_buffer_ctr_reg - 1'b1;
+ rx_buffer_ctr_we = 1'b1;
+ end
+
+ if (rx_buffer_ctr_reg == 4'h0)
+ begin
+ rx_buffer_empty = 1'b1;
+ end
+
+ if (rx_buffer_ctr_reg == BUFFER_MAX)
+ begin
+ rx_buffer_full = 1'b1;
+ end
+ end // rx_buffer_ctr
+
+
+ //----------------------------------------------------------------
+ // tx_buffer_ptr
+ //
+ // Logic for the tx buffer pointer. Supports reset and
+ // incremental updates.
+ //----------------------------------------------------------------
+ always @*
+ begin: tx_buffer_ptr
+ // Default assignments
+ tx_buffer_ptr_new = 4'h0;
+ tx_buffer_ptr_we = 1'b0;
+
+ if (tx_buffer_ptr_inc)
+ begin
+ tx_buffer_ptr_new = tx_buffer_ptr_reg + 1'b1;
+ tx_buffer_ptr_we = 1'b1;
+ end
+
+ else if (tx_buffer_ptr_rst)
+ begin
+ tx_buffer_ptr_new = 4'h0;
+ tx_buffer_ptr_we = 1'b1;
+ end
+ end // tx_buffer_ptr
+
+
+ //----------------------------------------------------------------
+ // rx_engine
+ //
+ // FSM responsible for handling receiving message bytes from the
+ // host interface and storing them in the receive buffer.
+ //----------------------------------------------------------------
+ always @*
+ begin: rx_engine
+ // Default assignments
+ rx_ack_new = 1'b0;
+ rx_ack_we = 1'b0;
+ rx_buffer_we = 1'b0;
+ rx_buffer_wr_ptr_inc = 1'b0;
+ rx_engine_new = RX_IDLE;
+ rx_engine_we = 1'b0;
+
+ case (rx_engine_reg)
+ RX_IDLE:
+ begin
+ if (rx_syn_reg)
+ begin
+ if (!rx_buffer_full)
+ begin
+ rx_buffer_we = 1'b1;
+ rx_engine_new = RX_ACK;
+ rx_engine_we = 1'b1;
+ end
+ end
+ end
+
+ RX_ACK:
+ begin
+ rx_ack_new = 1'b1;
+ rx_ack_we = 1'b1;
+ rx_buffer_wr_ptr_inc = 1'b1;
+ rx_engine_new = RX_NSYN;
+ rx_engine_we = 1'b1;
+ end
+
+ RX_NSYN:
+ begin
+ if (!rx_syn_reg)
+ begin
+ rx_ack_new = 1'b0;
+ rx_ack_we = 1'b1;
+ rx_engine_new = RX_IDLE;
+ rx_engine_we = 1;
+ end
+ end
+
+ default:
+ begin
+
+ end
+ endcase // case (rx_engine_reg)
+ end // rx_engine
+
+
+ //----------------------------------------------------------------
+ // tx_engine
+ //
+ // FSM responsible for handling transmitting message bytes
+ // to the host interface.
+ //----------------------------------------------------------------
+ always @*
+ begin: tx_engine
+ // Default assignments
+ tx_buffer_ptr_inc = 0;
+ tx_buffer_ptr_rst = 0;
+ response_sent_new = 0;
+ response_sent_we = 0;
+ tx_syn_new = 0;
+ tx_syn_we = 0;
+
+ tx_engine_new = TX_IDLE;
+ tx_engine_we = 0;
+
+ case (tx_engine_reg)
+ TX_IDLE:
+ begin
+ if (send_response_reg)
+ begin
+ tx_syn_new = 1;
+ tx_syn_we = 1;
+ tx_engine_new = TX_SYN;
+ tx_engine_we = 1;
+ end
+ end
+
+ TX_SYN:
+ begin
+ if (tx_ack_reg)
+ begin
+ tx_syn_new = 0;
+ tx_syn_we = 1;
+ tx_engine_new = TX_NOACK;
+ tx_engine_we = 1;
+ end
+ end
+
+ TX_NOACK:
+ begin
+ if (!tx_ack_reg)
+ begin
+ tx_engine_new = TX_NEXT;
+ tx_engine_we = 1;
+ end
+ end
+
+ TX_NEXT:
+ begin
+ if (tx_buffer_ptr_reg == tx_msg_len_reg)
+ begin
+ tx_engine_new = TX_SENT;
+ tx_engine_we = 1;
+ end
+ else
+ begin
+ tx_buffer_ptr_inc = 1;
+ tx_syn_new = 1;
+ tx_syn_we = 1;
+ tx_engine_new = TX_SYN;
+ tx_engine_we = 1;
+ end
+ end
+
+ TX_SENT:
+ begin
+ response_sent_new = 1;
+ response_sent_we = 1;
+ tx_engine_new = TX_DONE;
+ tx_engine_we = 1;
+ end
+
+ TX_DONE:
+ begin
+ response_sent_new = 0;
+ response_sent_we = 1;
+ tx_buffer_ptr_rst = 1;
+ tx_engine_new = TX_IDLE;
+ tx_engine_we = 1;
+ end
+
+ default:
+ begin
+ tx_engine_new = TX_IDLE;
+ tx_engine_we = 1;
+ end
+ endcase // case (tx_engine_reg)
+ end // tx_engine
+
+
+ //----------------------------------------------------------------
+ // test_engine
+ //
+ // Test engine FSM logic. Parses received commands, tries to
+ // execute the commands and assmbles the response to the
+ // given commands.
+ //----------------------------------------------------------------
+ always @*
+ begin: test_engine
+ // Default assignments.
+ core_reset_n_new = 1;
+ core_reset_n_we = 0;
+ core_cs_new = 0;
+ core_cs_we = 0;
+ core_we_new = 0;
+ core_we_we = 0;
+ sample_core_output = 0;
+ update_tx_buffer = 0;
+ response_type = 8'h00;
+ rx_buffer_rd_ptr_inc = 0;
+ cmd_we = 0;
+ core_addr_byte0_we = 0;
+ core_addr_byte1_we = 0;
+ core_wr_data_byte0_we = 0;
+ core_wr_data_byte1_we = 0;
+ core_wr_data_byte2_we = 0;
+ core_wr_data_byte3_we = 0;
+ send_response_new = 0;
+ send_response_we = 0;
+ test_engine_new = TEST_IDLE;
+ test_engine_we = 0;
+
+
+ case (test_engine_reg)
+ TEST_IDLE:
+ begin
+ if (!rx_buffer_empty)
+ begin
+ rx_buffer_rd_ptr_inc = 1;
+ if (rx_byte == SOC)
+ begin
+ test_engine_new = TEST_GET_CMD;
+ test_engine_we = 1;
+ end
+ end
+ end
+
+ TEST_GET_CMD:
+ begin
+ if (!rx_buffer_empty)
+ begin
+ rx_buffer_rd_ptr_inc = 1;
+ cmd_we = 1;
+ test_engine_new = TEST_PARSE_CMD;
+ test_engine_we = 1;
+ end
+ end
+
+ TEST_PARSE_CMD:
+ begin
+ case (cmd_reg)
+ RESET_CMD:
+ begin
+ test_engine_new = TEST_GET_EOC;
+ test_engine_we = 1;
+ end
+
+ READ_CMD:
+ begin
+ test_engine_new = TEST_GET_ADDR0;
+ test_engine_we = 1;
+ end
+
+ WRITE_CMD:
+ begin
+ test_engine_new = TEST_GET_ADDR0;
+ test_engine_we = 1;
+ end
+
+ default:
+ begin
+ test_engine_new = TEST_CMD_UNKNOWN;
+ test_engine_we = 1;
+ end
+ endcase // case (cmd_reg)
+ end
+
+
+ TEST_GET_ADDR0:
+ begin
+ if (!rx_buffer_empty)
+ begin
+ rx_buffer_rd_ptr_inc = 1;
+ core_addr_byte0_we = 1;
+ test_engine_new = TEST_GET_ADDR1;
+ test_engine_we = 1;
+ end
+ end
+
+
+ TEST_GET_ADDR1:
+ begin
+ if (!rx_buffer_empty)
+ begin
+ rx_buffer_rd_ptr_inc = 1;
+ core_addr_byte1_we = 1;
+
+ case (cmd_reg)
+ READ_CMD:
+ begin
+ test_engine_new = TEST_GET_EOC;
+ test_engine_we = 1;
+ end
+
+ WRITE_CMD:
+ begin
+ test_engine_new = TEST_GET_DATA0;
+ test_engine_we = 1;
+ end
+
+ default:
+ begin
+ test_engine_new = TEST_CMD_UNKNOWN;
+ test_engine_we = 1;
+ end
+ endcase // case (cmd_reg)
+ end
+ end
+
+
+ TEST_GET_DATA0:
+ begin
+ if (!rx_buffer_empty)
+ begin
+ rx_buffer_rd_ptr_inc = 1;
+ core_wr_data_byte0_we = 1;
+ test_engine_new = TEST_GET_DATA1;
+ test_engine_we = 1;
+ end
+ end
+
+
+ TEST_GET_DATA1:
+ begin
+ if (!rx_buffer_empty)
+ begin
+ rx_buffer_rd_ptr_inc = 1;
+ core_wr_data_byte1_we = 1;
+ test_engine_new = TEST_GET_DATA2;
+ test_engine_we = 1;
+ end
+ end
+
+
+ TEST_GET_DATA2:
+ begin
+ if (!rx_buffer_empty)
+ begin
+ rx_buffer_rd_ptr_inc = 1;
+ core_wr_data_byte2_we = 1;
+ test_engine_new = TEST_GET_DATA3;
+ test_engine_we = 1;
+ end
+ end
+
+
+ TEST_GET_DATA3:
+ begin
+ if (!rx_buffer_empty)
+ begin
+ rx_buffer_rd_ptr_inc = 1;
+ core_wr_data_byte3_we = 1;
+ test_engine_new = TEST_GET_EOC;
+ test_engine_we = 1;
+ end
+ end
+
+
+ TEST_GET_EOC:
+ begin
+ if (!rx_buffer_empty)
+ begin
+ rx_buffer_rd_ptr_inc = 1;
+ if (rx_byte == EOC)
+ begin
+ case (cmd_reg)
+ RESET_CMD:
+ begin
+ test_engine_new = TEST_RST_START;
+ test_engine_we = 1;
+ end
+
+ READ_CMD:
+ begin
+ test_engine_new = TEST_RD_START;
+ test_engine_we = 1;
+ end
+
+ WRITE_CMD:
+ begin
+ test_engine_new = TEST_WR_START;
+ test_engine_we = 1;
+ end
+
+ default:
+ begin
+ test_engine_new = TEST_CMD_UNKNOWN;
+ test_engine_we = 1;
+ end
+ endcase // case (cmd_reg)
+ end
+ else
+ begin
+ test_engine_new = TEST_CMD_ERROR;
+ test_engine_we = 1;
+ end
+ end
+ end
+
+
+ TEST_RST_START:
+ begin
+ core_reset_n_new = 0;
+ core_reset_n_we = 1;
+ test_engine_new = TEST_RST_WAIT;
+ test_engine_we = 1;
+ end
+
+
+ TEST_RST_WAIT:
+ begin
+ test_engine_new = TEST_RST_END;
+ test_engine_we = 1;
+ end
+
+
+ TEST_RST_END:
+ begin
+ core_reset_n_new = 1;
+ core_reset_n_we = 1;
+ update_tx_buffer = 1;
+ response_type = RESET_OK;
+ test_engine_new = TEST_SEND_RESPONSE;
+ test_engine_we = 1;
+ end
+
+
+ TEST_RD_START:
+ begin
+ core_cs_new = 1;
+ core_cs_we = 1;
+ test_engine_new = TEST_RD_WAIT;
+ test_engine_we = 1;
+ end
+
+
+ TEST_RD_WAIT:
+ begin
+ test_engine_new = TEST_RD_WAIT2;
+ test_engine_we = 1;
+ end
+
+
+ TEST_RD_WAIT2:
+ begin
+ sample_core_output = 1;
+ test_engine_new = TEST_RD_END;
+ test_engine_we = 1;
+ end
+
+
+ TEST_RD_END:
+ begin
+ core_cs_new = 0;
+ core_cs_we = 1;
+ sample_core_output = 0;
+
+ if (core_error_reg)
+ begin
+ update_tx_buffer = 1;
+ response_type = ERROR;
+ end
+ else
+ begin
+ update_tx_buffer = 1;
+ response_type = READ_OK;
+ end
+
+ test_engine_new = TEST_SEND_RESPONSE;
+ test_engine_we = 1;
+ end
+
+
+ TEST_WR_START:
+ begin
+ core_cs_new = 1;
+ core_cs_we = 1;
+ core_we_new = 1;
+ core_we_we = 1;
+
+ test_engine_new = TEST_WR_WAIT;
+ test_engine_we = 1;
+ end
+
+
+ TEST_WR_WAIT:
+ begin
+ sample_core_output = 1;
+ test_engine_new = TEST_WR_END;
+ test_engine_we = 1;
+ end
+
+
+ TEST_WR_END:
+ begin
+ core_cs_new = 0;
+ core_cs_we = 1;
+ core_we_new = 0;
+ core_we_we = 1;
+ sample_core_output = 0;
+
+ if (core_error_reg)
+ begin
+ update_tx_buffer = 1;
+ response_type = ERROR;
+ end
+ else
+ begin
+ update_tx_buffer = 1;
+ response_type = WRITE_OK;
+ end
+
+ test_engine_new = TEST_SEND_RESPONSE;
+ test_engine_we = 1;
+ end
+
+
+ TEST_CMD_UNKNOWN:
+ begin
+ update_tx_buffer = 1;
+ response_type = UNKNOWN;
+ test_engine_new = TEST_SEND_RESPONSE;
+ test_engine_we = 1;
+ end
+
+
+ TEST_CMD_ERROR:
+ begin
+ update_tx_buffer = 1;
+ response_type = ERROR;
+ test_engine_new = TEST_SEND_RESPONSE;
+ test_engine_we = 1;
+ end
+
+
+ TEST_SEND_RESPONSE:
+ begin
+ send_response_new = 1;
+ send_response_we = 1;
+ if (response_sent_reg)
+ begin
+ send_response_new = 0;
+ send_response_we = 1;
+ test_engine_new = TEST_IDLE;
+ test_engine_we = 1;
+ end
+ end
+
+
+ default:
+ begin
+ // If we encounter an unknown state we move
+ // back to idle.
+ test_engine_new = TEST_IDLE;
+ test_engine_we = 1;
+ end
+ endcase // case (test_engine_reg)
+ end // test_engine
+
+endmodule // coretest
+
+//======================================================================
+// EOF coretest.v
+//======================================================================
diff --git a/coretest/src/sw/seriedebug.py b/coretest/src/sw/seriedebug.py
new file mode 100755
index 0000000..2062116
--- /dev/null
+++ b/coretest/src/sw/seriedebug.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#=======================================================================
+#
+# seriedebug.py
+# -------------
+# Program that sends test bytes onto the serial link and print out
+# any response.
+#
+# Note: This proram requires the PySerial module.
+# http://pyserial.sourceforge.net/
+#
+#
+# Author: Joachim Strömbergson
+# Copyright (c) 2014 SUNET
+#
+# 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
+import serial
+
+
+#-------------------------------------------------------------------
+# main()
+#
+# Parse arguments.
+#-------------------------------------------------------------------
+def main():
+ print "Seriedebug started..."
+ print
+
+ verbose = True
+
+ # Create a serial devce and configure it.
+ # Should be:
+ # 1200 Baud
+ # 1 start bit
+ # 8 data bits
+ # 1 even parity bit
+ # 2 stop bits
+ # No RTS/CTS
+ # Note: You need to update to the correct device in your system.
+ ser = serial.Serial()
+ ser.port='/dev/cu.usbserial-A5020LKF'
+ ser.baudrate=1200
+ ser.bytesize=8
+ ser.parity='E'
+ ser.stopbits=2
+ ser.timeout=1
+ ser.writeTimeout=0
+
+ # Open the interface.
+ ser.open()
+ if verbose:
+ print "Opening device."
+
+ # Send a byte and try to get the response.
+ test_byte = '\xaa'
+ ser.write(test_byte)
+ if verbose:
+ print "transmitting byte 0x%0x" % ord(test_byte)
+
+
+ if verbose:
+ print "Waiting for response..."
+
+ response = ""
+ while not len(response):
+ response = ser.read()
+ if len(response):
+ print "received response: 0x%0x" % ord(response)
+
+ # Exit nicely.
+ if verbose:
+ print "Done. Closing device."
+ ser.close()
+
+
+#-------------------------------------------------------------------
+# __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 seriedebug.py
+#=======================================================================
diff --git a/coretest/src/tb/tb_coretest.v b/coretest/src/tb/tb_coretest.v
new file mode 100644
index 0000000..e70770d
--- /dev/null
+++ b/coretest/src/tb/tb_coretest.v
@@ -0,0 +1,492 @@
+//======================================================================
+//
+// tb_coretest.v
+// -------------
+// Testbench for coretest. Generates commands and observes responses.
+//
+//
+// 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/10ps
+
+
+module tb_coretest();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+ parameter VERBOSE = 0;
+ parameter CMD_MONITOR = 1;
+ parameter REC_MONITOR = 0;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = CLK_HALF_PERIOD * 2;
+
+ // Command and response constants.
+ parameter SOC = 8'h55;
+ parameter EOC = 8'haa;
+ parameter RESET_CMD = 8'h01;
+ parameter READ_CMD = 8'h10;
+ parameter WRITE_CMD = 8'h11;
+
+ parameter SOR = 8'haa;
+ parameter EOR = 8'h55;
+ parameter UNKNOWN = 8'hfe;
+ parameter ERROR = 8'hfd;
+ parameter READ_OK = 8'h7f;
+ parameter WRITE_OK = 8'h7e;
+ parameter RESET_OK = 8'h7d;
+
+ parameter MAX_MEM = 16'h00ff;
+
+
+ //----------------------------------------------------------------
+ // 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_rx_syn;
+ reg [7 : 0] tb_rx_data;
+ wire tb_rx_ack;
+ wire tb_tx_syn;
+ wire [7 : 0] tb_tx_data;
+ reg tb_tx_ack;
+
+ wire tb_core_reset_;
+ wire tb_core_cs;
+ wire tb_core_we;
+ wire [15 : 0] tb_core_address;
+ wire [31 : 0] tb_core_write_data;
+ reg [31 : 0] tb_core_read_data;
+ reg tb_core_error;
+
+ reg [7 : 0] received_tx_data;
+
+ reg [31 : 0] test_mem [0 : (MAX_MEM - 1'b1)];
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ coretest dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ // Interface to communication core
+ .rx_syn(tb_rx_syn),
+ .rx_data(tb_rx_data),
+ .rx_ack(tb_rx_ack),
+
+ .tx_syn(tb_tx_syn),
+ .tx_data(tb_tx_data),
+ .tx_ack(tb_tx_ack),
+
+ // Interface to the core being tested.
+ .core_reset_n(tb_core_reset_n),
+ .core_cs(tb_core_cs),
+ .core_we(tb_core_we),
+ .core_address(tb_core_address),
+ .core_write_data(tb_core_write_data),
+ .core_read_data(tb_core_read_data),
+ .core_error(tb_core_error)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor
+ //
+ // System monitor. Can display status about the dut and TB
+ // every cycle.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ #(CLK_PERIOD);
+ if (DEBUG)
+ begin
+ dump_dut_state();
+ $display("");
+ end
+
+ if (VERBOSE)
+ begin
+ $display("cycle: 0x%016x", cycle_ctr);
+ end
+ cycle_ctr = cycle_ctr + 1;
+ end
+
+
+ //----------------------------------------------------------------
+ // command_monitor
+ //
+ // Observes any read/write or reset commands generated
+ // by the DUT.
+ //----------------------------------------------------------------
+ always
+ begin : command_monitor
+ #(CLK_PERIOD);
+ if (CMD_MONITOR)
+ begin
+ if (!tb_core_reset_n)
+ begin
+ $display("Core is being reset by coretest.");
+ end
+
+ if (tb_core_cs)
+ begin
+ if (tb_core_we)
+ begin
+ $display("Core is being written to: address 0x%08x = 0x%08x",
+ tb_core_address, tb_core_write_data);
+ end
+ else
+ begin
+ $display("Core is being read from: address 0x%08x = 0x%08x",
+ tb_core_address, tb_core_read_data);
+ end
+ end
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // receive_logic
+ //
+ // The logic needed to the correct handshake expected by the DUT
+ // when it is sending bytes.
+ //----------------------------------------------------------------
+ always @ (posedge tb_clk)
+ begin : receive_logic
+ if (tb_tx_syn)
+ begin
+ if (REC_MONITOR)
+ begin
+ $display("Receiving byte 0x%02x from the DUT.", tb_tx_data);
+ end
+ #(2 * CLK_PERIOD);
+ tb_tx_ack = 1;
+
+ #(2 * CLK_PERIOD);
+ tb_tx_ack = 0;
+ end
+ end // receive_logic
+
+
+ //----------------------------------------------------------------
+ // test_mem_logic
+ //
+ // The logic needed to implement the test memory. We basically
+ // implement a simple memory to allow read and write operations
+ // via commands to the DUT to really be executed.
+ //----------------------------------------------------------------
+ always @ (posedge tb_clk)
+ begin : test_mem_logic
+ if (tb_core_cs)
+ begin
+ if (tb_core_we)
+ begin
+ if (tb_core_address < MAX_MEM)
+ begin
+ $display("Writing to test_mem[0x%08x] = 0x%08x",
+ tb_core_address, tb_core_write_data);
+ test_mem[tb_core_address] = tb_core_write_data;
+ end
+ else
+ begin
+ $display("Writing to incorrect address 0x%08x",
+ tb_core_address);
+ tb_core_error = 1;
+ end
+ end
+ else
+ begin
+ if (tb_core_address < MAX_MEM)
+ begin
+ $display("Reading from test_mem[0x%08x] = 0x%08x",
+ tb_core_address, tb_core_read_data);
+ tb_core_read_data = test_mem[tb_core_address];
+ end
+ else
+ begin
+ $display("Reading from incorrect address 0x%08x",
+ tb_core_address);
+ tb_core_error = 1;
+ end
+ end
+ end
+ else
+ begin
+ tb_core_read_data = 32'h00000000;
+ tb_core_error = 0;
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dut when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state();
+ begin
+ $display("State of DUT");
+ $display("------------");
+ $display("Inputs and outputs:");
+ $display("rx_syn = 0x%01x, rx_data = 0x%02x, rx_ack = 0x%01x",
+ dut.rx_syn, dut.rx_data, dut.rx_ack);
+ $display("tx_syn = 0x%01x, tx_data = 0x%02x, tx_ack = 0x%01x",
+ dut.tx_syn, dut.tx_data, dut.tx_ack);
+ $display("cs = 0x%01x, we = 0x%01x, address = 0x%04x, write_data = 0x%08x, read_data = 0x%08x, error = 0x%01x",
+ dut.core_cs, dut.core_we, dut.core_address, dut.core_write_data, dut.core_read_data, dut.core_error);
+ $display("");
+
+ $display("RX chain signals:");
+ $display("rx_buffer_wr_ptr = 0x%02x, rx_buffer_rd_ptr = 0x%02x, rx_buffer_ctr = 0x%02x, rx_buffer_empty = 0x%01x, rx_buffer_full = 0x%01x",
+ dut.rx_buffer_wr_ptr_reg, dut.rx_buffer_rd_ptr_reg, dut.rx_buffer_ctr_reg, dut.rx_buffer_empty, dut.rx_buffer_full);
+ $display("");
+
+ $display("Control signals and FSM state:");
+ $display("test_engine_reg = 0x%02x, cmd_reg = 0x%02x",
+ dut.test_engine_reg, dut.cmd_reg);
+ $display("");
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //----------------------------------------------------------------
+ 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();
+ reg [8 : 0] i;
+
+ begin
+ cycle_ctr = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+ tb_rx_syn = 0;
+ tb_rx_data = 8'h00;
+ tb_tx_ack = 0;
+
+ for (i = 0 ; i < 256 ; i = i + 1)
+ begin
+ test_mem[i[7 : 0]] = {4{i[7 : 0]}};
+ end
+ end
+ endtask // init_sim
+
+
+ //----------------------------------------------------------------
+ // send_byte
+ //
+ // Send a byte of data to the DUT.
+ //----------------------------------------------------------------
+ task send_byte(input [7 : 0] data);
+ integer i;
+ begin
+
+ if (VERBOSE)
+ begin
+ $display("*** Sending byte 0x%02x to the dut.", data);
+ $display("*** Setting RX data and RX SYN.");
+ end
+ tb_rx_data = data;
+ tb_rx_syn = 1;
+
+ while (!tb_rx_ack)
+ begin
+ #CLK_PERIOD;
+ if (VERBOSE)
+ begin
+ $display("*** Waiting for RX ACK.");
+ end
+ end
+
+ if (VERBOSE)
+ begin
+ $display("*** RX ACK seen. Dropping SYN.");
+ end
+ tb_rx_syn = 0;
+
+ #(2 * CLK_PERIOD);
+ end
+ endtask // send_byte
+
+
+ //----------------------------------------------------------------
+ // send_reset_command
+ //
+ // Generates a reset command to the dut.
+ //----------------------------------------------------------------
+ task send_reset_command();
+ begin
+ $display("*** Sending reset command.");
+ send_byte(SOC);
+ send_byte(RESET_CMD);
+ send_byte(EOC);
+ $display("*** Sending reset command done.");
+ end
+ endtask // send_write_command
+
+
+ //----------------------------------------------------------------
+ // send_read_command
+ //
+ // Generates a read command to the dut.
+ //----------------------------------------------------------------
+ task send_read_command(input [15 : 0] addr);
+ begin
+ $display("*** Sending read command: address 0x%04x.", addr);
+ send_byte(SOC);
+ send_byte(READ_CMD);
+ send_byte(addr[15 : 8]);
+ send_byte(addr[7 : 0]);
+ send_byte(EOC);
+ $display("*** Sending read command done.");
+ end
+ endtask // send_write_command
+
+
+ //----------------------------------------------------------------
+ // send_write_command
+ //
+ // Generates a write command to the dut.
+ //----------------------------------------------------------------
+ task send_write_command(input [15 : 0] addr, input [31 : 0] data);
+ begin
+ $display("*** Sending write command: address 0x%04x = 0x%08x.", addr, data);
+ send_byte(SOC);
+ send_byte(WRITE_CMD);
+ send_byte(addr[15 : 8]);
+ send_byte(addr[7 : 0]);
+ send_byte(data[31 : 24]);
+ send_byte(data[23 : 16]);
+ send_byte(data[15 : 8]);
+ send_byte(data[7 : 0]);
+ send_byte(EOC);
+ $display("*** Sending write command done.");
+ end
+ endtask // send_write_command
+
+
+ //----------------------------------------------------------------
+ // 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
+
+
+ //----------------------------------------------------------------
+ // coretest_test
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : coretest_test
+ $display(" -- Testbench for coretest started --");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+ #(64 * CLK_PERIOD);
+
+ send_reset_command();
+
+ send_read_command(16'h0023);
+ send_read_command(16'h0055);
+
+ send_write_command(16'h00aa, 32'h1337beef);
+ send_read_command(16'h00aa);
+ send_write_command(16'h0010, 32'h55aa55aa);
+ send_read_command(16'h0010);
+
+ #(200 * CLK_PERIOD);
+
+ display_test_result();
+ $display("*** Simulation done.");
+ $finish;
+ end // coretest_test
+endmodule // tb_coretest
+
+//======================================================================
+// EOF tb_coretest.v
+//======================================================================
diff --git a/coretest/toolruns/Makefile b/coretest/toolruns/Makefile
new file mode 100755
index 0000000..4a5d5d1
--- /dev/null
+++ b/coretest/toolruns/Makefile
@@ -0,0 +1,75 @@
+#===================================================================
+#
+# Makefile
+# --------
+# Makefile for building and simulating coretest.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2014 SUNET
+#
+# 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.
+#
+#===================================================================
+
+CORETEST_SRC=../src/rtl/coretest.v
+CORETEST_TB_SRC=../src/tb/tb_coretest.v
+CORETEST_TARGET = coretest.sim
+
+CC=iverilog
+
+
+all: coretest
+
+
+coretest: $(CORETEST_TB_SRC) $(CORETEST_SRC)
+ $(CC) -o $(CORETEST_TARGET) $(CORETEST_TB_SRC) $(CORETEST_SRC)
+
+
+sim-coretest: $(CORETEST_TARGET)
+ ./$(CORETEST_TARGET)
+
+
+debug:
+ @echo "No debug available."
+
+
+clean:
+ rm -f $(CORETEST_TARGET)
+
+
+help:
+ @echo "Supported targets:"
+ @echo "------------------"
+ @echo "coretest: Build coretest simulation target."
+ @echo "sim-coretest: Run coretest simulation."
+ @echo "debug: Print the internal varibles."
+ @echo "clean: Delete all built files."
+
+#===================================================================
+# EOF Makefile
+#===================================================================
+
diff --git a/coretest/toolruns/modelsim/coretest_wave.do b/coretest/toolruns/modelsim/coretest_wave.do
new file mode 100644
index 0000000..d7abc8e
--- /dev/null
+++ b/coretest/toolruns/modelsim/coretest_wave.do
@@ -0,0 +1,80 @@
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/clk
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/reset_n
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_syn
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_data
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_ack
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_syn
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_data
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_ack
+add wave -noupdate -divider <NULL>
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_reset_n
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_cs
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_we
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_address
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_write_data
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_read_data
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_error
+add wave -noupdate -divider <NULL>
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_reset_n_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_cs_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_we_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/send_response_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/response_sent_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/cmd_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_addr_byte0_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_addr_byte1_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_wr_data_byte0_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_wr_data_byte1_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_wr_data_byte2_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_wr_data_byte3_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_read_data_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/core_error_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/sample_core_output
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_buffer_rd_ptr_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_buffer_rd_ptr_inc
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_buffer_wr_ptr_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_buffer_wr_ptr_inc
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_buffer_ctr_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_buffer_ctr_inc
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_buffer_ctr_dec
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_buffer_full
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_buffer_empty
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_buffer
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_ptr_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_ptr_inc
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_engine_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_engine_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/test_engine_reg
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_muxed0
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_muxed1
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_muxed2
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_muxed3
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_muxed4
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_muxed5
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_muxed6
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_muxed7
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/tx_buffer_muxed8
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/update_tx_buffer
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/response_type
+add wave -noupdate -radix hexadecimal /tb_coretest/dut/rx_byte
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 1} {361000 ps} 0}
+quietly wave cursor active 1
+configure wave -namecolwidth 290
+configure wave -valuecolwidth 203
+configure wave -justifyvalue left
+configure wave -signalnamewidth 0
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+configure wave -timelineunits ps
+update
+WaveRestoreZoom {0 ps} {451500 ps}
diff --git a/eim/src/rtl/cdc_bus_pulse.v b/eim/src/rtl/cdc_bus_pulse.v
new file mode 100644
index 0000000..cc2d8db
--- /dev/null
+++ b/eim/src/rtl/cdc_bus_pulse.v
@@ -0,0 +1,145 @@
+//======================================================================
+//
+// cdc_bus_pulse.v
+// ---------------
+// Clock Domain Crossing handler for the Cryptech Novena
+// FPGA framework design.
+//
+// This module is based on design suggested on page 27 of the
+// paper 'Clock Domain Crossing (CDC) Design & Verification Techniques
+// Using SystemVerilog' by Clifford E. Cummings (Sunburst Design, Inc.)
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2015, 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 cdc_bus_pulse
+ #(parameter DATA_WIDTH = 32) // width of data bus
+ (
+ input wire src_clk, // source domain clock
+ input wire [DATA_WIDTH-1:0] src_din, // data from source clock domain
+ input wire src_req, // start transfer pulse from source clock domain
+
+ input wire dst_clk, // destination domain clock
+ output wire [DATA_WIDTH-1:0] dst_dout, // data to destination clock domain
+ output wire dst_pulse // transfer done pulse to destination clock domain
+ );
+
+ //
+ // Source Side Registers
+ //
+ reg src_ff = 1'b0; // transfer request flag
+ reg [DATA_WIDTH-1:0] src_latch = {DATA_WIDTH{1'bX}}; // source data buffer
+
+
+ //
+ // Source Request Handler
+ //
+ always @(posedge src_clk)
+ //
+ if (src_req) begin // transfer request pulse?
+ src_ff <= ~src_ff; // toggle transfer request flag...
+ src_latch <= src_din; // ... and capture data in source buffer
+ end
+
+
+ //
+ // Source -> Destination Flag Sync Logic
+ //
+
+ /* ISE may decide to infer SRL here, so we explicitly instantiate slice registers. */
+
+ wire flag_sync_first; // first FF output
+ wire flag_sync_second; // second FF output
+ wire flag_sync_third; // third FF output
+ wire flag_sync_pulse; // flag toggle detector output
+
+ FDCE ff_sync_first
+ (
+ .C(dst_clk),
+ .D(src_ff), // capture flag from another clock domain
+ .Q(flag_sync_first), // metastability can occur here
+ .CLR(1'b0),
+ .CE(1'b1)
+ );
+ FDCE ff_sync_second
+ (
+ .C(dst_clk),
+ .D(flag_sync_first), // synchronize captured flag to remove metastability
+ .Q(flag_sync_second), // and pass it to another flip-flop
+ .CLR(1'b0),
+ .CE(1'b1)
+ );
+ FDCE ff_sync_third
+ (
+ .C(dst_clk),
+ .D(flag_sync_second), // delay synchronized flag in another flip-flip, because we need
+ .Q(flag_sync_third), // two synchronized flag values (current and delayed) to detect its change
+ .CLR(1'b0),
+ .CE(1'b1)
+ );
+
+ // when delayed flag value differs from its current value, it was changed
+ // by the source side, so there must have been a transfer request
+ assign flag_sync_pulse = flag_sync_second ^ flag_sync_third;
+
+
+ //
+ // Destination Side Registers
+ //
+ reg dst_pulse_reg = 1'b0; // transfer done flag
+ reg [DATA_WIDTH-1:0] dst_latch = {DATA_WIDTH{1'bX}}; // destination data buffer
+
+ assign dst_pulse = dst_pulse_reg;
+ assign dst_dout = dst_latch;
+
+ //
+ // Destination Request Handler
+ //
+ always @(posedge dst_clk) begin
+ //
+ dst_pulse_reg <= flag_sync_pulse; // generate pulse if flag change was detected
+ //
+ if (flag_sync_pulse)
+ dst_latch <= src_latch;
+ /* By the time destination side receives synchronized flag
+ * value, data should be stable, we can safely capture and store
+ * it in the destination buffer.
+ */
+
+ end
+
+
+endmodule
+
+//======================================================================
+// EOF cdc_bus_pulse.v
+//======================================================================
diff --git a/eim/src/rtl/eim.v b/eim/src/rtl/eim.v
new file mode 100644
index 0000000..dcbd226
--- /dev/null
+++ b/eim/src/rtl/eim.v
@@ -0,0 +1,75 @@
+`define USE_EIM
+
+module eim
+ (
+ // EIM interface pins from CPU
+ input wire eim_bclk, // EIM burst clock. Started by the CPU.
+ input wire eim_cs0_n, // Chip select (active low).
+ inout wire [15 : 0] eim_da, // Bidirectional address and data port.
+ input wire [18: 16] eim_a, // MSB part of address port.
+ input wire eim_lba_n, // Latch address signal (active low).
+ input wire eim_wr_n, // write enable signal (active low).
+ input wire eim_oe_n, // output enable signal (active low).
+ output wire eim_wait_n, // Data wait signal (active low).
+
+ // system clock and reset
+ input wire sys_clk,
+ input wire sys_rst,
+
+ // EIM interface to cores
+ output wire [16: 0] sys_eim_addr,
+ output wire sys_eim_wr,
+ output wire sys_eim_rd,
+ output wire [31: 0] sys_eim_dout,
+ input wire [31: 0] sys_eim_din,
+
+ // Novena utility ports
+ output wire led_pin // LED on edge close to the FPGA.
+ );
+
+ // XXX add NAME0/NAME1/VERSION
+
+ //----------------------------------------------------------------
+ // EIM Arbiter
+ //
+ // EIM arbiter handles EIM access and transfers it into
+ // `sys_clk' clock domain.
+ //----------------------------------------------------------------
+
+ eim_arbiter eim
+ (
+ .eim_bclk(eim_bclk),
+ .eim_cs0_n(eim_cs0_n),
+ .eim_da(eim_da),
+ .eim_a(eim_a),
+ .eim_lba_n(eim_lba_n),
+ .eim_wr_n(eim_wr_n),
+ .eim_oe_n(eim_oe_n),
+ .eim_wait_n(eim_wait_n),
+
+ .sys_clk(sys_clk),
+
+ .sys_addr(sys_eim_addr),
+ .sys_wren(sys_eim_wr),
+ .sys_data_out(sys_eim_dout),
+ .sys_rden(sys_eim_rd),
+ .sys_data_in(sys_eim_din)
+ );
+
+
+ //----------------------------------------------------------------
+ // LED Driver
+ //
+ // A simple utility LED driver that turns on the Novena
+ // board LED when the EIM interface is active.
+ //----------------------------------------------------------------
+ eim_indicator led
+ (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+ .eim_active(sys_eim_wr | sys_eim_rd),
+ .led_out(led_pin)
+ );
+
+
+endmodule // eim
diff --git a/eim/src/rtl/eim_arbiter.v b/eim/src/rtl/eim_arbiter.v
new file mode 100644
index 0000000..e9b2c76
--- /dev/null
+++ b/eim/src/rtl/eim_arbiter.v
@@ -0,0 +1,309 @@
+//======================================================================
+//
+// eim_arbiter.v
+// -------------
+// Port arbiter for the EIM interface for the Cryptech
+// Novena FPGA framework.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2015, 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 eim_arbiter
+ (
+ // eim bus
+ input wire eim_bclk,
+ input wire eim_cs0_n,
+ inout wire [15: 0] eim_da,
+ input wire [18:16] eim_a,
+ input wire eim_lba_n,
+ input wire eim_wr_n,
+ input wire eim_oe_n,
+ output wire eim_wait_n,
+
+ // system clock
+ input wire sys_clk,
+
+ // user bus
+ output wire [16: 0] sys_addr,
+ output wire sys_wren,
+ output wire [31: 0] sys_data_out,
+ output wire sys_rden,
+ input wire [31: 0] sys_data_in
+ );
+
+
+ //
+ // Data/Address PHY
+ //
+
+ /* PHY is needed to control bi-directional address/data bus. */
+
+ wire [15: 0] da_ro; // value read from pins
+ reg [15: 0] da_di; // value drives onto pins
+
+ eim_da_phy da_phy
+ (
+ .buf_io(eim_da), // <-- connect directly top-level port
+ .buf_di(da_di),
+ .buf_ro(da_ro),
+ .buf_t(eim_oe_n) // <-- driven by EIM directly
+ );
+
+
+ //
+ // FSM
+ //
+ localparam EIM_FSM_STATE_INIT = 5'b0_0_000; // arbiter is idle
+
+ localparam EIM_FSM_STATE_WRITE_START = 5'b1_1_000; // got address to write at
+ localparam EIM_FSM_STATE_WRITE_LSB = 5'b1_1_001; // got lower 16 bits of data to write
+ localparam EIM_FSM_STATE_WRITE_MSB = 5'b1_1_010; // got upper 16 bits of data to write
+ localparam EIM_FSM_STATE_WRITE_WAIT = 5'b1_1_100; // request to user-side logic sent
+ localparam EIM_FSM_STATE_WRITE_DONE = 5'b1_1_111; // user-side logic acknowledged transaction
+
+ localparam EIM_FSM_STATE_READ_START = 5'b1_0_000; // got address to read from
+ localparam EIM_FSM_STATE_READ_WAIT = 5'b1_0_100; // request to user-side logic sent
+ localparam EIM_FSM_STATE_READ_READY = 5'b1_0_011; // got acknowledge from user logic
+ localparam EIM_FSM_STATE_READ_LSB = 5'b1_0_001; // returned lower 16 bits to master
+ localparam EIM_FSM_STATE_READ_MSB = 5'b1_0_010; // returned upper 16 bits to master
+ localparam EIM_FSM_STATE_READ_DONE = 5'b1_0_111; // transaction complete
+
+ reg [ 4: 0] eim_fsm_state = EIM_FSM_STATE_INIT; // fsm state
+ reg [16: 0] eim_addr_latch = {17{1'bX}}; // transaction address
+ reg [15: 0] eim_write_lsb_latch = {16{1'bX}}; // lower 16 bits of data to write
+
+ /* These flags are used to wake up from INIT state. */
+ wire eim_write_start_flag = (eim_lba_n == 1'b0) && (eim_wr_n == 1'b0) && (da_ro[1:0] == 2'b00);
+ wire eim_read_start_flag = (eim_lba_n == 1'b0) && (eim_wr_n == 1'b1) && (da_ro[1:0] == 2'b00);
+
+ /* These are transaction response flag and data from user-side logic. */
+ wire eim_user_ack;
+ wire [31: 0] eim_user_data;
+
+ /* FSM is reset whenever Chip Select is de-asserted. */
+
+ //
+ // FSM Transition Logic
+ //
+ always @(posedge eim_bclk or posedge eim_cs0_n)
+ begin
+ //
+ if (eim_cs0_n == 1'b1)
+ eim_fsm_state <= EIM_FSM_STATE_INIT;
+ //
+ else
+ begin
+ //
+ case (eim_fsm_state)
+ //
+ // INIT -> WRITE, INIT -> READ
+ //
+ EIM_FSM_STATE_INIT:
+ begin
+ if (eim_write_start_flag)
+ eim_fsm_state <= EIM_FSM_STATE_WRITE_START;
+ if (eim_read_start_flag)
+ eim_fsm_state <= EIM_FSM_STATE_READ_START;
+ end
+ //
+ // WRITE
+ //
+ EIM_FSM_STATE_WRITE_START:
+ eim_fsm_state <= EIM_FSM_STATE_WRITE_LSB;
+ //
+ EIM_FSM_STATE_WRITE_LSB:
+ eim_fsm_state <= EIM_FSM_STATE_WRITE_MSB;
+ //
+ EIM_FSM_STATE_WRITE_MSB:
+ eim_fsm_state <= EIM_FSM_STATE_WRITE_WAIT;
+ //
+ EIM_FSM_STATE_WRITE_WAIT:
+ if (eim_user_ack)
+ eim_fsm_state <= EIM_FSM_STATE_WRITE_DONE;
+ //
+ EIM_FSM_STATE_WRITE_DONE:
+ eim_fsm_state <= EIM_FSM_STATE_INIT;
+ //
+ // READ
+ //
+ EIM_FSM_STATE_READ_START:
+ eim_fsm_state <= EIM_FSM_STATE_READ_WAIT;
+ //
+ EIM_FSM_STATE_READ_WAIT:
+ if (eim_user_ack)
+ eim_fsm_state <= EIM_FSM_STATE_READ_READY;
+ //
+ EIM_FSM_STATE_READ_READY:
+ eim_fsm_state <= EIM_FSM_STATE_READ_LSB;
+ //
+ EIM_FSM_STATE_READ_LSB:
+ eim_fsm_state <= EIM_FSM_STATE_READ_MSB;
+ //
+ EIM_FSM_STATE_READ_MSB:
+ eim_fsm_state <= EIM_FSM_STATE_READ_DONE;
+ //
+ EIM_FSM_STATE_READ_DONE:
+ eim_fsm_state <= EIM_FSM_STATE_INIT;
+ //
+ //
+ //
+ default:
+ eim_fsm_state <= EIM_FSM_STATE_INIT;
+ //
+ endcase
+ //
+ end
+ //
+ end
+
+
+ //
+ // Address Latch
+ //
+ always @(posedge eim_bclk)
+ //
+ if ((eim_fsm_state == EIM_FSM_STATE_INIT) && (eim_write_start_flag || eim_read_start_flag))
+ eim_addr_latch <= {eim_a[18:16], da_ro[15:2]};
+
+
+ //
+ // Additional Write Logic
+ //
+ always @(posedge eim_bclk)
+ //
+ if (eim_fsm_state == EIM_FSM_STATE_WRITE_START)
+ eim_write_lsb_latch <= da_ro;
+
+
+ //
+ // Additional Read Logic
+ //
+
+ /* Note that this stuff operates on falling clock edge, because the cpu
+ * samples our bi-directional data bus on rising clock edge.
+ */
+
+ always @(negedge eim_bclk or posedge eim_cs0_n)
+ //
+ if (eim_cs0_n == 1'b1) da_di <= {16{1'bX}}; // don't care what to drive
+ else begin
+ //
+ if (eim_fsm_state == EIM_FSM_STATE_READ_LSB)
+ da_di <= eim_user_data[15: 0]; // drive lower 16 bits at first...
+ if (eim_fsm_state == EIM_FSM_STATE_READ_MSB)
+ da_di <= eim_user_data[31:16]; // ...then drive upper 16 bits
+ //
+ end
+
+
+ //
+ // Wait Logic
+ //
+
+ /* Note that this stuff operates on falling clock edge, because the cpu
+ * samples our WAIT_N flag on rising clock edge.
+ */
+
+ reg eim_wait_reg = 1'b0;
+
+ always @(negedge eim_bclk or posedge eim_cs0_n)
+ //
+ if (eim_cs0_n == 1'b1)
+ eim_wait_reg <= 1'b0; // clear wait
+ else begin
+ //
+ if (eim_fsm_state == EIM_FSM_STATE_WRITE_START)
+ eim_wait_reg <= 1'b1; // start waiting for write to complete
+ if (eim_fsm_state == EIM_FSM_STATE_READ_START)
+ eim_wait_reg <= 1'b1; // start waiting for read to complete
+ //
+ if (eim_fsm_state == EIM_FSM_STATE_WRITE_DONE)
+ eim_wait_reg <= 1'b0; // write transaction done
+ if (eim_fsm_state == EIM_FSM_STATE_READ_READY)
+ eim_wait_reg <= 1'b0; // read transaction done
+ //
+ if (eim_fsm_state == EIM_FSM_STATE_INIT)
+ eim_wait_reg <= 1'b0; // fsm is idle, no need to wait any more
+ //
+ end
+
+ assign eim_wait_n = ~eim_wait_reg;
+
+
+ /* These flags are used to generate 1-cycle pulses to trigger CDC
+ * transaction. Note that FSM goes from WRITE_LSB to WRITE_MSB and from
+ * READ_START to READ_WAIT unconditionally, so these flags will always be
+ * active for 1 cycle only, which is exactly what we need.
+ */
+
+ wire arbiter_write_req_pulse = (eim_fsm_state == EIM_FSM_STATE_WRITE_LSB) ? 1'b1 : 1'b0;
+ wire arbiter_read_req_pulse = (eim_fsm_state == EIM_FSM_STATE_READ_START) ? 1'b1 : 1'b0;
+
+ //
+ // CDC Block
+ //
+
+ /* This block is used to transfer request data from BCLK clock domain to
+ * SYS_CLK clock domain and then transfer acknowledge from SYS_CLK to BCLK
+ * clock domain in return. Af first 1+1+3+14+32 = 51 bits are transfered,
+ * these are: write flag, read flag, msb part of address, lsb part of address,
+ * write data. During read transaction some bogus write data is passed,
+ * which is not used later anyway. During read requests 32 bits of data are
+ * returned, during write requests 32 bits of bogus data are returned, that
+ * are never used later.
+ */
+
+ eim_arbiter_cdc eim_cdc
+ (
+ .eim_clk(eim_bclk),
+
+ .eim_req(arbiter_write_req_pulse | arbiter_read_req_pulse),
+ .eim_ack(eim_user_ack),
+
+ .eim_din({arbiter_write_req_pulse, arbiter_read_req_pulse,
+ eim_addr_latch, da_ro, eim_write_lsb_latch}),
+ .eim_dout(eim_user_data),
+
+ .sys_clk(sys_clk),
+ .sys_addr(sys_addr),
+ .sys_wren(sys_wren),
+ .sys_data_out(sys_data_out),
+ .sys_rden(sys_rden),
+ .sys_data_in(sys_data_in)
+ );
+
+
+endmodule
+
+//======================================================================
+// EOF eim_arbiter.v
+//======================================================================
diff --git a/eim/src/rtl/eim_arbiter_cdc.v b/eim/src/rtl/eim_arbiter_cdc.v
new file mode 100644
index 0000000..15dc433
--- /dev/null
+++ b/eim/src/rtl/eim_arbiter_cdc.v
@@ -0,0 +1,143 @@
+//======================================================================
+//
+// eim_arbiter_cdc.v
+// -----------------
+// The actual clock domain crossing handler od the EIM arbiter
+// for the Cryptech Novena FPGA framework.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2015, 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 eim_arbiter_cdc
+ (
+ input wire eim_clk, // eim clock
+ input wire eim_req, // eim transaction request
+ output wire eim_ack, // eim transaction acknowledge
+ input wire [50: 0] eim_din, // data from cpu to fpga (write access)
+ output wire [31: 0] eim_dout, // data from fpga to cpu (read access)
+
+ input wire sys_clk, // user internal clock
+ output wire [16: 0] sys_addr, // user access address
+ output wire sys_wren, // user write flag
+ output wire [31: 0] sys_data_out, // user write data
+ output wire sys_rden, // user read flag
+ input wire [31: 0] sys_data_in // user read data
+ );
+
+
+ //
+ // EIM_CLK -> SYS_CLK Request
+ //
+ wire sys_req; // request pulse in sys_clk clock domain
+ wire [50: 0] sys_dout; // transaction data in sys_clk clock domain
+
+ cdc_bus_pulse #
+ (
+ .DATA_WIDTH(51) // {write, read, msb addr, lsb addr, data}
+ )
+ cdc_eim_sys
+ (
+ .src_clk(eim_clk),
+ .src_din(eim_din),
+ .src_req(eim_req),
+
+ .dst_clk(sys_clk),
+ .dst_dout(sys_dout),
+ .dst_pulse(sys_req)
+ );
+
+
+ //
+ // Output Registers
+ //
+ reg sys_wren_reg = 1'b0;
+ reg sys_rden_reg = 1'b0;
+ reg [16: 0] sys_addr_reg = {17{1'bX}};
+ reg [31: 0] sys_data_out_reg = {32{1'bX}};
+
+ assign sys_wren = sys_wren_reg;
+ assign sys_rden = sys_rden_reg;
+ assign sys_addr = sys_addr_reg;
+ assign sys_data_out = sys_data_out_reg;
+
+
+ //
+ // System (User) Clock Access Handler
+ //
+ always @(posedge sys_clk)
+ //
+ if (sys_req) // request detected?
+ begin
+ sys_wren_reg <= sys_dout[50]; // set write flag if needed
+ sys_rden_reg <= sys_dout[49]; // set read flag if needed
+ sys_addr_reg <= sys_dout[48:32]; // set operation address
+ sys_data_out_reg <= sys_dout[31: 0]; // set data to write
+ end
+ else // no request active
+ begin
+ sys_wren_reg <= 1'b0; // clear write flag
+ sys_rden_reg <= 1'b0; // clear read flag
+ end
+
+
+ //
+ // System Request 2-cycle delay to compensate registered mux delay in user-side logic
+ //
+ reg [ 1: 0] sys_req_dly = 2'b00;
+
+ always @(posedge sys_clk)
+ sys_req_dly <= {sys_req_dly[0], sys_req};
+
+
+ //
+ // SYS_CLK -> EIM_CLK Acknowledge
+ //
+ cdc_bus_pulse #
+ (
+ .DATA_WIDTH(32)
+ )
+ cdc_sys_eim
+ (
+ .src_clk(sys_clk),
+ .src_din(sys_data_in),
+ .src_req(sys_req_dly[1]),
+
+ .dst_clk(eim_clk),
+ .dst_dout(eim_dout),
+ .dst_pulse(eim_ack)
+ );
+
+endmodule
+
+//======================================================================
+// EOF eim_arbiter_cdc.v
+//======================================================================
diff --git a/eim/src/rtl/eim_da_phy.v b/eim/src/rtl/eim_da_phy.v
new file mode 100644
index 0000000..8a4a8d7
--- /dev/null
+++ b/eim/src/rtl/eim_da_phy.v
@@ -0,0 +1,77 @@
+//======================================================================
+//
+// eim_da_phy.v
+// ------------
+// IO buffer module for the EIM DA port.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2015, 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 eim_da_phy
+ #(parameter BUS_WIDTH = 16)
+ (
+ inout wire [BUS_WIDTH-1:0] buf_io, // connect directly to top-level pins
+ input wire [BUS_WIDTH-1:0] buf_di, // drive input (value driven onto pins)
+ output wire [BUS_WIDTH-1:0] buf_ro, // receiver output (value read from pins)
+ input wire buf_t // tristate control (driver is disabled during tristate)
+ );
+
+ //
+ // IOBUFs
+ //
+ genvar i;
+ generate
+ for (i = 0; i < BUS_WIDTH; i = i+1)
+ begin: eim_da
+ //
+ IOBUF #
+ (
+ .IOSTANDARD("LVCMOS33"),
+ .DRIVE(12),
+ .SLEW("FAST")
+ )
+ IOBUF_inst
+ (
+ .IO(buf_io[i]),
+ .O(buf_ro[i]),
+ .I(buf_di[i]),
+ .T(buf_t)
+ );
+ //
+ end
+ endgenerate
+
+endmodule
+
+//======================================================================
+// EOF eim_da_phy.v
+//======================================================================
diff --git a/eim/src/rtl/eim_indicator.v b/eim/src/rtl/eim_indicator.v
new file mode 100644
index 0000000..cf9751d
--- /dev/null
+++ b/eim/src/rtl/eim_indicator.v
@@ -0,0 +1,69 @@
+//======================================================================
+//
+// eim_indicator.v
+// ---------------
+// A simple LED indicator to show that the EIM is alive.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2015, 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 eim_indicator
+ (
+ input wire sys_clk,
+ input wire sys_rst,
+ input wire eim_active,
+ output wire led_out
+ );
+
+ //
+ // Parameters
+ //
+ localparam CNT_BITS = 24; // led will be dim for 2**(24-1) = 8388608 ticks, which is ~100 ms @ 80 MHz.
+
+ //
+ // Counter
+ //
+ reg [CNT_BITS-1:0] cnt;
+
+ 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}};
+
+ assign led_out = ~cnt[CNT_BITS-1];
+
+endmodule
+
+//======================================================================
+// EOF eim_indicator.v
+//======================================================================
diff --git a/i2c/LICENSE b/i2c/LICENSE
new file mode 100644
index 0000000..0fb159c
--- /dev/null
+++ b/i2c/LICENSE
@@ -0,0 +1,24 @@
+Author: Joachim Strömbergson
+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:
+
+* 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.
+
+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/i2c/README.md b/i2c/README.md
new file mode 100644
index 0000000..24edcbb
--- /dev/null
+++ b/i2c/README.md
@@ -0,0 +1,7 @@
+i2c
+===
+
+An I2C slave implemented in Verilog.
+
+The core i2c functionality is based on Bunnie Huang's i2c_slave.v from the
+novena-ws2312b-fpga project (https://github.com/xobs/novena-ws2812b-fpga).
diff --git a/i2c/src/rtl/i2c.v b/i2c/src/rtl/i2c.v
new file mode 100644
index 0000000..4a3bc5d
--- /dev/null
+++ b/i2c/src/rtl/i2c.v
@@ -0,0 +1,217 @@
+//======================================================================
+//
+// i2c.v
+// ------
+// Top level wrapper for the i2c core.
+//
+// A simple I2C interface.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+//
+// 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 i2c(
+ input wire clk,
+ input wire reset_n,
+
+ // External interface.
+ input wire SCL,
+ input wire SDA,
+ output wire SDA_pd,
+ output wire [6:0] i2c_device_addr,
+
+ // Internal receive interface.
+ output wire rxd_syn,
+ output [7 : 0] rxd_data,
+ input wire rxd_ack,
+
+ // Internal transmit interface.
+ input wire txd_syn,
+ input wire [7 : 0] txd_data,
+ output wire txd_ack,
+
+ // API interface.
+ 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,
+
+ // Debug output.
+ output wire [7 : 0] debug
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ // API addresses.
+ parameter ADDR_CORE_NAME0 = 8'h00;
+ parameter ADDR_CORE_NAME1 = 8'h01;
+ parameter ADDR_CORE_TYPE = 8'h02;
+ parameter ADDR_CORE_VERSION = 8'h03;
+
+ // Core ID constants.
+ parameter CORE_NAME0 = 32'h69326320; // "i2c "
+ parameter CORE_NAME1 = 32'h20202020; // " "
+ parameter CORE_TYPE = 32'h20202031; // " 1"
+ parameter CORE_VERSION = 32'h302e3031; // "0.01"
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+
+ wire core_SCL;
+ wire core_SDA;
+ wire core_SDA_pd;
+
+ wire core_rxd_syn;
+ wire [7 : 0] core_rxd_data;
+ wire core_rxd_ack;
+
+ wire core_txd_syn;
+ wire [7 : 0] core_txd_data;
+ wire core_txd_ack;
+
+ reg [31 : 0] tmp_read_data;
+ reg tmp_error;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign core_SCL = SCL;
+ assign core_SDA = SDA;
+ assign SDA_pd = core_SDA_pd;
+
+ assign rxd_syn = core_rxd_syn;
+ assign rxd_data = core_rxd_data;
+ assign core_rxd_ack = rxd_ack;
+
+ assign core_txd_syn = txd_syn;
+ assign core_txd_data = txd_data;
+ assign txd_ack = core_txd_ack;
+
+ assign read_data = tmp_read_data;
+ assign error = tmp_error;
+
+ assign debug = core_rxd_data;
+
+
+ //----------------------------------------------------------------
+ // core
+ //
+ // Instantiation of the i2c core.
+ //----------------------------------------------------------------
+ i2c_core core(
+ .clk(clk),
+ .reset(reset_n),
+
+ // External data interface
+ .SCL(core_SCL),
+ .SDA(core_SDA),
+ .SDA_pd(core_SDA_pd),
+ .i2c_device_addr(i2c_device_addr),
+
+ // Internal receive interface.
+ .rxd_syn(core_rxd_syn),
+ .rxd_data(core_rxd_data),
+ .rxd_ack(core_rxd_ack),
+
+ // Internal transmit interface.
+ .txd_syn(core_txd_syn),
+ .txd_data(core_txd_data),
+ .txd_ack(core_txd_ack)
+ );
+
+
+ //----------------------------------------------------------------
+ // api
+ //
+ // The core API that allows an internal host to control the
+ // core functionality.
+ //----------------------------------------------------------------
+ always @*
+ begin: api
+ // Default assignments.
+ tmp_read_data = 32'h00000000;
+ tmp_error = 0;
+
+ if (cs)
+ begin
+ if (we)
+ begin
+ // Write operations.
+ case (address)
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end
+ else
+ begin
+ // Read operations.
+ case (address)
+ ADDR_CORE_NAME0:
+ begin
+ tmp_read_data = CORE_NAME0;
+ end
+
+ ADDR_CORE_NAME1:
+ begin
+ tmp_read_data = CORE_NAME1;
+ end
+
+ ADDR_CORE_TYPE:
+ begin
+ tmp_read_data = CORE_TYPE;
+ end
+
+ ADDR_CORE_VERSION:
+ begin
+ tmp_read_data = CORE_VERSION;
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end
+ end
+ end
+
+endmodule // i2c
+
+//======================================================================
+// EOF i2c.v
+//======================================================================
diff --git a/i2c/src/rtl/i2c_core.v b/i2c/src/rtl/i2c_core.v
new file mode 100644
index 0000000..798c105
--- /dev/null
+++ b/i2c/src/rtl/i2c_core.v
@@ -0,0 +1,580 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2011, Andrew "bunnie" Huang
+// 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.
+//
+// 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.
+//
+//////////////////////////////////////////////////////////////////////////////
+// A simple I2C slave implementation. Oversampled for robustness.
+// The slave is extended into the snoop & surpress version for the DDC bus;
+// this is just a starting point for basic testing and also simple comms
+// with the CPU.
+//
+// i2c slave module requires the top level module to implement the IOBs
+// This is just to keep the tri-state easy to implemen across the hierarchy
+//
+// The code required on the top level is:
+// IOBUF #(.DRIVE(12), .SLEW("SLOW")) IOBUF_sda (.IO(SDA), .I(1'b0), .T(!SDA_pd));
+//
+///////////
+`timescale 1 ns / 1 ps
+
+// This file is based on https://github.com/bunnie/novena-gpbb-fpga/blob/master/novena-gpbb.srcs/sources_1/imports/imports/i2c_slave.v
+//
+// For Cryptech, we replaced the register interface with the rxd/txd
+// interface to coretest, and changed i2c_device_addr from an 8-bit
+// input to a 7-bit output.
+
+module i2c_core (
+ input wire clk,
+ input wire reset,
+
+ // External data interface
+ input wire SCL,
+ input wire SDA,
+ output reg SDA_pd,
+ output wire [6:0] i2c_device_addr,
+
+ // Internal receive interface.
+ output wire rxd_syn,
+ output [7 : 0] rxd_data,
+ input wire rxd_ack,
+
+ // Internal transmit interface.
+ input wire txd_syn,
+ input wire [7 : 0] txd_data,
+ output wire txd_ack
+ );
+
+ /////// I2C physical layer components
+ /// SDA is stable when SCL is high.
+ /// If SDA moves while SCL is high, this is considered a start or stop condition.
+ ///
+ /// Otherwise, SDA can move around when SCL is low (this is where we suppress bits or
+ /// overdrive as needed). SDA is a wired-AND bus, so you only "drive" zero.
+ ///
+ /// In an oversampled implementation, a rising and falling edge de-glitcher is needed
+ /// for SCL and SDA.
+ ///
+
+ // rise fall time cycles computation:
+ // At 400kHz operation, 2.5us is a cycle. "chatter" from transition should be about
+ // 5% of total cycle time max (just rule of thumb), so 0.125us should be the equiv
+ // number of cycles.
+ // For the demo board, a 25 MHz clock is provided, and 0.125us ~ 4 cycles
+ // At 100kHz operation, 10us is a cycle, so 0.5us ~ 12 cycles
+ parameter TRF_CYCLES = 5'd4; // number of cycles for rise/fall time
+
+ ////////////////
+ ///// protocol-level state machine
+ ////////////////
+ parameter I2C_START = 16'b1 << 0; // should only pass through this state for one cycle
+ parameter I2C_RESTART = 16'b1 << 1;
+ parameter I2C_DADDR = 16'b1 << 2;
+ parameter I2C_ACK_DADDR = 16'b1 << 3;
+ parameter I2C_WR_DATA = 16'b1 << 4;
+ parameter I2C_ACK_WR = 16'b1 << 5;
+ parameter I2C_END_WR = 16'b1 << 6;
+ parameter I2C_RD_DATA = 16'b1 << 7;
+ parameter I2C_ACK_RD = 16'b1 << 8;
+ parameter I2C_END_RD = 16'b1 << 9;
+ parameter I2C_END_RD2 = 16'b1 << 10;
+ parameter I2C_WAITSTOP = 16'b1 << 11;
+ parameter I2C_RXD_SYN = 16'b1 << 12;
+ parameter I2C_RXD_ACK = 16'b1 << 13;
+ parameter I2C_TXD_SYN = 16'b1 << 14;
+ parameter I2C_TXD_ACK = 16'b1 << 15;
+
+ parameter I2C_nSTATES = 16;
+
+ reg [(I2C_nSTATES-1):0] I2C_cstate = {{(I2C_nSTATES-1){1'b0}}, 1'b1}; //current and next states
+ reg [(I2C_nSTATES-1):0] I2C_nstate;
+
+//`define SIMULATION
+`ifdef SIMULATION
+ // synthesis translate_off
+ reg [8*20:1] I2C_state_ascii = "I2C_START ";
+ always @(I2C_cstate) begin
+ if (I2C_cstate == I2C_START) I2C_state_ascii <= "I2C_START ";
+ else if (I2C_cstate == I2C_RESTART) I2C_state_ascii <= "I2C_RESTART ";
+ else if (I2C_cstate == I2C_DADDR) I2C_state_ascii <= "I2C_DADDR ";
+ else if (I2C_cstate == I2C_ACK_DADDR) I2C_state_ascii <= "I2C_ACK_DADDR ";
+ else if (I2C_cstate == I2C_WR_DATA) I2C_state_ascii <= "I2C_WR_DATA ";
+ else if (I2C_cstate == I2C_ACK_WR) I2C_state_ascii <= "I2C_ACK_WR ";
+ else if (I2C_cstate == I2C_END_WR) I2C_state_ascii <= "I2C_END_WR ";
+ else if (I2C_cstate == I2C_RD_DATA) I2C_state_ascii <= "I2C_RD_DATA ";
+ else if (I2C_cstate == I2C_ACK_RD) I2C_state_ascii <= "I2C_ACK_RD ";
+ else if (I2C_cstate == I2C_END_RD) I2C_state_ascii <= "I2C_END_RD ";
+ else if (I2C_cstate == I2C_END_RD2) I2C_state_ascii <= "I2C_END_RD2 ";
+ else if (I2C_cstate == I2C_WAITSTOP) I2C_state_ascii <= "I2C_WAITSTOP ";
+ else if (I2C_cstate == I2C_RXD_SYN) I2C_state_ascii <= "I2C_RXD_SYN ";
+ else if (I2C_cstate == I2C_RXD_ACK) I2C_state_ascii <= "I2C_RXD_ACK ";
+ else if (I2C_cstate == I2C_TXD_SYN) I2C_state_ascii <= "I2C_TXD_SYN ";
+ else if (I2C_cstate == I2C_TXD_ACK) I2C_state_ascii <= "I2C_TXD_ACK ";
+ else I2C_state_ascii <= "WTF ";
+ end
+ // synthesis translate_on
+`endif
+
+ reg [3:0] I2C_bitcnt;
+ reg [7:0] I2C_daddr;
+ reg [7:0] I2C_wdata;
+ reg [7:0] I2C_rdata;
+
+ reg rxd_syn_reg;
+ reg txd_ack_reg;
+
+ assign rxd_data = I2C_wdata;
+ assign rxd_syn = rxd_syn_reg;
+ assign txd_ack = txd_ack_reg;
+ assign i2c_device_addr = I2C_daddr[7:1];
+
+ ////////// code begins here
+ always @ (posedge clk) begin
+ if (reset || ((SCL_cstate == SCL_HIGH) && (SDA_cstate == SDA_RISE))) // stop condition always resets
+ I2C_cstate <= I2C_START;
+ else
+ I2C_cstate <= I2C_nstate;
+ end
+
+ always @ (*) begin
+ case (I2C_cstate)
+ I2C_START: begin // wait for the start condition
+ I2C_nstate = ((SDA_cstate == SDA_FALL) && (SCL_cstate == SCL_HIGH)) ? I2C_DADDR : I2C_START;
+ end
+ I2C_RESTART: begin // repeated start moves immediately to DADDR
+ I2C_nstate = I2C_DADDR;
+ end
+
+ // device address branch
+ I2C_DADDR: begin // 8 bits to get the address
+ I2C_nstate = ((I2C_bitcnt > 4'h7) && (SCL_cstate == SCL_FALL)) ? I2C_ACK_DADDR : I2C_DADDR;
+ end
+ I2C_ACK_DADDR: begin // depending upon W/R bit state, go to one of two branches
+ I2C_nstate = (SCL_cstate == SCL_FALL) ?
+ (I2C_daddr[0] == 1'b0 ? I2C_WR_DATA : I2C_TXD_SYN) :
+ I2C_ACK_DADDR; // !SCL_FALL
+ end
+
+ // write branch
+ I2C_WR_DATA: begin // 8 bits to get the write data
+ I2C_nstate = ((SDA_cstate == SDA_FALL) && (SCL_cstate == SCL_HIGH)) ? I2C_RESTART : // repeated start
+ ((I2C_bitcnt > 4'h7) && (SCL_cstate == SCL_FALL)) ? I2C_RXD_SYN : I2C_WR_DATA;
+ end
+ I2C_RXD_SYN: begin // put data on the coretest bus
+ I2C_nstate = I2C_RXD_ACK;
+ end
+ I2C_RXD_ACK: begin // wait for coretest ack
+ I2C_nstate = rxd_ack ? I2C_ACK_WR : I2C_RXD_ACK;
+ end
+ I2C_ACK_WR: begin // trigger the ack response (pull SDA low until next falling edge)
+ // and stay in this state until the next falling edge of SCL
+ I2C_nstate = (SCL_cstate == SCL_FALL) ? I2C_END_WR : I2C_ACK_WR;
+ end
+ I2C_END_WR: begin // one-cycle state to update address+1, reset SDA pulldown
+ I2C_nstate = I2C_WR_DATA; // SCL is now low
+ end
+
+ // read branch
+ I2C_TXD_SYN: begin // get data from the coretest bus
+ // if data isn't available (txd_syn isn't asserted) by the time we
+ // get to this state, it probably never will be, so skip it
+ I2C_nstate = txd_syn ? I2C_TXD_ACK : I2C_RD_DATA;
+ end
+ I2C_TXD_ACK: begin // send coretest ack
+ // hold ack high until syn is lowered
+ I2C_nstate = txd_syn ? I2C_TXD_ACK : I2C_RD_DATA;
+ end
+ I2C_RD_DATA: begin // 8 bits to get the read data
+ I2C_nstate = ((SDA_cstate == SDA_FALL) && (SCL_cstate == SCL_HIGH)) ? I2C_RESTART : // repeated start
+ ((I2C_bitcnt > 4'h7) && (SCL_cstate == SCL_FALL)) ? I2C_ACK_RD : I2C_RD_DATA;
+ end
+ I2C_ACK_RD: begin // wait for an (n)ack response
+ // need to sample (n)ack on a rising edge
+ I2C_nstate = (SCL_cstate == SCL_RISE) ? I2C_END_RD : I2C_ACK_RD;
+ end
+ I2C_END_RD: begin // if nack, just go to start state (don't explicitly check stop event)
+ // single cycle state for adr+1 update
+ I2C_nstate = (SDA_cstate == SDA_LOW) ? I2C_END_RD2 : I2C_START;
+ end
+ I2C_END_RD2: begin // before entering I2C_RD_DATA, we need to have seen a falling edge.
+ I2C_nstate = (SCL_cstate == SCL_FALL) ? I2C_RD_DATA : I2C_END_RD2;
+ end
+
+ // we're not the addressed device, so we just idle until we see a stop
+ I2C_WAITSTOP: begin
+ I2C_nstate = (((SCL_cstate == SCL_HIGH) && (SDA_cstate == SDA_RISE))) ? // stop
+ I2C_START :
+ (((SCL_cstate == SCL_HIGH) && (SDA_cstate == SDA_FALL))) ? // or start
+ I2C_RESTART :
+ I2C_WAITSTOP;
+ end
+ endcase // case (cstate)
+ end
+
+ always @ (posedge clk) begin
+ if( reset ) begin
+ I2C_bitcnt <= 4'b0;
+ I2C_daddr <= 8'b0;
+ I2C_wdata <= 8'b0;
+ SDA_pd <= 1'b0;
+ I2C_rdata <= 8'b0;
+ end else begin
+ case (I2C_cstate)
+ I2C_START: begin // everything in reset
+ I2C_bitcnt <= 4'b0;
+ I2C_daddr <= 8'b0;
+ I2C_wdata <= 8'b0;
+ I2C_rdata <= 8'b0;
+ SDA_pd <= 1'b0;
+ end
+
+ I2C_RESTART: begin
+ I2C_bitcnt <= 4'b0;
+ I2C_daddr <= 8'b0;
+ I2C_wdata <= 8'b0;
+ I2C_rdata <= 8'b0;
+ SDA_pd <= 1'b0;
+ end
+
+ // get my i2c device address (am I being talked to?)
+ I2C_DADDR: begin // shift in the address on rising edges of clock
+ if( SCL_cstate == SCL_RISE ) begin
+ I2C_bitcnt <= I2C_bitcnt + 4'b1;
+ I2C_daddr[7] <= I2C_daddr[6];
+ I2C_daddr[6] <= I2C_daddr[5];
+ I2C_daddr[5] <= I2C_daddr[4];
+ I2C_daddr[4] <= I2C_daddr[3];
+ I2C_daddr[3] <= I2C_daddr[2];
+ I2C_daddr[2] <= I2C_daddr[1];
+ I2C_daddr[1] <= I2C_daddr[0];
+ I2C_daddr[0] <= (SDA_cstate == SDA_HIGH) ? 1'b1 : 1'b0;
+ end else begin // we're oversampled so we need a hold-state gutter
+ I2C_bitcnt <= I2C_bitcnt;
+ I2C_daddr <= I2C_daddr;
+ end // else: !if( SCL_cstate == SCL_RISE )
+ SDA_pd <= 1'b0;
+ I2C_wdata <= 8'b0;
+ I2C_rdata <= 8'b0;
+ end // case: I2C_DADDR
+ I2C_ACK_DADDR: begin
+ SDA_pd <= 1'b1; // active pull down ACK
+ I2C_daddr <= I2C_daddr;
+ I2C_bitcnt <= 4'b0;
+ I2C_wdata <= 8'b0;
+ I2C_rdata <= 8'b0;
+ end
+
+ // write branch
+ I2C_WR_DATA: begin // shift in data on rising edges of clock
+ if( SCL_cstate == SCL_RISE ) begin
+ I2C_bitcnt <= I2C_bitcnt + 4'b1;
+ I2C_wdata[7] <= I2C_wdata[6];
+ I2C_wdata[6] <= I2C_wdata[5];
+ I2C_wdata[5] <= I2C_wdata[4];
+ I2C_wdata[4] <= I2C_wdata[3];
+ I2C_wdata[3] <= I2C_wdata[2];
+ I2C_wdata[2] <= I2C_wdata[1];
+ I2C_wdata[1] <= I2C_wdata[0];
+ I2C_wdata[0] <= (SDA_cstate == SDA_HIGH) ? 1'b1 : 1'b0;
+ end else begin
+ I2C_bitcnt <= I2C_bitcnt; // hold state gutter
+ I2C_wdata <= I2C_wdata;
+ end // else: !if( SCL_cstate == SCL_RISE )
+ SDA_pd <= 1'b0;
+ I2C_daddr <= I2C_daddr;
+ I2C_rdata <= I2C_rdata;
+ end // case: I2C_WR_DATA
+ I2C_RXD_SYN: begin // put data on the coretest bus and raise syn
+ rxd_syn_reg <= 1;
+ end
+ I2C_RXD_ACK: begin // wait for coretest ack
+ if (rxd_ack)
+ rxd_syn_reg <= 0;
+ end
+ I2C_ACK_WR: begin
+ SDA_pd <= 1'b1; // active pull down ACK
+ I2C_daddr <= I2C_daddr;
+ I2C_bitcnt <= 4'b0;
+ I2C_wdata <= I2C_wdata;
+ I2C_rdata <= I2C_rdata;
+ end
+ I2C_END_WR: begin
+ SDA_pd <= 1'b0; // let SDA rise (host may look for this to know ack is done
+ I2C_bitcnt <= 4'b0;
+ I2C_wdata <= 8'b0;
+ I2C_rdata <= I2C_rdata;
+ I2C_daddr <= I2C_daddr;
+ end
+
+ // read branch
+ I2C_TXD_SYN: begin // get data from the coretest bus
+ if (txd_syn) begin
+ I2C_rdata <= txd_data;
+ txd_ack_reg <= 1;
+ end
+ end
+ I2C_TXD_ACK: begin // send coretest ack
+ if (!txd_syn)
+ txd_ack_reg <= 0;
+ end
+ I2C_RD_DATA: begin // shift out data on falling edges of clock
+ SDA_pd <= I2C_rdata[7] ? 1'b0 : 1'b1;
+ if( SCL_cstate == SCL_RISE ) begin
+ I2C_bitcnt <= I2C_bitcnt + 4'b1;
+ end else begin
+ I2C_bitcnt <= I2C_bitcnt; // hold state gutter
+ end
+
+ if( SCL_cstate == SCL_FALL ) begin
+ I2C_rdata[7] <= I2C_rdata[6];
+ I2C_rdata[6] <= I2C_rdata[5];
+ I2C_rdata[5] <= I2C_rdata[4];
+ I2C_rdata[4] <= I2C_rdata[3];
+ I2C_rdata[3] <= I2C_rdata[2];
+ I2C_rdata[2] <= I2C_rdata[1];
+ I2C_rdata[1] <= I2C_rdata[0];
+ I2C_rdata[0] <= 1'b0;
+ end else begin
+ I2C_rdata <= I2C_rdata;
+ end // else: !if( SCL_cstate == SCL_RISE )
+ I2C_daddr <= I2C_daddr;
+ I2C_wdata <= I2C_wdata;
+ end // case: I2C_RD_DATA
+ I2C_ACK_RD: begin
+ SDA_pd <= 1'b0; // in ack state don't pull down, we are listening to host
+ I2C_daddr <= I2C_daddr;
+ I2C_bitcnt <= 4'b0;
+ I2C_rdata <= I2C_rdata;
+ I2C_wdata <= I2C_wdata;
+ end
+ I2C_END_RD: begin
+ SDA_pd <= 1'b0; // let SDA rise (host may look for this to know ack is done
+ I2C_daddr <= I2C_daddr;
+ I2C_bitcnt <= 4'b0;
+ I2C_rdata <= I2C_rdata;
+ I2C_wdata <= I2C_wdata;
+ end
+ I2C_END_RD2: begin
+ SDA_pd <= 1'b0;
+ I2C_daddr <= 8'b0;
+ I2C_bitcnt <= 4'b0;
+ I2C_rdata <= I2C_rdata;
+ I2C_wdata <= I2C_wdata;
+ end
+
+ I2C_WAITSTOP: begin
+ SDA_pd <= 1'b0;
+ I2C_daddr <= 8'b0;
+ I2C_bitcnt <= 4'b0;
+ I2C_rdata <= I2C_rdata;
+ I2C_wdata <= I2C_wdata;
+ end
+ endcase // case (cstate)
+ end // else: !if( reset )
+ end // always @ (posedge clk or posedge reset)
+
+
+ ///////////////////////////////////////////////////////////////
+ /////////// low level state machines //////////////////////////
+ ///////////////////////////////////////////////////////////////
+
+
+ ////////////////
+ ///// SCL low-level sampling state machine
+ ////////////////
+ parameter SCL_HIGH = 4'b1 << 0; // should only pass through this state for one cycle
+ parameter SCL_FALL = 4'b1 << 1;
+ parameter SCL_LOW = 4'b1 << 2;
+ parameter SCL_RISE = 4'b1 << 3;
+ parameter SCL_nSTATES = 4;
+
+ reg [(SCL_nSTATES-1):0] SCL_cstate = {{(SCL_nSTATES-1){1'b0}}, 1'b1}; //current and next states
+ reg [(SCL_nSTATES-1):0] SCL_nstate;
+
+//`define SIMULATION
+`ifdef SIMULATION
+ // synthesis translate_off
+ reg [8*20:1] SCL_state_ascii = "SCL_HIGH ";
+
+ always @(SCL_cstate) begin
+ if (SCL_cstate == SCL_HIGH) SCL_state_ascii <= "SCL_HIGH ";
+ else if (SCL_cstate == SCL_FALL) SCL_state_ascii <= "SCL_FALL ";
+ else if (SCL_cstate == SCL_LOW ) SCL_state_ascii <= "SCL_LOW ";
+ else if (SCL_cstate == SCL_RISE) SCL_state_ascii <= "SCL_RISE ";
+ else SCL_state_ascii <= "WTF ";
+ end
+ // synthesis translate_on
+`endif
+
+ reg [4:0] SCL_rfcnt;
+ reg SCL_s, SCL_sync;
+ reg SDA_s, SDA_sync;
+
+ always @ (posedge clk) begin
+ if (reset)
+ SCL_cstate <= SCL_HIGH; // always start here even if it's wrong -- easier to test
+ else
+ SCL_cstate <= SCL_nstate;
+ end
+
+ always @ (*) begin
+ case (SCL_cstate)
+ SCL_HIGH: begin
+ SCL_nstate = ((SCL_rfcnt > TRF_CYCLES) && (SCL_sync == 1'b0)) ? SCL_FALL : SCL_HIGH;
+ end
+ SCL_FALL: begin
+ SCL_nstate = SCL_LOW;
+ end
+ SCL_LOW: begin
+ SCL_nstate = ((SCL_rfcnt > TRF_CYCLES) && (SCL_sync == 1'b1)) ? SCL_RISE : SCL_LOW;
+ end
+ SCL_RISE: begin
+ SCL_nstate = SCL_HIGH;
+ end
+ endcase // case (cstate)
+ end // always @ (*)
+
+ always @ (posedge clk) begin
+ if( reset ) begin
+ SCL_rfcnt <= 5'b0;
+ end else begin
+ case (SCL_cstate)
+ SCL_HIGH: begin
+ if( SCL_sync == 1'b1 ) begin
+ SCL_rfcnt <= 5'b0;
+ end else begin
+ SCL_rfcnt <= SCL_rfcnt + 5'b1;
+ end
+ end
+ SCL_FALL: begin
+ SCL_rfcnt <= 5'b0;
+ end
+ SCL_LOW: begin
+ if( SCL_sync == 1'b0 ) begin
+ SCL_rfcnt <= 5'b0;
+ end else begin
+ SCL_rfcnt <= SCL_rfcnt + 5'b1;
+ end
+ end
+ SCL_RISE: begin
+ SCL_rfcnt <= 5'b0;
+ end
+ endcase // case (cstate)
+ end // else: !if( reset )
+ end // always @ (posedge clk or posedge reset)
+
+
+ ////////////////
+ ///// SDA low-level sampling state machine
+ ////////////////
+ parameter SDA_HIGH = 4'b1 << 0; // should only pass through this state for one cycle
+ parameter SDA_FALL = 4'b1 << 1;
+ parameter SDA_LOW = 4'b1 << 2;
+ parameter SDA_RISE = 4'b1 << 3;
+ parameter SDA_nSTATES = 4;
+
+ reg [(SDA_nSTATES-1):0] SDA_cstate = {{(SDA_nSTATES-1){1'b0}}, 1'b1}; //current and next states
+ reg [(SDA_nSTATES-1):0] SDA_nstate;
+
+//`define SIMULATION
+`ifdef SIMULATION
+ // synthesis translate_off
+ reg [8*20:1] SDA_state_ascii = "SDA_HIGH ";
+
+ always @(SDA_cstate) begin
+ if (SDA_cstate == SDA_HIGH) SDA_state_ascii <= "SDA_HIGH ";
+ else if (SDA_cstate == SDA_FALL) SDA_state_ascii <= "SDA_FALL ";
+ else if (SDA_cstate == SDA_LOW ) SDA_state_ascii <= "SDA_LOW ";
+ else if (SDA_cstate == SDA_RISE) SDA_state_ascii <= "SDA_RISE ";
+ else SDA_state_ascii <= "WTF ";
+ end
+ // synthesis translate_on
+`endif
+
+ reg [4:0] SDA_rfcnt;
+
+ always @ (posedge clk) begin
+ if (reset)
+ SDA_cstate <= SDA_HIGH; // always start here even if it's wrong -- easier to test
+ else
+ SDA_cstate <= SDA_nstate;
+ end
+
+ always @ (*) begin
+ case (SDA_cstate)
+ SDA_HIGH: begin
+ SDA_nstate = ((SDA_rfcnt > TRF_CYCLES) && (SDA_sync == 1'b0)) ? SDA_FALL : SDA_HIGH;
+ end
+ SDA_FALL: begin
+ SDA_nstate = SDA_LOW;
+ end
+ SDA_LOW: begin
+ SDA_nstate = ((SDA_rfcnt > TRF_CYCLES) && (SDA_sync == 1'b1)) ? SDA_RISE : SDA_LOW;
+ end
+ SDA_RISE: begin
+ SDA_nstate = SDA_HIGH;
+ end
+ endcase // case (cstate)
+ end // always @ (*)
+
+ always @ (posedge clk) begin
+ if( reset ) begin
+ SDA_rfcnt <= 5'b0;
+ end else begin
+ case (SDA_cstate)
+ SDA_HIGH: begin
+ if( SDA_sync == 1'b1 ) begin
+ SDA_rfcnt <= 5'b0;
+ end else begin
+ SDA_rfcnt <= SDA_rfcnt + 5'b1;
+ end
+ end
+ SDA_FALL: begin
+ SDA_rfcnt <= 5'b0;
+ end
+ SDA_LOW: begin
+ if( SDA_sync == 1'b0 ) begin
+ SDA_rfcnt <= 5'b0;
+ end else begin
+ SDA_rfcnt <= SDA_rfcnt + 5'b1;
+ end
+ end
+ SDA_RISE: begin
+ SDA_rfcnt <= 5'b0;
+ end
+ endcase // case (cstate)
+ end // else: !if( reset )
+ end // always @ (posedge clk or posedge reset)
+
+
+
+ /////////////////////
+ /////// synchronizers
+ /////////////////////
+ always @ (posedge clk) begin
+ SCL_s <= SCL;
+ SCL_sync <= SCL_s;
+ SDA_s <= SDA;
+ SDA_sync <= SDA_s;
+ end // always @ (posedge clk or posedge reset)
+
+endmodule // i2c_slave
diff --git a/novena/build/.gitignore b/novena/build/.gitignore
new file mode 100644
index 0000000..01d7e9c
--- /dev/null
+++ b/novena/build/.gitignore
@@ -0,0 +1,52 @@
+*.xrpt
+_xmsgs
+default.xreport
+netlist.lst
+*.bgn
+*.bit
+*.bld
+*.cfi
+*.drc
+*.lso
+*.lso
+*.map
+*.mcs
+*.mrp
+*.ncd
+*.ngc
+*.ngd
+*.ngm
+*.pcf
+*.post_map.twr
+*.post_map.twx
+*.prj
+*.prm
+*.psr
+*.scr
+*.srp
+*.twr
+*.twx
+*_bd.bmm
+*_bitgen.xwb
+*_bitgen.xwbt
+*_err.twr
+*_err.twx
+*_par.grf
+*_par.ncd
+*_par.pad
+*_par.par
+*_par.ptwx
+*_par.unroutes
+*_par.xpi
+*_par_pad.csv
+*_par_pad.txt
+*_summary.xml
+*_usage.xml
+par_usage_statistics.html
+smartguide.ncd
+smartpreview.twr
+smartpreview.twr
+usage_statistics_webtalk.html
+webtalk.log
+xlnx_auto*
+xst
diff --git a/novena/build/Makefile.eim b/novena/build/Makefile.eim
new file mode 100644
index 0000000..6544fdd
--- /dev/null
+++ b/novena/build/Makefile.eim
@@ -0,0 +1,39 @@
+project = novena_reorg_eim
+vendor = xilinx
+family = spartan6
+part = xc6slx45csg324-3
+top_module = novena_baseline_top
+isedir = /opt/Xilinx/14.7/ISE_DS
+xil_env = . $(isedir)/settings64.sh
+ucf = ../src/ucf/novena_eim.ucf
+
+vfiles = \
+ ../src/rtl/novena_eim.v \
+ ../src/rtl/novena_clkmgr.v \
+ ../src/rtl/ipcore/clkmgr_dcm.v \
+ ../src/rtl/novena_regs.v \
+ ../../eim/src/rtl/eim.v \
+ ../../eim/src/rtl/eim_arbiter.v \
+ ../../eim/src/rtl/eim_arbiter_cdc.v \
+ ../../eim/src/rtl/cdc_bus_pulse.v \
+ ../../eim/src/rtl/eim_da_phy.v \
+ ../../eim/src/rtl/eim_indicator.v \
+ ../../core_selector/src/rtl/core_selector.v \
+ ../../core_selector/src/rtl/hash_selector.v \
+ ../../core_selector/src/rtl/rng_selector.v \
+ ../../core_selector/src/rtl/cipher_selector.v \
+ ../../sha1/src/rtl/sha1.v \
+ ../../sha1/src/rtl/sha1_core.v \
+ ../../sha1/src/rtl/sha1_w_mem.v \
+ ../../sha256/src/rtl/sha256.v \
+ ../../sha256/src/rtl/sha256_core.v \
+ ../../sha256/src/rtl/sha256_k_constants.v \
+ ../../sha256/src/rtl/sha256_w_mem.v \
+ ../../sha256/src/rtl/wb_sha256.v \
+ ../../sha512/src/rtl/sha512.v \
+ ../../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
+
+include xilinx.mk
diff --git a/novena/build/Makefile.i2c b/novena/build/Makefile.i2c
new file mode 100644
index 0000000..267e33b
--- /dev/null
+++ b/novena/build/Makefile.i2c
@@ -0,0 +1,36 @@
+project = novena_reorg_i2c
+vendor = xilinx
+family = spartan6
+part = xc6slx45csg324-3
+top_module = novena_baseline_top
+isedir = /opt/Xilinx/14.7/ISE_DS
+xil_env = . $(isedir)/settings64.sh
+ucf = ../src/ucf/novena_i2c.ucf
+
+vfiles = \
+ ../src/rtl/novena_i2c.v \
+ ../src/rtl/novena_clkmgr.v \
+ ../src/rtl/ipcore/clkmgr_dcm.v \
+ ../src/rtl/novena_regs.v \
+ ../../i2c/src/rtl/i2c.v \
+ ../../i2c/src/rtl/i2c_core.v \
+ ../../coretest/src/rtl/coretest.v \
+ ../../core_selector/src/rtl/core_selector.v \
+ ../../core_selector/src/rtl/hash_selector.v \
+ ../../core_selector/src/rtl/rng_selector.v \
+ ../../core_selector/src/rtl/cipher_selector.v \
+ ../../sha1/src/rtl/sha1.v \
+ ../../sha1/src/rtl/sha1_core.v \
+ ../../sha1/src/rtl/sha1_w_mem.v \
+ ../../sha256/src/rtl/sha256.v \
+ ../../sha256/src/rtl/sha256_core.v \
+ ../../sha256/src/rtl/sha256_k_constants.v \
+ ../../sha256/src/rtl/sha256_w_mem.v \
+ ../../sha256/src/rtl/wb_sha256.v \
+ ../../sha512/src/rtl/sha512.v \
+ ../../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
+
+include xilinx.mk
diff --git a/novena/build/xilinx.mk b/novena/build/xilinx.mk
new file mode 100644
index 0000000..f35cc98
--- /dev/null
+++ b/novena/build/xilinx.mk
@@ -0,0 +1,174 @@
+# The top level module should define the variables below then include
+# this file. The files listed should be in the same directory as the
+# Makefile.
+#
+# variable description
+# ---------- -------------
+# project project name (top level module should match this name)
+# top_module top level module of the project
+# libdir path to library directory
+# libs library modules used
+# vfiles all local .v files
+# xilinx_cores all local .xco files
+# vendor vendor of FPGA (xilinx, altera, etc.)
+# family FPGA device family (spartan3e)
+# part FPGA part name (xc4vfx12-10-sf363)
+# flashsize size of flash for mcs file (16384)
+# optfile (optional) xst extra opttions file to put in .scr
+# map_opts (optional) options to give to map
+# par_opts (optional) options to give to par
+# intstyle (optional) intstyle option to all tools
+# ucf constraint file, defaults to $(project).ucf
+#
+# Library modules should have a modules.mk in their root directory,
+# namely $(libdir)/<libname>/module.mk, that simply adds to the vfiles
+# and xilinx_cores variable.
+#
+# all the .xco files listed in xilinx_cores will be generated with core, with
+# the resulting .v and .ngc files placed back in the same directory as
+# the .xco file.
+#
+# TODO: .xco files are device dependant, should use a template based system
+
+coregen_work_dir ?= ./coregen-tmp
+map_opts ?= -timing -ol high -detail -pr b -register_duplication -w
+par_opts ?= -ol high
+isedir ?= /opt/Xilinx/13.3/ISE_DS
+xil_env ?= . $(isedir)/settings32.sh
+flashsize ?= 8192
+ucf ?= $(project).ucf
+
+libmks = $(patsubst %,$(libdir)/%/module.mk,$(libs))
+mkfiles = $(libmks) xilinx.mk
+include $(libmks)
+
+corengcs = $(foreach core,$(xilinx_cores),$(core:.xco=.ngc))
+local_corengcs = $(foreach ngc,$(corengcs),$(notdir $(ngc)))
+vfiles += $(foreach core,$(xilinx_cores),$(core:.xco=.v))
+junk += $(local_corengcs)
+
+.PHONY: default xilinx_cores clean twr etwr
+default: $(project).bit $(project).mcs
+xilinx_cores: $(corengcs)
+twr: $(project).twr
+etwr: $(project)_err.twr
+
+define cp_template
+$(2): $(1)
+ cp $(1) $(2)
+endef
+$(foreach ngc,$(corengcs),$(eval $(call cp_template,$(ngc),$(notdir $(ngc)))))
+
+%.ngc %.v: %.xco
+ @echo "=== rebuilding $@"
+ if [ -d $(coregen_work_dir) ]; then \
+ rm -rf $(coregen_work_dir)/*; \
+ else \
+ mkdir -p $(coregen_work_dir); \
+ fi
+ cd $(coregen_work_dir); \
+ $(xil_env); \
+ coregen -b $$OLDPWD/$<; \
+ cd -
+ xcodir=`dirname $<`; \
+ basename=`basename $< .xco`; \
+ if [ ! -r $(coregen_work_dir/$$basename.ngc) ]; then \
+ echo "'$@' wasn't created."; \
+ exit 1; \
+ else \
+ cp $(coregen_work_dir)/$$basename.v $(coregen_work_dir)/$$basename.ngc $$xcodir; \
+ fi
+junk += $(coregen_work_dir)
+
+date = $(shell date +%F-%H-%M)
+
+# some common junk
+junk += *.xrpt
+
+programming_files: $(project).bit $(project).mcs
+ mkdir -p $@/$(date)
+ mkdir -p $@/latest
+ for x in .bit .mcs .cfi _bd.bmm; do cp $(project)$$x $@/$(date)/$(project)$$x; cp $(project)$$x $@/latest/$(project)$$x; done
+ $(xil_env); xst -help | head -1 | sed 's/^/#/' | cat - $(project).scr > $@/$(date)/$(project).scr
+
+$(project).mcs: $(project).bit
+ $(xil_env); \
+ promgen -w -s $(flashsize) -p mcs -o $@ -u 0 $^
+junk += $(project).mcs $(project).cfi $(project).prm
+
+$(project).bit: $(project)_par.ncd
+ $(xil_env); \
+ bitgen $(intstyle) -g UnusedPin:Pullnone -g DriveDone:yes -g StartupClk:Cclk -w $(project)_par.ncd $(project).bit
+junk += $(project).bgn $(project).bit $(project).drc $(project)_bd.bmm
+
+
+$(project)_par.ncd: $(project).ncd
+ $(xil_env); \
+ if par $(intstyle) $(par_opts) -w $(project).ncd $(project)_par.ncd; then \
+ :; \
+ else \
+ $(MAKE) etwr; \
+ fi
+junk += $(project)_par.ncd $(project)_par.par $(project)_par.pad
+junk += $(project)_par_pad.csv $(project)_par_pad.txt
+junk += $(project)_par.grf $(project)_par.ptwx
+junk += $(project)_par.unroutes $(project)_par.xpi
+
+$(project).ncd: $(project).ngd
+ if [ -r $(project)_par.ncd ]; then \
+ cp $(project)_par.ncd smartguide.ncd; \
+ smartguide="-smartguide smartguide.ncd"; \
+ else \
+ smartguide=""; \
+ fi; \
+ $(xil_env); \
+ map $(intstyle) $(map_opts) $$smartguide $<
+junk += $(project).ncd $(project).pcf $(project).ngm $(project).mrp $(project).map
+junk += smartguide.ncd $(project).psr
+junk += $(project)_summary.xml $(project)_usage.xml
+
+$(project).ngd: $(project).ngc $(ucf)
+ $(xil_env); ngdbuild $(intstyle) $(project).ngc -uc $(ucf)
+junk += $(project).ngd $(project).bld
+
+$(project).ngc: $(vfiles) $(local_corengcs) $(project).scr $(project).prj
+ $(xil_env); xst $(intstyle) -ifn $(project).scr
+junk += xlnx_auto* $(top_module).lso $(project).srp
+junk += netlist.lst xst $(project).ngc
+
+$(project).prj: $(vfiles) $(mkfiles)
+ for src in $(vfiles); do echo "verilog work $$src" >> $(project).tmpprj; done
+ sort -u $(project).tmpprj > $(project).prj
+ rm -f $(project).tmpprj
+junk += $(project).prj
+
+optfile += $(wildcard $(project).opt)
+top_module ?= $(project)
+$(project).scr: $(optfile) $(mkfiles) ./xilinx.opt
+ echo "run" > $@
+ echo "-p $(part)" >> $@
+ echo "-top $(top_module)" >> $@
+ echo "-ifn $(project).prj" >> $@
+ echo "-ofn $(project).ngc" >> $@
+ cat ./xilinx.opt $(optfile) >> $@
+junk += $(project).scr
+
+$(project).post_map.twr: $(project).ncd
+ $(xil_env); trce -e 10 $< $(project).pcf -o $@
+junk += $(project).post_map.twr $(project).post_map.twx smartpreview.twr
+
+$(project).twr: $(project)_par.ncd
+ $(xil_env); trce $< $(project).pcf -o $(project).twr
+junk += $(project).twr $(project).twx smartpreview.twr
+
+$(project)_err.twr: $(project)_par.ncd
+ $(xil_env); trce -e 10 $< $(project).pcf -o $(project)_err.twr
+junk += $(project)_err.twr $(project)_err.twx
+junk += $(project).lso $(project)_bitgen.xwb $(project)_bitgen.xwbt
+junk += usage_statistics_webtalk.html par_usage_statistics.html webtalk.log _xmsgs default.xreport
+
+.gitignore: $(mkfiles)
+ echo programming_files $(junk) | sed 's, ,\n,g' > .gitignore
+
+clean::
+ rm -rf $(junk)
diff --git a/novena/build/xilinx.opt b/novena/build/xilinx.opt
new file mode 100644
index 0000000..7fe9d8b
--- /dev/null
+++ b/novena/build/xilinx.opt
@@ -0,0 +1,42 @@
+-ifmt mixed
+-ofmt NGC
+-opt_mode speed
+-opt_level 1
+-iuc NO
+-keep_hierarchy no
+-netlist_hierarchy as_optimized
+-rtlview no
+-glob_opt AllClockNets
+-read_cores yes
+-write_timing_constraints NO
+-cross_clock_analysis NO
+-hierarchy_separator /
+-bus_delimiter <>
+-case maintain
+-slice_utilization_ratio 100
+-bram_utilization_ratio 100
+#-dsp_utilization_ratio 100
+-safe_implementation No
+-fsm_extract YES
+-fsm_encoding Auto
+-fsm_style lut
+-ram_extract Yes
+-ram_style Auto
+-rom_extract Yes
+-rom_style Auto
+-shreg_extract YES
+-auto_bram_packing NO
+-resource_sharing YES
+-async_to_sync NO
+#-use_dsp48 auto
+-iobuf YES
+-max_fanout 500
+-register_duplication YES
+-register_balancing No
+-optimize_primitives NO
+-use_clock_enable Auto
+-use_sync_set Auto
+-use_sync_reset Auto
+-iob auto
+-equivalent_register_removal YES
+-slice_utilization_ratio_maxmargin 5
diff --git a/novena/iseconfig/novena_reorg_eim/novena_reorg_eim.xise b/novena/iseconfig/novena_reorg_eim/novena_reorg_eim.xise
new file mode 100644
index 0000000..d09db95
--- /dev/null
+++ b/novena/iseconfig/novena_reorg_eim/novena_reorg_eim.xise
@@ -0,0 +1,466 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<project xmlns="http://www.xilinx.com/XMLSchema" xmlns:xil_pn="http://www.xilinx.com/XMLSchema">
+
+ <header>
+ <!-- ISE source project file created by Project Navigator. -->
+ <!-- -->
+ <!-- This file contains project source information including a list of -->
+ <!-- project source files, project and process properties. This file, -->
+ <!-- along with the project source files, is sufficient to open and -->
+ <!-- implement in ISE Project Navigator. -->
+ <!-- -->
+ <!-- Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved. -->
+ </header>
+
+ <version xil_pn:ise_version="14.7" xil_pn:schema_version="2"/>
+
+ <files>
+ <file xil_pn:name="../../src/rtl/novena_clkmgr.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="1"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="23"/>
+ </file>
+ <file xil_pn:name="../../src/rtl/novena_eim.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="2"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="26"/>
+ </file>
+ <file xil_pn:name="../../src/rtl/novena_regs.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="4"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="14"/>
+ </file>
+ <file xil_pn:name="../../src/rtl/ipcore/clkmgr_dcm.xco" xil_pn:type="FILE_COREGEN">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="5"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="17"/>
+ </file>
+ <file xil_pn:name="../../../core_selector/src/rtl/cipher_selector.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="11"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="22"/>
+ </file>
+ <file xil_pn:name="../../../core_selector/src/rtl/core_selector.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="12"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="25"/>
+ </file>
+ <file xil_pn:name="../../../core_selector/src/rtl/hash_selector.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="13"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="21"/>
+ </file>
+ <file xil_pn:name="../../../core_selector/src/rtl/rng_selector.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="14"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="20"/>
+ </file>
+ <file xil_pn:name="../../../eim/src/rtl/cdc_bus_pulse.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="16"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="10"/>
+ </file>
+ <file xil_pn:name="../../../eim/src/rtl/eim_arbiter_cdc.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="17"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="16"/>
+ </file>
+ <file xil_pn:name="../../../eim/src/rtl/eim_arbiter.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="18"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="19"/>
+ </file>
+ <file xil_pn:name="../../../eim/src/rtl/eim_da_phy.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="19"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="15"/>
+ </file>
+ <file xil_pn:name="../../../eim/src/rtl/eim_indicator.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="20"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="18"/>
+ </file>
+ <file xil_pn:name="../../../eim/src/rtl/eim.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="21"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="24"/>
+ </file>
+ <file xil_pn:name="../../../sha1/src/rtl/sha1_core.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="22"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="9"/>
+ </file>
+ <file xil_pn:name="../../../sha1/src/rtl/sha1_w_mem.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="23"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="6"/>
+ </file>
+ <file xil_pn:name="../../../sha1/src/rtl/sha1.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="24"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="13"/>
+ </file>
+ <file xil_pn:name="../../../sha256/src/rtl/sha256_core.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="25"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="8"/>
+ </file>
+ <file xil_pn:name="../../../sha256/src/rtl/sha256_k_constants.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="26"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="5"/>
+ </file>
+ <file xil_pn:name="../../../sha256/src/rtl/sha256_w_mem.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="27"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="4"/>
+ </file>
+ <file xil_pn:name="../../../sha256/src/rtl/sha256.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="28"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="12"/>
+ </file>
+ <file xil_pn:name="../../../sha512/src/rtl/sha512_core.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="30"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="7"/>
+ </file>
+ <file xil_pn:name="../../../sha512/src/rtl/sha512_h_constants.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="31"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="3"/>
+ </file>
+ <file xil_pn:name="../../../sha512/src/rtl/sha512_k_constants.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="32"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="2"/>
+ </file>
+ <file xil_pn:name="../../../sha512/src/rtl/sha512_w_mem.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="33"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="1"/>
+ </file>
+ <file xil_pn:name="../../../sha512/src/rtl/sha512.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="34"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="11"/>
+ </file>
+ <file xil_pn:name="../../src/ucf/novena_eim.ucf" xil_pn:type="FILE_UCF">
+ <association xil_pn:name="Implementation" xil_pn:seqID="0"/>
+ </file>
+ <file xil_pn:name="../../src/rtl/ipcore/clkmgr_dcm.xise" xil_pn:type="FILE_COREGENISE">
+ <association xil_pn:name="Implementation" xil_pn:seqID="0"/>
+ </file>
+ </files>
+
+ <properties>
+ <property xil_pn:name="AES Initial Vector spartan6" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="AES Key (Hex String) spartan6" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Add I/O Buffers" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Allow Logic Optimization Across Hierarchy" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Allow SelectMAP Pins to Persist" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Allow Unexpanded Blocks" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Allow Unmatched LOC Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Allow Unmatched Timing Group Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Analysis Effort Level" xil_pn:value="Standard" xil_pn:valueState="default"/>
+ <property xil_pn:name="Asynchronous To Synchronous" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Auto Implementation Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Auto Implementation Top" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Automatic BRAM Packing" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Automatically Insert glbl Module in the Netlist" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Automatically Run Generate Target PROM/ACE File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="BRAM Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
+ <property xil_pn:name="Bring Out Global Set/Reset Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Bring Out Global Tristate Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Bus Delimiter" xil_pn:value="<>" xil_pn:valueState="default"/>
+ <property xil_pn:name="Case" xil_pn:value="Maintain" xil_pn:valueState="default"/>
+ <property xil_pn:name="Case Implementation Style" xil_pn:value="None" xil_pn:valueState="default"/>
+ <property xil_pn:name="Change Device Speed To" xil_pn:value="-3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Change Device Speed To Post Trace" xil_pn:value="-3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Combinatorial Logic Optimization" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Compile EDK Simulation Library" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Compile SIMPRIM (Timing) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Compile UNISIM (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Compile XilinxCoreLib (CORE Generator) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Compile for HDL Debugging" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Clk (Configuration Pins)" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Pin Done" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Pin M0" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Pin M1" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Pin M2" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Pin Program" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Rate spartan6" xil_pn:value="2" xil_pn:valueState="default"/>
+ <property xil_pn:name="Correlate Output to Input Design" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create ASCII Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create Binary Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create Bit File" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create I/O Pads from Ports" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create IEEE 1532 Configuration File spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create Logic Allocation File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create Mask File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create ReadBack Data Files" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Cross Clock Analysis" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="DSP Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
+ <property xil_pn:name="Delay Values To Be Read from SDF" xil_pn:value="Setup Time" xil_pn:valueState="default"/>
+ <property xil_pn:name="Device" xil_pn:value="xc6slx45" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Device Family" xil_pn:value="Spartan6" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Device Speed Grade/Select ABS Minimum" xil_pn:value="-3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Disable Detailed Package Model Insertion" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Do Not Escape Signal and Instance Names in Netlist" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Done (Output Events)" xil_pn:value="Default (4)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Drive Awake Pin During Suspend/Wake Sequence spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Drive Done Pin High" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable BitStream Compression" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Cyclic Redundancy Checking (CRC) spartan6" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Debugging of Serial Mode BitStream" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable External Master Clock spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Hardware Co-Simulation" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Internal Done Pipe" xil_pn:value="true" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Enable Message Filtering" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Multi-Pin Wake-Up Suspend Mode spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Multi-Threading" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Multi-Threading par spartan6" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Outputs (Output Events)" xil_pn:value="Default (5)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Suspend/Wake Global Set/Reset spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Encrypt Bitstream spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Encrypt Key Select spartan6" xil_pn:value="BBRAM" xil_pn:valueState="default"/>
+ <property xil_pn:name="Equivalent Register Removal Map" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Equivalent Register Removal XST" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Essential Bits" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Evaluation Development Board" xil_pn:value="None Specified" xil_pn:valueState="default"/>
+ <property xil_pn:name="Exclude Compilation of Deprecated EDK Cores" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Exclude Compilation of EDK Sub-Libraries" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Extra Cost Tables Map" xil_pn:value="0" xil_pn:valueState="default"/>
+ <property xil_pn:name="Extra Effort (Highest PAR level only)" xil_pn:value="None" xil_pn:valueState="default"/>
+ <property xil_pn:name="FPGA Start-Up Clock" xil_pn:value="CCLK" xil_pn:valueState="default"/>
+ <property xil_pn:name="FSM Encoding Algorithm" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="FSM Style" xil_pn:value="LUT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Filter Files From Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Flatten Output Netlist" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Functional Model Target Language ArchWiz" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="Functional Model Target Language Coregen" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="Functional Model Target Language Schematic" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="GTS Cycle During Suspend/Wakeup Sequence spartan6" xil_pn:value="4" xil_pn:valueState="default"/>
+ <property xil_pn:name="GWE Cycle During Suspend/Wakeup Sequence spartan6" xil_pn:value="5" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Architecture Only (No Entity Declaration)" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Asynchronous Delay Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Clock Region Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Constraints Interaction Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Constraints Interaction Report Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Datasheet Section" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Datasheet Section Post Trace" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Detailed MAP Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Multiple Hierarchical Netlist Files" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Post-Place & Route Power Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Post-Place & Route Simulation Model" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate RTL Schematic" xil_pn:value="Yes" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate SAIF File for Power Optimization/Estimation Par" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Testbench File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Timegroups Section" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Timegroups Section Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generics, Parameters" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Global Optimization Goal" xil_pn:value="AllClockNets" xil_pn:valueState="default"/>
+ <property xil_pn:name="Global Optimization map spartan6" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Global Set/Reset Port Name" xil_pn:value="GSR_PORT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Global Tristate Port Name" xil_pn:value="GTS_PORT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Hierarchy Separator" xil_pn:value="/" xil_pn:valueState="default"/>
+ <property xil_pn:name="ISim UUT Instance Name" xil_pn:value="UUT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Ignore User Timing Constraints Map" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Ignore User Timing Constraints Par" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Implementation Top" xil_pn:value="Module|novena_baseline_top" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Implementation Top File" xil_pn:value="../../src/rtl/novena_eim.v" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Implementation Top Instance Path" xil_pn:value="/novena_baseline_top" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Include 'uselib Directive in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Include SIMPRIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Include UNISIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Include sdf_annotate task in Verilog File" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Incremental Compilation" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Insert Buffers to Prevent Pulse Swallowing" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Instantiation Template Target Language Xps" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="JTAG Pin TCK" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="JTAG Pin TDI" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="JTAG Pin TDO" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="JTAG Pin TMS" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Keep Hierarchy" xil_pn:value="No" xil_pn:valueState="default"/>
+ <property xil_pn:name="LUT Combining Map" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="LUT Combining Xst" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Language" xil_pn:value="VHDL" xil_pn:valueState="default"/>
+ <property xil_pn:name="Last Applied Goal" xil_pn:value="Balanced" xil_pn:valueState="default"/>
+ <property xil_pn:name="Last Applied Strategy" xil_pn:value="Xilinx Default (unlocked)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Last Unlock Status" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Launch SDK after Export" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Library for Verilog Sources" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Load glbl" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Manual Implementation Compile Order" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Map Slice Logic into Unused Block RAMs" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Mask Pins for Multi-Pin Wake-Up Suspend Mode spartan6" xil_pn:value="0x00" xil_pn:valueState="default"/>
+ <property xil_pn:name="Max Fanout" xil_pn:value="100000" xil_pn:valueState="default"/>
+ <property xil_pn:name="Maximum Compression" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Maximum Number of Lines in Report" xil_pn:value="1000" xil_pn:valueState="default"/>
+ <property xil_pn:name="Maximum Signal Name Length" xil_pn:value="20" xil_pn:valueState="default"/>
+ <property xil_pn:name="Move First Flip-Flop Stage" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Move Last Flip-Flop Stage" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: Insert IPROG CMD in the Bitfile spartan6" xil_pn:value="Enable" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: Next Configuration Mode spartan6" xil_pn:value="001" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: Starting Address for Golden Configuration spartan6" xil_pn:value="0x00000000" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: Starting Address for Next Configuration spartan6" xil_pn:value="0x00000000" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: Use New Mode for Next Configuration spartan6" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: User-Defined Register for Failsafe Scheme spartan6" xil_pn:value="0x0000" xil_pn:valueState="default"/>
+ <property xil_pn:name="Netlist Hierarchy" xil_pn:value="As Optimized" xil_pn:valueState="default"/>
+ <property xil_pn:name="Netlist Translation Type" xil_pn:value="Timestamp" xil_pn:valueState="default"/>
+ <property xil_pn:name="Number of Clock Buffers" xil_pn:value="16" xil_pn:valueState="default"/>
+ <property xil_pn:name="Number of Paths in Error/Verbose Report" xil_pn:value="3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Number of Paths in Error/Verbose Report Post Trace" xil_pn:value="3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Optimization Effort spartan6" xil_pn:value="Normal" xil_pn:valueState="default"/>
+ <property xil_pn:name="Optimization Goal" xil_pn:value="Speed" xil_pn:valueState="default"/>
+ <property xil_pn:name="Optimize Instantiated Primitives" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Bitgen Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Bitgen Command Line Options spartan6" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Compiler Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Compiler Options Map" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Compiler Options Par" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Compiler Options Translate" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Compxlib Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Map Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other NETGEN Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Ngdbuild Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Place & Route Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Simulator Commands Behavioral" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Simulator Commands Post-Map" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Simulator Commands Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Simulator Commands Post-Translate" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other XPWR Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other XST Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Output Extended Identifiers" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Output File Name" xil_pn:value="novena_baseline_top" xil_pn:valueState="default"/>
+ <property xil_pn:name="Overwrite Compiled Libraries" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Pack I/O Registers into IOBs" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Pack I/O Registers/Latches into IOBs" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Package" xil_pn:value="csg324" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Perform Advanced Analysis" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Perform Advanced Analysis Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Perform Timing-Driven Packing and Placement" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Place & Route Effort Level (Overall)" xil_pn:value="High" xil_pn:valueState="default"/>
+ <property xil_pn:name="Place And Route Mode" xil_pn:value="Normal Place and Route" xil_pn:valueState="default"/>
+ <property xil_pn:name="Place MultiBoot Settings into Bitstream spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Placer Effort Level Map" xil_pn:value="High" xil_pn:valueState="default"/>
+ <property xil_pn:name="Placer Extra Effort Map" xil_pn:value="None" xil_pn:valueState="default"/>
+ <property xil_pn:name="Port to be used" xil_pn:value="Auto - default" xil_pn:valueState="default"/>
+ <property xil_pn:name="Post Map Simulation Model Name" xil_pn:value="novena_baseline_top_map.v" xil_pn:valueState="default"/>
+ <property xil_pn:name="Post Place & Route Simulation Model Name" xil_pn:value="novena_baseline_top_timesim.v" xil_pn:valueState="default"/>
+ <property xil_pn:name="Post Synthesis Simulation Model Name" xil_pn:value="novena_baseline_top_synthesis.v" xil_pn:valueState="default"/>
+ <property xil_pn:name="Post Translate Simulation Model Name" xil_pn:value="novena_baseline_top_translate.v" xil_pn:valueState="default"/>
+ <property xil_pn:name="Power Reduction Map spartan6" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Power Reduction Par" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Power Reduction Xst" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Preferred Language" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="Produce Verbose Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Project Description" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Property Specification in Project File" xil_pn:value="Store all values" xil_pn:valueState="default"/>
+ <property xil_pn:name="RAM Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="RAM Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="ROM Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="ROM Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Read Cores" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Reduce Control Sets" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Regenerate Core" xil_pn:value="Under Current Project Setting" xil_pn:valueState="default"/>
+ <property xil_pn:name="Register Balancing" xil_pn:value="No" xil_pn:valueState="default"/>
+ <property xil_pn:name="Register Duplication Map" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Register Duplication Xst" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Register Ordering spartan6" xil_pn:value="4" xil_pn:valueState="default"/>
+ <property xil_pn:name="Release Write Enable (Output Events)" xil_pn:value="Default (6)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Rename Design Instance in Testbench File to" xil_pn:value="UUT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Rename Top Level Architecture To" xil_pn:value="Structure" xil_pn:valueState="default"/>
+ <property xil_pn:name="Rename Top Level Entity to" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Rename Top Level Module To" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Fastest Path(s) in Each Constraint" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Fastest Path(s) in Each Constraint Post Trace" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Paths by Endpoint" xil_pn:value="3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Paths by Endpoint Post Trace" xil_pn:value="3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Type" xil_pn:value="Verbose Report" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Type Post Trace" xil_pn:value="Verbose Report" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Unconstrained Paths" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Unconstrained Paths Post Trace" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Reset On Configuration Pulse Width" xil_pn:value="100" xil_pn:valueState="default"/>
+ <property xil_pn:name="Resource Sharing" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Retain Hierarchy" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Retry Configuration if CRC Error Occurs spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Revision Select" xil_pn:value="00" xil_pn:valueState="default"/>
+ <property xil_pn:name="Revision Select Tristate" xil_pn:value="Disable" xil_pn:valueState="default"/>
+ <property xil_pn:name="Run Design Rules Checker (DRC)" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Run for Specified Time" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Run for Specified Time Map" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Run for Specified Time Par" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Run for Specified Time Translate" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Safe Implementation" xil_pn:value="No" xil_pn:valueState="default"/>
+ <property xil_pn:name="Security" xil_pn:value="Enable Readback and Reconfiguration" xil_pn:valueState="default"/>
+ <property xil_pn:name="Selected Simulation Root Source Node Behavioral" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Selected Simulation Root Source Node Post-Map" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Selected Simulation Root Source Node Post-Translate" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Selected Simulation Source Node" xil_pn:value="UUT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Set SPI Configuration Bus Width spartan6" xil_pn:value="1" xil_pn:valueState="default"/>
+ <property xil_pn:name="Setup External Master Clock Division spartan6" xil_pn:value="1" xil_pn:valueState="default"/>
+ <property xil_pn:name="Shift Register Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Shift Register Minimum Size spartan6" xil_pn:value="2" xil_pn:valueState="default"/>
+ <property xil_pn:name="Show All Models" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulation Model Target" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulation Run Time ISim" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulation Run Time Map" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulation Run Time Par" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulation Run Time Translate" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulator" xil_pn:value="ISim (VHDL/Verilog)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Slice Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
+ <property xil_pn:name="Specify 'define Macro Name and Value" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Specify Top Level Instance Names Behavioral" xil_pn:value="Default" xil_pn:valueState="default"/>
+ <property xil_pn:name="Specify Top Level Instance Names Post-Map" xil_pn:value="Default" xil_pn:valueState="default"/>
+ <property xil_pn:name="Specify Top Level Instance Names Post-Route" xil_pn:value="Default" xil_pn:valueState="default"/>
+ <property xil_pn:name="Specify Top Level Instance Names Post-Translate" xil_pn:value="Default" xil_pn:valueState="default"/>
+ <property xil_pn:name="Speed Grade" xil_pn:value="-3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Starting Placer Cost Table (1-100) Map spartan6" xil_pn:value="1" xil_pn:valueState="default"/>
+ <property xil_pn:name="Synthesis Tool" xil_pn:value="XST (VHDL/Verilog)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Target Simulator" xil_pn:value="Please Specify" xil_pn:valueState="default"/>
+ <property xil_pn:name="Timing Mode Map" xil_pn:value="Performance Evaluation" xil_pn:valueState="default"/>
+ <property xil_pn:name="Timing Mode Par" xil_pn:value="Performance Evaluation" xil_pn:valueState="default"/>
+ <property xil_pn:name="Top-Level Module Name in Output Netlist" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Top-Level Source Type" xil_pn:value="HDL" xil_pn:valueState="default"/>
+ <property xil_pn:name="Trim Unconnected Signals" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Tristate On Configuration Pulse Width" xil_pn:value="0" xil_pn:valueState="default"/>
+ <property xil_pn:name="Unused IOB Pins" xil_pn:value="Pull Down" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use 64-bit PlanAhead on 64-bit Systems" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Clock Enable" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Project File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Project File Post-Map" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Project File Post-Route" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Project File Post-Translate" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Simulation Command File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Simulation Command File Map" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Simulation Command File Par" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Simulation Command File Translate" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Waveform Configuration File Behav" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Waveform Configuration File Map" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Waveform Configuration File Par" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Waveform Configuration File Translate" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use DSP Block spartan6" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use LOC Constraints" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use RLOC Constraints" xil_pn:value="Yes" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Smart Guide" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Synchronous Reset" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Synchronous Set" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Synthesis Constraints File" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="UserID Code (8 Digit Hexadecimal)" xil_pn:value="0xFFFFFFFF" xil_pn:valueState="default"/>
+ <property xil_pn:name="VCCAUX Voltage Level spartan6" xil_pn:value="2.5V" xil_pn:valueState="default"/>
+ <property xil_pn:name="VHDL Source Analysis Standard" xil_pn:value="VHDL-93" xil_pn:valueState="default"/>
+ <property xil_pn:name="Value Range Check" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Verilog Macros" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Wait for DCM and PLL Lock (Output Events) spartan6" xil_pn:value="Default (NoWait)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Wakeup Clock spartan6" xil_pn:value="Startup Clock" xil_pn:valueState="default"/>
+ <property xil_pn:name="Watchdog Timer Value spartan6" xil_pn:value="0xFFFF" xil_pn:valueState="default"/>
+ <property xil_pn:name="Working Directory" xil_pn:value="." xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Write Timing Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
+ <!-- -->
+ <!-- The following properties are for internal use only. These should not be modified.-->
+ <!-- -->
+ <property xil_pn:name="PROP_BehavioralSimTop" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_DesignName" xil_pn:value="novena_reorg_eim" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_DevFamilyPMName" xil_pn:value="spartan6" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_FPGAConfiguration" xil_pn:value="FPGAConfiguration" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_PostMapSimTop" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_PostParSimTop" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_PostSynthSimTop" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_PostXlateSimTop" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_PreSynthesis" xil_pn:value="PreSynthesis" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_intProjectCreationTimestamp" xil_pn:value="2015-02-18T12:52:31" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_intWbtProjectID" xil_pn:value="864F45CE2D69580E9CD3CF97C2CAF083" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_intWorkingDirLocWRTProjDir" xil_pn:value="Same" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_intWorkingDirUsed" xil_pn:value="No" xil_pn:valueState="non-default"/>
+ </properties>
+
+ <bindings/>
+
+ <libraries/>
+
+ <autoManagedFiles>
+ <!-- The following files are identified by `include statements in verilog -->
+ <!-- source files and are automatically managed by Project Navigator. -->
+ <!-- -->
+ <!-- Do not hand-edit this section, as it will be overwritten when the -->
+ <!-- project is analyzed based on files automatically identified as -->
+ <!-- include files. -->
+ </autoManagedFiles>
+
+</project>
diff --git a/novena/iseconfig/novena_reorg_i2c/novena_reorg_i2c.xise b/novena/iseconfig/novena_reorg_i2c/novena_reorg_i2c.xise
new file mode 100644
index 0000000..e7666bb
--- /dev/null
+++ b/novena/iseconfig/novena_reorg_i2c/novena_reorg_i2c.xise
@@ -0,0 +1,438 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<project xmlns="http://www.xilinx.com/XMLSchema" xmlns:xil_pn="http://www.xilinx.com/XMLSchema">
+
+ <header>
+ <!-- ISE source project file created by Project Navigator. -->
+ <!-- -->
+ <!-- This file contains project source information including a list of -->
+ <!-- project source files, project and process properties. This file, -->
+ <!-- along with the project source files, is sufficient to open and -->
+ <!-- implement in ISE Project Navigator. -->
+ <!-- -->
+ <!-- Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved. -->
+ </header>
+
+ <version xil_pn:ise_version="14.7" xil_pn:schema_version="2"/>
+
+ <files>
+ <file xil_pn:name="../../src/rtl/novena_i2c.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="1"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="20"/>
+ </file>
+ <file xil_pn:name="../../src/ucf/novena_i2c.ucf" xil_pn:type="FILE_UCF">
+ <association xil_pn:name="Implementation" xil_pn:seqID="0"/>
+ </file>
+ <file xil_pn:name="../../../core_selector/src/rtl/cipher_selector.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="3"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="16"/>
+ </file>
+ <file xil_pn:name="../../../core_selector/src/rtl/core_selector.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="4"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="18"/>
+ </file>
+ <file xil_pn:name="../../../core_selector/src/rtl/hash_selector.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="5"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="15"/>
+ </file>
+ <file xil_pn:name="../../../core_selector/src/rtl/rng_selector.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="6"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="14"/>
+ </file>
+ <file xil_pn:name="../../../coretest/src/rtl/coretest.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="7"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="19"/>
+ </file>
+ <file xil_pn:name="../../../i2c/src/rtl/i2c_core.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="8"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="17"/>
+ </file>
+ <file xil_pn:name="../../../sha1/src/rtl/sha1_core.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="9"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="8"/>
+ </file>
+ <file xil_pn:name="../../../sha1/src/rtl/sha1_w_mem.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="10"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="3"/>
+ </file>
+ <file xil_pn:name="../../../sha1/src/rtl/sha1.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="11"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="11"/>
+ </file>
+ <file xil_pn:name="../../../sha256/src/rtl/sha256_core.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="12"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="7"/>
+ </file>
+ <file xil_pn:name="../../../sha256/src/rtl/sha256_k_constants.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="13"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="2"/>
+ </file>
+ <file xil_pn:name="../../../sha256/src/rtl/sha256_w_mem.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="14"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="1"/>
+ </file>
+ <file xil_pn:name="../../../sha256/src/rtl/sha256.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="15"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="10"/>
+ </file>
+ <file xil_pn:name="../../../sha512/src/rtl/sha512_core.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="16"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="9"/>
+ </file>
+ <file xil_pn:name="../../../sha512/src/rtl/sha512_h_constants.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="17"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="6"/>
+ </file>
+ <file xil_pn:name="../../../sha512/src/rtl/sha512_k_constants.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="18"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="5"/>
+ </file>
+ <file xil_pn:name="../../../sha512/src/rtl/sha512_w_mem.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="19"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="4"/>
+ </file>
+ <file xil_pn:name="../../../sha512/src/rtl/sha512.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="20"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="13"/>
+ </file>
+ <file xil_pn:name="../../src/rtl/novena_regs.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="21"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="12"/>
+ </file>
+ </files>
+
+ <properties>
+ <property xil_pn:name="AES Initial Vector spartan6" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="AES Key (Hex String) spartan6" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Add I/O Buffers" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Allow Logic Optimization Across Hierarchy" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Allow SelectMAP Pins to Persist" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Allow Unexpanded Blocks" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Allow Unmatched LOC Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Allow Unmatched Timing Group Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Analysis Effort Level" xil_pn:value="Standard" xil_pn:valueState="default"/>
+ <property xil_pn:name="Asynchronous To Synchronous" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Auto Implementation Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Auto Implementation Top" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Automatic BRAM Packing" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Automatically Insert glbl Module in the Netlist" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Automatically Run Generate Target PROM/ACE File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="BRAM Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
+ <property xil_pn:name="Bring Out Global Set/Reset Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Bring Out Global Tristate Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Bus Delimiter" xil_pn:value="<>" xil_pn:valueState="default"/>
+ <property xil_pn:name="Case" xil_pn:value="Maintain" xil_pn:valueState="default"/>
+ <property xil_pn:name="Case Implementation Style" xil_pn:value="None" xil_pn:valueState="default"/>
+ <property xil_pn:name="Change Device Speed To" xil_pn:value="-3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Change Device Speed To Post Trace" xil_pn:value="-3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Combinatorial Logic Optimization" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Compile EDK Simulation Library" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Compile SIMPRIM (Timing) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Compile UNISIM (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Compile XilinxCoreLib (CORE Generator) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Compile for HDL Debugging" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Clk (Configuration Pins)" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Pin Done" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Pin M0" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Pin M1" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Pin M2" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Pin Program" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Configuration Rate spartan6" xil_pn:value="2" xil_pn:valueState="default"/>
+ <property xil_pn:name="Correlate Output to Input Design" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create ASCII Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create Binary Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create Bit File" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create I/O Pads from Ports" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create IEEE 1532 Configuration File spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create Logic Allocation File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create Mask File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Create ReadBack Data Files" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Cross Clock Analysis" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="DSP Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
+ <property xil_pn:name="Delay Values To Be Read from SDF" xil_pn:value="Setup Time" xil_pn:valueState="default"/>
+ <property xil_pn:name="Device" xil_pn:value="xc6slx45" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Device Family" xil_pn:value="Spartan6" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Device Speed Grade/Select ABS Minimum" xil_pn:value="-3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Disable Detailed Package Model Insertion" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Do Not Escape Signal and Instance Names in Netlist" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Done (Output Events)" xil_pn:value="Default (4)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Drive Awake Pin During Suspend/Wake Sequence spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Drive Done Pin High" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable BitStream Compression" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Cyclic Redundancy Checking (CRC) spartan6" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Debugging of Serial Mode BitStream" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable External Master Clock spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Internal Done Pipe" xil_pn:value="true" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Enable Message Filtering" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Multi-Pin Wake-Up Suspend Mode spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Multi-Threading" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Multi-Threading par spartan6" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Outputs (Output Events)" xil_pn:value="Default (5)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Enable Suspend/Wake Global Set/Reset spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Encrypt Bitstream spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Encrypt Key Select spartan6" xil_pn:value="BBRAM" xil_pn:valueState="default"/>
+ <property xil_pn:name="Equivalent Register Removal Map" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Equivalent Register Removal XST" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Essential Bits" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Evaluation Development Board" xil_pn:value="None Specified" xil_pn:valueState="default"/>
+ <property xil_pn:name="Exclude Compilation of Deprecated EDK Cores" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Exclude Compilation of EDK Sub-Libraries" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Extra Cost Tables Map" xil_pn:value="0" xil_pn:valueState="default"/>
+ <property xil_pn:name="Extra Effort (Highest PAR level only)" xil_pn:value="None" xil_pn:valueState="default"/>
+ <property xil_pn:name="FPGA Start-Up Clock" xil_pn:value="CCLK" xil_pn:valueState="default"/>
+ <property xil_pn:name="FSM Encoding Algorithm" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="FSM Style" xil_pn:value="LUT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Filter Files From Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Flatten Output Netlist" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Functional Model Target Language ArchWiz" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="Functional Model Target Language Coregen" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="Functional Model Target Language Schematic" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="GTS Cycle During Suspend/Wakeup Sequence spartan6" xil_pn:value="4" xil_pn:valueState="default"/>
+ <property xil_pn:name="GWE Cycle During Suspend/Wakeup Sequence spartan6" xil_pn:value="5" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Architecture Only (No Entity Declaration)" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Asynchronous Delay Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Clock Region Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Constraints Interaction Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Constraints Interaction Report Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Datasheet Section" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Datasheet Section Post Trace" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Detailed MAP Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Multiple Hierarchical Netlist Files" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Post-Place & Route Power Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Post-Place & Route Simulation Model" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate RTL Schematic" xil_pn:value="Yes" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate SAIF File for Power Optimization/Estimation Par" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Testbench File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Timegroups Section" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generate Timegroups Section Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Generics, Parameters" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Global Optimization Goal" xil_pn:value="AllClockNets" xil_pn:valueState="default"/>
+ <property xil_pn:name="Global Optimization map spartan6" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Global Set/Reset Port Name" xil_pn:value="GSR_PORT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Global Tristate Port Name" xil_pn:value="GTS_PORT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Hierarchy Separator" xil_pn:value="/" xil_pn:valueState="default"/>
+ <property xil_pn:name="ISim UUT Instance Name" xil_pn:value="UUT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Ignore User Timing Constraints Map" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Ignore User Timing Constraints Par" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Implementation Top" xil_pn:value="Module|novena_baseline_top" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Implementation Top File" xil_pn:value="../../src/rtl/novena_i2c.v" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Implementation Top Instance Path" xil_pn:value="/novena_baseline_top" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Include 'uselib Directive in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Include SIMPRIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Include UNISIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Include sdf_annotate task in Verilog File" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Incremental Compilation" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Insert Buffers to Prevent Pulse Swallowing" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Instantiation Template Target Language Xps" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="JTAG Pin TCK" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="JTAG Pin TDI" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="JTAG Pin TDO" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="JTAG Pin TMS" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
+ <property xil_pn:name="Keep Hierarchy" xil_pn:value="No" xil_pn:valueState="default"/>
+ <property xil_pn:name="LUT Combining Map" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="LUT Combining Xst" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Language" xil_pn:value="VHDL" xil_pn:valueState="default"/>
+ <property xil_pn:name="Last Applied Goal" xil_pn:value="Balanced" xil_pn:valueState="default"/>
+ <property xil_pn:name="Last Applied Strategy" xil_pn:value="Xilinx Default (unlocked)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Last Unlock Status" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Launch SDK after Export" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Library for Verilog Sources" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Load glbl" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Manual Implementation Compile Order" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Map Slice Logic into Unused Block RAMs" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Mask Pins for Multi-Pin Wake-Up Suspend Mode spartan6" xil_pn:value="0x00" xil_pn:valueState="default"/>
+ <property xil_pn:name="Max Fanout" xil_pn:value="100000" xil_pn:valueState="default"/>
+ <property xil_pn:name="Maximum Compression" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Maximum Number of Lines in Report" xil_pn:value="1000" xil_pn:valueState="default"/>
+ <property xil_pn:name="Maximum Signal Name Length" xil_pn:value="20" xil_pn:valueState="default"/>
+ <property xil_pn:name="Move First Flip-Flop Stage" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Move Last Flip-Flop Stage" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: Insert IPROG CMD in the Bitfile spartan6" xil_pn:value="Enable" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: Next Configuration Mode spartan6" xil_pn:value="001" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: Starting Address for Golden Configuration spartan6" xil_pn:value="0x00000000" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: Starting Address for Next Configuration spartan6" xil_pn:value="0x00000000" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: Use New Mode for Next Configuration spartan6" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="MultiBoot: User-Defined Register for Failsafe Scheme spartan6" xil_pn:value="0x0000" xil_pn:valueState="default"/>
+ <property xil_pn:name="Netlist Hierarchy" xil_pn:value="As Optimized" xil_pn:valueState="default"/>
+ <property xil_pn:name="Netlist Translation Type" xil_pn:value="Timestamp" xil_pn:valueState="default"/>
+ <property xil_pn:name="Number of Clock Buffers" xil_pn:value="16" xil_pn:valueState="default"/>
+ <property xil_pn:name="Number of Paths in Error/Verbose Report" xil_pn:value="3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Number of Paths in Error/Verbose Report Post Trace" xil_pn:value="3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Optimization Effort spartan6" xil_pn:value="Normal" xil_pn:valueState="default"/>
+ <property xil_pn:name="Optimization Goal" xil_pn:value="Speed" xil_pn:valueState="default"/>
+ <property xil_pn:name="Optimize Instantiated Primitives" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Bitgen Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Bitgen Command Line Options spartan6" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Compiler Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Compiler Options Map" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Compiler Options Par" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Compiler Options Translate" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Compxlib Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Map Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other NETGEN Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Ngdbuild Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Place & Route Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Simulator Commands Behavioral" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Simulator Commands Post-Map" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Simulator Commands Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other Simulator Commands Post-Translate" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other XPWR Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Other XST Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Output Extended Identifiers" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Output File Name" xil_pn:value="novena_baseline_top" xil_pn:valueState="default"/>
+ <property xil_pn:name="Overwrite Compiled Libraries" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Pack I/O Registers into IOBs" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Pack I/O Registers/Latches into IOBs" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Package" xil_pn:value="csg324" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Perform Advanced Analysis" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Perform Advanced Analysis Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Perform Timing-Driven Packing and Placement" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Place & Route Effort Level (Overall)" xil_pn:value="High" xil_pn:valueState="default"/>
+ <property xil_pn:name="Place And Route Mode" xil_pn:value="Normal Place and Route" xil_pn:valueState="default"/>
+ <property xil_pn:name="Place MultiBoot Settings into Bitstream spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Placer Effort Level Map" xil_pn:value="High" xil_pn:valueState="default"/>
+ <property xil_pn:name="Placer Extra Effort Map" xil_pn:value="None" xil_pn:valueState="default"/>
+ <property xil_pn:name="Port to be used" xil_pn:value="Auto - default" xil_pn:valueState="default"/>
+ <property xil_pn:name="Post Map Simulation Model Name" xil_pn:value="novena_baseline_top_map.v" xil_pn:valueState="default"/>
+ <property xil_pn:name="Post Place & Route Simulation Model Name" xil_pn:value="novena_baseline_top_timesim.v" xil_pn:valueState="default"/>
+ <property xil_pn:name="Post Synthesis Simulation Model Name" xil_pn:value="novena_baseline_top_synthesis.v" xil_pn:valueState="default"/>
+ <property xil_pn:name="Post Translate Simulation Model Name" xil_pn:value="novena_baseline_top_translate.v" xil_pn:valueState="default"/>
+ <property xil_pn:name="Power Reduction Map spartan6" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Power Reduction Par" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Power Reduction Xst" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Preferred Language" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="Produce Verbose Report" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Project Description" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Property Specification in Project File" xil_pn:value="Store all values" xil_pn:valueState="default"/>
+ <property xil_pn:name="RAM Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="RAM Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="ROM Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="ROM Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Read Cores" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Reduce Control Sets" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Regenerate Core" xil_pn:value="Under Current Project Setting" xil_pn:valueState="default"/>
+ <property xil_pn:name="Register Balancing" xil_pn:value="No" xil_pn:valueState="default"/>
+ <property xil_pn:name="Register Duplication Map" xil_pn:value="Off" xil_pn:valueState="default"/>
+ <property xil_pn:name="Register Duplication Xst" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Register Ordering spartan6" xil_pn:value="4" xil_pn:valueState="default"/>
+ <property xil_pn:name="Release Write Enable (Output Events)" xil_pn:value="Default (6)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Rename Design Instance in Testbench File to" xil_pn:value="UUT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Rename Top Level Architecture To" xil_pn:value="Structure" xil_pn:valueState="default"/>
+ <property xil_pn:name="Rename Top Level Entity to" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Rename Top Level Module To" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Fastest Path(s) in Each Constraint" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Fastest Path(s) in Each Constraint Post Trace" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Paths by Endpoint" xil_pn:value="3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Paths by Endpoint Post Trace" xil_pn:value="3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Type" xil_pn:value="Verbose Report" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Type Post Trace" xil_pn:value="Verbose Report" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Unconstrained Paths" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Report Unconstrained Paths Post Trace" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Reset On Configuration Pulse Width" xil_pn:value="100" xil_pn:valueState="default"/>
+ <property xil_pn:name="Resource Sharing" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Retain Hierarchy" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Retry Configuration if CRC Error Occurs spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Revision Select" xil_pn:value="00" xil_pn:valueState="default"/>
+ <property xil_pn:name="Revision Select Tristate" xil_pn:value="Disable" xil_pn:valueState="default"/>
+ <property xil_pn:name="Run Design Rules Checker (DRC)" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Run for Specified Time" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Run for Specified Time Map" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Run for Specified Time Par" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Run for Specified Time Translate" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Safe Implementation" xil_pn:value="No" xil_pn:valueState="default"/>
+ <property xil_pn:name="Security" xil_pn:value="Enable Readback and Reconfiguration" xil_pn:valueState="default"/>
+ <property xil_pn:name="Selected Simulation Root Source Node Behavioral" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Selected Simulation Root Source Node Post-Map" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Selected Simulation Root Source Node Post-Translate" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Selected Simulation Source Node" xil_pn:value="UUT" xil_pn:valueState="default"/>
+ <property xil_pn:name="Set SPI Configuration Bus Width spartan6" xil_pn:value="1" xil_pn:valueState="default"/>
+ <property xil_pn:name="Setup External Master Clock Division spartan6" xil_pn:value="1" xil_pn:valueState="default"/>
+ <property xil_pn:name="Shift Register Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Shift Register Minimum Size spartan6" xil_pn:value="2" xil_pn:valueState="default"/>
+ <property xil_pn:name="Show All Models" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulation Model Target" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulation Run Time ISim" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulation Run Time Map" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulation Run Time Par" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulation Run Time Translate" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulator" xil_pn:value="ISim (VHDL/Verilog)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Slice Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
+ <property xil_pn:name="Specify 'define Macro Name and Value" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Specify Top Level Instance Names Behavioral" xil_pn:value="Default" xil_pn:valueState="default"/>
+ <property xil_pn:name="Specify Top Level Instance Names Post-Map" xil_pn:value="Default" xil_pn:valueState="default"/>
+ <property xil_pn:name="Specify Top Level Instance Names Post-Route" xil_pn:value="Default" xil_pn:valueState="default"/>
+ <property xil_pn:name="Specify Top Level Instance Names Post-Translate" xil_pn:value="Default" xil_pn:valueState="default"/>
+ <property xil_pn:name="Speed Grade" xil_pn:value="-3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Starting Placer Cost Table (1-100) Map spartan6" xil_pn:value="1" xil_pn:valueState="default"/>
+ <property xil_pn:name="Synthesis Tool" xil_pn:value="XST (VHDL/Verilog)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Target Simulator" xil_pn:value="Please Specify" xil_pn:valueState="default"/>
+ <property xil_pn:name="Timing Mode Map" xil_pn:value="Performance Evaluation" xil_pn:valueState="default"/>
+ <property xil_pn:name="Timing Mode Par" xil_pn:value="Performance Evaluation" xil_pn:valueState="default"/>
+ <property xil_pn:name="Top-Level Module Name in Output Netlist" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Top-Level Source Type" xil_pn:value="HDL" xil_pn:valueState="default"/>
+ <property xil_pn:name="Trim Unconnected Signals" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Tristate On Configuration Pulse Width" xil_pn:value="0" xil_pn:valueState="default"/>
+ <property xil_pn:name="Unused IOB Pins" xil_pn:value="Pull Down" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use 64-bit PlanAhead on 64-bit Systems" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Clock Enable" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Project File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Project File Post-Map" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Project File Post-Route" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Project File Post-Translate" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Simulation Command File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Simulation Command File Map" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Simulation Command File Par" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Simulation Command File Translate" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Waveform Configuration File Behav" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Waveform Configuration File Map" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Waveform Configuration File Par" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Custom Waveform Configuration File Translate" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use DSP Block spartan6" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use LOC Constraints" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use RLOC Constraints" xil_pn:value="Yes" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Smart Guide" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Synchronous Reset" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Synchronous Set" xil_pn:value="Auto" xil_pn:valueState="default"/>
+ <property xil_pn:name="Use Synthesis Constraints File" xil_pn:value="true" xil_pn:valueState="default"/>
+ <property xil_pn:name="UserID Code (8 Digit Hexadecimal)" xil_pn:value="0xFFFFFFFF" xil_pn:valueState="default"/>
+ <property xil_pn:name="VCCAUX Voltage Level spartan6" xil_pn:value="2.5V" xil_pn:valueState="default"/>
+ <property xil_pn:name="VHDL Source Analysis Standard" xil_pn:value="VHDL-93" xil_pn:valueState="default"/>
+ <property xil_pn:name="Value Range Check" xil_pn:value="false" xil_pn:valueState="default"/>
+ <property xil_pn:name="Verilog Macros" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="Wait for DCM and PLL Lock (Output Events) spartan6" xil_pn:value="Default (NoWait)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Wakeup Clock spartan6" xil_pn:value="Startup Clock" xil_pn:valueState="default"/>
+ <property xil_pn:name="Watchdog Timer Value spartan6" xil_pn:value="0xFFFF" xil_pn:valueState="default"/>
+ <property xil_pn:name="Working Directory" xil_pn:value="." xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Write Timing Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
+ <!-- -->
+ <!-- The following properties are for internal use only. These should not be modified.-->
+ <!-- -->
+ <property xil_pn:name="PROP_BehavioralSimTop" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_DesignName" xil_pn:value="novena_reorg_i2c" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_DevFamilyPMName" xil_pn:value="spartan6" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_FPGAConfiguration" xil_pn:value="FPGAConfiguration" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_PostMapSimTop" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_PostParSimTop" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_PostSynthSimTop" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_PostXlateSimTop" xil_pn:value="" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_PreSynthesis" xil_pn:value="PreSynthesis" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_intProjectCreationTimestamp" xil_pn:value="2015-02-18T13:38:00" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_intWbtProjectID" xil_pn:value="884D55DDED613BF5E3BBF7BC051A0A88" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_intWorkingDirLocWRTProjDir" xil_pn:value="Same" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_intWorkingDirUsed" xil_pn:value="No" xil_pn:valueState="non-default"/>
+ </properties>
+
+ <bindings/>
+
+ <libraries/>
+
+ <autoManagedFiles>
+ <!-- The following files are identified by `include statements in verilog -->
+ <!-- source files and are automatically managed by Project Navigator. -->
+ <!-- -->
+ <!-- Do not hand-edit this section, as it will be overwritten when the -->
+ <!-- project is analyzed based on files automatically identified as -->
+ <!-- include files. -->
+ </autoManagedFiles>
+
+</project>
diff --git a/novena/src/rtl/ipcore/_xmsgs/cg.xmsgs b/novena/src/rtl/ipcore/_xmsgs/cg.xmsgs
new file mode 100644
index 0000000..985e6e3
--- /dev/null
+++ b/novena/src/rtl/ipcore/_xmsgs/cg.xmsgs
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- IMPORTANT: This is an internal file that has been generated
+ by the Xilinx ISE software. Any direct editing or
+ changes made to this file may result in unpredictable
+ behavior or data corruption. It is strongly advised that
+ users do not edit the contents of this file. -->
+<messages>
+<msg type="info" file="sim" num="172" delta="old" >Generating IP...
+</msg>
+
+<msg type="warning" file="sim" num="0" delta="new" ><arg fmt="%s" index="1">A core named 'clkmgr_dcm' already exists in the project. Output products for this core may be overwritten.</arg>
+</msg>
+
+<msg type="warning" file="sim" num="0" delta="new" ><arg fmt="%s" index="1">A core named 'clkmgr_dcm' already exists in the project. Output products for this core may be overwritten.</arg>
+</msg>
+
+<msg type="warning" file="sim" num="0" delta="new" ><arg fmt="%s" index="1">Component clk_wiz_v3_6 does not have a valid model name for Verilog synthesis</arg>
+</msg>
+
+<msg type="info" file="sim" num="949" delta="old" >Finished generation of ASY schematic symbol.
+</msg>
+
+<msg type="info" file="sim" num="948" delta="old" >Finished FLIST file generation.
+</msg>
+
+</messages>
+
diff --git a/novena/src/rtl/ipcore/_xmsgs/pn_parser.xmsgs b/novena/src/rtl/ipcore/_xmsgs/pn_parser.xmsgs
new file mode 100644
index 0000000..f69d969
--- /dev/null
+++ b/novena/src/rtl/ipcore/_xmsgs/pn_parser.xmsgs
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- IMPORTANT: This is an internal file that has been generated -->
+<!-- by the Xilinx ISE software. Any direct editing or -->
+<!-- changes made to this file may result in unpredictable -->
+<!-- behavior or data corruption. It is strongly advised that -->
+<!-- users do not edit the contents of this file. -->
+<!-- -->
+<!-- Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved. -->
+
+<messages>
+<msg type="info" file="ProjectMgmt" num="1845" ><arg fmt="%s" index="1">Analyzing Verilog file "/home/pselkirk/cryptech/user/paul/core/novena/src/rtl/ipcore/clkmgr_dcm.v" into library work</arg>
+</msg>
+
+</messages>
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm.asy b/novena/src/rtl/ipcore/clkmgr_dcm.asy
new file mode 100644
index 0000000..016d02a
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm.asy
@@ -0,0 +1,25 @@
+Version 4
+SymbolType BLOCK
+TEXT 32 32 LEFT 4 clkmgr_dcm
+RECTANGLE Normal 32 32 576 1088
+LINE Normal 0 80 32 80
+PIN 0 80 LEFT 36
+PINATTR PinName clk_in1
+PINATTR Polarity IN
+LINE Normal 0 432 32 432
+PIN 0 432 LEFT 36
+PINATTR PinName reset
+PINATTR Polarity IN
+LINE Normal 608 80 576 80
+PIN 608 80 RIGHT 36
+PINATTR PinName clk_out1
+PINATTR Polarity OUT
+LINE Normal 608 880 576 880
+PIN 608 880 RIGHT 36
+PINATTR PinName input_clk_stopped
+PINATTR Polarity OUT
+LINE Normal 608 1008 576 1008
+PIN 608 1008 RIGHT 36
+PINATTR PinName clk_valid
+PINATTR Polarity OUT
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm.gise b/novena/src/rtl/ipcore/clkmgr_dcm.gise
new file mode 100644
index 0000000..ed6d0f7
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm.gise
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<generated_project xmlns="http://www.xilinx.com/XMLSchema" xmlns:xil_pn="http://www.xilinx.com/XMLSchema">
+
+ <!-- -->
+
+ <!-- For tool use only. Do not edit. -->
+
+ <!-- -->
+
+ <!-- ProjectNavigator created generated project file. -->
+
+ <!-- For use in tracking generated file and other information -->
+
+ <!-- allowing preservation of process status. -->
+
+ <!-- -->
+
+ <!-- Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved. -->
+
+ <version xmlns="http://www.xilinx.com/XMLSchema">11.1</version>
+
+ <sourceproject xmlns="http://www.xilinx.com/XMLSchema" xil_pn:fileType="FILE_XISE" xil_pn:name="clkmgr_dcm.xise"/>
+
+ <files xmlns="http://www.xilinx.com/XMLSchema">
+ <file xil_pn:fileType="FILE_ASY" xil_pn:name="clkmgr_dcm.asy" xil_pn:origination="imported"/>
+ <file xil_pn:fileType="FILE_VEO" xil_pn:name="clkmgr_dcm.veo" xil_pn:origination="imported"/>
+ </files>
+
+ <transforms xmlns="http://www.xilinx.com/XMLSchema"/>
+
+</generated_project>
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm.ncf b/novena/src/rtl/ipcore/clkmgr_dcm.ncf
new file mode 100644
index 0000000..ef4e259
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm.ncf
@@ -0,0 +1,60 @@
+# file: clkmgr_dcm.ucf
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# Input clock periods. These duplicate the values entered for the
+# input clocks. You can use these to time your system
+#----------------------------------------------------------------
+NET "CLK_IN1" TNM_NET = "CLK_IN1";
+TIMESPEC "TS_CLK_IN1" = PERIOD "CLK_IN1" 20.0 ns HIGH 50% INPUT_JITTER 200.0ps;
+
+
+# FALSE PATH constraints
+PIN "RESET" TIG;
+
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm.sym b/novena/src/rtl/ipcore/clkmgr_dcm.sym
new file mode 100644
index 0000000..7d178b8
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm.sym
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<symbol version="7" name="clkmgr_dcm">
+ <symboltype>BLOCK</symboltype>
+ <timestamp>2015-1-28T21:56:19</timestamp>
+ <pin polarity="Input" x="0" y="80" name="clk_in1" />
+ <pin polarity="Input" x="0" y="432" name="reset" />
+ <pin polarity="Output" x="608" y="80" name="clk_out1" />
+ <pin polarity="Output" x="608" y="880" name="input_clk_stopped" />
+ <pin polarity="Output" x="608" y="1008" name="clk_valid" />
+ <graph>
+ <text style="fontsize:40;fontname:Arial" x="32" y="32">clkmgr_dcm</text>
+ <rect width="544" x="32" y="32" height="1056" />
+ <line x2="32" y1="80" y2="80" x1="0" />
+ <attrtext style="fontsize:24;fontname:Arial" attrname="PinName" x="36" y="80" type="pin clk_in1" />
+ <line x2="32" y1="432" y2="432" x1="0" />
+ <attrtext style="fontsize:24;fontname:Arial" attrname="PinName" x="36" y="432" type="pin reset" />
+ <line x2="576" y1="80" y2="80" x1="608" />
+ <attrtext style="alignment:RIGHT;fontsize:24;fontname:Arial" attrname="PinName" x="572" y="80" type="pin clk_out1" />
+ <line x2="576" y1="880" y2="880" x1="608" />
+ <attrtext style="alignment:RIGHT;fontsize:24;fontname:Arial" attrname="PinName" x="572" y="880" type="pin input_clk_stopped" />
+ <line x2="576" y1="1008" y2="1008" x1="608" />
+ <attrtext style="alignment:RIGHT;fontsize:24;fontname:Arial" attrname="PinName" x="572" y="1008" type="pin clk_valid" />
+ </graph>
+</symbol>
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm.ucf b/novena/src/rtl/ipcore/clkmgr_dcm.ucf
new file mode 100644
index 0000000..658fdb4
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm.ucf
@@ -0,0 +1,59 @@
+# file: clkmgr_dcm.ucf
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# Input clock periods. These duplicate the values entered for the
+# input clocks. You can use these to time your system
+#----------------------------------------------------------------
+NET "CLK_IN1" TNM_NET = "CLK_IN1";
+TIMESPEC "TS_CLK_IN1" = PERIOD "CLK_IN1" 20.0 ns HIGH 50% INPUT_JITTER 200.0ps;
+
+
+# FALSE PATH constraints
+PIN "RESET" TIG;
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm.v b/novena/src/rtl/ipcore/clkmgr_dcm.v
new file mode 100644
index 0000000..71477a8
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm.v
@@ -0,0 +1,148 @@
+// file: clkmgr_dcm.v
+//
+// (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+//
+// This file contains confidential and proprietary information
+// of Xilinx, Inc. and is protected under U.S. and
+// international copyright and other intellectual property
+// laws.
+//
+// DISCLAIMER
+// This disclaimer is not a license and does not grant any
+// rights to the materials distributed herewith. Except as
+// otherwise provided in a valid license issued to you by
+// Xilinx, and to the maximum extent permitted by applicable
+// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+// (2) Xilinx shall not be liable (whether in contract or tort,
+// including negligence, or under any other theory of
+// liability) for any loss or damage of any kind or nature
+// related to, arising under or in connection with these
+// materials, including for any direct, or any indirect,
+// special, incidental, or consequential loss or damage
+// (including loss of data, profits, goodwill, or any type of
+// loss or damage suffered as a result of any action brought
+// by a third party) even if such damage or loss was
+// reasonably foreseeable or Xilinx had been advised of the
+// possibility of the same.
+//
+// CRITICAL APPLICATIONS
+// Xilinx products are not designed or intended to be fail-
+// safe, or for use in any application requiring fail-safe
+// performance, such as life-support or safety devices or
+// systems, Class III medical devices, nuclear facilities,
+// applications related to the deployment of airbags, or any
+// other applications that could lead to death, personal
+// injury, or severe property or environmental damage
+// (individually and collectively, "Critical
+// Applications"). Customer assumes the sole risk and
+// liability of any use of Xilinx products in Critical
+// Applications, subject only to applicable laws and
+// regulations governing limitations on product liability.
+//
+// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+// PART OF THIS FILE AT ALL TIMES.
+//
+//----------------------------------------------------------------------------
+// User entered comments
+//----------------------------------------------------------------------------
+// None
+//
+//----------------------------------------------------------------------------
+// "Output Output Phase Duty Pk-to-Pk Phase"
+// "Clock Freq (MHz) (degrees) Cycle (%) Jitter (ps) Error (ps)"
+//----------------------------------------------------------------------------
+// CLK_OUT1____50.000______0.000______50.0______200.000____150.000
+//
+//----------------------------------------------------------------------------
+// "Input Clock Freq (MHz) Input Jitter (UI)"
+//----------------------------------------------------------------------------
+// __primary______________50____________0.010
+
+`timescale 1ps/1ps
+
+(* CORE_GENERATION_INFO = "clkmgr_dcm,clk_wiz_v3_6,{component_name=clkmgr_dcm,use_phase_alignment=true,use_min_o_jitter=false,use_max_i_jitter=false,use_dyn_phase_shift=false,use_inclk_switchover=false,use_dyn_reconfig=false,feedback_source=FDBK_AUTO,primtype_sel=DCM_SP,num_out_clk=1,clkin1_period=20.0,clkin2_period=20.0,use_power_down=false,use_reset=true,use_locked=false,use_inclk_stopped=true,use_status=false,use_freeze=false,use_clk_valid=true,feedback_type=SINGLE,clock_mgr_type=MANU [...]
+module clkmgr_dcm
+ (// Clock in ports
+ input CLK_IN1,
+ // Clock out ports
+ output CLK_OUT1,
+ // Status and control signals
+ input RESET,
+ output INPUT_CLK_STOPPED,
+ output CLK_VALID
+ );
+
+ // Input buffering
+ //------------------------------------
+ assign clkin1 = CLK_IN1;
+
+
+ // Clocking primitive
+ //------------------------------------
+
+ // Instantiation of the DCM primitive
+ // * Unused inputs are tied off
+ // * Unused outputs are labeled unused
+ wire psdone_unused;
+ wire locked_int;
+ wire [7:0] status_int;
+ wire clkfb;
+ wire clk0;
+
+ DCM_SP
+ #(.CLKDV_DIVIDE (2.000),
+ .CLKFX_DIVIDE (1),
+ .CLKFX_MULTIPLY (4),
+ .CLKIN_DIVIDE_BY_2 ("FALSE"),
+ .CLKIN_PERIOD (20.0),
+ .CLKOUT_PHASE_SHIFT ("NONE"),
+ .CLK_FEEDBACK ("1X"),
+ .DESKEW_ADJUST ("SYSTEM_SYNCHRONOUS"),
+ .PHASE_SHIFT (0),
+ .STARTUP_WAIT ("FALSE"))
+ dcm_sp_inst
+ // Input clock
+ (.CLKIN (clkin1),
+ .CLKFB (clkfb),
+ // Output clocks
+ .CLK0 (clk0),
+ .CLK90 (),
+ .CLK180 (),
+ .CLK270 (),
+ .CLK2X (),
+ .CLK2X180 (),
+ .CLKFX (),
+ .CLKFX180 (),
+ .CLKDV (),
+ // Ports for dynamic phase shift
+ .PSCLK (1'b0),
+ .PSEN (1'b0),
+ .PSINCDEC (1'b0),
+ .PSDONE (),
+ // Other control and status signals
+ .LOCKED (locked_int),
+ .STATUS (status_int),
+
+ .RST (RESET),
+ // Unused pin- tie low
+ .DSSEN (1'b0));
+
+ assign INPUT_CLK_STOPPED = status_int[1];
+ assign CLK_VALID = ( ( locked_int == 1'b 1 ) && ( status_int[1] == 1'b 0 ) );
+
+ // Output buffering
+ //-----------------------------------
+ assign clkfb = CLK_OUT1;
+
+ BUFG clkout1_buf
+ (.O (CLK_OUT1),
+ .I (clk0));
+
+
+
+
+endmodule
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm.veo b/novena/src/rtl/ipcore/clkmgr_dcm.veo
new file mode 100644
index 0000000..c4e1d31
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm.veo
@@ -0,0 +1,79 @@
+//
+// (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+//
+// This file contains confidential and proprietary information
+// of Xilinx, Inc. and is protected under U.S. and
+// international copyright and other intellectual property
+// laws.
+//
+// DISCLAIMER
+// This disclaimer is not a license and does not grant any
+// rights to the materials distributed herewith. Except as
+// otherwise provided in a valid license issued to you by
+// Xilinx, and to the maximum extent permitted by applicable
+// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+// (2) Xilinx shall not be liable (whether in contract or tort,
+// including negligence, or under any other theory of
+// liability) for any loss or damage of any kind or nature
+// related to, arising under or in connection with these
+// materials, including for any direct, or any indirect,
+// special, incidental, or consequential loss or damage
+// (including loss of data, profits, goodwill, or any type of
+// loss or damage suffered as a result of any action brought
+// by a third party) even if such damage or loss was
+// reasonably foreseeable or Xilinx had been advised of the
+// possibility of the same.
+//
+// CRITICAL APPLICATIONS
+// Xilinx products are not designed or intended to be fail-
+// safe, or for use in any application requiring fail-safe
+// performance, such as life-support or safety devices or
+// systems, Class III medical devices, nuclear facilities,
+// applications related to the deployment of airbags, or any
+// other applications that could lead to death, personal
+// injury, or severe property or environmental damage
+// (individually and collectively, "Critical
+// Applications"). Customer assumes the sole risk and
+// liability of any use of Xilinx products in Critical
+// Applications, subject only to applicable laws and
+// regulations governing limitations on product liability.
+//
+// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+// PART OF THIS FILE AT ALL TIMES.
+//
+//----------------------------------------------------------------------------
+// User entered comments
+//----------------------------------------------------------------------------
+// None
+//
+//----------------------------------------------------------------------------
+// "Output Output Phase Duty Pk-to-Pk Phase"
+// "Clock Freq (MHz) (degrees) Cycle (%) Jitter (ps) Error (ps)"
+//----------------------------------------------------------------------------
+// CLK_OUT1____50.000______0.000______50.0______200.000____150.000
+//
+//----------------------------------------------------------------------------
+// "Input Clock Freq (MHz) Input Jitter (UI)"
+//----------------------------------------------------------------------------
+// __primary______________50____________0.010
+
+// The following must be inserted into your Verilog file for this
+// core to be instantiated. Change the instance name and port connections
+// (in parentheses) to your own signal names.
+
+//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
+
+ clkmgr_dcm instance_name
+ (// Clock in ports
+ .CLK_IN1(CLK_IN1), // IN
+ // Clock out ports
+ .CLK_OUT1(CLK_OUT1), // OUT
+ // Status and control signals
+ .RESET(RESET),// IN
+ .INPUT_CLK_STOPPED(INPUT_CLK_STOPPED), // OUT
+ .CLK_VALID(CLK_VALID)); // OUT
+// INST_TAG_END ------ End INSTANTIATION Template ---------
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm.xco b/novena/src/rtl/ipcore/clkmgr_dcm.xco
new file mode 100644
index 0000000..37f1a1d
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm.xco
@@ -0,0 +1,269 @@
+##############################################################
+#
+# Xilinx Core Generator version 14.7
+# Date: Sun Feb 01 07:49:40 2015
+#
+##############################################################
+#
+# This file contains the customisation parameters for a
+# Xilinx CORE Generator IP GUI. It is strongly recommended
+# that you do not manually alter this file as it may cause
+# unexpected and unsupported behavior.
+#
+##############################################################
+#
+# Generated from component: xilinx.com:ip:clk_wiz:3.6
+#
+##############################################################
+#
+# BEGIN Project Options
+SET addpads = false
+SET asysymbol = true
+SET busformat = BusFormatAngleBracketNotRipped
+SET createndf = false
+SET designentry = Verilog
+SET device = xc6slx45
+SET devicefamily = spartan6
+SET flowvendor = Other
+SET formalverification = false
+SET foundationsym = false
+SET implementationfiletype = Ngc
+SET package = csg324
+SET removerpms = false
+SET simulationfiles = Behavioral
+SET speedgrade = -3
+SET verilogsim = true
+SET vhdlsim = false
+# END Project Options
+# BEGIN Select
+SELECT Clocking_Wizard xilinx.com:ip:clk_wiz:3.6
+# END Select
+# BEGIN Parameters
+CSET calc_done=DONE
+CSET clk_in_sel_port=CLK_IN_SEL
+CSET clk_out1_port=CLK_OUT1
+CSET clk_out1_use_fine_ps_gui=false
+CSET clk_out2_port=CLK_OUT2
+CSET clk_out2_use_fine_ps_gui=false
+CSET clk_out3_port=CLK_OUT3
+CSET clk_out3_use_fine_ps_gui=false
+CSET clk_out4_port=CLK_OUT4
+CSET clk_out4_use_fine_ps_gui=false
+CSET clk_out5_port=CLK_OUT5
+CSET clk_out5_use_fine_ps_gui=false
+CSET clk_out6_port=CLK_OUT6
+CSET clk_out6_use_fine_ps_gui=false
+CSET clk_out7_port=CLK_OUT7
+CSET clk_out7_use_fine_ps_gui=false
+CSET clk_valid_port=CLK_VALID
+CSET clkfb_in_n_port=CLKFB_IN_N
+CSET clkfb_in_p_port=CLKFB_IN_P
+CSET clkfb_in_port=CLKFB_IN
+CSET clkfb_in_signaling=SINGLE
+CSET clkfb_out_n_port=CLKFB_OUT_N
+CSET clkfb_out_p_port=CLKFB_OUT_P
+CSET clkfb_out_port=CLKFB_OUT
+CSET clkfb_stopped_port=CLKFB_STOPPED
+CSET clkin1_jitter_ps=200.0
+CSET clkin1_ui_jitter=0.010
+CSET clkin2_jitter_ps=100.0
+CSET clkin2_ui_jitter=0.010
+CSET clkout1_drives=BUFG
+CSET clkout1_requested_duty_cycle=50.0
+CSET clkout1_requested_out_freq=50
+CSET clkout1_requested_phase=0.000
+CSET clkout2_drives=BUFG
+CSET clkout2_requested_duty_cycle=50.0
+CSET clkout2_requested_out_freq=50
+CSET clkout2_requested_phase=0
+CSET clkout2_used=false
+CSET clkout3_drives=BUFG
+CSET clkout3_requested_duty_cycle=50.0
+CSET clkout3_requested_out_freq=100.000
+CSET clkout3_requested_phase=0.000
+CSET clkout3_used=false
+CSET clkout4_drives=BUFG
+CSET clkout4_requested_duty_cycle=50.0
+CSET clkout4_requested_out_freq=100.000
+CSET clkout4_requested_phase=0.000
+CSET clkout4_used=false
+CSET clkout5_drives=BUFG
+CSET clkout5_requested_duty_cycle=50.0
+CSET clkout5_requested_out_freq=100.000
+CSET clkout5_requested_phase=0.000
+CSET clkout5_used=false
+CSET clkout6_drives=BUFG
+CSET clkout6_requested_duty_cycle=50.0
+CSET clkout6_requested_out_freq=100.000
+CSET clkout6_requested_phase=0.000
+CSET clkout6_used=false
+CSET clkout7_drives=BUFG
+CSET clkout7_requested_duty_cycle=50.0
+CSET clkout7_requested_out_freq=100.000
+CSET clkout7_requested_phase=0.000
+CSET clkout7_used=false
+CSET clock_mgr_type=MANUAL
+CSET component_name=clkmgr_dcm
+CSET daddr_port=DADDR
+CSET dclk_port=DCLK
+CSET dcm_clk_feedback=1X
+CSET dcm_clk_out1_port=CLK0
+CSET dcm_clk_out2_port=CLK0
+CSET dcm_clk_out3_port=CLK0
+CSET dcm_clk_out4_port=CLK0
+CSET dcm_clk_out5_port=CLK0
+CSET dcm_clk_out6_port=CLK0
+CSET dcm_clkdv_divide=2.0
+CSET dcm_clkfx_divide=1
+CSET dcm_clkfx_multiply=4
+CSET dcm_clkgen_clk_out1_port=CLKFX
+CSET dcm_clkgen_clk_out2_port=CLKFX
+CSET dcm_clkgen_clk_out3_port=CLKFX
+CSET dcm_clkgen_clkfx_divide=1
+CSET dcm_clkgen_clkfx_md_max=0.000
+CSET dcm_clkgen_clkfx_multiply=4
+CSET dcm_clkgen_clkfxdv_divide=2
+CSET dcm_clkgen_clkin_period=10.000
+CSET dcm_clkgen_notes=None
+CSET dcm_clkgen_spread_spectrum=NONE
+CSET dcm_clkgen_startup_wait=false
+CSET dcm_clkin_divide_by_2=false
+CSET dcm_clkin_period=20.000
+CSET dcm_clkout_phase_shift=NONE
+CSET dcm_deskew_adjust=SYSTEM_SYNCHRONOUS
+CSET dcm_notes=None
+CSET dcm_phase_shift=0
+CSET dcm_pll_cascade=NONE
+CSET dcm_startup_wait=false
+CSET den_port=DEN
+CSET din_port=DIN
+CSET dout_port=DOUT
+CSET drdy_port=DRDY
+CSET dwe_port=DWE
+CSET feedback_source=FDBK_AUTO
+CSET in_freq_units=Units_MHz
+CSET in_jitter_units=Units_UI
+CSET input_clk_stopped_port=INPUT_CLK_STOPPED
+CSET jitter_options=UI
+CSET jitter_sel=No_Jitter
+CSET locked_port=LOCKED
+CSET mmcm_bandwidth=OPTIMIZED
+CSET mmcm_clkfbout_mult_f=4.000
+CSET mmcm_clkfbout_phase=0.000
+CSET mmcm_clkfbout_use_fine_ps=false
+CSET mmcm_clkin1_period=10.000
+CSET mmcm_clkin2_period=10.000
+CSET mmcm_clkout0_divide_f=4.000
+CSET mmcm_clkout0_duty_cycle=0.500
+CSET mmcm_clkout0_phase=0.000
+CSET mmcm_clkout0_use_fine_ps=false
+CSET mmcm_clkout1_divide=1
+CSET mmcm_clkout1_duty_cycle=0.500
+CSET mmcm_clkout1_phase=0.000
+CSET mmcm_clkout1_use_fine_ps=false
+CSET mmcm_clkout2_divide=1
+CSET mmcm_clkout2_duty_cycle=0.500
+CSET mmcm_clkout2_phase=0.000
+CSET mmcm_clkout2_use_fine_ps=false
+CSET mmcm_clkout3_divide=1
+CSET mmcm_clkout3_duty_cycle=0.500
+CSET mmcm_clkout3_phase=0.000
+CSET mmcm_clkout3_use_fine_ps=false
+CSET mmcm_clkout4_cascade=false
+CSET mmcm_clkout4_divide=1
+CSET mmcm_clkout4_duty_cycle=0.500
+CSET mmcm_clkout4_phase=0.000
+CSET mmcm_clkout4_use_fine_ps=false
+CSET mmcm_clkout5_divide=1
+CSET mmcm_clkout5_duty_cycle=0.500
+CSET mmcm_clkout5_phase=0.000
+CSET mmcm_clkout5_use_fine_ps=false
+CSET mmcm_clkout6_divide=1
+CSET mmcm_clkout6_duty_cycle=0.500
+CSET mmcm_clkout6_phase=0.000
+CSET mmcm_clkout6_use_fine_ps=false
+CSET mmcm_clock_hold=false
+CSET mmcm_compensation=ZHOLD
+CSET mmcm_divclk_divide=1
+CSET mmcm_notes=None
+CSET mmcm_ref_jitter1=0.010
+CSET mmcm_ref_jitter2=0.010
+CSET mmcm_startup_wait=false
+CSET num_out_clks=1
+CSET override_dcm=false
+CSET override_dcm_clkgen=false
+CSET override_mmcm=false
+CSET override_pll=false
+CSET platform=nt
+CSET pll_bandwidth=OPTIMIZED
+CSET pll_clk_feedback=CLKFBOUT
+CSET pll_clkfbout_mult=8
+CSET pll_clkfbout_phase=0.000
+CSET pll_clkin_period=20.0
+CSET pll_clkout0_divide=2
+CSET pll_clkout0_duty_cycle=0.500
+CSET pll_clkout0_phase=0.000
+CSET pll_clkout1_divide=10
+CSET pll_clkout1_duty_cycle=0.500
+CSET pll_clkout1_phase=0.000
+CSET pll_clkout2_divide=1
+CSET pll_clkout2_duty_cycle=0.500
+CSET pll_clkout2_phase=0.000
+CSET pll_clkout3_divide=1
+CSET pll_clkout3_duty_cycle=0.500
+CSET pll_clkout3_phase=0.000
+CSET pll_clkout4_divide=1
+CSET pll_clkout4_duty_cycle=0.500
+CSET pll_clkout4_phase=0.000
+CSET pll_clkout5_divide=1
+CSET pll_clkout5_duty_cycle=0.500
+CSET pll_clkout5_phase=0.000
+CSET pll_compensation=SYSTEM_SYNCHRONOUS
+CSET pll_divclk_divide=1
+CSET pll_notes=None
+CSET pll_ref_jitter=0.010
+CSET power_down_port=POWER_DOWN
+CSET prim_in_freq=50
+CSET prim_in_jitter=0.010
+CSET prim_source=No_buffer
+CSET primary_port=CLK_IN1
+CSET primitive=MMCM
+CSET primtype_sel=DCM_SP
+CSET psclk_port=PSCLK
+CSET psdone_port=PSDONE
+CSET psen_port=PSEN
+CSET psincdec_port=PSINCDEC
+CSET relative_inclk=REL_PRIMARY
+CSET reset_port=RESET
+CSET secondary_in_freq=100.000
+CSET secondary_in_jitter=0.010
+CSET secondary_port=CLK_IN2
+CSET secondary_source=Single_ended_clock_capable_pin
+CSET ss_mod_freq=250
+CSET ss_mode=CENTER_HIGH
+CSET status_port=STATUS
+CSET summary_strings=empty
+CSET use_clk_valid=true
+CSET use_clkfb_stopped=false
+CSET use_dyn_phase_shift=false
+CSET use_dyn_reconfig=false
+CSET use_freeze=false
+CSET use_freq_synth=true
+CSET use_inclk_stopped=true
+CSET use_inclk_switchover=false
+CSET use_locked=false
+CSET use_max_i_jitter=false
+CSET use_min_o_jitter=false
+CSET use_min_power=false
+CSET use_phase_alignment=true
+CSET use_power_down=false
+CSET use_reset=true
+CSET use_spread_spectrum=false
+CSET use_spread_spectrum_1=false
+CSET use_status=false
+# END Parameters
+# BEGIN Extra information
+MISC pkg_timestamp=2012-05-10T12:44:55Z
+# END Extra information
+GENERATE
+# CRC: d6857c2d
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm.xdc b/novena/src/rtl/ipcore/clkmgr_dcm.xdc
new file mode 100644
index 0000000..9ecc102
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm.xdc
@@ -0,0 +1,67 @@
+# file: clkmgr_dcm.xdc
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# Input clock periods. These duplicate the values entered for the
+# input clocks. You can use these to time your system
+#----------------------------------------------------------------
+create_clock -name CLK_IN1 -period 20.0 [get_ports CLK_IN1]
+set_propagated_clock CLK_IN1
+set_input_jitter CLK_IN1 0.2
+
+set_false_path -from [get_ports "RESET"]
+
+# Derived clock periods. These are commented out because they are
+# automatically propogated by the tools
+# However, if you'd like to use them for module level testing, you
+# can copy them into your module level timing checks
+#-----------------------------------------------------------------
+
+#-----------------------------------------------------------------
+
+#-----------------------------------------------------------------
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm.xise b/novena/src/rtl/ipcore/clkmgr_dcm.xise
new file mode 100644
index 0000000..7369d3b
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm.xise
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<project xmlns="http://www.xilinx.com/XMLSchema" xmlns:xil_pn="http://www.xilinx.com/XMLSchema">
+
+ <header>
+ <!-- ISE source project file created by Project Navigator. -->
+ <!-- -->
+ <!-- This file contains project source information including a list of -->
+ <!-- project source files, project and process properties. This file, -->
+ <!-- along with the project source files, is sufficient to open and -->
+ <!-- implement in ISE Project Navigator. -->
+ <!-- -->
+ <!-- Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved. -->
+ </header>
+
+ <version xil_pn:ise_version="14.7" xil_pn:schema_version="2"/>
+
+ <files>
+ <file xil_pn:name="clkmgr_dcm.ucf" xil_pn:type="FILE_UCF">
+ <association xil_pn:name="Implementation" xil_pn:seqID="0"/>
+ </file>
+ <file xil_pn:name="clkmgr_dcm.v" xil_pn:type="FILE_VERILOG">
+ <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="1"/>
+ <association xil_pn:name="Implementation" xil_pn:seqID="1"/>
+ <association xil_pn:name="PostMapSimulation" xil_pn:seqID="3"/>
+ <association xil_pn:name="PostRouteSimulation" xil_pn:seqID="3"/>
+ <association xil_pn:name="PostTranslateSimulation" xil_pn:seqID="3"/>
+ </file>
+ </files>
+
+ <properties>
+ <property xil_pn:name="Auto Implementation Top" xil_pn:value="false" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Device" xil_pn:value="xc6slx45" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Device Family" xil_pn:value="Spartan6" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Enable Internal Done Pipe" xil_pn:value="true" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Implementation Stop View" xil_pn:value="PreSynthesis" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Implementation Top" xil_pn:value="Module|clkmgr_dcm" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Implementation Top File" xil_pn:value="clkmgr_dcm.v" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Implementation Top Instance Path" xil_pn:value="/clkmgr_dcm" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Package" xil_pn:value="csg324" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Preferred Language" xil_pn:value="Verilog" xil_pn:valueState="default"/>
+ <property xil_pn:name="Project Generator" xil_pn:value="CoreGen" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="Property Specification in Project File" xil_pn:value="Store all values" xil_pn:valueState="default"/>
+ <property xil_pn:name="Simulator" xil_pn:value="ISim (VHDL/Verilog)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Speed Grade" xil_pn:value="-3" xil_pn:valueState="default"/>
+ <property xil_pn:name="Synthesis Tool" xil_pn:value="XST (VHDL/Verilog)" xil_pn:valueState="default"/>
+ <property xil_pn:name="Top-Level Source Type" xil_pn:value="HDL" xil_pn:valueState="default"/>
+ <property xil_pn:name="Working Directory" xil_pn:value="." xil_pn:valueState="non-default"/>
+ <!-- -->
+ <!-- The following properties are for internal use only. These should not be modified.-->
+ <!-- -->
+ <property xil_pn:name="PROP_DesignName" xil_pn:value="clkmgr_dcm" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_DevFamilyPMName" xil_pn:value="spartan6" xil_pn:valueState="default"/>
+ <property xil_pn:name="PROP_intProjectCreationTimestamp" xil_pn:value="2015-02-01T08:50:04" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_intWbtProjectID" xil_pn:value="67BEB73269CA45ADBC7997434CEC13CB" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_intWorkingDirLocWRTProjDir" xil_pn:value="Same" xil_pn:valueState="non-default"/>
+ <property xil_pn:name="PROP_intWorkingDirUsed" xil_pn:value="No" xil_pn:valueState="non-default"/>
+ </properties>
+
+ <bindings>
+ <binding xil_pn:location="/clkmgr_dcm" xil_pn:name="clkmgr_dcm.ucf"/>
+ </bindings>
+
+ <libraries/>
+
+ <autoManagedFiles>
+ <!-- The following files are identified by `include statements in verilog -->
+ <!-- source files and are automatically managed by Project Navigator. -->
+ <!-- -->
+ <!-- Do not hand-edit this section, as it will be overwritten when the -->
+ <!-- project is analyzed based on files automatically identified as -->
+ <!-- include files. -->
+ </autoManagedFiles>
+
+</project>
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/clk_wiz_v3_6_readme.txt b/novena/src/rtl/ipcore/clkmgr_dcm/clk_wiz_v3_6_readme.txt
new file mode 100644
index 0000000..91dcdd0
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/clk_wiz_v3_6_readme.txt
@@ -0,0 +1,184 @@
+CHANGE LOG for LogiCORE Clocking Wizard V3.6
+
+ Release Date: June 19, 2013
+--------------------------------------------------------------------------------
+
+Table of Contents
+
+1. INTRODUCTION
+2. DEVICE SUPPORT
+3. NEW FEATURE HISTORY
+4. RESOLVED ISSUES
+5. KNOWN ISSUES & LIMITATIONS
+6. TECHNICAL SUPPORT & FEEDBACK
+7. CORE RELEASE HISTORY
+8. LEGAL DISCLAIMER
+
+--------------------------------------------------------------------------------
+
+
+1. INTRODUCTION
+
+For installation instructions for this release, please go to:
+
+ http://www.xilinx.com/ipcenter/coregen/ip_update_install_instructions.htm
+
+For system requirements:
+
+ http://www.xilinx.com/ipcenter/coregen/ip_update_system_requirements.htm
+
+This file contains release notes for the Xilinx LogiCORE IP Clocking Wizard v3.6
+solution. For the latest core updates, see the product page at:
+
+ http://www.xilinx.com/products/design_resources/conn_central/solution_kits/wizards/
+
+................................................................................
+
+2. DEVICE SUPPORT
+
+
+ 2.1 ISE
+
+
+ The following device families are supported by the core for this release.
+
+ All 7 Series devices
+
+
+ Zynq-7000 devices
+ Zynq-7000
+ Defense Grade Zynq-7000Q (XQ)
+
+
+ All Virtex-6 devices
+
+
+ All Spartan-6 devices
+
+
+................................................................................
+
+3. NEW FEATURE HISTORY
+
+
+ 3.1 ISE
+
+ - Spread Spectrum support for 7 series MMCME2
+
+ - ISE 14.2 software support
+
+................................................................................
+
+4. RESOLVED ISSUES
+
+
+ 4.1 ISE
+
+ Resolved issue with example design becoming core top in planAhead
+
+ Resolved issue with Virtex6 MMCM instantiation for VHDL project
+ Please refer to AR 50719 - http://www.xilinx.com/support/answers/50719.htm
+
+................................................................................
+
+5. KNOWN ISSUES & LIMITATIONS
+
+
+ 5.1 ISE
+
+
+ The most recent information, including known issues, workarounds, and
+ resolutions for this version is provided in the IP Release Notes Guide
+ located at
+
+ www.xilinx.com/support/documentation/user_guides/xtp025.pdf
+
+
+................................................................................
+
+6. TECHNICAL SUPPORT & FEEDBACK
+
+
+To obtain technical support, create a WebCase at www.xilinx.com/support.
+Questions are routed to a team with expertise using this product.
+
+Xilinx provides technical support for use of this product when used
+according to the guidelines described in the core documentation, and
+cannot guarantee timing, functionality, or support of this product for
+designs that do not follow specified guidelines.
+
+
+................................................................................
+
+7. CORE RELEASE HISTORY
+
+
+Date By Version Description
+================================================================================
+06/19/2013 Xilinx, Inc. 3.6(Rev3) ISE 14.6 support
+10/16/2012 Xilinx, Inc. 3.6(Rev2) ISE 14.3 support
+07/25/2012 Xilinx, Inc. 3.6 ISE 14.2 support
+04/24/2012 Xilinx, Inc. 3.5 ISE 14.1 support
+01/18/2012 Xilinx, Inc. 3.3 ISE 13.4 support
+06/22/2011 Xilinx, Inc. 3.2 ISE 13.2 support
+03/01/2011 Xilinx, Inc. 3.1 ISE 13.1 support
+12/14/2010 Xilinx, Inc. 1.8 ISE 12.4 support
+09/21/2010 Xilinx, Inc. 1.7 ISE 12.3 support
+07/23/2010 Xilinx, Inc. 1.6 ISE 12.2 support
+04/19/2010 Xilinx, Inc. 1.5 ISE 12.1 support
+12/02/2009 Xilinx, Inc. 1.4 ISE 11.4 support
+09/16/2009 Xilinx, Inc. 1.3 ISE 11.3 support
+06/24/2009 Xilinx, Inc. 1.2 ISE 11.2 support
+04/24/2009 Xilinx, Inc. 1.1 Initial release; 11.1 support
+================================================================================
+
+................................................................................
+
+8. LEGAL DISCLAIMER
+
+(c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved.
+
+This file contains confidential and proprietary information
+of Xilinx, Inc. and is protected under U.S. and
+international copyright and other intellectual property
+laws.
+
+DISCLAIMER
+This disclaimer is not a license and does not grant any
+rights to the materials distributed herewith. Except as
+otherwise provided in a valid license issued to you by
+Xilinx, and to the maximum extent permitted by applicable
+law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+(2) Xilinx shall not be liable (whether in contract or tort,
+including negligence, or under any other theory of
+liability) for any loss or damage of any kind or nature
+related to, arising under or in connection with these
+materials, including for any direct, or any indirect,
+special, incidental, or consequential loss or damage
+(including loss of data, profits, goodwill, or any type of
+loss or damage suffered as a result of any action brought
+by a third party) even if such damage or loss was
+reasonably foreseeable or Xilinx had been advised of the
+possibility of the same.
+
+CRITICAL APPLICATIONS
+Xilinx products are not designed or intended to be fail-
+safe, or for use in any application requiring fail-safe
+performance, such as life-support or safety devices or
+systems, Class III medical devices, nuclear facilities,
+applications related to the deployment of airbags, or any
+other applications that could lead to death, personal
+injury, or severe property or environmental damage
+(individually and collectively, "Critical
+Applications"). Customer assumes the sole risk and
+liability of any use of Xilinx products in Critical
+Applications, subject only to applicable laws and
+regulations governing limitations on product liability.
+
+THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+PART OF THIS FILE AT ALL TIMES.
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_readme.txt b/novena/src/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_readme.txt
new file mode 100644
index 0000000..91dcdd0
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_readme.txt
@@ -0,0 +1,184 @@
+CHANGE LOG for LogiCORE Clocking Wizard V3.6
+
+ Release Date: June 19, 2013
+--------------------------------------------------------------------------------
+
+Table of Contents
+
+1. INTRODUCTION
+2. DEVICE SUPPORT
+3. NEW FEATURE HISTORY
+4. RESOLVED ISSUES
+5. KNOWN ISSUES & LIMITATIONS
+6. TECHNICAL SUPPORT & FEEDBACK
+7. CORE RELEASE HISTORY
+8. LEGAL DISCLAIMER
+
+--------------------------------------------------------------------------------
+
+
+1. INTRODUCTION
+
+For installation instructions for this release, please go to:
+
+ http://www.xilinx.com/ipcenter/coregen/ip_update_install_instructions.htm
+
+For system requirements:
+
+ http://www.xilinx.com/ipcenter/coregen/ip_update_system_requirements.htm
+
+This file contains release notes for the Xilinx LogiCORE IP Clocking Wizard v3.6
+solution. For the latest core updates, see the product page at:
+
+ http://www.xilinx.com/products/design_resources/conn_central/solution_kits/wizards/
+
+................................................................................
+
+2. DEVICE SUPPORT
+
+
+ 2.1 ISE
+
+
+ The following device families are supported by the core for this release.
+
+ All 7 Series devices
+
+
+ Zynq-7000 devices
+ Zynq-7000
+ Defense Grade Zynq-7000Q (XQ)
+
+
+ All Virtex-6 devices
+
+
+ All Spartan-6 devices
+
+
+................................................................................
+
+3. NEW FEATURE HISTORY
+
+
+ 3.1 ISE
+
+ - Spread Spectrum support for 7 series MMCME2
+
+ - ISE 14.2 software support
+
+................................................................................
+
+4. RESOLVED ISSUES
+
+
+ 4.1 ISE
+
+ Resolved issue with example design becoming core top in planAhead
+
+ Resolved issue with Virtex6 MMCM instantiation for VHDL project
+ Please refer to AR 50719 - http://www.xilinx.com/support/answers/50719.htm
+
+................................................................................
+
+5. KNOWN ISSUES & LIMITATIONS
+
+
+ 5.1 ISE
+
+
+ The most recent information, including known issues, workarounds, and
+ resolutions for this version is provided in the IP Release Notes Guide
+ located at
+
+ www.xilinx.com/support/documentation/user_guides/xtp025.pdf
+
+
+................................................................................
+
+6. TECHNICAL SUPPORT & FEEDBACK
+
+
+To obtain technical support, create a WebCase at www.xilinx.com/support.
+Questions are routed to a team with expertise using this product.
+
+Xilinx provides technical support for use of this product when used
+according to the guidelines described in the core documentation, and
+cannot guarantee timing, functionality, or support of this product for
+designs that do not follow specified guidelines.
+
+
+................................................................................
+
+7. CORE RELEASE HISTORY
+
+
+Date By Version Description
+================================================================================
+06/19/2013 Xilinx, Inc. 3.6(Rev3) ISE 14.6 support
+10/16/2012 Xilinx, Inc. 3.6(Rev2) ISE 14.3 support
+07/25/2012 Xilinx, Inc. 3.6 ISE 14.2 support
+04/24/2012 Xilinx, Inc. 3.5 ISE 14.1 support
+01/18/2012 Xilinx, Inc. 3.3 ISE 13.4 support
+06/22/2011 Xilinx, Inc. 3.2 ISE 13.2 support
+03/01/2011 Xilinx, Inc. 3.1 ISE 13.1 support
+12/14/2010 Xilinx, Inc. 1.8 ISE 12.4 support
+09/21/2010 Xilinx, Inc. 1.7 ISE 12.3 support
+07/23/2010 Xilinx, Inc. 1.6 ISE 12.2 support
+04/19/2010 Xilinx, Inc. 1.5 ISE 12.1 support
+12/02/2009 Xilinx, Inc. 1.4 ISE 11.4 support
+09/16/2009 Xilinx, Inc. 1.3 ISE 11.3 support
+06/24/2009 Xilinx, Inc. 1.2 ISE 11.2 support
+04/24/2009 Xilinx, Inc. 1.1 Initial release; 11.1 support
+================================================================================
+
+................................................................................
+
+8. LEGAL DISCLAIMER
+
+(c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved.
+
+This file contains confidential and proprietary information
+of Xilinx, Inc. and is protected under U.S. and
+international copyright and other intellectual property
+laws.
+
+DISCLAIMER
+This disclaimer is not a license and does not grant any
+rights to the materials distributed herewith. Except as
+otherwise provided in a valid license issued to you by
+Xilinx, and to the maximum extent permitted by applicable
+law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+(2) Xilinx shall not be liable (whether in contract or tort,
+including negligence, or under any other theory of
+liability) for any loss or damage of any kind or nature
+related to, arising under or in connection with these
+materials, including for any direct, or any indirect,
+special, incidental, or consequential loss or damage
+(including loss of data, profits, goodwill, or any type of
+loss or damage suffered as a result of any action brought
+by a third party) even if such damage or loss was
+reasonably foreseeable or Xilinx had been advised of the
+possibility of the same.
+
+CRITICAL APPLICATIONS
+Xilinx products are not designed or intended to be fail-
+safe, or for use in any application requiring fail-safe
+performance, such as life-support or safety devices or
+systems, Class III medical devices, nuclear facilities,
+applications related to the deployment of airbags, or any
+other applications that could lead to death, personal
+injury, or severe property or environmental damage
+(individually and collectively, "Critical
+Applications"). Customer assumes the sole risk and
+liability of any use of Xilinx products in Critical
+Applications, subject only to applicable laws and
+regulations governing limitations on product liability.
+
+THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+PART OF THIS FILE AT ALL TIMES.
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_vinfo.html b/novena/src/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_vinfo.html
new file mode 100644
index 0000000..d6deba0
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/doc/clk_wiz_v3_6_vinfo.html
@@ -0,0 +1,195 @@
+<HTML>
+<HEAD>
+<TITLE>clk_wiz_v3_6_vinfo</TITLE>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/plain;CHARSET=iso-8859-1">
+</HEAD>
+<BODY>
+<PRE><FONT face="Arial, Helvetica, sans-serif" size="-1">
+CHANGE LOG for LogiCORE Clocking Wizard V3.6
+
+ Release Date: June 19, 2013
+--------------------------------------------------------------------------------
+
+Table of Contents
+
+1. INTRODUCTION
+2. DEVICE SUPPORT
+3. NEW FEATURE HISTORY
+4. RESOLVED ISSUES
+5. KNOWN ISSUES & LIMITATIONS
+6. TECHNICAL SUPPORT & FEEDBACK
+7. CORE RELEASE HISTORY
+8. LEGAL DISCLAIMER
+
+--------------------------------------------------------------------------------
+
+
+1. INTRODUCTION
+
+For installation instructions for this release, please go to:
+
+ <A HREF="http://www.xilinx.com/ipcenter/coregen/ip_update_install_instructions.htm">www.xilinx.com/ipcenter/coregen/ip_update_install_instructions.htm</A>
+
+For system requirements:
+
+ <A HREF="http://www.xilinx.com/ipcenter/coregen/ip_update_system_requirements.htm">www.xilinx.com/ipcenter/coregen/ip_update_system_requirements.htm</A>
+
+This file contains release notes for the Xilinx LogiCORE IP Clocking Wizard v3.6
+solution. For the latest core updates, see the product page at:
+
+ <A HREF="http://www.xilinx.com/products/design_resources/conn_central/solution_kits/wizards/">www.xilinx.com/products/design_resources/conn_central/solution_kits/wizards/</A>
+
+................................................................................
+
+2. DEVICE SUPPORT
+
+
+ 2.1 ISE
+
+
+ The following device families are supported by the core for this release.
+
+ All 7 Series devices
+
+
+ Zynq-7000 devices
+ Zynq-7000
+ Defense Grade Zynq-7000Q (XQ)
+
+
+ All Virtex-6 devices
+
+
+ All Spartan-6 devices
+
+
+................................................................................
+
+3. NEW FEATURE HISTORY
+
+
+ 3.1 ISE
+
+ - Spread Spectrum support for 7 series MMCME2
+
+ - ISE 14.2 software support
+
+................................................................................
+
+4. RESOLVED ISSUES
+
+
+ 4.1 ISE
+
+ Resolved issue with example design becoming core top in planAhead
+
+ Resolved issue with Virtex6 MMCM instantiation for VHDL project
+ Please refer to AR 50719 - <A HREF="http://www.xilinx.com/support/answers/50719.htm">www.xilinx.com/support/answers/50719.htm</A>
+
+................................................................................
+
+5. KNOWN ISSUES & LIMITATIONS
+
+
+ 5.1 ISE
+
+
+ The most recent information, including known issues, workarounds, and
+ resolutions for this version is provided in the IP Release Notes Guide
+ located at
+
+ <A HREF="http://www.xilinx.com/support/documentation/user_guides/xtp025.pdf">www.xilinx.com/support/documentation/user_guides/xtp025.pdf</A>
+
+
+................................................................................
+
+6. TECHNICAL SUPPORT & FEEDBACK
+
+
+To obtain technical support, create a WebCase at <A HREF="http://www.xilinx.com/support.">www.xilinx.com/support.</A>
+Questions are routed to a team with expertise using this product.
+
+Xilinx provides technical support for use of this product when used
+according to the guidelines described in the core documentation, and
+cannot guarantee timing, functionality, or support of this product for
+designs that do not follow specified guidelines.
+
+
+................................................................................
+
+7. CORE RELEASE HISTORY
+
+
+Date By Version Description
+================================================================================
+06/19/2013 Xilinx, Inc. 3.6(Rev3) ISE 14.6 support
+10/16/2012 Xilinx, Inc. 3.6(Rev2) ISE 14.3 support
+07/25/2012 Xilinx, Inc. 3.6 ISE 14.2 support
+04/24/2012 Xilinx, Inc. 3.5 ISE 14.1 support
+01/18/2012 Xilinx, Inc. 3.3 ISE 13.4 support
+06/22/2011 Xilinx, Inc. 3.2 ISE 13.2 support
+03/01/2011 Xilinx, Inc. 3.1 ISE 13.1 support
+12/14/2010 Xilinx, Inc. 1.8 ISE 12.4 support
+09/21/2010 Xilinx, Inc. 1.7 ISE 12.3 support
+07/23/2010 Xilinx, Inc. 1.6 ISE 12.2 support
+04/19/2010 Xilinx, Inc. 1.5 ISE 12.1 support
+12/02/2009 Xilinx, Inc. 1.4 ISE 11.4 support
+09/16/2009 Xilinx, Inc. 1.3 ISE 11.3 support
+06/24/2009 Xilinx, Inc. 1.2 ISE 11.2 support
+04/24/2009 Xilinx, Inc. 1.1 Initial release; 11.1 support
+================================================================================
+
+................................................................................
+
+8. LEGAL DISCLAIMER
+
+(c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved.
+
+This file contains confidential and proprietary information
+of Xilinx, Inc. and is protected under U.S. and
+international copyright and other intellectual property
+laws.
+
+DISCLAIMER
+This disclaimer is not a license and does not grant any
+rights to the materials distributed herewith. Except as
+otherwise provided in a valid license issued to you by
+Xilinx, and to the maximum extent permitted by applicable
+law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+(2) Xilinx shall not be liable (whether in contract or tort,
+including negligence, or under any other theory of
+liability) for any loss or damage of any kind or nature
+related to, arising under or in connection with these
+materials, including for any direct, or any indirect,
+special, incidental, or consequential loss or damage
+(including loss of data, profits, goodwill, or any type of
+loss or damage suffered as a result of any action brought
+by a third party) even if such damage or loss was
+reasonably foreseeable or Xilinx had been advised of the
+possibility of the same.
+
+CRITICAL APPLICATIONS
+Xilinx products are not designed or intended to be fail-
+safe, or for use in any application requiring fail-safe
+performance, such as life-support or safety devices or
+systems, Class III medical devices, nuclear facilities,
+applications related to the deployment of airbags, or any
+other applications that could lead to death, personal
+injury, or severe property or environmental damage
+(individually and collectively, "Critical
+Applications"). Customer assumes the sole risk and
+liability of any use of Xilinx products in Critical
+Applications, subject only to applicable laws and
+regulations governing limitations on product liability.
+
+THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+PART OF THIS FILE AT ALL TIMES.
+
+</FONT>
+</PRE>
+</BODY>
+</HTML>
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/doc/pg065_clk_wiz.pdf b/novena/src/rtl/ipcore/clkmgr_dcm/doc/pg065_clk_wiz.pdf
new file mode 100644
index 0000000..a7daa60
Binary files /dev/null and b/novena/src/rtl/ipcore/clkmgr_dcm/doc/pg065_clk_wiz.pdf differ
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.ucf b/novena/src/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.ucf
new file mode 100644
index 0000000..dffb528
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.ucf
@@ -0,0 +1,60 @@
+# file: clkmgr_dcm_exdes.ucf
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# Input clock periods. These duplicate the values entered for the
+# input clocks. You can use these to time your system
+#----------------------------------------------------------------
+NET "CLK_IN1" TNM_NET = "CLK_IN1";
+TIMESPEC "TS_CLK_IN1" = PERIOD "CLK_IN1" 20.0 ns HIGH 50% INPUT_JITTER 200.0ps;
+
+
+# FALSE PATH constraints
+PIN "COUNTER_RESET" TIG;
+PIN "RESET" TIG;
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.v b/novena/src/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.v
new file mode 100644
index 0000000..10627b3
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.v
@@ -0,0 +1,164 @@
+// file: clkmgr_dcm_exdes.v
+//
+// (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+//
+// This file contains confidential and proprietary information
+// of Xilinx, Inc. and is protected under U.S. and
+// international copyright and other intellectual property
+// laws.
+//
+// DISCLAIMER
+// This disclaimer is not a license and does not grant any
+// rights to the materials distributed herewith. Except as
+// otherwise provided in a valid license issued to you by
+// Xilinx, and to the maximum extent permitted by applicable
+// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+// (2) Xilinx shall not be liable (whether in contract or tort,
+// including negligence, or under any other theory of
+// liability) for any loss or damage of any kind or nature
+// related to, arising under or in connection with these
+// materials, including for any direct, or any indirect,
+// special, incidental, or consequential loss or damage
+// (including loss of data, profits, goodwill, or any type of
+// loss or damage suffered as a result of any action brought
+// by a third party) even if such damage or loss was
+// reasonably foreseeable or Xilinx had been advised of the
+// possibility of the same.
+//
+// CRITICAL APPLICATIONS
+// Xilinx products are not designed or intended to be fail-
+// safe, or for use in any application requiring fail-safe
+// performance, such as life-support or safety devices or
+// systems, Class III medical devices, nuclear facilities,
+// applications related to the deployment of airbags, or any
+// other applications that could lead to death, personal
+// injury, or severe property or environmental damage
+// (individually and collectively, "Critical
+// Applications"). Customer assumes the sole risk and
+// liability of any use of Xilinx products in Critical
+// Applications, subject only to applicable laws and
+// regulations governing limitations on product liability.
+//
+// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+// PART OF THIS FILE AT ALL TIMES.
+//
+
+//----------------------------------------------------------------------------
+// Clocking wizard example design
+//----------------------------------------------------------------------------
+// This example design instantiates the created clocking network, where each
+// output clock drives a counter. The high bit of each counter is ported.
+//----------------------------------------------------------------------------
+
+`timescale 1ps/1ps
+
+module clkmgr_dcm_exdes
+ #(
+ parameter TCQ = 100
+ )
+ (// Clock in ports
+ input CLK_IN1,
+ // Reset that only drives logic in example design
+ input COUNTER_RESET,
+ output [1:1] CLK_OUT,
+ // High bits of counters driven by clocks
+ output COUNT,
+ // Status and control signals
+ input RESET,
+ output INPUT_CLK_STOPPED,
+ output CLK_VALID
+ );
+
+ // Parameters for the counters
+ //-------------------------------
+ // Counter width
+ localparam C_W = 16;
+ // Create reset for the counters
+ wire reset_int = RESET || COUNTER_RESET;
+
+ reg rst_sync;
+ reg rst_sync_int;
+ reg rst_sync_int1;
+ reg rst_sync_int2;
+
+
+
+ // Declare the clocks and counter
+ wire clk_int;
+ wire clk_n;
+ wire clk;
+ reg [C_W-1:0] counter;
+
+ // Insert BUFGs on all input clocks that don't already have them
+ //--------------------------------------------------------------
+ BUFG clkin1_buf
+ (.O (clk_in1_buf),
+ .I (CLK_IN1));
+
+ // Instantiation of the clocking network
+ //--------------------------------------
+ clkmgr_dcm clknetwork
+ (// Clock in ports
+ .CLK_IN1 (clk_in1_buf),
+ // Clock out ports
+ .CLK_OUT1 (clk_int),
+ // Status and control signals
+ .RESET (RESET),
+ .INPUT_CLK_STOPPED (INPUT_CLK_STOPPED),
+ .CLK_VALID (CLK_VALID));
+
+ assign clk_n = ~clk;
+
+ ODDR2 clkout_oddr
+ (.Q (CLK_OUT[1]),
+ .C0 (clk),
+ .C1 (clk_n),
+ .CE (1'b1),
+ .D0 (1'b1),
+ .D1 (1'b0),
+ .R (1'b0),
+ .S (1'b0));
+
+ // Connect the output clocks to the design
+ //-----------------------------------------
+ assign clk = clk_int;
+
+
+ // Reset synchronizer
+ //-----------------------------------
+ always @(posedge reset_int or posedge clk) begin
+ if (reset_int) begin
+ rst_sync <= 1'b1;
+ rst_sync_int <= 1'b1;
+ rst_sync_int1 <= 1'b1;
+ rst_sync_int2 <= 1'b1;
+ end
+ else begin
+ rst_sync <= 1'b0;
+ rst_sync_int <= rst_sync;
+ rst_sync_int1 <= rst_sync_int;
+ rst_sync_int2 <= rst_sync_int1;
+ end
+ end
+
+
+ // Output clock sampling
+ //-----------------------------------
+ always @(posedge clk or posedge rst_sync_int2) begin
+ if (rst_sync_int2) begin
+ counter <= #TCQ { C_W { 1'b 0 } };
+ end else begin
+ counter <= #TCQ counter + 1'b 1;
+ end
+ end
+
+ // alias the high bit to the output
+ assign COUNT = counter[C_W-1];
+
+
+
+endmodule
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.xdc b/novena/src/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.xdc
new file mode 100644
index 0000000..787023d
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/example_design/clkmgr_dcm_exdes.xdc
@@ -0,0 +1,69 @@
+# file: clkmgr_dcm_exdes.xdc
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# Input clock periods. These duplicate the values entered for the
+# input clocks. You can use these to time your system
+#----------------------------------------------------------------
+create_clock -name CLK_IN1 -period 20.0 [get_ports CLK_IN1]
+set_propagated_clock CLK_IN1
+set_input_jitter CLK_IN1 0.2
+
+# FALSE PATH constraint added on COUNTER_RESET
+set_false_path -from [get_ports "COUNTER_RESET"]
+set_false_path -from [get_ports "RESET"]
+
+# Derived clock periods. These are commented out because they are
+# automatically propogated by the tools
+# However, if you'd like to use them for module level testing, you
+# can copy them into your module level timing checks
+#-----------------------------------------------------------------
+
+#-----------------------------------------------------------------
+
+#-----------------------------------------------------------------
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/implement/implement.bat b/novena/src/rtl/ipcore/clkmgr_dcm/implement/implement.bat
new file mode 100644
index 0000000..3d313d5
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/implement/implement.bat
@@ -0,0 +1,90 @@
+REM file: implement.bat
+REM
+REM (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+REM
+REM This file contains confidential and proprietary information
+REM of Xilinx, Inc. and is protected under U.S. and
+REM international copyright and other intellectual property
+REM laws.
+REM
+REM DISCLAIMER
+REM This disclaimer is not a license and does not grant any
+REM rights to the materials distributed herewith. Except as
+REM otherwise provided in a valid license issued to you by
+REM Xilinx, and to the maximum extent permitted by applicable
+REM law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+REM WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+REM AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+REM BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+REM INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+REM (2) Xilinx shall not be liable (whether in contract or tort,
+REM including negligence, or under any other theory of
+REM liability) for any loss or damage of any kind or nature
+REM related to, arising under or in connection with these
+REM materials, including for any direct, or any indirect,
+REM special, incidental, or consequential loss or damage
+REM (including loss of data, profits, goodwill, or any type of
+REM loss or damage suffered as a result of any action brought
+REM by a third party) even if such damage or loss was
+REM reasonably foreseeable or Xilinx had been advised of the
+REM possibility of the same.
+REM
+REM CRITICAL APPLICATIONS
+REM Xilinx products are not designed or intended to be fail-
+REM safe, or for use in any application requiring fail-safe
+REM performance, such as life-support or safety devices or
+REM systems, Class III medical devices, nuclear facilities,
+REM applications related to the deployment of airbags, or any
+REM other applications that could lead to death, personal
+REM injury, or severe property or environmental damage
+REM (individually and collectively, "Critical
+REM Applications"). Customer assumes the sole risk and
+REM liability of any use of Xilinx products in Critical
+REM Applications, subject only to applicable laws and
+REM regulations governing limitations on product liability.
+REM
+REM THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+REM PART OF THIS FILE AT ALL TIMES.
+REM
+
+REM -----------------------------------------------------------------------------
+REM Script to synthesize and implement the RTL provided for the clocking wizard
+REM -----------------------------------------------------------------------------
+
+REM Clean up the results directory
+rmdir /S /Q results
+mkdir results
+
+REM Copy unisim_comp.v file to results directory
+copy %XILINX%\verilog\src\iSE\unisim_comp.v .\results\
+
+REM Synthesize the Verilog Wrapper Files
+echo 'Synthesizing Clocking Wizard design with XST'
+xst -ifn xst.scr
+move clkmgr_dcm_exdes.ngc results\
+
+REM Copy the constraints files generated by Coregen
+echo 'Copying files from constraints directory to results directory'
+copy ..\example_design\clkmgr_dcm_exdes.ucf results\
+
+cd results
+
+echo 'Running ngdbuild'
+ngdbuild -uc clkmgr_dcm_exdes.ucf clkmgr_dcm_exdes
+
+echo 'Running map'
+map -timing -pr b clkmgr_dcm_exdes -o mapped.ncd
+
+echo 'Running par'
+par -w mapped.ncd routed mapped.pcf
+
+echo 'Running trce'
+trce -e 10 routed -o routed mapped.pcf
+
+echo 'Running design through bitgen'
+bitgen -w routed
+
+echo 'Running netgen to create gate level model for the clocking wizard example design'
+netgen -ofmt verilog -sim -sdf_anno false -tm clkmgr_dcm_exdes -w routed.ncd routed.v
+cd ..
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/implement/implement.sh b/novena/src/rtl/ipcore/clkmgr_dcm/implement/implement.sh
new file mode 100644
index 0000000..2c64bee
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/implement/implement.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+# file: implement.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+#-----------------------------------------------------------------------------
+# Script to synthesize and implement the RTL provided for the clocking wizard
+#-----------------------------------------------------------------------------
+
+# Clean up the results directory
+rm -rf results
+mkdir results
+
+# Copy unisim_comp.v file to results directory
+cp $XILINX/verilog/src/iSE/unisim_comp.v ./results/
+
+# Synthesize the Verilog Wrapper Files
+echo 'Synthesizing Clocking Wizard design with XST'
+xst -ifn xst.scr
+mv clkmgr_dcm_exdes.ngc results/
+
+# Copy the constraints files generated by Coregen
+echo 'Copying files from constraints directory to results directory'
+cp ../example_design/clkmgr_dcm_exdes.ucf results/
+
+cd results
+
+echo 'Running ngdbuild'
+ngdbuild -uc clkmgr_dcm_exdes.ucf clkmgr_dcm_exdes
+
+echo 'Running map'
+map -timing clkmgr_dcm_exdes -o mapped.ncd
+
+echo 'Running par'
+par -w mapped.ncd routed mapped.pcf
+
+echo 'Running trce'
+trce -e 10 routed -o routed mapped.pcf
+
+echo 'Running design through bitgen'
+bitgen -w routed
+
+echo 'Running netgen to create gate level model for the clocking wizard example design'
+netgen -ofmt verilog -sim -sdf_anno false -tm clkmgr_dcm_exdes -w routed.ncd routed.v
+
+cd ..
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.bat b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.bat
new file mode 100644
index 0000000..9782028
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.bat
@@ -0,0 +1,58 @@
+REM file: planAhead_ise.bat
+REM
+REM (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+REM
+REM This file contains confidential and proprietary information
+REM of Xilinx, Inc. and is protected under U.S. and
+REM international copyright and other intellectual property
+REM laws.
+REM
+REM DISCLAIMER
+REM This disclaimer is not a license and does not grant any
+REM rights to the materials distributed herewith. Except as
+REM otherwise provided in a valid license issued to you by
+REM Xilinx, and to the maximum extent permitted by applicable
+REM law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+REM WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+REM AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+REM BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+REM INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+REM (2) Xilinx shall not be liable (whether in contract or tort,
+REM including negligence, or under any other theory of
+REM liability) for any loss or damage of any kind or nature
+REM related to, arising under or in connection with these
+REM materials, including for any direct, or any indirect,
+REM special, incidental, or consequential loss or damage
+REM (including loss of data, profits, goodwill, or any type of
+REM loss or damage suffered as a result of any action brought
+REM by a third party) even if such damage or loss was
+REM reasonably foreseeable or Xilinx had been advised of the
+REM possibility of the same.
+REM
+REM CRITICAL APPLICATIONS
+REM Xilinx products are not designed or intended to be fail-
+REM safe, or for use in any application requiring fail-safe
+REM performance, such as life-support or safety devices or
+REM systems, Class III medical devices, nuclear facilities,
+REM applications related to the deployment of airbags, or any
+REM other applications that could lead to death, personal
+REM injury, or severe property or environmental damage
+REM (individually and collectively, "Critical
+REM Applications"). Customer assumes the sole risk and
+REM liability of any use of Xilinx products in Critical
+REM Applications, subject only to applicable laws and
+REM regulations governing limitations on product liability.
+REM
+REM THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+REM PART OF THIS FILE AT ALL TIMES.
+REM
+
+REM-----------------------------------------------------------------------------
+REM Script to synthesize and implement the RTL provided for the clocking wizard
+REM-----------------------------------------------------------------------------
+
+del \f results
+mkdir results
+cd results
+
+planAhead -mode batch -source ..\planAhead_ise.tcl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.sh b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.sh
new file mode 100644
index 0000000..7f436b6
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+# file: planAhead_ise.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+#-----------------------------------------------------------------------------
+# Script to synthesize and implement the RTL provided for the clocking wizard
+#-----------------------------------------------------------------------------
+
+rm -rf results
+mkdir results
+cd results
+
+planAhead -mode batch -source ../planAhead_ise.tcl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.tcl b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.tcl
new file mode 100644
index 0000000..ab77638
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_ise.tcl
@@ -0,0 +1,78 @@
+# file: planAhead_ise.tcl
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+set projDir [file dirname [info script]]
+set projName clkmgr_dcm
+set topName clkmgr_dcm_exdes
+set device xc6slx45csg324-3
+
+create_project $projName $projDir/results/$projName -part $device
+
+set_property design_mode RTL [get_filesets sources_1]
+
+## Source files
+#set verilogSources [glob $srcDir/*.v]
+import_files -fileset [get_filesets sources_1] -force -norecurse ../../example_design/clkmgr_dcm_exdes.v
+import_files -fileset [get_filesets sources_1] -force -norecurse ../../../clkmgr_dcm.v
+
+
+#UCF file
+import_files -fileset [get_filesets constrs_1] -force -norecurse ../../example_design/clkmgr_dcm_exdes.ucf
+
+set_property top $topName [get_property srcset [current_run]]
+
+launch_runs -runs synth_1
+wait_on_run synth_1
+
+set_property add_step Bitgen [get_runs impl_1]
+launch_runs -runs impl_1
+wait_on_run impl_1
+
+
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.bat b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.bat
new file mode 100644
index 0000000..3e1e03b
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.bat
@@ -0,0 +1,58 @@
+REM file: planAhead_rdn.sh
+REM
+REM (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+REM
+REM This file contains confidential and proprietary information
+REM of Xilinx, Inc. and is protected under U.S. and
+REM international copyright and other intellectual property
+REM laws.
+REM
+REM DISCLAIMER
+REM This disclaimer is not a license and does not grant any
+REM rights to the materials distributed herewith. Except as
+REM otherwise provided in a valid license issued to you by
+REM Xilinx, and to the maximum extent permitted by applicable
+REM law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+REM WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+REM AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+REM BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+REM INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+REM (2) Xilinx shall not be liable (whether in contract or tort,
+REM including negligence, or under any other theory of
+REM liability) for any loss or damage of any kind or nature
+REM related to, arising under or in connection with these
+REM materials, including for any direct, or any indirect,
+REM special, incidental, or consequential loss or damage
+REM (including loss of data, profits, goodwill, or any type of
+REM loss or damage suffered as a result of any action brought
+REM by a third party) even if such damage or loss was
+REM reasonably foreseeable or Xilinx had been advised of the
+REM possibility of the same.
+REM
+REM CRITICAL APPLICATIONS
+REM Xilinx products are not designed or intended to be fail-
+REM safe, or for use in any application requiring fail-safe
+REM performance, such as life-support or safety devices or
+REM systems, Class III medical devices, nuclear facilities,
+REM applications related to the deployment of airbags, or any
+REM other applications that could lead to death, personal
+REM injury, or severe property or environmental damage
+REM (individually and collectively, "Critical
+REM Applications"). Customer assumes the sole risk and
+REM liability of any use of Xilinx products in Critical
+REM Applications, subject only to applicable laws and
+REM regulations governing limitations on product liability.
+REM
+REM THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+REM PART OF THIS FILE AT ALL TIMES.
+REM
+
+REM-----------------------------------------------------------------------------
+REM Script to synthesize and implement the RTL provided for the XADC wizard
+REM-----------------------------------------------------------------------------
+
+del \f results
+mkdir results
+cd results
+
+planAhead -mode batch -source ..\planAhead_rdn.tcl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.sh b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.sh
new file mode 100644
index 0000000..a5adee8
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# file: planAhead_rdn.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+#-----------------------------------------------------------------------------
+# Script to synthesize and implement the RTL provided for the XADC wizard
+#-----------------------------------------------------------------------------
+rm -rf results
+mkdir results
+cd results
+planAhead -mode batch -source ../planAhead_rdn.tcl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.tcl b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.tcl
new file mode 100644
index 0000000..e8c0fdf
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/implement/planAhead_rdn.tcl
@@ -0,0 +1,69 @@
+# file : planAhead_rdn.tcl
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+set device xc6slx45csg324-3
+set projName clkmgr_dcm
+set design clkmgr_dcm
+set projDir [file dirname [info script]]
+create_project $projName $projDir/results/$projName -part $device -force
+set_property design_mode RTL [current_fileset -srcset]
+set top_module clkmgr_dcm_exdes
+set_property top clkmgr_dcm_exdes [get_property srcset [current_run]]
+add_files -norecurse {../../../clkmgr_dcm.v}
+add_files -norecurse {../../example_design/clkmgr_dcm_exdes.v}
+import_files -fileset [get_filesets constrs_1 ] -force -norecurse {../../example_design/clkmgr_dcm_exdes.xdc}
+synth_design
+opt_design
+place_design
+route_design
+write_sdf -rename_top_module clkmgr_dcm_exdes -file routed.sdf
+write_verilog -nolib -mode timesim -sdf_anno false -rename_top_module clkmgr_dcm_exdes -file routed.v
+report_timing -nworst 30 -path_type full -file routed.twr
+report_drc -file report.drc
+write_bitstream -bitgen_options {-g UnconstrainedPins:Allow} -file routed.bit
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/implement/xst.prj b/novena/src/rtl/ipcore/clkmgr_dcm/implement/xst.prj
new file mode 100644
index 0000000..cd0e0e6
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/implement/xst.prj
@@ -0,0 +1,2 @@
+verilog work ../../clkmgr_dcm.v
+verilog work ../example_design/clkmgr_dcm_exdes.v
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/implement/xst.scr b/novena/src/rtl/ipcore/clkmgr_dcm/implement/xst.scr
new file mode 100644
index 0000000..20d09f4
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/implement/xst.scr
@@ -0,0 +1,9 @@
+run
+-ifmt MIXED
+-top clkmgr_dcm_exdes
+-p xc6slx45-csg324-3
+-ifn xst.prj
+-ofn clkmgr_dcm_exdes
+-keep_hierarchy soft
+-equivalent_register_removal no
+-max_fanout 65535
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/clkmgr_dcm_tb.v b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/clkmgr_dcm_tb.v
new file mode 100644
index 0000000..ee24750
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/clkmgr_dcm_tb.v
@@ -0,0 +1,145 @@
+// file: clkmgr_dcm_tb.v
+//
+// (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+//
+// This file contains confidential and proprietary information
+// of Xilinx, Inc. and is protected under U.S. and
+// international copyright and other intellectual property
+// laws.
+//
+// DISCLAIMER
+// This disclaimer is not a license and does not grant any
+// rights to the materials distributed herewith. Except as
+// otherwise provided in a valid license issued to you by
+// Xilinx, and to the maximum extent permitted by applicable
+// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+// (2) Xilinx shall not be liable (whether in contract or tort,
+// including negligence, or under any other theory of
+// liability) for any loss or damage of any kind or nature
+// related to, arising under or in connection with these
+// materials, including for any direct, or any indirect,
+// special, incidental, or consequential loss or damage
+// (including loss of data, profits, goodwill, or any type of
+// loss or damage suffered as a result of any action brought
+// by a third party) even if such damage or loss was
+// reasonably foreseeable or Xilinx had been advised of the
+// possibility of the same.
+//
+// CRITICAL APPLICATIONS
+// Xilinx products are not designed or intended to be fail-
+// safe, or for use in any application requiring fail-safe
+// performance, such as life-support or safety devices or
+// systems, Class III medical devices, nuclear facilities,
+// applications related to the deployment of airbags, or any
+// other applications that could lead to death, personal
+// injury, or severe property or environmental damage
+// (individually and collectively, "Critical
+// Applications"). Customer assumes the sole risk and
+// liability of any use of Xilinx products in Critical
+// Applications, subject only to applicable laws and
+// regulations governing limitations on product liability.
+//
+// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+// PART OF THIS FILE AT ALL TIMES.
+//
+
+//----------------------------------------------------------------------------
+// Clocking wizard demonstration testbench
+//----------------------------------------------------------------------------
+// This demonstration testbench instantiates the example design for the
+// clocking wizard. Input clocks are toggled, which cause the clocking
+// network to lock and the counters to increment.
+//----------------------------------------------------------------------------
+
+`timescale 1ps/1ps
+
+`define wait_lock @(posedge CLK_VALID)
+
+module clkmgr_dcm_tb ();
+
+ // Clock to Q delay of 100ps
+ localparam TCQ = 100;
+
+
+ // timescale is 1ps/1ps
+ localparam ONE_NS = 1000;
+ localparam PHASE_ERR_MARGIN = 100; // 100ps
+ // how many cycles to run
+ localparam COUNT_PHASE = 1024;
+ // we'll be using the period in many locations
+ localparam time PER1 = 20.0*ONE_NS;
+ localparam time PER1_1 = PER1/2;
+ localparam time PER1_2 = PER1 - PER1/2;
+
+ // Declare the input clock signals
+ reg CLK_IN1 = 1;
+
+ // The high bit of the sampling counter
+ wire COUNT;
+ // Status and control signals
+ reg RESET = 0;
+ wire INPUT_CLK_STOPPED;
+ wire CLK_VALID;
+ reg COUNTER_RESET = 0;
+wire [1:1] CLK_OUT;
+//Freq Check using the M & D values setting and actual Frequency generated
+
+
+ // Input clock generation
+ //------------------------------------
+ always begin
+ CLK_IN1 = #PER1_1 ~CLK_IN1;
+ CLK_IN1 = #PER1_2 ~CLK_IN1;
+ end
+
+ // Test sequence
+ reg [15*8-1:0] test_phase = "";
+ initial begin
+ // Set up any display statements using time to be readable
+ $timeformat(-12, 2, "ps", 10);
+ COUNTER_RESET = 0;
+ test_phase = "reset";
+ RESET = 1;
+ #(PER1*6);
+ RESET = 0;
+ test_phase = "wait lock";
+ `wait_lock;
+ #(PER1*6);
+ COUNTER_RESET = 1;
+ #(PER1*20)
+ COUNTER_RESET = 0;
+
+ test_phase = "counting";
+ #(PER1*COUNT_PHASE);
+
+ $display("SIMULATION PASSED");
+ $display("SYSTEM_CLOCK_COUNTER : %0d\n",$time/PER1);
+ $finish;
+ end
+
+ // Instantiation of the example design containing the clock
+ // network and sampling counters
+ //---------------------------------------------------------
+ clkmgr_dcm_exdes
+ #(
+ .TCQ (TCQ)
+ ) dut
+ (// Clock in ports
+ .CLK_IN1 (CLK_IN1),
+ // Reset for logic in example design
+ .COUNTER_RESET (COUNTER_RESET),
+ .CLK_OUT (CLK_OUT),
+ // High bits of the counters
+ .COUNT (COUNT),
+ // Status and control signals
+ .RESET (RESET),
+ .INPUT_CLK_STOPPED (INPUT_CLK_STOPPED),
+ .CLK_VALID (CLK_VALID));
+
+// Freq Check
+
+endmodule
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simcmds.tcl b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simcmds.tcl
new file mode 100644
index 0000000..e19ead8
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simcmds.tcl
@@ -0,0 +1,8 @@
+# file: simcmds.tcl
+
+# create the simulation script
+vcd dumpfile isim.vcd
+vcd dumpvars -m /clkmgr_dcm_tb -l 0
+wave add /
+run 50000ns
+quit
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.bat b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.bat
new file mode 100644
index 0000000..80904cb
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.bat
@@ -0,0 +1,59 @@
+REM file: simulate_isim.bat
+REM
+REM (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+REM
+REM This file contains confidential and proprietary information
+REM of Xilinx, Inc. and is protected under U.S. and
+REM international copyright and other intellectual property
+REM laws.
+REM
+REM DISCLAIMER
+REM This disclaimer is not a license and does not grant any
+REM rights to the materials distributed herewith. Except as
+REM otherwise provided in a valid license issued to you by
+REM Xilinx, and to the maximum extent permitted by applicable
+REM law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+REM WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+REM AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+REM BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+REM INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+REM (2) Xilinx shall not be liable (whether in contract or tort,
+REM including negligence, or under any other theory of
+REM liability) for any loss or damage of any kind or nature
+REM related to, arising under or in connection with these
+REM materials, including for any direct, or any indirect,
+REM special, incidental, or consequential loss or damage
+REM (including loss of data, profits, goodwill, or any type of
+REM loss or damage suffered as a result of any action brought
+REM by a third party) even if such damage or loss was
+REM reasonably foreseeable or Xilinx had been advised of the
+REM possibility of the same.
+REM
+REM CRITICAL APPLICATIONS
+REM Xilinx products are not designed or intended to be fail-
+REM safe, or for use in any application requiring fail-safe
+REM performance, such as life-support or safety devices or
+REM systems, Class III medical devices, nuclear facilities,
+REM applications related to the deployment of airbags, or any
+REM other applications that could lead to death, personal
+REM injury, or severe property or environmental damage
+REM (individually and collectively, "Critical
+REM Applications"). Customer assumes the sole risk and
+REM liability of any use of Xilinx products in Critical
+REM Applications, subject only to applicable laws and
+REM regulations governing limitations on product liability.
+REM
+REM THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+REM PART OF THIS FILE AT ALL TIMES.
+REM
+
+vlogcomp -work work %XILINX%\verilog\src\glbl.v
+vlogcomp -work work ..\..\..\clkmgr_dcm.v
+vlogcomp -work work ..\..\example_design\clkmgr_dcm_exdes.v
+vlogcomp -work work ..\clkmgr_dcm_tb.v
+
+REM compile the project
+fuse work.clkmgr_dcm_tb work.glbl -L unisims_ver -o clkmgr_dcm_isim.exe
+
+REM run the simulation script
+.\clkmgr_dcm_isim.exe -gui -tclbatch simcmds.tcl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.sh b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.sh
new file mode 100644
index 0000000..9fb5029
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_isim.sh
@@ -0,0 +1,61 @@
+# file: simulate_isim.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# nt
+# create the project
+vlogcomp -work work ${XILINX}/verilog/src/glbl.v
+vlogcomp -work work ../../../clkmgr_dcm.v
+vlogcomp -work work ../../example_design/clkmgr_dcm_exdes.v
+vlogcomp -work work ../clkmgr_dcm_tb.v
+
+# compile the project
+fuse work.clkmgr_dcm_tb work.glbl -L unisims_ver -o clkmgr_dcm_isim.exe
+
+# run the simulation script
+./clkmgr_dcm_isim.exe -gui -tclbatch simcmds.tcl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.bat b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.bat
new file mode 100644
index 0000000..7497cd9
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.bat
@@ -0,0 +1,61 @@
+REM file: simulate_mti.bat
+REM
+REM (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+REM
+REM This file contains confidential and proprietary information
+REM of Xilinx, Inc. and is protected under U.S. and
+REM international copyright and other intellectual property
+REM laws.
+REM
+REM DISCLAIMER
+REM This disclaimer is not a license and does not grant any
+REM rights to the materials distributed herewith. Except as
+REM otherwise provided in a valid license issued to you by
+REM Xilinx, and to the maximum extent permitted by applicable
+REM law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+REM WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+REM AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+REM BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+REM INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+REM (2) Xilinx shall not be liable (whether in contract or tort,
+REM including negligence, or under any other theory of
+REM liability) for any loss or damage of any kind or nature
+REM related to, arising under or in connection with these
+REM materials, including for any direct, or any indirect,
+REM special, incidental, or consequential loss or damage
+REM (including loss of data, profits, goodwill, or any type of
+REM loss or damage suffered as a result of any action brought
+REM by a third party) even if such damage or loss was
+REM reasonably foreseeable or Xilinx had been advised of the
+REM possibility of the same.
+REM
+REM CRITICAL APPLICATIONS
+REM Xilinx products are not designed or intended to be fail-
+REM safe, or for use in any application requiring fail-safe
+REM performance, such as life-support or safety devices or
+REM systems, Class III medical devices, nuclear facilities,
+REM applications related to the deployment of airbags, or any
+REM other applications that could lead to death, personal
+REM injury, or severe property or environmental damage
+REM (individually and collectively, "Critical
+REM Applications"). Customer assumes the sole risk and
+REM liability of any use of Xilinx products in Critical
+REM Applications, subject only to applicable laws and
+REM regulations governing limitations on product liability.
+REM
+REM THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+REM PART OF THIS FILE AT ALL TIMES.
+REM
+
+REM set up the working directory
+vlib work
+
+REM compile all of the files
+vlog -work work %XILINX%\verilog\src\glbl.v
+vlog -work work ..\..\..\clkmgr_dcm.v
+vlog -work work ..\..\example_design\clkmgr_dcm_exdes.v
+vlog -work work ..\clkmgr_dcm_tb.v
+
+REM run the simulation
+vsim -c -t ps -voptargs="+acc" -L secureip -L unisims_ver work.clkmgr_dcm_tb work.glbl
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.do b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.do
new file mode 100644
index 0000000..b0e526f
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.do
@@ -0,0 +1,65 @@
+# file: simulate_mti.do
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# set up the working directory
+set work work
+vlib work
+
+# compile all of the files
+vlog -work work $env(XILINX)/verilog/src/glbl.v
+vlog -work work ../../../clkmgr_dcm.v
+vlog -work work ../../example_design/clkmgr_dcm_exdes.v
+vlog -work work ../clkmgr_dcm_tb.v
+
+# run the simulation
+vsim -t ps -voptargs="+acc" -L unisims_ver work.clkmgr_dcm_tb work.glbl
+do wave.do
+log clkmgr_dcm_tb/dut/counter
+log -r /*
+run 50000ns
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.sh b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.sh
new file mode 100644
index 0000000..66099e0
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_mti.sh
@@ -0,0 +1,61 @@
+#/bin/sh
+# file: simulate_mti.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+# set up the working directory
+set work work
+vlib work
+
+# compile all of the files
+vlog -work work $XILINX/verilog/src/glbl.v
+vlog -work work ../../../clkmgr_dcm.v
+vlog -work work ../../example_design/clkmgr_dcm_exdes.v
+vlog -work work ../clkmgr_dcm_tb.v
+
+# run the simulation
+vsim -c -t ps -voptargs="+acc" -L secureip -L unisims_ver work.clkmgr_dcm_tb work.glbl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_ncsim.sh b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_ncsim.sh
new file mode 100644
index 0000000..01b0412
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_ncsim.sh
@@ -0,0 +1,62 @@
+#/bin/sh
+# file: simulate_ncsim.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# set up the working directory
+mkdir work
+
+# compile all of the files
+ncvlog -work work ${XILINX}/verilog/src/glbl.v
+ncvlog -work work ../../../clkmgr_dcm.v
+ncvlog -work work ../../example_design/clkmgr_dcm_exdes.v
+ncvlog -work work ../clkmgr_dcm_tb.v
+
+# elaborate and run the simulation
+ncelab -work work -access +wc work.clkmgr_dcm_tb work.glbl
+ncsim -input "@database -open -shm nc; probe -create -database nc -all -depth all; probe dut.counter; run 50000ns; exit" work.clkmgr_dcm_tb
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_vcs.sh b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_vcs.sh
new file mode 100644
index 0000000..39668df
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/simulate_vcs.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+# file: simulate_vcs.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# remove old files
+rm -rf simv* csrc DVEfiles AN.DB
+
+# compile all of the files
+# Note that -sverilog is not strictly required- You can
+# remove the -sverilog if you change the type of the
+# localparam for the periods in the testbench file to
+# [63:0] from time
+vlogan -sverilog \
+ ${XILINX}/verilog/src/glbl.v \
+ ../../../clkmgr_dcm.v \
+ ../../example_design/clkmgr_dcm_exdes.v \
+ ../clkmgr_dcm_tb.v
+
+# prepare the simulation
+vcs +vcs+lic+wait -debug clkmgr_dcm_tb glbl
+
+# run the simulation
+./simv -ucli -i ucli_commands.key
+
+# launch the viewer
+dve -vpd vcdplus.vpd -session vcs_session.tcl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/ucli_commands.key b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/ucli_commands.key
new file mode 100644
index 0000000..2bbdd0f
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/ucli_commands.key
@@ -0,0 +1,5 @@
+call {$vcdpluson}
+call {$vcdplusmemon(clkmgr_dcm_tb.dut.counter)}
+run
+call {$vcdplusclose}
+quit
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/vcs_session.tcl b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/vcs_session.tcl
new file mode 100644
index 0000000..628e55a
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/vcs_session.tcl
@@ -0,0 +1,18 @@
+gui_open_window Wave
+gui_sg_create clkmgr_dcm_group
+gui_list_add_group -id Wave.1 {clkmgr_dcm_group}
+gui_sg_addsignal -group clkmgr_dcm_group {clkmgr_dcm_tb.test_phase}
+gui_set_radix -radix {ascii} -signals {clkmgr_dcm_tb.test_phase}
+gui_sg_addsignal -group clkmgr_dcm_group {{Input_clocks}} -divider
+gui_sg_addsignal -group clkmgr_dcm_group {clkmgr_dcm_tb.CLK_IN1}
+gui_sg_addsignal -group clkmgr_dcm_group {{Output_clocks}} -divider
+gui_sg_addsignal -group clkmgr_dcm_group {clkmgr_dcm_tb.dut.clk}
+gui_list_expand -id Wave.1 clkmgr_dcm_tb.dut.clk
+gui_sg_addsignal -group clkmgr_dcm_group {{Status_control}} -divider
+gui_sg_addsignal -group clkmgr_dcm_group {clkmgr_dcm_tb.RESET}
+gui_sg_addsignal -group clkmgr_dcm_group {clkmgr_dcm_tb.USE_INCLK_STOPPED}
+gui_sg_addsignal -group clkmgr_dcm_group {{Counters}} -divider
+gui_sg_addsignal -group clkmgr_dcm_group {clkmgr_dcm_tb.COUNT}
+gui_sg_addsignal -group clkmgr_dcm_group {clkmgr_dcm_tb.dut.counter}
+gui_list_expand -id Wave.1 clkmgr_dcm_tb.dut.counter
+gui_zoom -window Wave.1 -full
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.do b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.do
new file mode 100644
index 0000000..eee7422
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.do
@@ -0,0 +1,60 @@
+# file: wave.do
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+add wave -noupdate -format Literal -radix ascii /clkmgr_dcm_tb/test_phase
+add wave -noupdate -divider {Input clocks}
+add wave -noupdate -format Logic /clkmgr_dcm_tb/CLK_IN1
+add wave -noupdate -divider {Output clocks}
+add wave -noupdate -format Logic /clkmgr_dcm_tb/dut/clk
+add wave -noupdate -divider Status/control
+add wave -noupdate -format Logic /clkmgr_dcm_tb/RESET
+add wave -noupdate -format Logic /clkmgr_dcm_tb/INPUT_CLK_STOPPED
+add wave -noupdate -divider Counters
+add wave -noupdate -format Literal -radix hexadecimal /clkmgr_dcm_tb/COUNT
+add wave -noupdate -format Literal -radix hexadecimal /clkmgr_dcm_tb/dut/counter
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.sv b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.sv
new file mode 100644
index 0000000..c3c3eef
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/functional/wave.sv
@@ -0,0 +1,118 @@
+# file: wave.sv
+#
+# (c) Copyright 2008 - 2010 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+# Get the windows set up
+#
+if {[catch {window new WatchList -name "Design Browser 1" -geometry 1054x819+536+322}] != ""} {
+ window geometry "Design Browser 1" 1054x819+536+322
+}
+window target "Design Browser 1" on
+browser using {Design Browser 1}
+browser set \
+ -scope nc::clkmgr_dcm_tb
+browser yview see nc::clkmgr_dcm_tb
+browser timecontrol set -lock 0
+
+if {[catch {window new WaveWindow -name "Waveform 1" -geometry 1010x600+0+541}] != ""} {
+ window geometry "Waveform 1" 1010x600+0+541
+}
+window target "Waveform 1" on
+waveform using {Waveform 1}
+waveform sidebar visibility partial
+waveform set \
+ -primarycursor TimeA \
+ -signalnames name \
+ -signalwidth 175 \
+ -units ns \
+ -valuewidth 75
+cursor set -using TimeA -time 0
+waveform baseline set -time 0
+waveform xview limits 0 20000n
+
+#
+# Define signal groups
+#
+catch {group new -name {Output clocks} -overlay 0}
+catch {group new -name {Status/control} -overlay 0}
+catch {group new -name {Counters} -overlay 0}
+
+set id [waveform add -signals [list {nc::clkmgr_dcm_tb.CLK_IN1}]]
+
+group using {Output clocks}
+group set -overlay 0
+group set -comment {}
+group clear 0 end
+
+group insert \
+ {clkmgr_dcm_tb.dut.clk} \
+
+group using {Counters}
+group set -overlay 0
+group set -comment {}
+group clear 0 end
+
+group insert \
+ {clkmgr_dcm_tb.dut.counter} \
+
+group using {Status/control}
+group set -overlay 0
+group set -comment {}
+group clear 0 end
+
+group insert \
+ {nc::clkmgr_dcm_tb.RESET} {nc::clkmgr_dcm_tb.INPUT_CLK_STOPPED}
+
+set id [waveform add -signals [list {nc::clkmgr_dcm_tb.COUNT} ]]
+
+set id [waveform add -signals [list {nc::clkmgr_dcm_tb.test_phase} ]]
+waveform format $id -radix %a
+
+set groupId [waveform add -groups {{Input clocks}}]
+set groupId [waveform add -groups {{Output clocks}}]
+set groupId [waveform add -groups {{Status/control}}]
+set groupId [waveform add -groups {{Counters}}]
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/clkmgr_dcm_tb.v b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/clkmgr_dcm_tb.v
new file mode 100644
index 0000000..9618253
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/clkmgr_dcm_tb.v
@@ -0,0 +1,149 @@
+// file: clkmgr_dcm_tb.v
+//
+// (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+//
+// This file contains confidential and proprietary information
+// of Xilinx, Inc. and is protected under U.S. and
+// international copyright and other intellectual property
+// laws.
+//
+// DISCLAIMER
+// This disclaimer is not a license and does not grant any
+// rights to the materials distributed herewith. Except as
+// otherwise provided in a valid license issued to you by
+// Xilinx, and to the maximum extent permitted by applicable
+// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+// (2) Xilinx shall not be liable (whether in contract or tort,
+// including negligence, or under any other theory of
+// liability) for any loss or damage of any kind or nature
+// related to, arising under or in connection with these
+// materials, including for any direct, or any indirect,
+// special, incidental, or consequential loss or damage
+// (including loss of data, profits, goodwill, or any type of
+// loss or damage suffered as a result of any action brought
+// by a third party) even if such damage or loss was
+// reasonably foreseeable or Xilinx had been advised of the
+// possibility of the same.
+//
+// CRITICAL APPLICATIONS
+// Xilinx products are not designed or intended to be fail-
+// safe, or for use in any application requiring fail-safe
+// performance, such as life-support or safety devices or
+// systems, Class III medical devices, nuclear facilities,
+// applications related to the deployment of airbags, or any
+// other applications that could lead to death, personal
+// injury, or severe property or environmental damage
+// (individually and collectively, "Critical
+// Applications"). Customer assumes the sole risk and
+// liability of any use of Xilinx products in Critical
+// Applications, subject only to applicable laws and
+// regulations governing limitations on product liability.
+//
+// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+// PART OF THIS FILE AT ALL TIMES.
+//
+
+//----------------------------------------------------------------------------
+// Clocking wizard demonstration testbench
+//----------------------------------------------------------------------------
+// This demonstration testbench instantiates the example design for the
+// clocking wizard. Input clocks are toggled, which cause the clocking
+// network to lock and the counters to increment.
+//----------------------------------------------------------------------------
+
+`timescale 1ps/1ps
+
+`define wait_lock @(posedge CLK_VALID)
+
+module clkmgr_dcm_tb ();
+
+ // Clock to Q delay of 100ps
+ localparam TCQ = 100;
+
+
+ // timescale is 1ps/1ps
+ localparam ONE_NS = 1000;
+ localparam PHASE_ERR_MARGIN = 100; // 100ps
+ // how many cycles to run
+ localparam COUNT_PHASE = 1024;
+ // we'll be using the period in many locations
+ localparam time PER1 = 20.0*ONE_NS;
+ localparam time PER1_1 = PER1/2;
+ localparam time PER1_2 = PER1 - PER1/2;
+
+ // Declare the input clock signals
+ reg CLK_IN1 = 1;
+
+ // The high bit of the sampling counter
+ wire COUNT;
+ // Status and control signals
+ reg RESET = 0;
+ wire INPUT_CLK_STOPPED;
+ wire CLK_VALID;
+ reg COUNTER_RESET = 0;
+wire [1:1] CLK_OUT;
+//Freq Check using the M & D values setting and actual Frequency generated
+
+ reg [13:0] timeout_counter = 14'b00000000000000;
+
+ // Input clock generation
+ //------------------------------------
+ always begin
+ CLK_IN1 = #PER1_1 ~CLK_IN1;
+ CLK_IN1 = #PER1_2 ~CLK_IN1;
+ end
+
+ // Test sequence
+ reg [15*8-1:0] test_phase = "";
+ initial begin
+ // Set up any display statements using time to be readable
+ $timeformat(-12, 2, "ps", 10);
+ $display ("Timing checks are not valid");
+ COUNTER_RESET = 0;
+ test_phase = "reset";
+ RESET = 1;
+ #(PER1*6);
+ RESET = 0;
+ test_phase = "wait lock";
+ `wait_lock;
+ #(PER1*6);
+ COUNTER_RESET = 1;
+ #(PER1*19.5)
+ COUNTER_RESET = 0;
+ #(PER1*1)
+ $display ("Timing checks are valid");
+ test_phase = "counting";
+ #(PER1*COUNT_PHASE);
+
+ $display("SIMULATION PASSED");
+ $display("SYSTEM_CLOCK_COUNTER : %0d\n",$time/PER1);
+ $finish;
+ end
+
+
+
+ // Instantiation of the example design containing the clock
+ // network and sampling counters
+ //---------------------------------------------------------
+ clkmgr_dcm_exdes
+ dut
+ (// Clock in ports
+ .CLK_IN1 (CLK_IN1),
+ // Reset for logic in example design
+ .COUNTER_RESET (COUNTER_RESET),
+ .CLK_OUT (CLK_OUT),
+ // High bits of the counters
+ .COUNT (COUNT),
+ // Status and control signals
+ .RESET (RESET),
+ .INPUT_CLK_STOPPED (INPUT_CLK_STOPPED),
+ .CLK_VALID (CLK_VALID));
+
+
+// Freq Check
+
+endmodule
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/sdf_cmd_file b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/sdf_cmd_file
new file mode 100644
index 0000000..d59e315
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/sdf_cmd_file
@@ -0,0 +1,2 @@
+COMPILED_SDF_FILE = "../../implement/results/routed.sdf.X",
+SCOPE = clkmgr_dcm_tb.dut;
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simcmds.tcl b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simcmds.tcl
new file mode 100644
index 0000000..14523af
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simcmds.tcl
@@ -0,0 +1,9 @@
+# file: simcmds.tcl
+
+# create the simulation script
+vcd dumpfile isim.vcd
+vcd dumpvars -m /clkmgr_dcm_tb -l 0
+wave add /
+run 50000ns
+quit
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_isim.sh b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_isim.sh
new file mode 100644
index 0000000..0152cb0
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_isim.sh
@@ -0,0 +1,62 @@
+# file: simulate_isim.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# create the project
+vlogcomp -work work ${XILINX}/verilog/src/glbl.v
+vlogcomp -work work ../../implement/results/routed.v
+vlogcomp -work work clkmgr_dcm_tb.v
+
+# compile the project
+fuse work.clkmgr_dcm_tb work.glbl -L secureip -L simprims_ver -o clkmgr_dcm_isim.exe
+
+# run the simulation script
+./clkmgr_dcm_isim.exe -tclbatch simcmds.tcl -sdfmax /clkmgr_dcm_tb/dut=../../implement/results/routed.sdf
+
+# run the simulation script
+#./clkmgr_dcm_isim.exe -gui -tclbatch simcmds.tcl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.bat b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.bat
new file mode 100644
index 0000000..8a08dc0
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.bat
@@ -0,0 +1,59 @@
+REM file: simulate_mti.bat
+REM
+REM (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+REM
+REM This file contains confidential and proprietary information
+REM of Xilinx, Inc. and is protected under U.S. and
+REM international copyright and other intellectual property
+REM laws.
+REM
+REM DISCLAIMER
+REM This disclaimer is not a license and does not grant any
+REM rights to the materials distributed herewith. Except as
+REM otherwise provided in a valid license issued to you by
+REM Xilinx, and to the maximum extent permitted by applicable
+REM law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+REM WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+REM AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+REM BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+REM INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+REM (2) Xilinx shall not be liable (whether in contract or tort,
+REM including negligence, or under any other theory of
+REM liability) for any loss or damage of any kind or nature
+REM related to, arising under or in connection with these
+REM materials, including for any direct, or any indirect,
+REM special, incidental, or consequential loss or damage
+REM (including loss of data, profits, goodwill, or any type of
+REM loss or damage suffered as a result of any action brought
+REM by a third party) even if such damage or loss was
+REM reasonably foreseeable or Xilinx had been advised of the
+REM possibility of the same.
+REM
+REM CRITICAL APPLICATIONS
+REM Xilinx products are not designed or intended to be fail-
+REM safe, or for use in any application requiring fail-safe
+REM performance, such as life-support or safety devices or
+REM systems, Class III medical devices, nuclear facilities,
+REM applications related to the deployment of airbags, or any
+REM other applications that could lead to death, personal
+REM injury, or severe property or environmental damage
+REM (individually and collectively, "Critical
+REM Applications"). Customer assumes the sole risk and
+REM liability of any use of Xilinx products in Critical
+REM Applications, subject only to applicable laws and
+REM regulations governing limitations on product liability.
+REM
+REM THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+REM PART OF THIS FILE AT ALL TIMES.
+REM
+# set up the working directory
+set work work
+vlib work
+
+REM compile all of the files
+vlog -work work %XILINX%\verilog\src\glbl.v
+vlog -work work ..\..\implement\results\routed.v
+vlog -work work clkmgr_dcm_tb.v
+
+REM run the simulation
+vsim -c -t ps +transport_int_delays -voptargs="+acc" -L secureip -L simprims_ver -sdfmax clkmgr_dcm_tb\dut=..\..\implement\results\routed.sdf +no_notifier work.clkmgr_dcm_tb work.glbl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.do b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.do
new file mode 100644
index 0000000..bfeb9c5
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.do
@@ -0,0 +1,65 @@
+# file: simulate_mti.do
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# set up the working directory
+set work work
+vlib work
+
+# compile all of the files
+vlog -work work $env(XILINX)/verilog/src/glbl.v
+vlog -work work ../../implement/results/routed.v
+vlog -work work clkmgr_dcm_tb.v
+
+# run the simulation
+vsim -t ps +transport_int_delays -voptargs="+acc" -L secureip -L simprims_ver -sdfmax clkmgr_dcm_tb/dut=../../implement/results/routed.sdf +no_notifier work.clkmgr_dcm_tb work.glbl
+#do wave.do
+#log -r /*
+run 50000ns
+
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.sh b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.sh
new file mode 100644
index 0000000..b842adc
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_mti.sh
@@ -0,0 +1,61 @@
+#/bin/sh
+# file: simulate_mti.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# set up the working directory
+set work work
+vlib work
+
+# compile all of the files
+vlog -work work $XILINX/verilog/src/glbl.v
+vlog -work work ../../implement/results/routed.v
+vlog -work work clkmgr_dcm_tb.v
+
+# run the simulation
+vsim -c -t ps +transport_int_delays -voptargs="+acc" -L secureip -L simprims_ver -sdfmax clkmgr_dcm_tb/dut=../../implement/results/routed.sdf +no_notifier work.clkmgr_dcm_tb work.glbl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_ncsim.sh b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_ncsim.sh
new file mode 100644
index 0000000..fd18dde
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_ncsim.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+# file: simulate_ncsim.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# set up the working directory
+mkdir work
+
+# compile all of the files
+ncvlog -work work ${XILINX}/verilog/src/glbl.v
+ncvlog -work work ../../implement/results/routed.v
+ncvlog -work work clkmgr_dcm_tb.v
+
+# elaborate and run the simulation
+ncsdfc ../../implement/results/routed.sdf
+
+ncelab -work work -access +wc -pulse_r 10 -nonotifier work.clkmgr_dcm_tb work.glbl -sdf_cmd_file sdf_cmd_file
+ncsim -input "@database -open -shm nc; probe -create -database nc -all -depth all; run 50000ns; exit" work.clkmgr_dcm_tb
+
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_vcs.sh b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_vcs.sh
new file mode 100644
index 0000000..26a8c27
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/simulate_vcs.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+# file: simulate_vcs.sh
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+# remove old files
+rm -rf simv* csrc DVEfiles AN.DB
+
+# compile all of the files
+# Note that -sverilog is not strictly required- You can
+# remove the -sverilog if you change the type of the
+# localparam for the periods in the testbench file to
+# [63:0] from time
+ vlogan -sverilog \
+ clkmgr_dcm_tb.v \
+ ../../implement/results/routed.v
+
+
+# prepare the simulation
+vcs -sdf max:clkmgr_dcm_exdes:../../implement/results/routed.sdf +v2k -y $XILINX/verilog/src/simprims \
+ +libext+.v -debug clkmgr_dcm_tb.v ../../implement/results/routed.v
+
+# run the simulation
+./simv -ucli -i ucli_commands.key
+
+# launch the viewer
+#dve -vpd vcdplus.vpd -session vcs_session.tcl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/ucli_commands.key b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/ucli_commands.key
new file mode 100644
index 0000000..b32669e
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/ucli_commands.key
@@ -0,0 +1,5 @@
+
+call {$vcdpluson}
+run 50000ns
+call {$vcdplusclose}
+quit
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/vcs_session.tcl b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/vcs_session.tcl
new file mode 100644
index 0000000..6cc6e24
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/vcs_session.tcl
@@ -0,0 +1 @@
+gui_open_window Wave
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/wave.do b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/wave.do
new file mode 100644
index 0000000..7cc804b
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm/simulation/timing/wave.do
@@ -0,0 +1,71 @@
+# file: wave.do
+#
+# (c) Copyright 2008 - 2011 Xilinx, Inc. All rights reserved.
+#
+# This file contains confidential and proprietary information
+# of Xilinx, Inc. and is protected under U.S. and
+# international copyright and other intellectual property
+# laws.
+#
+# DISCLAIMER
+# This disclaimer is not a license and does not grant any
+# rights to the materials distributed herewith. Except as
+# otherwise provided in a valid license issued to you by
+# Xilinx, and to the maximum extent permitted by applicable
+# law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+# WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+# AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+# INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+# (2) Xilinx shall not be liable (whether in contract or tort,
+# including negligence, or under any other theory of
+# liability) for any loss or damage of any kind or nature
+# related to, arising under or in connection with these
+# materials, including for any direct, or any indirect,
+# special, incidental, or consequential loss or damage
+# (including loss of data, profits, goodwill, or any type of
+# loss or damage suffered as a result of any action brought
+# by a third party) even if such damage or loss was
+# reasonably foreseeable or Xilinx had been advised of the
+# possibility of the same.
+#
+# CRITICAL APPLICATIONS
+# Xilinx products are not designed or intended to be fail-
+# safe, or for use in any application requiring fail-safe
+# performance, such as life-support or safety devices or
+# systems, Class III medical devices, nuclear facilities,
+# applications related to the deployment of airbags, or any
+# other applications that could lead to death, personal
+# injury, or severe property or environmental damage
+# (individually and collectively, "Critical
+# Applications"). Customer assumes the sole risk and
+# liability of any use of Xilinx products in Critical
+# Applications, subject only to applicable laws and
+# regulations governing limitations on product liability.
+#
+# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+# PART OF THIS FILE AT ALL TIMES.
+#
+
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate /clkmgr_dcm_tb/CLK_IN1
+add wave -noupdate /clkmgr_dcm_tb/COUNT
+add wave -noupdate /clkmgr_dcm_tb/RESET
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 1} {3223025 ps} 0}
+configure wave -namecolwidth 238
+configure wave -valuecolwidth 107
+configure wave -justifyvalue left
+configure wave -signalnamewidth 0
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+configure wave -timelineunits ps
+update
+WaveRestoreZoom {0 ps} {74848022 ps}
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm_flist.txt b/novena/src/rtl/ipcore/clkmgr_dcm_flist.txt
new file mode 100644
index 0000000..bd1b2cd
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm_flist.txt
@@ -0,0 +1,54 @@
+# Output products list for <clkmgr_dcm>
+_xmsgs\pn_parser.xmsgs
+clkmgr_dcm.asy
+clkmgr_dcm.gise
+clkmgr_dcm.ucf
+clkmgr_dcm.v
+clkmgr_dcm.veo
+clkmgr_dcm.xco
+clkmgr_dcm.xdc
+clkmgr_dcm.xise
+clkmgr_dcm\clk_wiz_v3_6_readme.txt
+clkmgr_dcm\doc\clk_wiz_v3_6_readme.txt
+clkmgr_dcm\doc\clk_wiz_v3_6_vinfo.html
+clkmgr_dcm\doc\pg065_clk_wiz.pdf
+clkmgr_dcm\example_design\clkmgr_dcm_exdes.ucf
+clkmgr_dcm\example_design\clkmgr_dcm_exdes.v
+clkmgr_dcm\example_design\clkmgr_dcm_exdes.xdc
+clkmgr_dcm\implement\implement.bat
+clkmgr_dcm\implement\implement.sh
+clkmgr_dcm\implement\planAhead_ise.bat
+clkmgr_dcm\implement\planAhead_ise.sh
+clkmgr_dcm\implement\planAhead_ise.tcl
+clkmgr_dcm\implement\planAhead_rdn.bat
+clkmgr_dcm\implement\planAhead_rdn.sh
+clkmgr_dcm\implement\planAhead_rdn.tcl
+clkmgr_dcm\implement\xst.prj
+clkmgr_dcm\implement\xst.scr
+clkmgr_dcm\simulation\clkmgr_dcm_tb.v
+clkmgr_dcm\simulation\functional\simcmds.tcl
+clkmgr_dcm\simulation\functional\simulate_isim.bat
+clkmgr_dcm\simulation\functional\simulate_isim.sh
+clkmgr_dcm\simulation\functional\simulate_mti.bat
+clkmgr_dcm\simulation\functional\simulate_mti.do
+clkmgr_dcm\simulation\functional\simulate_mti.sh
+clkmgr_dcm\simulation\functional\simulate_ncsim.sh
+clkmgr_dcm\simulation\functional\simulate_vcs.sh
+clkmgr_dcm\simulation\functional\ucli_commands.key
+clkmgr_dcm\simulation\functional\vcs_session.tcl
+clkmgr_dcm\simulation\functional\wave.do
+clkmgr_dcm\simulation\functional\wave.sv
+clkmgr_dcm\simulation\timing\clkmgr_dcm_tb.v
+clkmgr_dcm\simulation\timing\sdf_cmd_file
+clkmgr_dcm\simulation\timing\simcmds.tcl
+clkmgr_dcm\simulation\timing\simulate_isim.sh
+clkmgr_dcm\simulation\timing\simulate_mti.bat
+clkmgr_dcm\simulation\timing\simulate_mti.do
+clkmgr_dcm\simulation\timing\simulate_mti.sh
+clkmgr_dcm\simulation\timing\simulate_ncsim.sh
+clkmgr_dcm\simulation\timing\simulate_vcs.sh
+clkmgr_dcm\simulation\timing\ucli_commands.key
+clkmgr_dcm\simulation\timing\vcs_session.tcl
+clkmgr_dcm\simulation\timing\wave.do
+clkmgr_dcm_flist.txt
+clkmgr_dcm_xmdf.tcl
diff --git a/novena/src/rtl/ipcore/clkmgr_dcm_xmdf.tcl b/novena/src/rtl/ipcore/clkmgr_dcm_xmdf.tcl
new file mode 100644
index 0000000..307029b
--- /dev/null
+++ b/novena/src/rtl/ipcore/clkmgr_dcm_xmdf.tcl
@@ -0,0 +1,140 @@
+# The package naming convention is <core_name>_xmdf
+package provide clkmgr_dcm_xmdf 1.0
+
+# This includes some utilities that support common XMDF operations
+package require utilities_xmdf
+
+# Define a namespace for this package. The name of the name space
+# is <core_name>_xmdf
+namespace eval ::clkmgr_dcm_xmdf {
+# Use this to define any statics
+}
+
+# Function called by client to rebuild the params and port arrays
+# Optional when the use context does not require the param or ports
+# arrays to be available.
+proc ::clkmgr_dcm_xmdf::xmdfInit { instance } {
+# Variable containg name of library into which module is compiled
+# Recommendation: <module_name>
+# Required
+utilities_xmdf::xmdfSetData $instance Module Attributes Name clkmgr_dcm
+}
+# ::clkmgr_dcm_xmdf::xmdfInit
+
+# Function called by client to fill in all the xmdf* data variables
+# based on the current settings of the parameters
+proc ::clkmgr_dcm_xmdf::xmdfApplyParams { instance } {
+
+set fcount 0
+# Array containing libraries that are assumed to exist
+# Examples include unisim and xilinxcorelib
+# Optional
+# In this example, we assume that the unisim library will
+# be magically
+# available to the simulation and synthesis tool
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type logical_library
+utilities_xmdf::xmdfSetData $instance FileSet $fcount logical_library unisim
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/clk_wiz_readme.txt
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/doc/clk_wiz_ds709.pdf
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/doc/clk_wiz_gsg521.pdf
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/implement/implement.bat
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/implement/implement.sh
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/implement/xst.prj
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/implement/xst.scr
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/simulation/clkmgr_dcm_tb.v
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/simulation/functional/simcmds.tcl
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/simulation/functional/simulate_isim.sh
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/simulation/functional/simulate_mti.do
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/simulation/functional/simulate_ncsim.sh
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/simulation/functional/simulate_vcs.sh
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/simulation/functional/ucli_commands.key
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/simulation/functional/vcs_session.tcl
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/simulation/functional/wave.do
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm/simulation/functional/wave.sv
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type Ignore
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm.asy
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type asy
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm.ejp
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm.ucf
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type ucf
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm.v
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type verilog
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm.veo
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type verilog_template
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm.xco
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type coregen_ip
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path clkmgr_dcm_xmdf.tcl
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount associated_module clkmgr_dcm
+incr fcount
+
+}
+
+# ::gen_comp_name_xmdf::xmdfApplyParams
diff --git a/novena/src/rtl/ipcore/coregen.cgp b/novena/src/rtl/ipcore/coregen.cgp
new file mode 100644
index 0000000..8bc2e70
--- /dev/null
+++ b/novena/src/rtl/ipcore/coregen.cgp
@@ -0,0 +1,9 @@
+SET busformat = BusFormatAngleBracketNotRipped
+SET designentry = Verilog
+SET device = xc6slx45
+SET devicefamily = spartan6
+SET flowvendor = Other
+SET package = csg324
+SET speedgrade = -3
+SET verilogsim = true
+SET vhdlsim = false
diff --git a/novena/src/rtl/ipcore/create_clkmgr_dcm.tcl b/novena/src/rtl/ipcore/create_clkmgr_dcm.tcl
new file mode 100644
index 0000000..fec8dec
--- /dev/null
+++ b/novena/src/rtl/ipcore/create_clkmgr_dcm.tcl
@@ -0,0 +1,37 @@
+##
+## Core Generator Run Script, generator for Project Navigator create command
+##
+
+proc findRtfPath { relativePath } {
+ set xilenv ""
+ if { [info exists ::env(XILINX) ] } {
+ if { [info exists ::env(MYXILINX)] } {
+ set xilenv [join [list $::env(MYXILINX) $::env(XILINX)] $::xilinx::path_sep ]
+ } else {
+ set xilenv $::env(XILINX)
+ }
+ }
+ foreach path [ split $xilenv $::xilinx::path_sep ] {
+ set fullPath [ file join $path $relativePath ]
+ if { [ file exists $fullPath ] } {
+ return $fullPath
+ }
+ }
+ return ""
+}
+
+source [ findRtfPath "data/projnav/scripts/dpm_cgUtils.tcl" ]
+
+set result [ run_cg_create "xilinx.com:ip:clk_wiz:3.6" "clkmgr_dcm" "Clocking Wizard" "Clocking Wizard (xilinx.com:ip:clk_wiz:3.6) generated by Project Navigator" xc6slx45-3csg324 Verilog ]
+
+if { $result == 0 } {
+ puts "Core Generator create command completed successfully."
+} elseif { $result == 1 } {
+ puts "Core Generator create command failed."
+} elseif { $result == 3 || $result == 4 } {
+ # convert 'version check' result to real return range, bypassing any messages.
+ set result [ expr $result - 3 ]
+} else {
+ puts "Core Generator create cancelled."
+}
+exit $result
diff --git a/novena/src/rtl/ipcore/edit_clkmgr_dcm.tcl b/novena/src/rtl/ipcore/edit_clkmgr_dcm.tcl
new file mode 100644
index 0000000..4992eb1
--- /dev/null
+++ b/novena/src/rtl/ipcore/edit_clkmgr_dcm.tcl
@@ -0,0 +1,37 @@
+##
+## Core Generator Run Script, generator for Project Navigator edit command
+##
+
+proc findRtfPath { relativePath } {
+ set xilenv ""
+ if { [info exists ::env(XILINX) ] } {
+ if { [info exists ::env(MYXILINX)] } {
+ set xilenv [join [list $::env(MYXILINX) $::env(XILINX)] $::xilinx::path_sep ]
+ } else {
+ set xilenv $::env(XILINX)
+ }
+ }
+ foreach path [ split $xilenv $::xilinx::path_sep ] {
+ set fullPath [ file join $path $relativePath ]
+ if { [ file exists $fullPath ] } {
+ return $fullPath
+ }
+ }
+ return ""
+}
+
+source [ findRtfPath "data/projnav/scripts/dpm_cgUtils.tcl" ]
+
+set result [ run_cg_edit "clkmgr_dcm" xc6slx45-3csg324 Verilog ]
+
+if { $result == 0 } {
+ puts "Core Generator edit command completed successfully."
+} elseif { $result == 1 } {
+ puts "Core Generator edit command failed."
+} elseif { $result == 3 || $result == 4 } {
+ # convert 'version check' result to real return range, bypassing any messages.
+ set result [ expr $result - 3 ]
+} else {
+ puts "Core Generator edit cancelled."
+}
+exit $result
diff --git a/novena/src/rtl/novena_clkmgr.v b/novena/src/rtl/novena_clkmgr.v
new file mode 100644
index 0000000..00b2e5b
--- /dev/null
+++ b/novena/src/rtl/novena_clkmgr.v
@@ -0,0 +1,143 @@
+//======================================================================
+//
+// novena_clkmgr.v
+// ---------------
+// Clock and reset implementation for the Cryptech Novena
+// FPGA framework.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2015, 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 novena_clkmgr
+ (
+ input wire gclk_p, // signal from clock pins
+ input wire gclk_n, //
+
+ input wire reset_mcu_b, // cpu reset (async)
+
+ output wire sys_clk, // buffered system clock output
+ output wire sys_rst, // system reset output (sync)
+
+ input wire bclk_in, // signal from clock pin
+ output wire bclk_out // buffered clock output
+ );
+
+ //
+ // Ports
+ //
+
+
+ //
+ // IBUFGDS
+ //
+ (* BUFFER_TYPE="NONE" *)
+ wire gclk;
+
+ IBUFGDS IBUFGDS_gclk
+ (
+ .I(gclk_p),
+ .IB(gclk_n),
+ .O(gclk)
+ );
+
+
+ //
+ // DCM
+ //
+ wire dcm_reset; // dcm reset
+ wire dcm_locked; // output clock valid
+ wire gclk_missing; // no input clock
+
+ clkmgr_dcm dcm
+ (
+ .CLK_IN1(gclk),
+ .RESET(dcm_reset),
+ .INPUT_CLK_STOPPED(gclk_missing),
+
+ .CLK_OUT1(sys_clk),
+ .CLK_VALID(dcm_locked)
+ );
+
+
+ //
+ // DCM Reset Logic
+ //
+
+ /* DCM should be reset on power-up, when input clock is stopped or when the
+ * CPU gets reset.
+ */
+
+ reg [15: 0] dcm_rst_shreg = {16{1'b1}}; // 16-bit shift register
+
+ always @(posedge gclk or negedge reset_mcu_b or posedge gclk_missing)
+ //
+ if ((reset_mcu_b == 1'b0) || (gclk_missing == 1'b1))
+ dcm_rst_shreg <= {16{1'b1}};
+ else
+ dcm_rst_shreg <= {dcm_rst_shreg[14:0], 1'b0};
+
+ assign dcm_reset = dcm_rst_shreg[15];
+
+
+ //
+ // System Reset Logic
+ //
+
+ /* System reset is asserted for 16 cycles whenever DCM aquires lock. */
+
+ reg [15: 0] sys_rst_shreg = {16{1'b1}}; // 16-bit shift register
+
+ always @(posedge sys_clk or negedge reset_mcu_b or posedge gclk_missing or negedge dcm_locked)
+ //
+ if ((reset_mcu_b == 1'b0) || (gclk_missing == 1'b1) || (dcm_locked == 1'b0))
+ sys_rst_shreg <= {16{1'b1}};
+ else if (dcm_locked == 1'b1)
+ sys_rst_shreg <= {sys_rst_shreg[14:0], 1'b0};
+
+ assign sys_rst = sys_rst_shreg[15];
+
+
+ //
+ // BCLK BUFG
+ //
+ BUFG BUFG_BCLK
+ (
+ .I(bclk_in),
+ .O(bclk_out)
+ );
+
+
+endmodule
+
+//======================================================================
+// EOF novena_clkmgr.v
+//======================================================================
diff --git a/novena/src/rtl/novena_eim.v b/novena/src/rtl/novena_eim.v
new file mode 100644
index 0000000..8778291
--- /dev/null
+++ b/novena/src/rtl/novena_eim.v
@@ -0,0 +1,175 @@
+//======================================================================
+//
+// novena_baseline_top.v
+// ---------------------
+// Top module for the Cryptech Novena FPGA framework. This design
+// allow us to run the EIM interface at one clock and cores including
+// core selector with the always present global clock.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2015, 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 novena_baseline_top
+ (
+ // Differential input for 50 MHz general clock.
+ input wire gclk_p_pin,
+ input wire gclk_n_pin,
+
+ // Reset controlled by the CPU.
+ // this must be configured as input w/pullup
+ input wire reset_mcu_b_pin,
+
+ // Cryptech avalanche noise board input and LED outputs
+ input wire ct_noise,
+ output wire [7 : 0] ct_led,
+
+ // EIM interface
+ input wire eim_bclk, // EIM burst clock. Started by the CPU.
+ input wire eim_cs0_n, // Chip select (active low).
+ inout wire [15 : 0] eim_da, // Bidirectional address and data port.
+ input wire [18: 16] eim_a, // MSB part of address port.
+ input wire eim_lba_n, // Latch address signal (active low).
+ input wire eim_wr_n, // write enable signal (active low).
+ input wire eim_oe_n, // output enable signal (active low).
+ output wire eim_wait_n, // Data wait signal (active low).
+
+ // Novena utility ports
+ output wire apoptosis_pin, // Hold low to not restart after config.
+ output wire led_pin // LED on edge close to the FPGA.
+ );
+
+
+ //----------------------------------------------------------------
+ // Clock Manager
+ //
+ // Clock manager is used to buffer BCLK, generate SYS_CLK
+ // from GCLK and implement the reset logic.
+ //----------------------------------------------------------------
+ wire sys_clk;
+ wire sys_rst;
+ wire eim_bclk_buf;
+
+ novena_clkmgr clkmgr
+ (
+ .gclk_p(gclk_p_pin),
+ .gclk_n(gclk_n_pin),
+
+ .reset_mcu_b(reset_mcu_b_pin),
+
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .bclk_in(eim_bclk),
+ .bclk_out(eim_bclk_buf)
+ );
+
+
+ //----------------------------------------------------------------
+ // EIM Interface
+ //
+ // EIM subsystem handles all data transfer to/from CPU via EIM bus.
+ //----------------------------------------------------------------
+ wire [16: 0] sys_eim_addr;
+ wire sys_eim_wr;
+ wire sys_eim_rd;
+ wire [31: 0] sys_eim_dout;
+ wire [31: 0] sys_eim_din;
+
+ eim eim
+ (
+ .eim_bclk(eim_bclk_buf),
+ .eim_cs0_n(eim_cs0_n),
+ .eim_da(eim_da),
+ .eim_a(eim_a),
+ .eim_lba_n(eim_lba_n),
+ .eim_wr_n(eim_wr_n),
+ .eim_oe_n(eim_oe_n),
+ .eim_wait_n(eim_wait_n),
+
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .sys_eim_addr(sys_eim_addr),
+ .sys_eim_wr(sys_eim_wr),
+ .sys_eim_rd(sys_eim_rd),
+ .sys_eim_dout(sys_eim_dout),
+ .sys_eim_din(sys_eim_din),
+
+ .led_pin(led_pin)
+ );
+
+
+ //----------------------------------------------------------------
+ // Core Selector
+ //
+ // This multiplexer is used to map different types of cores, such as
+ // hashes, RNGs and ciphers to different regions (segments) of memory.
+ //----------------------------------------------------------------
+ core_selector cores
+ (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .sys_eim_addr(sys_eim_addr),
+ .sys_eim_wr(sys_eim_wr),
+ .sys_eim_rd(sys_eim_rd),
+
+ .sys_write_data(sys_eim_dout),
+ .sys_read_data(sys_eim_din)
+ );
+
+
+ //----------------------------------------------------------------
+ // Cryptech Logic
+ //
+ // Logic specific to the Cryptech use of the Novena.
+ // Currently we just hard wire the LED outputs.
+ //----------------------------------------------------------------
+ assign ct_led = {8{ct_noise}};
+
+
+ //----------------------------------------------------------------
+ // Novena Patch
+ //
+ // Patch logic to keep the Novena board happy.
+ // The apoptosis_pin pin must be kept low or the whole board
+ // (more exactly the CPU) will be reset after the FPGA has
+ // been configured.
+ //----------------------------------------------------------------
+ assign apoptosis_pin = 1'b0;
+
+
+endmodule
+
+//======================================================================
+// EOF novena_baseline_top.v
+//======================================================================
diff --git a/novena/src/rtl/novena_i2c.v b/novena/src/rtl/novena_i2c.v
new file mode 100644
index 0000000..23ce3d2
--- /dev/null
+++ b/novena/src/rtl/novena_i2c.v
@@ -0,0 +1,218 @@
+//======================================================================
+//
+// novena_baseline_top.v
+// ---------------------
+// Top module for the Cryptech Novena FPGA framework. This design
+// allow us to run the EIM interface at one clock and cores including
+// core selector with the always present global clock.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2015, 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 novena_baseline_top
+ (
+ // Differential input for 50 MHz general clock.
+ input wire gclk_p_pin,
+ input wire gclk_n_pin,
+
+ // Reset controlled by the CPU.
+ // this must be configured as input w/pullup
+ input wire reset_mcu_b_pin,
+
+ // Cryptech avalanche noise board input and LED outputs
+ input wire ct_noise,
+ output wire [7 : 0] ct_led,
+
+ // I2C interface
+ input wire i2c_scl,
+ inout wire i2c_sda,
+
+ // Novena utility ports
+ output wire apoptosis_pin, // Hold low to not restart after config.
+ output wire led_pin // LED on edge close to the FPGA.
+ );
+
+
+ //----------------------------------------------------------------
+ // Clock Manager
+ //
+ // Clock manager is used to buffer BCLK, generate SYS_CLK
+ // from GCLK and implement the reset logic.
+ //----------------------------------------------------------------
+ wire sys_clk;
+ wire sys_rst = 0;
+
+ IBUFGDS clkibufgds(
+ .I(gclk_p_pin),
+ .IB(gclk_n_pin),
+ .O(sys_clk)
+ );
+
+
+ //----------------------------------------------------------------
+ // I2C Interface
+ //
+ // I2C subsystem handles all data transfer to/from CPU via I2C bus.
+ //----------------------------------------------------------------
+ parameter I2C_DEVICE_ADDR = 7'h0f;
+
+ wire [16: 0] sys_eim_addr;
+ wire sys_eim_wr;
+ wire sys_eim_rd;
+
+ wire sda_pd;
+ wire sda_int;
+
+ wire clk = sys_clk;
+ wire reset_n = ~sys_rst;
+
+ // Coretest connections.
+ wire coretest_reset_n;
+ wire coretest_cs;
+ wire coretest_we;
+ wire [15 : 0] coretest_address;
+ wire [31 : 0] coretest_write_data;
+ wire [31 : 0] coretest_read_data;
+
+ // I2C connections
+ wire [6:0] i2c_device_addr;
+ wire i2c_rxd_syn;
+ wire [7 : 0] i2c_rxd_data;
+ wire i2c_rxd_ack;
+ wire i2c_txd_syn;
+ wire [7 : 0] i2c_txd_data;
+ wire i2c_txd_ack;
+
+ IOBUF #(.DRIVE(8), .SLEW("SLOW"))
+ IOBUF_sda (
+ .IO(i2c_sda),
+ .I(1'b0),
+ .T(!sda_pd),
+ .O(sda_int)
+ );
+
+ i2c_core i2c_core
+ (
+ .clk(clk),
+ .reset(sys_rst),
+
+ // External data interface
+ .SCL(i2c_scl),
+ .SDA(sda_int),
+ .SDA_pd(sda_pd),
+ .i2c_device_addr(i2c_device_addr),
+
+ // Internal receive interface.
+ .rxd_syn(i2c_rxd_syn),
+ .rxd_data(i2c_rxd_data),
+ .rxd_ack(i2c_rxd_ack),
+
+ // Internal transmit interface.
+ .txd_syn(i2c_txd_syn),
+ .txd_data(i2c_txd_data),
+ .txd_ack(i2c_txd_ack)
+ );
+
+ coretest coretest
+ (
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .rx_syn(i2c_rxd_syn),
+ .rx_data(i2c_rxd_data),
+ .rx_ack(i2c_rxd_ack),
+
+ .tx_syn(i2c_txd_syn),
+ .tx_data(i2c_txd_data),
+ .tx_ack(i2c_txd_ack),
+
+ // Interface to the core being tested.
+ .core_reset_n(coretest_reset_n),
+ .core_cs(coretest_cs),
+ .core_we(coretest_we),
+ .core_address(coretest_address),
+ .core_write_data(coretest_write_data),
+ .core_read_data(coretest_read_data)
+ );
+
+ wire select = (i2c_device_addr == I2C_DEVICE_ADDR);
+ assign sys_eim_addr = { coretest_address[15:13], 1'b0, coretest_address[12:0] };
+ assign sys_eim_wr = select & coretest_cs & coretest_we;
+ assign sys_eim_rd = select & coretest_cs & ~coretest_we;
+
+
+ //----------------------------------------------------------------
+ // Core Selector
+ //
+ // This multiplexer is used to map different types of cores, such as
+ // hashes, RNGs and ciphers to different regions (segments) of memory.
+ //----------------------------------------------------------------
+ core_selector cores
+ (
+ .sys_clk(clk),
+ .sys_rst(sys_rst),
+
+ .sys_eim_addr(sys_eim_addr),
+ .sys_eim_wr(sys_eim_wr),
+ .sys_eim_rd(sys_eim_rd),
+
+ .sys_write_data(coretest_write_data),
+ .sys_read_data(coretest_read_data)
+ );
+
+
+ //----------------------------------------------------------------
+ // Cryptech Logic
+ //
+ // Logic specific to the Cryptech use of the Novena.
+ // Currently we just hard wire the LED outputs.
+ //----------------------------------------------------------------
+ assign ct_led = {8{ct_noise}};
+
+
+ //----------------------------------------------------------------
+ // Novena Patch
+ //
+ // Patch logic to keep the Novena board happy.
+ // The apoptosis_pin pin must be kept low or the whole board
+ // (more exactly the CPU) will be reset after the FPGA has
+ // been configured.
+ //----------------------------------------------------------------
+ assign apoptosis_pin = 1'b0;
+
+ assign led_pin = 1'b1;
+
+endmodule
+
+//======================================================================
+// EOF novena_baseline_top.v
+//======================================================================
diff --git a/novena/src/rtl/novena_regs.v b/novena/src/rtl/novena_regs.v
new file mode 100644
index 0000000..7341092
--- /dev/null
+++ b/novena/src/rtl/novena_regs.v
@@ -0,0 +1,126 @@
+//======================================================================
+//
+// novena_regs.v
+// -------------
+// Global registers for the Cryptech Novena FPGA framework.
+//
+//
+// Author: Pavel Shatov
+// Copyright (c) 2015, 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.
+//
+//======================================================================
+
+`timescale 1ns / 1ps
+
+module novena_regs
+ (
+ input wire clk,
+ input wire rst,
+
+ input wire cs,
+ input wire we,
+
+ input wire [ 7 : 0] address,
+ input wire [31 : 0] write_data,
+ output wire [31 : 0] read_data
+ );
+
+
+ //----------------------------------------------------------------
+ // Board-Level Registers
+ //----------------------------------------------------------------
+ localparam ADDR_BOARD_TYPE = 8'h00; // board id
+ localparam ADDR_FIRMWARE_VER = 8'h01; // bitstream version
+ localparam ADDR_DUMMY_REG = 8'hFF; // general-purpose register
+
+
+ //----------------------------------------------------------------
+ // Constants
+ //----------------------------------------------------------------
+ localparam NOVENA_BOARD_TYPE = 32'h50565431; // PVT1
+ localparam NOVENA_DESIGN_VER = 32'h00_01_00_0b; // v0.1.0b
+
+
+ //
+ // Output Register
+ //
+ reg [31: 0] tmp_read_data;
+ assign read_data = tmp_read_data;
+
+
+ /* This dummy register can be used by users to check that they can actually
+ * write something.
+ */
+
+ reg [31: 0] reg_dummy;
+
+
+ //
+ // Access Handler
+ //
+ always @(posedge clk)
+ //
+ if (rst)
+ reg_dummy <= {32{1'b0}};
+ else if (cs) begin
+ //
+ if (we) begin
+ //
+ // WRITE handler
+ //
+ case (address)
+ ADDR_DUMMY_REG:
+ reg_dummy <= write_data;
+ endcase
+ //
+ end else begin
+ //
+ // READ handler
+ //
+ case (address)
+ ADDR_BOARD_TYPE:
+ tmp_read_data <= NOVENA_BOARD_TYPE;
+ ADDR_FIRMWARE_VER:
+ tmp_read_data <= NOVENA_DESIGN_VER;
+ ADDR_DUMMY_REG:
+ tmp_read_data <= reg_dummy;
+ //
+ default:
+ tmp_read_data <= {32{1'b0}}; // read non-existent locations as zeroes
+ endcase
+ //
+ end
+ //
+ end
+
+endmodule
+
+//======================================================================
+// EOF novena_regs.v
+//======================================================================
diff --git a/novena/src/sw/Makefile b/novena/src/sw/Makefile
new file mode 100755
index 0000000..8580a1a
--- /dev/null
+++ b/novena/src/sw/Makefile
@@ -0,0 +1,17 @@
+all: hash_tester_eim hash_tester_i2c
+
+.c.o:
+ gcc -c -Wall -o $@ $<
+
+hash_tester_eim: hash_tester_eim.o novena-eim.o
+ gcc -o $@ $^
+
+hash_tester_eim.o: hash_tester_eim.c novena-eim.h
+
+novena-eim.o: novena-eim.c novena-eim.h
+
+hash_tester_i2c: hash_tester_i2c.c
+ gcc -o $@ $^
+
+clean:
+ rm -f *.o hash_tester_eim hash_tester_i2c
diff --git a/novena/src/sw/hash_tester_eim.c b/novena/src/sw/hash_tester_eim.c
new file mode 100644
index 0000000..a0ab0f1
--- /dev/null
+++ b/novena/src/sw/hash_tester_eim.c
@@ -0,0 +1,876 @@
+/*
+ * hash_tester.c
+ * --------------
+ * This program sends several commands to the coretest_hashes subsystem
+ * in order to verify the SHA-1, SHA-256 and SHA-512/x hash function
+ * cores.
+ *
+ * Note: This version of the program talks to the FPGA over an EIM bus.
+ *
+ * The single and dual block test cases are taken from the
+ * NIST KAT document:
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
+ *
+ *
+ * Authors: Joachim Strömbergson, Paul Selkirk
+ * Copyright (c) 2014-2015, 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include "novena-eim.h"
+
+int debug = 0;
+int quiet = 0;
+int repeat = 0;
+
+/* instead of core number 0 we have a page of global registers */
+#define ADDR_GLOBAL_BOARD_TYPE EIM_BASE_ADDR + (0x00 << 2)
+#define ADDR_GLOBAL_BITSTREAM_VER EIM_BASE_ADDR + (0x01 << 2)
+#define ADDR_GLOBAL_DUMMY_REG EIM_BASE_ADDR + (0xFF << 2)
+
+#define SEGMENT_OFFSET_HASHES EIM_BASE_ADDR + 0x000000
+#define SEGMENT_OFFSET_RNGS EIM_BASE_ADDR + 0x010000
+#define SEGMENT_OFFSET_CIPHERS EIM_BASE_ADDR + 0x020000
+
+
+/* addresses and codes common to all hash cores */
+#define ADDR_NAME0 0x00
+#define ADDR_NAME1 0x04
+#define ADDR_VERSION 0x08
+#define ADDR_CTRL 0x20
+#define CTRL_INIT_CMD 1
+#define CTRL_NEXT_CMD 2
+#define ADDR_STATUS 0x24
+#define STATUS_READY_BIT 1
+#define STATUS_VALID_BIT 2
+#define ADDR_BLOCK 0x40
+#define ADDR_DIGEST 0x80
+
+#define HASH_CORE_SIZE 0x400
+
+/* addresses and codes for the specific hash cores */
+#define SHA1_ADDR_BASE SEGMENT_OFFSET_HASHES + (1*HASH_CORE_SIZE)
+#define SHA1_ADDR_NAME0 SHA1_ADDR_BASE + ADDR_NAME0
+#define SHA1_ADDR_NAME1 SHA1_ADDR_BASE + ADDR_NAME1
+#define SHA1_ADDR_VERSION SHA1_ADDR_BASE + ADDR_VERSION
+#define SHA1_ADDR_CTRL SHA1_ADDR_BASE + ADDR_CTRL
+#define SHA1_ADDR_STATUS SHA1_ADDR_BASE + ADDR_STATUS
+#define SHA1_ADDR_BLOCK SHA1_ADDR_BASE + ADDR_BLOCK
+#define SHA1_ADDR_DIGEST SHA1_ADDR_BASE + ADDR_DIGEST
+#define SHA1_BLOCK_LEN 512 / 8
+#define SHA1_DIGEST_LEN 160 / 8
+
+#define SHA256_ADDR_BASE SEGMENT_OFFSET_HASHES + (2*HASH_CORE_SIZE)
+#define SHA256_ADDR_NAME0 SHA256_ADDR_BASE + ADDR_NAME0
+#define SHA256_ADDR_NAME1 SHA256_ADDR_BASE + ADDR_NAME1
+#define SHA256_ADDR_VERSION SHA256_ADDR_BASE + ADDR_VERSION
+#define SHA256_ADDR_CTRL SHA256_ADDR_BASE + ADDR_CTRL
+#define SHA256_ADDR_STATUS SHA256_ADDR_BASE + ADDR_STATUS
+#define SHA256_ADDR_BLOCK SHA256_ADDR_BASE + ADDR_BLOCK
+#define SHA256_ADDR_DIGEST SHA256_ADDR_BASE + ADDR_DIGEST
+#define SHA256_BLOCK_LEN 512 / 8
+#define SHA256_DIGEST_LEN 256 / 8
+
+#define SHA512_ADDR_BASE SEGMENT_OFFSET_HASHES + (3*HASH_CORE_SIZE)
+#define SHA512_ADDR_NAME0 SHA512_ADDR_BASE + ADDR_NAME0
+#define SHA512_ADDR_NAME1 SHA512_ADDR_BASE + ADDR_NAME1
+#define SHA512_ADDR_VERSION SHA512_ADDR_BASE + ADDR_VERSION
+#define SHA512_ADDR_CTRL SHA512_ADDR_BASE + ADDR_CTRL
+#define SHA512_ADDR_STATUS SHA512_ADDR_BASE + ADDR_STATUS
+#define SHA512_ADDR_BLOCK SHA512_ADDR_BASE + ADDR_BLOCK
+#define SHA512_ADDR_DIGEST SHA512_ADDR_BASE + 0x100
+#define SHA512_BLOCK_LEN 1024 / 8
+#define SHA512_224_DIGEST_LEN 224 / 8
+#define SHA512_256_DIGEST_LEN 256 / 8
+#define SHA384_DIGEST_LEN 384 / 8
+#define SHA512_DIGEST_LEN 512 / 8
+#define MODE_SHA_512_224 0 << 2
+#define MODE_SHA_512_256 1 << 2
+#define MODE_SHA_384 2 << 2
+#define MODE_SHA_512 3 << 2
+
+/* SHA-1/SHA-256 One Block Message Sample
+ Input Message: "abc" */
+const uint8_t NIST_512_SINGLE[] =
+{ 0x61, 0x62, 0x63, 0x80, 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, 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, 0x18 };
+
+const uint8_t SHA1_SINGLE_DIGEST[] =
+{ 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
+ 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
+ 0x9c, 0xd0, 0xd8, 0x9d };
+
+const uint8_t SHA256_SINGLE_DIGEST[] =
+{ 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
+ 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
+ 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
+ 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD };
+
+/* SHA-1/SHA-256 Two Block Message Sample
+ Input Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" */
+const uint8_t NIST_512_DOUBLE0[] =
+{ 0x61, 0x62, 0x63, 0x64, 0x62, 0x63, 0x64, 0x65,
+ 0x63, 0x64, 0x65, 0x66, 0x64, 0x65, 0x66, 0x67,
+ 0x65, 0x66, 0x67, 0x68, 0x66, 0x67, 0x68, 0x69,
+ 0x67, 0x68, 0x69, 0x6A, 0x68, 0x69, 0x6A, 0x6B,
+ 0x69, 0x6A, 0x6B, 0x6C, 0x6A, 0x6B, 0x6C, 0x6D,
+ 0x6B, 0x6C, 0x6D, 0x6E, 0x6C, 0x6D, 0x6E, 0x6F,
+ 0x6D, 0x6E, 0x6F, 0x70, 0x6E, 0x6F, 0x70, 0x71,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+const uint8_t NIST_512_DOUBLE1[] =
+{ 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, 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, 0x01, 0xC0 };
+
+const uint8_t SHA1_DOUBLE_DIGEST[] =
+{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
+ 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
+ 0xE5, 0x46, 0x70, 0xF1 };
+
+const uint8_t SHA256_DOUBLE_DIGEST[] =
+{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
+ 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
+ 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
+ 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 };
+
+/* SHA-512 One Block Message Sample
+ Input Message: "abc" */
+const uint8_t NIST_1024_SINGLE[] =
+{ 0x61, 0x62, 0x63, 0x80, 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, 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, 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, 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, 0x18 };
+
+const uint8_t SHA512_224_SINGLE_DIGEST[] =
+{ 0x46, 0x34, 0x27, 0x0f, 0x70, 0x7b, 0x6a, 0x54,
+ 0xda, 0xae, 0x75, 0x30, 0x46, 0x08, 0x42, 0xe2,
+ 0x0e, 0x37, 0xed, 0x26, 0x5c, 0xee, 0xe9, 0xa4,
+ 0x3e, 0x89, 0x24, 0xaa };
+const uint8_t SHA512_256_SINGLE_DIGEST[] =
+{ 0x53, 0x04, 0x8e, 0x26, 0x81, 0x94, 0x1e, 0xf9,
+ 0x9b, 0x2e, 0x29, 0xb7, 0x6b, 0x4c, 0x7d, 0xab,
+ 0xe4, 0xc2, 0xd0, 0xc6, 0x34, 0xfc, 0x6d, 0x46,
+ 0xe0, 0xe2, 0xf1, 0x31, 0x07, 0xe7, 0xaf, 0x23 };
+const uint8_t SHA384_SINGLE_DIGEST[] =
+{ 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
+ 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
+ 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
+ 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
+ 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
+ 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 };
+const uint8_t SHA512_SINGLE_DIGEST[] =
+{ 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
+ 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+ 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
+ 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+ 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
+ 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+ 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
+ 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f };
+
+/* SHA-512 Two Block Message Sample
+ Input Message: "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" */
+const uint8_t NIST_1024_DOUBLE0[] =
+{ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
+ 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
+ 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
+ 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d,
+ 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71,
+ 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
+ 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
+ 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
+ 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+const uint8_t NIST_1024_DOUBLE1[] =
+{ 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, 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, 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, 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, 0x00, 0x00, 0x03, 0x80 };
+
+const uint8_t SHA512_224_DOUBLE_DIGEST[] =
+{ 0x23, 0xfe, 0xc5, 0xbb, 0x94, 0xd6, 0x0b, 0x23,
+ 0x30, 0x81, 0x92, 0x64, 0x0b, 0x0c, 0x45, 0x33,
+ 0x35, 0xd6, 0x64, 0x73, 0x4f, 0xe4, 0x0e, 0x72,
+ 0x68, 0x67, 0x4a, 0xf9 };
+const uint8_t SHA512_256_DOUBLE_DIGEST[] =
+{ 0x39, 0x28, 0xe1, 0x84, 0xfb, 0x86, 0x90, 0xf8,
+ 0x40, 0xda, 0x39, 0x88, 0x12, 0x1d, 0x31, 0xbe,
+ 0x65, 0xcb, 0x9d, 0x3e, 0xf8, 0x3e, 0xe6, 0x14,
+ 0x6f, 0xea, 0xc8, 0x61, 0xe1, 0x9b, 0x56, 0x3a };
+const uint8_t SHA384_DOUBLE_DIGEST[] =
+{ 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
+ 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
+ 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
+ 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
+ 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
+ 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 };
+const uint8_t SHA512_DOUBLE_DIGEST[] =
+{ 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
+ 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
+ 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
+ 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
+ 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
+ 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
+ 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
+ 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 };
+
+/* ---------------- test-case low-level code ---------------- */
+
+void dump(char *label, const uint8_t *buf, int len)
+{
+ if (debug) {
+ int i;
+ printf("%s [", label);
+ for (i = 0; i < len; ++i)
+ printf(" %02x", buf[i]);
+ printf(" ]\n");
+ }
+}
+
+int tc_write(off_t offset, const uint8_t *buf, int len)
+{
+ dump("write ", buf, len);
+
+ for (; len > 0; offset += 4, buf += 4, len -= 4) {
+ uint32_t val;
+ val = htonl(*(uint32_t *)buf);
+ eim_write_32(offset, &val);
+ }
+
+ return 0;
+}
+
+int tc_read(off_t offset, uint8_t *buf, int len)
+{
+ uint8_t *rbuf = buf;
+ int rlen = len;
+
+ for (; rlen > 0; offset += 4, rbuf += 4, rlen -= 4) {
+ uint32_t val;
+ eim_read_32(offset, &val);
+ *(uint32_t *)rbuf = ntohl(val);
+ }
+
+ dump("read ", buf, len);
+
+ return 0;
+}
+
+int tc_expected(off_t offset, const uint8_t *expected, int len)
+{
+ uint8_t *buf;
+ int i;
+
+ buf = malloc(len);
+ if (buf == NULL) {
+ perror("malloc");
+ return 1;
+ }
+ dump("expect", expected, len);
+
+ if (tc_read(offset, buf, len) != 0)
+ goto errout;
+
+ for (i = 0; i < len; ++i)
+ if (buf[i] != expected[i]) {
+ fprintf(stderr, "response byte %d: expected 0x%02x, got 0x%02x\n",
+ i, expected[i], buf[i]);
+ goto errout;
+ }
+
+ free(buf);
+ return 0;
+errout:
+ free(buf);
+ return 1;
+}
+
+int tc_init(off_t offset)
+{
+ uint8_t buf[4] = { 0, 0, 0, CTRL_INIT_CMD };
+
+ return tc_write(offset, buf, 4);
+}
+
+int tc_next(off_t offset)
+{
+ uint8_t buf[4] = { 0, 0, 0, CTRL_NEXT_CMD };
+
+ return tc_write(offset, buf, 4);
+}
+
+int tc_wait(off_t offset, uint8_t status)
+{
+ uint8_t buf[4];
+
+#if 0
+ do {
+ if (tc_read(offset, buf, 4) != 0)
+ return 1;
+ } while (!(buf[3] & status));
+
+ return 0;
+#else
+ int i;
+ for (i = 0; i < 10; ++i) {
+ if (tc_read(offset, buf, 4) != 0)
+ return 1;
+ if (buf[3] & status)
+ return 0;
+ }
+ fprintf(stderr, "tc_wait timed out\n");
+ return 1;
+#endif
+}
+
+int tc_wait_ready(off_t offset)
+{
+ return tc_wait(offset, STATUS_READY_BIT);
+}
+
+int tc_wait_valid(off_t offset)
+{
+ return tc_wait(offset, STATUS_VALID_BIT);
+}
+
+/* ---------------- sanity test case ---------------- */
+
+int TC0()
+{
+ uint8_t board_type[4] = { 'P', 'V', 'T', '1'}; /* "PVT1" */
+ uint8_t bitstream_ver[4] = { 0x00, 0x01, 0x00, 0x0B }; /* v0.1.0b */
+ uint8_t t[4];
+
+ uint8_t seg_rngs_reg_first[4] = { 0xAA, 0xAA, 0xAA, 0xAA};
+ uint8_t seg_rngs_reg_second[4] = { 0xBB, 0xBB, 0xBB, 0xBB};
+ uint8_t seg_rngs_reg_third[4] = { 0xCC, 0xCC, 0xCC, 0xCC};
+
+ uint8_t seg_ciphers_reg_first[4] = { 0xDD, 0xDD, 0xDD, 0xDD};
+ uint8_t seg_ciphers_reg_second[4] = { 0xEE, 0xEE, 0xEE, 0xEE};
+ uint8_t seg_ciphers_reg_third[4] = { 0xFF, 0xFF, 0xFF, 0xFF};
+
+ if (!quiet)
+ printf("TC0: Reading board type, version, and dummy reg from global registers.\n");
+
+ /* write current time into dummy register, then try to read it back
+ * to make sure that we can actually write something into EIM
+ */
+ (void)time((time_t *)t);
+ tc_write(ADDR_GLOBAL_DUMMY_REG, (void *)&t, 4);
+
+ return
+ tc_expected(ADDR_GLOBAL_BOARD_TYPE, board_type, 4) ||
+ tc_expected(ADDR_GLOBAL_BITSTREAM_VER, bitstream_ver, 4) ||
+ tc_expected(ADDR_GLOBAL_DUMMY_REG, (void *)t, 4) ||
+
+ tc_expected(SEGMENT_OFFSET_RNGS + (0 << 2), seg_rngs_reg_first, 4) ||
+ tc_expected(SEGMENT_OFFSET_RNGS + (1 << 2), seg_rngs_reg_second, 4) ||
+ tc_expected(SEGMENT_OFFSET_RNGS + (2 << 2), seg_rngs_reg_third, 4) ||
+
+ tc_expected(SEGMENT_OFFSET_CIPHERS + (0 << 2), seg_ciphers_reg_first, 4) ||
+ tc_expected(SEGMENT_OFFSET_CIPHERS + (1 << 2), seg_ciphers_reg_second, 4) ||
+ tc_expected(SEGMENT_OFFSET_CIPHERS + (2 << 2), seg_ciphers_reg_third, 4);
+}
+
+/* ---------------- SHA-1 test cases ---------------- */
+
+/* TC1: Read name and version from SHA-1 core. */
+int TC1(void)
+{
+ uint8_t name0[4] = { 0x73, 0x68, 0x61, 0x31 }; /* "sha1" */
+ uint8_t name1[4] = { 0x20, 0x20, 0x20, 0x20 }; /* " " */
+ uint8_t version[4] = { 0x30, 0x2e, 0x35, 0x30 }; /* "0.50" */
+
+ if (!quiet)
+ printf("TC1: Reading name, type and version words from SHA-1 core.\n");
+
+ return
+ tc_expected(SHA1_ADDR_NAME0, name0, 4) ||
+ tc_expected(SHA1_ADDR_NAME1, name1, 4) ||
+ tc_expected(SHA1_ADDR_VERSION, version, 4);
+}
+
+/* TC2: SHA-1 Single block message test as specified by NIST. */
+int TC2(void)
+{
+ const uint8_t *block = NIST_512_SINGLE;
+ const uint8_t *expected = SHA1_SINGLE_DIGEST;
+ int ret;
+
+ if (!quiet)
+ printf("TC2: Single block message test for SHA-1.\n");
+
+ /* Write block to SHA-1. */
+ tc_write(SHA1_ADDR_BLOCK, block, SHA1_BLOCK_LEN);
+ /* Start initial block hashing, wait and check status. */
+ tc_init(SHA1_ADDR_CTRL);
+ tc_wait_valid(SHA1_ADDR_STATUS);
+ /* Extract the digest. */
+ ret = tc_expected(SHA1_ADDR_DIGEST, expected, SHA1_DIGEST_LEN);
+ return ret;
+}
+
+/* TC3: SHA-1 Double block message test as specified by NIST. */
+int TC3(void)
+{
+ const uint8_t *block[2] = { NIST_512_DOUBLE0, NIST_512_DOUBLE1 };
+ static const uint8_t block0_expected[] =
+ { 0xF4, 0x28, 0x68, 0x18, 0xC3, 0x7B, 0x27, 0xAE,
+ 0x04, 0x08, 0xF5, 0x81, 0x84, 0x67, 0x71, 0x48,
+ 0x4A, 0x56, 0x65, 0x72 };
+ const uint8_t *expected = SHA1_DOUBLE_DIGEST;
+ int ret;
+
+ if (!quiet)
+ printf("TC3: Double block message test for SHA-1.\n");
+
+ /* Write first block to SHA-1. */
+ tc_write(SHA1_ADDR_BLOCK, block[0], SHA1_BLOCK_LEN);
+ /* Start initial block hashing, wait and check status. */
+ tc_init(SHA1_ADDR_CTRL);
+ tc_wait_valid(SHA1_ADDR_STATUS);
+ /* Extract the first digest. */
+ tc_expected(SHA1_ADDR_DIGEST, block0_expected, SHA1_DIGEST_LEN);
+ /* Write second block to SHA-1. */
+ tc_write(SHA1_ADDR_BLOCK, block[1], SHA1_BLOCK_LEN);
+ /* Start next block hashing, wait and check status. */
+ tc_next(SHA1_ADDR_CTRL);
+ tc_wait_valid(SHA1_ADDR_STATUS);
+ /* Extract the second digest. */
+ ret = tc_expected(SHA1_ADDR_DIGEST, expected, SHA1_DIGEST_LEN);
+ return ret;
+}
+
+/* ---------------- SHA-256 test cases ---------------- */
+
+/* TC4: Read name and version from SHA-256 core. */
+int TC4(void)
+{
+ uint8_t name0[4] = { 0x73, 0x68, 0x61, 0x32 }; /* "sha2" */
+ uint8_t name1[4] = { 0x2d, 0x32, 0x35, 0x36 }; /* "-256" */
+ uint8_t version[4] = { 0x30, 0x2e, 0x38, 0x30 }; /* "0.80" */
+
+ if (!quiet)
+ printf("TC4: Reading name, type and version words from SHA-256 core.\n");
+
+ return
+ tc_expected(SHA256_ADDR_NAME0, name0, 4) ||
+ tc_expected(SHA256_ADDR_NAME1, name1, 4) ||
+ tc_expected(SHA256_ADDR_VERSION, version, 4);
+}
+
+/* TC5: SHA-256 Single block message test as specified by NIST. */
+int TC5()
+{
+ const uint8_t *block = NIST_512_SINGLE;
+ const uint8_t *expected = SHA256_SINGLE_DIGEST;
+
+ if (!quiet)
+ printf("TC5: Single block message test for SHA-256.\n");
+
+ return
+ /* Write block to SHA-256. */
+ tc_write(SHA256_ADDR_BLOCK, block, SHA256_BLOCK_LEN) ||
+ /* Start initial block hashing, wait and check status. */
+ tc_init(SHA256_ADDR_CTRL) ||
+ tc_wait_valid(SHA256_ADDR_STATUS) ||
+ /* Extract the digest. */
+ tc_expected(SHA256_ADDR_DIGEST, expected, SHA256_DIGEST_LEN);
+}
+
+/* TC6: SHA-256 Double block message test as specified by NIST. */
+int TC6()
+{
+ const uint8_t *block[2] = { NIST_512_DOUBLE0, NIST_512_DOUBLE1 };
+ static const uint8_t block0_expected[] =
+ { 0x85, 0xE6, 0x55, 0xD6, 0x41, 0x7A, 0x17, 0x95,
+ 0x33, 0x63, 0x37, 0x6A, 0x62, 0x4C, 0xDE, 0x5C,
+ 0x76, 0xE0, 0x95, 0x89, 0xCA, 0xC5, 0xF8, 0x11,
+ 0xCC, 0x4B, 0x32, 0xC1, 0xF2, 0x0E, 0x53, 0x3A };
+ const uint8_t *expected = SHA256_DOUBLE_DIGEST;
+
+ if (!quiet)
+ printf("TC6: Double block message test for SHA-256.\n");
+
+ return
+ /* Write first block to SHA-256. */
+ tc_write(SHA256_ADDR_BLOCK, block[0], SHA256_BLOCK_LEN) ||
+ /* Start initial block hashing, wait and check status. */
+ tc_init(SHA256_ADDR_CTRL) ||
+ tc_wait_valid(SHA256_ADDR_STATUS) ||
+ /* Extract the first digest. */
+ tc_expected(SHA256_ADDR_DIGEST, block0_expected, SHA256_DIGEST_LEN) ||
+ /* Write second block to SHA-256. */
+ tc_write(SHA256_ADDR_BLOCK, block[1], SHA256_BLOCK_LEN) ||
+ /* Start next block hashing, wait and check status. */
+ tc_next(SHA256_ADDR_CTRL) ||
+ tc_wait_valid(SHA256_ADDR_STATUS) ||
+ /* Extract the second digest. */
+ tc_expected(SHA256_ADDR_DIGEST, expected, SHA256_DIGEST_LEN);
+}
+
+/* TC7: SHA-256 Huge message test. */
+int TC7()
+{
+ static const uint8_t block[] =
+ { 0xaa, 0x55, 0xaa, 0x55, 0xde, 0xad, 0xbe, 0xef,
+ 0x55, 0xaa, 0x55, 0xaa, 0xf0, 0x0f, 0xf0, 0x0f,
+ 0xaa, 0x55, 0xaa, 0x55, 0xde, 0xad, 0xbe, 0xef,
+ 0x55, 0xaa, 0x55, 0xaa, 0xf0, 0x0f, 0xf0, 0x0f,
+ 0xaa, 0x55, 0xaa, 0x55, 0xde, 0xad, 0xbe, 0xef,
+ 0x55, 0xaa, 0x55, 0xaa, 0xf0, 0x0f, 0xf0, 0x0f,
+ 0xaa, 0x55, 0xaa, 0x55, 0xde, 0xad, 0xbe, 0xef,
+ 0x55, 0xaa, 0x55, 0xaa, 0xf0, 0x0f, 0xf0, 0x0f };
+
+ /* final digest after 1000 iterations */
+ static const uint8_t expected[] =
+ { 0x76, 0x38, 0xf3, 0xbc, 0x50, 0x0d, 0xd1, 0xa6,
+ 0x58, 0x6d, 0xd4, 0xd0, 0x1a, 0x15, 0x51, 0xaf,
+ 0xd8, 0x21, 0xd2, 0x35, 0x2f, 0x91, 0x9e, 0x28,
+ 0xd5, 0x84, 0x2f, 0xab, 0x03, 0xa4, 0x0f, 0x2a };
+
+ int i, n = 1000;
+
+ if (!quiet)
+ printf("TC7: Message with %d blocks test for SHA-256.\n", n);
+
+ /* Write block data to SHA-256. */
+ if (tc_write(SHA256_ADDR_BLOCK, block, SHA256_BLOCK_LEN))
+ return 1;
+
+ /* Start initial block hashing, wait and check status. */
+ if (tc_init(SHA256_ADDR_CTRL) ||
+ tc_wait_ready(SHA256_ADDR_STATUS))
+ return 1;
+
+ /* First block done. Do the rest. */
+ for (i = 1; i < n; ++i) {
+ /* Start next block hashing, wait and check status. */
+ if (tc_next(SHA256_ADDR_CTRL) ||
+ tc_wait_ready(SHA256_ADDR_STATUS))
+ return 1;
+ }
+
+ /* XXX valid is probably set at the same time as ready */
+ if (tc_wait_valid(SHA256_ADDR_STATUS))
+ return 1;
+ /* Extract the final digest. */
+ return tc_expected(SHA256_ADDR_DIGEST, expected, SHA256_DIGEST_LEN);
+}
+
+/* ---------------- SHA-512 test cases ---------------- */
+
+/* TC8: Read name and version from SHA-512 core. */
+int TC8()
+{
+ uint8_t name0[4] = { 0x73, 0x68, 0x61, 0x32 }; /* "sha2" */
+ uint8_t name1[4] = { 0x2d, 0x35, 0x31, 0x32 }; /* "-512" */
+ uint8_t version[4] = { 0x30, 0x2e, 0x38, 0x30 }; /* "0.80" */
+
+ if (!quiet)
+ printf("TC8: Reading name, type and version words from SHA-512 core.\n");
+
+ return
+ tc_expected(SHA512_ADDR_NAME0, name0, 4) ||
+ tc_expected(SHA512_ADDR_NAME1, name1, 4) ||
+ tc_expected(SHA512_ADDR_VERSION, version, 4);
+}
+
+/* TC9: SHA-512 Single block message test as specified by NIST.
+ We do this for all modes. */
+int tc9(int mode, const uint8_t *expected, int digest_len)
+{
+ const uint8_t *block = NIST_1024_SINGLE;
+ uint8_t init[4] = { 0, 0, 0, CTRL_INIT_CMD + mode };
+
+ return
+ /* Write block to SHA-512. */
+ tc_write(SHA512_ADDR_BLOCK, block, SHA512_BLOCK_LEN) ||
+ /* Start initial block hashing, wait and check status. */
+ tc_write(SHA512_ADDR_CTRL, init, 4) ||
+ tc_wait_valid(SHA512_ADDR_STATUS) ||
+ /* Extract the digest. */
+ tc_expected(SHA512_ADDR_DIGEST, expected, digest_len);
+}
+
+int TC9()
+{
+ if (!quiet)
+ printf("TC9-1: Single block message test for SHA-512/224.\n");
+ if (tc9(MODE_SHA_512_224, SHA512_224_SINGLE_DIGEST, SHA512_224_DIGEST_LEN) != 0)
+ return 1;
+
+ if (!quiet)
+ printf("TC9-2: Single block message test for SHA-512/256.\n");
+ if (tc9(MODE_SHA_512_256, SHA512_256_SINGLE_DIGEST, SHA512_256_DIGEST_LEN) != 0)
+ return 1;
+
+ if (!quiet)
+ printf("TC9-3: Single block message test for SHA-384.\n");
+ if (tc9(MODE_SHA_384, SHA384_SINGLE_DIGEST, SHA384_DIGEST_LEN) != 0)
+ return 1;
+
+ if (!quiet)
+ printf("TC9-4: Single block message test for SHA-512.\n");
+ if (tc9(MODE_SHA_512, SHA512_SINGLE_DIGEST, SHA512_DIGEST_LEN) != 0)
+ return 1;
+
+ return 0;
+}
+
+/* TC10: SHA-512 Double block message test as specified by NIST.
+ We do this for all modes. */
+int tc10(int mode, const uint8_t *expected, int digest_len)
+{
+ const uint8_t *block[2] = { NIST_1024_DOUBLE0, NIST_1024_DOUBLE1 };
+ uint8_t init[4] = { 0, 0, 0, CTRL_INIT_CMD + mode };
+ uint8_t next[4] = { 0, 0, 0, CTRL_NEXT_CMD + mode };
+
+ return
+ /* Write first block to SHA-512. */
+ tc_write(SHA512_ADDR_BLOCK, block[0], SHA512_BLOCK_LEN) ||
+ /* Start initial block hashing, wait and check status. */
+ tc_write(SHA512_ADDR_CTRL, init, 4) ||
+ tc_wait_ready(SHA512_ADDR_STATUS) ||
+ /* Write second block to SHA-512. */
+ tc_write(SHA512_ADDR_BLOCK, block[1], SHA512_BLOCK_LEN) ||
+ /* Start next block hashing, wait and check status. */
+ tc_write(SHA512_ADDR_CTRL, next, 4) ||
+ tc_wait_valid(SHA512_ADDR_STATUS) ||
+ /* Extract the digest. */
+ tc_expected(SHA512_ADDR_DIGEST, expected, digest_len);
+}
+
+int TC10()
+{
+ if (!quiet)
+ printf("TC10-1: Double block message test for SHA-512/224.\n");
+ if (tc10(MODE_SHA_512_224, SHA512_224_DOUBLE_DIGEST, SHA512_224_DIGEST_LEN) != 0)
+ return 1;
+
+ if (!quiet)
+ printf("TC10-2: Double block message test for SHA-512/256.\n");
+ if (tc10(MODE_SHA_512_256, SHA512_256_DOUBLE_DIGEST, SHA512_256_DIGEST_LEN) != 0)
+ return 1;
+
+ if (!quiet)
+ printf("TC10-3: Double block message test for SHA-384.\n");
+ if (tc10(MODE_SHA_384, SHA384_DOUBLE_DIGEST, SHA384_DIGEST_LEN) != 0)
+ return 1;
+
+ if (!quiet)
+ printf("TC10-4: Double block message test for SHA-512.\n");
+ if (tc10(MODE_SHA_512, SHA512_DOUBLE_DIGEST, SHA512_DIGEST_LEN) != 0)
+ return 1;
+
+ return 0;
+}
+
+/* ---------------- main ---------------- */
+
+/* signal handler for ctrl-c to end repeat testing */
+unsigned long iter = 0;
+struct timeval tv_start, tv_end;
+void sighandler(int unused)
+{
+ double tv_diff;
+
+ gettimeofday(&tv_end, NULL);
+ tv_diff = (double)(tv_end.tv_sec - tv_start.tv_sec) +
+ (double)(tv_end.tv_usec - tv_start.tv_usec)/1000000;
+ printf("\n%lu iterations in %.3f seconds (%.3f iterations/sec)\n",
+ iter, tv_diff, (double)iter/tv_diff);
+ exit(EXIT_SUCCESS);
+}
+
+int main(int argc, char *argv[])
+{
+ typedef int (*tcfp)(void);
+ tcfp all_tests[] = { TC0, TC1, TC2, TC3, TC4, TC5, TC6, TC7, TC8, TC9, TC10 };
+ tcfp sha1_tests[] = { TC1, TC2, TC3 };
+ tcfp sha256_tests[] = { TC4, TC5, TC6, TC7 };
+ tcfp sha512_tests[] = { TC8, TC9, TC10 };
+
+ char *usage = "Usage: %s [-h] [-d] [-q] [-r] tc...\n";
+ int i, j, opt;
+
+ while ((opt = getopt(argc, argv, "h?dqr")) != -1) {
+ switch (opt) {
+ case 'h':
+ case '?':
+ printf(usage, argv[0]);
+ return EXIT_SUCCESS;
+ case 'd':
+ debug = 1;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 'r':
+ repeat = 1;
+ break;
+ default:
+ fprintf(stderr, usage, argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* set up EIM */
+ if (eim_setup() != 0) {
+ fprintf(stderr, "EIM setup failed\n");
+ return EXIT_FAILURE;
+ }
+
+ /* repeat one test until interrupted */
+ if (repeat) {
+ tcfp tc;
+ if (optind != argc - 1) {
+ fprintf(stderr, "only one test case can be repeated\n");
+ return EXIT_FAILURE;
+ }
+ j = atoi(argv[optind]);
+ if (j < 0 || j >= sizeof(all_tests)/sizeof(all_tests[0])) {
+ fprintf(stderr, "invalid test number %s\n", argv[optind]);
+ return EXIT_FAILURE;
+ }
+ tc = (all_tests[j]);
+ srand(time(NULL));
+ signal(SIGINT, sighandler);
+ gettimeofday(&tv_start, NULL);
+ while (1) {
+ ++iter;
+ if ((iter & 0xffff) == 0) {
+ printf(".");
+ fflush(stdout);
+ }
+ if (tc() != 0)
+ sighandler(0);
+ }
+ return EXIT_SUCCESS; /*NOTREACHED*/
+ }
+
+ /* no args == run all tests */
+ if (optind >= argc) {
+ for (j = 0; j < sizeof(all_tests)/sizeof(all_tests[0]); ++j)
+ if (all_tests[j]() != 0)
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+ }
+
+ /* run one or more tests (by number) or groups of tests (by name) */
+ for (i = optind; i < argc; ++i) {
+ if (strcmp(argv[i], "all") == 0) {
+ for (j = 0; j < sizeof(all_tests)/sizeof(all_tests[0]); ++j)
+ if (all_tests[j]() != 0)
+ return EXIT_FAILURE;
+ }
+ else if (strcmp(argv[i], "sha1") == 0) {
+ for (j = 0; j < sizeof(sha1_tests)/sizeof(sha1_tests[0]); ++j)
+ if (sha1_tests[j]() != 0)
+ return EXIT_FAILURE;
+ }
+ else if (strcmp(argv[i], "sha256") == 0) {
+ for (j = 0; j < sizeof(sha256_tests)/sizeof(sha256_tests[0]); ++j)
+ if (sha256_tests[j]() != 0)
+ return EXIT_FAILURE;
+ }
+ else if (strcmp(argv[i], "sha512") == 0) {
+ for (j = 0; j < sizeof(sha512_tests)/sizeof(sha512_tests[0]); ++j)
+ if (sha512_tests[j]() != 0)
+ return EXIT_FAILURE;
+ }
+ else if (isdigit(argv[i][0]) &&
+ (((j = atoi(argv[i])) >= 0) &&
+ (j < sizeof(all_tests)/sizeof(all_tests[0])))) {
+ if (all_tests[j]() != 0)
+ return EXIT_FAILURE;
+ }
+ else {
+ fprintf(stderr, "unknown test case %s\n", argv[i]);
+ return EXIT_FAILURE;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/novena/src/sw/hash_tester_i2c.c b/novena/src/sw/hash_tester_i2c.c
new file mode 100644
index 0000000..70b98c2
--- /dev/null
+++ b/novena/src/sw/hash_tester_i2c.c
@@ -0,0 +1,1013 @@
+/*
+ * hash_tester.c
+ * --------------
+ * This program sends several commands to the coretest_hashes subsystem
+ * in order to verify the SHA-1, SHA-256 and SHA-512/x hash function
+ * cores.
+ *
+ * Note: This version of the program talks to the FPGA over an I2C bus.
+ *
+ * The single and dual block test cases are taken from the
+ * NIST KAT document:
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
+ *
+ *
+ * Authors: Joachim Strömbergson, Paul Selkirk
+ * Copyright (c) 2014, SUNET
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <linux/i2c-dev.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+/* I2C configuration */
+#define I2C_dev "/dev/i2c-2"
+#define I2C_addr 0x0f
+
+/* command codes */
+#define SOC 0x55
+#define EOC 0xaa
+#define READ_CMD 0x10
+#define WRITE_CMD 0x11
+#define RESET_CMD 0x01
+
+/* response codes */
+#define SOR 0xaa
+#define EOR 0x55
+#define READ_OK 0x7f
+#define WRITE_OK 0x7e
+#define RESET_OK 0x7d
+#define UNKNOWN 0xfe
+#define ERROR 0xfd
+
+/* instead of core number 0 we have a page of global registers */
+#define GLOBAL_ADDR_PREFIX 0x00
+#define ADDR_GLOBAL_BOARD_TYPE 0x00
+#define ADDR_GLOBAL_BITSTREAM_VER 0x01
+#define ADDR_GLOBAL_DUMMY_REG 0xff
+
+#define SEGMENT_OFFSET_HASHES 0x00
+#define SEGMENT_OFFSET_RNGS 0x20
+#define SEGMENT_OFFSET_CIPHERS 0x40
+
+/* addresses and codes common to all hash cores */
+#define ADDR_NAME0 0x00
+#define ADDR_NAME1 0x01
+#define ADDR_VERSION 0x02
+#define ADDR_CTRL 0x08
+#define CTRL_INIT_CMD 1
+#define CTRL_NEXT_CMD 2
+#define ADDR_STATUS 0x09
+#define STATUS_READY_BIT 1
+#define STATUS_VALID_BIT 2
+
+/* addresses and codes for the specific hash cores */
+#define SHA1_ADDR_PREFIX 0x01
+#define SHA1_ADDR_BLOCK 0x10
+#define SHA1_BLOCK_LEN 16
+#define SHA1_ADDR_DIGEST 0x20
+#define SHA1_DIGEST_LEN 5
+
+#define SHA256_ADDR_PREFIX 0x02
+#define SHA256_ADDR_BLOCK 0x10
+#define SHA256_BLOCK_LEN 16
+#define SHA256_ADDR_DIGEST 0x20
+#define SHA256_DIGEST_LEN 8
+
+#define SHA512_ADDR_PREFIX 0x03
+#define SHA512_CTRL_MODE_LOW 2
+#define SHA512_CTRL_MODE_HIGH 3
+#define SHA512_ADDR_BLOCK 0x10
+#define SHA512_BLOCK_LEN 32
+#define SHA512_ADDR_DIGEST 0x40
+#define SHA512_DIGEST_LEN 16
+#define MODE_SHA_512_224 0
+#define MODE_SHA_512_256 1
+#define MODE_SHA_384 2
+#define MODE_SHA_512 3
+
+int i2cfd;
+int debug = 0;
+
+/* SHA-1/SHA-256 One Block Message Sample
+ Input Message: "abc" */
+const uint32_t NIST_512_SINGLE[] =
+{ 0x61626380, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000018 };
+
+const uint32_t SHA1_SINGLE_DIGEST[] =
+{ 0xa9993e36, 0x4706816a, 0xba3e2571, 0x7850c26c,
+ 0x9cd0d89d };
+
+const uint32_t SHA256_SINGLE_DIGEST[] =
+{ 0xBA7816BF, 0x8F01CFEA, 0x414140DE, 0x5DAE2223,
+ 0xB00361A3, 0x96177A9C, 0xB410FF61, 0xF20015AD };
+
+/* SHA-1/SHA-256 Two Block Message Sample
+ Input Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" */
+const uint32_t NIST_512_DOUBLE0[] =
+{ 0x61626364, 0x62636465, 0x63646566, 0x64656667,
+ 0x65666768, 0x66676869, 0x6768696A, 0x68696A6B,
+ 0x696A6B6C, 0x6A6B6C6D, 0x6B6C6D6E, 0x6C6D6E6F,
+ 0x6D6E6F70, 0x6E6F7071, 0x80000000, 0x00000000 };
+const uint32_t NIST_512_DOUBLE1[] =
+{ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x000001C0 };
+
+const uint32_t SHA1_DOUBLE_DIGEST[] =
+{ 0x84983E44, 0x1C3BD26E, 0xBAAE4AA1, 0xF95129E5,
+ 0xE54670F1 };
+
+const uint32_t SHA256_DOUBLE_DIGEST[] =
+{ 0x248D6A61, 0xD20638B8, 0xE5C02693, 0x0C3E6039,
+ 0xA33CE459, 0x64FF2167, 0xF6ECEDD4, 0x19DB06C1 };
+
+/* SHA-512 One Block Message Sample
+ Input Message: "abc" */
+const uint32_t NIST_1024_SINGLE[] =
+{ 0x61626380, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000018 };
+
+const uint32_t SHA512_224_SINGLE_DIGEST[] =
+{ 0x4634270f, 0x707b6a54, 0xdaae7530, 0x460842e2,
+ 0x0e37ed26, 0x5ceee9a4, 0x3e8924aa };
+const uint32_t SHA512_256_SINGLE_DIGEST[] =
+{ 0x53048e26, 0x81941ef9, 0x9b2e29b7, 0x6b4c7dab,
+ 0xe4c2d0c6, 0x34fc6d46, 0xe0e2f131, 0x07e7af23 };
+const uint32_t SHA384_SINGLE_DIGEST[] =
+{ 0xcb00753f, 0x45a35e8b, 0xb5a03d69, 0x9ac65007,
+ 0x272c32ab, 0x0eded163, 0x1a8b605a, 0x43ff5bed,
+ 0x8086072b, 0xa1e7cc23, 0x58baeca1, 0x34c825a7 };
+const uint32_t SHA512_SINGLE_DIGEST[] =
+{ 0xddaf35a1, 0x93617aba, 0xcc417349, 0xae204131,
+ 0x12e6fa4e, 0x89a97ea2, 0x0a9eeee6, 0x4b55d39a,
+ 0x2192992a, 0x274fc1a8, 0x36ba3c23, 0xa3feebbd,
+ 0x454d4423, 0x643ce80e, 0x2a9ac94f, 0xa54ca49f };
+
+/* SHA-512 Two Block Message Sample
+ Input Message: "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" */
+const uint32_t NIST_1024_DOUBLE0[] =
+{ 0x61626364, 0x65666768, 0x62636465, 0x66676869,
+ 0x63646566, 0x6768696a, 0x64656667, 0x68696a6b,
+ 0x65666768, 0x696a6b6c, 0x66676869, 0x6a6b6c6d,
+ 0x6768696a, 0x6b6c6d6e, 0x68696a6b, 0x6c6d6e6f,
+ 0x696a6b6c, 0x6d6e6f70, 0x6a6b6c6d, 0x6e6f7071,
+ 0x6b6c6d6e, 0x6f707172, 0x6c6d6e6f, 0x70717273,
+ 0x6d6e6f70, 0x71727374, 0x6e6f7071, 0x72737475,
+ 0x80000000, 0x00000000, 0x00000000, 0x00000000 };
+const uint32_t NIST_1024_DOUBLE1[] =
+{ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000380 };
+
+const uint32_t SHA512_224_DOUBLE_DIGEST[] =
+{ 0x23fec5bb, 0x94d60b23, 0x30819264, 0x0b0c4533,
+ 0x35d66473, 0x4fe40e72, 0x68674af9 };
+const uint32_t SHA512_256_DOUBLE_DIGEST[] =
+{ 0x3928e184, 0xfb8690f8, 0x40da3988, 0x121d31be,
+ 0x65cb9d3e, 0xf83ee614, 0x6feac861, 0xe19b563a };
+const uint32_t SHA384_DOUBLE_DIGEST[] =
+{ 0x09330c33, 0xf71147e8, 0x3d192fc7, 0x82cd1b47,
+ 0x53111b17, 0x3b3b05d2, 0x2fa08086, 0xe3b0f712,
+ 0xfcc7c71a, 0x557e2db9, 0x66c3e9fa, 0x91746039 };
+const uint32_t SHA512_DOUBLE_DIGEST[] =
+{ 0x8e959b75, 0xdae313da, 0x8cf4f728, 0x14fc143f,
+ 0x8f7779c6, 0xeb9f7fa1, 0x7299aead, 0xb6889018,
+ 0x501d289e, 0x4900f7e4, 0x331b99de, 0xc4b5433a,
+ 0xc7d329ee, 0xb6dd2654, 0x5e96e55b, 0x874be909 };
+
+/* ---------------- I2C low-level code ---------------- */
+int i2c_setup(char *dev, int addr)
+{
+ i2cfd = open(dev, O_RDWR);
+ if (i2cfd < 0) {
+ fprintf(stderr, "Unable to open %s: ", dev);
+ perror("");
+ i2cfd = 0;
+ return 1;
+ }
+
+ if (ioctl(i2cfd, I2C_SLAVE, addr) < 0) {
+ fprintf(stderr, "Unable to set I2C slave device 0x%02x: ", addr);
+ perror("");
+ return 1;
+ }
+
+ return 0;
+}
+
+int i2c_write(uint8_t *buf, int len)
+{
+ if (debug) {
+ int i;
+ printf("write [");
+ for (i = 0; i < len; ++i)
+ printf(" %02x", buf[i]);
+ printf(" ]\n");
+ }
+
+ if (write(i2cfd, buf, len) != len) {
+ perror("i2c write failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+int i2c_read(uint8_t *b)
+{
+ /* read() on the i2c device only returns one byte at a time,
+ * and tc_get_resp() needs to parse the response one byte at a time
+ */
+ if (read(i2cfd, b, 1) != 1) {
+ perror("i2c read failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+/* ---------------- test-case low-level code ---------------- */
+int tc_send_write_cmd(uint8_t addr0, uint8_t addr1, uint32_t data)
+{
+ uint8_t buf[9];
+
+ buf[0] = SOC;
+ buf[1] = WRITE_CMD;
+ buf[2] = addr0;
+ buf[3] = addr1;
+ buf[4] = (data >> 24) & 0xff;
+ buf[5] = (data >> 16) & 0xff;
+ buf[6] = (data >> 8) & 0xff;
+ buf[7] = data & 0xff;
+ buf[8] = EOC;
+
+ return i2c_write(buf, sizeof(buf));
+}
+
+int tc_send_read_cmd(uint8_t addr0, uint8_t addr1)
+{
+ uint8_t buf[5];
+
+ buf[0] = SOC;
+ buf[1] = READ_CMD;
+ buf[2] = addr0;
+ buf[3] = addr1;
+ buf[4] = EOC;
+
+ return i2c_write(buf, sizeof(buf));
+}
+
+int tc_get_resp(uint8_t *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; ++i) {
+ if (i2c_read(&buf[i]) != 0)
+ return 1;
+ if ((i == 0) && (buf[i] != SOR)) {
+ /* we've gotten out of sync, and there's probably nothing we can do */
+ fprintf(stderr, "response byte 0: expected 0x%02x (SOR), got 0x%02x\n",
+ SOR, buf[0]);
+ return 1;
+ }
+ else if (i == 1) { /* response code */
+ switch (buf[i]) {
+ case READ_OK:
+ len = 9;
+ break;
+ case WRITE_OK:
+ len = 5;
+ break;
+ case RESET_OK:
+ len = 3;
+ break;
+ case ERROR:
+ case UNKNOWN:
+ len = 4;
+ break;
+ default:
+ /* we've gotten out of sync, and there's probably nothing we can do */
+ fprintf(stderr, "unknown response code 0x%02x\n", buf[i]);
+ return 1;
+ }
+ }
+ }
+
+ if (debug) {
+ printf("read [");
+ for (i = 0; i < len; ++i)
+ printf(" %02x", buf[i]);
+ printf(" ]\n");
+ }
+
+ return 0;
+}
+
+int tc_get_expected(uint8_t *expected, int len)
+{
+ uint8_t buf[9];
+ int i;
+
+ if (tc_get_resp(buf, sizeof(buf)) != 0)
+ return 1;
+
+ for (i = 0; i < len; ++i) {
+ if (buf[i] != expected[i]) {
+ fprintf(stderr, "response byte %d: expected 0x%02x, got 0x%02x\n",
+ i, expected[i], buf[i]);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int tc_get_write_resp(uint8_t addr0, uint8_t addr1)
+{
+ uint8_t expected[5];
+
+ expected[0] = SOR;
+ expected[1] = WRITE_OK;
+ expected[2] = addr0;
+ expected[3] = addr1;
+ expected[4] = EOR;
+
+ return tc_get_expected(expected, sizeof(expected));
+}
+
+int tc_get_read_resp(uint8_t addr0, uint8_t addr1, uint32_t data)
+{
+ uint8_t expected[9];
+
+ expected[0] = SOR;
+ expected[1] = READ_OK;
+ expected[2] = addr0;
+ expected[3] = addr1;
+ expected[4] = (data >> 24) & 0xff;
+ expected[5] = (data >> 16) & 0xff;
+ expected[6] = (data >> 8) & 0xff;
+ expected[7] = data & 0xff;
+ expected[8] = EOR;
+
+ return tc_get_expected(expected, sizeof(expected));
+}
+
+int tc_write(uint8_t addr0, uint8_t addr1, uint32_t data)
+{
+ return (tc_send_write_cmd(addr0, addr1, data) ||
+ tc_get_write_resp(addr0, addr1));
+}
+
+int tc_read(uint8_t addr0, uint8_t addr1, uint32_t data)
+{
+ return (tc_send_read_cmd(addr0, addr1) ||
+ tc_get_read_resp(addr0, addr1, data));
+}
+
+int tc_init(uint8_t addr0)
+{
+ return tc_write(addr0, ADDR_CTRL, CTRL_INIT_CMD);
+}
+
+int tc_next(uint8_t addr0)
+{
+ return tc_write(addr0, ADDR_CTRL, CTRL_NEXT_CMD);
+}
+
+int tc_wait(uint8_t addr0, uint8_t status)
+{
+ uint8_t buf[9];
+
+ do {
+ if (tc_send_read_cmd(addr0, ADDR_STATUS) != 0)
+ return 1;
+ if (tc_get_resp(buf, 9) != 0)
+ return 1;
+ if (buf[1] != READ_OK)
+ return 1;
+ } while ((buf[7] & status) != status);
+
+ return 0;
+}
+
+int tc_wait_ready(uint8_t addr0)
+{
+ return tc_wait(addr0, STATUS_READY_BIT);
+}
+
+int tc_wait_valid(uint8_t addr0)
+{
+ return tc_wait(addr0, STATUS_VALID_BIT);
+}
+
+/* ---------------- sanity test case ---------------- */
+
+int TC0()
+{
+ uint32_t board_type = 0x50565431; /* "PVT1" */
+ uint32_t bitstream_ver = 0x0001000B; /* v0.1.0b */
+ uint32_t t;
+
+ printf("TC0: Reading board type, version, and dummy reg from global registers.\n");
+
+ /* write current time into dummy register, then try to read it back
+ * to make sure that we can actually write something into EIM
+ */
+ t = time(NULL);
+ tc_write(GLOBAL_ADDR_PREFIX, ADDR_GLOBAL_DUMMY_REG, t);
+
+ return
+ tc_read(GLOBAL_ADDR_PREFIX, ADDR_GLOBAL_BOARD_TYPE, board_type) ||
+ tc_read(GLOBAL_ADDR_PREFIX, ADDR_GLOBAL_BITSTREAM_VER, bitstream_ver) ||
+ tc_read(GLOBAL_ADDR_PREFIX, ADDR_GLOBAL_DUMMY_REG, t);
+}
+
+/* ---------------- SHA-1 test cases ---------------- */
+
+int sha1_read(uint8_t addr, uint32_t data)
+{
+ return tc_read(SHA1_ADDR_PREFIX, addr, data);
+}
+
+int sha1_write(uint8_t addr, uint32_t data)
+{
+ return tc_write(SHA1_ADDR_PREFIX, addr, data);
+}
+
+int sha1_init(void)
+{
+ return tc_init(SHA1_ADDR_PREFIX);
+}
+
+int sha1_next(void)
+{
+ return tc_next(SHA1_ADDR_PREFIX);
+}
+
+int sha1_wait_ready(void)
+{
+ return tc_wait_ready(SHA1_ADDR_PREFIX);
+}
+
+int sha1_wait_valid(void)
+{
+ return tc_wait_valid(SHA1_ADDR_PREFIX);
+}
+
+/* TC1: Read name and version from SHA-1 core. */
+int TC1(void)
+{
+ uint32_t name0 = 0x73686131; /* "sha1" */
+ uint32_t name1 = 0x20202020; /* " " */
+ uint32_t version = 0x302e3530; /* "0.50" */
+
+ printf("TC1: Reading name, type and version words from SHA-1 core.\n");
+
+ return
+ sha1_read(ADDR_NAME0, name0) ||
+ sha1_read(ADDR_NAME1, name1) ||
+ sha1_read(ADDR_VERSION, version);
+}
+
+/* TC2: SHA-1 Single block message test as specified by NIST. */
+int TC2(void)
+{
+ const uint32_t *block = NIST_512_SINGLE;
+ const uint32_t *expected = SHA1_SINGLE_DIGEST;
+ int i;
+
+ printf("TC2: Single block message test for SHA-1.\n");
+
+ /* Write block to SHA-1. */
+ for (i = 0; i < SHA1_BLOCK_LEN; ++i) {
+ if (sha1_write(SHA1_ADDR_BLOCK + i, block[i]) != 0)
+ return 1;
+ }
+
+ /* Start initial block hashing, wait and check status. */
+ if ((sha1_init() != 0) || (sha1_wait_valid() != 0))
+ return 1;
+
+ /* Extract the digest. */
+ for (i = 0; i < SHA1_DIGEST_LEN; ++i) {
+ if (sha1_read(SHA1_ADDR_DIGEST + i, expected[i]) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* TC3: SHA-1 Double block message test as specified by NIST. */
+int TC3(void)
+{
+ const uint32_t *block[2] = { NIST_512_DOUBLE0, NIST_512_DOUBLE1 };
+ static const uint32_t block0_expected[] =
+ { 0xF4286818, 0xC37B27AE, 0x0408F581, 0x84677148, 0x4A566572 };
+ const uint32_t *expected = SHA1_DOUBLE_DIGEST;
+ int i;
+
+ printf("TC3: Double block message test for SHA-1.\n");
+
+ /* Write first block to SHA-1. */
+ for (i = 0; i < SHA1_BLOCK_LEN; ++i) {
+ if (sha1_write(SHA1_ADDR_BLOCK + i, block[0][i]) != 0)
+ return 1;
+ }
+
+ /* Start initial block hashing, wait and check status. */
+ if ((sha1_init() != 0) || (sha1_wait_valid() != 0))
+ return 1;
+
+ /* Extract the first digest. */
+ for (i = 0; i < SHA1_DIGEST_LEN; ++i) {
+ if (sha1_read(SHA1_ADDR_DIGEST + i, block0_expected[i]) != 0)
+ return 1;
+ }
+
+ /* Write second block to SHA-1. */
+ for (i = 0; i < SHA1_BLOCK_LEN; ++i) {
+ if (sha1_write(SHA1_ADDR_BLOCK + i, block[1][i]) != 0)
+ return 1;
+ }
+
+ /* Start next block hashing, wait and check status. */
+ if ((sha1_next() != 0) || (sha1_wait_valid() != 0))
+ return 1;
+
+ /* Extract the second digest. */
+ for (i = 0; i < SHA1_DIGEST_LEN; ++i) {
+ if (sha1_read(SHA1_ADDR_DIGEST + i, expected[i]) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* ---------------- SHA-256 test cases ---------------- */
+
+int sha256_read(uint8_t addr, uint32_t data)
+{
+ return tc_read(SHA256_ADDR_PREFIX, addr, data);
+}
+
+int sha256_write(uint8_t addr, uint32_t data)
+{
+ return tc_write(SHA256_ADDR_PREFIX, addr, data);
+}
+
+int sha256_init(void)
+{
+ return tc_init(SHA256_ADDR_PREFIX);
+}
+
+int sha256_next(void)
+{
+ return tc_next(SHA256_ADDR_PREFIX);
+}
+
+int sha256_wait_ready(void)
+{
+ return tc_wait_ready(SHA256_ADDR_PREFIX);
+}
+
+int sha256_wait_valid(void)
+{
+ return tc_wait_valid(SHA256_ADDR_PREFIX);
+}
+
+/* TC4: Read name and version from SHA-256 core. */
+int TC4(void)
+{
+ uint32_t name0 = 0x73686132; /* "sha2" */
+ uint32_t name1 = 0x2d323536; /* "-256" */
+ uint32_t version = 0x302e3830; /* "0.80" */
+
+ printf("TC4: Reading name, type and version words from SHA-256 core.\n");
+
+ return
+ sha256_read(ADDR_NAME0, name0) ||
+ sha256_read(ADDR_NAME1, name1) ||
+ sha256_read(ADDR_VERSION, version);
+}
+
+/* TC5: SHA-256 Single block message test as specified by NIST. */
+int TC5(void)
+{
+ const uint32_t *block = NIST_512_SINGLE;
+ const uint32_t *expected = SHA256_SINGLE_DIGEST;
+ int i;
+
+ printf("TC5: Single block message test for SHA-256.\n");
+
+ /* Write block to SHA-256. */
+ for (i = 0; i < SHA256_BLOCK_LEN; ++i) {
+ if (sha256_write(SHA256_ADDR_BLOCK + i, block[i]) != 0)
+ return 1;
+ }
+
+ /* Start initial block hashing, wait and check status. */
+ if ((sha256_init() != 0) || (sha256_wait_valid() != 0))
+ return 1;
+
+ /* Extract the digest. */
+ for (i = 0; i < SHA256_DIGEST_LEN; ++i) {
+ if (sha256_read(SHA256_ADDR_DIGEST + i, expected[i]) != 0)
+ return 1;
+ }
+
+
+ return 0;
+}
+
+/* TC6: SHA-1 Double block message test as specified by NIST. */
+int TC6(void)
+{
+ const uint32_t *block[2] = { NIST_512_DOUBLE0, NIST_512_DOUBLE1 };
+ static const uint32_t block0_expected[] =
+ { 0x85E655D6, 0x417A1795, 0x3363376A, 0x624CDE5C,
+ 0x76E09589, 0xCAC5F811, 0xCC4B32C1, 0xF20E533A };
+ const uint32_t *expected = SHA256_DOUBLE_DIGEST;
+ int i;
+
+ printf("TC6: Double block message test for SHA-256.\n");
+
+ /* Write first block to SHA-256. */
+ for (i = 0; i < SHA256_BLOCK_LEN; ++i) {
+ if (sha256_write(SHA256_ADDR_BLOCK + i, block[0][i]) != 0)
+ return 1;
+ }
+
+ /* Start initial block hashing, wait and check status. */
+ if ((sha256_init() != 0) || (sha256_wait_valid() != 0))
+ return 1;
+
+ /* Extract the first digest. */
+ for (i = 0; i < SHA256_DIGEST_LEN; ++i) {
+ if (sha256_read(SHA256_ADDR_DIGEST + i, block0_expected[i]) != 0)
+ return 1;
+ }
+
+ /* Write second block to SHA-256. */
+ for (i = 0; i < SHA256_BLOCK_LEN; ++i) {
+ if (sha256_write(SHA256_ADDR_BLOCK + i, block[1][i]) != 0)
+ return 1;
+ }
+
+ /* Start next block hashing, wait and check status. */
+ if ((sha256_next() != 0) || (sha256_wait_valid() != 0))
+ return 1;
+
+ /* Extract the second digest. */
+ for (i = 0; i < SHA256_DIGEST_LEN; ++i) {
+ if (sha256_read(SHA256_ADDR_DIGEST + i, expected[i]) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* TC7: SHA-256 Huge message test. */
+int TC7(void)
+{
+ static const uint32_t block[] =
+ { 0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
+ 0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
+ 0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
+ 0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f };
+
+ /* final digest after 1000 iterations */
+ static const uint32_t expected[] =
+ { 0x7638f3bc, 0x500dd1a6, 0x586dd4d0, 0x1a1551af,
+ 0xd821d235, 0x2f919e28, 0xd5842fab, 0x03a40f2a };
+
+ int i, n = 1000;
+
+ printf("TC7: Message with %d blocks test for SHA-256.\n", n);
+
+ /* Write first block to SHA-256. */
+ for (i = 0; i < SHA256_BLOCK_LEN; ++i) {
+ if (sha256_write( SHA256_ADDR_BLOCK + i, block[i]) != 0)
+ return 1;
+ }
+
+ /* Start initial block hashing, wait and check status. */
+ if ((sha256_init() != 0) || (sha256_wait_ready() != 0))
+ return 1;
+
+ /* First block done. Do the rest. */
+ for (i = 1; i < n; ++i) {
+ /* Start next block hashing, wait and check status. */
+ if ((sha256_next() != 0) || (sha256_wait_ready() != 0))
+ return 1;
+ }
+
+ /* XXX valid is probably set at the same time as ready */
+ if (sha256_wait_valid() != 0)
+ return 1;
+ /* Extract the final digest. */
+ for (i = 0; i < SHA256_DIGEST_LEN; ++i) {
+ if (sha256_read(SHA256_ADDR_DIGEST + i, expected[i]) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* ---------------- SHA-512 test cases ---------------- */
+
+int sha512_read(uint8_t addr, uint32_t data)
+{
+ return tc_read(SHA512_ADDR_PREFIX, addr, data);
+}
+
+int sha512_write(uint8_t addr, uint32_t data)
+{
+ return tc_write(SHA512_ADDR_PREFIX, addr, data);
+}
+
+int sha512_init(uint8_t mode)
+{
+ return tc_write(SHA512_ADDR_PREFIX, ADDR_CTRL,
+ CTRL_INIT_CMD + (mode << SHA512_CTRL_MODE_LOW));
+}
+
+int sha512_next(uint8_t mode)
+{
+ return tc_write(SHA512_ADDR_PREFIX, ADDR_CTRL,
+ CTRL_NEXT_CMD + (mode << SHA512_CTRL_MODE_LOW));
+}
+
+int sha512_wait_ready(void)
+{
+ return tc_wait_ready(SHA512_ADDR_PREFIX);
+}
+
+int sha512_wait_valid(void)
+{
+ return tc_wait_valid(SHA512_ADDR_PREFIX);
+}
+
+/* TC8: Read name and version from SHA-512 core. */
+int TC8(void)
+{
+ uint32_t name0 = 0x73686132; /* "sha2" */
+ uint32_t name1 = 0x2d353132; /* "-512" */
+ uint32_t version = 0x302e3830; /* "0.80" */
+
+ printf("TC8: Reading name, type and version words from SHA-512 core.\n");
+
+ return
+ sha512_read(ADDR_NAME0, name0) ||
+ sha512_read(ADDR_NAME1, name1) ||
+ sha512_read(ADDR_VERSION, version);
+}
+
+/* TC9: SHA-512 Single block message test as specified by NIST.
+ We do this for all modes. */
+int tc9(uint8_t mode, const uint32_t *expected, int len)
+{
+ const uint32_t *block = NIST_1024_SINGLE;
+ int i;
+
+ /* Write block to SHA-512. */
+ for (i = 0; i < SHA512_BLOCK_LEN; ++i) {
+ if (sha512_write(SHA512_ADDR_BLOCK + i, block[i]) != 0)
+ return 1;
+ }
+
+ /* Start initial block hashing, wait and check status. */
+ if ((sha512_init(mode) != 0) || (sha512_wait_valid() != 0))
+ return 1;
+
+ /* Extract the digest. */
+ for (i = 0; i < len/4; ++i) {
+ if (sha512_read(SHA512_ADDR_DIGEST + i, expected[i]) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+int TC9(void)
+{
+ printf("TC9-1: Single block message test for SHA-512/224.\n");
+ if (tc9(MODE_SHA_512_224, SHA512_224_SINGLE_DIGEST,
+ sizeof(SHA512_224_SINGLE_DIGEST)) != 0)
+ return 1;
+
+ printf("TC9-2: Single block message test for SHA-512/256.\n");
+ if (tc9(MODE_SHA_512_256, SHA512_256_SINGLE_DIGEST,
+ sizeof(SHA512_256_SINGLE_DIGEST)) != 0)
+ return 1;
+
+ printf("TC9-3: Single block message test for SHA-384.\n");
+ if (tc9(MODE_SHA_384, SHA384_SINGLE_DIGEST,
+ sizeof(SHA384_SINGLE_DIGEST)) != 0)
+ return 1;
+
+ printf("TC9-4: Single block message test for SHA-512.\n");
+ if (tc9(MODE_SHA_512, SHA512_SINGLE_DIGEST,
+ sizeof(SHA512_SINGLE_DIGEST)) != 0)
+ return 1;
+
+ return 0;
+}
+
+/* TC10: SHA-512 Double block message test as specified by NIST.
+ We do this for all modes. */
+int tc10(uint8_t mode, const uint32_t *expected, int len)
+{
+ const uint32_t *block[2] = { NIST_1024_DOUBLE0, NIST_1024_DOUBLE1 };
+ int i;
+
+ /* Write first block to SHA-512. */
+ for (i = 0; i < SHA512_BLOCK_LEN; ++i) {
+ if (sha512_write(SHA512_ADDR_BLOCK + i, block[0][i]) != 0)
+ return 1;
+ }
+
+ /* Start initial block hashing, wait and check status. */
+ if ((sha512_init(mode) != 0) || (sha512_wait_ready() != 0))
+ return 1;
+
+ /* Write second block to SHA-512. */
+ for (i = 0; i < SHA512_BLOCK_LEN; ++i) {
+ if (sha512_write(SHA512_ADDR_BLOCK + i, block[1][i]) != 0)
+ return 1;
+ }
+
+ /* Start next block hashing, wait and check status. */
+ if ((sha512_next(mode) != 0) || (sha512_wait_valid() != 0))
+ return 1;
+
+ /* Extract the digest. */
+ for (i = 0; i < len/4; ++i) {
+ if (sha512_read(SHA512_ADDR_DIGEST + i, expected[i]) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+int TC10(void)
+{
+ printf("TC10-1: Double block message test for SHA-512/224.\n");
+ if (tc10(MODE_SHA_512_224, SHA512_224_DOUBLE_DIGEST,
+ sizeof(SHA512_224_DOUBLE_DIGEST)) != 0)
+ return 1;
+
+ printf("TC10-2: Double block message test for SHA-512/256.\n");
+ if (tc10(MODE_SHA_512_256, SHA512_256_DOUBLE_DIGEST,
+ sizeof(SHA512_256_DOUBLE_DIGEST)) != 0)
+ return 1;
+
+ printf("TC10-3: Double block message test for SHA-384.\n");
+ if (tc10(MODE_SHA_384, SHA384_DOUBLE_DIGEST,
+ sizeof(SHA384_DOUBLE_DIGEST)) != 0)
+ return 1;
+
+ printf("TC10-4: Double block message test for SHA-512.\n");
+ if (tc10(MODE_SHA_512, SHA512_DOUBLE_DIGEST,
+ sizeof(SHA512_DOUBLE_DIGEST)) != 0)
+ return 1;
+
+ return 0;
+}
+
+/* ---------------- main ---------------- */
+
+int main(int argc, char *argv[])
+{
+ typedef int (*tcfp)(void);
+ tcfp all_tests[] = { TC0, TC1, TC2, TC3, TC4, TC5, TC6, TC7, TC8, TC9, TC10 };
+ tcfp sha1_tests[] = { TC1, TC2, TC3 };
+ tcfp sha256_tests[] = { TC4, TC5, TC6, TC7 };
+ tcfp sha512_tests[] = { TC8, TC9, TC10 };
+
+ char *usage = "Usage: %s [-d] [-i I2C_device] [-a I2C_addr] tc...\n";
+ char *dev = I2C_dev;
+ int addr = I2C_addr;
+ int i, j, opt;
+
+ while ((opt = getopt(argc, argv, "h?di:a:")) != -1) {
+ switch (opt) {
+ case 'h':
+ case '?':
+ printf(usage, argv[0]);
+ return 0;
+ case 'd':
+ debug = 1;
+ break;
+ case 'i':
+ dev = optarg;
+ break;
+ case 'a':
+ addr = (int)strtol(optarg, NULL, 0);
+ if ((addr < 0x03) || (addr > 0x77)) {
+ fprintf(stderr, "addr must be between 0x03 and 0x77\n");
+ return 1;
+ }
+ break;
+ default:
+ fprintf(stderr, usage, argv[0]);
+ return 1;
+ }
+ }
+
+ if (i2c_setup(dev, addr) != 0)
+ return 1;
+
+ /* no args == run all tests */
+ if (optind >= argc) {
+ for (j = 0; j < sizeof(all_tests)/sizeof(all_tests[0]); ++j)
+ if (all_tests[j]() != 0)
+ return 1;
+ return 0;
+ }
+
+ for (i = optind; i < argc; ++i) {
+ if (strcmp(argv[i], "all") == 0) {
+ for (j = 0; j < sizeof(all_tests)/sizeof(all_tests[0]); ++j)
+ if (all_tests[j]() != 0)
+ return 1;
+ }
+ else if (strcmp(argv[i], "sha1") == 0) {
+ for (j = 0; j < sizeof(sha1_tests)/sizeof(sha1_tests[0]); ++j)
+ if (sha1_tests[j]() != 0)
+ return 1;
+ }
+ else if (strcmp(argv[i], "sha256") == 0) {
+ for (j = 0; j < sizeof(sha256_tests)/sizeof(sha256_tests[0]); ++j)
+ if (sha256_tests[j]() != 0)
+ return 1;
+ }
+ else if (strcmp(argv[i], "sha512") == 0) {
+ for (j = 0; j < sizeof(sha512_tests)/sizeof(sha512_tests[0]); ++j)
+ if (sha512_tests[j]() != 0)
+ return 1;
+ }
+ else if (isdigit(argv[i][0]) &&
+ (((j = atoi(argv[i])) >= 0) &&
+ (j < sizeof(all_tests)/sizeof(all_tests[0])))) {
+ if (all_tests[j]() != 0)
+ return 1;
+ }
+ else {
+ fprintf(stderr, "unknown test case %s\n", argv[i]);
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/novena/src/sw/novena-eim.c b/novena/src/sw/novena-eim.c
new file mode 100644
index 0000000..85bfac0
--- /dev/null
+++ b/novena/src/sw/novena-eim.c
@@ -0,0 +1,708 @@
+/*
+ * novena-eim.c
+ * ------------
+ * This module contains the userland magic to set up and use the EIM bus.
+ *
+ *
+ * Author: Pavel Shatov
+ * Copyright (c) 2014-2015, 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.
+ */
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/mman.h>
+
+#include "novena-eim.h"
+
+
+//------------------------------------------------------------------------------
+// Defines
+//------------------------------------------------------------------------------
+#define MEMORY_DEVICE "/dev/mem"
+
+#define IOMUXC_MUX_MODE_ALT0 0 // 000
+
+#define IOMUXC_PAD_CTL_SRE_FAST 1 // 1
+#define IOMUXC_PAD_CTL_DSE_33_OHM 7 // 111
+#define IOMUXC_PAD_CTL_SPEED_MEDIUM_10 2 // 10
+#define IOMUXC_PAD_CTL_ODE_DISABLED 0 // 0
+#define IOMUXC_PAD_CTL_PKE_DISABLED 0 // 0
+#define IOMUXC_PAD_CTL_PUE_PULL 1 // 1
+#define IOMUXC_PAD_CTL_PUS_100K_OHM_PU 2 // 10
+#define IOMUXC_PAD_CTL_HYS_DISABLED 0 // 0
+
+#define CCM_CGR_OFF 0 // 00
+#define CCM_CGR_ON_EXCEPT_STOP 3 // 11
+
+
+//------------------------------------------------------------------------------
+// CPU Registers
+//------------------------------------------------------------------------------
+enum IMX6DQ_REGISTER_OFFSET
+{
+ IOMUXC_SW_MUX_CTL_PAD_EIM_CS0_B = 0x020E00F8,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_OE_B = 0x020E0100,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_RW = 0x020E0104,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_LBA_B = 0x020E0108,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD00 = 0x020E0114,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD01 = 0x020E0118,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD02 = 0x020E011C,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD03 = 0x020E0120,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD04 = 0x020E0124,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD05 = 0x020E0128,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD06 = 0x020E012C,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD07 = 0x020E0130,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD08 = 0x020E0134,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD09 = 0x020E0138,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD10 = 0x020E013C,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD11 = 0x020E0140,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD12 = 0x020E0144,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD13 = 0x020E0148,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD14 = 0x020E014C,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_AD15 = 0x020E0150,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_WAIT_B = 0x020E0154,
+ IOMUXC_SW_MUX_CTL_PAD_EIM_BCLK = 0x020E0158,
+
+ IOMUXC_SW_PAD_CTL_PAD_EIM_CS0_B = 0x020E040C,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_OE_B = 0x020E0414,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_RW = 0x020E0418,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_LBA_B = 0x020E041C,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD00 = 0x020E0428,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD01 = 0x020E042C,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD02 = 0x020E0430,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD03 = 0x020E0434,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD04 = 0x020E0438,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD05 = 0x020E043C,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD06 = 0x020E0440,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD07 = 0x020E0444,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD08 = 0x020E0448,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD09 = 0x020E044C,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD10 = 0x020E0450,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD11 = 0x020E0454,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD12 = 0x020E0458,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD13 = 0x020E045C,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD14 = 0x020E0460,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_AD15 = 0x020E0464,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_WAIT_B = 0x020E0468,
+ IOMUXC_SW_PAD_CTL_PAD_EIM_BCLK = 0x020E046C,
+
+ CCM_CCGR6 = 0x020C4080,
+
+ EIM_CS0GCR1 = 0x021B8000,
+ EIM_CS0GCR2 = 0x021B8004,
+ EIM_CS0RCR1 = 0x021B8008,
+ EIM_CS0RCR2 = 0x021B800C,
+ EIM_CS0WCR1 = 0x021B8010,
+ EIM_CS0WCR2 = 0x021B8014,
+
+ EIM_WCR = 0x021B8090,
+ EIM_WIAR = 0x021B8094,
+ EIM_EAR = 0x021B8098,
+};
+
+
+//------------------------------------------------------------------------------
+// Structures
+//------------------------------------------------------------------------------
+struct IOMUXC_SW_MUX_CTL_PAD_EIM
+{
+ unsigned int mux_mode : 3;
+ unsigned int reserved_3 : 1;
+ unsigned int sion : 1;
+ unsigned int reserved_31_5 : 27;
+};
+
+struct IOMUXC_SW_PAD_CTL_PAD_EIM
+{
+ unsigned int sre : 1;
+ unsigned int reserved_2_1 : 2;
+ unsigned int dse : 3;
+ unsigned int speed : 2;
+ unsigned int reserved_10_8 : 3;
+ unsigned int ode : 1;
+ unsigned int pke : 1;
+ unsigned int pue : 1;
+ unsigned int pus : 2;
+ unsigned int hys : 1;
+ unsigned int reserved_31_17 : 15;
+};
+
+struct CCM_CCGR6
+{
+ unsigned int cg0_usboh3 : 2;
+ unsigned int cg1_usdhc1 : 2;
+ unsigned int cg2_usdhc2 : 2;
+ unsigned int cg3_usdhc3 : 2;
+
+ unsigned int cg3_usdhc4 : 2;
+ unsigned int cg5_eim_slow : 2;
+ unsigned int cg6_vdoaxiclk : 2;
+ unsigned int cg7_vpu : 2;
+
+ unsigned int cg8_reserved : 2;
+ unsigned int cg9_reserved : 2;
+ unsigned int cg10_reserved : 2;
+ unsigned int cg11_reserved : 2;
+
+ unsigned int cg12_reserved : 2;
+ unsigned int cg13_reserved : 2;
+ unsigned int cg14_reserved : 2;
+ unsigned int cg15_reserved : 2;
+};
+
+struct EIM_CS_GCR1
+{
+ unsigned int csen : 1;
+ unsigned int swr : 1;
+ unsigned int srd : 1;
+ unsigned int mum : 1;
+ unsigned int wfl : 1;
+ unsigned int rfl : 1;
+ unsigned int cre : 1;
+ unsigned int crep : 1;
+ unsigned int bl : 3;
+ unsigned int wc : 1;
+ unsigned int bcd : 2;
+ unsigned int bcs : 2;
+ unsigned int dsz : 3;
+ unsigned int sp : 1;
+ unsigned int csrec : 3;
+ unsigned int aus : 1;
+ unsigned int gbc : 3;
+ unsigned int wp : 1;
+ unsigned int psz : 4;
+};
+
+struct EIM_CS_GCR2
+{
+ unsigned int adh : 2;
+ unsigned int reserved_3_2 : 2;
+ unsigned int daps : 4;
+ unsigned int dae : 1;
+ unsigned int dap : 1;
+ unsigned int reserved_11_10 : 2;
+ unsigned int mux16_byp_grant : 1;
+ unsigned int reserved_31_13 : 19;
+};
+
+struct EIM_CS_RCR1
+{
+ unsigned int rcsn : 3;
+ unsigned int reserved_3 : 1;
+ unsigned int rcsa : 3;
+ unsigned int reserved_7 : 1;
+ unsigned int oen : 3;
+ unsigned int reserved_11 : 1;
+ unsigned int oea : 3;
+ unsigned int reserved_15 : 1;
+ unsigned int radvn : 3;
+ unsigned int ral : 1;
+ unsigned int radva : 3;
+ unsigned int reserved_23 : 1;
+ unsigned int rwsc : 6;
+ unsigned int reserved_31_30 : 2;
+};
+
+struct EIM_CS_RCR2
+{
+ unsigned int rben : 3;
+ unsigned int rbe : 1;
+ unsigned int rbea : 3;
+ unsigned int reserved_7 : 1;
+ unsigned int rl : 2;
+ unsigned int reserved_11_10 : 2;
+ unsigned int pat : 3;
+ unsigned int apr : 1;
+ unsigned int reserved_31_16 : 16;
+};
+
+struct EIM_CS_WCR1
+{
+ unsigned int wcsn : 3;
+ unsigned int wcsa : 3;
+ unsigned int wen : 3;
+ unsigned int wea : 3;
+ unsigned int wben : 3;
+ unsigned int wbea : 3;
+ unsigned int wadvn : 3;
+ unsigned int wadva : 3;
+ unsigned int wwsc : 6;
+ unsigned int wbed : 1;
+ unsigned int wal : 1;
+};
+
+struct EIM_CS_WCR2
+{
+ unsigned int wbcdd : 1;
+ unsigned int reserved_31_1 : 31;
+};
+
+struct EIM_WCR
+{
+ unsigned int bcm : 1;
+ unsigned int gbcd : 2;
+ unsigned int reserved_3 : 1;
+ unsigned int inten : 1;
+ unsigned int intpol : 1;
+ unsigned int reserved_7_6 : 2;
+ unsigned int wdog_en : 1;
+ unsigned int wdog_limit : 2;
+ unsigned int reserved_31_11 : 21;
+};
+
+struct EIM_WIAR
+{
+ unsigned int ips_req : 1;
+ unsigned int ips_ack : 1;
+ unsigned int irq : 1;
+ unsigned int errst : 1;
+ unsigned int aclk_en : 1;
+ unsigned int reserved_31_5 : 27;
+};
+
+struct EIM_EAR
+{
+ unsigned int error_addr : 32;
+};
+
+
+//------------------------------------------------------------------------------
+// Variables
+//------------------------------------------------------------------------------
+static long mem_page_size = 0;
+static int mem_dev_fd = -1;
+static void * mem_map_ptr = MAP_FAILED;
+static off_t mem_base_addr = 0;
+
+
+//------------------------------------------------------------------------------
+// Prototypes
+//------------------------------------------------------------------------------
+static void _eim_setup_iomuxc (void);
+static void _eim_setup_ccm (void);
+static void _eim_setup_eim (void);
+static void _eim_cleanup (void);
+static off_t _eim_calc_offset (off_t);
+static void _eim_remap_mem (off_t);
+
+
+//------------------------------------------------------------------------------
+// Set up EIM bus. Returns 0 on success, -1 on failure.
+//------------------------------------------------------------------------------
+int eim_setup(void)
+{
+ // register cleanup function
+ if (atexit(_eim_cleanup) != 0) {
+ fprintf(stderr, "ERROR: atexit() failed.\n");
+ return -1;
+ }
+
+ // determine memory page size to use in mmap()
+ mem_page_size = sysconf(_SC_PAGESIZE);
+ if (mem_page_size < 1) {
+ fprintf(stderr, "ERROR: sysconf(_SC_PAGESIZE) == %ld\n", mem_page_size);
+ return -1;
+ }
+
+ // try to open memory device
+ mem_dev_fd = open(MEMORY_DEVICE, O_RDWR | O_SYNC);
+ if (mem_dev_fd == -1) {
+ fprintf(stderr, "ERROR: open(%s) failed.\n", MEMORY_DEVICE);
+ return -1;
+ }
+
+ // configure IOMUXC
+ _eim_setup_iomuxc();
+
+ // configure Clock Controller Module
+ _eim_setup_ccm();
+
+ /* We need to properly configure EIM mode and all the corresponding parameters.
+ * That's a lot of code, let's do it now.
+ */
+ _eim_setup_eim();
+
+ // done
+ return 0;
+}
+
+
+//------------------------------------------------------------------------------
+// Shut down EIM bus. This is called automatically on exit().
+//------------------------------------------------------------------------------
+static void _eim_cleanup(void)
+{
+ // unmap memory if needed
+ if (mem_map_ptr != MAP_FAILED)
+ if (munmap(mem_map_ptr, mem_page_size) != 0)
+ fprintf(stderr, "WARNING: munmap() failed.\n");
+
+ // close memory device if needed
+ if (mem_dev_fd != -1)
+ if (close(mem_dev_fd) != 0)
+ fprintf(stderr, "WARNING: close() failed.\n");
+}
+
+
+//------------------------------------------------------------------------------
+// Several blocks in the CPU have common pins. We use the I/O MUX Controller
+// to configure what block will actually use I/O pins. We wait for the EIM
+// module to be able to communicate with the on-board FPGA.
+//------------------------------------------------------------------------------
+static void _eim_setup_iomuxc(void)
+{
+ // create structures
+ struct IOMUXC_SW_MUX_CTL_PAD_EIM reg_mux; // mux control register
+ struct IOMUXC_SW_PAD_CTL_PAD_EIM reg_pad; // pad control register
+
+ // setup mux control register
+ reg_mux.mux_mode = IOMUXC_MUX_MODE_ALT0; // ALT0 mode must be used for EIM
+ reg_mux.sion = 0; // forced input not needed
+ reg_mux.reserved_3 = 0; // must be 0
+ reg_mux.reserved_31_5 = 0; // must be 0
+
+ // setup pad control register
+ reg_pad.sre = IOMUXC_PAD_CTL_SRE_FAST; // fast slew rate
+ reg_pad.dse = IOMUXC_PAD_CTL_DSE_33_OHM; // highest drive strength
+ reg_pad.speed = IOMUXC_PAD_CTL_SPEED_MEDIUM_10; // medium speed
+ reg_pad.ode = IOMUXC_PAD_CTL_ODE_DISABLED; // open drain not needed
+ reg_pad.pke = IOMUXC_PAD_CTL_PKE_DISABLED; // neither pull nor keeper are needed
+ reg_pad.pue = IOMUXC_PAD_CTL_PUE_PULL; // doesn't matter actually, because PKE is disabled
+ reg_pad.pus = IOMUXC_PAD_CTL_PUS_100K_OHM_PU; // doesn't matter actually, because PKE is disabled
+ reg_pad.hys = IOMUXC_PAD_CTL_HYS_DISABLED; // use CMOS, not Schmitt trigger input
+ reg_pad.reserved_2_1 = 0; // must be 0
+ reg_pad.reserved_10_8 = 0; // must be 0
+ reg_pad.reserved_31_17 = 0; // must be 0
+
+ // all the pins must be configured to use the same ALT0 mode
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_CS0_B, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_OE_B, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_RW, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_LBA_B, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD00, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD01, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD02, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD03, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD04, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD05, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD06, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD07, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD08, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD09, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD10, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD11, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD12, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD13, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD14, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD15, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_WAIT_B, (uint32_t *)®_mux);
+ eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_BCLK, (uint32_t *)®_mux);
+
+ // we need to configure all the I/O pads too
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_CS0_B, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_OE_B, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_RW, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_LBA_B, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD00, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD01, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD02, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD03, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD04, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD05, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD06, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD07, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD08, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD09, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD10, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD11, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD12, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD13, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD14, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD15, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_WAIT_B, (uint32_t *)®_pad);
+ eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_BCLK, (uint32_t *)®_pad);
+}
+
+
+//------------------------------------------------------------------------------
+// Configure Clock Controller Module to enable clocking of EIM block.
+//------------------------------------------------------------------------------
+static void _eim_setup_ccm(void)
+{
+ // create structure
+ struct CCM_CCGR6 ccm_ccgr6;
+
+ // read register
+ eim_read_32(CCM_CCGR6, (uint32_t *)&ccm_ccgr6);
+
+ // modify register
+ ccm_ccgr6.cg0_usboh3 = CCM_CGR_ON_EXCEPT_STOP;
+ ccm_ccgr6.cg1_usdhc1 = CCM_CGR_OFF;
+ ccm_ccgr6.cg2_usdhc2 = CCM_CGR_ON_EXCEPT_STOP;
+ ccm_ccgr6.cg3_usdhc3 = CCM_CGR_ON_EXCEPT_STOP;
+
+ ccm_ccgr6.cg3_usdhc4 = CCM_CGR_OFF;
+ ccm_ccgr6.cg5_eim_slow = CCM_CGR_ON_EXCEPT_STOP;
+ ccm_ccgr6.cg6_vdoaxiclk = CCM_CGR_OFF;
+ ccm_ccgr6.cg7_vpu = CCM_CGR_OFF;
+
+ ccm_ccgr6.cg8_reserved = 0;
+ ccm_ccgr6.cg9_reserved = 0;
+ ccm_ccgr6.cg10_reserved = 0;
+ ccm_ccgr6.cg11_reserved = 0;
+ ccm_ccgr6.cg12_reserved = 0;
+ ccm_ccgr6.cg13_reserved = 0;
+ ccm_ccgr6.cg14_reserved = 0;
+ ccm_ccgr6.cg15_reserved = 0;
+
+ // write register
+ eim_write_32(CCM_CCGR6, (uint32_t *)&ccm_ccgr6);
+}
+
+
+//------------------------------------------------------------------------------
+// Configure EIM mode and all the corresponding parameters. That's a lot of code.
+//------------------------------------------------------------------------------
+static void _eim_setup_eim(void)
+{
+ // create structures
+ struct EIM_CS_GCR1 gcr1;
+ struct EIM_CS_GCR2 gcr2;
+ struct EIM_CS_RCR1 rcr1;
+ struct EIM_CS_RCR2 rcr2;
+ struct EIM_CS_WCR1 wcr1;
+ struct EIM_CS_WCR2 wcr2;
+
+ struct EIM_WCR wcr;
+ struct EIM_WIAR wiar;
+ struct EIM_EAR ear;
+
+ // read all the registers
+ eim_read_32(EIM_CS0GCR1, (uint32_t *)&gcr1);
+ eim_read_32(EIM_CS0GCR2, (uint32_t *)&gcr2);
+ eim_read_32(EIM_CS0RCR1, (uint32_t *)&rcr1);
+ eim_read_32(EIM_CS0RCR2, (uint32_t *)&rcr2);
+ eim_read_32(EIM_CS0WCR1, (uint32_t *)&wcr1);
+ eim_read_32(EIM_CS0WCR2, (uint32_t *)&wcr2);
+
+ eim_read_32(EIM_WCR, (uint32_t *)&wcr);
+ eim_read_32(EIM_WIAR, (uint32_t *)&wiar);
+ eim_read_32(EIM_EAR, (uint32_t *)&ear);
+
+ // manipulate registers as needed
+ gcr1.csen = 1; // chip select is enabled
+ gcr1.swr = 1; // write is sync
+ gcr1.srd = 1; // read is sync
+ gcr1.mum = 1; // address and data are multiplexed
+ gcr1.wfl = 0; // write latency is not fixed
+ gcr1.rfl = 0; // read latency is not fixed
+ gcr1.cre = 0; // CRE signal not needed
+ //gcr1.crep = x; // don't care, CRE not used
+ gcr1.bl = 4; // burst length
+ gcr1.wc = 0; // write is not continuous
+ gcr1.bcd = 3; // BCLK divisor is 3+1=4
+ gcr1.bcs = 1; // delay from ~CS to BCLK is 1 cycle
+ gcr1.dsz = 1; // 16 bits per databeat at DATA[15:0]
+ gcr1.sp = 0; // supervisor protection is disabled
+ gcr1.csrec = 1; // ~CS recovery is 1 cycle
+ gcr1.aus = 1; // address is not shifted
+ gcr1.gbc = 1; // ~CS gap is 1 cycle
+ gcr1.wp = 0; // write protection is not enabled
+ //gcr1.psz = x; // don't care, page mode is not used
+
+ gcr2.adh = 0; // address hold duration is 1 cycle
+ //gcr2.daps = x; // don't care, DTACK is not used
+ gcr2.dae = 0; // DTACK is not used
+ //gcr2.dap = x; // don't care, DTACK is not used
+ gcr2.mux16_byp_grant= 1; // enable grant mechanism
+ gcr2.reserved_3_2 = 0; // must be 0
+ gcr2.reserved_11_10 = 0; // must be 0
+ gcr2.reserved_31_13 = 0; // must be 0
+
+ //rcr1.rcsn = x; // don't care in sync mode
+ rcr1.rcsa = 0; // no delay for ~CS needed
+ //rcr1.oen = x; // don't care in sync mode
+ rcr1.oea = 0; // no delay for ~OE needed
+ rcr1.radvn = 0; // no delay for ~LBA needed
+ rcr1.ral = 0; // clear ~LBA when needed
+ rcr1.radva = 0; // no delay for ~LBA needed
+ rcr1.rwsc = 1; // one wait state
+ rcr1.reserved_3 = 0; // must be 0
+ rcr1.reserved_7 = 0; // must be 0
+ rcr1.reserved_11 = 0; // must be 0
+ rcr1.reserved_15 = 0; // must be 0
+ rcr1.reserved_23 = 0; // must be 0
+ rcr1.reserved_31_30 = 0; // must be 0
+
+ //rcr2.rben = x; // don't care in sync mode
+ rcr2.rbe = 0; // BE is disabled
+ //rcr2.rbea = x; // don't care when BE is not used
+ rcr2.rl = 0; // read latency is 0
+ //rcr2.pat = x; // don't care when page read is not used
+ rcr2.apr = 0; // page read mode is not used
+ rcr2.reserved_7 = 0; // must be 0
+ rcr2.reserved_11_10 = 0; // must be 0
+ rcr2.reserved_31_16 = 0; // must be 0
+
+ //wcr1.wcsn = x; // don't care in sync mode
+ wcr1.wcsa = 0; // no delay for ~CS needed
+ //wcr1.wen = x; // don't care in sync mode
+ wcr1.wea = 0; // no delay for ~WR_N needed
+ //wcr1.wben = x; // don't care in sync mode
+ //wcr1.wbea = x; // don't care in sync mode
+ wcr1.wadvn = 0; // no delay for ~LBA needed
+ wcr1.wadva = 0; // no delay for ~LBA needed
+ wcr1.wwsc = 1; // no wait state in needed
+ wcr1.wbed = 1; // BE is disabled
+ wcr1.wal = 0; // clear ~LBA when needed
+
+ wcr2.wbcdd = 0; // write clock division is not needed
+ wcr2.reserved_31_1 = 0; // must be 0
+
+ wcr.bcm = 0; // clock is only active during access
+ //wcr.gbcd = x; // don't care when BCM=0
+ wcr.inten = 0; // interrupt is not used
+ //wcr.intpol = x; // don't care when interrupt is not used
+ wcr.wdog_en = 1; // watchdog is enabled
+ wcr.wdog_limit = 00; // timeout is 128 BCLK cycles
+ wcr.reserved_3 = 0; // must be 0
+ wcr.reserved_7_6 = 0; // must be 0
+ wcr.reserved_31_11 = 0; // must be 0
+
+ wiar.ips_req = 0; // IPS not needed
+ wiar.ips_ack = 0; // IPS not needed
+ //wiar.irq = x; // don't touch
+ //wiar.errst = x; // don't touch
+ wiar.aclk_en = 1; // clock is enabled
+ wiar.reserved_31_5 = 0; // must be 0
+
+ //ear.error_addr = x; // read-only
+
+ // write modified registers
+ eim_write_32(EIM_CS0GCR1, (uint32_t *)&gcr1);
+ eim_write_32(EIM_CS0GCR2, (uint32_t *)&gcr2);
+ eim_write_32(EIM_CS0RCR1, (uint32_t *)&rcr1);
+ eim_write_32(EIM_CS0RCR2, (uint32_t *)&rcr2);
+ eim_write_32(EIM_CS0WCR1, (uint32_t *)&wcr1);
+ eim_write_32(EIM_CS0WCR2, (uint32_t *)&wcr2);
+ eim_write_32(EIM_WCR, (uint32_t *)&wcr);
+ eim_write_32(EIM_WIAR, (uint32_t *)&wiar);
+/* eim_write_32(EIM_EAR, (uint32_t *)&ear);*/
+}
+
+
+//------------------------------------------------------------------------------
+// Write a 32-bit word to EIM.
+// If EIM is not set up correctly, this will abort with a bus error.
+//------------------------------------------------------------------------------
+void eim_write_32(off_t offset, uint32_t *pvalue)
+{
+ // calculate memory offset
+ uint32_t *ptr = (uint32_t *)_eim_calc_offset(offset);
+
+ // write data to memory
+ memcpy(ptr, pvalue, sizeof(uint32_t));
+}
+
+//------------------------------------------------------------------------------
+// Read a 32-bit word from EIM.
+// If EIM is not set up correctly, this will abort with a bus error.
+//------------------------------------------------------------------------------
+void eim_read_32(off_t offset, uint32_t *pvalue)
+{
+ // calculate memory offset
+ uint32_t *ptr = (uint32_t *)_eim_calc_offset(offset);
+
+ // read data from memory
+ memcpy(pvalue, ptr, sizeof(uint32_t));
+}
+
+
+//------------------------------------------------------------------------------
+// Calculate an offset into the currently-mapped EIM page.
+//------------------------------------------------------------------------------
+static off_t _eim_calc_offset(off_t offset)
+{
+ // make sure that memory is mapped
+ if (mem_map_ptr == MAP_FAILED)
+ _eim_remap_mem(offset);
+
+ // calculate starting and ending addresses of currently mapped page
+ off_t offset_low = mem_base_addr;
+ off_t offset_high = mem_base_addr + (mem_page_size - 1);
+
+ // check that offset is in currently mapped page, remap new page otherwise
+ if ((offset < offset_low) || (offset > offset_high))
+ _eim_remap_mem(offset);
+
+ // calculate pointer
+ return (off_t)mem_map_ptr + (offset - mem_base_addr);
+}
+
+
+//------------------------------------------------------------------------------
+// Map in a new EIM page.
+//------------------------------------------------------------------------------
+static void _eim_remap_mem(off_t offset)
+{
+ // unmap old memory page if needed
+ if (mem_map_ptr != MAP_FAILED) {
+ if (munmap(mem_map_ptr, mem_page_size) != 0) {
+ fprintf(stderr, "ERROR: munmap() failed.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ // calculate starting address of new page
+ while (offset % mem_page_size)
+ offset--;
+
+ // try to map new memory page
+ mem_map_ptr = mmap(NULL, mem_page_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ mem_dev_fd, offset);
+ if (mem_map_ptr == MAP_FAILED) {
+ fprintf(stderr, "ERROR: mmap() failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // save last mapped page address
+ mem_base_addr = offset;
+}
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/novena/src/sw/novena-eim.h b/novena/src/sw/novena-eim.h
new file mode 100644
index 0000000..75613bf
--- /dev/null
+++ b/novena/src/sw/novena-eim.h
@@ -0,0 +1,52 @@
+/*
+ * novena-eim.h
+ * ------------
+ * This module contains the userland magic to set up and use the EIM bus.
+ *
+ *
+ * Author: Pavel Shatov
+ * Copyright (c) 2014-2015, 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.
+ */
+
+#define EIM_BASE_ADDR 0x08000000
+
+/* Set up EIM bus.
+ * Returns 0 on success, -1 on failure.
+ */
+int eim_setup(void);
+
+/* Write a 32-bit word to EIM.
+ * If EIM is not set up correctly, this will abort with a bus error.
+ */
+void eim_write_32(off_t, uint32_t *);
+
+/* Read a 32-bit word from EIM.
+ * If EIM is not set up correctly, this will abort with a bus error.
+ */
+void eim_read_32(off_t, uint32_t *);
diff --git a/novena/src/ucf/novena_eim.ucf b/novena/src/ucf/novena_eim.ucf
new file mode 100644
index 0000000..160b8d9
--- /dev/null
+++ b/novena/src/ucf/novena_eim.ucf
@@ -0,0 +1,152 @@
+#======================================================================
+#
+# novena_baseline.ucf
+# -------------------
+# Constraint file for implementing the Cryptech Novena base
+# for the Xilinx Spartan6 LX45 on the Novena.
+#
+#
+# Author: Pavel Shatov
+# 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.
+#
+#======================================================================
+
+#-------------------------------------------------------------------------------
+CONFIG VCCAUX = 3.3;
+#-------------------------------------------------------------------------------
+
+
+#--------------------------------------------------------------------------------
+# GCLK Timing
+#--------------------------------------------------------------------------------
+NET "gclk_p_pin" TNM_NET = TNM_gclk;
+TIMESPEC TS_gclk = PERIOD TNM_gclk 20 ns HIGH 50%;
+
+
+#-------------------------------------------------------------------------------
+# BCLK Timing
+#-------------------------------------------------------------------------------
+NET "eim_bclk" TNM_NET = TNM_bclk;
+TIMESPEC TS_bclk = PERIOD TNM_bclk 30 ns HIGH 50%;
+
+
+#-------------------------------------------------------------------------------
+# FPGA Pinout
+#-------------------------------------------------------------------------------
+NET "led_pin" LOC = "A16" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 12;
+NET "apoptosis_pin" LOC = "K1" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 12;
+NET "reset_mcu_b_pin" LOC = "F1" | IOSTANDARD = "LVCMOS33" | PULLUP;
+
+NET "gclk_p_pin" LOC = "H2" | IOSTANDARD = "LVDS_33" | DIFF_TERM = "TRUE";
+NET "gclk_n_pin" LOC = "H1" | IOSTANDARD = "LVDS_33" | DIFF_TERM = "TRUE";
+
+NET "eim_bclk" LOC = "C9" | IOSTANDARD = "LVCMOS33";
+NET "eim_cs0_n" LOC = "B11" | IOSTANDARD = "LVCMOS33";
+
+NET "eim_da<0>" LOC = "G9" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<1>" LOC = "A10" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<2>" LOC = "F9" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<3>" LOC = "B9" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<4>" LOC = "E13" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<5>" LOC = "F13" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<6>" LOC = "A9" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<7>" LOC = "A8" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<8>" LOC = "B8" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<9>" LOC = "D8" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<10>" LOC = "D11" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<11>" LOC = "C8" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<12>" LOC = "C7" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<13>" LOC = "C11" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<14>" LOC = "C4" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+NET "eim_da<15>" LOC = "B6" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+
+NET "eim_a<16>" LOC = "A11" | IOSTANDARD = "LVCMOS33";
+NET "eim_a<17>" LOC = "B12" | IOSTANDARD = "LVCMOS33";
+NET "eim_a<18>" LOC = "D14" | IOSTANDARD = "LVCMOS33";
+
+NET "eim_lba_n" LOC = "B14" | IOSTANDARD = "LVCMOS33";
+NET "eim_wr_n" LOC = "C14" | IOSTANDARD = "LVCMOS33";
+NET "eim_oe_n" LOC = "C10" | IOSTANDARD = "LVCMOS33";
+NET "eim_wait_n" LOC = "A7" | IOSTANDARD = "LVCMOS33" | SLEW = "FAST" | DRIVE = 12;
+
+# Pins to the header where the LEDs on the Cryptech
+# Avalanche Noise Board are connected.
+NET "ct_led<0>" LOC = K6 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<1>" LOC = H4 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<2>" LOC = H3 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<3>" LOC = M1 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<4>" LOC = L7 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<5>" LOC = G1 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<6>" LOC = T2 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<7>" LOC = H7 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+
+# Pins to the header where the noise sources on the
+# Cryptech Avalanche Noise Board are connected.
+NET "ct_noise" LOC = L4 | IOSTANDARD = LVCMOS33;
+
+#-------------------------------------------------------------------------------
+# EIM Input Timing
+#-------------------------------------------------------------------------------
+NET "eim_cs0_n" TNM = "TNM_EIM_IN";
+NET "eim_da<*>" TNM = "TNM_EIM_IN";
+NET "eim_lba_n" TNM = "TNM_EIM_IN";
+NET "eim_wr_n" TNM = "TNM_EIM_IN";
+NET "eim_oe_n" TNM = "TNM_EIM_IN";
+
+TIMEGRP "TNM_EIM_IN" OFFSET = IN 9.75 ns VALID 16.0 ns BEFORE "eim_bclk" RISING;
+
+
+#-------------------------------------------------------------------------------
+# EIM Output Timing
+#-------------------------------------------------------------------------------
+NET "eim_da<*>" TNM = "TNM_EIM_OUT";
+NET "eim_wait_n" TNM = "TNM_EIM_OUT";
+
+TIMEGRP "TNM_EIM_OUT" OFFSET = OUT 13.0 ns AFTER "eim_bclk" FALLING;
+
+
+#-------------------------------------------------------------------------------
+# CDC Paths
+#-------------------------------------------------------------------------------
+INST "eim/eim/eim_cdc/cdc_eim_sys/src_ff" TNM = "TNM_from_bclk";
+INST "eim/eim/eim_cdc/cdc_eim_sys/src_latch*" TNM = "TNM_from_bclk";
+INST "eim/eim/eim_cdc/cdc_eim_sys/ff_sync*" TNM = "TNM_to_sys_clk";
+INST "eim/eim/eim_cdc/cdc_eim_sys/dst_latch*" TNM = "TNM_to_sys_clk";
+
+INST "eim/eim/eim_cdc/cdc_sys_eim/src_ff" TNM = "TNM_from_sys_clk";
+INST "eim/eim/eim_cdc/cdc_sys_eim/src_latch*" TNM = "TNM_from_sys_clk";
+INST "eim/eim/eim_cdc/cdc_sys_eim/ff_sync*" TNM = "TNM_to_bclk";
+INST "eim/eim/eim_cdc/cdc_sys_eim/dst_latch*" TNM = "TNM_to_bclk";
+
+TIMESPEC "TS_bclk_2_sys_clk" = FROM "TNM_from_bclk" TO "TNM_to_sys_clk" TIG;
+TIMESPEC "TS_sys_clk_2_bclk" = FROM "TNM_from_sys_clk" TO "TNM_to_bclk" TIG;
+
+#======================================================================
+# EOF novena_baseline.ucf
+#======================================================================
diff --git a/novena/src/ucf/novena_i2c.ucf b/novena/src/ucf/novena_i2c.ucf
new file mode 100644
index 0000000..4f6f1f2
--- /dev/null
+++ b/novena/src/ucf/novena_i2c.ucf
@@ -0,0 +1,82 @@
+#======================================================================
+#
+# novena_baseline.ucf
+# -------------------
+# Constraint file for implementing the Cryptech Novena base
+# for the Xilinx Spartan6 LX45 on the Novena.
+#
+#
+# Author: Pavel Shatov
+# 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.
+#
+#======================================================================
+
+#-------------------------------------------------------------------------------
+CONFIG VCCAUX = 3.3;
+#-------------------------------------------------------------------------------
+
+
+#--------------------------------------------------------------------------------
+# GCLK Timing
+#--------------------------------------------------------------------------------
+NET "gclk_p_pin" TNM_NET = TNM_gclk;
+TIMESPEC TS_gclk = PERIOD TNM_gclk 20 ns HIGH 50%;
+
+
+#-------------------------------------------------------------------------------
+# FPGA Pinout
+#-------------------------------------------------------------------------------
+NET "led_pin" LOC = "A16" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 12;
+NET "apoptosis_pin" LOC = "K1" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 12;
+NET "reset_mcu_b_pin" LOC = "F1" | IOSTANDARD = "LVCMOS33" | PULLUP;
+
+NET "gclk_p_pin" LOC = "H2" | IOSTANDARD = "LVDS_33" | DIFF_TERM = "TRUE";
+NET "gclk_n_pin" LOC = "H1" | IOSTANDARD = "LVDS_33" | DIFF_TERM = "TRUE";
+
+NET "i2c_scl" LOC = "P4" | IOSTANDARD = LVCMOS33;
+NET "i2c_sda" LOC = "P3" | IOSTANDARD = LVCMOS33;
+
+# Pins to the header where the LEDs on the Cryptech
+# Avalanche Noise Board are connected.
+NET "ct_led<0>" LOC = K6 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<1>" LOC = H4 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<2>" LOC = H3 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<3>" LOC = M1 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<4>" LOC = L7 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<5>" LOC = G1 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<6>" LOC = T2 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+NET "ct_led<7>" LOC = H7 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
+
+# Pins to the header where the noise sources on the
+# Cryptech Avalanche Noise Board are connected.
+NET "ct_noise" LOC = L4 | IOSTANDARD = LVCMOS33;
+
+#======================================================================
+# EOF novena_baseline.ucf
+#======================================================================
diff --git a/sha1/LICENSE.txt b/sha1/LICENSE.txt
new file mode 100644
index 0000000..2acf230
--- /dev/null
+++ b/sha1/LICENSE.txt
@@ -0,0 +1,24 @@
+
+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:
+
+* 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.
+
+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/sha1/README.md b/sha1/README.md
new file mode 100644
index 0000000..f7eac7f
--- /dev/null
+++ b/sha1/README.md
@@ -0,0 +1,125 @@
+sha1
+====
+
+## Introduction ##
+Verilog implementation of the SHA-1 cryptgraphic hash function. The
+functionality follows the specification in NIST FIPS 180-4.
+
+The sha1 design is divided into the following sections.
+ - src/rtl - RTL source files
+ - src/tb - Testbenches for the RTL files
+ - src/model/python - Functional model written in python
+ - doc/ - documentation (currently not done.)
+ - toolruns/ - Where tools are supposed to be run. Includes a Makefile
+ for building and simulating the design using [Icarus
+ Verilog](http://iverilog.icarus.com/).
+
+The actual core consists of the following RTL files:
+ - sha1.v
+ - sha1_core.v
+ - sha1_w_mem.v
+
+The main core functionality is in the sha1_core file. The file
+sha1_w_mem contains the message block memory W (see FIPS 180-4).
+The top level entity is called sha1_core. The sha1_core module has wide
+interfaces (512 bit block input, 160 bit digest). In order to make it
+usable you probably want to wrap the core with a bus interface.
+
+The file sha1.v contains a top level wrapper that provides a simple
+interface with 32-bit data access . This interface contains mesage block
+and digest registers to allow a host to load the next block while the
+current block is being processed.
+
+## API ##
+The following list contains the address map for all registers
+implemented by the sha1 top level wrapper:
+
+| address | name | access | description |
+|---------|----------|--------|------------- |
+| 0x00 | name0 | R | "SHA1" |
+| 0x01 | name1 | R | " " |
+| 0x02 | version | R | "0.50" |
+| | | | |
+| 0x08 | control | R/W | Control of core. Bit 0: init, Bit 1: next |
+| 0x09 | status | R/W | Status of core. Bit 0: Ready, Bit 1: valid data |
+| | | | |
+| 0x10 | block0 | R/W | data block register |
+| 0x11 | block1 | R/W | data block register |
+| 0x12 | block2 | R/W | data block register |
+| 0x13 | block3 | R/W | data block register |
+| 0x14 | block4 | R/W | data block register |
+| 0x15 | block5 | R/W | data block register |
+| 0x16 | block6 | R/W | data block register |
+| 0x17 | block7 | R/W | data block register |
+| 0x18 | block8 | R/W | data block register |
+| 0x19 | block9 | R/W | data block register |
+| 0x1a | block10 | R/W | data block register |
+| 0x1b | block11 | R/W | data block register |
+| 0x1c | block12 | R/W | data block register |
+| 0x1d | block13 | R/W | data block register |
+| 0x1e | block14 | R/W | data block register |
+| 0x1f | block15 | R/W | data block register |
+| | | | |
+| 0x20 | digest0 | R/W | digest register |
+| 0x21 | digest1 | R/W | digest register |
+| 0x22 | digest2 | R/W | digest register |
+| 0x23 | digest3 | R/W | digest register |
+| 0x24 | digest4 | R/W | digest register |
+
+
+## Implementation details ##
+The implementation is iterative with one cycle/round. The initialization
+takes one cycle. The W memory is based around a sliding window of 16
+32-bit registers that are updated in sync with the round processing. The
+total latency/message block is 82 cycles.
+
+All registers have asynchronous reset.
+
+The design has been implemented and tested on TerasIC DE0-Nano and C5G
+FPGA boards.
+
+
+## Status ##
+The design has been implemented and extensively been tested on TerasIC
+DE0-Nano and C5G FPGA boards. The core has also been tested using SW
+running on The Novena CPU talking to the core in the Xilinx Spartan-6
+FPGA.
+
+
+## FPGA-results ##
+
+### Altera Cyclone FPGAs ###
+Implementation results using Altera Quartus-II 13.1.
+
+***Altera Cyclone IV E***
+- EP4CE6F17C6
+- 2913 LEs
+- 1527 regs
+- 107 MHz
+
+***Altera Cyclone IV GX***
+- EP4CGX22CF19C6
+- 2814 LEs
+- 1527 regs
+- 105 MHz
+
+***Altera Cyclone V***
+- 5CGXFC7C7F23C8
+- 1124 ALMs
+- 1527 regs
+- 104 MHz
+
+
+### Xilinx FPGAs ###
+Implementation results using ISE 14.7.
+
+** Xilinx Spartan-6 **
+- xc6slx45-3csg324
+- 1589 LUTs
+- 564 Slices
+- 1592 regs
+- 100 MHz
+
+
+## TODO ##
+* Documentation
diff --git a/sha1/src/model/python/sha1.py b/sha1/src/model/python/sha1.py
new file mode 100755
index 0000000..9bae18a
--- /dev/null
+++ b/sha1/src/model/python/sha1.py
@@ -0,0 +1,269 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#=======================================================================
+#
+# sha1.py
+# ---------
+# Simple, pure Python model of the SHA-1 function. Used as a
+# reference for the HW implementation. The code follows the structure
+# of the HW implementation as much as possible.
+#
+#
+# Author: Joachim Strömbergson
+# (c) 2014, SUNET
+#
+# 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.
+#-------------------------------------------------------------------
+
+
+#-------------------------------------------------------------------
+# ChaCha()
+#-------------------------------------------------------------------
+class SHA1():
+ def __init__(self, verbose = 0):
+ self.verbose = verbose
+ self.H = [0] * 5
+ self.T = 0
+ self.a = 0
+ self.b = 0
+ self.c = 0
+ self.d = 0
+ self.e = 0
+ self.W = [0] * 80
+ self.k = 0
+
+
+ def init(self):
+ self.H = [0x67452301, 0xefcdab89, 0x98badcfe,
+ 0x10325476, 0xc3d2e1f0]
+
+
+ def next(self, block):
+ self._W_schedule(block)
+ self._copy_digest()
+ for i in range(80):
+ self._sha1_round(i)
+ self._update_digest()
+
+
+ def get_digest(self):
+ return self.H
+
+
+ def _copy_digest(self):
+ self.a = self.H[0]
+ self.b = self.H[1]
+ self.c = self.H[2]
+ self.d = self.H[3]
+ self.e = self.H[4]
+
+
+ def _update_digest(self):
+ self.H[0] = (self.H[0] + self.a) & 0xffffffff
+ self.H[1] = (self.H[1] + self.b) & 0xffffffff
+ self.H[2] = (self.H[2] + self.c) & 0xffffffff
+ self.H[3] = (self.H[3] + self.d) & 0xffffffff
+ self.H[4] = (self.H[4] + self.e) & 0xffffffff
+
+
+ def _sha1_round(self, round):
+ if round <= 19:
+ self.k = 0x5a827999
+ self.f = self._Ch(self.b, self.c, self.d)
+
+ elif 20 <= round <= 39:
+ self.k = 0x6ed9eba1
+ self.f = self._Parity(self.b, self.c, self.d)
+
+ elif 40 <= round <= 59:
+ self.k = 0x8f1bbcdc
+ self.f = self._Maj(self.b, self.c, self.d)
+
+ elif 60 <= round <= 79:
+ self.k = 0xca62c1d6
+ self.f = self._Parity(self.b, self.c, self.d)
+
+ if self.verbose:
+ print("Round %0d" % round)
+ print("Round input values:")
+ print("a = 0x%08x, b = 0x%08x, c = 0x%08x" % (self.a, self.b, self.c))
+ print("d = 0x%08x, e = 0x%08x" % (self.d, self.e))
+ print("f = 0x%08x, k = 0x%08x, w = 0x%08x" % (self.f, self.k, self.W[round]))
+
+
+ self.T = (self._rotl32(self.a, 5) + self.f + self.e + self.k + self.W[round]) & 0xffffffff
+ self.e = self.d
+ self.d = self.c
+ self.c = self._rotl32(self.b, 30)
+ self.b = self.a
+ self.a = self.T
+
+ if self.verbose:
+ print("Round output values:")
+ print("a = 0x%08x, b = 0x%08x, c = 0x%08x" % (self.a, self.b, self.c))
+ print("d = 0x%08x, e = 0x%08x" % (self.d, self.e))
+ print("")
+
+
+ def _W_schedule(self, block):
+ # Expand the block into 80 words before round operations.
+ for i in range(80):
+ if (i < 16):
+ self.W[i] = block[i]
+ else:
+ self.W[i] = self._rotl32((self.W[(i - 3)] ^ self.W[(i - 8)] ^
+ self.W[(i - 14)] ^ self.W[(i - 16)]), 1)
+ if (self.verbose):
+ print("W after schedule:")
+ for i in range(80):
+ print("W[%02d] = 0x%08x" % (i, self.W[i]))
+ print("")
+
+
+ def _Ch(self, x, y, z):
+ return (x & y) ^ (~x & z)
+
+
+ def _Maj(self, x, y, z):
+ return (x & y) ^ (x & z) ^ (y & z)
+
+
+ def _Parity(self, x, y, z):
+ return (x ^ y ^ z)
+
+ def _rotl32(self, n, r):
+ return ((n << r) | (n >> (32 - r))) & 0xffffffff
+
+
+def compare_digests(digest, expected):
+ if (digest != expected):
+ print("Error:")
+ print("Got:")
+ print(digest)
+ print("Expected:")
+ print(expected)
+ else:
+ print("Test case ok.")
+
+
+#-------------------------------------------------------------------
+# main()
+#
+# If executed tests the ChaCha class using known test vectors.
+#-------------------------------------------------------------------
+def main():
+ print("Testing the SHA-1 Python model.")
+ print("-------------------------------")
+ print
+
+ my_sha1 = SHA1(verbose=0);
+
+ # TC1: NIST testcase with message "abc"
+ print("TC1: Single block NIST test case.")
+ TC1_block = [0x61626380, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000018]
+
+ TC1_expected = [0xa9993e36, 0x4706816a, 0xba3e2571,
+ 0x7850c26c, 0x9cd0d89d]
+ my_sha1.init()
+ my_sha1.next(TC1_block)
+ my_digest = my_sha1.get_digest()
+ compare_digests(my_digest, TC1_expected)
+ print("")
+
+
+ # TC2: NIST testcase with message two block message.
+ print("TC2: Dual block NIST test case.")
+ TC2_1_block = [0x61626364, 0x62636465, 0x63646566, 0x64656667,
+ 0x65666768, 0x66676869, 0x6768696A, 0x68696A6B,
+ 0x696A6B6C, 0x6A6B6C6D, 0x6B6C6D6E, 0x6C6D6E6F,
+ 0x6D6E6F70, 0x6E6F7071, 0x80000000, 0x00000000]
+
+
+ TC2_2_block = [0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x000001C0]
+
+ TC2_1_expected = [0xF4286818, 0xC37B27AE, 0x0408F581,
+ 0x84677148, 0x4A566572]
+
+ TC2_2_expected = [0x84983E44, 0x1C3BD26E, 0xBAAE4AA1,
+ 0xF95129E5, 0xE54670F1]
+
+ my_sha1.init()
+ my_sha1.next(TC2_1_block)
+ my_digest = my_sha1.get_digest()
+ compare_digests(my_digest, TC2_1_expected)
+ my_sha1.next(TC2_2_block)
+ my_digest = my_sha1.get_digest()
+ compare_digests(my_digest, TC2_2_expected)
+ print("")
+
+
+ # TC3: Huge message with n blocks
+ n = 10000
+ print("TC3: Huge message with %d blocks test case." % n)
+ TC3_block = [0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
+ 0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
+ 0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
+ 0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f]
+
+ TC3_expected = [0xea2ebc79, 0x35516705, 0xde1e1467,
+ 0x31e55587, 0xa0038725]
+
+ my_sha1.init()
+ for i in range(n):
+ my_sha1.next(TC3_block)
+ my_digest = my_sha1.get_digest()
+ compare_digests(my_digest, TC3_expected)
+
+
+#-------------------------------------------------------------------
+# __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 sha1.py
+#=======================================================================
diff --git a/sha1/src/rtl/sha1.v b/sha1/src/rtl/sha1.v
new file mode 100644
index 0000000..d0b4a4e
--- /dev/null
+++ b/sha1/src/rtl/sha1.v
@@ -0,0 +1,204 @@
+//======================================================================
+//
+// sha1.v
+// ------
+// Top level wrapper for the SHA-1 hash function providing
+// a simple memory like interface with 32 bit data access.
+//
+// Authors: Joachim Strömbergson, Paul Selkirk
+// Copyright (c) 2014-2015, 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 sha1(
+ // 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
+ );
+
+ //----------------------------------------------------------------
+ // 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_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_BLOCK = 8'h10;
+
+ parameter ADDR_DIGEST = 8'h20;
+
+ parameter CORE_NAME0 = 32'h73686131; // "sha1"
+ parameter CORE_NAME1 = 32'h20202020; // " "
+ parameter CORE_VERSION = 32'h302e3530; // "0.50"
+
+ parameter BLOCK_BITS = 512;
+ parameter DIGEST_BITS = 160;
+ parameter BLOCK_WORDS = BLOCK_BITS / 32;
+ parameter DIGEST_WORDS = DIGEST_BITS / 32;
+
+ //----------------------------------------------------------------
+ // Registers.
+ //----------------------------------------------------------------
+ reg [0 : BLOCK_BITS - 1] block_reg;
+ reg [0 : DIGEST_BITS - 1] digest_reg;
+ reg init_reg;
+ reg next_reg;
+
+ reg [31 : 0] tmp_read_data;
+ reg [31 : 0] tmp_read_data_reg;
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ wire core_init;
+ wire core_next;
+ wire core_ready;
+ wire [0 : BLOCK_BITS - 1] core_block;
+ wire [0 : DIGEST_BITS - 1] core_digest;
+ wire core_digest_valid;
+
+ wire [31 : 0] core_name0 = CORE_NAME0;
+ wire [31 : 0] core_name1 = CORE_NAME1;
+ wire [31 : 0] core_version = CORE_VERSION;
+ wire [31 : 0] core_ctrl;
+ wire [31 : 0] core_status;
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign core_init = init_reg;
+ assign core_next = next_reg;
+ assign core_ctrl = { 30'b0, next_reg, init_reg };
+ assign core_status = { 30'b0, core_digest_valid, core_ready };
+ assign core_block = block_reg;
+
+ assign read_data = tmp_read_data_reg;
+
+ //----------------------------------------------------------------
+ // core instantiation.
+ //----------------------------------------------------------------
+ sha1_core core(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .init(core_init),
+ .next(core_next),
+
+ .block(core_block),
+
+ .ready(core_ready),
+
+ .digest(core_digest),
+ .digest_valid(core_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // latch in digest when ready
+ //----------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (core_digest_valid)
+ digest_reg <= core_digest;
+ end
+
+ //----------------------------------------------------------------
+ // storage registers for mapping memory to core interface
+ //----------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ init_reg <= 0;
+ next_reg <= 0;
+
+ if (cs && we)
+ begin
+ // write operations
+ if ((address >= ADDR_BLOCK) &&
+ (address < ADDR_BLOCK + BLOCK_WORDS))
+ block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data;
+ else if (address == ADDR_CTRL)
+ begin
+ init_reg <= write_data[CTRL_INIT_BIT];
+ next_reg <= write_data[CTRL_NEXT_BIT];
+ end
+ end
+ end
+
+ always @*
+ begin
+ tmp_read_data = 32'h00000000;
+
+ if (cs && !we)
+ begin
+ // read operations
+ if ((address >= ADDR_BLOCK) &&
+ (address < ADDR_BLOCK + BLOCK_WORDS))
+ tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32];
+ else if ((address >= ADDR_DIGEST) &&
+ (address < ADDR_DIGEST + DIGEST_WORDS))
+ tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32];
+ else
+ case (address)
+ ADDR_NAME0:
+ tmp_read_data = core_name0;
+ ADDR_NAME1:
+ tmp_read_data = core_name1;
+ ADDR_VERSION:
+ tmp_read_data = core_version;
+ ADDR_CTRL:
+ tmp_read_data = core_ctrl;
+ ADDR_STATUS:
+ tmp_read_data = core_status;
+ endcase
+ end
+ end
+
+ always @(posedge clk)
+ begin
+ tmp_read_data_reg <= tmp_read_data;
+ end
+
+endmodule // sha1
diff --git a/sha1/src/rtl/sha1_core.v b/sha1/src/rtl/sha1_core.v
new file mode 100644
index 0000000..78fe2b9
--- /dev/null
+++ b/sha1/src/rtl/sha1_core.v
@@ -0,0 +1,443 @@
+//======================================================================
+//
+// sha1_core.v
+// -----------
+// Verilog 2001 implementation of the SHA-1 hash function.
+// This is the internal core with wide interfaces.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014 SUNET
+//
+// 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 sha1_core(
+ input wire clk,
+ input wire reset_n,
+
+ input wire init,
+ input wire next,
+
+ input wire [511 : 0] block,
+
+ output wire ready,
+
+ output wire [159 : 0] digest,
+ output wire digest_valid
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter H0_0 = 32'h67452301;
+ parameter H0_1 = 32'hefcdab89;
+ parameter H0_2 = 32'h98badcfe;
+ parameter H0_3 = 32'h10325476;
+ parameter H0_4 = 32'hc3d2e1f0;
+
+ parameter SHA1_ROUNDS = 79;
+
+ parameter CTRL_IDLE = 0;
+ parameter CTRL_ROUNDS = 1;
+ parameter CTRL_DIGEST = 2;
+ parameter CTRL_DONE = 3;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] a_reg;
+ reg [31 : 0] a_new;
+ reg [31 : 0] b_reg;
+ reg [31 : 0] b_new;
+ reg [31 : 0] c_reg;
+ reg [31 : 0] c_new;
+ reg [31 : 0] d_reg;
+ reg [31 : 0] d_new;
+ reg [31 : 0] e_reg;
+ reg [31 : 0] e_new;
+ reg a_e_we;
+
+ reg [31 : 0] H0_reg;
+ reg [31 : 0] H0_new;
+ reg [31 : 0] H1_reg;
+ reg [31 : 0] H1_new;
+ reg [31 : 0] H2_reg;
+ reg [31 : 0] H2_new;
+ reg [31 : 0] H3_reg;
+ reg [31 : 0] H3_new;
+ reg [31 : 0] H4_reg;
+ reg [31 : 0] H4_new;
+ reg H_we;
+
+ reg [6 : 0] round_ctr_reg;
+ reg [6 : 0] round_ctr_new;
+ reg round_ctr_we;
+ reg round_ctr_inc;
+ reg round_ctr_rst;
+
+ reg digest_valid_reg;
+ reg digest_valid_new;
+ reg digest_valid_we;
+
+ reg [1 : 0] sha1_ctrl_reg;
+ reg [1 : 0] sha1_ctrl_new;
+ reg sha1_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg digest_init;
+ reg digest_update;
+ reg state_init;
+ reg state_update;
+ reg first_block;
+ reg ready_flag;
+ reg w_init;
+ reg w_next;
+ wire [31 : 0] w;
+
+
+ //----------------------------------------------------------------
+ // Module instantiantions.
+ //----------------------------------------------------------------
+ sha1_w_mem w_mem_inst(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .block(block),
+
+ .init(w_init),
+ .next(w_next),
+
+ .w(w)
+ );
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign ready = ready_flag;
+ assign digest = {H0_reg, H1_reg, H2_reg, H3_reg, H4_reg};
+ assign digest_valid = digest_valid_reg;
+
+
+ //----------------------------------------------------------------
+ // 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 : reg_update
+ if (!reset_n)
+ begin
+ a_reg <= 32'h00000000;
+ b_reg <= 32'h00000000;
+ c_reg <= 32'h00000000;
+ d_reg <= 32'h00000000;
+ e_reg <= 32'h00000000;
+ H0_reg <= 32'h00000000;
+ H1_reg <= 32'h00000000;
+ H2_reg <= 32'h00000000;
+ H3_reg <= 32'h00000000;
+ H4_reg <= 32'h00000000;
+ digest_valid_reg <= 0;
+ round_ctr_reg <= 7'b0000000;
+ sha1_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ if (a_e_we)
+ begin
+ a_reg <= a_new;
+ b_reg <= b_new;
+ c_reg <= c_new;
+ d_reg <= d_new;
+ e_reg <= e_new;
+ end
+
+ if (H_we)
+ begin
+ H0_reg <= H0_new;
+ H1_reg <= H1_new;
+ H2_reg <= H2_new;
+ H3_reg <= H3_new;
+ H4_reg <= H4_new;
+ end
+
+ if (round_ctr_we)
+ begin
+ round_ctr_reg <= round_ctr_new;
+ end
+
+ if (digest_valid_we)
+ begin
+ digest_valid_reg <= digest_valid_new;
+ end
+
+ if (sha1_ctrl_we)
+ begin
+ sha1_ctrl_reg <= sha1_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // digest_logic
+ //
+ // The logic needed to init as well as update the digest.
+ //----------------------------------------------------------------
+ always @*
+ begin : digest_logic
+ H0_new = 32'h00000000;
+ H1_new = 32'h00000000;
+ H2_new = 32'h00000000;
+ H3_new = 32'h00000000;
+ H4_new = 32'h00000000;
+ H_we = 0;
+
+ if (digest_init)
+ begin
+ H0_new = H0_0;
+ H1_new = H0_1;
+ H2_new = H0_2;
+ H3_new = H0_3;
+ H4_new = H0_4;
+ H_we = 1;
+ end
+
+ if (digest_update)
+ begin
+ H0_new = H0_reg + a_reg;
+ H1_new = H1_reg + b_reg;
+ H2_new = H2_reg + c_reg;
+ H3_new = H3_reg + d_reg;
+ H4_new = H4_reg + e_reg;
+ H_we = 1;
+ end
+ end // digest_logic
+
+
+ //----------------------------------------------------------------
+ // state_logic
+ //
+ // The logic needed to init as well as update the state during
+ // round processing.
+ //----------------------------------------------------------------
+ always @*
+ begin : state_logic
+ reg [31 : 0] a5;
+ reg [31 : 0] f;
+ reg [31 : 0] k;
+ reg [31 : 0] t;
+
+ a5 = 32'h00000000;
+ f = 32'h00000000;
+ k = 32'h00000000;
+ t = 32'h00000000;
+ a_new = 32'h00000000;
+ b_new = 32'h00000000;
+ c_new = 32'h00000000;
+ d_new = 32'h00000000;
+ e_new = 32'h00000000;
+ a_e_we = 0;
+
+ if (state_init)
+ begin
+ if (first_block)
+ begin
+ a_new = H0_0;
+ b_new = H0_1;
+ c_new = H0_2;
+ d_new = H0_3;
+ e_new = H0_4;
+ a_e_we = 1;
+ end
+ else
+ begin
+ a_new = H0_reg;
+ b_new = H1_reg;
+ c_new = H2_reg;
+ d_new = H3_reg;
+ e_new = H4_reg;
+ a_e_we = 1;
+ end
+ end
+
+ if (state_update)
+ begin
+ if (round_ctr_reg <= 19)
+ begin
+ k = 32'h5a827999;
+ f = ((b_reg & c_reg) ^ (~b_reg & d_reg));
+ end
+ else if ((round_ctr_reg >= 20) && (round_ctr_reg <= 39))
+ begin
+ k = 32'h6ed9eba1;
+ f = b_reg ^ c_reg ^ d_reg;
+ end
+ else if ((round_ctr_reg >= 40) && (round_ctr_reg <= 59))
+ begin
+ k = 32'h8f1bbcdc;
+ f = ((b_reg | c_reg) ^ (b_reg | d_reg) ^ (c_reg | d_reg));
+ end
+ else if (round_ctr_reg >= 60)
+ begin
+ k = 32'hca62c1d6;
+ f = b_reg ^ c_reg ^ d_reg;
+ end
+
+ a5 = {a_reg[26 : 0], a_reg[31 : 27]};
+ t = a5 + e_reg + f + k + w;
+
+ a_new = t;
+ b_new = a_reg;
+ c_new = {b_reg[1 : 0], b_reg[31 : 2]};
+ d_new = c_reg;
+ e_new = d_reg;
+ a_e_we = 1;
+ end
+ end // state_logic
+
+
+ //----------------------------------------------------------------
+ // round_ctr
+ //
+ // Update logic for the round counter, a monotonically
+ // increasing counter with reset.
+ //----------------------------------------------------------------
+ always @*
+ begin : round_ctr
+ round_ctr_new = 0;
+ round_ctr_we = 0;
+
+ if (round_ctr_rst)
+ begin
+ round_ctr_new = 0;
+ round_ctr_we = 1;
+ end
+
+ if (round_ctr_inc)
+ begin
+ round_ctr_new = round_ctr_reg + 1'b1;
+ round_ctr_we = 1;
+ end
+ end // round_ctr
+
+
+ //----------------------------------------------------------------
+ // sha1_ctrl_fsm
+ // Logic for the state machine controlling the core behaviour.
+ //----------------------------------------------------------------
+ always @*
+ begin : sha1_ctrl_fsm
+ digest_init = 0;
+ digest_update = 0;
+ state_init = 0;
+ state_update = 0;
+ first_block = 0;
+ ready_flag = 0;
+ w_init = 0;
+ w_next = 0;
+ round_ctr_inc = 0;
+ round_ctr_rst = 0;
+ digest_valid_new = 0;
+ digest_valid_we = 0;
+ sha1_ctrl_new = CTRL_IDLE;
+ sha1_ctrl_we = 0;
+
+ case (sha1_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ ready_flag = 1;
+
+ if (init)
+ begin
+ digest_init = 1;
+ w_init = 1;
+ state_init = 1;
+ first_block = 1;
+ round_ctr_rst = 1;
+ digest_valid_new = 0;
+ digest_valid_we = 1;
+ sha1_ctrl_new = CTRL_ROUNDS;
+ sha1_ctrl_we = 1;
+ end
+
+ if (next)
+ begin
+ w_init = 1;
+ state_init = 1;
+ round_ctr_rst = 1;
+ digest_valid_new = 0;
+ digest_valid_we = 1;
+ sha1_ctrl_new = CTRL_ROUNDS;
+ sha1_ctrl_we = 1;
+ end
+ end
+
+
+ CTRL_ROUNDS:
+ begin
+ state_update = 1;
+ round_ctr_inc = 1;
+ w_next = 1;
+
+ if (round_ctr_reg == SHA1_ROUNDS)
+ begin
+ sha1_ctrl_new = CTRL_DIGEST;
+ sha1_ctrl_we = 1;
+ end
+ end
+
+ CTRL_DIGEST:
+ begin
+ digest_update = 1;
+ sha1_ctrl_new = CTRL_DONE;
+ sha1_ctrl_we = 1;
+ end
+
+ CTRL_DONE:
+ begin
+ digest_valid_new = 1;
+ digest_valid_we = 1;
+ sha1_ctrl_new = CTRL_IDLE;
+ sha1_ctrl_we = 1;
+ end
+ endcase // case (sha1_ctrl_reg)
+ end // sha1_ctrl_fsm
+
+endmodule // sha1_core
+
+//======================================================================
+// EOF sha1_core.v
+//======================================================================
diff --git a/sha1/src/rtl/sha1_w_mem.v b/sha1/src/rtl/sha1_w_mem.v
new file mode 100644
index 0000000..cafb35c
--- /dev/null
+++ b/sha1/src/rtl/sha1_w_mem.v
@@ -0,0 +1,343 @@
+//======================================================================
+//
+// sha1_w_mem_reg.v
+// -----------------
+// The SHA-1 W memory. This memory is based around a sliding window
+// of 16 32-bit registers that are used to create the w words
+// needed by the core during the 80 rounds.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014 SUNET
+//
+// 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 sha1_w_mem(
+ input wire clk,
+ input wire reset_n,
+
+ input wire [511 : 0] block,
+
+ input wire init,
+ input wire next,
+
+ output wire [31 : 0] w
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter SHA1_ROUNDS = 79;
+
+ parameter CTRL_IDLE = 1'b0;
+ parameter CTRL_UPDATE = 1'b1;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] w_mem [0 : 15];
+ reg [31 : 0] w_mem00_new;
+ reg [31 : 0] w_mem01_new;
+ reg [31 : 0] w_mem02_new;
+ reg [31 : 0] w_mem03_new;
+ reg [31 : 0] w_mem04_new;
+ reg [31 : 0] w_mem05_new;
+ reg [31 : 0] w_mem06_new;
+ reg [31 : 0] w_mem07_new;
+ reg [31 : 0] w_mem08_new;
+ reg [31 : 0] w_mem09_new;
+ reg [31 : 0] w_mem10_new;
+ reg [31 : 0] w_mem11_new;
+ reg [31 : 0] w_mem12_new;
+ reg [31 : 0] w_mem13_new;
+ reg [31 : 0] w_mem14_new;
+ reg [31 : 0] w_mem15_new;
+ reg w_mem_we;
+
+ reg [6 : 0] w_ctr_reg;
+ reg [6 : 0] w_ctr_new;
+ reg w_ctr_we;
+ reg w_ctr_inc;
+ reg w_ctr_rst;
+
+ reg sha1_w_mem_ctrl_reg;
+ reg sha1_w_mem_ctrl_new;
+ reg sha1_w_mem_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] w_tmp;
+ reg [31 : 0] w_new;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign w = w_tmp;
+
+
+ //----------------------------------------------------------------
+ // 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 : reg_update
+ if (!reset_n)
+ begin
+ w_mem[00] <= 32'h00000000;
+ w_mem[01] <= 32'h00000000;
+ w_mem[02] <= 32'h00000000;
+ w_mem[03] <= 32'h00000000;
+ w_mem[04] <= 32'h00000000;
+ w_mem[05] <= 32'h00000000;
+ w_mem[06] <= 32'h00000000;
+ w_mem[07] <= 32'h00000000;
+ w_mem[08] <= 32'h00000000;
+ w_mem[09] <= 32'h00000000;
+ w_mem[10] <= 32'h00000000;
+ w_mem[11] <= 32'h00000000;
+ w_mem[12] <= 32'h00000000;
+ w_mem[13] <= 32'h00000000;
+ w_mem[14] <= 32'h00000000;
+ w_mem[15] <= 32'h00000000;
+ w_ctr_reg <= 7'h00;
+ sha1_w_mem_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ if (w_mem_we)
+ begin
+ w_mem[00] <= w_mem00_new;
+ w_mem[01] <= w_mem01_new;
+ w_mem[02] <= w_mem02_new;
+ w_mem[03] <= w_mem03_new;
+ w_mem[04] <= w_mem04_new;
+ w_mem[05] <= w_mem05_new;
+ w_mem[06] <= w_mem06_new;
+ w_mem[07] <= w_mem07_new;
+ w_mem[08] <= w_mem08_new;
+ w_mem[09] <= w_mem09_new;
+ w_mem[10] <= w_mem10_new;
+ w_mem[11] <= w_mem11_new;
+ w_mem[12] <= w_mem12_new;
+ w_mem[13] <= w_mem13_new;
+ w_mem[14] <= w_mem14_new;
+ w_mem[15] <= w_mem15_new;
+ end
+
+ if (w_ctr_we)
+ begin
+ w_ctr_reg <= w_ctr_new;
+ end
+
+ if (sha1_w_mem_ctrl_we)
+ begin
+ sha1_w_mem_ctrl_reg <= sha1_w_mem_ctrl_new;
+ end
+
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // select_w
+ //
+ // W word selection logic. Returns either directly from the
+ // memory or the next w value calculated.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_schedule
+ if (w_ctr_reg < 16)
+ begin
+ w_tmp = w_mem[w_ctr_reg[3 : 0]];
+ end
+ else
+ begin
+ w_tmp = w_new;
+ end
+ end // w_schedule
+
+
+ //----------------------------------------------------------------
+ // w_mem_update_logic
+ //
+ // Update logic for the W memory. This is where the scheduling
+ // based on a sliding window is implemented.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_mem_update_logic
+ reg [31 : 0] w_0;
+ reg [31 : 0] w_2;
+ reg [31 : 0] w_8;
+ reg [31 : 0] w_13;
+ reg [31 : 0] w_16;
+
+ w_mem00_new = 32'h00000000;
+ w_mem01_new = 32'h00000000;
+ w_mem02_new = 32'h00000000;
+ w_mem03_new = 32'h00000000;
+ w_mem04_new = 32'h00000000;
+ w_mem05_new = 32'h00000000;
+ w_mem06_new = 32'h00000000;
+ w_mem07_new = 32'h00000000;
+ w_mem08_new = 32'h00000000;
+ w_mem09_new = 32'h00000000;
+ w_mem10_new = 32'h00000000;
+ w_mem11_new = 32'h00000000;
+ w_mem12_new = 32'h00000000;
+ w_mem13_new = 32'h00000000;
+ w_mem14_new = 32'h00000000;
+ w_mem15_new = 32'h00000000;
+ w_mem_we = 0;
+
+ w_0 = w_mem[0];
+ w_2 = w_mem[2];
+ w_8 = w_mem[8];
+ w_13 = w_mem[13];
+ w_16 = w_13 ^ w_8 ^ w_2 ^ w_0;
+ w_new = {w_16[30 : 0], w_16[31]};
+
+ if (init)
+ begin
+ w_mem00_new = block[511 : 480];
+ w_mem01_new = block[479 : 448];
+ w_mem02_new = block[447 : 416];
+ w_mem03_new = block[415 : 384];
+ w_mem04_new = block[383 : 352];
+ w_mem05_new = block[351 : 320];
+ w_mem06_new = block[319 : 288];
+ w_mem07_new = block[287 : 256];
+ w_mem08_new = block[255 : 224];
+ w_mem09_new = block[223 : 192];
+ w_mem10_new = block[191 : 160];
+ w_mem11_new = block[159 : 128];
+ w_mem12_new = block[127 : 96];
+ w_mem13_new = block[95 : 64];
+ w_mem14_new = block[63 : 32];
+ w_mem15_new = block[31 : 0];
+ w_mem_we = 1;
+ end
+
+ else if (w_ctr_reg > 15)
+ begin
+ w_mem00_new = w_mem[01];
+ w_mem01_new = w_mem[02];
+ w_mem02_new = w_mem[03];
+ w_mem03_new = w_mem[04];
+ w_mem04_new = w_mem[05];
+ w_mem05_new = w_mem[06];
+ w_mem06_new = w_mem[07];
+ w_mem07_new = w_mem[08];
+ w_mem08_new = w_mem[09];
+ w_mem09_new = w_mem[10];
+ w_mem10_new = w_mem[11];
+ w_mem11_new = w_mem[12];
+ w_mem12_new = w_mem[13];
+ w_mem13_new = w_mem[14];
+ w_mem14_new = w_mem[15];
+ w_mem15_new = w_new;
+ w_mem_we = 1;
+ end
+ end // w_mem_update_logic
+
+
+ //----------------------------------------------------------------
+ // w_ctr
+ //
+ // W schedule adress counter. Counts from 0x10 to 0x3f and
+ // is used to expand the block into words.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_ctr
+ w_ctr_new = 7'h00;
+ w_ctr_we = 0;
+
+ if (w_ctr_rst)
+ begin
+ w_ctr_new = 7'h00;
+ w_ctr_we = 1;
+ end
+
+ if (w_ctr_inc)
+ begin
+ w_ctr_new = w_ctr_reg + 7'h01;
+ w_ctr_we = 1;
+ end
+ end // w_ctr
+
+
+ //----------------------------------------------------------------
+ // sha1_w_mem_fsm
+ //
+ // Logic for the w shedule FSM.
+ //----------------------------------------------------------------
+ always @*
+ begin : sha1_w_mem_fsm
+ w_ctr_rst = 0;
+ w_ctr_inc = 0;
+ sha1_w_mem_ctrl_new = CTRL_IDLE;
+ sha1_w_mem_ctrl_we = 0;
+
+ case (sha1_w_mem_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (init)
+ begin
+ w_ctr_rst = 1;
+ sha1_w_mem_ctrl_new = CTRL_UPDATE;
+ sha1_w_mem_ctrl_we = 1;
+ end
+ end
+
+ CTRL_UPDATE:
+ begin
+ if (next)
+ begin
+ w_ctr_inc = 1;
+ end
+
+ if (w_ctr_reg == SHA1_ROUNDS)
+ begin
+ sha1_w_mem_ctrl_new = CTRL_IDLE;
+ sha1_w_mem_ctrl_we = 1;
+ end
+ end
+ endcase // case (sha1_ctrl_reg)
+ end // sha1_ctrl_fsm
+endmodule // sha1_w_mem
+
+//======================================================================
+// sha1_w_mem.v
+//======================================================================
diff --git a/sha1/src/tb/tb_sha1.v b/sha1/src/tb/tb_sha1.v
new file mode 100644
index 0000000..abf25d2
--- /dev/null
+++ b/sha1/src/tb/tb_sha1.v
@@ -0,0 +1,589 @@
+//======================================================================
+//
+// tb_sha1.v
+// ---------
+// Testbench for the SHA-1 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/10ps
+
+module tb_sha1();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG_CORE = 0;
+ parameter DEBUG_TOP = 0;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = CLK_HALF_PERIOD * 2;
+
+ 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_INIT_VALUE = 8'h01;
+ parameter CTRL_NEXT_VALUE = 8'h02;
+
+ parameter ADDR_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_BLOCK0 = 8'h10;
+ parameter ADDR_BLOCK1 = 8'h11;
+ parameter ADDR_BLOCK2 = 8'h12;
+ parameter ADDR_BLOCK3 = 8'h13;
+ parameter ADDR_BLOCK4 = 8'h14;
+ parameter ADDR_BLOCK5 = 8'h15;
+ parameter ADDR_BLOCK6 = 8'h16;
+ parameter ADDR_BLOCK7 = 8'h17;
+ parameter ADDR_BLOCK8 = 8'h18;
+ parameter ADDR_BLOCK9 = 8'h19;
+ parameter ADDR_BLOCK10 = 8'h1a;
+ parameter ADDR_BLOCK11 = 8'h1b;
+ parameter ADDR_BLOCK12 = 8'h1c;
+ parameter ADDR_BLOCK13 = 8'h1d;
+ parameter ADDR_BLOCK14 = 8'h1e;
+ parameter ADDR_BLOCK15 = 8'h1f;
+
+ parameter ADDR_DIGEST0 = 8'h20;
+ parameter ADDR_DIGEST1 = 8'h21;
+ parameter ADDR_DIGEST2 = 8'h22;
+ parameter ADDR_DIGEST3 = 8'h23;
+ parameter ADDR_DIGEST4 = 8'h24;
+
+
+ //----------------------------------------------------------------
+ // 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_write_read;
+ reg [7 : 0] tb_address;
+ reg [31 : 0] tb_data_in;
+ wire [31 : 0] tb_data_out;
+
+ reg [31 : 0] read_data;
+ reg [159 : 0] digest_data;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha1 dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .cs(tb_cs),
+ .we(tb_write_read),
+
+ .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
+
+
+ //----------------------------------------------------------------
+ // sys_monitor
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ if (DEBUG_CORE)
+ begin
+ dump_core_state();
+ end
+
+ if (DEBUG_TOP)
+ begin
+ dump_top_state();
+ end
+
+ #(CLK_PERIOD);
+ cycle_ctr = cycle_ctr + 1;
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_top_state()
+ //
+ // Dump state of the the top of the dut.
+ //----------------------------------------------------------------
+ task dump_top_state();
+ begin
+ $display("State of top");
+ $display("-------------");
+ $display("Inputs and outputs:");
+ $display("cs = 0x%01x, we = 0x%01x", dut.cs, dut.we);
+ $display("address = 0x%02x, write_data = 0x%08x", dut.address, dut.write_data);
+ $display("error = 0x%01x, read_data = 0x%08x", dut.error, dut.read_data);
+ $display("");
+
+ $display("Control and status flags:");
+ $display("init = 0x%01x, next = 0x%01x, ready = 0x%01x",
+ dut.init_reg, dut.next_reg, dut.ready_reg);
+ $display("");
+
+ $display("block registers:");
+ $display("block0_reg = 0x%08x, block1_reg = 0x%08x, block2_reg = 0x%08x, block3_reg = 0x%08x",
+ dut.block0_reg, dut.block1_reg, dut.block2_reg, dut.block3_reg);
+
+ $display("block4_reg = 0x%08x, block5_reg = 0x%08x, block6_reg = 0x%08x, block7_reg = 0x%08x",
+ dut.block4_reg, dut.block5_reg, dut.block6_reg, dut.block7_reg);
+
+ $display("block8_reg = 0x%08x, block9_reg = 0x%08x, block10_reg = 0x%08x, block11_reg = 0x%08x",
+ dut.block8_reg, dut.block9_reg, dut.block10_reg, dut.block11_reg);
+
+ $display("block12_reg = 0x%08x, block13_reg = 0x%08x, block14_reg = 0x%08x, block15_reg = 0x%08x",
+ dut.block12_reg, dut.block13_reg, dut.block14_reg, dut.block15_reg);
+ $display("");
+
+ $display("Digest registers:");
+ $display("digest_reg = 0x%040x", dut.digest_reg);
+ $display("");
+ end
+ endtask // dump_top_state
+
+
+ //----------------------------------------------------------------
+ // dump_core_state()
+ //
+ // Dump the state of the core inside the dut.
+ //----------------------------------------------------------------
+ task dump_core_state();
+ begin
+ $display("State of core");
+ $display("-------------");
+ $display("Inputs and outputs:");
+ $display("init = 0x%01x, next = 0x%01x",
+ dut.core.init, dut.core.next);
+ $display("block = 0x%0128x", dut.core.block);
+
+ $display("ready = 0x%01x, valid = 0x%01x",
+ dut.core.ready, dut.core.digest_valid);
+ $display("digest = 0x%040x", dut.core.digest);
+ $display("H0_reg = 0x%08x, H1_reg = 0x%08x, H2_reg = 0x%08x, H3_reg = 0x%08x, H4_reg = 0x%08x",
+ dut.core.H0_reg, dut.core.H1_reg, dut.core.H2_reg, dut.core.H3_reg, dut.core.H4_reg);
+ $display("");
+
+ $display("Control signals and counter:");
+ $display("sha1_ctrl_reg = 0x%01x", dut.core.sha1_ctrl_reg);
+ $display("digest_init = 0x%01x, digest_update = 0x%01x",
+ dut.core.digest_init, dut.core.digest_update);
+ $display("state_init = 0x%01x, state_update = 0x%01x",
+ dut.core.state_init, dut.core.state_update);
+ $display("first_block = 0x%01x, ready_flag = 0x%01x, w_init = 0x%01x",
+ dut.core.first_block, dut.core.ready_flag, dut.core.w_init);
+ $display("round_ctr_inc = 0x%01x, round_ctr_rst = 0x%01x, round_ctr_reg = 0x%02x",
+ dut.core.round_ctr_inc, dut.core.round_ctr_rst, dut.core.round_ctr_reg);
+ $display("");
+
+ $display("State registers:");
+ $display("a_reg = 0x%08x, b_reg = 0x%08x, c_reg = 0x%08x, d_reg = 0x%08x, e_reg = 0x%08x",
+ dut.core.a_reg, dut.core.b_reg, dut.core.c_reg, dut.core.d_reg, dut.core.e_reg);
+ $display("a_new = 0x%08x, b_new = 0x%08x, c_new = 0x%08x, d_new = 0x%08x, e_new = 0x%08x",
+ dut.core.a_new, dut.core.b_new, dut.core.c_new, dut.core.d_new, dut.core.e_new);
+ $display("");
+
+ $display("State update values:");
+ $display("f = 0x%08x, k = 0x%08x, t = 0x%08x, w = 0x%08x,",
+ dut.core.state_logic.f, dut.core.state_logic.k, dut.core.state_logic.t, dut.core.w);
+ $display("");
+ end
+ endtask // dump_core_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(4 * CLK_HALF_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 = 32'h00000000;
+ error_ctr = 32'h00000000;
+ tc_ctr = 32'h00000000;
+
+ tb_clk = 0;
+ tb_reset_n = 0;
+ tb_cs = 0;
+ tb_write_read = 0;
+ tb_address = 6'h00;
+ tb_data_in = 32'h00000000;
+ end
+ endtask // init_dut
+
+
+ //----------------------------------------------------------------
+ // 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 completed.", tc_ctr);
+ $display("*** %02d errors detected during testing.", error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ // (Actually we wait for either ready or valid 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
+ read_data = 0;
+
+ while (read_data == 0)
+ begin
+ read_word(ADDR_STATUS);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // 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 [7 : 0] address);
+ begin
+ tb_address = address;
+ tb_cs = 1;
+ tb_write_read = 0;
+ #(CLK_PERIOD);
+ read_data = tb_data_out;
+ tb_cs = 0;
+
+ if (DEBUG_TOP)
+ begin
+ $display("*** Reading 0x%08x from 0x%02x.", read_data, address);
+ $display("");
+ end
+ end
+ endtask // read_word
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [7 : 0] address,
+ input [31 : 0] word);
+ begin
+ if (DEBUG_TOP)
+ begin
+ $display("*** Writing 0x%08x to 0x%02x.", word, address);
+ $display("");
+ end
+
+ tb_address = address;
+ tb_data_in = word;
+ tb_cs = 1;
+ tb_write_read = 1;
+ #(CLK_PERIOD);
+ tb_cs = 0;
+ tb_write_read = 0;
+ end
+ endtask // write_word
+
+
+ //----------------------------------------------------------------
+ // write_block()
+ //
+ // Write the given block to the dut.
+ //----------------------------------------------------------------
+ task write_block(input [511 : 0] block);
+ begin
+ write_word(ADDR_BLOCK0, block[511 : 480]);
+ write_word(ADDR_BLOCK1, block[479 : 448]);
+ write_word(ADDR_BLOCK2, block[447 : 416]);
+ write_word(ADDR_BLOCK3, block[415 : 384]);
+ write_word(ADDR_BLOCK4, block[383 : 352]);
+ write_word(ADDR_BLOCK5, block[351 : 320]);
+ write_word(ADDR_BLOCK6, block[319 : 288]);
+ write_word(ADDR_BLOCK7, block[287 : 256]);
+ write_word(ADDR_BLOCK8, block[255 : 224]);
+ write_word(ADDR_BLOCK9, block[223 : 192]);
+ write_word(ADDR_BLOCK10, block[191 : 160]);
+ write_word(ADDR_BLOCK11, block[159 : 128]);
+ write_word(ADDR_BLOCK12, block[127 : 96]);
+ write_word(ADDR_BLOCK13, block[95 : 64]);
+ write_word(ADDR_BLOCK14, block[63 : 32]);
+ write_word(ADDR_BLOCK15, block[31 : 0]);
+ end
+ endtask // write_block
+
+
+ //----------------------------------------------------------------
+ // check_name_version()
+ //
+ // Read the name and version from the DUT.
+ //----------------------------------------------------------------
+ task check_name_version();
+ reg [31 : 0] name0;
+ reg [31 : 0] name1;
+ reg [31 : 0] version;
+ begin
+
+ read_word(ADDR_NAME0);
+ name0 = read_data;
+ read_word(ADDR_NAME1);
+ name1 = read_data;
+ read_word(ADDR_VERSION);
+ version = read_data;
+
+ $display("DUT name: %c%c%c%c%c%c%c%c",
+ name0[31 : 24], name0[23 : 16], name0[15 : 8], name0[7 : 0],
+ name1[31 : 24], name1[23 : 16], name1[15 : 8], name1[7 : 0]);
+ $display("DUT version: %c%c%c%c",
+ version[31 : 24], version[23 : 16], version[15 : 8], version[7 : 0]);
+ end
+ endtask // check_name_version
+
+
+ //----------------------------------------------------------------
+ // read_digest()
+ //
+ // Read the digest in the dut. The resulting digest will be
+ // available in the global variable digest_data.
+ //----------------------------------------------------------------
+ task read_digest();
+ begin
+ read_word(ADDR_DIGEST0);
+ digest_data[159 : 128] = read_data;
+ read_word(ADDR_DIGEST1);
+ digest_data[127 : 96] = read_data;
+ read_word(ADDR_DIGEST2);
+ digest_data[95 : 64] = read_data;
+ read_word(ADDR_DIGEST3);
+ digest_data[63 : 32] = read_data;
+ read_word(ADDR_DIGEST4);
+ digest_data[31 : 0] = read_data;
+ end
+ endtask // read_digest
+
+
+ //----------------------------------------------------------------
+ // single_block_test()
+ //
+ //
+ // Perform test of a single block digest.
+ //----------------------------------------------------------------
+ task single_block_test(input [511 : 0] block,
+ input [159 : 0] expected
+ );
+ begin
+ $display("*** TC%01d - Single block test started.", tc_ctr);
+
+ write_block(block);
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ if (digest_data == expected)
+ begin
+ $display("TC%01d: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR.", tc_ctr);
+ $display("TC%01d: Expected: 0x%040x", tc_ctr, expected);
+ $display("TC%01d: Got: 0x%040x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+ $display("*** TC%01d - Single block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test()
+ //
+ //
+ // Perform test of a double block digest. Note that we check
+ // the digests for both the first and final block.
+ //----------------------------------------------------------------
+ task double_block_test(input [511 : 0] block0,
+ input [159 : 0] expected0,
+ input [511 : 0] block1,
+ input [159 : 0] expected1
+ );
+ begin
+ $display("*** TC%01d - Double block test started.", tc_ctr);
+
+ // First block
+ write_block(block0);
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ if (digest_data == expected0)
+ begin
+ $display("TC%01d first block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in first digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%040x", tc_ctr, expected0);
+ $display("TC%01d: Got: 0x%040x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ // Final block
+ write_block(block1);
+ write_word(ADDR_CTRL, CTRL_NEXT_VALUE);
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ if (digest_data == expected1)
+ begin
+ $display("TC%01d final block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in final digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%040x", tc_ctr, expected1);
+ $display("TC%01d: Got: 0x%040x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ $display("*** TC%01d - Double block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // double_block_test
+
+
+ //----------------------------------------------------------------
+ // sha1_test
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : sha1_test
+ reg [511 : 0] tc1;
+ reg [159 : 0] res1;
+
+ reg [511 : 0] tc2_1;
+ reg [159 : 0] res2_1;
+ reg [511 : 0] tc2_2;
+ reg [159 : 0] res2_2;
+
+ $display(" -- Testbench for sha1 started --");
+
+ init_sim();
+ reset_dut();
+ check_name_version();
+
+ // TC1: Single block message: "abc".
+ tc1 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ res1 = 160'ha9993e364706816aba3e25717850c26c9cd0d89d;
+ single_block_test(tc1, res1);
+
+ // TC2: Double block message.
+ // "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ tc2_1 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res2_1 = 160'hf4286818c37b27ae0408f581846771484a566572;
+
+ tc2_2 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res2_2 = 160'h84983e441c3bd26ebaae4aa1f95129e5e54670f1;
+ double_block_test(tc2_1, res2_1, tc2_2, res2_2);
+
+ display_test_result();
+ $display("*** Simulation done. ***");
+ $finish;
+ end // sha1_test
+endmodule // tb_sha1
+
+//======================================================================
+// EOF tb_sha1.v
+//======================================================================
+
diff --git a/sha1/src/tb/tb_sha1_core.v b/sha1/src/tb/tb_sha1_core.v
new file mode 100644
index 0000000..0ae592d
--- /dev/null
+++ b/sha1/src/tb/tb_sha1_core.v
@@ -0,0 +1,388 @@
+//======================================================================
+//
+// tb_sha1_core.v
+// ----------------
+// Testbench for the SHA-1 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/10ps
+
+module tb_sha1_core();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_HALF_PERIOD = 1;
+ parameter CLK_PERIOD = CLK_HALF_PERIOD * 2;
+
+
+ //----------------------------------------------------------------
+ // 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_init;
+ reg tb_next;
+ reg [511 : 0] tb_block;
+ wire tb_ready;
+ wire [159 : 0] tb_digest;
+ wire tb_digest_valid;
+
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha1_core dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .init(tb_init),
+ .next(tb_next),
+
+ .block(tb_block),
+
+ .ready(tb_ready),
+
+ .digest(tb_digest),
+ .digest_valid(tb_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ #(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("init = 0x%01x, next = 0x%01x",
+ dut.init, dut.next);
+ $display("block = 0x%0128x", dut.block);
+
+ $display("ready = 0x%01x, valid = 0x%01x",
+ dut.ready, dut.digest_valid);
+ $display("digest = 0x%040x", dut.digest);
+ $display("H0_reg = 0x%08x, H1_reg = 0x%08x, H2_reg = 0x%08x, H3_reg = 0x%08x, H4_reg = 0x%08x",
+ dut.H0_reg, dut.H1_reg, dut.H2_reg, dut.H3_reg, dut.H4_reg);
+ $display("");
+
+ $display("Control signals and counter:");
+ $display("sha1_ctrl_reg = 0x%01x", dut.sha1_ctrl_reg);
+ $display("digest_init = 0x%01x, digest_update = 0x%01x",
+ dut.digest_init, dut.digest_update);
+ $display("state_init = 0x%01x, state_update = 0x%01x",
+ dut.state_init, dut.state_update);
+ $display("first_block = 0x%01x, ready_flag = 0x%01x, w_init = 0x%01x",
+ dut.first_block, dut.ready_flag, dut.w_init);
+ $display("round_ctr_inc = 0x%01x, round_ctr_rst = 0x%01x, round_ctr_reg = 0x%02x",
+ dut.round_ctr_inc, dut.round_ctr_rst, dut.round_ctr_reg);
+ $display("");
+
+ $display("State registers:");
+ $display("a_reg = 0x%08x, b_reg = 0x%08x, c_reg = 0x%08x, d_reg = 0x%08x, e_reg = 0x%08x",
+ dut.a_reg, dut.b_reg, dut.c_reg, dut.d_reg, dut.e_reg);
+ $display("a_new = 0x%08x, b_new = 0x%08x, c_new = 0x%08x, d_new = 0x%08x, e_new = 0x%08x",
+ dut.a_new, dut.b_new, dut.c_new, dut.d_new, dut.e_new);
+ $display("");
+
+ $display("State update values:");
+ $display("f = 0x%08x, k = 0x%08x, t = 0x%08x, w = 0x%08x,",
+ dut.state_logic.f, dut.state_logic.k, dut.state_logic.t, dut.w);
+ $display("");
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(4 * CLK_HALF_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
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+
+ tb_init = 0;
+ tb_next = 0;
+ tb_block = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ end
+ endtask // init_dut
+
+
+ //----------------------------------------------------------------
+ // 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
+
+
+ //----------------------------------------------------------------
+ // 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
+
+
+ //----------------------------------------------------------------
+ // single_block_test
+ //
+ // Test a message of at most one block.
+ //----------------------------------------------------------------
+ task single_block_test(input [7 : 0] tc_number,
+ input [511 : 0] block,
+ input [159 : 0] expected);
+ begin
+ $display("*** TC %0d single block test case started.", tc_number);
+ tc_ctr = tc_ctr + 1;
+
+ tb_block = block;
+ tb_init = 1;
+ #(CLK_PERIOD);
+ tb_init = 0;
+ wait_ready();
+
+
+ if (tb_digest == expected)
+ begin
+ $display("*** TC %0d successful.", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d NOT successful.", tc_number);
+ $display("Expected: 0x%040x", expected);
+ $display("Got: 0x%040x", tb_digest);
+ $display("");
+
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test
+ //
+ // Test message consisting of two blocks.
+ //----------------------------------------------------------------
+ task double_block_test(input [7 : 0] tc_number,
+ input [511 : 0] block1,
+ input [159 : 0] expected1,
+ input [511 : 0] block2,
+ input [159 : 0] expected2);
+
+ reg [159 : 0] db_digest1;
+ reg db_error;
+ begin
+ $display("*** TC %0d double block test case started.", tc_number);
+ db_error = 0;
+ tc_ctr = tc_ctr + 1;
+
+ $display("*** TC %0d first block started.", tc_number);
+ tb_block = block1;
+ tb_init = 1;
+ #(CLK_PERIOD);
+ tb_init = 0;
+ wait_ready();
+ db_digest1 = tb_digest;
+ $display("*** TC %0d first block done.", tc_number);
+
+ $display("*** TC %0d second block started.", tc_number);
+ tb_block = block2;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+ $display("*** TC %0d second block done.", tc_number);
+
+ if (db_digest1 == expected1)
+ begin
+ $display("*** TC %0d first block successful", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d first block NOT successful", tc_number);
+ $display("Expected: 0x%040x", expected1);
+ $display("Got: 0x%040x", db_digest1);
+ $display("");
+ db_error = 1;
+ end
+
+ if (db_digest1 == expected1)
+ begin
+ $display("*** TC %0d second block successful", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d second block NOT successful", tc_number);
+ $display("Expected: 0x%040x", expected2);
+ $display("Got: 0x%040x", tb_digest);
+ $display("");
+ db_error = 1;
+ end
+
+ if (db_error)
+ begin
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // double_block_test
+
+
+ //----------------------------------------------------------------
+ // sha1_core_test
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : sha1_core_test
+ reg [511 : 0] tc1;
+ reg [159 : 0] res1;
+
+ reg [511 : 0] tc2_1;
+ reg [159 : 0] res2_1;
+ reg [511 : 0] tc2_2;
+ reg [159 : 0] res2_2;
+
+ $display(" -- Testbench for sha1 core started --");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+ // TC1: Single block message: "abc".
+ tc1 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ res1 = 160'ha9993e364706816aba3e25717850c26c9cd0d89d;
+ single_block_test(1, tc1, res1);
+
+ // TC2: Double block message.
+ // "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ tc2_1 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res2_1 = 160'hf4286818c37b27ae0408f581846771484a566572;
+
+ tc2_2 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res2_2 = 160'h84983e441c3bd26ebaae4aa1f95129e5e54670f1;
+ double_block_test(2, tc2_1, res2_1, tc2_2, res2_2);
+
+ display_test_result();
+ $display("*** Simulation done.");
+ $finish;
+ end // sha1_core_test
+endmodule // tb_sha1_core
+
+//======================================================================
+// EOF tb_sha1_core.v
+//======================================================================
diff --git a/sha1/src/tb/tb_sha1_w_mem.v b/sha1/src/tb/tb_sha1_w_mem.v
new file mode 100644
index 0000000..7426bcd
--- /dev/null
+++ b/sha1/src/tb/tb_sha1_w_mem.v
@@ -0,0 +1,287 @@
+//======================================================================
+//
+// Tb_sha1_w_mem.v
+// ---------------
+// Testbench for the SHA-1 W memory module.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014 SUNET
+//
+// 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/10ps
+
+module tb_sha1_w_mem();
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 1;
+ parameter DISPLAY_CYCLES = 0;
+
+ parameter CLK_HALF_PERIOD = 2;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg tb_clk;
+ reg tb_reset_n;
+ reg tb_init;
+ reg tb_next;
+ reg [511 : 0] tb_block;
+ wire [31 : 0] tb_w;
+
+ reg [63 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha1_w_mem dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .block(tb_block),
+
+ .init(tb_init),
+ .next(tb_next),
+
+ .w(tb_w)
+ );
+
+
+ //----------------------------------------------------------------
+ // 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_CYCLES)
+ begin
+ $display("cycle = %016x:", cycle_ctr);
+ end
+
+ if (DEBUG)
+ begin
+ dump_w_state();
+ end
+ end // dut_monitor
+
+
+ //----------------------------------------------------------------
+ // dump_w_state()
+ //
+ // Dump the current state of all W registers.
+ //----------------------------------------------------------------
+ task dump_w_state();
+ begin
+ $display("W state:");
+
+
+ $display("ctrl_reg = %01x, w_ctr_reg = %02x, init = %01x, next = %01x",
+ dut.sha1_w_mem_ctrl_reg, dut.w_ctr_reg, dut.init, dut.next);
+
+ $display("w_tmp = %08x, w_new = %08x", dut.w_tmp, dut.w_new);
+
+ $display("w0_reg = %08x, w1_reg = %08x, w2_reg = %08x, w3_reg = %08x",
+ dut.w_mem[00], dut.w_mem[01], dut.w_mem[02], dut.w_mem[03]);
+
+ $display("w4_reg = %08x, w5_reg = %08x, w6_reg = %08x, w7_reg = %08x",
+ dut.w_mem[04], dut.w_mem[05], dut.w_mem[06], dut.w_mem[07]);
+
+ $display("w8_reg = %08x, w9_reg = %08x, w10_reg = %08x, w11_reg = %08x",
+ dut.w_mem[08], dut.w_mem[09], dut.w_mem[10], dut.w_mem[11]);
+
+ $display("w12_reg = %08x, w13_reg = %08x, w14_reg = %08x, w15_reg = %08x",
+ dut.w_mem[12], dut.w_mem[13], dut.w_mem[14], dut.w_mem[15]);
+
+ $display("");
+ end
+ endtask // dump_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(4 * CLK_HALF_PERIOD);
+ tb_reset_n = 1;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // init_sim
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ $display("*** Simulation init.");
+ tb_clk = 0;
+ tb_reset_n = 1;
+ cycle_ctr = 0;
+ tb_init = 0;
+ tb_next = 0;
+ tb_block = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // dump_mem()
+ //
+ // Dump the contents of the memory by directly reading from
+ // the registers in the dut, not via the read port.
+ //----------------------------------------------------------------
+ task dump_mem();
+ begin
+ $display("*** Dumping memory:");
+ $display("W[00] = 0x%08x", dut.w_mem[00]);
+ $display("W[01] = 0x%08x", dut.w_mem[01]);
+ $display("W[02] = 0x%08x", dut.w_mem[02]);
+ $display("W[03] = 0x%08x", dut.w_mem[03]);
+ $display("W[04] = 0x%08x", dut.w_mem[04]);
+ $display("W[05] = 0x%08x", dut.w_mem[05]);
+ $display("W[06] = 0x%08x", dut.w_mem[06]);
+ $display("W[07] = 0x%08x", dut.w_mem[07]);
+ $display("W[08] = 0x%08x", dut.w_mem[08]);
+ $display("W[09] = 0x%08x", dut.w_mem[09]);
+ $display("W[10] = 0x%08x", dut.w_mem[10]);
+ $display("W[11] = 0x%08x", dut.w_mem[11]);
+ $display("W[12] = 0x%08x", dut.w_mem[12]);
+ $display("W[13] = 0x%08x", dut.w_mem[13]);
+ $display("W[14] = 0x%08x", dut.w_mem[14]);
+ $display("W[15] = 0x%08x", dut.w_mem[15]);
+ $display("");
+ end
+ endtask // dump_mem
+
+
+ //----------------------------------------------------------------
+ // test_w_schedule()
+ //
+ // Test that W scheduling happens and work correctly.
+ // Note: Currently not a self checking test case.
+ //----------------------------------------------------------------
+ task test_w_schedule();
+ begin
+ $display("*** Test of W schedule processing. --");
+ tb_block = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ tb_init = 1;
+ #(4 * CLK_HALF_PERIOD);
+ tb_init = 0;
+
+ tb_next = 1;
+ #(200 * CLK_HALF_PERIOD);
+
+ dump_w_state();
+ end
+ endtask // test_w_schedule
+
+
+ //----------------------------------------------------------------
+ // test_read_w/(
+ //
+ // Test that we can read data from all W registers.
+ // Note: Currently not a self checking test case.
+ //----------------------------------------------------------------
+ task test_read_w();
+ reg [7 : 0] i;
+ begin
+ $display("*** Test of W read operations. --");
+ i = 0;
+ tb_init = 1;
+ #(2 * CLK_HALF_PERIOD);
+ tb_init = 0;
+
+ while (i < 80)
+ begin
+ tb_next = i;
+ $display("API: w%02x = 0x%02x", i, dut.w_tmp);
+ i = i + 1;
+ #(2 * CLK_HALF_PERIOD);
+ end
+ end
+ endtask // read_w
+
+
+ //----------------------------------------------------------------
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : w_mem_test
+ $display(" -- Testbench for sha1 w memory started --");
+ init_sim();
+
+ dump_mem();
+ reset_dut();
+ dump_mem();
+
+ test_w_schedule();
+
+ test_read_w();
+
+ $display("*** Simulation done.");
+ $finish;
+ end
+
+endmodule // w_mem_test
+
+//======================================================================
+// EOF tb_sha1_w_mem.v
+//======================================================================
diff --git a/sha1/toolruns/Makefile b/sha1/toolruns/Makefile
new file mode 100755
index 0000000..16dc069
--- /dev/null
+++ b/sha1/toolruns/Makefile
@@ -0,0 +1,102 @@
+#===================================================================
+#
+# Makefile
+# --------
+# Makefile for building sha1 core and top simulation files.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2014, SUNET
+#
+# 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.
+#
+#===================================================================
+
+WMEM_SRC=../src/rtl/sha1_w_mem.v
+WMEM_TB_SRC=../src/tb/tb_sha1_w_mem.v
+
+CORE_SRC=../src/rtl/sha1_core.v ../src/rtl/sha1_w_mem.v
+CORE_TB_SRC=../src/tb/tb_sha1_core.v
+
+TOP_SRC=../src/rtl/sha1.v $(CORE_SRC)
+TOP_TB_SRC=../src/tb/tb_sha1.v
+
+CC=iverilog
+
+
+all: top core wmem
+
+
+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)
+
+
+wmem: $(WMEM_SRC) $(WMEM_TB_SRC)
+ $(CC) -o wmem.sim $(WMEM_SRC) $(WMEM_TB_SRC)
+
+
+sim-top: top.sim
+ ./top.sim
+
+
+sim-core: core.sim
+ ./core.sim
+
+
+sim-wmem: wmem.sim
+ ./wmem.sim
+
+
+debug:
+ @echo "No debug available."
+
+
+clean:
+ rm -f top.sim
+ rm -f core.sim
+ rm -f wmem.sim
+
+
+help:
+ @echo "Supported targets:"
+ @echo "------------------"
+ @echo "all: Build all simulation targets."
+ @echo "top: Build the top simulation target."
+ @echo "core: Build the core simulation target."
+ @echo "wmem: Build the wmem simulation target."
+ @echo "sim-top: Run top level simulation."
+ @echo "sim-core: Run core level simulation."
+ @echo "sim-wmem: Run wmem level simulation."
+ @echo "debug: Print the internal varibles."
+ @echo "clean: Delete all built files."
+
+#===================================================================
+# EOF Makefile
+#===================================================================
diff --git a/sha256/LICENSE.txt b/sha256/LICENSE.txt
new file mode 100644
index 0000000..2acf230
--- /dev/null
+++ b/sha256/LICENSE.txt
@@ -0,0 +1,24 @@
+
+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:
+
+* 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.
+
+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/sha256/README.md b/sha256/README.md
new file mode 100644
index 0000000..10150df
--- /dev/null
+++ b/sha256/README.md
@@ -0,0 +1,113 @@
+# sha256 #
+Hardware implementation of the SHA-256 cryptographic hash function. The
+implementation is written in Verilog 2001 compliant code. The
+implementation includes a core and a wrapper that provides a 32-bit
+interface for simple integration. There is also an alternative wrapper
+that implements a Wishbone compliant interface.
+
+This is a low area implementation that iterates over the rounds but
+there is no sharing of operations such as adders.
+
+The hardware implementation is complemented by a functional model
+written in Python.
+
+## Implementation details ##
+The sha256 is divided into the following sections.
+- src/rtl - RTL source files
+- src/tb - Testbenches for the RTL files
+- src/model/python - Functional model written in python
+- doc - documentation (currently not done.)
+- toolruns - Where tools are supposed to be run. Includes a Makefile for
+building and simulating the design using [Icarus Verilog](http://iverilog.icarus.com/)
+
+The actual core consists of the following files:
+- sha256_core.v - The core itself with wide interfaces.
+- sha256_w_mem.v - W message block memort and expansion logic.
+- sha256_k_constants.v - K constants ROM memory.
+
+The top level entity is called sha256_core. This entity has wide
+interfaces (512 bit block input, 256 bit digest). In order to make it
+usable you probably want to wrap the core with a bus interface.
+
+Unless you want to provide your own interface you therefore also need to
+select one top level wrapper. There are two wrappers provided:
+- sha256.v - A wrapper with a 32-bit memory like interface.
+- wb_sha256.v - A wrapper that implements a [Wishbone](http://opencores.org/opencores,wishbone) interface.
+
+***Do not include both wrappers in the same project.***
+
+The core (sha256_core) will sample all data inputs when given the init
+or next signal. the wrappers provided contains additional data
+registers. This allows you to load a new block while the core is
+processing the previous block.
+
+The W-memory scheduler is based on 16 32-bit registers. Thee registers
+are loaded with the current block. After 16 rounds the contents of the
+registers slide through the registers r5..r0 while the new W word is
+inserted at r15 as well as being returned to the core.
+
+
+## FPGA-results ##
+
+### Altera Cyclone FPGAs ###
+Implementation results using Altera Quartus-II 13.1.
+
+***Cyclone IV E***
+- EP4CE6F17C6
+- 3882 LEs
+- 1813 registers
+- 74 MHz
+- 66 cycles latency
+
+***Cyclone IV GX***
+- EP4CGX22CF19C6
+- 3773 LEs
+- 1813 registers
+- 76 MHz
+- 66 cycles latency
+
+***Cyclone V***
+- 5CGXFC7C7F23C8
+- 1469 ALMs
+- 1813 registers
+- 79 MHz
+- 66 cycles latency
+
+
+## TODO ##
+- Extensive verification in physical device.
+- Complete documentation.
+
+
+## Status ##
+***(2013-02-23)***
+
+Cleanup, more results etc. Move all wmem update logic to a separate
+process for a cleaner code.
+
+
+**(2014-02-22)**
+
+Redesigned the W-memory into a sliding window solution. This not only
+removed 48 32-registers but also several muxes and address decoders.
+
+The old implementation resources and performance:
+- 9587 LEs
+- 3349 registers
+- 73 MHz
+- 66 cycles latency
+
+The new implementation resources and performance:
+- 3765 LEs
+- 1813 registers
+- 76 MHz
+- 66 cycles latency
+
+
+
+**(2014-02-19)**
+- The core has been added to the Cryptech repo. The core comes from
+ https://github.com/secworks/sha256
+
+
+
diff --git a/sha256/src/model/sha256.py b/sha256/src/model/sha256.py
new file mode 100755
index 0000000..3b16e1f
--- /dev/null
+++ b/sha256/src/model/sha256.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#=======================================================================
+#
+# sha256.py
+# ---------
+# Simple, pure Python model of the SHA-256 hash function. Used as a
+# reference for the HW implementation. The code follows the structure
+# of the HW implementation as much as possible.
+#
+#
+# Author: Joachim Strömbergson
+# Copyright (c) 2013, 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
+
+
+#-------------------------------------------------------------------
+# ChaCha()
+#-------------------------------------------------------------------
+class SHA256():
+ def __init__(self, verbose = 0):
+ self.verbose = verbose
+ self.H = [0] * 8
+ self.t1 = 0
+ self.t2 = 0
+ self.a = 0
+ self.b = 0
+ self.c = 0
+ self.d = 0
+ self.e = 0
+ self.f = 0
+ self.g = 0
+ self.h = 0
+ self.w = 0
+ self.W = [0] * 16
+ self.k = 0
+ self.K = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]
+
+
+ def init(self):
+ self.H = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
+
+
+ def next(self, block):
+ self._W_schedule(block)
+ self._copy_digest()
+ if self.verbose:
+ print("State after init:")
+ self._print_state(0)
+
+ for i in range(64):
+ self._sha256_round(i)
+ if self.verbose:
+ self._print_state(i)
+
+ self._update_digest()
+
+
+ def get_digest(self):
+ return self.H
+
+
+ def _copy_digest(self):
+ self.a = self.H[0]
+ self.b = self.H[1]
+ self.c = self.H[2]
+ self.d = self.H[3]
+ self.e = self.H[4]
+ self.f = self.H[5]
+ self.g = self.H[6]
+ self.h = self.H[7]
+
+
+ def _update_digest(self):
+ self.H[0] = (self.H[0] + self.a) & 0xffffffff
+ self.H[1] = (self.H[1] + self.b) & 0xffffffff
+ self.H[2] = (self.H[2] + self.c) & 0xffffffff
+ self.H[3] = (self.H[3] + self.d) & 0xffffffff
+ self.H[4] = (self.H[4] + self.e) & 0xffffffff
+ self.H[5] = (self.H[5] + self.f) & 0xffffffff
+ self.H[6] = (self.H[6] + self.g) & 0xffffffff
+ self.H[7] = (self.H[7] + self.h) & 0xffffffff
+
+
+ def _print_state(self, round):
+ print("State at round 0x%02x:" % round)
+ print("t1 = 0x%08x, t2 = 0x%08x" % (self.t1, self.t2))
+ print("k = 0x%08x, w = 0x%08x" % (self.k, self.w))
+ print("a = 0x%08x, b = 0x%08x" % (self.a, self.b))
+ print("c = 0x%08x, d = 0x%08x" % (self.c, self.d))
+ print("e = 0x%08x, f = 0x%08x" % (self.e, self.f))
+ print("g = 0x%08x, h = 0x%08x" % (self.g, self.h))
+ print("")
+
+
+ def _sha256_round(self, round):
+ self.k = self.K[round]
+ self.w = self._next_w(round)
+ self.t1 = self._T1(self.e, self.f, self.g, self.h, self.k, self.w)
+ self.t2 = self._T2(self.a, self.b, self.c)
+ self.h = self.g
+ self.g = self.f
+ self.f = self.e
+ self.e = (self.d + self.t1) & 0xffffffff
+ self.d = self.c
+ self.c = self.b
+ self.b = self.a
+ self.a = (self.t1 + self.t2) & 0xffffffff
+
+
+ def _next_w(self, round):
+ if (round < 16):
+ return self.W[round]
+
+ else:
+ tmp_w = (self._delta1(self.W[14]) +
+ self.W[9] +
+ self._delta0(self.W[1]) +
+ self.W[0]) & 0xffffffff
+ for i in range(15):
+ self.W[i] = self.W[(i+1)]
+ self.W[15] = tmp_w
+ return tmp_w
+
+
+ def _W_schedule(self, block):
+ for i in range(16):
+ self.W[i] = block[i]
+
+
+ def _Ch(self, x, y, z):
+ return (x & y) ^ (~x & z)
+
+
+ def _Maj(self, x, y, z):
+ return (x & y) ^ (x & z) ^ (y & z)
+
+ def _sigma0(self, x):
+ return (self._rotr32(x, 2) ^ self._rotr32(x, 13) ^ self._rotr32(x, 22))
+
+
+ def _sigma1(self, x):
+ return (self._rotr32(x, 6) ^ self._rotr32(x, 11) ^ self._rotr32(x, 25))
+
+
+ def _delta0(self, x):
+ return (self._rotr32(x, 7) ^ self._rotr32(x, 18) ^ self._shr32(x, 3))
+
+
+ def _delta1(self, x):
+ return (self._rotr32(x, 17) ^ self._rotr32(x, 19) ^ self._shr32(x, 10))
+
+
+ def _T1(self, e, f, g, h, k, w):
+ return (h + self._sigma1(e) + self._Ch(e, f, g) + k + w) & 0xffffffff
+
+
+ def _T2(self, a, b, c):
+ return (self._sigma0(a) + self._Maj(a, b, c)) & 0xffffffff
+
+
+ def _rotr32(self, n, r):
+ return ((n >> r) | (n << (32 - r))) & 0xffffffff
+
+
+ def _shr32(self, n, r):
+ return (n >> r)
+
+
+#-------------------------------------------------------------------
+# print_digest()
+#
+# Print the given digest.
+#-------------------------------------------------------------------
+def print_digest(digest):
+ print("0x%08x, 0x%08x, 0x%08x, 0x%08x" %\
+ (digest[0], digest[1], digest[2], digest[3]))
+ print("0x%08x, 0x%08x, 0x%08x, 0x%08x" %\
+ (digest[4], digest[5], digest[6], digest[7]))
+ print("")
+
+
+#-------------------------------------------------------------------
+# compare_digests()
+#
+# Check that the given digest matches the expected digest.
+#-------------------------------------------------------------------
+def compare_digests(digest, expected):
+ if (digest != expected):
+ print("Error:")
+ print("Got:")
+ print_digest(digest)
+ print("Expected:")
+ print_digest(expected)
+ else:
+ print("Test case ok.")
+
+
+#-------------------------------------------------------------------
+# main()
+#
+# If executed tests the ChaCha class using known test vectors.
+#-------------------------------------------------------------------
+def main():
+ print("Testing the SHA-256 Python model.")
+ print("---------------------------------")
+ print
+
+ my_sha256 = SHA256(verbose=0);
+
+ # TC1: NIST testcase with message "abc"
+ print("TC1: Single block message test specified by NIST.")
+ TC1_block = [0x61626380, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000018]
+
+ TC1_expected = [0xBA7816BF, 0x8F01CFEA, 0x414140DE, 0x5DAE2223,
+ 0xB00361A3, 0x96177A9C, 0xB410FF61, 0xF20015AD]
+
+ my_sha256.init()
+ my_sha256.next(TC1_block)
+ my_digest = my_sha256.get_digest()
+ compare_digests(my_digest, TC1_expected)
+ print("")
+
+
+ # TC2: NIST testcase with double block message."
+ print("TC2: Double block message test specified by NIST.")
+ TC2_1_block = [0x61626364, 0x62636465, 0x63646566, 0x64656667,
+ 0x65666768, 0x66676869, 0x6768696A, 0x68696A6B,
+ 0x696A6B6C, 0x6A6B6C6D, 0x6B6C6D6E, 0x6C6D6E6F,
+ 0x6D6E6F70, 0x6E6F7071, 0x80000000, 0x00000000]
+
+
+ TC2_2_block = [0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x000001C0]
+
+ TC2_1_expected = [0x85E655D6, 0x417A1795, 0x3363376A, 0x624CDE5C,
+ 0x76E09589, 0xCAC5F811, 0xCC4B32C1, 0xF20E533A]
+
+ TC2_2_expected = [0x248D6A61, 0xD20638B8, 0xE5C02693, 0x0C3E6039,
+ 0xA33CE459, 0x64FF2167, 0xF6ECEDD4, 0x19DB06C1]
+
+ my_sha256.init()
+ my_sha256.next(TC2_1_block)
+ my_digest = my_sha256.get_digest()
+ compare_digests(my_digest, TC2_1_expected)
+
+ my_sha256.next(TC2_2_block)
+ my_digest = my_sha256.get_digest()
+ compare_digests(my_digest, TC2_2_expected)
+ print("")
+
+
+ # TC3: Huge message with n blocks
+ n = 1000
+ print("TC3: Huge message with %d blocks test case." % n)
+ TC3_block = [0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
+ 0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
+ 0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
+ 0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f]
+
+ TC3_expected = [0x7638f3bc, 0x500dd1a6, 0x586dd4d0, 0x1a1551af,
+ 0xd821d235, 0x2f919e28, 0xd5842fab, 0x03a40f2a]
+
+ my_sha256.init()
+ for i in range(n):
+ my_sha256.next(TC3_block)
+ my_digest = my_sha256.get_digest()
+ if (VERBOSE):
+ print("Digest for block %d:" % i)
+ print_digest(my_digest)
+ compare_digests(my_digest, TC3_expected)
+
+
+#-------------------------------------------------------------------
+# __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 sha256.py
+#=======================================================================
diff --git a/sha256/src/rtl/sha256.v b/sha256/src/rtl/sha256.v
new file mode 100644
index 0000000..04048b1
--- /dev/null
+++ b/sha256/src/rtl/sha256.v
@@ -0,0 +1,204 @@
+//======================================================================
+//
+// sha256.v
+// ------
+// Top level wrapper for the SHA-256 hash function providing
+// a simple memory like interface with 32 bit data access.
+//
+// Authors: Joachim Strömbergson, Paul Selkirk
+// Copyright (c) 2014-2015, 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 sha256(
+ // 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
+ );
+
+ //----------------------------------------------------------------
+ // 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_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_BLOCK = 8'h10;
+
+ parameter ADDR_DIGEST = 8'h20;
+
+ parameter CORE_NAME0 = 32'h73686132; // "sha2"
+ parameter CORE_NAME1 = 32'h2d323536; // "-256"
+ parameter CORE_VERSION = 32'h302e3830; // "0.80"
+
+ parameter BLOCK_BITS = 512;
+ parameter DIGEST_BITS = 256;
+ parameter BLOCK_WORDS = BLOCK_BITS / 32;
+ parameter DIGEST_WORDS = DIGEST_BITS / 32;
+
+ //----------------------------------------------------------------
+ // Registers.
+ //----------------------------------------------------------------
+ reg [0 : BLOCK_BITS - 1] block_reg;
+ reg [0 : DIGEST_BITS - 1] digest_reg;
+ reg init_reg;
+ reg next_reg;
+
+ reg [31 : 0] tmp_read_data;
+ reg [31 : 0] tmp_read_data_reg;
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ wire core_init;
+ wire core_next;
+ wire core_ready;
+ wire [0 : BLOCK_BITS - 1] core_block;
+ wire [0 : DIGEST_BITS - 1] core_digest;
+ wire core_digest_valid;
+
+ wire [31 : 0] core_name0 = CORE_NAME0;
+ wire [31 : 0] core_name1 = CORE_NAME1;
+ wire [31 : 0] core_version = CORE_VERSION;
+ wire [31 : 0] core_ctrl;
+ wire [31 : 0] core_status;
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign core_init = init_reg;
+ assign core_next = next_reg;
+ assign core_ctrl = { 30'b0, next_reg, init_reg };
+ assign core_status = { 30'b0, core_digest_valid, core_ready };
+ assign core_block = block_reg;
+
+ assign read_data = tmp_read_data_reg;
+
+ //----------------------------------------------------------------
+ // core instantiation.
+ //----------------------------------------------------------------
+ sha256_core core(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .init(core_init),
+ .next(core_next),
+
+ .block(core_block),
+
+ .ready(core_ready),
+
+ .digest(core_digest),
+ .digest_valid(core_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // latch in digest when ready
+ //----------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (core_digest_valid)
+ digest_reg <= core_digest;
+ end
+
+ //----------------------------------------------------------------
+ // storage registers for mapping memory to core interface
+ //----------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ init_reg <= 0;
+ next_reg <= 0;
+
+ if (cs && we)
+ begin
+ // write operations
+ if ((address >= ADDR_BLOCK) &&
+ (address < ADDR_BLOCK + BLOCK_WORDS))
+ block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data;
+ else if (address == ADDR_CTRL)
+ begin
+ init_reg <= write_data[CTRL_INIT_BIT];
+ next_reg <= write_data[CTRL_NEXT_BIT];
+ end
+ end
+ end
+
+ always @*
+ begin
+ tmp_read_data = 32'h00000000;
+
+ if (cs && !we)
+ begin
+ // read operations
+ if ((address >= ADDR_BLOCK) &&
+ (address < ADDR_BLOCK + BLOCK_WORDS))
+ tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32];
+ else if ((address >= ADDR_DIGEST) &&
+ (address < ADDR_DIGEST + DIGEST_WORDS))
+ tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32];
+ else
+ case (address)
+ ADDR_NAME0:
+ tmp_read_data = core_name0;
+ ADDR_NAME1:
+ tmp_read_data = core_name1;
+ ADDR_VERSION:
+ tmp_read_data = core_version;
+ ADDR_CTRL:
+ tmp_read_data = core_ctrl;
+ ADDR_STATUS:
+ tmp_read_data = core_status;
+ endcase
+ end
+ end
+
+ always @(posedge clk)
+ begin
+ tmp_read_data_reg <= tmp_read_data;
+ end
+
+endmodule // sha256
diff --git a/sha256/src/rtl/sha256_core.v b/sha256/src/rtl/sha256_core.v
new file mode 100644
index 0000000..a88a359
--- /dev/null
+++ b/sha256/src/rtl/sha256_core.v
@@ -0,0 +1,519 @@
+//======================================================================
+//
+// sha256_core.v
+// -------------
+// Verilog 2001 implementation of the SHA-256 hash function.
+// This is the internal core with wide interfaces.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014 SUNET
+//
+// 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 sha256_core(
+ input wire clk,
+ input wire reset_n,
+
+ input wire init,
+ input wire next,
+
+ input wire [511 : 0] block,
+
+ output wire ready,
+
+ output wire [255 : 0] digest,
+ output wire digest_valid
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter H0_0 = 32'h6a09e667;
+ parameter H0_1 = 32'hbb67ae85;
+ parameter H0_2 = 32'h3c6ef372;
+ parameter H0_3 = 32'ha54ff53a;
+ parameter H0_4 = 32'h510e527f;
+ parameter H0_5 = 32'h9b05688c;
+ parameter H0_6 = 32'h1f83d9ab;
+ parameter H0_7 = 32'h5be0cd19;
+
+ parameter SHA256_ROUNDS = 63;
+
+ parameter CTRL_IDLE = 0;
+ parameter CTRL_ROUNDS = 1;
+ parameter CTRL_DONE = 2;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] a_reg;
+ reg [31 : 0] a_new;
+ reg [31 : 0] b_reg;
+ reg [31 : 0] b_new;
+ reg [31 : 0] c_reg;
+ reg [31 : 0] c_new;
+ reg [31 : 0] d_reg;
+ reg [31 : 0] d_new;
+ reg [31 : 0] e_reg;
+ reg [31 : 0] e_new;
+ reg [31 : 0] f_reg;
+ reg [31 : 0] f_new;
+ reg [31 : 0] g_reg;
+ reg [31 : 0] g_new;
+ reg [31 : 0] h_reg;
+ reg [31 : 0] h_new;
+ reg a_h_we;
+
+ reg [31 : 0] H0_reg;
+ reg [31 : 0] H0_new;
+ reg [31 : 0] H1_reg;
+ reg [31 : 0] H1_new;
+ reg [31 : 0] H2_reg;
+ reg [31 : 0] H2_new;
+ reg [31 : 0] H3_reg;
+ reg [31 : 0] H3_new;
+ reg [31 : 0] H4_reg;
+ reg [31 : 0] H4_new;
+ reg [31 : 0] H5_reg;
+ reg [31 : 0] H5_new;
+ reg [31 : 0] H6_reg;
+ reg [31 : 0] H6_new;
+ reg [31 : 0] H7_reg;
+ reg [31 : 0] H7_new;
+ reg H_we;
+
+ reg [5 : 0] t_ctr_reg;
+ reg [5 : 0] t_ctr_new;
+ reg t_ctr_we;
+ reg t_ctr_inc;
+ reg t_ctr_rst;
+
+ reg digest_valid_reg;
+ reg digest_valid_new;
+ reg digest_valid_we;
+
+ reg [1 : 0] sha256_ctrl_reg;
+ reg [1 : 0] sha256_ctrl_new;
+ reg sha256_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg digest_init;
+ reg digest_update;
+
+ reg state_init;
+ reg state_update;
+
+ reg first_block;
+
+ reg ready_flag;
+
+ reg [31 : 0] t1;
+ reg [31 : 0] t2;
+
+ wire [31 : 0] k_data;
+
+ reg w_init;
+ reg w_next;
+ wire [31 : 0] w_data;
+
+
+ //----------------------------------------------------------------
+ // Module instantiantions.
+ //----------------------------------------------------------------
+ sha256_k_constants k_constants_inst(
+ .addr(t_ctr_reg),
+ .K(k_data)
+ );
+
+
+ sha256_w_mem w_mem_inst(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .block(block),
+
+ .init(w_init),
+ .next(w_next),
+ .w(w_data)
+ );
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign ready = ready_flag;
+
+ assign digest = {H0_reg, H1_reg, H2_reg, H3_reg,
+ H4_reg, H5_reg, H6_reg, H7_reg};
+
+ assign digest_valid = digest_valid_reg;
+
+
+ //----------------------------------------------------------------
+ // 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 : reg_update
+ if (!reset_n)
+ begin
+ a_reg <= 32'h00000000;
+ b_reg <= 32'h00000000;
+ c_reg <= 32'h00000000;
+ d_reg <= 32'h00000000;
+ e_reg <= 32'h00000000;
+ f_reg <= 32'h00000000;
+ g_reg <= 32'h00000000;
+ h_reg <= 32'h00000000;
+ H0_reg <= 32'h00000000;
+ H1_reg <= 32'h00000000;
+ H2_reg <= 32'h00000000;
+ H3_reg <= 32'h00000000;
+ H4_reg <= 32'h00000000;
+ H5_reg <= 32'h00000000;
+ H6_reg <= 32'h00000000;
+ H7_reg <= 32'h00000000;
+ digest_valid_reg <= 0;
+ t_ctr_reg <= 6'b000000;
+ sha256_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+
+ if (a_h_we)
+ begin
+ a_reg <= a_new;
+ b_reg <= b_new;
+ c_reg <= c_new;
+ d_reg <= d_new;
+ e_reg <= e_new;
+ f_reg <= f_new;
+ g_reg <= g_new;
+ h_reg <= h_new;
+ end
+
+ if (H_we)
+ begin
+ H0_reg <= H0_new;
+ H1_reg <= H1_new;
+ H2_reg <= H2_new;
+ H3_reg <= H3_new;
+ H4_reg <= H4_new;
+ H5_reg <= H5_new;
+ H6_reg <= H6_new;
+ H7_reg <= H7_new;
+ end
+
+ if (t_ctr_we)
+ begin
+ t_ctr_reg <= t_ctr_new;
+ end
+
+ if (digest_valid_we)
+ begin
+ digest_valid_reg <= digest_valid_new;
+ end
+
+ if (sha256_ctrl_we)
+ begin
+ sha256_ctrl_reg <= sha256_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // digest_logic
+ //
+ // The logic needed to init as well as update the digest.
+ //----------------------------------------------------------------
+ always @*
+ begin : digest_logic
+ H0_new = 32'h00000000;
+ H1_new = 32'h00000000;
+ H2_new = 32'h00000000;
+ H3_new = 32'h00000000;
+ H4_new = 32'h00000000;
+ H5_new = 32'h00000000;
+ H6_new = 32'h00000000;
+ H7_new = 32'h00000000;
+ H_we = 0;
+
+ if (digest_init)
+ begin
+ H0_new = H0_0;
+ H1_new = H0_1;
+ H2_new = H0_2;
+ H3_new = H0_3;
+ H4_new = H0_4;
+ H5_new = H0_5;
+ H6_new = H0_6;
+ H7_new = H0_7;
+ H_we = 1;
+ end
+
+ if (digest_update)
+ begin
+ H0_new = H0_reg + a_reg;
+ H1_new = H1_reg + b_reg;
+ H2_new = H2_reg + c_reg;
+ H3_new = H3_reg + d_reg;
+ H4_new = H4_reg + e_reg;
+ H5_new = H5_reg + f_reg;
+ H6_new = H6_reg + g_reg;
+ H7_new = H7_reg + h_reg;
+ H_we = 1;
+ end
+ end // digest_logic
+
+
+ //----------------------------------------------------------------
+ // t1_logic
+ //
+ // The logic for the T1 function.
+ //----------------------------------------------------------------
+ always @*
+ begin : t1_logic
+ reg [31 : 0] sum1;
+ reg [31 : 0] ch;
+
+ sum1 = {e_reg[5 : 0], e_reg[31 : 6]} ^
+ {e_reg[10 : 0], e_reg[31 : 11]} ^
+ {e_reg[24 : 0], e_reg[31 : 25]};
+
+ ch = (e_reg & f_reg) ^ ((~e_reg) & g_reg);
+
+ t1 = h_reg + sum1 + ch + w_data + k_data;
+ end // t1_logic
+
+
+ //----------------------------------------------------------------
+ // t2_logic
+ //
+ // The logic for the T2 function
+ //----------------------------------------------------------------
+ always @*
+ begin : t2_logic
+ reg [31 : 0] sum0;
+ reg [31 : 0] maj;
+
+ sum0 = {a_reg[1 : 0], a_reg[31 : 2]} ^
+ {a_reg[12 : 0], a_reg[31 : 13]} ^
+ {a_reg[21 : 0], a_reg[31 : 22]};
+
+ maj = (a_reg & b_reg) ^ (a_reg & c_reg) ^ (b_reg & c_reg);
+
+ t2 = sum0 + maj;
+ end // t2_logic
+
+
+ //----------------------------------------------------------------
+ // state_logic
+ //
+ // The logic needed to init as well as update the state during
+ // round processing.
+ //----------------------------------------------------------------
+ always @*
+ begin : state_logic
+ a_new = 32'h00000000;
+ b_new = 32'h00000000;
+ c_new = 32'h00000000;
+ d_new = 32'h00000000;
+ e_new = 32'h00000000;
+ f_new = 32'h00000000;
+ g_new = 32'h00000000;
+ h_new = 32'h00000000;
+ a_h_we = 0;
+
+ if (state_init)
+ begin
+ if (first_block)
+ begin
+ a_new = H0_0;
+ b_new = H0_1;
+ c_new = H0_2;
+ d_new = H0_3;
+ e_new = H0_4;
+ f_new = H0_5;
+ g_new = H0_6;
+ h_new = H0_7;
+ a_h_we = 1;
+ end
+ else
+ begin
+ a_new = H0_reg;
+ b_new = H1_reg;
+ c_new = H2_reg;
+ d_new = H3_reg;
+ e_new = H4_reg;
+ f_new = H5_reg;
+ g_new = H6_reg;
+ h_new = H7_reg;
+ a_h_we = 1;
+ end
+ end
+
+ if (state_update)
+ begin
+ a_new = t1 + t2;
+ b_new = a_reg;
+ c_new = b_reg;
+ d_new = c_reg;
+ e_new = d_reg + t1;
+ f_new = e_reg;
+ g_new = f_reg;
+ h_new = g_reg;
+ a_h_we = 1;
+ end
+ end // state_logic
+
+
+ //----------------------------------------------------------------
+ // t_ctr
+ //
+ // Update logic for the round counter, a monotonically
+ // increasing counter with reset.
+ //----------------------------------------------------------------
+ always @*
+ begin : t_ctr
+ t_ctr_new = 0;
+ t_ctr_we = 0;
+
+ if (t_ctr_rst)
+ begin
+ t_ctr_new = 0;
+ t_ctr_we = 1;
+ end
+
+ if (t_ctr_inc)
+ begin
+ t_ctr_new = t_ctr_reg + 1'b1;
+ t_ctr_we = 1;
+ end
+ end // t_ctr
+
+
+ //----------------------------------------------------------------
+ // sha256_ctrl_fsm
+ //
+ // Logic for the state machine controlling the core behaviour.
+ //----------------------------------------------------------------
+ always @*
+ begin : sha256_ctrl_fsm
+ digest_init = 0;
+ digest_update = 0;
+
+ state_init = 0;
+ state_update = 0;
+
+ first_block = 0;
+ ready_flag = 0;
+
+ w_init = 0;
+ w_next = 0;
+
+ t_ctr_inc = 0;
+ t_ctr_rst = 0;
+
+ digest_valid_new = 0;
+ digest_valid_we = 0;
+
+ sha256_ctrl_new = CTRL_IDLE;
+ sha256_ctrl_we = 0;
+
+
+ case (sha256_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ ready_flag = 1;
+
+ if (init)
+ begin
+ digest_init = 1;
+ w_init = 1;
+ state_init = 1;
+ first_block = 1;
+ t_ctr_rst = 1;
+ digest_valid_new = 0;
+ digest_valid_we = 1;
+ sha256_ctrl_new = CTRL_ROUNDS;
+ sha256_ctrl_we = 1;
+ end
+
+ if (next)
+ begin
+ w_init = 1;
+ state_init = 1;
+ t_ctr_rst = 1;
+ digest_valid_new = 0;
+ digest_valid_we = 1;
+ sha256_ctrl_new = CTRL_ROUNDS;
+ sha256_ctrl_we = 1;
+ end
+ end
+
+
+ CTRL_ROUNDS:
+ begin
+ w_next = 1;
+ state_update = 1;
+ t_ctr_inc = 1;
+
+ if (t_ctr_reg == SHA256_ROUNDS)
+ begin
+ sha256_ctrl_new = CTRL_DONE;
+ sha256_ctrl_we = 1;
+ end
+ end
+
+
+ CTRL_DONE:
+ begin
+ digest_update = 1;
+ digest_valid_new = 1;
+ digest_valid_we = 1;
+
+ sha256_ctrl_new = CTRL_IDLE;
+ sha256_ctrl_we = 1;
+ end
+ endcase // case (sha256_ctrl_reg)
+ end // sha256_ctrl_fsm
+
+endmodule // sha256_core
+
+//======================================================================
+// EOF sha256_core.v
+//======================================================================
diff --git a/sha256/src/rtl/sha256_k_constants.v b/sha256/src/rtl/sha256_k_constants.v
new file mode 100644
index 0000000..2acd3a6
--- /dev/null
+++ b/sha256/src/rtl/sha256_k_constants.v
@@ -0,0 +1,387 @@
+//======================================================================
+//
+// sha256_k_constants.v
+// --------------------
+// The table K with constants in the SHA-256 hash function.
+// A simple combinational ROM basically.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014 SUNET
+//
+// 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 sha256_k_constants(
+ input wire [5 : 0] addr,
+ output wire [31 : 0] K
+ );
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] tmp_K;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign K = tmp_K;
+
+
+ //----------------------------------------------------------------
+ // addr_mux
+ //----------------------------------------------------------------
+ always @*
+ begin : addr_mux
+ case(addr)
+ 0:
+ begin
+ tmp_K = 32'h428a2f98;
+ end
+
+ 1:
+ begin
+ tmp_K = 32'h71374491;
+ end
+
+ 2:
+ begin
+ tmp_K = 32'hb5c0fbcf;
+ end
+
+ 3:
+ begin
+ tmp_K = 32'he9b5dba5;
+ end
+
+ 4:
+ begin
+ tmp_K = 32'h3956c25b;
+ end
+
+ 5:
+ begin
+ tmp_K = 32'h59f111f1;
+ end
+
+ 6:
+ begin
+ tmp_K = 32'h923f82a4;
+ end
+
+ 7:
+ begin
+ tmp_K = 32'hab1c5ed5;
+ end
+
+ 8:
+ begin
+ tmp_K = 32'hd807aa98;
+ end
+
+ 9:
+ begin
+ tmp_K = 32'h12835b01;
+ end
+
+ 10:
+ begin
+ tmp_K = 32'h243185be;
+ end
+
+ 11:
+ begin
+ tmp_K = 32'h550c7dc3;
+ end
+
+ 12:
+ begin
+ tmp_K = 32'h72be5d74;
+ end
+
+ 13:
+ begin
+ tmp_K = 32'h80deb1fe;
+ end
+
+ 14:
+ begin
+ tmp_K = 32'h9bdc06a7;
+ end
+
+ 15:
+ begin
+ tmp_K = 32'hc19bf174;
+ end
+
+ 16:
+ begin
+ tmp_K = 32'he49b69c1;
+ end
+
+ 17:
+ begin
+ tmp_K = 32'hefbe4786;
+ end
+
+ 18:
+ begin
+ tmp_K = 32'h0fc19dc6;
+ end
+
+ 19:
+ begin
+ tmp_K = 32'h240ca1cc;
+ end
+
+ 20:
+ begin
+ tmp_K = 32'h2de92c6f;
+ end
+
+ 21:
+ begin
+ tmp_K = 32'h4a7484aa;
+ end
+
+ 22:
+ begin
+ tmp_K = 32'h5cb0a9dc;
+ end
+
+ 23:
+ begin
+ tmp_K = 32'h76f988da;
+ end
+
+ 24:
+ begin
+ tmp_K = 32'h983e5152;
+ end
+
+ 25:
+ begin
+ tmp_K = 32'ha831c66d;
+ end
+
+ 26:
+ begin
+ tmp_K = 32'hb00327c8;
+ end
+
+ 27:
+ begin
+ tmp_K = 32'hbf597fc7;
+ end
+
+ 28:
+ begin
+ tmp_K = 32'hc6e00bf3;
+ end
+
+ 29:
+ begin
+ tmp_K = 32'hd5a79147;
+ end
+
+ 30:
+ begin
+ tmp_K = 32'h06ca6351;
+ end
+
+ 31:
+ begin
+ tmp_K = 32'h14292967;
+ end
+
+ 32:
+ begin
+ tmp_K = 32'h27b70a85;
+ end
+
+ 33:
+ begin
+ tmp_K = 32'h2e1b2138;
+ end
+
+ 34:
+ begin
+ tmp_K = 32'h4d2c6dfc;
+ end
+
+ 35:
+ begin
+ tmp_K = 32'h53380d13;
+ end
+
+ 36:
+ begin
+ tmp_K = 32'h650a7354;
+ end
+
+ 37:
+ begin
+ tmp_K = 32'h766a0abb;
+ end
+
+ 38:
+ begin
+ tmp_K = 32'h81c2c92e;
+ end
+
+ 39:
+ begin
+ tmp_K = 32'h92722c85;
+ end
+
+ 40:
+ begin
+ tmp_K = 32'ha2bfe8a1;
+ end
+
+ 41:
+ begin
+ tmp_K = 32'ha81a664b;
+ end
+
+ 42:
+ begin
+ tmp_K = 32'hc24b8b70;
+ end
+
+ 43:
+ begin
+ tmp_K = 32'hc76c51a3;
+ end
+
+ 44:
+ begin
+ tmp_K = 32'hd192e819;
+ end
+
+ 45:
+ begin
+ tmp_K = 32'hd6990624;
+ end
+
+ 46:
+ begin
+ tmp_K = 32'hf40e3585;
+ end
+
+ 47:
+ begin
+ tmp_K = 32'h106aa070;
+ end
+
+ 48:
+ begin
+ tmp_K = 32'h19a4c116;
+ end
+
+ 49:
+ begin
+ tmp_K = 32'h1e376c08;
+ end
+
+ 50:
+ begin
+ tmp_K = 32'h2748774c;
+ end
+
+ 51:
+ begin
+ tmp_K = 32'h34b0bcb5;
+ end
+
+ 52:
+ begin
+ tmp_K = 32'h391c0cb3;
+ end
+
+ 53:
+ begin
+ tmp_K = 32'h4ed8aa4a;
+ end
+
+ 54:
+ begin
+ tmp_K = 32'h5b9cca4f;
+ end
+
+ 55:
+ begin
+ tmp_K = 32'h682e6ff3;
+ end
+
+ 56:
+ begin
+ tmp_K = 32'h748f82ee;
+ end
+
+ 57:
+ begin
+ tmp_K = 32'h78a5636f;
+ end
+
+ 58:
+ begin
+ tmp_K = 32'h84c87814;
+ end
+
+ 59:
+ begin
+ tmp_K = 32'h8cc70208;
+ end
+
+ 60:
+ begin
+ tmp_K = 32'h90befffa;
+ end
+
+ 61:
+ begin
+ tmp_K = 32'ha4506ceb;
+ end
+
+ 62:
+ begin
+ tmp_K = 32'hbef9a3f7;
+ end
+
+ 63:
+ begin
+ tmp_K = 32'hc67178f2;
+ end
+ endcase // case (addr)
+ end // block: addr_mux
+endmodule // sha256_k_constants
+
+//======================================================================
+// EOF sha256_k_constants.v
+//======================================================================
diff --git a/sha256/src/rtl/sha256_w_mem.v b/sha256/src/rtl/sha256_w_mem.v
new file mode 100644
index 0000000..f58c428
--- /dev/null
+++ b/sha256/src/rtl/sha256_w_mem.v
@@ -0,0 +1,345 @@
+//======================================================================
+//
+// sha256_w_mem_regs.v
+// -------------------
+// The W memory. This version uses 16 32-bit registers as a sliding
+// window to generate the 64 words.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014 SUNET
+//
+// 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 sha256_w_mem(
+ input wire clk,
+ input wire reset_n,
+
+ input wire [511 : 0] block,
+
+ input wire init,
+ input wire next,
+ output wire [31 : 0] w
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter CTRL_IDLE = 0;
+ parameter CTRL_UPDATE = 1;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] w_mem [0 : 15];
+ reg [31 : 0] w_mem00_new;
+ reg [31 : 0] w_mem01_new;
+ reg [31 : 0] w_mem02_new;
+ reg [31 : 0] w_mem03_new;
+ reg [31 : 0] w_mem04_new;
+ reg [31 : 0] w_mem05_new;
+ reg [31 : 0] w_mem06_new;
+ reg [31 : 0] w_mem07_new;
+ reg [31 : 0] w_mem08_new;
+ reg [31 : 0] w_mem09_new;
+ reg [31 : 0] w_mem10_new;
+ reg [31 : 0] w_mem11_new;
+ reg [31 : 0] w_mem12_new;
+ reg [31 : 0] w_mem13_new;
+ reg [31 : 0] w_mem14_new;
+ reg [31 : 0] w_mem15_new;
+ reg w_mem_we;
+
+ reg [5 : 0] w_ctr_reg;
+ reg [5 : 0] w_ctr_new;
+ reg w_ctr_we;
+ reg w_ctr_inc;
+ reg w_ctr_rst;
+
+ reg [1 : 0] sha256_w_mem_ctrl_reg;
+ reg [1 : 0] sha256_w_mem_ctrl_new;
+ reg sha256_w_mem_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] w_tmp;
+ reg [31 : 0] w_new;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign w = w_tmp;
+
+
+ //----------------------------------------------------------------
+ // 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 : reg_update
+ if (!reset_n)
+ begin
+ w_mem[00] <= 32'h00000000;
+ w_mem[01] <= 32'h00000000;
+ w_mem[02] <= 32'h00000000;
+ w_mem[03] <= 32'h00000000;
+ w_mem[04] <= 32'h00000000;
+ w_mem[05] <= 32'h00000000;
+ w_mem[06] <= 32'h00000000;
+ w_mem[07] <= 32'h00000000;
+ w_mem[08] <= 32'h00000000;
+ w_mem[09] <= 32'h00000000;
+ w_mem[10] <= 32'h00000000;
+ w_mem[11] <= 32'h00000000;
+ w_mem[12] <= 32'h00000000;
+ w_mem[13] <= 32'h00000000;
+ w_mem[14] <= 32'h00000000;
+ w_mem[15] <= 32'h00000000;
+ w_ctr_reg <= 6'h00;
+ sha256_w_mem_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ if (w_mem_we)
+ begin
+ w_mem[00] <= w_mem00_new;
+ w_mem[01] <= w_mem01_new;
+ w_mem[02] <= w_mem02_new;
+ w_mem[03] <= w_mem03_new;
+ w_mem[04] <= w_mem04_new;
+ w_mem[05] <= w_mem05_new;
+ w_mem[06] <= w_mem06_new;
+ w_mem[07] <= w_mem07_new;
+ w_mem[08] <= w_mem08_new;
+ w_mem[09] <= w_mem09_new;
+ w_mem[10] <= w_mem10_new;
+ w_mem[11] <= w_mem11_new;
+ w_mem[12] <= w_mem12_new;
+ w_mem[13] <= w_mem13_new;
+ w_mem[14] <= w_mem14_new;
+ w_mem[15] <= w_mem15_new;
+ end
+
+ if (w_ctr_we)
+ begin
+ w_ctr_reg <= w_ctr_new;
+ end
+
+ if (sha256_w_mem_ctrl_we)
+ begin
+ sha256_w_mem_ctrl_reg <= sha256_w_mem_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // select_w
+ //
+ // Mux for the external read operation. This is where we exract
+ // the W variable.
+ //----------------------------------------------------------------
+ always @*
+ begin : select_w
+ if (w_ctr_reg < 16)
+ begin
+ w_tmp = w_mem[w_ctr_reg[3 : 0]];
+ end
+ else
+ begin
+ w_tmp = w_new;
+ end
+ end // select_w
+
+
+ //----------------------------------------------------------------
+ // w_new_logic
+ //
+ // Logic that calculates the next value to be inserted into
+ // the sliding window of the memory.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_mem_update_logic
+ reg [31 : 0] w_0;
+ reg [31 : 0] w_1;
+ reg [31 : 0] w_9;
+ reg [31 : 0] w_14;
+ reg [31 : 0] d0;
+ reg [31 : 0] d1;
+
+ w_mem00_new = 32'h00000000;
+ w_mem01_new = 32'h00000000;
+ w_mem02_new = 32'h00000000;
+ w_mem03_new = 32'h00000000;
+ w_mem04_new = 32'h00000000;
+ w_mem05_new = 32'h00000000;
+ w_mem06_new = 32'h00000000;
+ w_mem07_new = 32'h00000000;
+ w_mem08_new = 32'h00000000;
+ w_mem09_new = 32'h00000000;
+ w_mem10_new = 32'h00000000;
+ w_mem11_new = 32'h00000000;
+ w_mem12_new = 32'h00000000;
+ w_mem13_new = 32'h00000000;
+ w_mem14_new = 32'h00000000;
+ w_mem15_new = 32'h00000000;
+ w_mem_we = 0;
+
+ w_0 = w_mem[0];
+ w_1 = w_mem[1];
+ w_9 = w_mem[9];
+ w_14 = w_mem[14];
+
+ d0 = {w_1[6 : 0], w_1[31 : 7]} ^
+ {w_1[17 : 0], w_1[31 : 18]} ^
+ {3'b000, w_1[31 : 3]};
+
+ d1 = {w_14[16 : 0], w_14[31 : 17]} ^
+ {w_14[18 : 0], w_14[31 : 19]} ^
+ {10'b0000000000, w_14[31 : 10]};
+
+ w_new = d1 + w_9 + d0 + w_0;
+
+ if (init)
+ begin
+ w_mem00_new = block[511 : 480];
+ w_mem01_new = block[479 : 448];
+ w_mem02_new = block[447 : 416];
+ w_mem03_new = block[415 : 384];
+ w_mem04_new = block[383 : 352];
+ w_mem05_new = block[351 : 320];
+ w_mem06_new = block[319 : 288];
+ w_mem07_new = block[287 : 256];
+ w_mem08_new = block[255 : 224];
+ w_mem09_new = block[223 : 192];
+ w_mem10_new = block[191 : 160];
+ w_mem11_new = block[159 : 128];
+ w_mem12_new = block[127 : 96];
+ w_mem13_new = block[95 : 64];
+ w_mem14_new = block[63 : 32];
+ w_mem15_new = block[31 : 0];
+ w_mem_we = 1;
+ end
+ else if (w_ctr_reg > 15)
+ begin
+ w_mem00_new = w_mem[01];
+ w_mem01_new = w_mem[02];
+ w_mem02_new = w_mem[03];
+ w_mem03_new = w_mem[04];
+ w_mem04_new = w_mem[05];
+ w_mem05_new = w_mem[06];
+ w_mem06_new = w_mem[07];
+ w_mem07_new = w_mem[08];
+ w_mem08_new = w_mem[09];
+ w_mem09_new = w_mem[10];
+ w_mem10_new = w_mem[11];
+ w_mem11_new = w_mem[12];
+ w_mem12_new = w_mem[13];
+ w_mem13_new = w_mem[14];
+ w_mem14_new = w_mem[15];
+ w_mem15_new = w_new;
+ w_mem_we = 1;
+ end
+ end // w_mem_update_logic
+
+
+ //----------------------------------------------------------------
+ // w_ctr
+ // W schedule adress counter. Counts from 0x10 to 0x3f and
+ // is used to expand the block into words.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_ctr
+ w_ctr_new = 0;
+ w_ctr_we = 0;
+
+ if (w_ctr_rst)
+ begin
+ w_ctr_new = 6'h00;
+ w_ctr_we = 1;
+ end
+
+ if (w_ctr_inc)
+ begin
+ w_ctr_new = w_ctr_reg + 6'h01;
+ w_ctr_we = 1;
+ end
+ end // w_ctr
+
+
+ //----------------------------------------------------------------
+ // sha256_w_mem_fsm
+ // Logic for the w shedule FSM.
+ //----------------------------------------------------------------
+ always @*
+ begin : sha256_w_mem_fsm
+ w_ctr_rst = 0;
+ w_ctr_inc = 0;
+
+ sha256_w_mem_ctrl_new = CTRL_IDLE;
+ sha256_w_mem_ctrl_we = 0;
+
+ case (sha256_w_mem_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (init)
+ begin
+ w_ctr_rst = 1;
+ sha256_w_mem_ctrl_new = CTRL_UPDATE;
+ sha256_w_mem_ctrl_we = 1;
+ end
+ end
+
+ CTRL_UPDATE:
+ begin
+ if (next)
+ begin
+ w_ctr_inc = 1;
+ end
+
+ if (w_ctr_reg == 6'h3f)
+ begin
+ sha256_w_mem_ctrl_new = CTRL_IDLE;
+ sha256_w_mem_ctrl_we = 1;
+ end
+ end
+ endcase // case (sha256_ctrl_reg)
+ end // sha256_ctrl_fsm
+
+endmodule // sha256_w_mem
+
+//======================================================================
+// sha256_w_mem.v
+//======================================================================
diff --git a/sha256/src/rtl/wb_sha256.v b/sha256/src/rtl/wb_sha256.v
new file mode 100644
index 0000000..024d0b9
--- /dev/null
+++ b/sha256/src/rtl/wb_sha256.v
@@ -0,0 +1,674 @@
+//======================================================================
+//
+// wb_sha256.v
+// -----------
+// Wisbone compliant top level wrapper for the SHA-256 hash core.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014 SUNET
+//
+// 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 wb_sha256(
+ // Clock and reset.
+ input wire CLK_I,
+ input wire RST_I,
+
+ // Control and status.
+ input wire STB_I,
+ input wire WE_I,
+ output wire ACK_O,
+ output wire ERR_O,
+
+ // Address and data.
+ input wire [7 : 0] ADR_I,
+ input wire [31 : 0] DAT_I,
+ output wire [31 : 0] DAT_O
+ );
+
+
+ //----------------------------------------------------------------
+ // 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_INIT_VALUE = 8'h01;
+ parameter CTRL_NEXT_BIT = 1;
+ parameter CTRL_NEXT_VALUE = 8'h02;
+
+ parameter ADDR_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_BLOCK0 = 8'h10;
+ parameter ADDR_BLOCK1 = 8'h11;
+ parameter ADDR_BLOCK2 = 8'h12;
+ parameter ADDR_BLOCK3 = 8'h13;
+ parameter ADDR_BLOCK4 = 8'h14;
+ parameter ADDR_BLOCK5 = 8'h15;
+ parameter ADDR_BLOCK6 = 8'h16;
+ parameter ADDR_BLOCK7 = 8'h17;
+ parameter ADDR_BLOCK8 = 8'h18;
+ parameter ADDR_BLOCK9 = 8'h19;
+ parameter ADDR_BLOCK10 = 8'h1a;
+ parameter ADDR_BLOCK11 = 8'h1b;
+ parameter ADDR_BLOCK12 = 8'h1c;
+ parameter ADDR_BLOCK13 = 8'h1d;
+ parameter ADDR_BLOCK14 = 8'h1e;
+ parameter ADDR_BLOCK15 = 8'h1f;
+
+ parameter ADDR_DIGEST0 = 8'h20;
+ parameter ADDR_DIGEST1 = 8'h21;
+ parameter ADDR_DIGEST2 = 8'h22;
+ parameter ADDR_DIGEST3 = 8'h23;
+ parameter ADDR_DIGEST4 = 8'h24;
+ parameter ADDR_DIGEST5 = 8'h25;
+ parameter ADDR_DIGEST6 = 8'h26;
+ parameter ADDR_DIGEST7 = 8'h27;
+
+ parameter CORE_NAME0 = 32'h73686132; // "sha2"
+ parameter CORE_NAME1 = 32'h2d323536; // "-256"
+ parameter CORE_VERSION = 32'h302e3830; // "0.80"
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg init_reg;
+ reg next_reg;
+ reg ctrl_we;
+
+ reg ready_reg;
+
+ 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] block4_reg;
+ reg block4_we;
+ reg [31 : 0] block5_reg;
+ reg block5_we;
+ reg [31 : 0] block6_reg;
+ reg block6_we;
+ reg [31 : 0] block7_reg;
+ reg block7_we;
+ reg [31 : 0] block8_reg;
+ reg block8_we;
+ reg [31 : 0] block9_reg;
+ reg block9_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 [255 : 0] digest_reg;
+
+ reg digest_valid_reg;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ wire core_init;
+ wire core_next;
+ wire core_ready;
+ wire [511 : 0] core_block;
+ wire [255 : 0] core_digest;
+ wire core_digest_valid;
+
+ reg [31 : 0] tmp_data_out;
+ reg tmp_ACK_O;
+ reg tmp_ERR_O;
+
+ wire reset_n;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign core_init = init_reg;
+
+ assign core_next = next_reg;
+
+ assign core_block = {block0_reg, block1_reg, block2_reg, block3_reg,
+ block4_reg, block5_reg, block6_reg, block7_reg,
+ block8_reg, block9_reg, block10_reg, block11_reg,
+ block12_reg, block13_reg, block14_reg, block15_reg};
+
+ assign DAT_O = tmp_data_out;
+
+ assign ACK_O = tmp_ACK_O;
+ assign ERR_O = tmp_ERR_O;
+
+ assign reset_n = ~RST_I;
+
+
+ //----------------------------------------------------------------
+ // core instantiation.
+ //----------------------------------------------------------------
+ sha256_core core(
+ .clk(CLK_I),
+ .reset_n(reset_n),
+
+ .init(core_init),
+ .next(core_next),
+
+ .block(core_block),
+
+ .ready(core_ready),
+
+ .digest(core_digest),
+ .digest_valid(core_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // 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_I)
+ begin
+ if (!reset_n)
+ begin
+ init_reg <= 0;
+ next_reg <= 0;
+ ready_reg <= 0;
+ digest_reg <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ digest_valid_reg <= 0;
+ block0_reg <= 32'h00000000;
+ block1_reg <= 32'h00000000;
+ block2_reg <= 32'h00000000;
+ block3_reg <= 32'h00000000;
+ block4_reg <= 32'h00000000;
+ block5_reg <= 32'h00000000;
+ block6_reg <= 32'h00000000;
+ block7_reg <= 32'h00000000;
+ block8_reg <= 32'h00000000;
+ block9_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;
+ end
+ else
+ begin
+ ready_reg <= core_ready;
+ digest_valid_reg <= core_digest_valid;
+
+ if (ctrl_we)
+ begin
+ init_reg <= DAT_I[CTRL_INIT_BIT];
+ next_reg <= DAT_I[CTRL_NEXT_BIT];
+ end
+
+ if (core_digest_valid)
+ begin
+ digest_reg <= core_digest;
+ end
+
+ if (block0_we)
+ begin
+ block0_reg <= DAT_I;
+ end
+
+ if (block1_we)
+ begin
+ block1_reg <= DAT_I;
+ end
+
+ if (block2_we)
+ begin
+ block2_reg <= DAT_I;
+ end
+
+ if (block3_we)
+ begin
+ block3_reg <= DAT_I;
+ end
+
+ if (block4_we)
+ begin
+ block4_reg <= DAT_I;
+ end
+
+ if (block5_we)
+ begin
+ block5_reg <= DAT_I;
+ end
+
+ if (block6_we)
+ begin
+ block6_reg <= DAT_I;
+ end
+
+ if (block7_we)
+ begin
+ block7_reg <= DAT_I;
+ end
+
+ if (block8_we)
+ begin
+ block8_reg <= DAT_I;
+ end
+
+ if (block9_we)
+ begin
+ block9_reg <= DAT_I;
+ end
+
+ if (block10_we)
+ begin
+ block10_reg <= DAT_I;
+ end
+
+ if (block11_we)
+ begin
+ block11_reg <= DAT_I;
+ end
+
+ if (block12_we)
+ begin
+ block12_reg <= DAT_I;
+ end
+
+ if (block13_we)
+ begin
+ block13_reg <= DAT_I;
+ end
+
+ if (block14_we)
+ begin
+ block14_reg <= DAT_I;
+ end
+
+ if (block15_we)
+ begin
+ block15_reg <= DAT_I;
+ end
+
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // addr_decoder
+ //
+ // IF SEL_I is enabled will either try to write to or read
+ // from the internal registers.
+ //----------------------------------------------------------------
+ always @*
+ begin : addr_decoder
+ ctrl_we = 0;
+ block0_we = 0;
+ block1_we = 0;
+ block2_we = 0;
+ block3_we = 0;
+ block4_we = 0;
+ block5_we = 0;
+ block6_we = 0;
+ block7_we = 0;
+ block8_we = 0;
+ block9_we = 0;
+ block10_we = 0;
+ block11_we = 0;
+ block12_we = 0;
+ block13_we = 0;
+ block14_we = 0;
+ block15_we = 0;
+ tmp_data_out = 32'h00000000;
+ tmp_ERR_O = 0;
+ tmp_ACK_O = 0;
+
+ if (STB_I)
+ begin
+ if (WE_I)
+ begin
+ case (ADR_I)
+ // Write operations.
+ ADDR_CTRL:
+ begin
+ ctrl_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK0:
+ begin
+ block0_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK1:
+ begin
+ block1_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK2:
+ begin
+ block2_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK3:
+ begin
+ block3_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK4:
+ begin
+ block4_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK5:
+ begin
+ block5_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK6:
+ begin
+ block6_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK7:
+ begin
+ block7_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK8:
+ begin
+ block8_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK9:
+ begin
+ block9_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK10:
+ begin
+ block10_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK11:
+ begin
+ block11_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK12:
+ begin
+ block12_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK13:
+ begin
+ block13_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK14:
+ begin
+ block14_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK15:
+ begin
+ block15_we = 1;
+ tmp_ACK_O = 1;
+ end
+
+ default:
+ begin
+ tmp_ERR_O = 1;
+ end
+ endcase // case (ADR_I)
+ end // if (WE_I)
+
+ else
+ begin
+ case (ADR_I)
+ // Read operations.
+ ADDR_NAME0:
+ begin
+ tmp_data_out = CORE_NAME0;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_NAME1:
+ begin
+ tmp_data_out = CORE_NAME1;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_VERSION:
+ begin
+ tmp_data_out = CORE_VERSION;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_CTRL:
+ begin
+ tmp_data_out = {28'h0000000, 2'b00, next_reg, init_reg};
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_STATUS:
+ begin
+ tmp_data_out = {28'h0000000, 2'b00, digest_valid_reg, ready_reg};
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK0:
+ begin
+ tmp_data_out = block0_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK1:
+ begin
+ tmp_data_out = block1_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK2:
+ begin
+ tmp_data_out = block2_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK3:
+ begin
+ tmp_data_out = block3_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK4:
+ begin
+ tmp_data_out = block4_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK5:
+ begin
+ tmp_data_out = block5_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK6:
+ begin
+ tmp_data_out = block6_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK7:
+ begin
+ tmp_data_out = block7_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK8:
+ begin
+ tmp_data_out = block8_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK9:
+ begin
+ tmp_data_out = block9_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK10:
+ begin
+ tmp_data_out = block10_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK11:
+ begin
+ tmp_data_out = block11_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK12:
+ begin
+ tmp_data_out = block12_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK13:
+ begin
+ tmp_data_out = block13_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK14:
+ begin
+ tmp_data_out = block14_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_BLOCK15:
+ begin
+ tmp_data_out = block15_reg;
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_DIGEST0:
+ begin
+ tmp_data_out = digest_reg[255 : 224];
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_DIGEST1:
+ begin
+ tmp_data_out = digest_reg[223 : 192];
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_DIGEST2:
+ begin
+ tmp_data_out = digest_reg[191 : 160];
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_DIGEST3:
+ begin
+ tmp_data_out = digest_reg[159 : 128];
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_DIGEST4:
+ begin
+ tmp_data_out = digest_reg[127 : 96];
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_DIGEST5:
+ begin
+ tmp_data_out = digest_reg[95 : 64];
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_DIGEST6:
+ begin
+ tmp_data_out = digest_reg[63 : 32];
+ tmp_ACK_O = 1;
+ end
+
+ ADDR_DIGEST7:
+ begin
+ tmp_data_out = digest_reg[31 : 0];
+ tmp_ACK_O = 1;
+ end
+
+ default:
+ begin
+ tmp_ERR_O = 1;
+ end
+ endcase // case (ADR_I)
+ end
+ end
+ end // addr_decoder
+endmodule // wb_sha256
+
+//======================================================================
+// EOF wb_sha256.v
+//======================================================================
diff --git a/sha256/src/tb/tb_sha256.v b/sha256/src/tb/tb_sha256.v
new file mode 100644
index 0000000..72e7d21
--- /dev/null
+++ b/sha256/src/tb/tb_sha256.v
@@ -0,0 +1,556 @@
+//======================================================================
+//
+// tb_sha256.v
+// -----------
+// Testbench for the SHA-256 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/10ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_sha256();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_HALF_PERIOD = 2;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+ // The 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_VALUE = 8'h01;
+ parameter CTRL_NEXT_VALUE = 8'h02;
+
+ parameter ADDR_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_BLOCK0 = 8'h10;
+ parameter ADDR_BLOCK1 = 8'h11;
+ parameter ADDR_BLOCK2 = 8'h12;
+ parameter ADDR_BLOCK3 = 8'h13;
+ parameter ADDR_BLOCK4 = 8'h14;
+ parameter ADDR_BLOCK5 = 8'h15;
+ parameter ADDR_BLOCK6 = 8'h16;
+ parameter ADDR_BLOCK7 = 8'h17;
+ parameter ADDR_BLOCK8 = 8'h18;
+ parameter ADDR_BLOCK9 = 8'h19;
+ parameter ADDR_BLOCK10 = 8'h1a;
+ parameter ADDR_BLOCK11 = 8'h1b;
+ parameter ADDR_BLOCK12 = 8'h1c;
+ parameter ADDR_BLOCK13 = 8'h1d;
+ parameter ADDR_BLOCK14 = 8'h1e;
+ parameter ADDR_BLOCK15 = 8'h1f;
+
+ parameter ADDR_DIGEST0 = 8'h20;
+ parameter ADDR_DIGEST1 = 8'h21;
+ parameter ADDR_DIGEST2 = 8'h22;
+ parameter ADDR_DIGEST3 = 8'h23;
+ parameter ADDR_DIGEST4 = 8'h24;
+ parameter ADDR_DIGEST5 = 8'h25;
+ parameter ADDR_DIGEST6 = 8'h26;
+ parameter ADDR_DIGEST7 = 8'h27;
+
+
+ //----------------------------------------------------------------
+ // 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 [31 : 0] read_data;
+ reg [255 : 0] digest_data;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha256 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)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor
+ //
+ // Generates a cycle counter and displays information about
+ // the dut as needed.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ #(2 * CLK_HALF_PERIOD);
+ cycle_ctr = cycle_ctr + 1;
+ 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("cs = 0x%01x, we = 0x%01x",
+ dut.cs, dut.we);
+ $display("address = 0x%02x", dut.address);
+ $display("write_data = 0x%08x, read_data = 0x%08x",
+ dut.write_data, dut.read_data);
+ $display("tmp_read_data = 0x%08x", dut.tmp_read_data);
+ $display("");
+
+ $display("Control and status:");
+ $display("ctrl = 0x%02x, status = 0x%02x",
+ {dut.next_reg, dut.init_reg},
+ {dut.digest_valid_reg, dut.ready_reg});
+ $display("");
+
+ $display("Message block:");
+ $display("block0 = 0x%08x, block1 = 0x%08x, block2 = 0x%08x, block3 = 0x%08x",
+ dut.block0_reg, dut.block1_reg, dut.block2_reg, dut.block3_reg);
+ $display("block4 = 0x%08x, block5 = 0x%08x, block6 = 0x%08x, block7 = 0x%08x",
+ dut.block4_reg, dut.block5_reg, dut.block6_reg, dut.block7_reg);
+
+ $display("block8 = 0x%08x, block9 = 0x%08x, block10 = 0x%08x, block11 = 0x%08x",
+ dut.block8_reg, dut.block9_reg, dut.block10_reg, dut.block11_reg);
+ $display("block12 = 0x%08x, block13 = 0x%08x, block14 = 0x%08x, block15 = 0x%08x",
+ dut.block12_reg, dut.block13_reg, dut.block14_reg, dut.block15_reg);
+ $display("");
+
+ $display("Digest:");
+ $display("digest = 0x%064x", dut.digest_reg);
+ $display("");
+
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggles reset to force the DUT into a well defined state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(4 * CLK_HALF_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 = 32'h00000000;
+ error_ctr = 32'h00000000;
+ tc_ctr = 32'h00000000;
+
+ tb_clk = 0;
+ tb_reset_n = 0;
+ tb_cs = 0;
+ tb_we = 0;
+ tb_address = 6'h00;
+ tb_write_data = 32'h00000000;
+ end
+ endtask // init_dut
+
+
+ //----------------------------------------------------------------
+ // 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 completed.", tc_ctr);
+ $display("*** %02d errors detected during testing.", error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ // (Actually we wait for either ready or valid 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
+ read_data = 0;
+
+ while (read_data == 0)
+ begin
+ read_word(ADDR_STATUS);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [7 : 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;
+ #(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 [511 : 0] block);
+ begin
+ write_word(ADDR_BLOCK0, block[511 : 480]);
+ write_word(ADDR_BLOCK1, block[479 : 448]);
+ write_word(ADDR_BLOCK2, block[447 : 416]);
+ write_word(ADDR_BLOCK3, block[415 : 384]);
+ write_word(ADDR_BLOCK4, block[383 : 352]);
+ write_word(ADDR_BLOCK5, block[351 : 320]);
+ write_word(ADDR_BLOCK6, block[319 : 288]);
+ write_word(ADDR_BLOCK7, block[287 : 256]);
+ write_word(ADDR_BLOCK8, block[255 : 224]);
+ write_word(ADDR_BLOCK9, block[223 : 192]);
+ write_word(ADDR_BLOCK10, block[191 : 160]);
+ write_word(ADDR_BLOCK11, block[159 : 128]);
+ write_word(ADDR_BLOCK12, block[127 : 96]);
+ write_word(ADDR_BLOCK13, block[95 : 64]);
+ write_word(ADDR_BLOCK14, block[63 : 32]);
+ write_word(ADDR_BLOCK15, 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 [7 : 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
+
+
+ //----------------------------------------------------------------
+ // check_name_version()
+ //
+ // Read the name and version from the DUT.
+ //----------------------------------------------------------------
+ task check_name_version();
+ reg [31 : 0] name0;
+ reg [31 : 0] name1;
+ reg [31 : 0] version;
+ begin
+
+ read_word(ADDR_NAME0);
+ name0 = read_data;
+ read_word(ADDR_NAME1);
+ name1 = read_data;
+ read_word(ADDR_VERSION);
+ version = read_data;
+
+ $display("DUT name: %c%c%c%c%c%c%c%c",
+ name0[31 : 24], name0[23 : 16], name0[15 : 8], name0[7 : 0],
+ name1[31 : 24], name1[23 : 16], name1[15 : 8], name1[7 : 0]);
+ $display("DUT version: %c%c%c%c",
+ version[31 : 24], version[23 : 16], version[15 : 8], version[7 : 0]);
+ end
+ endtask // check_name_version
+
+
+ //----------------------------------------------------------------
+ // read_digest()
+ //
+ // Read the digest in the dut. The resulting digest will be
+ // available in the global variable digest_data.
+ //----------------------------------------------------------------
+ task read_digest();
+ begin
+ read_word(ADDR_DIGEST0);
+ digest_data[255 : 224] = read_data;
+ read_word(ADDR_DIGEST1);
+ digest_data[223 : 192] = read_data;
+ read_word(ADDR_DIGEST2);
+ digest_data[191 : 160] = read_data;
+ read_word(ADDR_DIGEST3);
+ digest_data[159 : 128] = read_data;
+ read_word(ADDR_DIGEST4);
+ digest_data[127 : 96] = read_data;
+ read_word(ADDR_DIGEST5);
+ digest_data[95 : 64] = read_data;
+ read_word(ADDR_DIGEST6);
+ digest_data[63 : 32] = read_data;
+ read_word(ADDR_DIGEST7);
+ digest_data[31 : 0] = read_data;
+ end
+ endtask // read_digest
+
+
+ //----------------------------------------------------------------
+ // single_block_test()
+ //
+ //
+ // Perform test of a single block digest.
+ //----------------------------------------------------------------
+ task single_block_test(input [511 : 0] block,
+ input [255 : 0] expected);
+ begin
+ $display("*** TC%01d - Single block test started.", tc_ctr);
+
+ write_block(block);
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ if (digest_data == expected)
+ begin
+ $display("TC%01d: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR.", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+ $display("*** TC%01d - Single block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test()
+ //
+ //
+ // Perform test of a double block digest. Note that we check
+ // the digests for both the first and final block.
+ //----------------------------------------------------------------
+ task double_block_test(input [511 : 0] block0,
+ input [255 : 0] expected0,
+ input [511 : 0] block1,
+ input [255 : 0] expected1
+ );
+ begin
+ $display("*** TC%01d - Double block test started.", tc_ctr);
+
+ // First block
+ write_block(block0);
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ if (digest_data == expected0)
+ begin
+ $display("TC%01d first block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in first digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected0);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ // Final block
+ write_block(block1);
+ write_word(ADDR_CTRL, CTRL_NEXT_VALUE);
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ if (digest_data == expected1)
+ begin
+ $display("TC%01d final block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in final digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected1);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ $display("*** TC%01d - Double block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // double_block_test
+
+
+ //----------------------------------------------------------------
+ // sha256_test
+ // The main test functionality.
+ //
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf
+ //----------------------------------------------------------------
+ initial
+ begin : sha256_test
+ reg [511 : 0] tc0;
+ reg [255 : 0] res0;
+
+ reg [511 : 0] tc1_0;
+ reg [255 : 0] res1_0;
+ reg [511 : 0] tc1_1;
+ reg [255 : 0] res1_1;
+
+ $display(" -- Testbench for sha256 started --");
+
+ init_sim();
+ reset_dut();
+ check_name_version();
+
+ // dump_dut_state();
+ // write_word(ADDR_BLOCK0, 32'hdeadbeef);
+ // dump_dut_state();
+ // read_word(ADDR_BLOCK0);
+ // dump_dut_state();
+
+ tc0 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ res0 = 256'hBA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD;
+ single_block_test(tc0, res0);
+
+ tc1_0 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res1_0 = 256'h85E655D6417A17953363376A624CDE5C76E09589CAC5F811CC4B32C1F20E533A;
+ tc1_1 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res1_1 = 256'h248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1;
+ double_block_test(tc1_0, res1_0, tc1_1, res1_1);
+
+ display_test_result();
+
+ $display(" -- Testbench for sha256 done. --");
+ $finish;
+ end // sha256_test
+endmodule // tb_sha256
+
+//======================================================================
+// EOF tb_sha256.v
+//======================================================================
diff --git a/sha256/src/tb/tb_sha256_core.v b/sha256/src/tb/tb_sha256_core.v
new file mode 100644
index 0000000..df0cafc
--- /dev/null
+++ b/sha256/src/tb/tb_sha256_core.v
@@ -0,0 +1,406 @@
+//======================================================================
+//
+// tb_sha256_core.v
+// ----------------
+// Testbench for the SHA-256 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/10ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_sha256_core();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_HALF_PERIOD = 2;
+ 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_init;
+ reg tb_next;
+ reg [511 : 0] tb_block;
+ wire tb_ready;
+ wire [255 : 0] tb_digest;
+ wire tb_digest_valid;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha256_core dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .init(tb_init),
+ .next(tb_next),
+
+ .block(tb_block),
+
+ .ready(tb_ready),
+
+ .digest(tb_digest),
+ .digest_valid(tb_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // 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;
+ #(2 * CLK_HALF_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("init = 0x%01x, next = 0x%01x",
+ dut.init, dut.next);
+ $display("block = 0x%0128x", dut.block);
+
+ $display("ready = 0x%01x, valid = 0x%01x",
+ dut.ready, dut.digest_valid);
+ $display("digest = 0x%064x", dut.digest);
+ $display("H0_reg = 0x%08x, H1_reg = 0x%08x, H2_reg = 0x%08x, H3_reg = 0x%08x",
+ dut.H0_reg, dut.H1_reg, dut.H2_reg, dut.H3_reg);
+ $display("H4_reg = 0x%08x, H5_reg = 0x%08x, H6_reg = 0x%08x, H7_reg = 0x%08x",
+ dut.H4_reg, dut.H5_reg, dut.H6_reg, dut.H7_reg);
+ $display("");
+
+ $display("Control signals and counter:");
+ $display("sha256_ctrl_reg = 0x%02x", dut.sha256_ctrl_reg);
+ $display("digest_init = 0x%01x, digest_update = 0x%01x",
+ dut.digest_init, dut.digest_update);
+ $display("state_init = 0x%01x, state_update = 0x%01x",
+ dut.state_init, dut.state_update);
+ $display("first_block = 0x%01x, ready_flag = 0x%01x, w_init = 0x%01x",
+ dut.first_block, dut.ready_flag, dut.w_init);
+ $display("t_ctr_inc = 0x%01x, t_ctr_rst = 0x%01x, t_ctr_reg = 0x%02x",
+ dut.t_ctr_inc, dut.t_ctr_rst, dut.t_ctr_reg);
+ $display("");
+
+ $display("State registers:");
+ $display("a_reg = 0x%08x, b_reg = 0x%08x, c_reg = 0x%08x, d_reg = 0x%08x",
+ dut.a_reg, dut.b_reg, dut.c_reg, dut.d_reg);
+ $display("e_reg = 0x%08x, f_reg = 0x%08x, g_reg = 0x%08x, h_reg = 0x%08x",
+ dut.e_reg, dut.f_reg, dut.g_reg, dut.h_reg);
+ $display("");
+ $display("a_new = 0x%08x, b_new = 0x%08x, c_new = 0x%08x, d_new = 0x%08x",
+ dut.a_new, dut.b_new, dut.c_new, dut.d_new);
+ $display("e_new = 0x%08x, f_new = 0x%08x, g_new = 0x%08x, h_new = 0x%08x",
+ dut.e_new, dut.f_new, dut.g_new, dut.h_new);
+ $display("");
+
+ $display("State update values:");
+ $display("w = 0x%08x, k = 0x%08x", dut.w_data, dut.k_data);
+ $display("t1 = 0x%08x, t2 = 0x%08x", dut.t1, dut.t2);
+ $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;
+ #(4 * CLK_HALF_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_init = 0;
+ tb_next = 0;
+ tb_block = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ end
+ endtask // init_dut
+
+
+ //----------------------------------------------------------------
+ // 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
+
+
+ //----------------------------------------------------------------
+ // 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
+
+
+ //----------------------------------------------------------------
+ // single_block_test()
+ //
+ // Run a test case spanning a single data block.
+ //----------------------------------------------------------------
+ task single_block_test(input [7 : 0] tc_number,
+ input [511 : 0] block,
+ input [255 : 0] expected);
+ begin
+ $display("*** TC %0d single block test case started.", tc_number);
+ tc_ctr = tc_ctr + 1;
+
+ tb_block = block;
+ tb_init = 1;
+ #(CLK_PERIOD);
+ wait_ready();
+
+
+ if (tb_digest == expected)
+ begin
+ $display("*** TC %0d successful.", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d NOT successful.", tc_number);
+ $display("Expected: 0x%064x", expected);
+ $display("Got: 0x%064x", tb_digest);
+ $display("");
+
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test()
+ //
+ // Run a test case spanning two data blocks. We check both
+ // intermediate and final digest.
+ //----------------------------------------------------------------
+ task double_block_test(input [7 : 0] tc_number,
+ input [511 : 0] block1,
+ input [255 : 0] expected1,
+ input [511 : 0] block2,
+ input [255 : 0] expected2);
+
+ reg [255 : 0] db_digest1;
+ reg db_error;
+ begin
+ $display("*** TC %0d double block test case started.", tc_number);
+ db_error = 0;
+ tc_ctr = tc_ctr + 1;
+
+ $display("*** TC %0d first block started.", tc_number);
+ tb_block = block1;
+ tb_init = 1;
+ #(CLK_PERIOD);
+ wait_ready();
+ db_digest1 = tb_digest;
+ $display("*** TC %0d first block done.", tc_number);
+
+ $display("*** TC %0d second block started.", tc_number);
+ tb_block = block2;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ wait_ready();
+ $display("*** TC %0d second block done.", tc_number);
+
+ if (db_digest1 == expected1)
+ begin
+ $display("*** TC %0d first block successful", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d first block NOT successful", tc_number);
+ $display("Expected: 0x%064x", expected1);
+ $display("Got: 0x%064x", db_digest1);
+ $display("");
+ db_error = 1;
+ end
+
+ if (db_digest1 == expected1)
+ begin
+ $display("*** TC %0d second block successful", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d second block NOT successful", tc_number);
+ $display("Expected: 0x%064x", expected2);
+ $display("Got: 0x%064x", tb_digest);
+ $display("");
+ db_error = 1;
+ end
+
+ if (db_error)
+ begin
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // sha256_core_test
+ // The main test functionality.
+ //
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf
+ //----------------------------------------------------------------
+ initial
+ begin : sha256_core_test
+ reg [511 : 0] tc1;
+ reg [255 : 0] res1;
+
+ reg [511 : 0] tc2_1;
+ reg [255 : 0] res2_1;
+ reg [511 : 0] tc2_2;
+ reg [255 : 0] res2_2;
+
+ $display(" -- Testbench for sha256 core started --");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+ // TC1: Single block message: "abc".
+ tc1 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ res1 = 256'hBA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD;
+ single_block_test(1, tc1, res1);
+
+ // TC2: Double block message.
+ // "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ tc2_1 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res2_1 = 256'h85E655D6417A17953363376A624CDE5C76E09589CAC5F811CC4B32C1F20E533A;
+
+ tc2_2 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res2_2 = 256'h248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1;
+ double_block_test(2, tc2_1, res2_1, tc2_2, res2_2);
+
+ display_test_result();
+ $display("*** Simulation done.");
+ $finish;
+ end // sha256_core_test
+endmodule // tb_sha256_core
+
+//======================================================================
+// EOF tb_sha256_core.v
+//======================================================================
diff --git a/sha256/src/tb/tb_sha256_w_mem.v b/sha256/src/tb/tb_sha256_w_mem.v
new file mode 100644
index 0000000..c95317d
--- /dev/null
+++ b/sha256/src/tb/tb_sha256_w_mem.v
@@ -0,0 +1,222 @@
+//======================================================================
+//
+// tb_sha256_w_mem.v
+// -----------------
+// Testbench for the SHA-256 W memory module.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014 SUNET
+//
+// 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/10ps
+
+module tb_sha256_w_mem();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 1;
+ parameter DISPLAY_CYCLES = 0;
+
+ parameter CLK_HALF_PERIOD = 2;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg tb_clk;
+ reg tb_reset_n;
+
+ reg tb_init;
+ reg tb_next;
+ reg [511 : 0] tb_block;
+ wire [31 : 0] tb_w;
+
+ reg [63 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha256_w_mem dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .block(tb_block),
+
+ .init(tb_init),
+ .next(tb_next),
+
+ .w(tb_w)
+ );
+
+
+ //----------------------------------------------------------------
+ // 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_CYCLES)
+ begin
+ $display("cycle = %016x:", cycle_ctr);
+ end
+
+ if (DEBUG)
+ begin
+ $display("dut ctrl_state = %02x:", dut.sha256_w_mem_ctrl_reg);
+ $display("dut w_ctr = %02x:", dut.w_ctr_reg);
+ $display("dut w_tmp = %02x:", dut.w_tmp);
+ dump_w_state();
+ end
+ end // dut_monitor
+
+
+ //----------------------------------------------------------------
+ // dump_w_state()
+ //
+ // Dump the current state of all W registers.
+ //----------------------------------------------------------------
+ task dump_w_state();
+ begin
+ $display("W state:");
+
+ $display("w0_reg = %08x, w1_reg = %08x, w2_reg = %08x, w3_reg = %08x",
+ dut.w_mem[00], dut.w_mem[01], dut.w_mem[02], dut.w_mem[03]);
+
+ $display("w4_reg = %08x, w5_reg = %08x, w6_reg = %08x, w7_reg = %08x",
+ dut.w_mem[04], dut.w_mem[05], dut.w_mem[06], dut.w_mem[07]);
+
+ $display("w8_reg = %08x, w9_reg = %08x, w10_reg = %08x, w11_reg = %08x",
+ dut.w_mem[08], dut.w_mem[09], dut.w_mem[10], dut.w_mem[11]);
+
+ $display("w12_reg = %08x, w13_reg = %08x, w14_reg = %08x, w15_reg = %08x",
+ dut.w_mem[12], dut.w_mem[13], dut.w_mem[14], dut.w_mem[15]);
+
+ $display("w_new = %08x", dut.w_new);
+ $display("");
+ end
+ endtask // dump_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(4 * CLK_HALF_PERIOD);
+ tb_reset_n = 1;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // init_sim
+ //----------------------------------------------------------------
+ task init_sim();
+ begin
+ $display("*** Simulation init.");
+ tb_clk = 0;
+ tb_reset_n = 1;
+ cycle_ctr = 0;
+
+ tb_init = 0;
+ tb_block = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // test_w_schedule()
+ //
+ // Test that W scheduling happens and work correctly.
+ // Note: Currently not a self checking test case.
+ //----------------------------------------------------------------
+ task test_w_schedule();
+ begin
+ $display("*** Test of W schedule processing. --");
+ tb_block = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ tb_init = 1;
+ #(4 * CLK_HALF_PERIOD);
+ tb_init = 0;
+ dump_w_state();
+
+ tb_next = 1;
+ #(150 * CLK_HALF_PERIOD);
+ end
+ endtask // test_w_schedule
+
+
+ //----------------------------------------------------------------
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : w_mem_test
+ $display(" -- Testbench for sha256 w memory started --");
+ init_sim();
+ reset_dut();
+ test_w_schedule();
+
+ $display("*** Simulation done.");
+ $finish;
+ end
+
+endmodule // w_mem_test
+
+//======================================================================
+// EOF tb_sha256_w_mem.v
+//======================================================================
diff --git a/sha256/src/tb/tb_wb_sha256.v b/sha256/src/tb/tb_wb_sha256.v
new file mode 100644
index 0000000..6d5fe08
--- /dev/null
+++ b/sha256/src/tb/tb_wb_sha256.v
@@ -0,0 +1,556 @@
+//======================================================================
+//
+// tb_wb_sha256.v
+// --------------
+// Testbench for the SHA-256 top level Wishbone wrapper.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014, SUNET
+//
+// 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/10ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_wb_sha256();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_HALF_PERIOD = 2;
+
+ // The 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_INIT_VALUE = 8'h01;
+ parameter CTRL_NEXT_BIT = 1;
+ parameter CTRL_NEXT_VALUE = 8'h02;
+
+ parameter ADDR_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_BLOCK0 = 8'h10;
+ parameter ADDR_BLOCK1 = 8'h11;
+ parameter ADDR_BLOCK2 = 8'h12;
+ parameter ADDR_BLOCK3 = 8'h13;
+ parameter ADDR_BLOCK4 = 8'h14;
+ parameter ADDR_BLOCK5 = 8'h15;
+ parameter ADDR_BLOCK6 = 8'h16;
+ parameter ADDR_BLOCK7 = 8'h17;
+ parameter ADDR_BLOCK8 = 8'h18;
+ parameter ADDR_BLOCK9 = 8'h19;
+ parameter ADDR_BLOCK10 = 8'h1a;
+ parameter ADDR_BLOCK11 = 8'h1b;
+ parameter ADDR_BLOCK12 = 8'h1c;
+ parameter ADDR_BLOCK13 = 8'h1d;
+ parameter ADDR_BLOCK14 = 8'h1e;
+ parameter ADDR_BLOCK15 = 8'h1f;
+
+ parameter ADDR_DIGEST0 = 8'h20;
+ parameter ADDR_DIGEST1 = 8'h21;
+ parameter ADDR_DIGEST2 = 8'h22;
+ parameter ADDR_DIGEST3 = 8'h23;
+ parameter ADDR_DIGEST4 = 8'h24;
+ parameter ADDR_DIGEST5 = 8'h25;
+ parameter ADDR_DIGEST6 = 8'h26;
+ parameter ADDR_DIGEST7 = 8'h27;
+
+
+ //----------------------------------------------------------------
+ // 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;
+ reg tb_cs;
+ reg tb_write_read;
+ reg [7 : 0] tb_address;
+ reg [31 : 0] tb_data_in;
+ wire [31 : 0] tb_data_out;
+
+ reg [31 : 0] read_data;
+ reg [255 : 0] digest_data;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ wb_sha256 dut(
+ .CLK_I(tb_clk),
+ .RST_I(tb_reset),
+
+ .STB_I(tb_cs),
+ .WE_I(tb_write_read),
+ .ACK_O(tb_ack),
+ .ERR_O(tb_err),
+
+ .ADR_I(tb_address),
+ .DAT_I(tb_data_in),
+ .DAT_O(tb_data_out)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor
+ //
+ // Generates a cycle counter and displays information about
+ // the dut as needed.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ #(2 * CLK_HALF_PERIOD);
+ cycle_ctr = cycle_ctr + 1;
+ 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("STB_I = 0x%01x, WE_I = 0x%01x",
+ dut.STB_I, dut.WE_I);
+ $display("ADR_I = 0x%02x", dut.ADR_I);
+ $display("DAT_I = 0x%08x, DAT_O = 0x%08x",
+ dut.DAT_I, dut.DAT_O);
+ $display("tmp_data_out = 0x%08x", dut.tmp_data_out);
+ $display("");
+
+ $display("Control and status:");
+ $display("ctrl = 0x%02x, status = 0x%02x",
+ {dut.next_reg, dut.init_reg},
+ {dut.digest_valid_reg, dut.ready_reg});
+ $display("");
+
+ $display("Message block:");
+ $display("block0 = 0x%08x, block1 = 0x%08x, block2 = 0x%08x, block3 = 0x%08x",
+ dut.block0_reg, dut.block1_reg, dut.block2_reg, dut.block3_reg);
+ $display("block4 = 0x%08x, block5 = 0x%08x, block6 = 0x%08x, block7 = 0x%08x",
+ dut.block4_reg, dut.block5_reg, dut.block6_reg, dut.block7_reg);
+
+ $display("block8 = 0x%08x, block9 = 0x%08x, block10 = 0x%08x, block11 = 0x%08x",
+ dut.block8_reg, dut.block9_reg, dut.block10_reg, dut.block11_reg);
+ $display("block12 = 0x%08x, block13 = 0x%08x, block14 = 0x%08x, block15 = 0x%08x",
+ dut.block12_reg, dut.block13_reg, dut.block14_reg, dut.block15_reg);
+ $display("");
+
+ $display("Digest:");
+ $display("digest = 0x%064x", dut.digest_reg);
+ $display("");
+
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggles reset to force the DUT into a well defined state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset = 1;
+ #(4 * CLK_HALF_PERIOD);
+ tb_reset = 0;
+ 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 = 32'h00000000;
+ error_ctr = 32'h00000000;
+ tc_ctr = 32'h00000000;
+
+ tb_clk = 0;
+ tb_reset = 0;
+ tb_cs = 0;
+ tb_write_read = 0;
+ tb_address = 6'h00;
+ tb_data_in = 32'h00000000;
+ end
+ endtask // init_dut
+
+
+ //----------------------------------------------------------------
+ // 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 completed.", tc_ctr);
+ $display("*** %02d errors detected during testing.", error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ // (Actually we wait for either ready or valid 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
+ read_data = 0;
+
+ while (read_data == 0)
+ begin
+ read_word(ADDR_STATUS);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [7 : 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_data_in = word;
+ tb_cs = 1;
+ tb_write_read = 1;
+ #(2 * CLK_HALF_PERIOD);
+ tb_cs = 0;
+ tb_write_read = 0;
+ end
+ endtask // write_word
+
+
+ //----------------------------------------------------------------
+ // write_block()
+ //
+ // Write the given block to the dut.
+ //----------------------------------------------------------------
+ task write_block(input [511 : 0] block);
+ begin
+ write_word(ADDR_BLOCK0, block[511 : 480]);
+ write_word(ADDR_BLOCK1, block[479 : 448]);
+ write_word(ADDR_BLOCK2, block[447 : 416]);
+ write_word(ADDR_BLOCK3, block[415 : 384]);
+ write_word(ADDR_BLOCK4, block[383 : 352]);
+ write_word(ADDR_BLOCK5, block[351 : 320]);
+ write_word(ADDR_BLOCK6, block[319 : 288]);
+ write_word(ADDR_BLOCK7, block[287 : 256]);
+ write_word(ADDR_BLOCK8, block[255 : 224]);
+ write_word(ADDR_BLOCK9, block[223 : 192]);
+ write_word(ADDR_BLOCK10, block[191 : 160]);
+ write_word(ADDR_BLOCK11, block[159 : 128]);
+ write_word(ADDR_BLOCK12, block[127 : 96]);
+ write_word(ADDR_BLOCK13, block[95 : 64]);
+ write_word(ADDR_BLOCK14, block[63 : 32]);
+ write_word(ADDR_BLOCK15, 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 [7 : 0] address);
+ begin
+ tb_address = address;
+ tb_cs = 1;
+ tb_write_read = 0;
+ #(2 * CLK_HALF_PERIOD);
+ read_data = tb_data_out;
+ tb_cs = 0;
+
+ if (DEBUG)
+ begin
+ $display("*** Reading 0x%08x from 0x%02x.", read_data, address);
+ $display("");
+ end
+ end
+ endtask // read_word
+
+
+ //----------------------------------------------------------------
+ // check_name_version()
+ //
+ // Read the name and version from the DUT.
+ //----------------------------------------------------------------
+ task check_name_version();
+ reg [31 : 0] name0;
+ reg [31 : 0] name1;
+ reg [31 : 0] version;
+ begin
+
+ read_word(ADDR_NAME0);
+ name0 = read_data;
+ read_word(ADDR_NAME1);
+ name1 = read_data;
+ read_word(ADDR_VERSION);
+ version = read_data;
+
+ $display("DUT name: %c%c%c%c%c%c%c%c",
+ name0[31 : 24], name0[23 : 16], name0[15 : 8], name0[7 : 0],
+ name1[31 : 24], name1[23 : 16], name1[15 : 8], name1[7 : 0]);
+ $display("DUT version: %c%c%c%c",
+ version[31 : 24], version[23 : 16], version[15 : 8], version[7 : 0]);
+ end
+ endtask // check_name_version
+
+
+ //----------------------------------------------------------------
+ // read_digest()
+ //
+ // Read the digest in the dut. The resulting digest will be
+ // available in the global variable digest_data.
+ //----------------------------------------------------------------
+ task read_digest();
+ begin
+ read_word(ADDR_DIGEST0);
+ digest_data[255 : 224] = read_data;
+ read_word(ADDR_DIGEST1);
+ digest_data[223 : 192] = read_data;
+ read_word(ADDR_DIGEST2);
+ digest_data[191 : 160] = read_data;
+ read_word(ADDR_DIGEST3);
+ digest_data[159 : 128] = read_data;
+ read_word(ADDR_DIGEST4);
+ digest_data[127 : 96] = read_data;
+ read_word(ADDR_DIGEST5);
+ digest_data[95 : 64] = read_data;
+ read_word(ADDR_DIGEST6);
+ digest_data[63 : 32] = read_data;
+ read_word(ADDR_DIGEST7);
+ digest_data[31 : 0] = read_data;
+ end
+ endtask // read_digest
+
+
+ //----------------------------------------------------------------
+ // single_block_test()
+ //
+ //
+ // Perform test of a single block digest.
+ //----------------------------------------------------------------
+ task single_block_test([511 : 0] block,
+ [255 : 0] expected);
+ begin
+ $display("*** TC%01d - Single block test started.", tc_ctr);
+
+ write_block(block);
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+ write_word(ADDR_CTRL, 8'h00);
+ wait_ready();
+ read_digest();
+
+ if (digest_data == expected)
+ begin
+ $display("TC%01d: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR.", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+ $display("*** TC%01d - Single block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test()
+ //
+ //
+ // Perform test of a double block digest. Note that we check
+ // the digests for both the first and final block.
+ //----------------------------------------------------------------
+ task double_block_test([511 : 0] block0,
+ [255 : 0] expected0,
+ [511 : 0] block1,
+ [255 : 0] expected1
+ );
+ begin
+ $display("*** TC%01d - Double block test started.", tc_ctr);
+
+ // First block
+ write_block(block0);
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+ write_word(ADDR_CTRL, 8'h00);
+ wait_ready();
+ read_digest();
+
+ if (digest_data == expected0)
+ begin
+ $display("TC%01d first block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in first digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected0);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ // Final block
+ write_block(block1);
+ write_word(ADDR_CTRL, CTRL_NEXT_VALUE);
+ write_word(ADDR_CTRL, 8'h00);
+ wait_ready();
+ read_digest();
+
+ if (digest_data == expected1)
+ begin
+ $display("TC%01d final block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in final digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected1);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ $display("*** TC%01d - Double block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // double_block_test
+
+
+ //----------------------------------------------------------------
+ // wb_sha256_test
+ //
+ // The main test functionality.
+ //
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf
+ //----------------------------------------------------------------
+ initial
+ begin : wb_sha256_test
+ reg [511 : 0] tc0;
+ reg [255 : 0] res0;
+
+ reg [511 : 0] tc1_0;
+ reg [255 : 0] res1_0;
+ reg [511 : 0] tc1_1;
+ reg [255 : 0] res1_1;
+
+ $display(" -- Testbench for wb_sha256 started --");
+
+ init_sim();
+ reset_dut();
+ check_name_version();
+
+ // dump_dut_state();
+ // write_word(ADDR_BLOCK0, 32'hdeadbeef);
+ // dump_dut_state();
+ // read_word(ADDR_BLOCK0);
+ // dump_dut_state();
+
+ tc0 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ res0 = 256'hBA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD;
+ single_block_test(tc0, res0);
+
+ tc1_0 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res1_0 = 256'h85E655D6417A17953363376A624CDE5C76E09589CAC5F811CC4B32C1F20E533A;
+ tc1_1 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res1_1 = 256'h248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1;
+ double_block_test(tc1_0, res1_0, tc1_1, res1_1);
+
+ display_test_result();
+
+ $display(" -- Testbench for wb_sha256 done. --");
+ $finish;
+ end // wb_sha256_test
+endmodule // tb_wb_sha256
+
+//======================================================================
+// EOF tb_wb_sha256.v
+//======================================================================
diff --git a/sha256/toolruns/Makefile b/sha256/toolruns/Makefile
new file mode 100755
index 0000000..4ac5f46
--- /dev/null
+++ b/sha256/toolruns/Makefile
@@ -0,0 +1,117 @@
+#===================================================================
+#
+# Makefile
+# --------
+# Makefile for building sha256 wmem, core top and wishbone
+# simulations.
+#
+#
+# Author: Joachim Strombergson
+# Copyright (c) 2014, SUNET
+#
+# 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.
+#
+#===================================================================
+
+WMEM_SRC=../src/rtl/sha256_w_mem.v
+WMEM_TB_SRC=../src/tb/tb_sha256_w_mem.v
+
+CORE_SRC=../src/rtl/sha256_core.v ../src/rtl/sha256_k_constants.v ../src/rtl/sha256_w_mem.v
+CORE_TB_SRC=../src/tb/tb_sha256_core.v
+
+TOP_SRC=../src/rtl/sha256.v $(CORE_SRC)
+TOP_TB_SRC=../src/tb/tb_sha256.v
+
+WB_SRC=../src/rtl/wb_sha256.v $(CORE_SRC)
+WB_TB_SRC=../src/tb/tb_wb_sha256.v
+
+CC=iverilog
+
+
+all: wb top core wmem
+
+
+wb: $(WB_TB_SRC) $(WB_SRC)
+ $(CC) -o wb.sim $(WB_TB_SRC) $(WB_SRC)
+
+
+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)
+
+
+wmem: $(WMEM_SRC) $(WMEM_TB_SRC)
+ $(CC) -o wmem.sim $(WMEM_SRC) $(WMEM_TB_SRC)
+
+
+sim-wb: wb.sim
+ ./wb.sim
+
+
+sim-top: top.sim
+ ./top.sim
+
+
+sim-core: core.sim
+ ./core.sim
+
+
+sim-wmem: wmem.sim
+ ./wmem.sim
+
+
+debug:
+ @echo "No debug available."
+
+
+clean:
+ rm -f top.sim
+ rm -f core.sim
+ rm -f wmem.sim
+
+
+help:
+ @echo "Supported targets:"
+ @echo "------------------"
+ @echo "all: Build all simulation targets."
+ @echo "wb: Build the Wishbone simulation target."
+ @echo "top: Build the top simulation target."
+ @echo "core: Build the core simulation target."
+ @echo "wmem: Build the wmem simulation target."
+ @echo "sim-wb: Run top Wishbone simulation."
+ @echo "sim-top: Run top level simulation."
+ @echo "sim-core: Run core level simulation."
+ @echo "sim-wmem: Run wmem level simulation."
+ @echo "debug: Print the internal varibles."
+ @echo "clean: Delete all built files."
+
+#===================================================================
+# EOF Makefile
+#===================================================================
+
diff --git a/sha512/LICENSE b/sha512/LICENSE
new file mode 100644
index 0000000..0fb159c
--- /dev/null
+++ b/sha512/LICENSE
@@ -0,0 +1,24 @@
+Author: Joachim Strömbergson
+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:
+
+* 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.
+
+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/sha512/README.md b/sha512/README.md
new file mode 100644
index 0000000..d6f4d92
--- /dev/null
+++ b/sha512/README.md
@@ -0,0 +1,41 @@
+sha512
+======
+
+Verilog implementation of the SHA-512 hash function. This implementation
+complies with the functionality in NIST FIPS 180-4. The supports the
+SHA-512 variants SHA-512/224, SHA-512/256, SHA-384 and SHA-512.
+
+
+## Implementation details ##
+The core uses a sliding window with 16 64-bit registers for the W
+memory. The top level wrapper contains flag control registers for init
+and next that automatically resets. This means that the flags must be
+set for every block to be processed.
+
+
+## Status ##
+***(2014-04-05)***
+
+RTL for the core and top is completed Testbenches for core and top
+completed. All single block and dual block test cases works. Results
+after building the complete design for Altera Cyclone V GX:
+
+- 2919 ALMs
+- 3609 Registers
+- 77 MHz max clock frequency
+
+
+***(2014-03-24)***
+
+Core works for the SHA-512 mode case. Added top level wrapper and built
+the design for Altera Cyclone V GX:
+
+- 2923 ALMs
+- 3609 Registers
+- 80 MHz max clock frequency
+
+
+
+***(2014-02-23)***
+
+Initial version. Based on the SHA-256 core. Nothing really to see yet.
diff --git a/sha512/src/model/python/sha512.py b/sha512/src/model/python/sha512.py
new file mode 100755
index 0000000..844c9ef
--- /dev/null
+++ b/sha512/src/model/python/sha512.py
@@ -0,0 +1,345 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#=======================================================================
+#
+# sha512.py
+# ---------
+# Simple, pure Python model of the SHA-512 hash function. Used as a
+# reference for the HW implementation. The code follows the structure
+# of the HW implementation as much as possible.
+#
+#
+# Author: Joachim Strömbergson
+# 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.
+#-------------------------------------------------------------------
+MAX_64BIT = 0xffffffffffffffff
+
+
+#-------------------------------------------------------------------
+# ChaCha()
+#-------------------------------------------------------------------
+class SHA512():
+ def __init__(self, mode = 'MODE_SHA_512', verbose = 0):
+ assert mode in ['MODE_SHA_512_224', 'MODE_SHA_512_256',
+ 'MODE_SHA_384', 'MODE_SHA_512']
+ self.mode = mode
+ self.verbose = verbose
+ self.mode
+ self.NUM_ROUNDS = 80
+ self.H = [0] * 8
+ self.t1 = 0
+ self.t2 = 0
+ self.a = 0
+ self.b = 0
+ self.c = 0
+ self.d = 0
+ self.e = 0
+ self.f = 0
+ self.g = 0
+ self.h = 0
+ self.w = 0
+ self.W = [0] * 16
+ self.k = 0
+ self.K = [0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
+ 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
+ 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
+ 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
+ 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
+ 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
+ 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
+ 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
+ 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
+ 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
+ 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
+ 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
+ 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
+ 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
+ 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
+ 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
+ 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
+ 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
+ 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
+ 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
+ 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
+ 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
+ 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
+ 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
+ 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
+ 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
+ 0x5fcb6fab3ad6faec, 0x6c44198c4a475817]
+
+
+ def init(self):
+ if self.mode == 'MODE_SHA_512_224':
+ self.H = [0x8c3d37c819544da2, 0x73e1996689dcd4d6,
+ 0x1dfab7ae32ff9c82, 0x679dd514582f9fcf,
+ 0x0f6d2b697bd44da8, 0x77e36f7304c48942,
+ 0x3f9d85a86a1d36c8, 0x1112e6ad91d692a1]
+
+ elif self.mode == 'MODE_SHA_512_256':
+ self.H = [0x22312194fc2bf72c, 0x9f555fa3c84c64c2,
+ 0x2393b86b6f53b151, 0x963877195940eabd,
+ 0x96283ee2a88effe3, 0xbe5e1e2553863992,
+ 0x2b0199fc2c85b8aa, 0x0eb72ddc81c52ca2]
+
+ elif self.mode == 'MODE_SHA_384':
+ self.H = [0xcbbb9d5dc1059ed8, 0x629a292a367cd507,
+ 0x9159015a3070dd17, 0x152fecd8f70e5939,
+ 0x67332667ffc00b31, 0x8eb44a8768581511,
+ 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4]
+
+ elif self.mode == 'MODE_SHA_512':
+ self.H = [0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
+ 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
+ 0x510e527fade682d1, 0x9b05688c2b3e6c1f,
+ 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179]
+
+
+ def next(self, block):
+ self._W_schedule(block)
+ self._copy_digest()
+ if self.verbose:
+ print("State after init:")
+ self._print_state(0)
+
+ for i in range(self.NUM_ROUNDS):
+ self._sha512_round(i)
+ if self.verbose:
+ self._print_state(i)
+
+ self._update_digest()
+
+
+ def get_digest(self):
+ if self.mode == 'MODE_SHA_512_224':
+ return self.H[0:3] # FIX THIS!
+
+ elif self.mode == 'MODE_SHA_512_256':
+ return self.H[0:4]
+
+ elif self.mode == 'MODE_SHA_384':
+ return self.H[0:6]
+
+ elif self.mode == 'MODE_SHA_512':
+ return self.H
+
+
+ def _copy_digest(self):
+ self.a = self.H[0]
+ self.b = self.H[1]
+ self.c = self.H[2]
+ self.d = self.H[3]
+ self.e = self.H[4]
+ self.f = self.H[5]
+ self.g = self.H[6]
+ self.h = self.H[7]
+
+
+ def _update_digest(self):
+ self.H[0] = (self.H[0] + self.a) & MAX_64BIT
+ self.H[1] = (self.H[1] + self.b) & MAX_64BIT
+ self.H[2] = (self.H[2] + self.c) & MAX_64BIT
+ self.H[3] = (self.H[3] + self.d) & MAX_64BIT
+ self.H[4] = (self.H[4] + self.e) & MAX_64BIT
+ self.H[5] = (self.H[5] + self.f) & MAX_64BIT
+ self.H[6] = (self.H[6] + self.g) & MAX_64BIT
+ self.H[7] = (self.H[7] + self.h) & MAX_64BIT
+
+
+ def _print_state(self, round):
+ print("State at round 0x%02x:" % round)
+ print("t1 = 0x%016x, t2 = 0x%016x" % (self.t1, self.t2))
+ print("k = 0x%016x, w = 0x%016x" % (self.k, self.w))
+ print("a = 0x%016x, b = 0x%016x" % (self.a, self.b))
+ print("c = 0x%016x, d = 0x%016x" % (self.c, self.d))
+ print("e = 0x%016x, f = 0x%016x" % (self.e, self.f))
+ print("g = 0x%016x, h = 0x%016x" % (self.g, self.h))
+ print("")
+
+
+ def _sha512_round(self, round):
+ self.k = self.K[round]
+ self.w = self._next_w(round)
+ self.t1 = self._T1(self.e, self.f, self.g, self.h, self.k, self.w)
+ self.t2 = self._T2(self.a, self.b, self.c)
+ self.h = self.g
+ self.g = self.f
+ self.f = self.e
+ self.e = (self.d + self.t1) & MAX_64BIT
+ self.d = self.c
+ self.c = self.b
+ self.b = self.a
+ self.a = (self.t1 + self.t2) & MAX_64BIT
+
+
+ def _next_w(self, round):
+ if (round < 16):
+ return self.W[round]
+
+ else:
+ tmp_w = (self._delta1(self.W[14]) +
+ self.W[9] +
+ self._delta0(self.W[1]) +
+ self.W[0]) & MAX_64BIT
+ for i in range(15):
+ self.W[i] = self.W[(i+1)]
+ self.W[15] = tmp_w
+ return tmp_w
+
+
+ def _W_schedule(self, block):
+ for i in range(16):
+ self.W[i] = block[i]
+
+
+ def _Ch(self, x, y, z):
+ return (x & y) ^ (~x & z)
+
+
+ def _Maj(self, x, y, z):
+ return (x & y) ^ (x & z) ^ (y & z)
+
+ def _sigma0(self, x):
+ return (self._rotr64(x, 28) ^ self._rotr64(x, 34) ^ self._rotr64(x, 39))
+
+
+ def _sigma1(self, x):
+ return (self._rotr64(x, 14) ^ self._rotr64(x, 18) ^ self._rotr64(x, 41))
+
+
+ def _delta0(self, x):
+ return (self._rotr64(x, 1) ^ self._rotr64(x, 8) ^ self._shr64(x, 7))
+
+
+ def _delta1(self, x):
+ return (self._rotr64(x, 19) ^ self._rotr64(x, 61) ^ self._shr64(x, 6))
+
+
+ def _T1(self, e, f, g, h, k, w):
+ return (h + self._sigma1(e) + self._Ch(e, f, g) + k + w) & MAX_64BIT
+
+
+ def _T2(self, a, b, c):
+ return (self._sigma0(a) + self._Maj(a, b, c)) & MAX_64BIT
+
+
+ def _rotr64(self, n, r):
+ return ((n >> r) | (n << (64 - r))) & MAX_64BIT
+
+
+ def _shr64(self, n, r):
+ return (n >> r)
+
+
+def compare_digests(digest, expected):
+ if (digest != expected):
+ print("Error:")
+ print("Got:")
+ print(digest)
+ print("Expected:")
+ print(expected)
+ else:
+ print("Test case ok.")
+
+
+#-------------------------------------------------------------------
+# main()
+#
+# If executed tests the ChaCha class using known test vectors.
+#-------------------------------------------------------------------
+def main():
+ print("Testing the SHA-512 Python model.")
+ print("---------------------------------")
+ print
+
+ # Single block message.
+ TC1_block = [0x6162638000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+ 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+ 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+ 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000018]
+
+
+ my_sha512 = SHA512(mode = 'MODE_SHA_512', verbose=1);
+ TC1_expected = [0xDDAF35A193617ABA, 0xCC417349AE204131, 0x12E6FA4E89A97EA2, 0x0A9EEEE64B55D39A,
+ 0x2192992A274FC1A8, 0x36BA3C23A3FEEBBD, 0x454D4423643CE80E, 0x2A9AC94FA54CA49F]
+ my_sha512.init()
+ my_sha512.next(TC1_block)
+ my_digest = my_sha512.get_digest()
+ compare_digests(my_digest, TC1_expected)
+
+
+ my_sha512 = SHA512(mode = 'MODE_SHA_512_224', verbose=1);
+ TC2_expected = [0x4634270F707B6A54, 0xDAAE7530460842E2, 0x0E37ED265CEEE9A4, 0x3E8924AA00000000]
+ my_sha512.init()
+ my_sha512.next(TC1_block)
+ my_digest = my_sha512.get_digest()
+ compare_digests(my_digest, TC2_expected)
+
+
+ my_sha512 = SHA512(mode = 'MODE_SHA_512_256', verbose=1);
+ TC3_expected = [0x53048E2681941EF9, 0x9B2E29B76B4C7DAB, 0xE4C2D0C634FC6D46, 0xE0E2F13107E7AF23]
+ my_sha512.init()
+ my_sha512.next(TC1_block)
+ my_digest = my_sha512.get_digest()
+ compare_digests(my_digest, TC3_expected)
+
+
+ my_sha512 = SHA512(mode = 'MODE_SHA_384', verbose=1);
+ TC4_expected = [0xCB00753F45A35E8B, 0xB5A03D699AC65007, 0x272C32AB0EDED163, 0x1A8B605A43FF5BED,
+ 0x8086072BA1E7CC23, 0x58BAECA134C825A7]
+ my_sha512.init()
+ my_sha512.next(TC1_block)
+ my_digest = my_sha512.get_digest()
+ compare_digests(my_digest, TC4_expected)
+
+
+
+#-------------------------------------------------------------------
+# __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 sha512.py
+#=======================================================================
diff --git a/sha512/src/rtl/sha512.v b/sha512/src/rtl/sha512.v
new file mode 100644
index 0000000..8826782
--- /dev/null
+++ b/sha512/src/rtl/sha512.v
@@ -0,0 +1,241 @@
+//======================================================================
+//
+// sha512.v
+// ------
+// Top level wrapper for the SHA-512 hash function providing
+// a simple memory like interface with 32 bit data access.
+//
+// Authors: Joachim Strömbergson, Paul Selkirk
+// Copyright (c) 2014-2015, 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 sha512(
+ // 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
+ );
+
+ //----------------------------------------------------------------
+ // 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 CTRL_MODE_LOW_BIT = 2;
+ parameter CTRL_MODE_HIGH_BIT = 3;
+ parameter CTRL_WORK_FACTOR_BIT = 7;
+
+ parameter ADDR_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_WORK_FACTOR_NUM = 8'h0a;
+
+ parameter ADDR_BLOCK = 8'h10;
+
+ parameter ADDR_DIGEST = 8'h40;
+
+ parameter CORE_NAME0 = 32'h73686132; // "sha2"
+ parameter CORE_NAME1 = 32'h2d353132; // "-512"
+ parameter CORE_VERSION = 32'h302e3830; // "0.80"
+
+ parameter MODE_SHA_512_224 = 2'h0;
+ parameter MODE_SHA_512_256 = 2'h1;
+ parameter MODE_SHA_384 = 2'h2;
+ parameter MODE_SHA_512 = 2'h3;
+
+ parameter DEFAULT_WORK_FACTOR_NUM = 32'h000f0000;
+
+ parameter BLOCK_BITS = 1024;
+ parameter DIGEST_BITS = 512;
+ parameter BLOCK_WORDS = BLOCK_BITS / 32;
+ parameter DIGEST_WORDS = DIGEST_BITS / 32;
+
+ //----------------------------------------------------------------
+ // Registers.
+ //----------------------------------------------------------------
+ reg [0 : BLOCK_BITS - 1] block_reg;
+ reg [0 : DIGEST_BITS - 1] digest_reg;
+ reg init_reg;
+ reg next_reg;
+ reg [1 : 0] mode_reg;
+ reg work_factor_reg;
+ reg [31 : 0] work_factor_num_reg;
+
+ reg [31 : 0] tmp_read_data;
+ reg [31 : 0] tmp_read_data_reg;
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ wire core_init;
+ wire core_next;
+ wire core_ready;
+ wire [1 : 0] core_mode;
+ wire core_work_factor;
+ wire [31 : 0] core_work_factor_num;
+ wire [0 : BLOCK_BITS - 1] core_block;
+ wire [0 : DIGEST_BITS - 1] core_digest;
+ wire core_digest_valid;
+
+ wire [31 : 0] core_name0 = CORE_NAME0;
+ wire [31 : 0] core_name1 = CORE_NAME1;
+ wire [31 : 0] core_version = CORE_VERSION;
+ wire [31 : 0] core_ctrl;
+ wire [31 : 0] core_status;
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign core_init = init_reg;
+ assign core_next = next_reg;
+ assign core_mode = mode_reg;
+ assign core_work_factor = work_factor_reg;
+ assign core_work_factor_num = work_factor_num_reg;
+ assign core_ctrl = {24'h000000, work_factor_reg, 3'b000,
+ mode_reg, next_reg, init_reg};
+ assign core_status = { 30'b0, core_digest_valid, core_ready };
+ assign core_block = block_reg;
+
+ assign read_data = tmp_read_data_reg;
+
+ //----------------------------------------------------------------
+ // core instantiation.
+ //----------------------------------------------------------------
+ sha512_core core(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .init(core_init),
+ .next(core_next),
+ .mode(core_mode),
+
+ .work_factor(core_work_factor),
+ .work_factor_num(core_work_factor_num),
+
+ .block(core_block),
+
+ .ready(core_ready),
+
+ .digest(core_digest),
+ .digest_valid(core_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // latch in digest when ready
+ //----------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (core_digest_valid)
+ digest_reg <= core_digest;
+ end
+
+ //----------------------------------------------------------------
+ // storage registers for mapping memory to core interface
+ //----------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ init_reg <= 0;
+ next_reg <= 0;
+ mode_reg <= MODE_SHA_512;
+ work_factor_reg <= 0;
+ work_factor_num_reg <= DEFAULT_WORK_FACTOR_NUM;
+
+ if (cs && we)
+ begin
+ // write operations
+ if ((address >= ADDR_BLOCK) &&
+ (address < ADDR_BLOCK + BLOCK_WORDS))
+ block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data;
+ else if (address == ADDR_CTRL)
+ begin
+ init_reg <= write_data[CTRL_INIT_BIT];
+ next_reg <= write_data[CTRL_NEXT_BIT];
+ mode_reg <= write_data[CTRL_MODE_HIGH_BIT : CTRL_MODE_LOW_BIT];
+ work_factor_reg <= write_data[CTRL_WORK_FACTOR_BIT];
+ end
+ else if (address == ADDR_WORK_FACTOR_NUM)
+ begin
+ work_factor_num_reg <= write_data;
+ end
+ end
+ end
+
+ always @*
+ begin
+ tmp_read_data = 32'h00000000;
+
+ if (cs && !we)
+ begin
+ // read operations
+ if ((address >= ADDR_BLOCK) &&
+ (address < ADDR_BLOCK + BLOCK_WORDS))
+ tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32];
+ else if ((address >= ADDR_DIGEST) &&
+ (address < ADDR_DIGEST + DIGEST_WORDS))
+ tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32];
+ else
+ case (address)
+ ADDR_NAME0:
+ tmp_read_data = core_name0;
+ ADDR_NAME1:
+ tmp_read_data = core_name1;
+ ADDR_VERSION:
+ tmp_read_data = core_version;
+ ADDR_CTRL:
+ tmp_read_data = core_ctrl;
+ ADDR_STATUS:
+ tmp_read_data = core_status;
+ ADDR_WORK_FACTOR_NUM:
+ tmp_read_data = work_factor_num_reg;
+ endcase
+ end
+ end
+
+ always @(posedge clk)
+ begin
+ tmp_read_data_reg <= tmp_read_data;
+ end
+
+endmodule // sha512
diff --git a/sha512/src/rtl/sha512_core.v b/sha512/src/rtl/sha512_core.v
new file mode 100644
index 0000000..12742a8
--- /dev/null
+++ b/sha512/src/rtl/sha512_core.v
@@ -0,0 +1,607 @@
+//======================================================================
+//
+// sha512_core.v
+// -------------
+// Verilog 2001 implementation of the SHA-512 hash function.
+// This is the internal core with wide interfaces.
+//
+//
+// 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 sha512_core(
+ input wire clk,
+ input wire reset_n,
+
+ input wire init,
+ input wire next,
+ input wire [1 : 0] mode,
+
+ input wire work_factor,
+ input wire [31 : 0] work_factor_num,
+
+ input wire [1023 : 0] block,
+
+ output wire ready,
+ output wire [511 : 0] digest,
+ output wire digest_valid
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter SHA512_ROUNDS = 79;
+
+ parameter CTRL_IDLE = 0;
+ parameter CTRL_ROUNDS = 1;
+ parameter CTRL_DONE = 2;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [63 : 0] a_reg;
+ reg [63 : 0] a_new;
+ reg [63 : 0] b_reg;
+ reg [63 : 0] b_new;
+ reg [63 : 0] c_reg;
+ reg [63 : 0] c_new;
+ reg [63 : 0] d_reg;
+ reg [63 : 0] d_new;
+ reg [63 : 0] e_reg;
+ reg [63 : 0] e_new;
+ reg [63 : 0] f_reg;
+ reg [63 : 0] f_new;
+ reg [63 : 0] g_reg;
+ reg [63 : 0] g_new;
+ reg [63 : 0] h_reg;
+ reg [63 : 0] h_new;
+ reg a_h_we;
+
+ reg [63 : 0] H0_reg;
+ reg [63 : 0] H0_new;
+ reg [63 : 0] H1_reg;
+ reg [63 : 0] H1_new;
+ reg [63 : 0] H2_reg;
+ reg [63 : 0] H2_new;
+ reg [63 : 0] H3_reg;
+ reg [63 : 0] H3_new;
+ reg [63 : 0] H4_reg;
+ reg [63 : 0] H4_new;
+ reg [63 : 0] H5_reg;
+ reg [63 : 0] H5_new;
+ reg [63 : 0] H6_reg;
+ reg [63 : 0] H6_new;
+ reg [63 : 0] H7_reg;
+ reg [63 : 0] H7_new;
+ reg H_we;
+
+ reg [6 : 0] t_ctr_reg;
+ reg [6 : 0] t_ctr_new;
+ reg t_ctr_we;
+ reg t_ctr_inc;
+ reg t_ctr_rst;
+
+ reg [31 : 0] work_factor_ctr_reg;
+ reg [31 : 0] work_factor_ctr_new;
+ reg work_factor_ctr_rst;
+ reg work_factor_ctr_inc;
+ reg work_factor_ctr_done;
+ reg work_factor_ctr_we;
+
+ reg digest_valid_reg;
+ reg digest_valid_new;
+ reg digest_valid_we;
+
+ reg [1 : 0] sha512_ctrl_reg;
+ reg [1 : 0] sha512_ctrl_new;
+ reg sha512_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg digest_init;
+ reg digest_update;
+
+ reg state_init;
+ reg state_update;
+
+ reg first_block;
+
+ reg ready_flag;
+
+ reg [63 : 0] t1;
+ reg [63 : 0] t2;
+
+ wire [63 : 0] k_data;
+
+ reg w_init;
+ reg w_next;
+ wire [63 : 0] w_data;
+
+ wire [63 : 0] H0_0;
+ wire [63 : 0] H0_1;
+ wire [63 : 0] H0_2;
+ wire [63 : 0] H0_3;
+ wire [63 : 0] H0_4;
+ wire [63 : 0] H0_5;
+ wire [63 : 0] H0_6;
+ wire [63 : 0] H0_7;
+
+
+ //----------------------------------------------------------------
+ // Module instantiantions.
+ //----------------------------------------------------------------
+ sha512_k_constants k_constants_inst(
+ .addr(t_ctr_reg),
+ .K(k_data)
+ );
+
+
+ sha512_h_constants h_constants_inst(
+ .mode(mode),
+
+ .H0(H0_0),
+ .H1(H0_1),
+ .H2(H0_2),
+ .H3(H0_3),
+ .H4(H0_4),
+ .H5(H0_5),
+ .H6(H0_6),
+ .H7(H0_7)
+ );
+
+
+ sha512_w_mem w_mem_inst(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .block(block),
+
+ .init(w_init),
+ .next(w_next),
+ .w(w_data)
+ );
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign ready = ready_flag;
+
+ assign digest = {H0_reg, H1_reg, H2_reg, H3_reg,
+ H4_reg, H5_reg, H6_reg, H7_reg};
+
+ assign digest_valid = digest_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
+ a_reg <= 64'h0000000000000000;
+ b_reg <= 64'h0000000000000000;
+ c_reg <= 64'h0000000000000000;
+ d_reg <= 64'h0000000000000000;
+ e_reg <= 64'h0000000000000000;
+ f_reg <= 64'h0000000000000000;
+ g_reg <= 64'h0000000000000000;
+ h_reg <= 64'h0000000000000000;
+ H0_reg <= 64'h0000000000000000;
+ H1_reg <= 64'h0000000000000000;
+ H2_reg <= 64'h0000000000000000;
+ H3_reg <= 64'h0000000000000000;
+ H4_reg <= 64'h0000000000000000;
+ H5_reg <= 64'h0000000000000000;
+ H6_reg <= 64'h0000000000000000;
+ H7_reg <= 64'h0000000000000000;
+ work_factor_ctr_reg <= 32'h00000000;
+ digest_valid_reg <= 0;
+ t_ctr_reg <= 7'h00;
+ sha512_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+
+ if (a_h_we)
+ begin
+ a_reg <= a_new;
+ b_reg <= b_new;
+ c_reg <= c_new;
+ d_reg <= d_new;
+ e_reg <= e_new;
+ f_reg <= f_new;
+ g_reg <= g_new;
+ h_reg <= h_new;
+ end
+
+ if (H_we)
+ begin
+ H0_reg <= H0_new;
+ H1_reg <= H1_new;
+ H2_reg <= H2_new;
+ H3_reg <= H3_new;
+ H4_reg <= H4_new;
+ H5_reg <= H5_new;
+ H6_reg <= H6_new;
+ H7_reg <= H7_new;
+ end
+
+ if (t_ctr_we)
+ begin
+ t_ctr_reg <= t_ctr_new;
+ end
+
+ if (work_factor_ctr_we)
+ begin
+ work_factor_ctr_reg <= work_factor_ctr_new;
+ end
+
+ if (digest_valid_we)
+ begin
+ digest_valid_reg <= digest_valid_new;
+ end
+
+ if (sha512_ctrl_we)
+ begin
+ sha512_ctrl_reg <= sha512_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // digest_logic
+ //
+ // The logic needed to init as well as update the digest.
+ //----------------------------------------------------------------
+ always @*
+ begin : digest_logic
+ H0_new = 64'h00000000;
+ H1_new = 64'h00000000;
+ H2_new = 64'h00000000;
+ H3_new = 64'h00000000;
+ H4_new = 64'h00000000;
+ H5_new = 64'h00000000;
+ H6_new = 64'h00000000;
+ H7_new = 64'h00000000;
+ H_we = 0;
+
+ if (digest_init)
+ begin
+ H0_new = H0_0;
+ H1_new = H0_1;
+ H2_new = H0_2;
+ H3_new = H0_3;
+ H4_new = H0_4;
+ H5_new = H0_5;
+ H6_new = H0_6;
+ H7_new = H0_7;
+ H_we = 1;
+ end
+
+ if (digest_update)
+ begin
+ H0_new = H0_reg + a_reg;
+ H1_new = H1_reg + b_reg;
+ H2_new = H2_reg + c_reg;
+ H3_new = H3_reg + d_reg;
+ H4_new = H4_reg + e_reg;
+ H5_new = H5_reg + f_reg;
+ H6_new = H6_reg + g_reg;
+ H7_new = H7_reg + h_reg;
+ H_we = 1;
+ end
+ end // digest_logic
+
+
+ //----------------------------------------------------------------
+ // t1_logic
+ //
+ // The logic for the T1 function.
+ //----------------------------------------------------------------
+ always @*
+ begin : t1_logic
+ reg [63 : 0] sum1;
+ reg [63 : 0] ch;
+
+ sum1 = {e_reg[13 : 0], e_reg[63 : 14]} ^
+ {e_reg[17 : 0], e_reg[63 : 18]} ^
+ {e_reg[40 : 0], e_reg[63 : 41]};
+
+ ch = (e_reg & f_reg) ^ ((~e_reg) & g_reg);
+
+ t1 = h_reg + sum1 + ch + k_data + w_data;
+ end // t1_logic
+
+
+ //----------------------------------------------------------------
+ // t2_logic
+ //
+ // The logic for the T2 function
+ //----------------------------------------------------------------
+ always @*
+ begin : t2_logic
+ reg [63 : 0] sum0;
+ reg [63 : 0] maj;
+
+ sum0 = {a_reg[27 : 0], a_reg[63 : 28]} ^
+ {a_reg[33 : 0], a_reg[63 : 34]} ^
+ {a_reg[38 : 0], a_reg[63 : 39]};
+
+ maj = (a_reg & b_reg) ^ (a_reg & c_reg) ^ (b_reg & c_reg);
+
+ t2 = sum0 + maj;
+ end // t2_logic
+
+
+ //----------------------------------------------------------------
+ // state_logic
+ //
+ // The logic needed to init as well as update the state during
+ // round processing.
+ //----------------------------------------------------------------
+ always @*
+ begin : state_logic
+ a_new = 64'h00000000;
+ b_new = 64'h00000000;
+ c_new = 64'h00000000;
+ d_new = 64'h00000000;
+ e_new = 64'h00000000;
+ f_new = 64'h00000000;
+ g_new = 64'h00000000;
+ h_new = 64'h00000000;
+ a_h_we = 0;
+
+ if (state_init)
+ begin
+ if (first_block)
+ begin
+ a_new = H0_0;
+ b_new = H0_1;
+ c_new = H0_2;
+ d_new = H0_3;
+ e_new = H0_4;
+ f_new = H0_5;
+ g_new = H0_6;
+ h_new = H0_7;
+ a_h_we = 1;
+ end
+ else
+ begin
+ a_new = H0_reg;
+ b_new = H1_reg;
+ c_new = H2_reg;
+ d_new = H3_reg;
+ e_new = H4_reg;
+ f_new = H5_reg;
+ g_new = H6_reg;
+ h_new = H7_reg;
+ a_h_we = 1;
+ end
+ end
+
+ if (state_update)
+ begin
+ a_new = t1 + t2;
+ b_new = a_reg;
+ c_new = b_reg;
+ d_new = c_reg;
+ e_new = d_reg + t1;
+ f_new = e_reg;
+ g_new = f_reg;
+ h_new = g_reg;
+ a_h_we = 1;
+ end
+ end // state_logic
+
+
+ //----------------------------------------------------------------
+ // t_ctr
+ //
+ // Update logic for the round counter, a monotonically
+ // increasing counter with reset.
+ //----------------------------------------------------------------
+ always @*
+ begin : t_ctr
+ t_ctr_new = 7'h00;
+ t_ctr_we = 0;
+
+ if (t_ctr_rst)
+ begin
+ t_ctr_new = 7'h00;
+ t_ctr_we = 1;
+ end
+
+ if (t_ctr_inc)
+ begin
+ t_ctr_new = t_ctr_reg + 1'b1;
+ t_ctr_we = 1;
+ end
+ end // t_ctr
+
+
+ //----------------------------------------------------------------
+ // work_factor_ctr
+ //
+ // Work factor counter logic.
+ //----------------------------------------------------------------
+ always @*
+ begin : work_factor_ctr
+ work_factor_ctr_new = 32'h00000000;
+ work_factor_ctr_we = 0;
+ work_factor_ctr_done = 0;
+
+ if (work_factor_ctr_reg == work_factor_num)
+ begin
+ work_factor_ctr_done = 1;
+ end
+
+ if (work_factor_ctr_rst)
+ begin
+ work_factor_ctr_new = 32'h00000000;
+ work_factor_ctr_we = 1;
+ end
+
+ if (work_factor_ctr_inc)
+ begin
+ work_factor_ctr_new = work_factor_ctr_reg + 1'b1;
+ work_factor_ctr_we = 1;
+ end
+ end // work_factor_ctr
+
+
+ //----------------------------------------------------------------
+ // sha512_ctrl_fsm
+ //
+ // Logic for the state machine controlling the core behaviour.
+ //----------------------------------------------------------------
+ always @*
+ begin : sha512_ctrl_fsm
+ digest_init = 0;
+ digest_update = 0;
+
+ state_init = 0;
+ state_update = 0;
+
+ first_block = 0;
+ ready_flag = 0;
+
+ w_init = 0;
+ w_next = 0;
+
+ t_ctr_inc = 0;
+ t_ctr_rst = 0;
+
+ digest_valid_new = 0;
+ digest_valid_we = 0;
+
+ work_factor_ctr_rst = 0;
+ work_factor_ctr_inc = 0;
+
+ sha512_ctrl_new = CTRL_IDLE;
+ sha512_ctrl_we = 0;
+
+
+ case (sha512_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ ready_flag = 1;
+
+ if (init)
+ begin
+ work_factor_ctr_rst = 1;
+ digest_init = 1;
+ w_init = 1;
+ state_init = 1;
+ first_block = 1;
+ t_ctr_rst = 1;
+ digest_valid_new = 0;
+ digest_valid_we = 1;
+ sha512_ctrl_new = CTRL_ROUNDS;
+ sha512_ctrl_we = 1;
+ end
+
+ if (next)
+ begin
+ work_factor_ctr_rst = 1;
+ w_init = 1;
+ state_init = 1;
+ t_ctr_rst = 1;
+ digest_valid_new = 0;
+ digest_valid_we = 1;
+ sha512_ctrl_new = CTRL_ROUNDS;
+ sha512_ctrl_we = 1;
+ end
+ end
+
+
+ CTRL_ROUNDS:
+ begin
+ w_next = 1;
+ state_update = 1;
+ t_ctr_inc = 1;
+
+ if (t_ctr_reg == SHA512_ROUNDS)
+ begin
+ work_factor_ctr_inc = 1;
+ sha512_ctrl_new = CTRL_DONE;
+ sha512_ctrl_we = 1;
+ end
+ end
+
+
+ CTRL_DONE:
+ begin
+ if (work_factor)
+ begin
+ if (!work_factor_ctr_done)
+ begin
+ w_init = 1;
+ state_init = 1;
+ t_ctr_rst = 1;
+ sha512_ctrl_new = CTRL_ROUNDS;
+ sha512_ctrl_we = 1;
+ end
+ else
+ begin
+ digest_update = 1;
+ digest_valid_new = 1;
+ digest_valid_we = 1;
+ sha512_ctrl_new = CTRL_IDLE;
+ sha512_ctrl_we = 1;
+ end
+ end
+ else
+ begin
+ digest_update = 1;
+ digest_valid_new = 1;
+ digest_valid_we = 1;
+ sha512_ctrl_new = CTRL_IDLE;
+ sha512_ctrl_we = 1;
+ end
+ end
+ endcase // case (sha512_ctrl_reg)
+ end // sha512_ctrl_fsm
+
+endmodule // sha512_core
+
+//======================================================================
+// EOF sha512_core.v
+//======================================================================
diff --git a/sha512/src/rtl/sha512_h_constants.v b/sha512/src/rtl/sha512_h_constants.v
new file mode 100644
index 0000000..3a38712
--- /dev/null
+++ b/sha512/src/rtl/sha512_h_constants.v
@@ -0,0 +1,143 @@
+//======================================================================
+//
+// sha512_h_constants.v
+// ---------------------
+// The H initial constants for the different modes in SHA-512.
+//
+//
+// 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 sha512_h_constants(
+ input wire [1 : 0] mode,
+
+ output wire [63 : 0] H0,
+ output wire [63 : 0] H1,
+ output wire [63 : 0] H2,
+ output wire [63 : 0] H3,
+ output wire [63 : 0] H4,
+ output wire [63 : 0] H5,
+ output wire [63 : 0] H6,
+ output wire [63 : 0] H7
+ );
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [63 : 0] tmp_H0;
+ reg [63 : 0] tmp_H1;
+ reg [63 : 0] tmp_H2;
+ reg [63 : 0] tmp_H3;
+ reg [63 : 0] tmp_H4;
+ reg [63 : 0] tmp_H5;
+ reg [63 : 0] tmp_H6;
+ reg [63 : 0] tmp_H7;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign H0 = tmp_H0;
+ assign H1 = tmp_H1;
+ assign H2 = tmp_H2;
+ assign H3 = tmp_H3;
+ assign H4 = tmp_H4;
+ assign H5 = tmp_H5;
+ assign H6 = tmp_H6;
+ assign H7 = tmp_H7;
+
+
+ //----------------------------------------------------------------
+ // mode_mux
+ //
+ // Based on the given mode, the correct H constants are selected.
+ //----------------------------------------------------------------
+ always @*
+ begin : mode_mux
+ case(mode)
+ 0:
+ begin
+ // SHA-512/224
+ tmp_H0 = 64'h8c3d37c819544da2;
+ tmp_H1 = 64'h73e1996689dcd4d6;
+ tmp_H2 = 64'h1dfab7ae32ff9c82;
+ tmp_H3 = 64'h679dd514582f9fcf;
+ tmp_H4 = 64'h0f6d2b697bd44da8;
+ tmp_H5 = 64'h77e36f7304c48942;
+ tmp_H6 = 64'h3f9d85a86a1d36c8;
+ tmp_H7 = 64'h1112e6ad91d692a1;
+ end
+
+ 1:
+ begin
+ // SHA-512/256
+ tmp_H0 = 64'h22312194fc2bf72c;
+ tmp_H1 = 64'h9f555fa3c84c64c2;
+ tmp_H2 = 64'h2393b86b6f53b151;
+ tmp_H3 = 64'h963877195940eabd;
+ tmp_H4 = 64'h96283ee2a88effe3;
+ tmp_H5 = 64'hbe5e1e2553863992;
+ tmp_H6 = 64'h2b0199fc2c85b8aa;
+ tmp_H7 = 64'h0eb72ddc81c52ca2;
+ end
+
+ 2:
+ begin
+ // SHA-384
+ tmp_H0 = 64'hcbbb9d5dc1059ed8;
+ tmp_H1 = 64'h629a292a367cd507;
+ tmp_H2 = 64'h9159015a3070dd17;
+ tmp_H3 = 64'h152fecd8f70e5939;
+ tmp_H4 = 64'h67332667ffc00b31;
+ tmp_H5 = 64'h8eb44a8768581511;
+ tmp_H6 = 64'hdb0c2e0d64f98fa7;
+ tmp_H7 = 64'h47b5481dbefa4fa4;
+ end
+
+ 3:
+ begin
+ // SHA-512
+ tmp_H0 = 64'h6a09e667f3bcc908;
+ tmp_H1 = 64'hbb67ae8584caa73b;
+ tmp_H2 = 64'h3c6ef372fe94f82b;
+ tmp_H3 = 64'ha54ff53a5f1d36f1;
+ tmp_H4 = 64'h510e527fade682d1;
+ tmp_H5 = 64'h9b05688c2b3e6c1f;
+ tmp_H6 = 64'h1f83d9abfb41bd6b;
+ tmp_H7 = 64'h5be0cd19137e2179;
+ end
+ endcase // case (addr)
+ end // block: mode_mux
+endmodule // sha512_h_constants
+
+//======================================================================
+// sha512_h_constants.v
+//======================================================================
diff --git a/sha512/src/rtl/sha512_k_constants.v b/sha512/src/rtl/sha512_k_constants.v
new file mode 100644
index 0000000..61cfb6d
--- /dev/null
+++ b/sha512/src/rtl/sha512_k_constants.v
@@ -0,0 +1,472 @@
+//======================================================================
+//
+// sha512_k_constants.v
+// --------------------
+// The table K with constants in the SHA-512 hash function.
+//
+//
+// 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 sha512_k_constants(
+ input wire [6 : 0] addr,
+ output wire [63 : 0] K
+ );
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [63 : 0] tmp_K;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign K = tmp_K;
+
+
+ //----------------------------------------------------------------
+ // addr_mux
+ //----------------------------------------------------------------
+ always @*
+ begin : addr_mux
+ case(addr)
+ 0:
+ begin
+ tmp_K = 64'h428a2f98d728ae22;
+ end
+
+ 1:
+ begin
+ tmp_K = 64'h7137449123ef65cd;
+ end
+
+ 2:
+ begin
+ tmp_K = 64'hb5c0fbcfec4d3b2f;
+ end
+
+ 3:
+ begin
+ tmp_K = 64'he9b5dba58189dbbc;
+ end
+
+ 4:
+ begin
+ tmp_K = 64'h3956c25bf348b538;
+ end
+
+ 5:
+ begin
+ tmp_K = 64'h59f111f1b605d019;
+ end
+
+ 6:
+ begin
+ tmp_K = 64'h923f82a4af194f9b;
+ end
+
+ 7:
+ begin
+ tmp_K = 64'hab1c5ed5da6d8118;
+ end
+
+ 8:
+ begin
+ tmp_K = 64'hd807aa98a3030242;
+ end
+
+ 9:
+ begin
+ tmp_K = 64'h12835b0145706fbe;
+ end
+
+ 10:
+ begin
+ tmp_K = 64'h243185be4ee4b28c;
+ end
+
+ 11:
+ begin
+ tmp_K = 64'h550c7dc3d5ffb4e2;
+ end
+
+ 12:
+ begin
+ tmp_K = 64'h72be5d74f27b896f;
+ end
+
+ 13:
+ begin
+ tmp_K = 64'h80deb1fe3b1696b1;
+ end
+
+ 14:
+ begin
+ tmp_K = 64'h9bdc06a725c71235;
+ end
+
+ 15:
+ begin
+ tmp_K = 64'hc19bf174cf692694;
+ end
+
+ 16:
+ begin
+ tmp_K = 64'he49b69c19ef14ad2;
+ end
+
+ 17:
+ begin
+ tmp_K = 64'hefbe4786384f25e3;
+ end
+
+ 18:
+ begin
+ tmp_K = 64'h0fc19dc68b8cd5b5;
+ end
+
+ 19:
+ begin
+ tmp_K = 64'h240ca1cc77ac9c65;
+ end
+
+ 20:
+ begin
+ tmp_K = 64'h2de92c6f592b0275;
+ end
+
+ 21:
+ begin
+ tmp_K = 64'h4a7484aa6ea6e483;
+ end
+
+ 22:
+ begin
+ tmp_K = 64'h5cb0a9dcbd41fbd4;
+ end
+
+ 23:
+ begin
+ tmp_K = 64'h76f988da831153b5;
+ end
+
+ 24:
+ begin
+ tmp_K = 64'h983e5152ee66dfab;
+ end
+
+ 25:
+ begin
+ tmp_K = 64'ha831c66d2db43210;
+ end
+
+ 26:
+ begin
+ tmp_K = 64'hb00327c898fb213f;
+ end
+
+ 27:
+ begin
+ tmp_K = 64'hbf597fc7beef0ee4;
+ end
+
+ 28:
+ begin
+ tmp_K = 64'hc6e00bf33da88fc2;
+ end
+
+ 29:
+ begin
+ tmp_K = 64'hd5a79147930aa725;
+ end
+
+ 30:
+ begin
+ tmp_K = 64'h06ca6351e003826f;
+ end
+
+ 31:
+ begin
+ tmp_K = 64'h142929670a0e6e70;
+ end
+
+ 32:
+ begin
+ tmp_K = 64'h27b70a8546d22ffc;
+ end
+
+ 33:
+ begin
+ tmp_K = 64'h2e1b21385c26c926;
+ end
+
+ 34:
+ begin
+ tmp_K = 64'h4d2c6dfc5ac42aed;
+ end
+
+ 35:
+ begin
+ tmp_K = 64'h53380d139d95b3df;
+ end
+
+ 36:
+ begin
+ tmp_K = 64'h650a73548baf63de;
+ end
+
+ 37:
+ begin
+ tmp_K = 64'h766a0abb3c77b2a8;
+ end
+
+ 38:
+ begin
+ tmp_K = 64'h81c2c92e47edaee6;
+ end
+
+ 39:
+ begin
+ tmp_K = 64'h92722c851482353b;
+ end
+
+ 40:
+ begin
+ tmp_K = 64'ha2bfe8a14cf10364;
+ end
+
+ 41:
+ begin
+ tmp_K = 64'ha81a664bbc423001;
+ end
+
+ 42:
+ begin
+ tmp_K = 64'hc24b8b70d0f89791;
+ end
+
+ 43:
+ begin
+ tmp_K = 64'hc76c51a30654be30;
+ end
+
+ 44:
+ begin
+ tmp_K = 64'hd192e819d6ef5218;
+ end
+
+ 45:
+ begin
+ tmp_K = 64'hd69906245565a910;
+ end
+
+ 46:
+ begin
+ tmp_K = 64'hf40e35855771202a;
+ end
+
+ 47:
+ begin
+ tmp_K = 64'h106aa07032bbd1b8;
+ end
+
+ 48:
+ begin
+ tmp_K = 64'h19a4c116b8d2d0c8;
+ end
+
+ 49:
+ begin
+ tmp_K = 64'h1e376c085141ab53;
+ end
+
+ 50:
+ begin
+ tmp_K = 64'h2748774cdf8eeb99;
+ end
+
+ 51:
+ begin
+ tmp_K = 64'h34b0bcb5e19b48a8;
+ end
+
+ 52:
+ begin
+ tmp_K = 64'h391c0cb3c5c95a63;
+ end
+
+ 53:
+ begin
+ tmp_K = 64'h4ed8aa4ae3418acb;
+ end
+
+ 54:
+ begin
+ tmp_K = 64'h5b9cca4f7763e373;
+ end
+
+ 55:
+ begin
+ tmp_K = 64'h682e6ff3d6b2b8a3;
+ end
+
+ 56:
+ begin
+ tmp_K = 64'h748f82ee5defb2fc;
+ end
+
+ 57:
+ begin
+ tmp_K = 64'h78a5636f43172f60;
+ end
+
+ 58:
+ begin
+ tmp_K = 64'h84c87814a1f0ab72;
+ end
+
+ 59:
+ begin
+ tmp_K = 64'h8cc702081a6439ec;
+ end
+
+ 60:
+ begin
+ tmp_K = 64'h90befffa23631e28;
+ end
+
+ 61:
+ begin
+ tmp_K = 64'ha4506cebde82bde9;
+ end
+
+ 62:
+ begin
+ tmp_K = 64'hbef9a3f7b2c67915;
+ end
+
+ 63:
+ begin
+ tmp_K = 64'hc67178f2e372532b;
+ end
+
+ 64:
+ begin
+ tmp_K = 64'hca273eceea26619c;
+ end
+
+ 65:
+ begin
+ tmp_K = 64'hd186b8c721c0c207;
+ end
+
+ 66:
+ begin
+ tmp_K = 64'heada7dd6cde0eb1e;
+ end
+
+ 67:
+ begin
+ tmp_K = 64'hf57d4f7fee6ed178;
+ end
+
+ 68:
+ begin
+ tmp_K = 64'h06f067aa72176fba;
+ end
+
+ 69:
+ begin
+ tmp_K = 64'h0a637dc5a2c898a6;
+ end
+
+ 70:
+ begin
+ tmp_K = 64'h113f9804bef90dae;
+ end
+
+ 71:
+ begin
+ tmp_K = 64'h1b710b35131c471b;
+ end
+
+ 72:
+ begin
+ tmp_K = 64'h28db77f523047d84;
+ end
+
+ 73:
+ begin
+ tmp_K = 64'h32caab7b40c72493;
+ end
+
+ 74:
+ begin
+ tmp_K = 64'h3c9ebe0a15c9bebc;
+ end
+
+ 75:
+ begin
+ tmp_K = 64'h431d67c49c100d4c;
+ end
+
+ 76:
+ begin
+ tmp_K = 64'h4cc5d4becb3e42b6;
+ end
+
+ 77:
+ begin
+ tmp_K = 64'h597f299cfc657e2a;
+ end
+
+ 78:
+ begin
+ tmp_K = 64'h5fcb6fab3ad6faec;
+ end
+
+ 79:
+ begin
+ tmp_K = 64'h6c44198c4a475817;
+ end
+
+ default:
+ begin
+ tmp_K = 64'h0000000000000000;
+ end
+ endcase // case (addr)
+ end // block: addr_mux
+endmodule // sha512_k_constants
+
+//======================================================================
+// sha512_k_constants.v
+//======================================================================
diff --git a/sha512/src/rtl/sha512_w_mem.v b/sha512/src/rtl/sha512_w_mem.v
new file mode 100644
index 0000000..824316d
--- /dev/null
+++ b/sha512/src/rtl/sha512_w_mem.v
@@ -0,0 +1,346 @@
+//======================================================================
+//
+// sha512_w_mem_regs.v
+// -------------------
+// The W memory for the SHA-512 core. This version uses 16
+// 32-bit registers as a sliding window to generate the 64 words.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014 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 sha512_w_mem(
+ input wire clk,
+ input wire reset_n,
+
+ input wire [1023 : 0] block,
+
+ input wire init,
+ input wire next,
+ output wire [63 : 0] w
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter CTRL_IDLE = 1'b0;
+ parameter CTRL_UPDATE = 1'b1;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [63 : 0] w_mem [0 : 15];
+ reg [63 : 0] w_mem00_new;
+ reg [63 : 0] w_mem01_new;
+ reg [63 : 0] w_mem02_new;
+ reg [63 : 0] w_mem03_new;
+ reg [63 : 0] w_mem04_new;
+ reg [63 : 0] w_mem05_new;
+ reg [63 : 0] w_mem06_new;
+ reg [63 : 0] w_mem07_new;
+ reg [63 : 0] w_mem08_new;
+ reg [63 : 0] w_mem09_new;
+ reg [63 : 0] w_mem10_new;
+ reg [63 : 0] w_mem11_new;
+ reg [63 : 0] w_mem12_new;
+ reg [63 : 0] w_mem13_new;
+ reg [63 : 0] w_mem14_new;
+ reg [63 : 0] w_mem15_new;
+ reg w_mem_we;
+
+ reg [6 : 0] w_ctr_reg;
+ reg [6 : 0] w_ctr_new;
+ reg w_ctr_we;
+ reg w_ctr_inc;
+ reg w_ctr_rst;
+
+ reg sha512_w_mem_ctrl_reg;
+ reg sha512_w_mem_ctrl_new;
+ reg sha512_w_mem_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [63 : 0] w_tmp;
+ reg [63 : 0] w_new;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign w = w_tmp;
+
+
+ //----------------------------------------------------------------
+ // 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
+ w_mem[00] <= 64'h0000000000000000;
+ w_mem[01] <= 64'h0000000000000000;
+ w_mem[02] <= 64'h0000000000000000;
+ w_mem[03] <= 64'h0000000000000000;
+ w_mem[04] <= 64'h0000000000000000;
+ w_mem[05] <= 64'h0000000000000000;
+ w_mem[06] <= 64'h0000000000000000;
+ w_mem[07] <= 64'h0000000000000000;
+ w_mem[08] <= 64'h0000000000000000;
+ w_mem[09] <= 64'h0000000000000000;
+ w_mem[10] <= 64'h0000000000000000;
+ w_mem[11] <= 64'h0000000000000000;
+ w_mem[12] <= 64'h0000000000000000;
+ w_mem[13] <= 64'h0000000000000000;
+ w_mem[14] <= 64'h0000000000000000;
+ w_mem[15] <= 64'h0000000000000000;
+ w_ctr_reg <= 7'h00;
+ sha512_w_mem_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+ if (w_mem_we)
+ begin
+ w_mem[00] <= w_mem00_new;
+ w_mem[01] <= w_mem01_new;
+ w_mem[02] <= w_mem02_new;
+ w_mem[03] <= w_mem03_new;
+ w_mem[04] <= w_mem04_new;
+ w_mem[05] <= w_mem05_new;
+ w_mem[06] <= w_mem06_new;
+ w_mem[07] <= w_mem07_new;
+ w_mem[08] <= w_mem08_new;
+ w_mem[09] <= w_mem09_new;
+ w_mem[10] <= w_mem10_new;
+ w_mem[11] <= w_mem11_new;
+ w_mem[12] <= w_mem12_new;
+ w_mem[13] <= w_mem13_new;
+ w_mem[14] <= w_mem14_new;
+ w_mem[15] <= w_mem15_new;
+ end
+
+ if (w_ctr_we)
+ begin
+ w_ctr_reg <= w_ctr_new;
+ end
+
+ if (sha512_w_mem_ctrl_we)
+ begin
+ sha512_w_mem_ctrl_reg <= sha512_w_mem_ctrl_new;
+ end
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // select_w
+ //
+ // Mux for the external read operation. This is where we exract
+ // the W variable.
+ //----------------------------------------------------------------
+ always @*
+ begin : select_w
+ if (w_ctr_reg < 16)
+ begin
+ w_tmp = w_mem[w_ctr_reg[3 : 0]];
+ end
+ else
+ begin
+ w_tmp = w_new;
+ end
+ end // select_w
+
+
+ //----------------------------------------------------------------
+ // w_new_logic
+ //
+ // Logic that calculates the next value to be inserted into
+ // the sliding window of the memory.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_mem_update_logic
+ reg [63 : 0] w_0;
+ reg [63 : 0] w_1;
+ reg [63 : 0] w_9;
+ reg [63 : 0] w_14;
+ reg [63 : 0] d0;
+ reg [63 : 0] d1;
+
+ w_mem00_new = 64'h0000000000000000;
+ w_mem01_new = 64'h0000000000000000;
+ w_mem02_new = 64'h0000000000000000;
+ w_mem03_new = 64'h0000000000000000;
+ w_mem04_new = 64'h0000000000000000;
+ w_mem05_new = 64'h0000000000000000;
+ w_mem06_new = 64'h0000000000000000;
+ w_mem07_new = 64'h0000000000000000;
+ w_mem08_new = 64'h0000000000000000;
+ w_mem09_new = 64'h0000000000000000;
+ w_mem10_new = 64'h0000000000000000;
+ w_mem11_new = 64'h0000000000000000;
+ w_mem12_new = 64'h0000000000000000;
+ w_mem13_new = 64'h0000000000000000;
+ w_mem14_new = 64'h0000000000000000;
+ w_mem15_new = 64'h0000000000000000;
+ w_mem_we = 0;
+
+ w_0 = w_mem[0];
+ w_1 = w_mem[1];
+ w_9 = w_mem[9];
+ w_14 = w_mem[14];
+
+ d0 = {w_1[0], w_1[63 : 1]} ^ // ROTR1
+ {w_1[7 : 0], w_1[63 : 8]} ^ // ROTR8
+ {7'b0000000, w_1[63 : 7]}; // SHR7
+
+ d1 = {w_14[18 : 0], w_14[63 : 19]} ^ // ROTR19
+ {w_14[60 : 0], w_14[63 : 61]} ^ // ROTR61
+ {6'b000000, w_14[63 : 6]}; // SHR6
+
+ w_new = w_0 + d0 + w_9 + d1;
+
+ if (init)
+ begin
+ w_mem00_new = block[1023 : 960];
+ w_mem01_new = block[959 : 896];
+ w_mem02_new = block[895 : 832];
+ w_mem03_new = block[831 : 768];
+ w_mem04_new = block[767 : 704];
+ w_mem05_new = block[703 : 640];
+ w_mem06_new = block[639 : 576];
+ w_mem07_new = block[575 : 512];
+ w_mem08_new = block[511 : 448];
+ w_mem09_new = block[447 : 384];
+ w_mem10_new = block[383 : 320];
+ w_mem11_new = block[319 : 256];
+ w_mem12_new = block[255 : 192];
+ w_mem13_new = block[191 : 128];
+ w_mem14_new = block[127 : 64];
+ w_mem15_new = block[63 : 0];
+ w_mem_we = 1;
+ end
+ else if (w_ctr_reg > 15)
+ begin
+ w_mem00_new = w_mem[01];
+ w_mem01_new = w_mem[02];
+ w_mem02_new = w_mem[03];
+ w_mem03_new = w_mem[04];
+ w_mem04_new = w_mem[05];
+ w_mem05_new = w_mem[06];
+ w_mem06_new = w_mem[07];
+ w_mem07_new = w_mem[08];
+ w_mem08_new = w_mem[09];
+ w_mem09_new = w_mem[10];
+ w_mem10_new = w_mem[11];
+ w_mem11_new = w_mem[12];
+ w_mem12_new = w_mem[13];
+ w_mem13_new = w_mem[14];
+ w_mem14_new = w_mem[15];
+ w_mem15_new = w_new;
+ w_mem_we = 1;
+ end
+ end // w_mem_update_logic
+
+
+ //----------------------------------------------------------------
+ // w_ctr
+ // W schedule adress counter. Counts from 0x10 to 0x3f and
+ // is used to expand the block into words.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_ctr
+ w_ctr_new = 0;
+ w_ctr_we = 0;
+
+ if (w_ctr_rst)
+ begin
+ w_ctr_new = 7'h00;
+ w_ctr_we = 1;
+ end
+
+ if (w_ctr_inc)
+ begin
+ w_ctr_new = w_ctr_reg + 7'h01;
+ w_ctr_we = 1;
+ end
+ end // w_ctr
+
+
+ //----------------------------------------------------------------
+ // sha512_w_mem_fsm
+ // Logic for the w shedule FSM.
+ //----------------------------------------------------------------
+ always @*
+ begin : sha512_w_mem_fsm
+ w_ctr_rst = 0;
+ w_ctr_inc = 0;
+
+ sha512_w_mem_ctrl_new = CTRL_IDLE;
+ sha512_w_mem_ctrl_we = 0;
+
+ case (sha512_w_mem_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ if (init)
+ begin
+ w_ctr_rst = 1;
+ sha512_w_mem_ctrl_new = CTRL_UPDATE;
+ sha512_w_mem_ctrl_we = 1;
+ end
+ end
+
+ CTRL_UPDATE:
+ begin
+ if (next)
+ begin
+ w_ctr_inc = 1;
+ end
+
+ if (w_ctr_reg == 7'h3f)
+ begin
+ sha512_w_mem_ctrl_new = CTRL_IDLE;
+ sha512_w_mem_ctrl_we = 1;
+ end
+ end
+ endcase // case (sha512_ctrl_reg)
+ end // sha512_ctrl_fsm
+
+endmodule // sha512_w_mem
+
+//======================================================================
+// sha512_w_mem.v
+//======================================================================
diff --git a/sha512/src/tb/tb_sha512.v b/sha512/src/tb/tb_sha512.v
new file mode 100644
index 0000000..c993cfc
--- /dev/null
+++ b/sha512/src/tb/tb_sha512.v
@@ -0,0 +1,798 @@
+//======================================================================
+//
+// tb_sha512.v
+// -----------
+// Testbench for the SHA-512 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/10ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_sha512();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_PERIOD = 2;
+ parameter CLK_HALF_PERIOD = CLK_PERIOD / 2;
+
+
+ // The 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_MODE_LOW_BIT = 2;
+ parameter CTRL_MODE_HIGH_BIT = 3;
+ parameter CTRL_WORK_FACTOR_BIT = 7;
+
+ parameter ADDR_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_WORK_FACTOR_NUM = 8'h0a;
+
+ parameter ADDR_BLOCK0 = 8'h10;
+ parameter ADDR_BLOCK1 = 8'h11;
+ parameter ADDR_BLOCK2 = 8'h12;
+ parameter ADDR_BLOCK3 = 8'h13;
+ parameter ADDR_BLOCK4 = 8'h14;
+ parameter ADDR_BLOCK5 = 8'h15;
+ parameter ADDR_BLOCK6 = 8'h16;
+ parameter ADDR_BLOCK7 = 8'h17;
+ parameter ADDR_BLOCK8 = 8'h18;
+ parameter ADDR_BLOCK9 = 8'h19;
+ parameter ADDR_BLOCK10 = 8'h1a;
+ parameter ADDR_BLOCK11 = 8'h1b;
+ parameter ADDR_BLOCK12 = 8'h1c;
+ parameter ADDR_BLOCK13 = 8'h1d;
+ parameter ADDR_BLOCK14 = 8'h1e;
+ parameter ADDR_BLOCK15 = 8'h1f;
+ parameter ADDR_BLOCK16 = 8'h20;
+ parameter ADDR_BLOCK17 = 8'h21;
+ parameter ADDR_BLOCK18 = 8'h22;
+ parameter ADDR_BLOCK19 = 8'h23;
+ parameter ADDR_BLOCK20 = 8'h24;
+ parameter ADDR_BLOCK21 = 8'h25;
+ parameter ADDR_BLOCK22 = 8'h26;
+ parameter ADDR_BLOCK23 = 8'h27;
+ parameter ADDR_BLOCK24 = 8'h28;
+ parameter ADDR_BLOCK25 = 8'h29;
+ parameter ADDR_BLOCK26 = 8'h2a;
+ parameter ADDR_BLOCK27 = 8'h2b;
+ parameter ADDR_BLOCK28 = 8'h2c;
+ parameter ADDR_BLOCK29 = 8'h2d;
+ parameter ADDR_BLOCK30 = 8'h2e;
+ parameter ADDR_BLOCK31 = 8'h2f;
+
+ parameter ADDR_DIGEST0 = 8'h40;
+ parameter ADDR_DIGEST1 = 8'h41;
+ parameter ADDR_DIGEST2 = 8'h42;
+ parameter ADDR_DIGEST3 = 8'h43;
+ parameter ADDR_DIGEST4 = 8'h44;
+ parameter ADDR_DIGEST5 = 8'h45;
+ parameter ADDR_DIGEST6 = 8'h46;
+ parameter ADDR_DIGEST7 = 8'h47;
+ parameter ADDR_DIGEST8 = 8'h48;
+ parameter ADDR_DIGEST9 = 8'h49;
+ parameter ADDR_DIGEST10 = 8'h4a;
+ parameter ADDR_DIGEST11 = 8'h4b;
+ parameter ADDR_DIGEST12 = 8'h4c;
+ parameter ADDR_DIGEST13 = 8'h4d;
+ parameter ADDR_DIGEST14 = 8'h4e;
+ parameter ADDR_DIGEST15 = 8'h4f;
+
+ parameter MODE_SHA_512_224 = 2'h0;
+ parameter MODE_SHA_512_256 = 2'h1;
+ parameter MODE_SHA_384 = 2'h2;
+ parameter MODE_SHA_512 = 2'h3;
+
+ parameter CTRL_INIT_VALUE = 2'h1;
+ parameter CTRL_NEXT_VALUE = 2'h2;
+ parameter CTRL_WORK_FACTOR_VALUE = 1'h1;
+
+
+ //----------------------------------------------------------------
+ // 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 [31 : 0] read_data;
+ reg [511 : 0] digest_data;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha512 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)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor
+ //
+ // Generates a cycle counter and displays information about
+ // the dut as needed.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ #(2 * CLK_HALF_PERIOD);
+ cycle_ctr = cycle_ctr + 1;
+ 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("cs = 0x%01x, we = 0x%01x",
+ dut.cs, dut.we);
+ $display("address = 0x%02x", dut.address);
+ $display("write_data = 0x%08x, read_data = 0x%08x",
+ dut.write_data, dut.read_data);
+ $display("tmp_read_data = 0x%08x", dut.tmp_read_data);
+ $display("");
+
+ $display("Control and status:");
+ $display("ctrl = 0x%02x, status = 0x%02x",
+ {dut.next_reg, dut.init_reg},
+ {dut.digest_valid_reg, dut.ready_reg});
+ $display("");
+
+ $display("Message block:");
+ $display("block0 = 0x%08x, block1 = 0x%08x, block2 = 0x%08x, block3 = 0x%08x",
+ dut.block0_reg, dut.block1_reg, dut.block2_reg, dut.block3_reg);
+ $display("block4 = 0x%08x, block5 = 0x%08x, block6 = 0x%08x, block7 = 0x%08x",
+ dut.block4_reg, dut.block5_reg, dut.block6_reg, dut.block7_reg);
+
+ $display("block8 = 0x%08x, block9 = 0x%08x, block10 = 0x%08x, block11 = 0x%08x",
+ dut.block8_reg, dut.block9_reg, dut.block10_reg, dut.block11_reg);
+ $display("block12 = 0x%08x, block13 = 0x%08x, block14 = 0x%08x, block15 = 0x%08x",
+ dut.block12_reg, dut.block13_reg, dut.block14_reg, dut.block15_reg);
+
+ $display("block16 = 0x%08x, block17 = 0x%08x, block18 = 0x%08x, block19 = 0x%08x",
+ dut.block16_reg, dut.block17_reg, dut.block18_reg, dut.block19_reg);
+ $display("block20 = 0x%08x, block21 = 0x%08x, block22 = 0x%08x, block23 = 0x%08x",
+ dut.block20_reg, dut.block21_reg, dut.block22_reg, dut.block23_reg);
+
+ $display("block24 = 0x%08x, block25 = 0x%08x, block26 = 0x%08x, block27 = 0x%08x",
+ dut.block24_reg, dut.block25_reg, dut.block26_reg, dut.block27_reg);
+ $display("block28 = 0x%08x, block29 = 0x%08x, block30 = 0x%08x, block31 = 0x%08x",
+ dut.block28_reg, dut.block29_reg, dut.block30_reg, dut.block31_reg);
+
+ $display("");
+
+ $display("Digest:");
+ $display("digest = 0x%0128x", dut.digest_reg);
+ $display("");
+
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggles reset to force the DUT into a well defined state.
+ //----------------------------------------------------------------
+ task reset_dut();
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+
+ #(4 * CLK_HALF_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 = 32'h00000000;
+ error_ctr = 32'h00000000;
+ tc_ctr = 32'h00000000;
+
+ tb_clk = 0;
+ tb_reset_n = 0;
+ tb_cs = 0;
+ tb_we = 0;
+ tb_address = 6'h00;
+ tb_write_data = 32'h00000000;
+ end
+ endtask // init_dut
+
+
+ //----------------------------------------------------------------
+ // 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 completed.", tc_ctr);
+ $display("*** %02d errors detected during testing.", error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ // (Actually we wait for either ready or valid 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
+ read_data = 0;
+
+ while (read_data == 0)
+ begin
+ read_word(ADDR_STATUS);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [7 : 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_HALF_PERIOD);
+ tb_cs = 0;
+ tb_we = 0;
+ end
+ endtask // write_word
+
+
+ //----------------------------------------------------------------
+ // write_block()
+ //
+ // Write the given block to the dut.
+ //----------------------------------------------------------------
+ task write_block(input [1023 : 0] block);
+ begin
+ write_word(ADDR_BLOCK0, block[1023 : 992]);
+ write_word(ADDR_BLOCK1, block[991 : 960]);
+ write_word(ADDR_BLOCK2, block[959 : 928]);
+ write_word(ADDR_BLOCK3, block[927 : 896]);
+ write_word(ADDR_BLOCK4, block[895 : 864]);
+ write_word(ADDR_BLOCK5, block[863 : 832]);
+ write_word(ADDR_BLOCK6, block[831 : 800]);
+ write_word(ADDR_BLOCK7, block[799 : 768]);
+ write_word(ADDR_BLOCK8, block[767 : 736]);
+ write_word(ADDR_BLOCK9, block[735 : 704]);
+ write_word(ADDR_BLOCK10, block[703 : 672]);
+ write_word(ADDR_BLOCK11, block[671 : 640]);
+ write_word(ADDR_BLOCK12, block[639 : 608]);
+ write_word(ADDR_BLOCK13, block[607 : 576]);
+ write_word(ADDR_BLOCK14, block[575 : 544]);
+ write_word(ADDR_BLOCK15, block[543 : 512]);
+ write_word(ADDR_BLOCK16, block[511 : 480]);
+ write_word(ADDR_BLOCK17, block[479 : 448]);
+ write_word(ADDR_BLOCK18, block[447 : 416]);
+ write_word(ADDR_BLOCK19, block[415 : 384]);
+ write_word(ADDR_BLOCK20, block[383 : 352]);
+ write_word(ADDR_BLOCK21, block[351 : 320]);
+ write_word(ADDR_BLOCK22, block[319 : 288]);
+ write_word(ADDR_BLOCK23, block[287 : 256]);
+ write_word(ADDR_BLOCK24, block[255 : 224]);
+ write_word(ADDR_BLOCK25, block[223 : 192]);
+ write_word(ADDR_BLOCK26, block[191 : 160]);
+ write_word(ADDR_BLOCK27, block[159 : 128]);
+ write_word(ADDR_BLOCK28, block[127 : 96]);
+ write_word(ADDR_BLOCK29, block[95 : 64]);
+ write_word(ADDR_BLOCK30, block[63 : 32]);
+ write_word(ADDR_BLOCK31, 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 [7 : 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
+
+
+ //----------------------------------------------------------------
+ // check_name_version()
+ //
+ // Read the name and version from the DUT.
+ //----------------------------------------------------------------
+ task check_name_version();
+ reg [31 : 0] name0;
+ reg [31 : 0] name1;
+ reg [31 : 0] version;
+ begin
+
+ read_word(ADDR_NAME0);
+ name0 = read_data;
+ read_word(ADDR_NAME1);
+ name1 = read_data;
+ read_word(ADDR_VERSION);
+ version = read_data;
+
+ $display("DUT name: %c%c%c%c%c%c%c%c",
+ name0[31 : 24], name0[23 : 16], name0[15 : 8], name0[7 : 0],
+ name1[31 : 24], name1[23 : 16], name1[15 : 8], name1[7 : 0]);
+ $display("DUT version: %c%c%c%c",
+ version[31 : 24], version[23 : 16], version[15 : 8], version[7 : 0]);
+ end
+ endtask // check_name_version
+
+
+ //----------------------------------------------------------------
+ // read_digest()
+ //
+ // Read the digest in the dut. The resulting digest will be
+ // available in the global variable digest_data.
+ //----------------------------------------------------------------
+ task read_digest();
+ begin
+ read_word(ADDR_DIGEST0);
+ digest_data[511 : 480] = read_data;
+ read_word(ADDR_DIGEST1);
+ digest_data[479 : 448] = read_data;
+ read_word(ADDR_DIGEST2);
+ digest_data[447 : 416] = read_data;
+ read_word(ADDR_DIGEST3);
+ digest_data[415 : 384] = read_data;
+ read_word(ADDR_DIGEST4);
+ digest_data[383 : 352] = read_data;
+ read_word(ADDR_DIGEST5);
+ digest_data[351 : 320] = read_data;
+ read_word(ADDR_DIGEST6);
+ digest_data[319 : 288] = read_data;
+ read_word(ADDR_DIGEST7);
+ digest_data[287 : 256] = read_data;
+
+ read_word(ADDR_DIGEST8);
+ digest_data[255 : 224] = read_data;
+ read_word(ADDR_DIGEST9);
+ digest_data[223 : 192] = read_data;
+ read_word(ADDR_DIGEST10);
+ digest_data[191 : 160] = read_data;
+ read_word(ADDR_DIGEST11);
+ digest_data[159 : 128] = read_data;
+ read_word(ADDR_DIGEST12);
+ digest_data[127 : 96] = read_data;
+ read_word(ADDR_DIGEST13);
+ digest_data[95 : 64] = read_data;
+ read_word(ADDR_DIGEST14);
+ digest_data[63 : 32] = read_data;
+ read_word(ADDR_DIGEST15);
+ digest_data[31 : 0] = read_data;
+ end
+ endtask // read_digest
+
+
+ //----------------------------------------------------------------
+ // get_mask()
+ //
+ // Create the mask needed for a given mode.
+ //----------------------------------------------------------------
+ function [511 : 0] get_mask(input [1 : 0] mode);
+ begin
+ case (mode)
+ MODE_SHA_512_224:
+ begin
+ if (DEBUG)
+ begin
+ $display("Mode MODE_SHA_512_224");
+ end
+ get_mask = {{7{32'hffffffff}}, {9{32'h00000000}}};
+ end
+
+ MODE_SHA_512_256:
+ begin
+ if (DEBUG)
+ begin
+ $display("Mode MODE_SHA_512_256");
+ end
+ get_mask = {{8{32'hffffffff}}, {8{32'h00000000}}};
+ end
+
+ MODE_SHA_384:
+ begin
+ if (DEBUG)
+ begin
+ $display("Mode MODE_SHA_512_384");
+ end
+ get_mask = {{12{32'hffffffff}}, {4{32'h00000000}}};
+ end
+
+ MODE_SHA_512:
+ begin
+ if (DEBUG)
+ begin
+ $display("Mode MODE_SHA_512");
+ end
+ get_mask = {16{32'hffffffff}};
+ end
+ endcase // case (mode)
+ end
+ endfunction // get_mask
+
+
+ //----------------------------------------------------------------
+ // single_block_test()
+ //
+ //
+ // Perform test of a single block digest.
+ //----------------------------------------------------------------
+ task single_block_test(input [7 : 0] tc_number,
+ input [1 : 0] mode,
+ input [1023 : 0] block,
+ input [511 : 0] expected);
+
+ reg [511 : 0] mask;
+ reg [511 : 0] masked_data;
+
+ begin
+ $display("*** TC%01d - Single block test started.", tc_ctr);
+
+ write_block(block);
+ write_word(ADDR_CTRL, {28'h0000000, mode, CTRL_INIT_VALUE});
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ mask = get_mask(mode);
+ masked_data = digest_data & mask;
+
+ if (DEBUG)
+ begin
+ $display("masked_data = 0x%0128x", masked_data);
+ end
+
+ if (masked_data == expected)
+ begin
+ $display("TC%01d: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR.", tc_ctr);
+ $display("TC%01d: Expected: 0x%0128x", tc_ctr, expected);
+ $display("TC%01d: Got: 0x%0128x", tc_ctr, masked_data);
+ error_ctr = error_ctr + 1;
+ end
+ $display("*** TC%01d - Single block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test()
+ //
+ //
+ // Perform test of a double block digest. Note that we check
+ // the digests for both the first and final block.
+ //----------------------------------------------------------------
+ task double_block_test(input [7 : 0] tc_number,
+ input [1 : 0] mode,
+ input [1023 : 0] block0,
+ input [1023 : 0] block1,
+ input [511 : 0] expected0,
+ input [511 : 0] expected1
+ );
+ reg [511 : 0] mask;
+ reg [511 : 0] masked_data1;
+ reg [31 : 0] ctrl_cmd;
+
+ begin
+ $display("*** TC%01d - Double block test started.", tc_ctr);
+
+ // First block
+ write_block(block0);
+ write_word(ADDR_CTRL, {28'h0000000, mode, CTRL_INIT_VALUE});
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ if (digest_data == expected0)
+ begin
+ $display("TC%01d first block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in first digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected0);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ // Final block
+ write_block(block1);
+ write_word(ADDR_CTRL, {28'h0000000, mode, CTRL_NEXT_VALUE});
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ mask = get_mask(mode);
+ masked_data1 = digest_data & mask;
+
+ if (masked_data1 == expected1)
+ begin
+ $display("TC%01d final block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in final digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%0128x", tc_ctr, expected1);
+ $display("TC%01d: Got: 0x%0128x", tc_ctr, masked_data1);
+ error_ctr = error_ctr + 1;
+ end
+
+ $display("*** TC%01d - Double block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // double_block_test
+
+
+ //----------------------------------------------------------------
+ // work_factor_test()
+ //
+ // Perform test of the work factor function.
+ //----------------------------------------------------------------
+ task work_factor_test();
+ reg [1023 : 0] my_block;
+ reg [511 : 0] my_digest;
+ reg [31 : 0] my_ctrl_cmd;
+
+ begin
+ $display("*** TC%01d - Work factor test started.", tc_ctr);
+
+ // Read out work factor number.
+ read_word(ADDR_WORK_FACTOR_NUM);
+
+ // Trying to change the work factor number.
+ write_word(ADDR_WORK_FACTOR_NUM, 32'h00000003);
+ read_word(ADDR_WORK_FACTOR_NUM);
+
+ // Set block to all zero
+ my_block = {16{64'h0000000000000000}};
+ write_block(my_block);
+
+ // Set init+ work factor. We use SHA-512 mode.
+ my_ctrl_cmd = 32'h00000000 + (CTRL_WORK_FACTOR_VALUE << 7) +
+ (MODE_SHA_512 << 2) + CTRL_INIT_VALUE;
+ write_word(ADDR_CTRL, my_ctrl_cmd);
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ $display("*** TC%01d - Work factor test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // work_factor_test
+
+
+ //----------------------------------------------------------------
+ // sha512_test
+ // The main test functionality.
+ //
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
+ //----------------------------------------------------------------
+ initial
+ begin : sha512_test
+ reg [1024 : 0] single_block;
+ reg [511 : 0] tc1_expected;
+ reg [511 : 0] tc2_expected;
+ reg [511 : 0] tc3_expected;
+ reg [511 : 0] tc4_expected;
+
+ reg [1024 : 0] double_block_one;
+ reg [1024 : 0] double_block_two;
+ reg [511 : 0] tc5_expected;
+ reg [511 : 0] tc6_expected;
+ reg [511 : 0] tc7_expected;
+ reg [511 : 0] tc8_expected;
+ reg [511 : 0] tc9_expected;
+ reg [511 : 0] tc10_expected;
+ reg [511 : 0] tc11_expected;
+ reg [511 : 0] tc12_expected;
+
+ $display(" -- Testbench for sha512 started --");
+
+ init_sim();
+ reset_dut();
+ check_name_version();
+
+ // dump_dut_state();
+ // write_word(ADDR_BLOCK0, 32'hdeadbeef);
+ dump_dut_state();
+ // read_word(ADDR_BLOCK0);
+ // dump_dut_state();
+
+ // Single block test mesage.
+ single_block = 1024'h6162638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+
+ // SHA-512 single block digest and test.
+ tc1_expected = 512'hDDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F;
+ single_block_test(8'h01, MODE_SHA_512, single_block, tc1_expected);
+
+ // SHA-512_224 single block digest and test.
+ tc2_expected = {224'h4634270F707B6A54DAAE7530460842E20E37ED265CEEE9A43E8924AA, {9{32'h00000000}}};
+ single_block_test(8'h02, MODE_SHA_512_224, single_block, tc2_expected);
+
+ // SHA-512_256 single block digest and test.
+ tc3_expected = {256'h53048E2681941EF99B2E29B76B4C7DABE4C2D0C634FC6D46E0E2F13107E7AF23, {8{32'h00000000}}};
+ single_block_test(8'h03, MODE_SHA_512_256, single_block, tc3_expected);
+
+ // SHA-384 single block digest and test.
+ tc4_expected = {384'hCB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7, {4{32'h00000000}}};
+ single_block_test(8'h04, MODE_SHA_384, single_block, tc4_expected);
+
+
+ // Two block test message.
+ double_block_one = 1024'h61626364656667686263646566676869636465666768696A6465666768696A6B65666768696A6B6C666768696A6B6C6D6768696A6B6C6D6E68696A6B6C6D6E6F696A6B6C6D6E6F706A6B6C6D6E6F70716B6C6D6E6F7071726C6D6E6F707172736D6E6F70717273746E6F70717273747580000000000000000000000000000000;
+ double_block_two = 1024'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000380;
+
+ // SHA-512 two block digests and test.
+ tc5_expected = 512'h4319017A2B706E69CD4B05938BAE5E890186BF199F30AA956EF8B71D2F810585D787D6764B20BDA2A26014470973692000EC057F37D14B8E06ADD5B50E671C72;
+ tc6_expected = 512'h8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA17299AEADB6889018501D289E4900F7E4331B99DEC4B5433AC7D329EEB6DD26545E96E55B874BE909;
+ double_block_test(8'h05, MODE_SHA_512, double_block_one, double_block_two, tc5_expected, tc6_expected);
+
+ // SHA-512_224 two block digests and test.
+ tc7_expected = 512'h9606CB2DB7823CE75FE35E2674A8F9EF1417ED9E89C412BB54EA29664586108625852563EED495096DEBAAE2F4737FD75319224B135486F8E6C0F55E700C35B3;
+ tc8_expected = {224'h23FEC5BB94D60B23308192640B0C453335D664734FE40E7268674AF9, {9{32'h00000000}}};
+ double_block_test(8'h06, MODE_SHA_512_224, double_block_one, double_block_two, tc7_expected, tc8_expected);
+
+ // SHA-512_256 two block digests and test.
+ tc9_expected = 512'h8DD99EB081311F8BCBBBC42CC7AFB288E8E9408730419D1E953FF7A2B194048DAE24175483C44C7C809B348E8E88E3ECBF2EA614CEED9C5B51807937F11867E1;
+ tc10_expected = {256'h3928E184FB8690F840DA3988121D31BE65CB9D3EF83EE6146FEAC861E19B563A, {8{32'h00000000}}};
+ double_block_test(8'h07, MODE_SHA_512_256, double_block_one, double_block_two, tc9_expected, tc10_expected);
+
+ // SHA-384 two block digests and test.
+ tc11_expected = 512'h2A7F1D895FD58E0BEAAE96D1A673C741015A2173796C1A88F6352CA156ACAFF7C662113E9EBB4D6417B61A85E2CCF0A937EB9A6660FEB5198F2EBE9A81E6A2C5;
+ tc12_expected = {384'h09330C33F71147E83D192FC782CD1B4753111B173B3B05D22FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039, {4{32'h00000000}}};
+ double_block_test(8'h08, MODE_SHA_384, double_block_one, double_block_two, tc11_expected, tc12_expected);
+
+ // Work factor test.
+ work_factor_test();
+
+ dump_dut_state();
+
+ display_test_result();
+
+ $display(" -- Testbench for sha512 done. --");
+ $finish;
+ end // sha512_test
+endmodule // tb_sha512
+
+//======================================================================
+// EOF tb_sha512.v
+//======================================================================
diff --git a/sha512/src/tb/tb_sha512_core.v b/sha512/src/tb/tb_sha512_core.v
new file mode 100644
index 0000000..e4d3bb8
--- /dev/null
+++ b/sha512/src/tb/tb_sha512_core.v
@@ -0,0 +1,535 @@
+//======================================================================
+//
+// tb_sha512_core.v
+// ----------------
+// Testbench for the SHA-512 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/10ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_sha512_core();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_PERIOD = 2;
+ parameter CLK_HALF_PERIOD = CLK_PERIOD / 2;
+
+ parameter MODE_SHA_512_224 = 0;
+ parameter MODE_SHA_512_256 = 1;
+ parameter MODE_SHA_384 = 2;
+ parameter MODE_SHA_512 = 3;
+
+
+ //----------------------------------------------------------------
+ // 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_init;
+ reg tb_next;
+ reg [1 : 0] tb_mode;
+ reg [1023 : 0] tb_block;
+ wire tb_ready;
+ wire [511 : 0] tb_digest;
+ wire tb_digest_valid;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha512_core dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .init(tb_init),
+ .next(tb_next),
+ .mode(tb_mode),
+
+ .block(tb_block),
+
+ .ready(tb_ready),
+
+ .digest(tb_digest),
+ .digest_valid(tb_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // 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 dut.
+ //----------------------------------------------------------------
+ task dump_dut_state();
+ begin
+ $display("State of DUT");
+ $display("------------");
+ $display("Inputs and outputs:");
+ $display("init = 0x%01x, next = 0x%01x. mode = 0x%01x",
+ dut.init, dut.next, dut.mode);
+ $display("block = 0x%0128x", dut.block);
+
+ $display("ready = 0x%01x, valid = 0x%01x",
+ dut.ready, dut.digest_valid);
+ $display("digest = 0x%064x", dut.digest);
+ $display("H0_reg = 0x%08x, H1_reg = 0x%08x, H2_reg = 0x%08x, H3_reg = 0x%08x",
+ dut.H0_reg, dut.H1_reg, dut.H2_reg, dut.H3_reg);
+ $display("H4_reg = 0x%08x, H5_reg = 0x%08x, H6_reg = 0x%08x, H7_reg = 0x%08x",
+ dut.H4_reg, dut.H5_reg, dut.H6_reg, dut.H7_reg);
+ $display("");
+
+ $display("Control signals and counter:");
+ $display("sha512_ctrl_reg = 0x%02x", dut.sha512_ctrl_reg);
+ $display("digest_init = 0x%01x, digest_update = 0x%01x",
+ dut.digest_init, dut.digest_update);
+ $display("state_init = 0x%01x, state_update = 0x%01x",
+ dut.state_init, dut.state_update);
+ $display("first_block = 0x%01x, ready_flag = 0x%01x, w_init = 0x%01x",
+ dut.first_block, dut.ready_flag, dut.w_init);
+ $display("t_ctr_inc = 0x%01x, t_ctr_rst = 0x%01x, t_ctr_reg = 0x%02x",
+ dut.t_ctr_inc, dut.t_ctr_rst, dut.t_ctr_reg);
+ $display("");
+
+ $display("State registers:");
+ $display("a_reg = 0x%08x, b_reg = 0x%08x, c_reg = 0x%08x, d_reg = 0x%08x",
+ dut.a_reg, dut.b_reg, dut.c_reg, dut.d_reg);
+ $display("e_reg = 0x%08x, f_reg = 0x%08x, g_reg = 0x%08x, h_reg = 0x%08x",
+ dut.e_reg, dut.f_reg, dut.g_reg, dut.h_reg);
+ $display("");
+ $display("a_new = 0x%08x, b_new = 0x%08x, c_new = 0x%08x, d_new = 0x%08x",
+ dut.a_new, dut.b_new, dut.c_new, dut.d_new);
+ $display("e_new = 0x%08x, f_new = 0x%08x, g_new = 0x%08x, h_new = 0x%08x",
+ dut.e_new, dut.f_new, dut.g_new, dut.h_new);
+ $display("");
+
+ $display("State update values:");
+ $display("w = 0x%08x, k = 0x%08x", dut.w_data, dut.k_data);
+ $display("t1 = 0x%08x, t2 = 0x%08x", dut.t1, dut.t2);
+ $display("");
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // dump_dut_wmem()
+ //
+ // Dump the state of the dut wmem.
+ //----------------------------------------------------------------
+ task dump_dut_wmem();
+ begin
+ $display("State of DUT WMEM");
+ $display("-----------------");
+ $display("W[00] = 0x%016x, W[01] = 0x%016x, W[02] = 0x%016x, W[03] = 0x%016x",
+ dut.w_mem_inst.w_mem[00], dut.w_mem_inst.w_mem[01],
+ dut.w_mem_inst.w_mem[02], dut.w_mem_inst.w_mem[03]);
+ $display("W[04] = 0x%016x, W[05] = 0x%016x, W[06] = 0x%016x, W[07] = 0x%016x",
+ dut.w_mem_inst.w_mem[04], dut.w_mem_inst.w_mem[05],
+ dut.w_mem_inst.w_mem[06], dut.w_mem_inst.w_mem[07]);
+ $display("W[08] = 0x%016x, W[09] = 0x%016x, W[10] = 0x%016x, W[11] = 0x%016x",
+ dut.w_mem_inst.w_mem[08], dut.w_mem_inst.w_mem[09],
+ dut.w_mem_inst.w_mem[10], dut.w_mem_inst.w_mem[11]);
+ $display("W[12] = 0x%016x, W[13] = 0x%016x, W[14] = 0x%016x, W[15] = 0x%016x",
+ dut.w_mem_inst.w_mem[12], dut.w_mem_inst.w_mem[13],
+ dut.w_mem_inst.w_mem[14], dut.w_mem_inst.w_mem[15]);
+ $display("");
+ end
+ endtask // dump_dut_wmem
+
+
+ //----------------------------------------------------------------
+ // 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_init = 0;
+ tb_next = 0;
+ tb_next = 2'b00;
+ tb_mode = 2'b00;
+ tb_block = {32{32'h00000000}};
+ end
+ endtask // init_dut
+
+
+ //----------------------------------------------------------------
+ // 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
+
+
+ //----------------------------------------------------------------
+ // 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
+ #(2 * CLK_PERIOD);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // single_block_test()
+ //
+ // Run a test case spanning a single data block.
+ //----------------------------------------------------------------
+ task single_block_test(input [7 : 0] tc_number,
+ input [1 : 0] mode,
+ input [1023 : 0] block,
+ input [511 : 0] expected);
+ reg [511 : 0] mask;
+
+ begin
+ $display("*** TC %0d single block test case started.", tc_number);
+ tc_ctr = tc_ctr + 1;
+
+ tb_block = block;
+ tb_mode = mode;
+ tb_init = 1;
+ #(2 * CLK_PERIOD);
+ tb_init = 0;
+
+ wait_ready();
+
+ case (mode)
+ MODE_SHA_512_224:
+ begin
+ mask = {{7{32'hffffffff}}, {9{32'h00000000}}};
+ end
+
+ MODE_SHA_512_256:
+ begin
+ mask = {{8{32'hffffffff}}, {8{32'h00000000}}};
+ end
+
+ MODE_SHA_384:
+ begin
+ mask = {{12{32'hffffffff}}, {4{32'h00000000}}};
+ end
+
+ MODE_SHA_512:
+ begin
+ mask = {16{32'hffffffff}};
+ end
+ endcase // case (mode)
+
+ if ((tb_digest & mask) == expected)
+ begin
+ $display("*** TC %0d successful.", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d NOT successful.", tc_number);
+ $display("Expected: 0x%064x", expected);
+ $display("Got: 0x%064x", tb_digest);
+ $display("");
+
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test()
+ //
+ // Run a test case spanning two data blocks. We check both
+ // intermediate and final digest.
+ //----------------------------------------------------------------
+ task double_block_test(input [7 : 0] tc_number,
+ input [1 : 0] mode,
+ input [1023 : 0] block1,
+ input [1023 : 0] block2,
+ input [511 : 0] expected1,
+ input [511 : 0] expected2);
+
+ reg [511 : 0] mask;
+ reg [511 : 0] db_digest1;
+ reg db_error;
+ begin
+ $display("*** TC %0d double block test case started.", tc_number);
+ db_error = 0;
+ tc_ctr = tc_ctr + 1;
+
+ $display("*** TC %0d first block started.", tc_number);
+ tb_mode = mode;
+ tb_block = block1;
+ tb_init = 1;
+ #(2 * CLK_PERIOD);
+ tb_init = 0;
+ wait_ready();
+ db_digest1 = tb_digest;
+ $display("*** TC %0d first block done.", tc_number);
+
+ $display("*** TC %0d second block started.", tc_number);
+ tb_block = block2;
+ tb_next = 1;
+ #(2 * CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+ $display("*** TC %0d second block done.", tc_number);
+
+ if (db_digest1 == expected1)
+ begin
+ $display("*** TC %0d first block successful", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d first block NOT successful", tc_number);
+ $display("Expected: 0x%064x", expected1);
+ $display("Got: 0x%064x", db_digest1);
+ $display("");
+ db_error = 1;
+ end
+
+ case (mode)
+ MODE_SHA_512_224:
+ begin
+ mask = {{7{32'hffffffff}}, {9{32'h00000000}}};
+ end
+
+ MODE_SHA_512_256:
+ begin
+ mask = {{8{32'hffffffff}}, {8{32'h00000000}}};
+ end
+
+ MODE_SHA_384:
+ begin
+ mask = {{12{32'hffffffff}}, {4{32'h00000000}}};
+ end
+
+ MODE_SHA_512:
+ begin
+ mask = {16{32'hffffffff}};
+ end
+ endcase // case (mode)
+
+ if ((tb_digest & mask) == expected2)
+ begin
+ $display("*** TC %0d second block successful", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d second block NOT successful", tc_number);
+ $display("Expected: 0x%064x", expected2);
+ $display("Got: 0x%064x", tb_digest);
+ $display("");
+ db_error = 1;
+ end
+
+ if (db_error)
+ begin
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // double_block_test
+
+
+ //----------------------------------------------------------------
+ // sha512_core_test
+ // The main test functionality.
+ //
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
+ //----------------------------------------------------------------
+ initial
+ begin : sha512_core_test
+ reg [1024 : 0] single_block;
+ reg [511 : 0] tc1_expected;
+ reg [511 : 0] tc2_expected;
+ reg [511 : 0] tc3_expected;
+ reg [511 : 0] tc4_expected;
+
+ reg [1024 : 0] double_block_one;
+ reg [1024 : 0] double_block_two;
+ reg [511 : 0] tc5_expected;
+ reg [511 : 0] tc6_expected;
+ reg [511 : 0] tc7_expected;
+ reg [511 : 0] tc8_expected;
+ reg [511 : 0] tc9_expected;
+ reg [511 : 0] tc10_expected;
+ reg [511 : 0] tc11_expected;
+ reg [511 : 0] tc12_expected;
+
+ $display(" -- Testbench for sha512 core started --");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+ // Single block test mesage.
+ single_block = 1024'h6162638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+
+ // SHA-512 single block digest and test.
+ tc1_expected = 512'hDDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F;
+ single_block_test(8'h01, MODE_SHA_512, single_block, tc1_expected);
+
+ // SHA-512_224 single block digest and test.
+ tc2_expected = {224'h4634270F707B6A54DAAE7530460842E20E37ED265CEEE9A43E8924AA, {9{32'h00000000}}};
+ single_block_test(8'h02, MODE_SHA_512_224, single_block, tc2_expected);
+
+ // SHA-512_256 single block digest and test.
+ tc3_expected = {256'h53048E2681941EF99B2E29B76B4C7DABE4C2D0C634FC6D46E0E2F13107E7AF23, {8{32'h00000000}}};
+ single_block_test(8'h03, MODE_SHA_512_256, single_block, tc3_expected);
+
+ // SHA-384 single block digest and test.
+ tc4_expected = {384'hCB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7, {4{32'h00000000}}};
+ single_block_test(8'h04, MODE_SHA_384, single_block, tc4_expected);
+
+
+ // Two block test message.
+ double_block_one = 1024'h61626364656667686263646566676869636465666768696A6465666768696A6B65666768696A6B6C666768696A6B6C6D6768696A6B6C6D6E68696A6B6C6D6E6F696A6B6C6D6E6F706A6B6C6D6E6F70716B6C6D6E6F7071726C6D6E6F707172736D6E6F70717273746E6F70717273747580000000000000000000000000000000;
+ double_block_two = 1024'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000380;
+
+ // SHA-512 two block digests and test.
+ tc5_expected = 512'h4319017A2B706E69CD4B05938BAE5E890186BF199F30AA956EF8B71D2F810585D787D6764B20BDA2A26014470973692000EC057F37D14B8E06ADD5B50E671C72;
+ tc6_expected = 512'h8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA17299AEADB6889018501D289E4900F7E4331B99DEC4B5433AC7D329EEB6DD26545E96E55B874BE909;
+ double_block_test(8'h05, MODE_SHA_512, double_block_one, double_block_two, tc5_expected, tc6_expected);
+
+ // SHA-512_224 two block digests and test.
+ tc7_expected = 512'h9606CB2DB7823CE75FE35E2674A8F9EF1417ED9E89C412BB54EA29664586108625852563EED495096DEBAAE2F4737FD75319224B135486F8E6C0F55E700C35B3;
+ tc8_expected = {224'h23FEC5BB94D60B23308192640B0C453335D664734FE40E7268674AF9, {9{32'h00000000}}};
+ double_block_test(8'h06, MODE_SHA_512_224, double_block_one, double_block_two, tc7_expected, tc8_expected);
+
+ // SHA-512_256 two block digests and test.
+ tc9_expected = 512'h8DD99EB081311F8BCBBBC42CC7AFB288E8E9408730419D1E953FF7A2B194048DAE24175483C44C7C809B348E8E88E3ECBF2EA614CEED9C5B51807937F11867E1;
+ tc10_expected = {256'h3928E184FB8690F840DA3988121D31BE65CB9D3EF83EE6146FEAC861E19B563A, {8{32'h00000000}}};
+ double_block_test(8'h07, MODE_SHA_512_256, double_block_one, double_block_two, tc9_expected, tc10_expected);
+
+ // SHA-384 two block digests and test.
+ tc11_expected = 512'h2A7F1D895FD58E0BEAAE96D1A673C741015A2173796C1A88F6352CA156ACAFF7C662113E9EBB4D6417B61A85E2CCF0A937EB9A6660FEB5198F2EBE9A81E6A2C5;
+ tc12_expected = {384'h09330C33F71147E83D192FC782CD1B4753111B173B3B05D22FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039, {4{32'h00000000}}};
+ double_block_test(8'h08, MODE_SHA_384, double_block_one, double_block_two, tc11_expected, tc12_expected);
+
+
+ display_test_result();
+ $display("*** Simulation done.");
+ $finish;
+ end // sha512_core_test
+endmodule // tb_sha512_core
+
+//======================================================================
+// EOF tb_sha512_core.v
+//======================================================================
diff --git a/sha512/toolruns/Makefile b/sha512/toolruns/Makefile
new file mode 100755
index 0000000..03073ca
--- /dev/null
+++ b/sha512/toolruns/Makefile
@@ -0,0 +1,96 @@
+#===================================================================
+#
+# Makefile
+# --------
+# Makefile for building sha512 wmem, 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.
+#
+#===================================================================
+
+#WMEM_SRC=../src/rtl/sha256_w_mem.v
+#WMEM_TB_SRC=../src/tb/tb_sha256_w_mem.v
+
+CORE_SRC=../src/rtl/sha512_core.v ../src/rtl/sha512_h_constants.v ../src/rtl/sha512_k_constants.v ../src/rtl/sha512_w_mem.v
+CORE_TB_SRC=../src/tb/tb_sha512_core.v
+
+TOP_SRC=../src/rtl/sha512.v
+TOP_TB_SRC=../src/tb/tb_sha512.v
+
+#WB_SRC=../src/rtl/wb_sha256.v $(CORE_SRC)
+#WB_TB_SRC=../src/tb/tb_wb_sha256.v
+
+CC=iverilog
+
+
+all: top core
+
+
+#wb: $(WB_TB_SRC) $(WB_SRC)
+# $(CC) -o wb.sim $(WB_TB_SRC) $(WB_SRC)
+
+
+top: $(TOP_TB_SRC) $(TOP_SRC)
+ $(CC) -o top.sim $(TOP_TB_SRC) $(TOP_SRC) $(CORE_SRC)
+
+
+core: $(CORE_TB_SRC) $(CORE_SRC)
+ $(CC) -o core.sim $(CORE_SRC) $(CORE_TB_SRC)
+
+
+sim-top: top.sim
+ ./top.sim
+
+
+sim-core: core.sim
+ ./core.sim
+
+
+clean:
+ rm -f top.sim
+ rm -f core.sim
+ rm -f wmem.sim
+
+
+help:
+ @echo "Supported targets:"
+ @echo "------------------"
+ @echo "all: Build all simulation targets."
+ @echo "top: Build the top simulation target."
+ @echo "core: Build the core simulation target."
+ @echo "sim-top: Run top level simulation."
+ @echo "sim-core: Run core level simulation."
+ @echo "clean: Delete all built files."
+
+#===================================================================
+# EOF Makefile
+#===================================================================
+
More information about the Commits
mailing list