aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Selkirk <paul@psgd.org>2017-01-17 23:43:46 -0500
committerPaul Selkirk <paul@psgd.org>2017-01-17 23:43:46 -0500
commit8fd190d498cc68a8b51b4141c1ed6f12ef2ec2dd (patch)
tree0127422845da6f4fca9799ba5a1ff95b04e82cf9
parent2f4a3aaf057b21a830112461d77bd4717ac41737 (diff)
Rename and rewrite the core_selector generator.
By moving most of the domain-specific knowledge from the script to the config file, we can a) merge back the fork in platform/alpha, and b) remove the special-case code that has to know about the modexp and trng cores.
-rw-r--r--config/config.cfg140
-rw-r--r--config/core.cfg255
-rwxr-xr-xconfig/core_config.py (renamed from config/config.py)357
-rw-r--r--config/core_selector.v278
-rw-r--r--config/core_vfiles.mk42
5 files changed, 384 insertions, 688 deletions
diff --git a/config/config.cfg b/config/config.cfg
deleted file mode 100644
index d3834d6..0000000
--- a/config/config.cfg
+++ /dev/null
@@ -1,140 +0,0 @@
-# Config file for the Cryptech Novena FPGA framework.
-#
-# Variables used in this file:
-#
-# default-section: Name of the configuration to build if the user
-# doesn't specify one. Only meaningful in the default section.
-#
-# cores: A list of cores to build. Use with the --section option.
-#
-# vfiles: A list of Verilog files to include in the vfiles list when
-# including a particular core. All (optional) cores must have a
-# vfiles option, so that the configuration program knows what to put
-# into core_vfiles.mk.
-#
-# requires: A list of other cores whose vfiles must be loaded to build
-# this core. This has no effect on the generated core_selector.v
-# file, and has no effect at all if an instance of a core named here
-# is already included in the build.
-#
-# error_wire: boolean indicating whether the core wants a error wire.
-#
-# block_memory: boolean indicating whether the core uses block memory.
-# Effect of this is a bit strange: setting it triggers generation of
-# a one-cycle timing delay for every core in this build that does
-# *not* use block memory. When no cores in the build use block
-# memory, the delay isn't necessary and is therefore omitted.
-
-[default]
-default-section = rsa
-
-# for quick builds to test the bus
-[bare]
-cores =
-
-[hash]
-cores = sha1 sha256 sha512
-
-[trng]
-cores = trng
-
-[modexp]
-cores = modexps6
-
-[rsa]
-cores = sha256 aes trng modexps6
-
-[mkmif]
-cores = mkmif
-
-# include multiple of the same core
-[multi-test]
-cores = sha256 aes aes chacha aes
-
-[sha1]
-vfiles =
- hash/sha1/src/rtl/sha1.v
- hash/sha1/src/rtl/sha1_core.v
- hash/sha1/src/rtl/sha1_w_mem.v
-
-[sha256]
-vfiles =
- hash/sha256/src/rtl/sha256.v
- hash/sha256/src/rtl/sha256_core.v
- hash/sha256/src/rtl/sha256_k_constants.v
- hash/sha256/src/rtl/sha256_w_mem.v
-
-[sha512]
-vfiles =
- hash/sha512/src/rtl/sha512.v
- hash/sha512/src/rtl/sha512_core.v
- hash/sha512/src/rtl/sha512_h_constants.v
- hash/sha512/src/rtl/sha512_k_constants.v
- hash/sha512/src/rtl/sha512_w_mem.v
-
-[trng]
-requires = chacha sha512
-vfiles =
- rng/avalanche_entropy/src/rtl/avalanche_entropy.v
- rng/avalanche_entropy/src/rtl/avalanche_entropy_core.v
- rng/rosc_entropy/src/rtl/rosc.v
- rng/rosc_entropy/src/rtl/rosc_entropy.v
- rng/rosc_entropy/src/rtl/rosc_entropy_core.v
- rng/trng/src/rtl/trng.v
- rng/trng/src/rtl/trng_csprng.v
- rng/trng/src/rtl/trng_csprng_fifo.v
- rng/trng/src/rtl/trng_mixer.v
-
-[aes]
-vfiles =
- cipher/aes/src/rtl/aes.v
- cipher/aes/src/rtl/aes_core.v
- cipher/aes/src/rtl/aes_decipher_block.v
- cipher/aes/src/rtl/aes_encipher_block.v
- cipher/aes/src/rtl/aes_inv_sbox.v
- cipher/aes/src/rtl/aes_key_mem.v
- cipher/aes/src/rtl/aes_sbox.v
-
-[chacha]
-vfiles =
- cipher/chacha/src/rtl/chacha.v
- cipher/chacha/src/rtl/chacha_core.v
- cipher/chacha/src/rtl/chacha_qr.v
-
-[modexps6]
-block_memory = yes
-error_wire = no
-vfiles =
- math/modexps6/src/rtl/modexps6_adder64_carry32.v
- math/modexps6/src/rtl/modexps6_buffer_core.v
- math/modexps6/src/rtl/modexps6_buffer_user.v
- math/modexps6/src/rtl/modexps6_modinv32.v
- math/modexps6/src/rtl/modexps6_montgomery_coeff.v
- math/modexps6/src/rtl/modexps6_montgomery_multiplier.v
- math/modexps6/src/rtl/modexps6_top.v
- math/modexps6/src/rtl/modexps6_wrapper.v
- math/modexps6/src/rtl/ram_1rw_1ro_readfirst.v
- math/modexps6/src/rtl/ipcore/multiplier_s6.v
- math/modexps6/src/rtl/ipcore/subtractor_s6.v
-
-[modexp]
-error_wire = no
-vfiles =
- math/modexp/src/rtl/adder.v
- math/modexp/src/rtl/blockmem1r1w.v
- math/modexp/src/rtl/blockmem2r1wptr.v
- math/modexp/src/rtl/blockmem2r1w.v
- math/modexp/src/rtl/blockmem2rptr1w.v
- math/modexp/src/rtl/modexp.v
- math/modexp/src/rtl/modexp_core.v
- math/modexp/src/rtl/montprod.v
- math/modexp/src/rtl/residue.v
- math/modexp/src/rtl/shl.v
- math/modexp/src/rtl/shr.v
-
-[mkmif]
-error_wire = no
-vfiles =
- util/mkmif/src/rtl/mkmif.v
- util/mkmif/src/rtl/mkmif_core.v
- util/mkmif/src/rtl/mkmif_spi.v
diff --git a/config/core.cfg b/config/core.cfg
new file mode 100644
index 0000000..48e92ff
--- /dev/null
+++ b/config/core.cfg
@@ -0,0 +1,255 @@
+# Config file for the Cryptech FPGA framework.
+
+# [default] section. Defines defaults, if not specified on the command line.
+#
+# board: Name of the default [board] section to build, if the --board
+# option is not given.
+#
+# project: Name of the default [project] section to build, if the
+# --project option is not given.
+
+[default]
+board = alpha
+project = hsm
+
+# [board] sections, defining the target device.
+#
+# bus name: Name of the FPGA communications bus, used by applications to
+# read/write the FPGA core registers.
+#
+# bus width: Width of the FPGA address bus. (The data bus is always 32 bits.)
+#
+# extra wires: Defines extra I/O ports in the core_selector module definition.
+# Note this is a blob of text, not interpreted, so formatting and commas
+# will be copied out verbatim.
+#
+# requires: A list of cores that must be present. This supports a fallback
+# scheme so that, for example, if 'mkmif' is not in the project's list
+# of cores, it will use 'dummy-mkmif' instead. In this case, there is no
+# whitespace around the '/'.
+
+[board alpha]
+# Cryptech Alpha board
+bus name = fmc
+bus width = 24
+modexp = modexpa7
+extra wires =
+ output wire mkm_sclk,
+ output wire mkm_cs_n,
+ input wire mkm_do,
+ output wire mkm_di,
+requires = mkmif/dummy-mkmif
+
+[board dev-bridge]
+# Cryptech dev-bridge board - a Novena daughterboard that talks to the
+# Novena's FPGA through the high-speed connector.
+bus name = fmc
+bus width = 17
+modexp = modexps6
+
+[board novena]
+# Novena board
+bus name = eim
+bus width = 17
+modexp = modexps6
+
+# [project] sections
+#
+# cores: A list of cores to build.
+
+[project bare]
+# for quick builds to test the bus
+cores =
+
+[project hash]
+# for testing just the SHA cores
+cores = sha1 sha256 sha512
+
+[project trng]
+# for testing just the True Random Number Generator
+cores = trng
+
+[project modexp]
+# for testing just the Modular Exponentiation
+cores = modexp
+
+[project mkmif]
+# for testing just the Master Key Memory Interface
+cores = mkmif
+
+[project rsa]
+# RSA signing and verification. This is as much as will fit on the
+# Novena's Spartan-6 FPGA.
+cores = sha256 aes trng modexp
+
+[project hsm]
+# make me one with everything
+#cores = sha1 sha256 sha512 aes trng modexp
+# super-size it
+cores = mkmif trng sha1 sha1 sha1 sha256 sha256 sha256 sha512 sha512 sha512 aes aes aes modexp modexp modexp
+
+# [core] sections
+#
+# vfiles: A list of Verilog files to include in the vfiles list when
+# including a particular core. All (optional) cores must have a
+# vfiles option, so that the configuration program knows what to put
+# into core_vfiles.mk.
+#
+# requires: A list of other cores whose vfiles must be loaded to build
+# this core. This has no effect on the generated core_selector.v
+# file, and has no effect at all if an instance of a core named here
+# is already included in the build.
+#
+# subcores: The TRNG core has an internal mux with slots for 16 sub-cores
+# (although it only uses 4). Unlike 'requires', subcores consume address
+# space and have to be accounted for in core_selector.v.
+#
+# core blocks: By default, each core gets a block of 256 registers. If a
+# core needs more address space (e.g. for block memories or subcores),
+# set the number of 256-block registers here.
+#
+# error wire: boolean indicating whether the core wants a error wire.
+#
+# block memory: boolean indicating whether the core uses block memory.
+# Effect of this is a bit strange: setting it triggers generation of
+# a one-cycle timing delay for every core in this build that does
+# *not* use block memory. When no cores in the build use block
+# memory, the delay isn't necessary and is therefore omitted.
+#
+# extra ports: Extra port definitions in the core instance.
+# Note this is a blob of text, not interpreted, so formatting and commas
+# will be copied out verbatim.
+
+[core sha1]
+vfiles =
+ hash/sha1/src/rtl/sha1.v
+ hash/sha1/src/rtl/sha1_core.v
+ hash/sha1/src/rtl/sha1_w_mem.v
+
+[core sha256]
+vfiles =
+ hash/sha256/src/rtl/sha256.v
+ hash/sha256/src/rtl/sha256_core.v
+ hash/sha256/src/rtl/sha256_k_constants.v
+ hash/sha256/src/rtl/sha256_w_mem.v
+
+[core sha512]
+vfiles =
+ hash/sha512/src/rtl/sha512.v
+ hash/sha512/src/rtl/sha512_core.v
+ hash/sha512/src/rtl/sha512_h_constants.v
+ hash/sha512/src/rtl/sha512_k_constants.v
+ hash/sha512/src/rtl/sha512_w_mem.v
+
+[core trng]
+requires = chacha sha512
+core blocks = 16
+subcores =
+ avalanche_entropy
+ rosc_entropy
+ trng_mixer
+ trng_csprng
+extra ports =
+ .avalanche_noise(noise),
+ .debug(debug),
+vfiles =
+ rng/avalanche_entropy/src/rtl/avalanche_entropy.v
+ rng/avalanche_entropy/src/rtl/avalanche_entropy_core.v
+ rng/rosc_entropy/src/rtl/rosc.v
+ rng/rosc_entropy/src/rtl/rosc_entropy.v
+ rng/rosc_entropy/src/rtl/rosc_entropy_core.v
+ rng/trng/src/rtl/trng.v
+ rng/trng/src/rtl/trng_csprng.v
+ rng/trng/src/rtl/trng_csprng_fifo.v
+ rng/trng/src/rtl/trng_mixer.v
+
+[core aes]
+vfiles =
+ cipher/aes/src/rtl/aes.v
+ cipher/aes/src/rtl/aes_core.v
+ cipher/aes/src/rtl/aes_decipher_block.v
+ cipher/aes/src/rtl/aes_encipher_block.v
+ cipher/aes/src/rtl/aes_inv_sbox.v
+ cipher/aes/src/rtl/aes_key_mem.v
+ cipher/aes/src/rtl/aes_sbox.v
+
+[core chacha]
+vfiles =
+ cipher/chacha/src/rtl/chacha.v
+ cipher/chacha/src/rtl/chacha_core.v
+ cipher/chacha/src/rtl/chacha_qr.v
+
+[core modexpa7]
+# ModExp for Xilinx Artix-7
+core blocks = 4
+block memory = yes
+error wire = no
+module name = modexpa7_wrapper
+vfiles =
+ math/modexpa7/src/rtl/dsp_multiplier_a7.v
+ math/modexpa7/src/rtl/dsp_subtractor_a7.v
+ math/modexpa7/src/rtl/modexpa7_adder64_carry32.v
+ math/modexpa7/src/rtl/modexpa7_buffer_core.v
+ math/modexpa7/src/rtl/modexpa7_buffer_user.v
+ math/modexpa7/src/rtl/modexpa7_modinv32.v
+ math/modexpa7/src/rtl/modexpa7_montgomery_coeff.v
+ math/modexpa7/src/rtl/modexpa7_montgomery_multiplier.v
+ math/modexpa7/src/rtl/modexpa7_top.v
+ math/modexpa7/src/rtl/modexpa7_wrapper.v
+ math/modexpa7/src/rtl/ram_1rw_1ro_readfirst.v
+
+[core modexps6]
+# ModExp for Xilinx Spartan-6
+core blocks = 4
+block memory = yes
+error wire = no
+module name = modexps6_wrapper
+vfiles =
+ math/modexps6/src/rtl/modexps6_adder64_carry32.v
+ math/modexps6/src/rtl/modexps6_buffer_core.v
+ math/modexps6/src/rtl/modexps6_buffer_user.v
+ math/modexps6/src/rtl/modexps6_modinv32.v
+ math/modexps6/src/rtl/modexps6_montgomery_coeff.v
+ math/modexps6/src/rtl/modexps6_montgomery_multiplier.v
+ math/modexps6/src/rtl/modexps6_top.v
+ math/modexps6/src/rtl/modexps6_wrapper.v
+ math/modexps6/src/rtl/ram_1rw_1ro_readfirst.v
+ math/modexps6/src/rtl/ipcore/multiplier_s6.v
+ math/modexps6/src/rtl/ipcore/subtractor_s6.v
+
+[core modexp]
+# portable ModExp
+error wire = no
+vfiles =
+ math/modexp/src/rtl/adder.v
+ math/modexp/src/rtl/blockmem1r1w.v
+ math/modexp/src/rtl/blockmem2r1wptr.v
+ math/modexp/src/rtl/blockmem2r1w.v
+ math/modexp/src/rtl/blockmem2rptr1w.v
+ math/modexp/src/rtl/modexp.v
+ math/modexp/src/rtl/modexp_core.v
+ math/modexp/src/rtl/montprod.v
+ math/modexp/src/rtl/residue.v
+ math/modexp/src/rtl/shl.v
+ math/modexp/src/rtl/shr.v
+
+[core mkmif]
+# Master Key Memory Interface
+error wire = no
+extra ports =
+ .spi_sclk(mkm_sclk),
+ .spi_cs_n(mkm_cs_n),
+ .spi_do(mkm_do),
+ .spi_di(mkm_di),
+vfiles =
+ util/mkmif/src/rtl/mkmif.v
+ util/mkmif/src/rtl/mkmif_core.v
+ util/mkmif/src/rtl/mkmif_spi.v
+
+[core dummy-mkmif]
+# Dummy wires if the mkmif core isn't present, so we don't have unsourced
+# outputs.
+dummy =
+ assign mkm_sclk = 0;
+ assign mkm_cs_n = 0;
+ assign mkm_di = 0;
diff --git a/config/config.py b/config/core_config.py
index 5ff3ccc..3f75243 100755
--- a/config/config.py
+++ b/config/core_config.py
@@ -5,7 +5,7 @@ Generate core_selector.v and core_vfiles.mk for a set of cores.
"""
#=======================================================================
-# Copyright (c) 2015, NORDUnet A/S All rights reserved.
+# Copyright (c) 2015-2017, NORDUnet A/S All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -34,9 +34,9 @@ Generate core_selector.v and core_vfiles.mk for a set of cores.
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#=======================================================================
-# The modexps6 core drags in a one clock cycle delay to other cores,
+# The modexpa7 core drags in a one clock cycle delay to other cores,
# to compensate for the extra clock cycle consumed by the block
-# memories used in the modexps6 core. We probably want a general
+# memories used in the modexpa7 core. We probably want a general
# solution for this, because we're going to run into this problem for
# any core that handles arguments big enough to require block memory.
@@ -48,9 +48,6 @@ Generate core_selector.v and core_vfiles.mk for a set of cores.
# all other cores would get the delay. Slightly tedious but
# something we can calculate easily enough, and probably an
# improvement over wiring in the delay when nothing needs it.
-#
-# - Rename script and its config file to something more meaningful.
-
def main():
"""
@@ -62,10 +59,11 @@ def main():
parser = ArgumentParser(description = __doc__, formatter_class = ArgumentDefaultsHelpFormatter)
parser.add_argument("-d", "--debug", help = "enable debugging", action = "store_true")
- parser.add_argument("-s", "--section", help = "config file section")
- parser.add_argument("-c", "--config", help = "configuration file", default = "config.cfg", type = FileType("r"))
- parser.add_argument("--verilog", help = "verilog output file", default = "core_selector.v", type = FileType("w"))
- parser.add_argument("--makefile", help = "output makefile", default = "core_vfiles.mk", type = FileType("w"))
+ parser.add_argument("-c", "--config", help = "configuration file", default = "core.cfg", type = FileType("r"))
+ parser.add_argument("-b", "--board", help = "config file 'board' section")
+ parser.add_argument("-p", "--project", help = "config file 'project' section")
+ parser.add_argument("-v", "--verilog", help = "verilog output file",default = "core_selector.v", type = FileType("w"))
+ parser.add_argument("-m", "--makefile",help = "output makefile", default = "core_vfiles.mk", type = FileType("w"))
parser.add_argument("core", help = "name(s) of core(s)", nargs = "*")
args = parser.parse_args()
@@ -73,23 +71,46 @@ def main():
cfg = RawConfigParser()
cfg.readfp(args.config)
+ board = args.board or cfg.get("default", "board")
+ board_section = "board " + board
+ Core.bus_name = cfg.get(board_section, "bus name")
+ Core.bus_width = int(cfg.get(board_section, "bus width"))
+ Core.bus_max = Core.bus_width - 1
+ Core.addr_width = Core.bus_width - 8
+ Core.addr_max = Core.addr_width - 1
+ Core.extra_wires = cfg.get(board_section, "extra wires")
+ Core.modexp = cfg.get(board_section, "modexp")
+ if Core.extra_wires:
+ # restore formatting
+ Core.extra_wires = Core.extra_wires.replace("\n", "\n ") + "\n"
+
if args.core:
cores = args.core
else:
- section = args.section or cfg.get("default", "default-section")
- cores = cfg.get(section, "cores").split()
+ project = args.project or cfg.get("default", "project")
+ cores = cfg.get("project " + project, "cores").split()
+
+ for core in cfg.getvalues(board_section, "requires"):
+ try:
+ (c1, c2) = core.split("/")
+ if c1 not in cores and c2 not in cores:
+ cores.append(c2)
+ except ValueError:
+ if core not in cores:
+ cores.append(core)
+
cores.insert(0, "board_regs")
cores.insert(1, "comm_regs")
- cores = tuple(Core.new(core) for core in cores)
+ cores = tuple(Core(core) for core in cores)
- core_number = 0
for core in cores:
- core_number = core.assign_core_number(core_number)
+ core.configure(cfg)
+ core_number = 0
for core in cores:
- core.configure(cfg)
+ core_number = core.assign_core_number(core_number)
if False:
@@ -101,10 +122,10 @@ def main():
Core.need_one_cycle_delay = any(core.block_memory for core in cores)
args.verilog.write(createModule_template.format(
+ core = cores[0],
addrs = "".join(core.createAddr() for core in cores),
insts = "".join(core.createInstance() for core in cores),
- muxes = "".join(core.createMux() for core in cores),
- ports = "".join(core.createPort() for core in cores) ))
+ muxes = "".join(core.createMux() for core in cores) ))
args.makefile.write(listVfiles_template.format(
vfiles = "".join(core.listVfiles() for core in cores)))
@@ -137,6 +158,17 @@ class RawConfigParser(configparser.RawConfigParser):
for value in self.get(section, option).split():
yield value
+ def get(self, section, option):
+ try:
+ return configparser.RawConfigParser.get(self, section, option)
+ except configparser.NoSectionError:
+ if section in ("core board_regs", "core comm_regs"):
+ return ""
+ else:
+ raise
+ except configparser.NoOptionError:
+ return ""
+
class Core(object):
"""
@@ -150,40 +182,59 @@ class Core(object):
_instance_count = {}
- # Class variable mapping core name to subclass for special cases.
-
- special_class = {}
-
# Class variable recording whether we need a one-cycle delay to
# compensate for block memories.
need_one_cycle_delay = True
def __init__(self, name):
+ if Core.modexp and name == "modexp":
+ name = Core.modexp
self.name = name
+ self.cfg_section = "core " + name
self.core_number = None
self.vfiles = []
self.error_wire = True
self.block_memory = False
self.instance_number = self._instance_count.get(name, 0)
self._instance_count[name] = self.instance_number + 1
-
- @classmethod
- def new(cls, name):
- return cls.special_class.get(name, cls)(name)
+ self.subcores = []
+ self.blocks = 1
+ self.dummy = False
def assign_core_number(self, n):
self.core_number = n
- return n + 1
+ for i, subcore in enumerate(self.subcores):
+ subcore.assign_core_number(n + i + 1)
+ return n + self.blocks
def configure(self, cfg):
if self.instance_number == 0:
- self.vfiles.extend(cfg.getvalues(self.name, "vfiles"))
- for required in cfg.getvalues(self.name, "requires"):
+ self.vfiles.extend(cfg.getvalues(self.cfg_section, "vfiles"))
+ for required in cfg.getvalues(self.cfg_section, "requires"):
if required not in self._instance_count:
- self.vfiles.extend(cfg.getvalues(required, "vfiles"))
- self.error_wire = cfg.getboolean(self.name, "error_wire", self.error_wire)
- self.block_memory = cfg.getboolean(self.name, "block_memory", self.block_memory)
+ self.vfiles.extend(cfg.getvalues("core " + required, "vfiles"))
+ self.error_wire = cfg.getboolean(self.cfg_section, "error wire", self.error_wire)
+ self.block_memory = cfg.getboolean(self.cfg_section, "block memory", self.block_memory)
+ self.extra_ports = cfg.get(self.cfg_section, "extra ports")
+ if self.extra_ports:
+ self.extra_ports = self.extra_ports.replace("\n", "\n ") + "\n"
+ self.blocks = int(cfg.get(self.cfg_section, "core blocks") or 1)
+ self.block_max = self.blocks - 1
+ if self.blocks > 1:
+ try:
+ self.block_bits = {4:2, 8:3, 16:4}[self.blocks]
+ except KeyError:
+ raise ValueError, "In [{}]: unexpected value \"core blocks = {}\"".format(self.cfg_section, self.blocks)
+ self.block_bit_max = self.block_bits - 1
+ for subcore in cfg.getvalues(self.cfg_section, "subcores"):
+ self.subcores.append(SubCore(subcore, self))
+ if len(self.subcores) > self.blocks - 1:
+ raise ValueError, "In [{}]: number of subcores exceeds size of \"core blocks\"".format(self.cfg_section)
+ self.module_name = cfg.get(self.cfg_section, "module name") or self.name
+ self.dummy = cfg.get(self.cfg_section, "dummy")
+ if self.dummy:
+ self.dummy = self.dummy.replace("\n", "\n ") + "\n"
@property
def instance_name(self):
@@ -197,8 +248,8 @@ class Core(object):
return self.instance_name.upper()
@property
- def reset_pin(self):
- return ".reset_n(sys_rst_n)"
+ def error_wire_decl(self):
+ return "\n wire error_{core.instance_name};".format(core = self) if self.error_wire else ""
@property
def error_port(self):
@@ -209,6 +260,13 @@ class Core(object):
return one_cycle_delay_template.format(core = self) if self.need_one_cycle_delay and not self.block_memory else ""
@property
+ def mux_core_addr(self):
+ if self.blocks == 1 or self.subcores:
+ return "CORE_ADDR_{core.upper_instance_name}".format(core=self)
+ else:
+ return ",\n ".join("CORE_ADDR_{core.upper_instance_name} + {0}".format(i, core=self) for i in range(self.blocks))
+
+ @property
def mux_data_reg(self):
return "read_data_" + self.instance_name + ("_reg" if self.need_one_cycle_delay and not self.block_memory else "")
@@ -217,16 +275,18 @@ class Core(object):
return "error_" + self.instance_name if self.error_wire else "0"
def createInstance(self):
- return createInstance_template_generic.format(core = self)
+ template = createInstance_template_dummy if self.dummy else createInstance_template_generic if self.blocks == 1 else createInstance_template_multi_block
+ return template.format(core = self)
def createAddr(self):
- return createAddr_template.format(core = self)
+ if self.dummy:
+ return ""
+ return createAddr_template.format(core = self) + "".join(subcore.createAddr() for subcore in self.subcores)
def createMux(self):
- return createMux_template.format(core = self, core0 = self)
-
- def createPort(self):
- return ""
+ if self.dummy:
+ return ""
+ return createMux_template.format(core = self, core0 = self) + "".join(subcore.createMux() for subcore in self.subcores)
def listVfiles(self):
return "".join(" \\\n\t$(CORE_TREE)/" + vfile for vfile in self.vfiles)
@@ -245,92 +305,6 @@ class SubCore(Core):
return createMux_template.format(core = self, core0 = self.parent)
-class TRNGCore(Core):
- """
- The TRNG core has an internal mux with slots for 15 sub-cores,
- most of which are empty. This is a bit of a mess.
-
- Mostly this means that our method calls have to iterate over all
- of the subcores after handling the base TRNG core, but we also use
- different templates, and fiddle with addresses a bit.
-
- Mux numbers have to be dug out of the TRNG Verilog source.
- """
-
- # TRNG subcore name -> internal mux number.
- subcore_parameters = dict(avalanche_entropy = 0x1,
- rosc_entropy = 0x2,
- trng_mixer = 0x3,
- trng_csprng = 0x4)
-
- def __init__(self, name):
- super(TRNGCore, self).__init__(name)
- self.subcores = tuple(SubCore(name, self)
- for name in sorted(self.subcore_parameters,
- key = lambda x: self.subcore_parameters[x]))
-
- def assign_core_number(self, n):
- n = super(TRNGCore, self).assign_core_number(n)
- for subcore in self.subcores:
- subcore.assign_core_number(self.core_number + self.subcore_parameters[subcore.name])
- return n + 15
-
- @property
- def last_subcore_upper_instance_name(self):
- return self.subcores[-1].upper_instance_name
-
- def createInstance(self):
- return createInstance_template_TRNG.format(core = self)
-
- def createAddr(self):
- return super(TRNGCore, self).createAddr() + "".join(subcore.createAddr() for subcore in self.subcores)
-
- def createMux(self):
- return super(TRNGCore, self).createMux() + "".join(subcore.createMux() for subcore in self.subcores)
-
-
-class ModExpS6Core(Core):
- """
- ModExpS6 core consumes as much space as four ordinary cores, and
- uses different templates to handle the differences in timing and
- addressing.
- """
-
- def assign_core_number(self, n):
- n = super(ModExpS6Core, self).assign_core_number(n)
- return n + 3
-
- def createInstance(self):
- return createInstance_template_ModExpS6.format(core = self)
-
- def createMux(self):
- return createMux_modexps6_template.format(core = self, core0 = self)
-
-class MkmifCore(Core):
- """
- MKM interface core has extra ports for the SPI signal lines.
- """
-
- def createPort(self):
- return """ \
-
- output wire mkm_sclk,
- output wire mkm_cs_n,
- input wire mkm_do,
- output wire mkm_di,
- """
-
- def createInstance(self):
- return createInstance_template_MKMIF.format(core = self)
-
-# Hook special classes in as handlers for the cores that require them.
-
-Core.special_class.update(
- trng = TRNGCore,
- modexps6 = ModExpS6Core,
- mkmif = MkmifCore)
-
-
# Templates (format strings), here instead of inline in the functions
# that use them, both because some of these are shared between
# multiple functions and because it's easier to read these (and get
@@ -339,7 +313,7 @@ Core.special_class.update(
# Template used by .createAddr() methods.
createAddr_template = """\
- localparam CORE_ADDR_{core.upper_instance_name:21s} = 9'h{core.core_number:02x};
+ localparam CORE_ADDR_{core.upper_instance_name:21s} = {core.addr_width}'h{core.core_number:02x};
"""
# Template used by Core.createInstance().
@@ -349,16 +323,15 @@ createInstance_template_generic = """\
// {core.upper_instance_name}
//----------------------------------------------------------------
wire enable_{core.instance_name} = (addr_core_num == CORE_ADDR_{core.upper_instance_name});
- wire [31: 0] read_data_{core.instance_name};
- wire error_{core.instance_name};
+ wire [31: 0] read_data_{core.instance_name};{core.error_wire_decl}
- {core.name} {core.instance_name}_inst
+ {core.module_name} {core.instance_name}_inst
(
.clk(sys_clk),
- {core.reset_pin},
-
- .cs(enable_{core.instance_name} & (sys_eim_rd | sys_eim_wr)),
- .we(sys_eim_wr),
+ .reset_n(sys_rst_n),
+{core.extra_ports}
+ .cs(enable_{core.instance_name} & (sys_{core.bus_name}_rd | sys_{core.bus_name}_wr)),
+ .we(sys_{core.bus_name}_wr),
.address(addr_core_reg),
.write_data(sys_write_data),
@@ -369,97 +342,39 @@ createInstance_template_generic = """\
"""
-# Template used by ModExpS6Core.createInstance(). This is different
+# Template used for multi-block cores (modexp and trng). This is different
# enough from the base template that it's easier to make this separate.
-createInstance_template_ModExpS6 = """\
+createInstance_template_multi_block = """\
//----------------------------------------------------------------
// {core.upper_instance_name}
//----------------------------------------------------------------
- wire enable_{core.instance_name} = (addr_core_num >= CORE_ADDR_{core.upper_instance_name}) && (addr_core_num <= CORE_ADDR_{core.upper_instance_name} + 9'h03);
- wire [31: 0] read_data_{core.instance_name};
- wire [1:0] {core.instance_name}_prefix = addr_core_num[1:0] - CORE_ADDR_{core.upper_instance_name};
+ wire enable_{core.instance_name} = (addr_core_num >= CORE_ADDR_{core.upper_instance_name}) && (addr_core_num <= CORE_ADDR_{core.upper_instance_name} + {core.addr_width}'h{core.block_max:02x});
+ wire [31: 0] read_data_{core.instance_name};{core.error_wire_decl}
+ wire [{core.block_bit_max}:0] {core.instance_name}_prefix = addr_core_num[{core.block_bit_max}:0] - CORE_ADDR_{core.upper_instance_name};
- {core.name}_wrapper {core.instance_name}_inst
+ {core.module_name} {core.instance_name}_inst
(
.clk(sys_clk),
- {core.reset_pin},
-
- .cs(enable_{core.instance_name} & (sys_eim_rd | sys_eim_wr)),
- .we(sys_eim_wr),
+ .reset_n(sys_rst_n),
+{core.extra_ports}
+ .cs(enable_{core.instance_name} & (sys_{core.bus_name}_rd | sys_{core.bus_name}_wr)),
+ .we(sys_{core.bus_name}_wr),
.address({{{core.instance_name}_prefix, addr_core_reg}}),
.write_data(sys_write_data),
- .read_data(read_data_{core.instance_name})
- );
-
-
-"""
-
-# Template used by TRNGCore.createInstance(); this is different enough
-# from the generic template that it's (probably) clearer to have this
-# separate.
-
-createInstance_template_TRNG = """\
- //----------------------------------------------------------------
- // {core.upper_instance_name}
- //----------------------------------------------------------------
- wire enable_{core.instance_name} = (addr_core_num >= CORE_ADDR_{core.upper_instance_name}) && (addr_core_num <= CORE_ADDR_{core.upper_instance_name} + 9'h0f);
- wire [31: 0] read_data_{core.instance_name};
- wire error_{core.instance_name};
- wire [3:0] {core.instance_name}_prefix = addr_core_num[3:0] - CORE_ADDR_{core.upper_instance_name};
-
- {core.name} {core.instance_name}_inst
- (
- .clk(sys_clk),
- {core.reset_pin},
-
- .cs(enable_{core.instance_name} & (sys_eim_rd | sys_eim_wr)),
- .we(sys_eim_wr),
-
- .address({{{core.instance_name}_prefix, addr_core_reg}}),
- .write_data(sys_write_data),
- .read_data(read_data_{core.instance_name}),
- .error(error_{core.instance_name}),
-
- .avalanche_noise(noise),
- .debug(debug)
+ .read_data(read_data_{core.instance_name}){core.error_port}
);
{core.one_cycle_delay}
"""
-# Template used by Mkmif.createInstance(). This is different
-# enough from the base template that it's easier to make this separate.
-
-createInstance_template_MKMIF = """\
+createInstance_template_dummy = """\
//----------------------------------------------------------------
// {core.upper_instance_name}
//----------------------------------------------------------------
- wire enable_{core.instance_name} = (addr_core_num == CORE_ADDR_{core.upper_instance_name});
- wire [31: 0] read_data_{core.instance_name};
-
- {core.name} {core.instance_name}_inst
- (
- .clk(sys_clk),
- {core.reset_pin},
-
- .spi_sclk(mkm_sclk),
- .spi_cs_n(mkm_cs_n),
- .spi_do(mkm_do),
- .spi_di(mkm_di),
-
- .cs(enable_{core.instance_name} & (sys_eim_rd | sys_eim_wr)),
- .we(sys_eim_wr),
-
- .address(addr_core_reg),
- .write_data(sys_write_data),
- .read_data(read_data_{core.instance_name}){core.error_port}
- );
-
-{core.one_cycle_delay}
-
+{core.dummy}
"""
# Template for one-cycle delay code.
@@ -473,44 +388,30 @@ one_cycle_delay_template = """\
# Template for .createMux() methods.
createMux_template = """\
- CORE_ADDR_{core.upper_instance_name}:
- begin
- sys_read_data_mux = {core0.mux_data_reg};
- sys_error_mux = {core0.mux_error_reg};
- end
-"""
-
-# Template for ModExpS6.createMux() method.
-
-createMux_modexps6_template = """\
- CORE_ADDR_{core.upper_instance_name} + 0,
- CORE_ADDR_{core.upper_instance_name} + 1,
- CORE_ADDR_{core.upper_instance_name} + 2,
- CORE_ADDR_{core.upper_instance_name} + 3:
+ {core.mux_core_addr}:
begin
sys_read_data_mux = {core0.mux_data_reg};
sys_error_mux = {core0.mux_error_reg};
end
"""
-
# Top-level (createModule) template.
createModule_template = """\
-// NOTE: This file is generated; do not edit by hand.
+// NOTE: This file is generated; do not edit.
module core_selector
(
input wire sys_clk,
input wire sys_rst_n,
- input wire [16: 0] sys_eim_addr,
- input wire sys_eim_wr,
- input wire sys_eim_rd,
+ input wire [{core.bus_max}: 0] sys_{core.bus_name}_addr,
+ input wire sys_{core.bus_name}_wr,
+ input wire sys_{core.bus_name}_rd,
output wire [31: 0] sys_read_data,
input wire [31: 0] sys_write_data,
output wire sys_error,
-{ports}
+{core.extra_wires}
input wire noise,
output wire [7 : 0] debug
);
@@ -519,10 +420,10 @@ module core_selector
//----------------------------------------------------------------
// Address Decoder
//----------------------------------------------------------------
- // upper 9 bits specify core being addressed
- wire [ 8: 0] addr_core_num = sys_eim_addr[16: 8];
+ // upper {core.addr_width} bits specify core being addressed
+ wire [{core.addr_max:>2}: 0] addr_core_num = sys_{core.bus_name}_addr[{core.bus_max}: 8];
// lower 8 bits specify register offset in core
- wire [ 7: 0] addr_core_reg = sys_eim_addr[ 7: 0];
+ wire [ 7: 0] addr_core_reg = sys_{core.bus_name}_addr[ 7: 0];
//----------------------------------------------------------------
diff --git a/config/core_selector.v b/config/core_selector.v
deleted file mode 100644
index 298c39e..0000000
--- a/config/core_selector.v
+++ /dev/null
@@ -1,278 +0,0 @@
-// NOTE: This file is generated; do not edit by hand.
-
-module core_selector
- (
- input wire sys_clk,
- input wire sys_rst_n,
-
- input wire [16: 0] sys_eim_addr,
- input wire sys_eim_wr,
- input wire sys_eim_rd,
- output wire [31: 0] sys_read_data,
- input wire [31: 0] sys_write_data,
- output wire sys_error,
-
- input wire noise,
- output wire [7 : 0] debug
- );
-
-
- //----------------------------------------------------------------
- // Address Decoder
- //----------------------------------------------------------------
- // upper 9 bits specify core being addressed
- wire [ 8: 0] addr_core_num = sys_eim_addr[16: 8];
- // lower 8 bits specify register offset in core
- wire [ 7: 0] addr_core_reg = sys_eim_addr[ 7: 0];
-
-
- //----------------------------------------------------------------
- // Core Address Table
- //----------------------------------------------------------------
- localparam CORE_ADDR_BOARD_REGS = 9'h00;
- localparam CORE_ADDR_COMM_REGS = 9'h01;
- localparam CORE_ADDR_SHA256 = 9'h02;
- localparam CORE_ADDR_AES = 9'h03;
- localparam CORE_ADDR_TRNG = 9'h04;
- localparam CORE_ADDR_AVALANCHE_ENTROPY = 9'h05;
- localparam CORE_ADDR_ROSC_ENTROPY = 9'h06;
- localparam CORE_ADDR_TRNG_MIXER = 9'h07;
- localparam CORE_ADDR_TRNG_CSPRNG = 9'h08;
- localparam CORE_ADDR_MODEXPS6 = 9'h14;
-
-
- //----------------------------------------------------------------
- // BOARD_REGS
- //----------------------------------------------------------------
- wire enable_board_regs = (addr_core_num == CORE_ADDR_BOARD_REGS);
- wire [31: 0] read_data_board_regs;
- wire error_board_regs;
-
- board_regs board_regs_inst
- (
- .clk(sys_clk),
- .reset_n(sys_rst_n),
-
- .cs(enable_board_regs & (sys_eim_rd | sys_eim_wr)),
- .we(sys_eim_wr),
-
- .address(addr_core_reg),
- .write_data(sys_write_data),
- .read_data(read_data_board_regs),
- .error(error_board_regs)
- );
-
- reg [31: 0] read_data_board_regs_reg;
- always @(posedge sys_clk)
- read_data_board_regs_reg <= read_data_board_regs;
-
-
- //----------------------------------------------------------------
- // COMM_REGS
- //----------------------------------------------------------------
- wire enable_comm_regs = (addr_core_num == CORE_ADDR_COMM_REGS);
- wire [31: 0] read_data_comm_regs;
- wire error_comm_regs;
-
- comm_regs comm_regs_inst
- (
- .clk(sys_clk),
- .reset_n(sys_rst_n),
-
- .cs(enable_comm_regs & (sys_eim_rd | sys_eim_wr)),
- .we(sys_eim_wr),
-
- .address(addr_core_reg),
- .write_data(sys_write_data),
- .read_data(read_data_comm_regs),
- .error(error_comm_regs)
- );
-
- reg [31: 0] read_data_comm_regs_reg;
- always @(posedge sys_clk)
- read_data_comm_regs_reg <= read_data_comm_regs;
-
-
- //----------------------------------------------------------------
- // SHA256
- //----------------------------------------------------------------
- wire enable_sha256 = (addr_core_num == CORE_ADDR_SHA256);
- wire [31: 0] read_data_sha256;
- wire error_sha256;
-
- sha256 sha256_inst
- (
- .clk(sys_clk),
- .reset_n(sys_rst_n),
-
- .cs(enable_sha256 & (sys_eim_rd | sys_eim_wr)),
- .we(sys_eim_wr),
-
- .address(addr_core_reg),
- .write_data(sys_write_data),
- .read_data(read_data_sha256),
- .error(error_sha256)
- );
-
- reg [31: 0] read_data_sha256_reg;
- always @(posedge sys_clk)
- read_data_sha256_reg <= read_data_sha256;
-
-
- //----------------------------------------------------------------
- // AES
- //----------------------------------------------------------------
- wire enable_aes = (addr_core_num == CORE_ADDR_AES);
- wire [31: 0] read_data_aes;
- wire error_aes;
-
- aes aes_inst
- (
- .clk(sys_clk),
- .reset_n(sys_rst_n),
-
- .cs(enable_aes & (sys_eim_rd | sys_eim_wr)),
- .we(sys_eim_wr),
-
- .address(addr_core_reg),
- .write_data(sys_write_data),
- .read_data(read_data_aes),
- .error(error_aes)
- );
-
- reg [31: 0] read_data_aes_reg;
- always @(posedge sys_clk)
- read_data_aes_reg <= read_data_aes;
-
-
- //----------------------------------------------------------------
- // TRNG
- //----------------------------------------------------------------
- wire enable_trng = (addr_core_num >= CORE_ADDR_TRNG) && (addr_core_num <= CORE_ADDR_TRNG + 9'h0f);
- wire [31: 0] read_data_trng;
- wire error_trng;
- wire [3:0] trng_prefix = addr_core_num[3:0] - CORE_ADDR_TRNG;
-
- trng trng_inst
- (
- .clk(sys_clk),
- .reset_n(sys_rst_n),
-
- .cs(enable_trng & (sys_eim_rd | sys_eim_wr)),
- .we(sys_eim_wr),
-
- .address({trng_prefix, addr_core_reg}),
- .write_data(sys_write_data),
- .read_data(read_data_trng),
- .error(error_trng),
-
- .avalanche_noise(noise),
- .debug(debug)
- );
-
- reg [31: 0] read_data_trng_reg;
- always @(posedge sys_clk)
- read_data_trng_reg <= read_data_trng;
-
-
- //----------------------------------------------------------------
- // MODEXPS6
- //----------------------------------------------------------------
- wire enable_modexps6 = (addr_core_num >= CORE_ADDR_MODEXPS6) && (addr_core_num <= CORE_ADDR_MODEXPS6 + 9'h03);
- wire [31: 0] read_data_modexps6;
- wire [1:0] modexps6_prefix = addr_core_num[1:0] - CORE_ADDR_MODEXPS6;
-
- modexps6_wrapper modexps6_inst
- (
- .clk(sys_clk),
- .reset_n(sys_rst_n),
-
- .cs(enable_modexps6 & (sys_eim_rd | sys_eim_wr)),
- .we(sys_eim_wr),
-
- .address({modexps6_prefix, addr_core_reg}),
- .write_data(sys_write_data),
- .read_data(read_data_modexps6)
- );
-
-
-
- //----------------------------------------------------------------
- // Output (Read Data) Multiplexer
- //----------------------------------------------------------------
- reg [31: 0] sys_read_data_mux;
- assign sys_read_data = sys_read_data_mux;
- reg sys_error_mux;
- assign sys_error = sys_error_mux;
-
- always @*
-
- case (addr_core_num)
- CORE_ADDR_BOARD_REGS:
- begin
- sys_read_data_mux = read_data_board_regs_reg;
- sys_error_mux = error_board_regs;
- end
- CORE_ADDR_COMM_REGS:
- begin
- sys_read_data_mux = read_data_comm_regs_reg;
- sys_error_mux = error_comm_regs;
- end
- CORE_ADDR_SHA256:
- begin
- sys_read_data_mux = read_data_sha256_reg;
- sys_error_mux = error_sha256;
- end
- CORE_ADDR_AES:
- begin
- sys_read_data_mux = read_data_aes_reg;
- sys_error_mux = error_aes;
- end
- CORE_ADDR_TRNG:
- begin
- sys_read_data_mux = read_data_trng_reg;
- sys_error_mux = error_trng;
- end
- CORE_ADDR_AVALANCHE_ENTROPY:
- begin
- sys_read_data_mux = read_data_trng_reg;
- sys_error_mux = error_trng;
- end
- CORE_ADDR_ROSC_ENTROPY:
- begin
- sys_read_data_mux = read_data_trng_reg;
- sys_error_mux = error_trng;
- end
- CORE_ADDR_TRNG_MIXER:
- begin
- sys_read_data_mux = read_data_trng_reg;
- sys_error_mux = error_trng;
- end
- CORE_ADDR_TRNG_CSPRNG:
- begin
- sys_read_data_mux = read_data_trng_reg;
- sys_error_mux = error_trng;
- end
- CORE_ADDR_MODEXPS6 + 0,
- CORE_ADDR_MODEXPS6 + 1,
- CORE_ADDR_MODEXPS6 + 2,
- CORE_ADDR_MODEXPS6 + 3:
- begin
- sys_read_data_mux = read_data_modexps6;
- sys_error_mux = 0;
- end
-
- default:
- begin
- sys_read_data_mux = {32{1'b0}};
- sys_error_mux = 1;
- end
- endcase
-
-
-endmodule
-
-
-//======================================================================
-// EOF core_selector.v
-//======================================================================
diff --git a/config/core_vfiles.mk b/config/core_vfiles.mk
deleted file mode 100644
index 4020234..0000000
--- a/config/core_vfiles.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# NOTE: This file is generated; do not edit by hand.
-
-vfiles += \
- $(CORE_TREE)/hash/sha256/src/rtl/sha256.v \
- $(CORE_TREE)/hash/sha256/src/rtl/sha256_core.v \
- $(CORE_TREE)/hash/sha256/src/rtl/sha256_k_constants.v \
- $(CORE_TREE)/hash/sha256/src/rtl/sha256_w_mem.v \
- $(CORE_TREE)/cipher/aes/src/rtl/aes.v \
- $(CORE_TREE)/cipher/aes/src/rtl/aes_core.v \
- $(CORE_TREE)/cipher/aes/src/rtl/aes_decipher_block.v \
- $(CORE_TREE)/cipher/aes/src/rtl/aes_encipher_block.v \
- $(CORE_TREE)/cipher/aes/src/rtl/aes_inv_sbox.v \
- $(CORE_TREE)/cipher/aes/src/rtl/aes_key_mem.v \
- $(CORE_TREE)/cipher/aes/src/rtl/aes_sbox.v \
- $(CORE_TREE)/rng/avalanche_entropy/src/rtl/avalanche_entropy.v \
- $(CORE_TREE)/rng/avalanche_entropy/src/rtl/avalanche_entropy_core.v \
- $(CORE_TREE)/rng/rosc_entropy/src/rtl/rosc.v \
- $(CORE_TREE)/rng/rosc_entropy/src/rtl/rosc_entropy.v \
- $(CORE_TREE)/rng/rosc_entropy/src/rtl/rosc_entropy_core.v \
- $(CORE_TREE)/rng/trng/src/rtl/trng.v \
- $(CORE_TREE)/rng/trng/src/rtl/trng_csprng.v \
- $(CORE_TREE)/rng/trng/src/rtl/trng_csprng_fifo.v \
- $(CORE_TREE)/rng/trng/src/rtl/trng_mixer.v \
- $(CORE_TREE)/cipher/chacha/src/rtl/chacha.v \
- $(CORE_TREE)/cipher/chacha/src/rtl/chacha_core.v \
- $(CORE_TREE)/cipher/chacha/src/rtl/chacha_qr.v \
- $(CORE_TREE)/hash/sha512/src/rtl/sha512.v \
- $(CORE_TREE)/hash/sha512/src/rtl/sha512_core.v \
- $(CORE_TREE)/hash/sha512/src/rtl/sha512_h_constants.v \
- $(CORE_TREE)/hash/sha512/src/rtl/sha512_k_constants.v \
- $(CORE_TREE)/hash/sha512/src/rtl/sha512_w_mem.v \
- $(CORE_TREE)/math/modexps6/src/rtl/modexps6_adder64_carry32.v \
- $(CORE_TREE)/math/modexps6/src/rtl/modexps6_buffer_core.v \
- $(CORE_TREE)/math/modexps6/src/rtl/modexps6_buffer_user.v \
- $(CORE_TREE)/math/modexps6/src/rtl/modexps6_modinv32.v \
- $(CORE_TREE)/math/modexps6/src/rtl/modexps6_montgomery_coeff.v \
- $(CORE_TREE)/math/modexps6/src/rtl/modexps6_montgomery_multiplier.v \
- $(CORE_TREE)/math/modexps6/src/rtl/modexps6_top.v \
- $(CORE_TREE)/math/modexps6/src/rtl/modexps6_wrapper.v \
- $(CORE_TREE)/math/modexps6/src/rtl/ram_1rw_1ro_readfirst.v \
- $(CORE_TREE)/math/modexps6/src/rtl/ipcore/multiplier_s6.v \
- $(CORE_TREE)/math/modexps6/src/rtl/ipcore/subtractor_s6.v