[Cryptech-Commits] [core/math/modexp] 01/01: (1) Adding auto generated testbench for verilog. (2) Update of the test generator. (3) Update of the Makefile to run test generator.

git at cryptech.is git at cryptech.is
Fri Apr 24 13:16:31 UTC 2015


This is an automated email from the git hooks/post-receive script.

joachim at secworks.se pushed a commit to branch master
in repository core/math/modexp.

commit 502f0f429a261628fe5e43582280012541c40804
Author: Joachim Strömbergson <joachim at secworks.se>
Date:   Fri Apr 24 15:16:23 2015 +0200

    (1) Adding auto generated testbench for verilog. (2) Update of the test generator. (3) Update of the Makefile to run test generator.
---
 src/model/c/Debug/makefile                         |   11 +-
 src/model/c/Debug/modexp                           |  Bin 0 -> 47444 bytes
 src/model/c/Debug/src/subdir.mk                    |   30 +-
 src/model/c/src/ModExpTestBench.c                  |   13 +
 src/model/c/src/autogenerated_tests.c              |  227 +++++
 src/model/c/src/autogenerated_tests.h              |    6 +
 src/model/c/src/bajs.c                             |  226 +++++
 src/model/c/src/bignum_uint32_t.c                  |   47 +-
 src/model/c/src/bignum_uint32_t.h                  |   19 +-
 src/model/c/src/findn_test.c                       |   25 +
 src/model/c/src/montgomery_array.c                 |   49 +-
 src/model/c/src/montgomery_array.h                 |    5 +-
 src/model/c/src/montgomery_array_test.c            |  165 +---
 src/model/c/src/montgomery_array_test.h            |    2 +-
 src/model/c/src/simple_tests.c                     |   72 ++
 src/model/c/src/simple_tests.h                     |   47 +
 src/model/c/src/test                               |  Bin 0 -> 8628 bytes
 src/tb/tb_modexp_autogenerated.v                   | 1007 ++++++++++++++++++++
 src/tb/tb_modexp_autogenerated_template.v          |  479 ++++++++++
 .../modexp/testgenerator/TestGenerator.java        |   31 +-
 .../modexp/testgenerator/format/GeneratorC.java    |   53 +-
 .../testgenerator/format/GeneratorVerilog.java     |  122 +++
 .../testgenerator/format/ModExpTestFormater.java   |   25 +-
 toolruns/Makefile                                  |   76 +-
 24 files changed, 2462 insertions(+), 275 deletions(-)

diff --git a/src/model/c/Debug/makefile b/src/model/c/Debug/makefile
index 92c7223..e4fb64d 100644
--- a/src/model/c/Debug/makefile
+++ b/src/model/c/Debug/makefile
@@ -5,6 +5,7 @@
 -include ../makefile.init
 
 RM := rm -rf
+CC = clang
 
 # All of the sources participating in the build are defined here
 -include sources.mk
@@ -20,22 +21,22 @@ endif
 
 -include ../makefile.defs
 
-# Add inputs and outputs from these tool invocations to the build variables 
+# Add inputs and outputs from these tool invocations to the build variables
 
 # All Target
-all: rsa
+all: modexp
 
 # Tool invocations
-rsa: $(OBJS) $(USER_OBJS)
+modexp: $(OBJS) $(USER_OBJS)
 	@echo 'Building target: $@'
 	@echo 'Invoking: MacOS X C Linker'
-	gcc  -o "rsa" $(OBJS) $(USER_OBJS) $(LIBS)
+	$(CC) -o "modexp" $(OBJS) $(USER_OBJS) $(LIBS)
 	@echo 'Finished building target: $@'
 	@echo ' '
 
 # Other Targets
 clean:
-	-$(RM) $(EXECUTABLES)$(OBJS)$(C_DEPS) rsa
+	-$(RM) $(EXECUTABLES)$(OBJS)$(C_DEPS) modexp
 	- at echo ' '
 
 .PHONY: all clean dependents
diff --git a/src/model/c/Debug/modexp b/src/model/c/Debug/modexp
new file mode 100755
index 0000000..a49298d
Binary files /dev/null and b/src/model/c/Debug/modexp differ
diff --git a/src/model/c/Debug/src/subdir.mk b/src/model/c/Debug/src/subdir.mk
index 05aad58..c45f860 100644
--- a/src/model/c/Debug/src/subdir.mk
+++ b/src/model/c/Debug/src/subdir.mk
@@ -2,32 +2,40 @@
 # Automatically-generated file. Do not edit!
 ################################################################################
 
-# Add inputs and outputs from these tool invocations to the build variables 
+CC = clang
+CC_OPT = -O2
+CC_FLAGS = -g3 -pedantic -pedantic-errors -Wall -Wextra -Werror -Wconversion -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)"
+
+# Add inputs and outputs from these tool invocations to the build variables
 C_SRCS += \
-../src/RSATestBench.c \
+../src/ModExpTestBench.c \
+../src/simple_tests.c \
+../src/autogenerated_tests.c \
 ../src/bignum_uint32_t.c \
 ../src/montgomery_array.c \
-../src/montgomery_array_test.c 
+../src/montgomery_array_test.c
 
 OBJS += \
-./src/RSATestBench.o \
+./src/ModExpTestBench.o \
+./src/simple_tests.o \
+./src/autogenerated_tests.o \
 ./src/bignum_uint32_t.o \
 ./src/montgomery_array.o \
-./src/montgomery_array_test.o 
+./src/montgomery_array_test.o
 
 C_DEPS += \
-./src/RSATestBench.d \
+./src/ModExpTestBench.d \
+./src/simple_tests.d \
+./src/autogenerated_tests.d \
 ./src/bignum_uint32_t.d \
 ./src/montgomery_array.d \
-./src/montgomery_array_test.d 
+./src/montgomery_array_test.d
 
 
 # Each subdirectory must supply rules for building sources it contributes
 src/%.o: ../src/%.c
 	@echo 'Building file: $<'
-	@echo 'Invoking: GCC C Compiler'
-	gcc -O0 -g3 -pedantic -pedantic-errors -Wall -Wextra -Werror -Wconversion -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
+	@echo 'Invoking: clang C Compiler'
+	$(CC) $(CC_OPT) $(CC_FLAGS) -o "$@" "$<"
 	@echo 'Finished building: $<'
 	@echo ' '
-
-
diff --git a/src/model/c/src/ModExpTestBench.c b/src/model/c/src/ModExpTestBench.c
new file mode 100644
index 0000000..ab236c1
--- /dev/null
+++ b/src/model/c/src/ModExpTestBench.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "simple_tests.h"
+#include "autogenerated_tests.h"
+#include "montgomery_array_test.h"
+
+int main(void) {
+  simple_tests();
+  autogenerated_tests();
+  montgomery_array_tests(0);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/model/c/src/autogenerated_tests.c b/src/model/c/src/autogenerated_tests.c
new file mode 100644
index 0000000..e9ec0b7
--- /dev/null
+++ b/src/model/c/src/autogenerated_tests.c
@@ -0,0 +1,227 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "montgomery_array.h"
+#include "bignum_uint32_t.h"
+void autogenerated_BASIC_M4962768465676381896(void) {
+  printf("=== autogenerated_BASIC_M4962768465676381896 ===\n");
+  uint32_t X[] = { 0x00000001, 0x946473e1 };
+  uint32_t E[] = { 0x00000001, 0x0e85e74f };
+  uint32_t M[] = { 0x00000001, 0x70754797 };
+  uint32_t expected[] = { 0x00000000, 0x7761ed4f };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_8982867242010371843(void) {
+  printf("=== autogenerated_BASIC_8982867242010371843 ===\n");
+  uint32_t X[] = { 0x00000001, 0x6eb4ac2d };
+  uint32_t E[] = { 0x00000001, 0xbb200e41 };
+  uint32_t M[] = { 0x00000001, 0x27347dc3 };
+  uint32_t expected[] = { 0x00000000, 0x87d16204 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_5090788032873075449(void) {
+  printf("=== autogenerated_BASIC_5090788032873075449 ===\n");
+  uint32_t X[] = { 0x00000001, 0x9e504a03 };
+  uint32_t E[] = { 0x00000001, 0x9bc057ef };
+  uint32_t M[] = { 0x00000001, 0xc8b53fe5 };
+  uint32_t expected[] = { 0x00000001, 0xc1a6494c };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_8448510918869952728(void) {
+  printf("=== autogenerated_BASIC_8448510918869952728 ===\n");
+  uint32_t X[] = { 0x00000001, 0x73f7b309 };
+  uint32_t E[] = { 0x00000001, 0x91c10f7f };
+  uint32_t M[] = { 0x00000001, 0x4be322c9 };
+  uint32_t expected[] = { 0x00000000, 0x9a155286 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_4036237668019554146(void) {
+  printf("=== autogenerated_BASIC_4036237668019554146 ===\n");
+  uint32_t X[] = { 0x00000001, 0xd0f3961d };
+  uint32_t E[] = { 0x00000001, 0xcdbc9c9d };
+  uint32_t M[] = { 0x00000001, 0x30367d5b };
+  uint32_t expected[] = { 0x00000001, 0x15a9c15d };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_M8925041444689012509(void) {
+  printf("=== autogenerated_BASIC_M8925041444689012509 ===\n");
+  uint32_t X[] = { 0x00000001, 0x34130e17 };
+  uint32_t E[] = { 0x00000001, 0xf45e52c9 };
+  uint32_t M[] = { 0x00000001, 0x9cb5c68d };
+  uint32_t expected[] = { 0x00000000, 0x7c129d37 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_M5713608137760059379(void) {
+  printf("=== autogenerated_BASIC_M5713608137760059379 ===\n");
+  uint32_t X[] = { 0x00000001, 0x77505dbd };
+  uint32_t E[] = { 0x00000001, 0xdb808627 };
+  uint32_t M[] = { 0x00000001, 0xad1fed09 };
+  uint32_t expected[] = { 0x00000001, 0x842cd733 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_6816968587684568101(void) {
+  printf("=== autogenerated_BASIC_6816968587684568101 ===\n");
+  uint32_t X[] = { 0x00000001, 0x3272b6ef };
+  uint32_t E[] = { 0x00000001, 0x2cb6c09b };
+  uint32_t M[] = { 0x00000001, 0xefbc64fd };
+  uint32_t expected[] = { 0x00000001, 0x59c3b603 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_4168013900853404774(void) {
+  printf("=== autogenerated_BASIC_4168013900853404774 ===\n");
+  uint32_t X[] = { 0x00000001, 0x3c20bbcf };
+  uint32_t E[] = { 0x00000001, 0xa495d8ab };
+  uint32_t M[] = { 0x00000001, 0x75ddb9ef };
+  uint32_t expected[] = { 0x00000001, 0x1413eac7 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_M8394821325674331878(void) {
+  printf("=== autogenerated_BASIC_M8394821325674331878 ===\n");
+  uint32_t X[] = { 0x00000001, 0x93d3d0d3 };
+  uint32_t E[] = { 0x00000001, 0x43c2dfef };
+  uint32_t M[] = { 0x00000001, 0x7443cbf1 };
+  uint32_t expected[] = { 0x00000000, 0xc2eda7c3 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_M2919828800172604435(void) {
+  printf("=== autogenerated_BASIC_M2919828800172604435 ===\n");
+  uint32_t X[] = { 0x3d746ec5 };
+  uint32_t E[] = { 0x3f7ea6d5 };
+  uint32_t M[] = { 0x29b6675f };
+  uint32_t expected[] = { 0x040c43d8 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_4770912732078070597(void) {
+  printf("=== autogenerated_BASIC_4770912732078070597 ===\n");
+  uint32_t X[] = { 0x200c0f45 };
+  uint32_t E[] = { 0x24774bab };
+  uint32_t M[] = { 0x234ca073 };
+  uint32_t expected[] = { 0x14505436 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_3593487472385409519(void) {
+  printf("=== autogenerated_BASIC_3593487472385409519 ===\n");
+  uint32_t X[] = { 0x248819d1 };
+  uint32_t E[] = { 0x2ad2b6ed };
+  uint32_t M[] = { 0x269cc6bf };
+  uint32_t expected[] = { 0x0f09d466 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_4981749054780354961(void) {
+  printf("=== autogenerated_BASIC_4981749054780354961 ===\n");
+  uint32_t X[] = { 0x27bec4e7 };
+  uint32_t E[] = { 0x36fe540f };
+  uint32_t M[] = { 0x25a46d61 };
+  uint32_t expected[] = { 0x0bab2269 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_7702189670289360961(void) {
+  printf("=== autogenerated_BASIC_7702189670289360961 ===\n");
+  uint32_t X[] = { 0x302def29 };
+  uint32_t E[] = { 0x25b9c233 };
+  uint32_t M[] = { 0x33af5461 };
+  uint32_t expected[] = { 0x0229dc08 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_M5169634701858105792(void) {
+  printf("=== autogenerated_BASIC_M5169634701858105792 ===\n");
+  uint32_t X[] = { 0x240d8cf5 };
+  uint32_t E[] = { 0x2a6a7381 };
+  uint32_t M[] = { 0x3471d1e9 };
+  uint32_t expected[] = { 0x244dec19 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_6469444563916025786(void) {
+  printf("=== autogenerated_BASIC_6469444563916025786 ===\n");
+  uint32_t X[] = { 0x3cc9270b };
+  uint32_t E[] = { 0x27858fdd };
+  uint32_t M[] = { 0x21e65001 };
+  uint32_t expected[] = { 0x17200d8c };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_M2453278165832221565(void) {
+  printf("=== autogenerated_BASIC_M2453278165832221565 ===\n");
+  uint32_t X[] = { 0x30ca6ceb };
+  uint32_t E[] = { 0x212c387b };
+  uint32_t M[] = { 0x2e07a7bb };
+  uint32_t expected[] = { 0x0fc15a1f };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_M1847183855567461116(void) {
+  printf("=== autogenerated_BASIC_M1847183855567461116 ===\n");
+  uint32_t X[] = { 0x3d02c5a1 };
+  uint32_t E[] = { 0x35f12b45 };
+  uint32_t M[] = { 0x32f0b03f };
+  uint32_t expected[] = { 0x2340f96f };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_M7037130911981370263(void) {
+  printf("=== autogenerated_BASIC_M7037130911981370263 ===\n");
+  uint32_t X[] = { 0x2692d1cd };
+  uint32_t E[] = { 0x3b21ef8d };
+  uint32_t M[] = { 0x2042c76d };
+  uint32_t expected[] = { 0x1b753aea };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_tests(void) {
+  autogenerated_BASIC_M4962768465676381896();
+  autogenerated_BASIC_8982867242010371843();
+  autogenerated_BASIC_5090788032873075449();
+  autogenerated_BASIC_8448510918869952728();
+  autogenerated_BASIC_4036237668019554146();
+  autogenerated_BASIC_M8925041444689012509();
+  autogenerated_BASIC_M5713608137760059379();
+  autogenerated_BASIC_6816968587684568101();
+  autogenerated_BASIC_4168013900853404774();
+  autogenerated_BASIC_M8394821325674331878();
+  autogenerated_BASIC_M2919828800172604435();
+  autogenerated_BASIC_4770912732078070597();
+  autogenerated_BASIC_3593487472385409519();
+  autogenerated_BASIC_4981749054780354961();
+  autogenerated_BASIC_7702189670289360961();
+  autogenerated_BASIC_M5169634701858105792();
+  autogenerated_BASIC_6469444563916025786();
+  autogenerated_BASIC_M2453278165832221565();
+  autogenerated_BASIC_M1847183855567461116();
+  autogenerated_BASIC_M7037130911981370263();
+
+}
diff --git a/src/model/c/src/autogenerated_tests.h b/src/model/c/src/autogenerated_tests.h
new file mode 100644
index 0000000..ce7a89e
--- /dev/null
+++ b/src/model/c/src/autogenerated_tests.h
@@ -0,0 +1,6 @@
+#ifndef AUTOGENERATED_TESTS_H_
+#define AUTOGENERATED_TESTS_H_
+
+void autogenerated_tests(void);
+
+#endif /* AUTOGENERATED_TESTS_H_ */
diff --git a/src/model/c/src/bajs.c b/src/model/c/src/bajs.c
new file mode 100644
index 0000000..e064fb8
--- /dev/null
+++ b/src/model/c/src/bajs.c
@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "montgomery_array.h"
+#include "bignum_uint32_t.h"
+void autogenerated_BASIC_M4962768465676381896(void) {
+  printf("=== autogenerated_BASIC_M4962768465676381896 ===\n");
+  uint32_t X[] = { 0x00000001, 0x946473e1 };
+  uint32_t E[] = { 0x00000001, 0x0e85e74f };
+  uint32_t M[] = { 0x00000001, 0x70754797 };
+  uint32_t expected[] = { 0x00000000, 0x7761ed4f };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_8982867242010371843(void) {
+  printf("=== autogenerated_BASIC_8982867242010371843 ===\n");
+  uint32_t X[] = { 0x00000001, 0x6eb4ac2d };
+  uint32_t E[] = { 0x00000001, 0xbb200e41 };
+  uint32_t M[] = { 0x00000001, 0x27347dc3 };
+  uint32_t expected[] = { 0x00000000, 0x87d16204 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_5090788032873075449(void) {
+  printf("=== autogenerated_BASIC_5090788032873075449 ===\n");
+  uint32_t X[] = { 0x00000001, 0x9e504a03 };
+  uint32_t E[] = { 0x00000001, 0x9bc057ef };
+  uint32_t M[] = { 0x00000001, 0xc8b53fe5 };
+  uint32_t expected[] = { 0x00000001, 0xc1a6494c };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_8448510918869952728(void) {
+  printf("=== autogenerated_BASIC_8448510918869952728 ===\n");
+  uint32_t X[] = { 0x00000001, 0x73f7b309 };
+  uint32_t E[] = { 0x00000001, 0x91c10f7f };
+  uint32_t M[] = { 0x00000001, 0x4be322c9 };
+  uint32_t expected[] = { 0x00000000, 0x9a155286 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_4036237668019554146(void) {
+  printf("=== autogenerated_BASIC_4036237668019554146 ===\n");
+  uint32_t X[] = { 0x00000001, 0xd0f3961d };
+  uint32_t E[] = { 0x00000001, 0xcdbc9c9d };
+  uint32_t M[] = { 0x00000001, 0x30367d5b };
+  uint32_t expected[] = { 0x00000001, 0x15a9c15d };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_M8925041444689012509(void) {
+  printf("=== autogenerated_BASIC_M8925041444689012509 ===\n");
+  uint32_t X[] = { 0x00000001, 0x34130e17 };
+  uint32_t E[] = { 0x00000001, 0xf45e52c9 };
+  uint32_t M[] = { 0x00000001, 0x9cb5c68d };
+  uint32_t expected[] = { 0x00000000, 0x7c129d37 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_M5713608137760059379(void) {
+  printf("=== autogenerated_BASIC_M5713608137760059379 ===\n");
+  uint32_t X[] = { 0x00000001, 0x77505dbd };
+  uint32_t E[] = { 0x00000001, 0xdb808627 };
+  uint32_t M[] = { 0x00000001, 0xad1fed09 };
+  uint32_t expected[] = { 0x00000001, 0x842cd733 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_6816968587684568101(void) {
+  printf("=== autogenerated_BASIC_6816968587684568101 ===\n");
+  uint32_t X[] = { 0x00000001, 0x3272b6ef };
+  uint32_t E[] = { 0x00000001, 0x2cb6c09b };
+  uint32_t M[] = { 0x00000001, 0xefbc64fd };
+  uint32_t expected[] = { 0x00000001, 0x59c3b603 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_4168013900853404774(void) {
+  printf("=== autogenerated_BASIC_4168013900853404774 ===\n");
+  uint32_t X[] = { 0x00000001, 0x3c20bbcf };
+  uint32_t E[] = { 0x00000001, 0xa495d8ab };
+  uint32_t M[] = { 0x00000001, 0x75ddb9ef };
+  uint32_t expected[] = { 0x00000001, 0x1413eac7 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_M8394821325674331878(void) {
+  printf("=== autogenerated_BASIC_M8394821325674331878 ===\n");
+  uint32_t X[] = { 0x00000001, 0x93d3d0d3 };
+  uint32_t E[] = { 0x00000001, 0x43c2dfef };
+  uint32_t M[] = { 0x00000001, 0x7443cbf1 };
+  uint32_t expected[] = { 0x00000000, 0xc2eda7c3 };
+  uint32_t Z[] = { 0x00000000, 0x00000000 };
+  mod_exp_array(2, X, E, M, Z);
+  assertArrayEquals(2, expected, Z);
+}
+void autogenerated_BASIC_M2919828800172604435(void) {
+  printf("=== autogenerated_BASIC_M2919828800172604435 ===\n");
+  uint32_t X[] = { 0x3d746ec5 };
+  uint32_t E[] = { 0x3f7ea6d5 };
+  uint32_t M[] = { 0x29b6675f };
+  uint32_t expected[] = { 0x040c43d8 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_4770912732078070597(void) {
+  printf("=== autogenerated_BASIC_4770912732078070597 ===\n");
+  uint32_t X[] = { 0x200c0f45 };
+  uint32_t E[] = { 0x24774bab };
+  uint32_t M[] = { 0x234ca073 };
+  uint32_t expected[] = { 0x14505436 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_3593487472385409519(void) {
+  printf("=== autogenerated_BASIC_3593487472385409519 ===\n");
+  uint32_t X[] = { 0x248819d1 };
+  uint32_t E[] = { 0x2ad2b6ed };
+  uint32_t M[] = { 0x269cc6bf };
+  uint32_t expected[] = { 0x0f09d466 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_4981749054780354961(void) {
+  printf("=== autogenerated_BASIC_4981749054780354961 ===\n");
+  uint32_t X[] = { 0x27bec4e7 };
+  uint32_t E[] = { 0x36fe540f };
+  uint32_t M[] = { 0x25a46d61 };
+  uint32_t expected[] = { 0x0bab2269 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_7702189670289360961(void) {
+  printf("=== autogenerated_BASIC_7702189670289360961 ===\n");
+  uint32_t X[] = { 0x302def29 };
+  uint32_t E[] = { 0x25b9c233 };
+  uint32_t M[] = { 0x33af5461 };
+  uint32_t expected[] = { 0x0229dc08 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_M5169634701858105792(void) {
+  printf("=== autogenerated_BASIC_M5169634701858105792 ===\n");
+  uint32_t X[] = { 0x240d8cf5 };
+  uint32_t E[] = { 0x2a6a7381 };
+  uint32_t M[] = { 0x3471d1e9 };
+  uint32_t expected[] = { 0x244dec19 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_6469444563916025786(void) {
+  printf("=== autogenerated_BASIC_6469444563916025786 ===\n");
+  uint32_t X[] = { 0x3cc9270b };
+  uint32_t E[] = { 0x27858fdd };
+  uint32_t M[] = { 0x21e65001 };
+  uint32_t expected[] = { 0x17200d8c };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_M2453278165832221565(void) {
+  printf("=== autogenerated_BASIC_M2453278165832221565 ===\n");
+  uint32_t X[] = { 0x30ca6ceb };
+  uint32_t E[] = { 0x212c387b };
+  uint32_t M[] = { 0x2e07a7bb };
+  uint32_t expected[] = { 0x0fc15a1f };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_M1847183855567461116(void) {
+  printf("=== autogenerated_BASIC_M1847183855567461116 ===\n");
+  uint32_t X[] = { 0x3d02c5a1 };
+  uint32_t E[] = { 0x35f12b45 };
+  uint32_t M[] = { 0x32f0b03f };
+  uint32_t expected[] = { 0x2340f96f };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_BASIC_M7037130911981370263(void) {
+  printf("=== autogenerated_BASIC_M7037130911981370263 ===\n");
+  uint32_t X[] = { 0x2692d1cd };
+  uint32_t E[] = { 0x3b21ef8d };
+  uint32_t M[] = { 0x2042c76d };
+  uint32_t expected[] = { 0x1b753aea };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+void autogenerated_tests(void) {
+  autogenerated_BASIC_M4962768465676381896();
+  autogenerated_BASIC_8982867242010371843();
+  autogenerated_BASIC_5090788032873075449();
+  autogenerated_BASIC_8448510918869952728();
+  autogenerated_BASIC_4036237668019554146();
+  autogenerated_BASIC_M8925041444689012509();
+  autogenerated_BASIC_M5713608137760059379();
+  autogenerated_BASIC_6816968587684568101();
+  autogenerated_BASIC_4168013900853404774();
+  autogenerated_BASIC_M8394821325674331878();
+  autogenerated_BASIC_M2919828800172604435();
+  autogenerated_BASIC_4770912732078070597();
+  autogenerated_BASIC_3593487472385409519();
+  autogenerated_BASIC_4981749054780354961();
+  autogenerated_BASIC_7702189670289360961();
+  autogenerated_BASIC_M5169634701858105792();
+  autogenerated_BASIC_6469444563916025786();
+  autogenerated_BASIC_M2453278165832221565();
+  autogenerated_BASIC_M1847183855567461116();
+  autogenerated_BASIC_M7037130911981370263();
+}
diff --git a/src/model/c/src/bignum_uint32_t.c b/src/model/c/src/bignum_uint32_t.c
index 75d27a8..c40b538 100644
--- a/src/model/c/src/bignum_uint32_t.c
+++ b/src/model/c/src/bignum_uint32_t.c
@@ -2,14 +2,27 @@
 #include <stdlib.h>
 #include "bignum_uint32_t.h"
 
-void copy_array(int length, uint32_t *src, uint32_t *dst) {
-	for (int i = 0; i < length; i++)
+void assertArrayEquals(uint32_t length, uint32_t *expected, uint32_t *actual) { //needed in tests
+	int equals = 1;
+	for (uint32_t i = 0; i < length; i++)
+		equals &= expected[i] == actual[i];
+	printf("%s expected: [", equals ? "PASS" : "FAIL");
+	for (uint32_t i = 0; i < length - 1; i++)
+		printf("%8x, ", expected[i]);
+	printf("%8x] actual: [ ", expected[length - 1]);
+	for (uint32_t i = 0; i < length - 1; i++)
+		printf("%8x, ", actual[i]);
+	printf("%8x]\n", actual[length - 1]);
+}
+
+void copy_array(uint32_t length, uint32_t *src, uint32_t *dst) {
+	for (uint32_t i = 0; i < length; i++)
 		dst[i] = src[i];
 }
 
-void add_array(int length, uint32_t *a, uint32_t *b, uint32_t *result) {
+void add_array(uint32_t length, uint32_t *a, uint32_t *b, uint32_t *result) {
 	uint64_t carry = 0;
-	for (int i = length - 1; i >= 0; i--) {
+	for (int32_t i = ((int32_t) length) - 1; i >= 0; i--) {
 		uint64_t r = carry;
 		uint32_t aa = a[i];
 		uint32_t bb = b[i];
@@ -20,9 +33,9 @@ void add_array(int length, uint32_t *a, uint32_t *b, uint32_t *result) {
 	}
 }
 
-void sub_array(int length, uint32_t *a, uint32_t *b, uint32_t *result) {
+void sub_array(uint32_t length, uint32_t *a, uint32_t *b, uint32_t *result) {
 	uint64_t carry = 1;
-	for (int wordIndex = length - 1; wordIndex >= 0; wordIndex--) {
+	for (int32_t wordIndex = ((int32_t) length) - 1; wordIndex >= 0; wordIndex--) {
 		uint64_t r = carry;
 		uint32_t aa = a[wordIndex];
 		uint32_t bb = ~b[wordIndex];
@@ -33,18 +46,18 @@ void sub_array(int length, uint32_t *a, uint32_t *b, uint32_t *result) {
 	}
 }
 
-void shift_right_1_array(int length, uint32_t *a, uint32_t *result) {
+void shift_right_1_array(uint32_t length, uint32_t *a, uint32_t *result) {
 	uint32_t prev = 0; // MSB will be zero extended
-	for (int wordIndex = 0; wordIndex < length; wordIndex++) {
+	for (uint32_t wordIndex = 0; wordIndex < length; wordIndex++) {
 		uint32_t aa = a[wordIndex];
 		result[wordIndex] = (aa >> 1) | (prev << 31);
 		prev = aa & 1; // Lower word will be extended with LSB of this word
 	}
 }
 
-void shift_left_1_array(int length, uint32_t *a, uint32_t *result) {
+void shift_left_1_array(uint32_t length, uint32_t *a, uint32_t *result) {
 	uint32_t prev = 0; // LSB will be zero extended
-	for (int wordIndex = length - 1; wordIndex >= 0; wordIndex--) {
+	for (int32_t wordIndex = ((int32_t) length) - 1; wordIndex >= 0; wordIndex--) {
 		uint32_t aa = a[wordIndex];
 		result[wordIndex] = (aa << 1) | prev;
 
@@ -53,15 +66,15 @@ void shift_left_1_array(int length, uint32_t *a, uint32_t *result) {
 	}
 }
 
-void debugArray(char *msg, int length, uint32_t *array) {
+void debugArray(char *msg, uint32_t length, uint32_t *array) {
 	printf("%s ", msg);
-	for (int i = 0; i < length; i++) {
+	for (uint32_t i = 0; i < length; i++) {
 		printf("%8x ", array[i]);
 	}
 	printf("\n");
 }
 
-void modulus_array(int length, uint32_t *a, uint32_t *modulus, uint32_t *temp,
+void modulus_array(uint32_t length, uint32_t *a, uint32_t *modulus, uint32_t *temp,
 		uint32_t *reminder) {
 	copy_array(length, a, reminder);
 
@@ -77,13 +90,13 @@ void modulus_array(int length, uint32_t *a, uint32_t *modulus, uint32_t *temp,
 	}
 }
 
-void zero_array(int length, uint32_t *a) {
-	for (int i = 0; i < length; i++)
+void zero_array(uint32_t length, uint32_t *a) {
+	for (uint32_t i = 0; i < length; i++)
 		a[i] = 0;
 }
 
-int greater_than_array(int length, uint32_t *a, uint32_t *b) {
-	for (int i = 0; i < length; i++) {
+int greater_than_array(uint32_t length, uint32_t *a, uint32_t *b) {
+	for (uint32_t i = 0; i < length; i++) {
 		if (a[i] > b[i])
 			return 1;
 		if (a[i] < b[i])
diff --git a/src/model/c/src/bignum_uint32_t.h b/src/model/c/src/bignum_uint32_t.h
index c0fc991..e275fc4 100644
--- a/src/model/c/src/bignum_uint32_t.h
+++ b/src/model/c/src/bignum_uint32_t.h
@@ -8,15 +8,16 @@
 #ifndef BIGNUM_UINT32_T_H_
 #define BIGNUM_UINT32_T_H_
 
-void modulus_array(int length, uint32_t *a, uint32_t *modulus, uint32_t *temp,
+void modulus_array(uint32_t length, uint32_t *a, uint32_t *modulus, uint32_t *temp,
 		uint32_t *reminder);
-int greater_than_array(int length, uint32_t *a, uint32_t *b);
-void add_array(int length, uint32_t *a, uint32_t *b, uint32_t *result);
-void sub_array(int length, uint32_t *a, uint32_t *b, uint32_t *result);
-void shift_right_1_array(int length, uint32_t *a, uint32_t *result);
-void shift_left_1_array(int length, uint32_t *a, uint32_t *result);
-void zero_array(int length, uint32_t *a);
-void copy_array(int length, uint32_t *src, uint32_t *dst);
-void debugArray(char *msg, int length, uint32_t *array);
+int greater_than_array(uint32_t length, uint32_t *a, uint32_t *b);
+void add_array(uint32_t length, uint32_t *a, uint32_t *b, uint32_t *result);
+void sub_array(uint32_t length, uint32_t *a, uint32_t *b, uint32_t *result);
+void shift_right_1_array(uint32_t length, uint32_t *a, uint32_t *result);
+void shift_left_1_array(uint32_t length, uint32_t *a, uint32_t *result);
+void zero_array(uint32_t length, uint32_t *a);
+void copy_array(uint32_t length, uint32_t *src, uint32_t *dst);
+void debugArray(char *msg, uint32_t length, uint32_t *array);
+void assertArrayEquals(uint32_t length, uint32_t *expected, uint32_t *actual);
 
 #endif /* BIGNUM_UINT32_T_H_ */
diff --git a/src/model/c/src/findn_test.c b/src/model/c/src/findn_test.c
new file mode 100644
index 0000000..3c4a2fe
--- /dev/null
+++ b/src/model/c/src/findn_test.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <stdint.h>
+
+uint32_t findN(uint32_t length, uint32_t *E) {
+       uint32_t n = -1;
+       for (int i = 0; i < 32 * length; i++) {
+               uint32_t ei_ = E[length - 1 - (i / 32)];
+               uint32_t ei = (ei_ >> (i % 32)) & 1;
+
+               printf("ei_ = 0x%08x, ei = 0x%08x\n", ei_, ei);
+               if (ei == 1) {
+                       n = i;
+               }
+       }
+       return n + 1;
+}
+
+
+int main(void) {
+  uint32_t my_e[4] = {0x5a00aaaa, 0x555555, 0x80808080, 0x01010101};
+
+  printf("Result: %08d\n", findN(1, &my_e[0]));
+
+  return 0;
+}
diff --git a/src/model/c/src/montgomery_array.c b/src/model/c/src/montgomery_array.c
index 65e33e1..0ddc742 100644
--- a/src/model/c/src/montgomery_array.c
+++ b/src/model/c/src/montgomery_array.c
@@ -3,10 +3,10 @@
 #include "bignum_uint32_t.h"
 #include "montgomery_array.h"
 
-void mont_prod_array(int length, uint32_t *A, uint32_t *B, uint32_t *M,
+void mont_prod_array(uint32_t length, uint32_t *A, uint32_t *B, uint32_t *M,
 		uint32_t *temp, uint32_t *s) {
 	zero_array(length, s);
-	for (int wordIndex = length - 1; wordIndex >= 0; wordIndex--) {
+	for (int32_t wordIndex = ((int32_t) length) - 1; wordIndex >= 0; wordIndex--) {
 		for (int i = 0; i < 32; i++) {
 
 			int b = (B[wordIndex] >> i) & 1;
@@ -38,11 +38,11 @@ void mont_prod_array(int length, uint32_t *A, uint32_t *B, uint32_t *M,
 	}
 }
 
-void m_residue_2_2N_array(int length, int N, uint32_t *M, uint32_t *temp,
+void m_residue_2_2N_array(uint32_t length, uint32_t N, uint32_t *M, uint32_t *temp,
 		uint32_t *Nr) {
 	zero_array(length, Nr);
 	Nr[length - 1] = 1; // Nr = 1 == 2**(2N-2N)
-	for (int i = 0; i < 2 * N; i++) {
+	for (uint32_t i = 0; i < 2 * N; i++) {
 		shift_left_1_array(length, Nr, Nr);
 		modulus_array(length, Nr, M, temp, Nr);
 //			debugArray(length, Nr);
@@ -50,19 +50,19 @@ void m_residue_2_2N_array(int length, int N, uint32_t *M, uint32_t *temp,
 	// Nr = (2 ** 2N) mod M
 }
 
-int findN(int length, uint32_t *E) {
-	int n = -1;
-	for (int i = 0; i < 32 * length; i++) {
+uint32_t findN(uint32_t length, uint32_t *E) {
+	uint32_t n = 0;
+	for (uint32_t i = 0; i < 32 * length; i++) {
 		uint32_t ei_ = E[length - 1 - (i / 32)];
 		uint32_t ei = (ei_ >> (i % 32)) & 1;
 		if (ei == 1) {
-			n = i;
+			n = i+1;
 		}
 	}
-	return n + 1;
+	return n;
 }
 
-void mont_exp_array(int length, uint32_t *X, uint32_t *E, uint32_t *M,
+void mont_exp_array(uint32_t length, uint32_t *X, uint32_t *E, uint32_t *M,
 		uint32_t *Nr, uint32_t *P, uint32_t *ONE, uint32_t *temp,
 		uint32_t *temp2, uint32_t *Z) {
 	//debugArray("X ", length, X);
@@ -70,7 +70,7 @@ void mont_exp_array(int length, uint32_t *X, uint32_t *E, uint32_t *M,
 	//debugArray("M ", length, M);
 
 	// 1. Nr := 2 ** 2N mod M
-	const int N = 32 * length;
+	const uint32_t N = 32 * length;
 	m_residue_2_2N_array(length, N, M, temp, Nr);
 	//debugArray("Nr", length, Nr);
 
@@ -85,8 +85,8 @@ void mont_exp_array(int length, uint32_t *X, uint32_t *E, uint32_t *M,
 	//debugArray("P0", length, P);
 
 	// 4. for i = 0 to n-1 loop
-	const int n = findN(length, E); //loop optimization for low values of E. Not necessary.
-	for (int i = 0; i < n; i++) {
+	const uint32_t n = findN(length, E); //loop optimization for low values of E. Not necessary.
+	for (uint32_t i = 0; i < n; i++) {
 		uint32_t ei_ = E[length - 1 - (i / 32)];
 		uint32_t ei = (ei_ >> (i % 32)) & 1;
 		// 6. if (ei = 1) then Zi+1 := MontProd ( Zi, Pi, M) else Zi+1 := Zi
@@ -109,3 +109,26 @@ void mont_exp_array(int length, uint32_t *X, uint32_t *E, uint32_t *M,
 
 }
 
+void die(const char *c) {
+	printf("Fatal error: %s\n", c);
+	exit(1);
+}
+
+void mod_exp_array(uint32_t length, uint32_t *X, uint32_t *E, uint32_t *M, uint32_t *Z) {
+	uint32_t *Nr = calloc(length, sizeof(uint32_t));
+	uint32_t *P = calloc(length, sizeof(uint32_t));
+	uint32_t *ONE = calloc(length, sizeof(uint32_t));
+	uint32_t *temp = calloc(length, sizeof(uint32_t));
+	uint32_t *temp2 = calloc(length, sizeof(uint32_t));
+	if (Nr == NULL) die("calloc");
+	if (P == NULL) die("calloc");
+	if (ONE == NULL) die("calloc");
+	if (temp == NULL) die("calloc");
+	if (temp2 == NULL) die("calloc");
+	mont_exp_array(length, X, E, M, Nr, P, ONE, temp, temp2, Z);
+	free(Nr);
+	free(P);
+	free(ONE);
+	free(temp);
+	free(temp2);
+}
diff --git a/src/model/c/src/montgomery_array.h b/src/model/c/src/montgomery_array.h
index 2bafc56..82ef9de 100644
--- a/src/model/c/src/montgomery_array.h
+++ b/src/model/c/src/montgomery_array.h
@@ -8,9 +8,8 @@
 #ifndef MONTGOMERY_ARRAY_H_
 #define MONTGOMERY_ARRAY_H_
 
-void mont_prod_array(int length, uint32_t *A, uint32_t *B, uint32_t *M,
+void mont_prod_array(uint32_t length, uint32_t *A, uint32_t *B, uint32_t *M,
 		uint32_t *temp, uint32_t *s);
-void mont_exp_array(int length, uint32_t *X, uint32_t *E, uint32_t *M,
-		uint32_t *Nr, uint32_t *P, uint32_t *ONE, uint32_t *temp, uint32_t *temp2, uint32_t *Z);
+void mod_exp_array(uint32_t length, uint32_t *X, uint32_t *E, uint32_t *M, uint32_t *Z);
 
 #endif /* MONTGOMERY_ARRAY_H_ */
diff --git a/src/model/c/src/montgomery_array_test.c b/src/model/c/src/montgomery_array_test.c
index ca76266..e865799 100644
--- a/src/model/c/src/montgomery_array_test.c
+++ b/src/model/c/src/montgomery_array_test.c
@@ -6,19 +6,6 @@
 const uint32_t TEST_CONSTANT_PRIME_15_1 = 65537;
 const uint32_t TEST_CONSTANT_PRIME_31_1 = 2147483647u; // eighth Mersenne prime
 
-void assertArrayEquals(int length, uint32_t *expected, uint32_t *actual) {
-	int equals = 1;
-	for (int i = 0; i < length; i++)
-		equals &= expected[i] == actual[i];
-	printf("%s expected: [", equals ? "PASS" : "FAIL");
-	for (int i = 0; i < length - 1; i++)
-		printf("%8x, ", expected[i]);
-	printf("%8x] actual: [ ", expected[length - 1]);
-	for (int i = 0; i < length - 1; i++)
-		printf("%8x, ", actual[i]);
-	printf("%8x]\n", actual[length - 1]);
-}
-
 void testShiftRight() {
 	printf("=== Test shift right ===\n");
 	uint32_t a[] = { 0x01234567, 0x89abcdef };
@@ -168,23 +155,16 @@ void test_montgomery_modexp() {
 	uint32_t M[] = { (1 << (89 - 64)) - 1, 0xffffffff, 0xffffffff }; //2^89-1 R. E. Powers
 	uint32_t E[] = { 0, 0, (1 << 31) - 1 }; //Leonhard Euler
 
-	//temp variables
-	uint32_t Nr[] = { 0, 0, 0 };
-	uint32_t ONE[] = { 0, 0, 0 };
-	uint32_t P[] = { 0, 0, 0 };
-	uint32_t temp[] = { 0, 0, 0 };
-	uint32_t temp2[] = { 0, 0, 0 };
-
-	//output
+	uint32_t ONE[] = { 0, 0, 1 };
 	uint32_t Z[] = { 0, 0, 0 };
 
-	mont_exp_array(3, ONE, ONE, M, Nr, P, ONE, temp, temp2, Z);
+	mod_exp_array(3, ONE, ONE, M, Z);
 	assertArrayEquals(3, ONE, Z);
 
-	mont_exp_array(3, ONE, E, M, Nr, P, ONE, temp, temp2, Z);
+	mod_exp_array(3, ONE, E, M, Z);
 	assertArrayEquals(3, ONE, Z);
 
-	mont_exp_array(3, X, E, M, Nr, P, ONE, temp, temp2, Z);
+	mod_exp_array(3, X, E, M, Z);
 	uint32_t expected[] = { 0x0153db9b, 0x314b8066, 0x3462631f };
 	assertArrayEquals(3, expected, Z);
 }
@@ -276,38 +256,6 @@ void test_modExp_4096bit_e65537() {
 			0x58fa13ff, 0x6cf0a5c2, 0x0ac24bf4, 0xd7901e58, 0x9b616f55,
 			0x2517443d, 0xb00a5613, 0x217b8957, 0x5a4ba6c4 };
 
-	//temp variables
-	uint32_t Nr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-	uint32_t ONE[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-	uint32_t P[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-	uint32_t temp[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-	uint32_t temp2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
 	//output
 	uint32_t Z[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -316,7 +264,7 @@ void test_modExp_4096bit_e65537() {
 			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-	mont_exp_array(129, X, E, M, Nr, P, ONE, temp, temp2, Z);
+	mod_exp_array(129, X, E, M, Z);
 	assertArrayEquals(129, expected, Z);
 }
 
@@ -491,68 +439,6 @@ void test_modExp_8192_e65537() {
 			0x5e6b03ab, 0x89fc8de9, 0x554365e2, 0x63f40c6c, 0x1246d838,
 			0x054a15e6, 0x9b8fdd15, 0x346ae73d };
 
-	// temp variables
-	uint32_t Nr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0 };
-	uint32_t ONE[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0 };
-	uint32_t P[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0 };
-	uint32_t temp[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0 };
-	uint32_t temp2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
 	// output
 	uint32_t Z[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -567,7 +453,7 @@ void test_modExp_8192_e65537() {
 			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 			0, 0, 0, 0, 0, 0, 0 };
 
-	mont_exp_array(257, X, E, M, Nr, P, ONE, temp, temp2, Z);
+	mod_exp_array(257, X, E, M, Z);
 	assertArrayEquals(257, expected, Z);
 }
 
@@ -784,29 +670,30 @@ void test_modExp_8192bit() {
 
 	size_t length = 1 + ((8192 / 8) / sizeof(uint32_t));
 
-	//temp variables
-	uint32_t *Nr = calloc(length, sizeof(uint32_t));
-	uint32_t *ONE = calloc(length, sizeof(uint32_t));
-	uint32_t *P = calloc(length, sizeof(uint32_t));
-	uint32_t *temp = calloc(length, sizeof(uint32_t));
-	uint32_t *temp2 = calloc(length, sizeof(uint32_t));
-
 	//output
 	uint32_t *Z = calloc(length, sizeof(uint32_t));
 
-	mont_exp_array(257, X, E, M, Nr, P, ONE, temp, temp2, Z);
+	mod_exp_array(257, X, E, M, Z);
 	assertArrayEquals(257, expected, Z);
 }
 
-void montgomery_array_tests() {
-	test_montgomery_modexp();
-	test_modExp_4096bit_e65537();
-	test_modExp_8192_e65537();
-	test_modExp_8192bit();
-	testShiftRight();
-	testAdd();
-	testSub();
-	test_montgomery_one_item_array();
-	test_montgomery_modulus();
+void montgomery_array_tests(int bigtests) {
+  // Sub function tests.
+  testShiftRight();
+  testAdd();
+  testSub();
+  test_montgomery_one_item_array();
+  test_montgomery_modulus();
+
+  // modexp tests.
+  test_montgomery_modexp();
+
+  // Fairly big.
+  test_modExp_4096bit_e65537();
+  test_modExp_8192_e65537();
+
+  // Bigtests.
+  if (bigtests) {
+    test_modExp_8192bit();
+  }
 }
-
diff --git a/src/model/c/src/montgomery_array_test.h b/src/model/c/src/montgomery_array_test.h
index 085d0ee..281a739 100644
--- a/src/model/c/src/montgomery_array_test.h
+++ b/src/model/c/src/montgomery_array_test.h
@@ -8,6 +8,6 @@
 #ifndef MONTGOMERY_ARRAY_TEST_H_
 #define MONTGOMERY_ARRAY_TEST_H_
 
-void montgomery_array_tests();
+void montgomery_array_tests(int bigtests);
 
 #endif /* MONTGOMERY_ARRAY_TEST_H_ */
diff --git a/src/model/c/src/simple_tests.c b/src/model/c/src/simple_tests.c
new file mode 100644
index 0000000..402a8ac
--- /dev/null
+++ b/src/model/c/src/simple_tests.c
@@ -0,0 +1,72 @@
+//======================================================================
+//
+// simple_tests.h
+// --------------
+// Header fil to export the simple tests of the modexp C model.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2015, Assured 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.
+//======================================================================
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "montgomery_array.h"
+#include "bignum_uint32_t.h"
+
+void simple_3_7_11(void) {
+  printf("=== Simple test with X = 3, E = 7 and M = 11 ===\n");
+  uint32_t X[] = { 0x3 };
+  uint32_t E[] = { 0x7 };
+  uint32_t M[] = { 0xb };
+  uint32_t expected[] = { 0x9 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+
+void simple_251_251_257(void) {
+  printf("=== Simple test with X = 251, E = 251 and M = 257 ===\n");
+  uint32_t X[] = { 0xfb };
+  uint32_t E[] = { 0xfb };
+  uint32_t M[] = { 0x101 };
+  uint32_t expected[] = { 0xb7 };
+  uint32_t Z[] = { 0x00000000 };
+  mod_exp_array(1, X, E, M, Z);
+  assertArrayEquals(1, expected, Z);
+}
+
+void simple_tests(void) {
+  simple_3_7_11();
+  simple_251_251_257();
+}
+
+//======================================================================
+// EOF simple_tests.h
+//======================================================================
diff --git a/src/model/c/src/simple_tests.h b/src/model/c/src/simple_tests.h
new file mode 100644
index 0000000..23f6922
--- /dev/null
+++ b/src/model/c/src/simple_tests.h
@@ -0,0 +1,47 @@
+//======================================================================
+//
+// simple_tests.h
+// --------------
+// Header fil to export the simple tests of the modexp C model.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2015, Assured 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.
+//======================================================================
+
+#ifndef SIMPLE_TESTS_H_
+#define SIMPLE_TESTS_H_
+
+void simple_tests(void);
+
+#endif // SIMPLE_TESTS_H_
+
+//======================================================================
+// EOF simple_tests.h
+//======================================================================
diff --git a/src/model/c/src/test b/src/model/c/src/test
new file mode 100755
index 0000000..77faf32
Binary files /dev/null and b/src/model/c/src/test differ
diff --git a/src/tb/tb_modexp_autogenerated.v b/src/tb/tb_modexp_autogenerated.v
new file mode 100644
index 0000000..65cbeef
--- /dev/null
+++ b/src/tb/tb_modexp_autogenerated.v
@@ -0,0 +1,1007 @@
+//======================================================================
+//
+// tb_modexp_autogenerated.v
+// -----------
+// Testbench modular exponentiation core.
+//
+//
+// Author: Joachim Strombergson, Peter Magnusson
+// Copyright (c) 2015, Assured 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.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_modexp_autogenerated();
+
+  //----------------------------------------------------------------
+  // Internal constant and parameter definitions.
+  //----------------------------------------------------------------
+  parameter DEBUG = 1;
+
+  localparam CLK_HALF_PERIOD = 1;
+  localparam CLK_PERIOD      = 2 * CLK_HALF_PERIOD;
+
+  // The DUT address map.
+  localparam GENERAL_PREFIX      = 4'h0;
+  localparam ADDR_NAME0          = 8'h00;
+  localparam ADDR_NAME1          = 8'h01;
+  localparam ADDR_VERSION        = 8'h02;
+
+  localparam ADDR_CTRL           = 8'h08;
+  localparam CTRL_START_BIT      = 0;
+
+  localparam ADDR_STATUS         = 8'h09;
+  localparam STATUS_READY_BIT    = 0;
+
+  localparam ADDR_MODULUS_LENGTH  = 8'h20;
+  localparam ADDR_MESSAGE_LENGTH  = 8'h21;
+  localparam ADDR_EXPONENT_LENGTH = 8'h22;
+
+  localparam MODULUS_PREFIX      = 4'h1;
+  localparam ADDR_MODULUS_START  = 8'h00;
+  localparam ADDR_MODULUS_END    = 8'hff;
+
+  localparam EXPONENT_PREFIX     = 4'h2;
+  localparam ADDR_EXPONENT_START = 8'h00;
+  localparam ADDR_EXPONENT_END   = 8'hff;
+
+  localparam MESSAGE_PREFIX      = 4'h3;
+  localparam MESSAGE_START       = 8'h00;
+  localparam MESSAGE_END         = 8'hff;
+
+  localparam RESULT_PREFIX       = 4'h4;
+  localparam RESULT_START        = 8'h00;
+  localparam RESULT_END          = 8'hff;
+
+
+  //----------------------------------------------------------------
+  // Register and Wire declarations.
+  //----------------------------------------------------------------
+  reg [31 : 0]  cycle_ctr;
+  reg [31 : 0]  error_ctr;
+  reg [31 : 0]  tc_ctr;
+
+  reg [31 : 0]  read_data;
+  reg [127 : 0] result_data;
+
+  reg           tb_clk;
+  reg           tb_reset_n;
+  reg           tb_cs;
+  reg           tb_we;
+  reg [11  : 0] tb_address;
+  reg [31 : 0]  tb_write_data;
+  wire [31 : 0] tb_read_data;
+  wire          tb_error;
+
+
+  //----------------------------------------------------------------
+  // Device Under Test.
+  //----------------------------------------------------------------
+  modexp 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)
+            );
+
+
+  //----------------------------------------------------------------
+  // clk_gen
+  //
+  // Always running clock generator process.
+  //----------------------------------------------------------------
+  always
+    begin : clk_gen
+      #CLK_HALF_PERIOD;
+      tb_clk = !tb_clk;
+    end // clk_gen
+
+
+  //----------------------------------------------------------------
+  // sys_monitor()
+  //
+  // An always running process that creates a cycle counter and
+  // conditionally displays information about the DUT.
+  //----------------------------------------------------------------
+  always
+    begin : sys_monitor
+      cycle_ctr = cycle_ctr + 1;
+
+      #(CLK_PERIOD);
+
+      if (DEBUG)
+        begin
+          dump_dut_state();
+        end
+    end
+
+
+  //----------------------------------------------------------------
+  // dump_dut_state()
+  //
+  // Dump the state of the dump when needed.
+  //----------------------------------------------------------------
+  task dump_dut_state();
+    begin
+      $display("cycle: 0x%016x", cycle_ctr);
+      $display("State of DUT");
+      $display("------------");
+      $display("Inputs and outputs:");
+      $display("cs   = 0x%01x, we = 0x%01x", tb_cs, tb_we);
+      $display("addr = 0x%08x, read_data = 0x%08x, write_data = 0x%08x",
+               tb_address, tb_read_data, tb_write_data);
+      $display("");
+
+      $display("State:");
+      $display("ready_reg = 0x%01x, start_reg = 0x%01x, start_new = 0x%01x, start_we = 0x%01x",
+               dut.ready_reg, dut.start_reg, dut.start_new, dut.start_we);
+      $display("residue_valid = 0x%01x", dut.residue_valid_reg);
+      $display("loop_counter_reg = 0x%08x", dut.loop_counter_reg);
+      $display("exponent_length_reg = 0x%02x, modulus_length_reg = 0x%02x",
+               dut.exponent_length_reg, dut.modulus_length_reg);
+      $display("length_reg = 0x%02x, length_m1_reg = 0x%02x",
+               dut.length_reg, dut.length_m1_reg);
+      $display("ctrl_reg = 0x%04x", dut.modexp_ctrl_reg);
+      $display("");
+    end
+  endtask // dump_dut_state
+
+
+  //----------------------------------------------------------------
+  // reset_dut()
+  //
+  // Toggle reset to put the DUT into a well known state.
+  //----------------------------------------------------------------
+  task reset_dut();
+    begin
+      $display("*** Toggle reset.");
+      tb_reset_n = 0;
+
+      #(2 * CLK_PERIOD);
+      tb_reset_n = 1;
+      $display("");
+    end
+  endtask // reset_dut
+
+
+  //----------------------------------------------------------------
+  // display_test_results()
+  //
+  // Display the accumulated test results.
+  //----------------------------------------------------------------
+  task display_test_results();
+    begin
+      if (error_ctr == 0)
+        begin
+          $display("*** All %02d test cases completed successfully", tc_ctr);
+        end
+      else
+        begin
+          $display("*** %02d tests completed - %02d test cases did not complete successfully.",
+                   tc_ctr, error_ctr);
+        end
+    end
+  endtask // display_test_results
+
+
+  //----------------------------------------------------------------
+  // init_sim()
+  //
+  // Initialize all counters and testbed functionality as well
+  // as setting the DUT inputs to defined values.
+  //----------------------------------------------------------------
+  task init_sim();
+    begin
+      cycle_ctr          = 0;
+      error_ctr          = 0;
+      tc_ctr             = 0;
+
+      tb_clk             = 0;
+      tb_reset_n         = 1;
+
+      tb_cs              = 0;
+      tb_we              = 0;
+      tb_address         = 8'h00;
+      tb_write_data      = 32'h00000000;
+    end
+  endtask // init_sim
+
+
+  //----------------------------------------------------------------
+  // read_word()
+  //
+  // Read a data word from the given address in the DUT.
+  // the word read will be available in the global variable
+  // read_data.
+  //----------------------------------------------------------------
+  task read_word(input [11 : 0] address);
+    begin
+      tb_address = address;
+      tb_cs = 1;
+      tb_we = 0;
+      #(CLK_PERIOD);
+      read_data = tb_read_data;
+      tb_cs = 0;
+
+      if (DEBUG)
+        begin
+          $display("*** (read_word) 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 [11 : 0] address,
+                  input [31 : 0] word);
+    begin
+      if (DEBUG)
+        begin
+          $display("*** (write_word) Writing 0x%08x to 0x%02x.", word, address);
+          $display("");
+        end
+
+      tb_address = address;
+      tb_write_data = word;
+      tb_cs = 1;
+      tb_we = 1;
+      #(2 * CLK_PERIOD);
+      tb_cs = 0;
+      tb_we = 0;
+    end
+  endtask // write_word
+
+
+  //----------------------------------------------------------------
+  // wait_ready()
+  //
+  // Wait until the ready flag in the core is set.
+  //----------------------------------------------------------------
+  task wait_ready();
+    begin
+      while (tb_read_data != 32'h00000001)
+          read_word({GENERAL_PREFIX, ADDR_STATUS});
+
+      if (DEBUG)
+        $display("*** (wait_ready) Ready flag has been set.");
+    end
+  endtask // wait_ready
+
+
+  //----------------------------------------------------------------
+  // dump_message_mem()
+  //
+  // Dump the contents of the message memory.
+  //----------------------------------------------------------------
+  task dump_message_mem();
+    reg [8 : 0] i;
+    begin
+      $display("Contents of the message memory:");
+      for (i = 0 ; i < 256 ; i = i + 8)
+        begin
+          $display("message_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x  0x%08x 0x%08x 0x%08x 0x%08x",
+                   i[7 : 0], (i[7 : 0] + 8'h07),
+                   dut.message_mem.mem[(i[7 : 0] + 0)], dut.message_mem.mem[(i[7 : 0] + 1)],
+                   dut.message_mem.mem[(i[7 : 0] + 2)], dut.message_mem.mem[(i[7 : 0] + 3)],
+                   dut.message_mem.mem[(i[7 : 0] + 4)], dut.message_mem.mem[(i[7 : 0] + 5)],
+                   dut.message_mem.mem[(i[7 : 0] + 6)], dut.message_mem.mem[(i[7 : 0] + 7)],
+                   );
+        end
+      $display("");
+    end
+  endtask // dump_message_mem
+
+
+  //----------------------------------------------------------------
+  // dump_exponent_mem()
+  //
+  // Dump the contents of the exponent memory.
+  //----------------------------------------------------------------
+  task dump_exponent_mem();
+    reg [8 : 0] i;
+    begin
+      $display("Contents of the exponent memory:");
+      for (i = 0 ; i < 256 ; i = i + 8)
+        begin
+          $display("exponent_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x  0x%08x 0x%08x 0x%08x 0x%08x",
+                   i[7 : 0], (i[7 : 0] + 8'h07),
+                   dut.exponent_mem.mem[(i[7 : 0] + 0)], dut.exponent_mem.mem[(i[7 : 0] + 1)],
+                   dut.exponent_mem.mem[(i[7 : 0] + 2)], dut.exponent_mem.mem[(i[7 : 0] + 3)],
+                   dut.exponent_mem.mem[(i[7 : 0] + 4)], dut.exponent_mem.mem[(i[7 : 0] + 5)],
+                   dut.exponent_mem.mem[(i[7 : 0] + 6)], dut.exponent_mem.mem[(i[7 : 0] + 7)],
+                   );
+        end
+      $display("");
+    end
+  endtask // dump_exponent_mem
+
+
+  //----------------------------------------------------------------
+  // dump_modulus_mem()
+  //
+  // Dump the contents of the modulus memory.
+  //----------------------------------------------------------------
+  task dump_modulus_mem();
+    reg [8 : 0] i;
+    begin
+      $display("Contents of the modulus memory:");
+      for (i = 0 ; i < 256 ; i = i + 8)
+        begin
+          $display("modulus_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x  0x%08x 0x%08x 0x%08x 0x%08x",
+                   i[7 : 0], (i[7 : 0] + 8'h07),
+                   dut.modulus_mem.mem[(i[7 : 0] + 0)], dut.modulus_mem.mem[(i[7 : 0] + 1)],
+                   dut.modulus_mem.mem[(i[7 : 0] + 2)], dut.modulus_mem.mem[(i[7 : 0] + 3)],
+                   dut.modulus_mem.mem[(i[7 : 0] + 4)], dut.modulus_mem.mem[(i[7 : 0] + 5)],
+                   dut.modulus_mem.mem[(i[7 : 0] + 6)], dut.modulus_mem.mem[(i[7 : 0] + 7)],
+                   );
+        end
+      $display("");
+    end
+  endtask // dump_modulus_mem
+
+
+  //----------------------------------------------------------------
+  // dump_residue_mem()
+  //
+  // Dump the contents of the residue memory.
+  //----------------------------------------------------------------
+  task dump_residue_mem();
+    reg [8 : 0] i;
+    begin
+      $display("Contents of the residue memory:");
+      for (i = 0 ; i < 256 ; i = i + 8)
+        begin
+          $display("residue_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x  0x%08x 0x%08x 0x%08x 0x%08x",
+                   i[7 : 0], (i[7 : 0] + 8'h07),
+                   dut.residue_mem.mem[(i[7 : 0] + 0)], dut.residue_mem.mem[(i[7 : 0] + 1)],
+                   dut.residue_mem.mem[(i[7 : 0] + 2)], dut.residue_mem.mem[(i[7 : 0] + 3)],
+                   dut.residue_mem.mem[(i[7 : 0] + 4)], dut.residue_mem.mem[(i[7 : 0] + 5)],
+                   dut.residue_mem.mem[(i[7 : 0] + 6)], dut.residue_mem.mem[(i[7 : 0] + 7)],
+                   );
+        end
+      $display("");
+    end
+  endtask // dump_residue_mem
+
+
+  //----------------------------------------------------------------
+  // dump_result_mem()
+  //
+  // Dump the contents of the result memory.
+  //----------------------------------------------------------------
+  task dump_result_mem();
+    reg [8 : 0] i;
+    begin
+      $display("Contents of the result memory:");
+      for (i = 0 ; i < 256 ; i = i + 8)
+        begin
+          $display("result_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x  0x%08x 0x%08x 0x%08x 0x%08x",
+                   i[7 : 0], (i[7 : 0] + 8'h07),
+                   dut.result_mem.mem[(i[7 : 0] + 0)], dut.result_mem.mem[(i[7 : 0] + 1)],
+                   dut.result_mem.mem[(i[7 : 0] + 2)], dut.result_mem.mem[(i[7 : 0] + 3)],
+                   dut.result_mem.mem[(i[7 : 0] + 4)], dut.result_mem.mem[(i[7 : 0] + 5)],
+                   dut.result_mem.mem[(i[7 : 0] + 6)], dut.result_mem.mem[(i[7 : 0] + 7)],
+                   );
+        end
+      $display("");
+    end
+  endtask // dump_result_mem
+
+
+  //----------------------------------------------------------------
+  // dump_memories()
+  //
+  // Dump the contents of the memories in the dut.
+  //----------------------------------------------------------------
+  task dump_memories();
+    begin
+      dump_message_mem();
+      dump_exponent_mem();
+      dump_modulus_mem();
+      dump_residue_mem();
+      dump_result_mem();
+    end
+  endtask // dump_memories
+
+task autogenerated_BASIC_M4962768465676381896();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_M4962768465676381896");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001);
+write_word({MESSAGE_PREFIX, 8'h01}, 32'h946473e1);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001);
+write_word({EXPONENT_PREFIX, 8'h01}, 32'h0e85e74f);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001);
+write_word({MODULUS_PREFIX, 8'h01}, 32'h70754797);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000002);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h00000000))
+  begin
+    $display("Expected: 0x00000000, got 0x%08x", read_data);
+  end
+read_word({RESULT_PREFIX,8'h01});
+read_data = tb_read_data;
+if (read_data !== 32'h7761ed4f))
+  begin
+    $display("Expected: 0x7761ed4f, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_M4962768465676381896
+task autogenerated_BASIC_8982867242010371843();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_8982867242010371843");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001);
+write_word({MESSAGE_PREFIX, 8'h01}, 32'h6eb4ac2d);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001);
+write_word({EXPONENT_PREFIX, 8'h01}, 32'hbb200e41);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001);
+write_word({MODULUS_PREFIX, 8'h01}, 32'h27347dc3);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000002);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h00000000))
+  begin
+    $display("Expected: 0x00000000, got 0x%08x", read_data);
+  end
+read_word({RESULT_PREFIX,8'h01});
+read_data = tb_read_data;
+if (read_data !== 32'h87d16204))
+  begin
+    $display("Expected: 0x87d16204, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_8982867242010371843
+task autogenerated_BASIC_5090788032873075449();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_5090788032873075449");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001);
+write_word({MESSAGE_PREFIX, 8'h01}, 32'h9e504a03);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001);
+write_word({EXPONENT_PREFIX, 8'h01}, 32'h9bc057ef);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001);
+write_word({MODULUS_PREFIX, 8'h01}, 32'hc8b53fe5);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000002);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h00000001))
+  begin
+    $display("Expected: 0x00000001, got 0x%08x", read_data);
+  end
+read_word({RESULT_PREFIX,8'h01});
+read_data = tb_read_data;
+if (read_data !== 32'hc1a6494c))
+  begin
+    $display("Expected: 0xc1a6494c, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_5090788032873075449
+task autogenerated_BASIC_8448510918869952728();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_8448510918869952728");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001);
+write_word({MESSAGE_PREFIX, 8'h01}, 32'h73f7b309);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001);
+write_word({EXPONENT_PREFIX, 8'h01}, 32'h91c10f7f);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001);
+write_word({MODULUS_PREFIX, 8'h01}, 32'h4be322c9);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000002);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h00000000))
+  begin
+    $display("Expected: 0x00000000, got 0x%08x", read_data);
+  end
+read_word({RESULT_PREFIX,8'h01});
+read_data = tb_read_data;
+if (read_data !== 32'h9a155286))
+  begin
+    $display("Expected: 0x9a155286, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_8448510918869952728
+task autogenerated_BASIC_4036237668019554146();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_4036237668019554146");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001);
+write_word({MESSAGE_PREFIX, 8'h01}, 32'hd0f3961d);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001);
+write_word({EXPONENT_PREFIX, 8'h01}, 32'hcdbc9c9d);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001);
+write_word({MODULUS_PREFIX, 8'h01}, 32'h30367d5b);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000002);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h00000001))
+  begin
+    $display("Expected: 0x00000001, got 0x%08x", read_data);
+  end
+read_word({RESULT_PREFIX,8'h01});
+read_data = tb_read_data;
+if (read_data !== 32'h15a9c15d))
+  begin
+    $display("Expected: 0x15a9c15d, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_4036237668019554146
+task autogenerated_BASIC_M8925041444689012509();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_M8925041444689012509");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001);
+write_word({MESSAGE_PREFIX, 8'h01}, 32'h34130e17);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001);
+write_word({EXPONENT_PREFIX, 8'h01}, 32'hf45e52c9);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001);
+write_word({MODULUS_PREFIX, 8'h01}, 32'h9cb5c68d);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000002);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h00000000))
+  begin
+    $display("Expected: 0x00000000, got 0x%08x", read_data);
+  end
+read_word({RESULT_PREFIX,8'h01});
+read_data = tb_read_data;
+if (read_data !== 32'h7c129d37))
+  begin
+    $display("Expected: 0x7c129d37, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_M8925041444689012509
+task autogenerated_BASIC_M5713608137760059379();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_M5713608137760059379");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001);
+write_word({MESSAGE_PREFIX, 8'h01}, 32'h77505dbd);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001);
+write_word({EXPONENT_PREFIX, 8'h01}, 32'hdb808627);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001);
+write_word({MODULUS_PREFIX, 8'h01}, 32'had1fed09);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000002);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h00000001))
+  begin
+    $display("Expected: 0x00000001, got 0x%08x", read_data);
+  end
+read_word({RESULT_PREFIX,8'h01});
+read_data = tb_read_data;
+if (read_data !== 32'h842cd733))
+  begin
+    $display("Expected: 0x842cd733, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_M5713608137760059379
+task autogenerated_BASIC_6816968587684568101();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_6816968587684568101");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001);
+write_word({MESSAGE_PREFIX, 8'h01}, 32'h3272b6ef);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001);
+write_word({EXPONENT_PREFIX, 8'h01}, 32'h2cb6c09b);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001);
+write_word({MODULUS_PREFIX, 8'h01}, 32'hefbc64fd);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000002);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h00000001))
+  begin
+    $display("Expected: 0x00000001, got 0x%08x", read_data);
+  end
+read_word({RESULT_PREFIX,8'h01});
+read_data = tb_read_data;
+if (read_data !== 32'h59c3b603))
+  begin
+    $display("Expected: 0x59c3b603, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_6816968587684568101
+task autogenerated_BASIC_4168013900853404774();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_4168013900853404774");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001);
+write_word({MESSAGE_PREFIX, 8'h01}, 32'h3c20bbcf);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001);
+write_word({EXPONENT_PREFIX, 8'h01}, 32'ha495d8ab);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001);
+write_word({MODULUS_PREFIX, 8'h01}, 32'h75ddb9ef);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000002);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h00000001))
+  begin
+    $display("Expected: 0x00000001, got 0x%08x", read_data);
+  end
+read_word({RESULT_PREFIX,8'h01});
+read_data = tb_read_data;
+if (read_data !== 32'h1413eac7))
+  begin
+    $display("Expected: 0x1413eac7, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_4168013900853404774
+task autogenerated_BASIC_M8394821325674331878();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_M8394821325674331878");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h00000001);
+write_word({MESSAGE_PREFIX, 8'h01}, 32'h93d3d0d3);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h00000001);
+write_word({EXPONENT_PREFIX, 8'h01}, 32'h43c2dfef);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000002););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h00000001);
+write_word({MODULUS_PREFIX, 8'h01}, 32'h7443cbf1);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000002););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000002);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h00000000))
+  begin
+    $display("Expected: 0x00000000, got 0x%08x", read_data);
+  end
+read_word({RESULT_PREFIX,8'h01});
+read_data = tb_read_data;
+if (read_data !== 32'hc2eda7c3))
+  begin
+    $display("Expected: 0xc2eda7c3, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_M8394821325674331878
+task autogenerated_BASIC_M2919828800172604435();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_M2919828800172604435");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h3d746ec5);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h3f7ea6d5);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h29b6675f);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h040c43d8))
+  begin
+    $display("Expected: 0x040c43d8, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_M2919828800172604435
+task autogenerated_BASIC_4770912732078070597();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_4770912732078070597");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h200c0f45);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h24774bab);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h234ca073);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h14505436))
+  begin
+    $display("Expected: 0x14505436, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_4770912732078070597
+task autogenerated_BASIC_3593487472385409519();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_3593487472385409519");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h248819d1);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h2ad2b6ed);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h269cc6bf);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h0f09d466))
+  begin
+    $display("Expected: 0x0f09d466, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_3593487472385409519
+task autogenerated_BASIC_4981749054780354961();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_4981749054780354961");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h27bec4e7);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h36fe540f);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h25a46d61);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h0bab2269))
+  begin
+    $display("Expected: 0x0bab2269, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_4981749054780354961
+task autogenerated_BASIC_7702189670289360961();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_7702189670289360961");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h302def29);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h25b9c233);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h33af5461);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h0229dc08))
+  begin
+    $display("Expected: 0x0229dc08, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_7702189670289360961
+task autogenerated_BASIC_M5169634701858105792();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_M5169634701858105792");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h240d8cf5);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h2a6a7381);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h3471d1e9);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h244dec19))
+  begin
+    $display("Expected: 0x244dec19, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_M5169634701858105792
+task autogenerated_BASIC_6469444563916025786();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_6469444563916025786");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h3cc9270b);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h27858fdd);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h21e65001);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h17200d8c))
+  begin
+    $display("Expected: 0x17200d8c, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_6469444563916025786
+task autogenerated_BASIC_M2453278165832221565();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_M2453278165832221565");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h30ca6ceb);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h212c387b);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h2e07a7bb);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h0fc15a1f))
+  begin
+    $display("Expected: 0x0fc15a1f, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_M2453278165832221565
+task autogenerated_BASIC_M1847183855567461116();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_M1847183855567461116");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h3d02c5a1);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h35f12b45);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h32f0b03f);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h2340f96f))
+  begin
+    $display("Expected: 0x2340f96f, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_M1847183855567461116
+task autogenerated_BASIC_M7037130911981370263();
+reg [31 : 0] read_data;
+begin
+tc_ctr = tc_ctr + 1;
+$display("autogenerated_BASIC_M7037130911981370263");
+write_word({MESSAGE_PREFIX, 8'h00}, 32'h2692d1cd);
+write_word({EXPONENT_PREFIX, 8'h00}, 32'h3b21ef8d);
+write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h00000001););
+write_word({MODULUS_PREFIX, 8'h00}, 32'h2042c76d);
+write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h00000001););
+dump_memories()
+write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h00000001);
+wait_ready();
+read_word({RESULT_PREFIX,8'h00});
+read_data = tb_read_data;
+if (read_data !== 32'h1b753aea))
+  begin
+    $display("Expected: 0x1b753aea, got 0x%08x", read_data);
+  end
+end
+endtask // autogenerated_BASIC_M7037130911981370263
+
+  //----------------------------------------------------------------
+  // main
+  //
+  // The main test functionality.
+  //----------------------------------------------------------------
+  initial
+    begin : main
+
+      $display("   -= Testbench for modexp started =-");
+      $display("    =================================");
+      $display("");
+
+      init_sim();
+      dump_dut_state();
+      reset_dut();
+      dump_dut_state();
+
+autogenerated_BASIC_M4962768465676381896();
+autogenerated_BASIC_8982867242010371843();
+autogenerated_BASIC_5090788032873075449();
+autogenerated_BASIC_8448510918869952728();
+autogenerated_BASIC_4036237668019554146();
+autogenerated_BASIC_M8925041444689012509();
+autogenerated_BASIC_M5713608137760059379();
+autogenerated_BASIC_6816968587684568101();
+autogenerated_BASIC_4168013900853404774();
+autogenerated_BASIC_M8394821325674331878();
+autogenerated_BASIC_M2919828800172604435();
+autogenerated_BASIC_4770912732078070597();
+autogenerated_BASIC_3593487472385409519();
+autogenerated_BASIC_4981749054780354961();
+autogenerated_BASIC_7702189670289360961();
+autogenerated_BASIC_M5169634701858105792();
+autogenerated_BASIC_6469444563916025786();
+autogenerated_BASIC_M2453278165832221565();
+autogenerated_BASIC_M1847183855567461116();
+autogenerated_BASIC_M7037130911981370263();
+
+      display_test_results();
+
+      $display("");
+      $display("*** modexp simulation done. ***");
+      $finish;
+    end // main
+endmodule // tb_modexp
+
+//======================================================================
+// EOF tb_modexp.v
+//======================================================================
diff --git a/src/tb/tb_modexp_autogenerated_template.v b/src/tb/tb_modexp_autogenerated_template.v
new file mode 100644
index 0000000..62ab7dc
--- /dev/null
+++ b/src/tb/tb_modexp_autogenerated_template.v
@@ -0,0 +1,479 @@
+//======================================================================
+//
+// tb_modexp_autogenerated.v
+// -----------
+// Testbench modular exponentiation core.
+//
+//
+// Author: Joachim Strombergson, Peter Magnusson
+// Copyright (c) 2015, Assured 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.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/100ps
+
+
+//------------------------------------------------------------------
+// Test module.
+//------------------------------------------------------------------
+module tb_modexp_autogenerated();
+
+  //----------------------------------------------------------------
+  // Internal constant and parameter definitions.
+  //----------------------------------------------------------------
+  parameter DEBUG = 1;
+
+  localparam CLK_HALF_PERIOD = 1;
+  localparam CLK_PERIOD      = 2 * CLK_HALF_PERIOD;
+
+  // The DUT address map.
+  localparam GENERAL_PREFIX      = 4'h0;
+  localparam ADDR_NAME0          = 8'h00;
+  localparam ADDR_NAME1          = 8'h01;
+  localparam ADDR_VERSION        = 8'h02;
+
+  localparam ADDR_CTRL           = 8'h08;
+  localparam CTRL_START_BIT      = 0;
+
+  localparam ADDR_STATUS         = 8'h09;
+  localparam STATUS_READY_BIT    = 0;
+
+  localparam ADDR_MODULUS_LENGTH  = 8'h20;
+  localparam ADDR_MESSAGE_LENGTH  = 8'h21;
+  localparam ADDR_EXPONENT_LENGTH = 8'h22;
+
+  localparam MODULUS_PREFIX      = 4'h1;
+  localparam ADDR_MODULUS_START  = 8'h00;
+  localparam ADDR_MODULUS_END    = 8'hff;
+
+  localparam EXPONENT_PREFIX     = 4'h2;
+  localparam ADDR_EXPONENT_START = 8'h00;
+  localparam ADDR_EXPONENT_END   = 8'hff;
+
+  localparam MESSAGE_PREFIX      = 4'h3;
+  localparam MESSAGE_START       = 8'h00;
+  localparam MESSAGE_END         = 8'hff;
+
+  localparam RESULT_PREFIX       = 4'h4;
+  localparam RESULT_START        = 8'h00;
+  localparam RESULT_END          = 8'hff;
+
+
+  //----------------------------------------------------------------
+  // Register and Wire declarations.
+  //----------------------------------------------------------------
+  reg [31 : 0]  cycle_ctr;
+  reg [31 : 0]  error_ctr;
+  reg [31 : 0]  tc_ctr;
+
+  reg [31 : 0]  read_data;
+  reg [127 : 0] result_data;
+
+  reg           tb_clk;
+  reg           tb_reset_n;
+  reg           tb_cs;
+  reg           tb_we;
+  reg [11  : 0] tb_address;
+  reg [31 : 0]  tb_write_data;
+  wire [31 : 0] tb_read_data;
+  wire          tb_error;
+
+
+  //----------------------------------------------------------------
+  // Device Under Test.
+  //----------------------------------------------------------------
+  modexp 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)
+            );
+
+
+  //----------------------------------------------------------------
+  // clk_gen
+  //
+  // Always running clock generator process.
+  //----------------------------------------------------------------
+  always
+    begin : clk_gen
+      #CLK_HALF_PERIOD;
+      tb_clk = !tb_clk;
+    end // clk_gen
+
+
+  //----------------------------------------------------------------
+  // sys_monitor()
+  //
+  // An always running process that creates a cycle counter and
+  // conditionally displays information about the DUT.
+  //----------------------------------------------------------------
+  always
+    begin : sys_monitor
+      cycle_ctr = cycle_ctr + 1;
+
+      #(CLK_PERIOD);
+
+      if (DEBUG)
+        begin
+          dump_dut_state();
+        end
+    end
+
+
+  //----------------------------------------------------------------
+  // dump_dut_state()
+  //
+  // Dump the state of the dump when needed.
+  //----------------------------------------------------------------
+  task dump_dut_state();
+    begin
+      $display("cycle: 0x%016x", cycle_ctr);
+      $display("State of DUT");
+      $display("------------");
+      $display("Inputs and outputs:");
+      $display("cs   = 0x%01x, we = 0x%01x", tb_cs, tb_we);
+      $display("addr = 0x%08x, read_data = 0x%08x, write_data = 0x%08x",
+               tb_address, tb_read_data, tb_write_data);
+      $display("");
+
+      $display("State:");
+      $display("ready_reg = 0x%01x, start_reg = 0x%01x, start_new = 0x%01x, start_we = 0x%01x",
+               dut.ready_reg, dut.start_reg, dut.start_new, dut.start_we);
+      $display("residue_valid = 0x%01x", dut.residue_valid_reg);
+      $display("loop_counter_reg = 0x%08x", dut.loop_counter_reg);
+      $display("exponent_length_reg = 0x%02x, modulus_length_reg = 0x%02x",
+               dut.exponent_length_reg, dut.modulus_length_reg);
+      $display("length_reg = 0x%02x, length_m1_reg = 0x%02x",
+               dut.length_reg, dut.length_m1_reg);
+      $display("ctrl_reg = 0x%04x", dut.modexp_ctrl_reg);
+      $display("");
+    end
+  endtask // dump_dut_state
+
+
+  //----------------------------------------------------------------
+  // reset_dut()
+  //
+  // Toggle reset to put the DUT into a well known state.
+  //----------------------------------------------------------------
+  task reset_dut();
+    begin
+      $display("*** Toggle reset.");
+      tb_reset_n = 0;
+
+      #(2 * CLK_PERIOD);
+      tb_reset_n = 1;
+      $display("");
+    end
+  endtask // reset_dut
+
+
+  //----------------------------------------------------------------
+  // display_test_results()
+  //
+  // Display the accumulated test results.
+  //----------------------------------------------------------------
+  task display_test_results();
+    begin
+      if (error_ctr == 0)
+        begin
+          $display("*** All %02d test cases completed successfully", tc_ctr);
+        end
+      else
+        begin
+          $display("*** %02d tests completed - %02d test cases did not complete successfully.",
+                   tc_ctr, error_ctr);
+        end
+    end
+  endtask // display_test_results
+
+
+  //----------------------------------------------------------------
+  // init_sim()
+  //
+  // Initialize all counters and testbed functionality as well
+  // as setting the DUT inputs to defined values.
+  //----------------------------------------------------------------
+  task init_sim();
+    begin
+      cycle_ctr          = 0;
+      error_ctr          = 0;
+      tc_ctr             = 0;
+
+      tb_clk             = 0;
+      tb_reset_n         = 1;
+
+      tb_cs              = 0;
+      tb_we              = 0;
+      tb_address         = 8'h00;
+      tb_write_data      = 32'h00000000;
+    end
+  endtask // init_sim
+
+
+  //----------------------------------------------------------------
+  // read_word()
+  //
+  // Read a data word from the given address in the DUT.
+  // the word read will be available in the global variable
+  // read_data.
+  //----------------------------------------------------------------
+  task read_word(input [11 : 0] address);
+    begin
+      tb_address = address;
+      tb_cs = 1;
+      tb_we = 0;
+      #(CLK_PERIOD);
+      read_data = tb_read_data;
+      tb_cs = 0;
+
+      if (DEBUG)
+        begin
+          $display("*** (read_word) 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 [11 : 0] address,
+                  input [31 : 0] word);
+    begin
+      if (DEBUG)
+        begin
+          $display("*** (write_word) Writing 0x%08x to 0x%02x.", word, address);
+          $display("");
+        end
+
+      tb_address = address;
+      tb_write_data = word;
+      tb_cs = 1;
+      tb_we = 1;
+      #(2 * CLK_PERIOD);
+      tb_cs = 0;
+      tb_we = 0;
+    end
+  endtask // write_word
+
+
+  //----------------------------------------------------------------
+  // wait_ready()
+  //
+  // Wait until the ready flag in the core is set.
+  //----------------------------------------------------------------
+  task wait_ready();
+    begin
+      while (tb_read_data != 32'h00000001)
+          read_word({GENERAL_PREFIX, ADDR_STATUS});
+
+      if (DEBUG)
+        $display("*** (wait_ready) Ready flag has been set.");
+    end
+  endtask // wait_ready
+
+
+  //----------------------------------------------------------------
+  // dump_message_mem()
+  //
+  // Dump the contents of the message memory.
+  //----------------------------------------------------------------
+  task dump_message_mem();
+    reg [8 : 0] i;
+    begin
+      $display("Contents of the message memory:");
+      for (i = 0 ; i < 256 ; i = i + 8)
+        begin
+          $display("message_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x  0x%08x 0x%08x 0x%08x 0x%08x",
+                   i[7 : 0], (i[7 : 0] + 8'h07),
+                   dut.message_mem.mem[(i[7 : 0] + 0)], dut.message_mem.mem[(i[7 : 0] + 1)],
+                   dut.message_mem.mem[(i[7 : 0] + 2)], dut.message_mem.mem[(i[7 : 0] + 3)],
+                   dut.message_mem.mem[(i[7 : 0] + 4)], dut.message_mem.mem[(i[7 : 0] + 5)],
+                   dut.message_mem.mem[(i[7 : 0] + 6)], dut.message_mem.mem[(i[7 : 0] + 7)],
+                   );
+        end
+      $display("");
+    end
+  endtask // dump_message_mem
+
+
+  //----------------------------------------------------------------
+  // dump_exponent_mem()
+  //
+  // Dump the contents of the exponent memory.
+  //----------------------------------------------------------------
+  task dump_exponent_mem();
+    reg [8 : 0] i;
+    begin
+      $display("Contents of the exponent memory:");
+      for (i = 0 ; i < 256 ; i = i + 8)
+        begin
+          $display("exponent_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x  0x%08x 0x%08x 0x%08x 0x%08x",
+                   i[7 : 0], (i[7 : 0] + 8'h07),
+                   dut.exponent_mem.mem[(i[7 : 0] + 0)], dut.exponent_mem.mem[(i[7 : 0] + 1)],
+                   dut.exponent_mem.mem[(i[7 : 0] + 2)], dut.exponent_mem.mem[(i[7 : 0] + 3)],
+                   dut.exponent_mem.mem[(i[7 : 0] + 4)], dut.exponent_mem.mem[(i[7 : 0] + 5)],
+                   dut.exponent_mem.mem[(i[7 : 0] + 6)], dut.exponent_mem.mem[(i[7 : 0] + 7)],
+                   );
+        end
+      $display("");
+    end
+  endtask // dump_exponent_mem
+
+
+  //----------------------------------------------------------------
+  // dump_modulus_mem()
+  //
+  // Dump the contents of the modulus memory.
+  //----------------------------------------------------------------
+  task dump_modulus_mem();
+    reg [8 : 0] i;
+    begin
+      $display("Contents of the modulus memory:");
+      for (i = 0 ; i < 256 ; i = i + 8)
+        begin
+          $display("modulus_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x  0x%08x 0x%08x 0x%08x 0x%08x",
+                   i[7 : 0], (i[7 : 0] + 8'h07),
+                   dut.modulus_mem.mem[(i[7 : 0] + 0)], dut.modulus_mem.mem[(i[7 : 0] + 1)],
+                   dut.modulus_mem.mem[(i[7 : 0] + 2)], dut.modulus_mem.mem[(i[7 : 0] + 3)],
+                   dut.modulus_mem.mem[(i[7 : 0] + 4)], dut.modulus_mem.mem[(i[7 : 0] + 5)],
+                   dut.modulus_mem.mem[(i[7 : 0] + 6)], dut.modulus_mem.mem[(i[7 : 0] + 7)],
+                   );
+        end
+      $display("");
+    end
+  endtask // dump_modulus_mem
+
+
+  //----------------------------------------------------------------
+  // dump_residue_mem()
+  //
+  // Dump the contents of the residue memory.
+  //----------------------------------------------------------------
+  task dump_residue_mem();
+    reg [8 : 0] i;
+    begin
+      $display("Contents of the residue memory:");
+      for (i = 0 ; i < 256 ; i = i + 8)
+        begin
+          $display("residue_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x  0x%08x 0x%08x 0x%08x 0x%08x",
+                   i[7 : 0], (i[7 : 0] + 8'h07),
+                   dut.residue_mem.mem[(i[7 : 0] + 0)], dut.residue_mem.mem[(i[7 : 0] + 1)],
+                   dut.residue_mem.mem[(i[7 : 0] + 2)], dut.residue_mem.mem[(i[7 : 0] + 3)],
+                   dut.residue_mem.mem[(i[7 : 0] + 4)], dut.residue_mem.mem[(i[7 : 0] + 5)],
+                   dut.residue_mem.mem[(i[7 : 0] + 6)], dut.residue_mem.mem[(i[7 : 0] + 7)],
+                   );
+        end
+      $display("");
+    end
+  endtask // dump_residue_mem
+
+
+  //----------------------------------------------------------------
+  // dump_result_mem()
+  //
+  // Dump the contents of the result memory.
+  //----------------------------------------------------------------
+  task dump_result_mem();
+    reg [8 : 0] i;
+    begin
+      $display("Contents of the result memory:");
+      for (i = 0 ; i < 256 ; i = i + 8)
+        begin
+          $display("result_mem[0x%02x .. 0x%02x] = 0x%08x 0x%08x 0x%08x 0x%08x  0x%08x 0x%08x 0x%08x 0x%08x",
+                   i[7 : 0], (i[7 : 0] + 8'h07),
+                   dut.result_mem.mem[(i[7 : 0] + 0)], dut.result_mem.mem[(i[7 : 0] + 1)],
+                   dut.result_mem.mem[(i[7 : 0] + 2)], dut.result_mem.mem[(i[7 : 0] + 3)],
+                   dut.result_mem.mem[(i[7 : 0] + 4)], dut.result_mem.mem[(i[7 : 0] + 5)],
+                   dut.result_mem.mem[(i[7 : 0] + 6)], dut.result_mem.mem[(i[7 : 0] + 7)],
+                   );
+        end
+      $display("");
+    end
+  endtask // dump_result_mem
+
+
+  //----------------------------------------------------------------
+  // dump_memories()
+  //
+  // Dump the contents of the memories in the dut.
+  //----------------------------------------------------------------
+  task dump_memories();
+    begin
+      dump_message_mem();
+      dump_exponent_mem();
+      dump_modulus_mem();
+      dump_residue_mem();
+      dump_result_mem();
+    end
+  endtask // dump_memories
+
+// ===TEMPLATE_HEADER_END===
+
+  //----------------------------------------------------------------
+  // main
+  //
+  // The main test functionality.
+  //----------------------------------------------------------------
+  initial
+    begin : main
+
+      $display("   -= Testbench for modexp started =-");
+      $display("    =================================");
+      $display("");
+
+      init_sim();
+      dump_dut_state();
+      reset_dut();
+      dump_dut_state();
+
+// ===TEMPLATE_CALL_TASKS===
+
+      display_test_results();
+
+      $display("");
+      $display("*** modexp simulation done. ***");
+      $finish;
+    end // main
+endmodule // tb_modexp
+
+//======================================================================
+// EOF tb_modexp.v
+//======================================================================
diff --git a/src/testgenerator/src/org/crypttech/modexp/testgenerator/TestGenerator.java b/src/testgenerator/src/org/crypttech/modexp/testgenerator/TestGenerator.java
index af5850b..6ca48c1 100644
--- a/src/testgenerator/src/org/crypttech/modexp/testgenerator/TestGenerator.java
+++ b/src/testgenerator/src/org/crypttech/modexp/testgenerator/TestGenerator.java
@@ -1,19 +1,40 @@
 package org.crypttech.modexp.testgenerator;
 
-import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.crypttech.modexp.testgenerator.format.GeneratorC;
+import org.crypttech.modexp.testgenerator.format.GeneratorVerilog;
+import org.crypttech.modexp.testgenerator.format.ModExpTestFormater;
 
 public class TestGenerator {
 	public static void main(String[] argv) throws Exception {
+		String basePath;
+		if (argv.length == 1)
+			basePath = argv[0];
+		else
+			basePath = "..";
+		
+		System.out.println("Generating modexp test values.");
+
 		List<TestVector> vectors = new ArrayList<TestVector>();
 		vectors.addAll(TestGeneratorBasic.getTestVectors());
-		PrintWriter pw = new PrintWriter("../model/c/src/autogenerated_tests.c");
-		try (GeneratorC genC = new GeneratorC(pw)) {
-			for (TestVector vector : vectors)
-				genC.format(vector);
+		try (GeneratorC genC = new GeneratorC(
+				basePath + "/model/c/src/autogenerated_tests.c")) {
+			try (GeneratorVerilog genVerilog = new GeneratorVerilog(
+					basePath + "/tb/tb_modexp_autogenerated_template.v",
+					basePath + "/tb/tb_modexp_autogenerated.v")) {
+
+				emitTests(vectors, genC, genVerilog);
+			}
 		}
+
+	}
+
+	private static void emitTests(List<TestVector> vectors,
+			ModExpTestFormater... generators) {
+		for (ModExpTestFormater generator : generators)
+			for (TestVector vector : vectors)
+				generator.format(vector);
 	}
 }
diff --git a/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/GeneratorC.java b/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/GeneratorC.java
index fbfd852..449557e 100644
--- a/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/GeneratorC.java
+++ b/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/GeneratorC.java
@@ -1,18 +1,17 @@
 package org.crypttech.modexp.testgenerator.format;
 
+import java.io.FileNotFoundException;
 import java.io.PrintWriter;
 
 import org.crypttech.modexp.testgenerator.TestVector;
 
 public class GeneratorC extends ModExpTestFormater {
-	private static final char LF = (char) 10;
-
-	public GeneratorC(PrintWriter pw) {
-		super(pw);
-		out("#include <stdio.h>" + LF);
-		out("#include <stdlib.h>" + LF);
-		out("#include \"montgomery_array.h\"" + LF);
-		out("#include \"bignum_uint32_t.h\"" + LF);
+	public GeneratorC(String file) throws FileNotFoundException {
+		super(new PrintWriter(file), true);
+		out("#include <stdio.h>");
+		out("#include <stdlib.h>");
+		out("#include \"montgomery_array.h\"");
+		out("#include \"bignum_uint32_t.h\"");
 	}
 
 	StringBuilder footer = new StringBuilder();
@@ -21,40 +20,36 @@ public class GeneratorC extends ModExpTestFormater {
 	public void format(TestVector testVector) {
 		String testname = ("autogenerated_" + testVector.generator + "_" + testVector.seed)
 				.replace("-", "M");
-		footer.append("  ").append(testname).append("();").append(LF);
-
-		StringBuilder sb = new StringBuilder();
-		sb.append("void ").append(testname).append("(void) {").append(LF);
-		sb.append("  printf(\"=== ").append(testname).append(" ===\\n\");")
-				.append(LF);
-		appendCArray(sb, "X", testVector.X);
-		appendCArray(sb, "E", testVector.E);
-		appendCArray(sb, "M", testVector.M);
-		appendCArray(sb, "expected", testVector.expected);
+		footer.append("  ").append(testname).append("();").append((char) 10);
+
+		out("void %s(void) {", testname);
+		out("  printf(\"=== %s ===\\n\");", testname);
+		appendCArray("X", testVector.X);
+		appendCArray("E", testVector.E);
+		appendCArray("M", testVector.M);
+		appendCArray("expected", testVector.expected);
 		int[] Z = new int[testVector.length];
-		appendCArray(sb, "Z", Z);
-		sb.append("  mod_exp_array(").append(testVector.length)
-				.append(", X, E, M, Z);").append(LF);
-		sb.append("  assertArrayEquals(").append(testVector.length)
-				.append(", expected, Z);").append(LF);
-		sb.append("}").append(LF);
-		out(sb.toString());
+		appendCArray("Z", Z);
+		out("  mod_exp_array(%s, X, E, M, Z);", testVector.length);
+		out("  assertArrayEquals(%d, expected, Z);", testVector.length);
+		out("}");
 	}
 
-	private void appendCArray(StringBuilder sb, String arrayName, int[] array) {
+	private void appendCArray(String arrayName, int[] array) {
+		StringBuilder sb = new StringBuilder();
 		sb.append("  uint32_t ").append(arrayName).append("[] = ");
 		sb.append("{ ");
 		for (int m : array)
 			sb.append(String.format("0x%08x, ", m));
 		sb.replace(sb.length() - 2, sb.length(), " };");
-		sb.append(LF);
+		out(sb.toString());
 	}
 
 	@Override
 	public void close() throws Exception {
-		out("void autogenerated_tests(void) {" + LF);
+		out("void autogenerated_tests(void) {");
 		out(footer.toString());
-		out("}" + LF);
+		out("}");
 		super.close();
 	}
 
diff --git a/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/GeneratorVerilog.java b/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/GeneratorVerilog.java
new file mode 100644
index 0000000..18efaa8
--- /dev/null
+++ b/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/GeneratorVerilog.java
@@ -0,0 +1,122 @@
+package org.crypttech.modexp.testgenerator.format;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.crypttech.modexp.testgenerator.TestVector;
+
+public class GeneratorVerilog extends ModExpTestFormater {
+	private BufferedReader br;
+	private List<String> taskCalls = new ArrayList<String>();
+	private boolean headerEmitted = false;
+
+	public GeneratorVerilog(String templateFile, String destinationFile)
+			throws FileNotFoundException {
+		super(new PrintWriter(destinationFile), true);
+		this.br = new BufferedReader(new InputStreamReader(new FileInputStream(
+				templateFile)));
+
+	}
+
+	@Override
+	public void format(TestVector testVector) {
+		emitHeader();
+
+		String testname = ("autogenerated_" + testVector.generator + "_" + testVector.seed)
+				.replace("-", "M");
+		taskCalls.add(testname + "();");
+
+		out("task " + testname + "();");
+		out("reg [31 : 0] read_data;");
+		out("begin");
+		out("tc_ctr = tc_ctr + 1;");
+		out("$display(\"" + testname + "\");");
+
+		for (int i = 0; i < testVector.X.length; i++)
+			out("write_word({MESSAGE_PREFIX, 8'h%02x}, 32'h%08x);", i,
+					testVector.X[i]);
+
+		for (int i = 0; i < testVector.E.length; i++)
+			out("write_word({EXPONENT_PREFIX, 8'h%02x}, 32'h%08x);", i,
+					testVector.E[i]);
+
+		out("write_word({GENERAL_PREFIX, ADDR_EXPONENT_LENGTH}, 32'h%08x););",
+				testVector.E.length);
+
+		for (int i = 0; i < testVector.M.length; i++)
+			out("write_word({MODULUS_PREFIX, 8'h%02x}, 32'h%08x);", i,
+					testVector.M[i]);
+
+		out("write_word({GENERAL_PREFIX, ADDR_MODULUS_LENGTH}, 32'h%08x););",
+				testVector.E.length);
+
+		out("dump_memories()");
+
+		out("write_word({GENERAL_PREFIX, ADDR_CTRL}, 32'h%08x);",
+				testVector.length);
+		out("wait_ready();");
+
+		for (int i = 0; i < testVector.expected.length; i++) {
+			out("read_word({RESULT_PREFIX,8'h%02x});", i);
+			out("read_data = tb_read_data;");
+			out("if (read_data !== 32'h%08x))", testVector.expected[i]);
+			out("  begin");
+			out("    $display(\"Expected: 0x%08x, got 0x%%08x\", read_data);",
+					testVector.expected[i]);
+			out("  end");
+		}
+		out("end");
+		out("endtask // " + testname);
+
+	}
+
+	@Override
+	public void close() throws Exception {
+		emitMiddle();
+		for (String taskCall : taskCalls)
+			out(taskCall);
+		emitFinal();
+		if (br != null)
+			br.close();
+		super.close();
+	}
+
+	private void emitHeader() {
+		if (headerEmitted == true)
+			return;
+		headerEmitted = true;
+		String terminatingLine = "===TEMPLATE_HEADER_END===";
+		emitTemplateSection(terminatingLine);
+	}
+
+	private void emitMiddle() {
+		String terminatingLine = "===TEMPLATE_CALL_TASKS===";
+		emitTemplateSection(terminatingLine);
+	}
+
+	private void emitFinal() {
+		String terminatingLine = "Never gonna give you up, never gonna let you down";
+		emitTemplateSection(terminatingLine);
+	}
+
+	private void emitTemplateSection(String terminatingLine) {
+		String line;
+		try {
+			while ((line = br.readLine()) != null) {
+				if (line.contains(terminatingLine))
+					return;
+				out(line);
+			}
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		} finally {
+		}
+	}
+
+}
diff --git a/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/ModExpTestFormater.java b/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/ModExpTestFormater.java
index c15ca88..7f9bbb3 100644
--- a/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/ModExpTestFormater.java
+++ b/src/testgenerator/src/org/crypttech/modexp/testgenerator/format/ModExpTestFormater.java
@@ -5,22 +5,33 @@ import java.io.PrintWriter;
 import org.crypttech.modexp.testgenerator.TestVector;
 
 public abstract class ModExpTestFormater implements AutoCloseable {
-	private PrintWriter pw;
-	
-	public ModExpTestFormater(PrintWriter pw) {
+	private static final char LF = (char) 10;
+	private final boolean alwaysLF;
+	private final PrintWriter pw;
+
+	public ModExpTestFormater(PrintWriter pw, boolean alwaysLF) {
 		this.pw = pw;
+		this.alwaysLF = alwaysLF;
+	}
+
+	public ModExpTestFormater(PrintWriter pw) {
+		this(pw, false);
 	}
-	
+
 	public abstract void format(TestVector testVector);
 
 	protected final void out(String s) {
 		pw.print(s);
+		if (alwaysLF)
+			pw.print(LF);
+	}
+
+	protected final void out(String frmt, Object... args) {
+		out(String.format(frmt, args));
 	}
-	
+
 	@Override
 	public void close() throws Exception {
 		pw.close();
 	}
-	
-	
 }
diff --git a/toolruns/Makefile b/toolruns/Makefile
index 835e2b0..64aed4f 100755
--- a/toolruns/Makefile
+++ b/toolruns/Makefile
@@ -2,38 +2,38 @@
 #
 # Makefile
 # --------
-# Makefile for building the modular exponentiation submodules,
-# core and top simulations.
+# Makefile for building the modular exponentiation submodules, core
+# and top simulations.
 #
 #
-# Author: Joachim Strombergson, Peter Magnusson
-# Copyright (c) 2015, NORDUnet A/S All rights reserved.
+# 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:
-# - Redistributions of source code must retain the above copyright notice,
-#   this list of conditions and the following disclaimer.
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
 #
-# - 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.
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
 #
-# - 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.
+# 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
-# 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.
+# 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.
 #
 #===================================================================
 
@@ -53,16 +53,16 @@ RESIDUE_SRC = ../src/rtl/residue.v
 MONTPROD_TB = ../src/tb/tb_montprod.v
 MONTPROD_SRC = ../src/rtl/montprod.v
 
-TOP_SRC=../src/rtl/modexp.v $(MONTPROD_SRC) $(RESIDUE_SRC) $(COMMON_SRC)
-TOP_TB=../src/tb/tb_modexp.v
+MODEXP_SRC=../src/rtl/modexp.v $(MONTPROD_SRC) $(RESIDUE_SRC) $(COMMON_SRC)
+MODEXP_TB=../src/tb/tb_modexp.v
 
 
 # Rules.
-all: top.sim montprod.sim residue.sim
+all: modexp.sim montprod.sim residue.sim
 
 
-top.sim: $(TOP_TB) $(TOP_SRC)
-	$(CC) $(CCFLAGS) -o top.sim $(TOP_TB) $(TOP_SRC)
+modexp.sim: $(MODEXP_TB) $(MODEXP_SRC)
+	$(CC) $(CCFLAGS) -o modexp.sim $(MODEXP_TB) $(MODEXP_SRC)
 
 
 montprod.sim: $(MONTPROD_TB) $(MONTPROD_SRC) $(COMMON_SRC)
@@ -73,8 +73,8 @@ residue.sim: $(RESIDUE_TB) $(RESIDUE_SRC) $(COMMON_SRC)
 	$(CC) $(CCFLAGS) -o residue.sim $(RESIDUE_TB) $(RESIDUE_SRC) $(COMMON_SRC)
 
 
-sim-top: top.sim
-	./top.sim
+sim-modexp: modexp.sim
+	./modexp.sim
 
 
 sim-montprod: montprod.sim
@@ -95,12 +95,16 @@ lint:
 	@echo ""
 
 	@echo "Linting of modexp:"
-	$(LINT) $(LINTFLAGS) --top-module modexp $(TOP_SRC)
+	$(LINT) $(LINTFLAGS) --top-module modexp $(MODEXP_SRC)
 	@echo ""
 
 
+autogenerate-tests:
+	javac -cp ../src/testgenerator/src/ -d ../src/testgenerator/bin/ ../src/testgenerator/src/org/crypttech/modexp/testgenerator/TestGenerator.java
+	java -cp ../src/testgenerator/bin/ org.crypttech.modexp.testgenerator.TestGenerator ../src
+
 clean:
-	rm -f top.sim
+	rm -f modexp.sim
 	rm -f montprod.sim
 	rm -f residue.sim
 
@@ -112,7 +116,7 @@ help:
 	@echo "------------------"
 	@echo "all:          Build all simulation targets."
 	@echo "lint:         Lint all modules and hierarchies."
-	@echo "top.sim:      Build top level simulation target."
+	@echo "modexp.sim:   Build modexp simulation target."
 	@echo "montprod.sim: Build Montgomery product simulation target."
 	@echo "residue.sim:  Build Residue calculation simulation target."
 	@echo "sim-top:      Run top level simulation."



More information about the Commits mailing list