From f141a79d805acbab07876d9f007e8809603718b5 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Wed, 10 Jun 2015 12:30:58 -0400 Subject: generate core_selector, probe FPGA for cores at software startup --- config/config.cfg | 19 ++++ config/config.py | 212 +++++++++++++++++++++++++++++++++++++++++ config/core_selector.v | 250 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 481 insertions(+) create mode 100644 config/config.cfg create mode 100755 config/config.py create mode 100644 config/core_selector.v (limited to 'config') diff --git a/config/config.cfg b/config/config.cfg new file mode 100644 index 0000000..360988e --- /dev/null +++ b/config/config.cfg @@ -0,0 +1,19 @@ +# Config file for the Cryptech Novena FPGA framework. + +[default] +default = rsa + +[hash-only] +cores = sha1, sha256, sha512 + +[trng-only] +cores = trng + +[modexp-only] +cores = modexp + +[rsa] +cores = sha256, aes, trng, modexp + +[multi-test] +cores = sha256, aes, aes, chacha, aes diff --git a/config/config.py b/config/config.py new file mode 100755 index 0000000..86c8615 --- /dev/null +++ b/config/config.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python +# +# Generate core_selector.v for a set of cores + +import argparse +import re +import sys +if sys.version > '3': + import configparser +else: + import ConfigParser as configparser + +# defaults +config = 'config.cfg' +outfile = 'core_selector.v' +section = '' +cores = [] + +# added cores for TRNG, muxed through trng.v +trng_cores = ['avalanche_entropy', 'rosc_entropy', 'trng_mixer', 'trng_csprng'] + +# parse the command line +def cmdParse(): + global config, outfile, section, cores + + parser = argparse.ArgumentParser() + parser.add_argument('--cores', help='comma-delimited list of cores') + parser.add_argument('-c', '--config', default=config, + help='config file (default "%s")' % config) + parser.add_argument('-s', '--section', help='config file section') + parser.add_argument('-o', '--outfile', + help='output file (default "%s")' % outfile) + args = parser.parse_args() + + if args.cores: + cores = re.split(',\s*', args.cores) + if args.config: + config = args.config + if args.outfile: + outfile = args.outfile + if args.section: + section = args.section + +# parse the config file +def configParse(section): + cfg = configparser.ConfigParser() + try: + with open(config, 'r') as f: + cfg.readfp(f) + except (IOError, configparser.MissingSectionHeaderError) as e: + print e + exit(1); + + try: + if not section: + section = cfg.get('default', 'default') + cores = cfg.get(section, 'cores') + except (configparser.NoSectionError, configparser.NoOptionError) as e: + print e + exit(1); + + return re.split(r',\s*', cores) + +# create an entry in the Core Address Table +def createAddr(core, corenum): + return " localparam CORE_ADDR_{:21s} = 9'h{:02x};\n".format(core.upper(), corenum) + +# create an instantiation of the core +# This is complicated because TRNG is a mux for 5 cores. +def createInstance(core): + core_stripped = re.sub('_\d+$', '', core) + if core_stripped == 'trng': + s3 = "(addr_core_num >= CORE_ADDR_TRNG) && (addr_core_num <= CORE_ADDR_TRNG_CSPRNG)" + s4 = " wire [3:0] trng_prefix = addr_core_num[3:0] - CORE_ADDR_TRNG;\n" + s5 = "{trng_prefix, addr_core_reg}" + s6 = ",\n\n .avalanche_noise(noise),\n .debug(debug)" + else: + s3 = "(addr_core_num == CORE_ADDR_{0})".format(core.upper()) + s4 = "" + s5 = "addr_core_reg" + s6 = "" + + return "\ + //----------------------------------------------------------------\n\ + // {1}\n\ + //----------------------------------------------------------------\n\ + wire enable_{0} = {3};\n\ + wire [31: 0] read_data_{0};\n\ + wire error_{0};\n\ +{4}\n\ + {2} {0}_inst\n\ + (\n\ + .clk(sys_clk),\n\ + .reset_n(~sys_rst),\n\ +\n\ + .cs(enable_{0} & (sys_eim_rd | sys_eim_wr)),\n\ + .we(sys_eim_wr),\n\ +\n\ + .address({5}),\n\ + .write_data(sys_write_data),\n\ + .read_data(read_data_{0}){6}\n\ + );\n\n\n".format(core, core.upper(), core_stripped, s3, s4, s5, s6) + +# create an entry in the Output (Read Data) Multiplexer +def createMux(core, core0): + return "\ + CORE_ADDR_{0}:\n\ + begin\n\ + sys_read_data_mux = read_data_{1};\n\ + sys_error_mux = error_{1};\n\ + end\n".format(core.upper(), core0) + +# create the core_selector module +def createModule(cores): + cores = ['board_regs', 'comm_regs'] + cores + + # if multiple instances of a core, number them + for a in set([x for x in cores if cores.count(x) > 1]): + i = 0 + j = 0 + while (1): + try: + j = cores.index(a, j) + except ValueError: + break + cores[j] += '_' + str(i) + i += 1 + j += 1 + + addrs = "" + insts = "" + muxs = "" + corenum = 0 + for core in cores: + addrs += createAddr(core, corenum) + insts += createInstance(core) + muxs += createMux(core, core) + corenum += 1 + if core == 'trng': + for tcore in trng_cores: + addrs += createAddr(tcore, corenum) + muxs += createMux(tcore, core) + corenum += 1 + + # write the boilerplate and all per-core bits + with open(outfile, 'w') as f: + f.write("\ +// NOTE: This file is generated; do not edit by hand.\n\ +\n\ +module core_selector\n\ + (\n\ + input wire sys_clk,\n\ + input wire sys_rst,\n\ +\n\ + input wire [16: 0] sys_eim_addr,\n\ + input wire sys_eim_wr,\n\ + input wire sys_eim_rd,\n\ + output wire [31: 0] sys_read_data,\n\ + input wire [31: 0] sys_write_data,\n\ + output wire sys_error,\n\ +\n\ + input wire noise,\n\ + output wire [7 : 0] debug\n\ + );\n\ +\n\ +\n\ + //----------------------------------------------------------------\n\ + // Address Decoder\n\ + //----------------------------------------------------------------\n\ + // upper 9 bits specify core being addressed\n\ + wire [ 8: 0] addr_core_num = sys_eim_addr[16: 8];\n\ + // lower 8 bits specify register offset in core\n\ + wire [ 7: 0] addr_core_reg = sys_eim_addr[ 7: 0];\n\ +\n\n\ + //----------------------------------------------------------------\n\ + // Core Address Table\n\ + //----------------------------------------------------------------\n\ +{0}\n\ +\n\ +{1}\n\ + //----------------------------------------------------------------\n\ + // Output (Read Data) Multiplexer\n\ + //----------------------------------------------------------------\n\ + reg [31: 0] sys_read_data_mux;\n\ + assign sys_read_data = sys_read_data_mux;\n\ + reg sys_error_mux;\n\ + assign sys_error = sys_error_mux;\n\ +\n\ + always @*\n\ +\n\ + case (addr_core_num)\n\ +{2}\n\ + default:\n\ + begin\n\ + sys_read_data_mux = {{32{{1'b0}}}};\n\ + sys_error_mux = 1;\n\ + end\n\ + endcase\n\ +\n\ +\n\ +endmodule\n\ +\n\ +\n\ +//======================================================================\n\ +// EOF core_selector.v\n\ +//======================================================================\n".format(addrs, insts, muxs)) + +# main +cmdParse() +if not cores: + cores = configParse(section) +createModule(cores) diff --git a/config/core_selector.v b/config/core_selector.v new file mode 100644 index 0000000..4debd60 --- /dev/null +++ b/config/core_selector.v @@ -0,0 +1,250 @@ +// NOTE: This file is generated; do not edit by hand. + +module core_selector + ( + input wire sys_clk, + input wire sys_rst, + + input wire [16: 0] sys_eim_addr, + input wire sys_eim_wr, + input wire sys_eim_rd, + output wire [31: 0] sys_read_data, + input wire [31: 0] sys_write_data, + 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_MODEXP = 9'h09; + + + //---------------------------------------------------------------- + // 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), + + .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) + ); + + + //---------------------------------------------------------------- + // 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), + + .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) + ); + + + //---------------------------------------------------------------- + // 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), + + .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) + ); + + + //---------------------------------------------------------------- + // 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), + + .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) + ); + + + //---------------------------------------------------------------- + // TRNG + //---------------------------------------------------------------- + wire enable_trng = (addr_core_num >= CORE_ADDR_TRNG) && (addr_core_num <= CORE_ADDR_TRNG_CSPRNG); + 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), + + .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), + + .avalanche_noise(noise), + .debug(debug) + ); + + + //---------------------------------------------------------------- + // MODEXP + //---------------------------------------------------------------- + wire enable_modexp = (addr_core_num == CORE_ADDR_MODEXP); + wire [31: 0] read_data_modexp; + wire error_modexp; + + modexp modexp_inst + ( + .clk(sys_clk), + .reset_n(~sys_rst), + + .cs(enable_modexp & (sys_eim_rd | sys_eim_wr)), + .we(sys_eim_wr), + + .address(addr_core_reg), + .write_data(sys_write_data), + .read_data(read_data_modexp) + ); + + + + //---------------------------------------------------------------- + // 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; + sys_error_mux = error_board_regs; + end + CORE_ADDR_COMM_REGS: + begin + sys_read_data_mux = read_data_comm_regs; + sys_error_mux = error_comm_regs; + end + CORE_ADDR_SHA256: + begin + sys_read_data_mux = read_data_sha256; + sys_error_mux = error_sha256; + end + CORE_ADDR_AES: + begin + sys_read_data_mux = read_data_aes; + sys_error_mux = error_aes; + end + CORE_ADDR_TRNG: + begin + sys_read_data_mux = read_data_trng; + sys_error_mux = error_trng; + end + CORE_ADDR_AVALANCHE_ENTROPY: + begin + sys_read_data_mux = read_data_trng; + sys_error_mux = error_trng; + end + CORE_ADDR_ROSC_ENTROPY: + begin + sys_read_data_mux = read_data_trng; + sys_error_mux = error_trng; + end + CORE_ADDR_TRNG_MIXER: + begin + sys_read_data_mux = read_data_trng; + sys_error_mux = error_trng; + end + CORE_ADDR_TRNG_CSPRNG: + begin + sys_read_data_mux = read_data_trng; + sys_error_mux = error_trng; + end + CORE_ADDR_MODEXP: + begin + sys_read_data_mux = read_data_modexp; + sys_error_mux = error_modexp; + end + + default: + begin + sys_read_data_mux = {32{1'b0}}; + sys_error_mux = 1; + end + endcase + + +endmodule + + +//====================================================================== +// EOF core_selector.v +//====================================================================== -- cgit v1.2.3 From 026fc461d9791bc360036f1269d0f6d61c45d179 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Wed, 23 Sep 2015 16:31:28 -0400 Subject: Trailing whitespace cleanup. --- config/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index 86c8615..bdbda1a 100755 --- a/config/config.py +++ b/config/config.py @@ -79,7 +79,7 @@ def createInstance(core): s4 = "" s5 = "addr_core_reg" s6 = "" - + return "\ //----------------------------------------------------------------\n\ // {1}\n\ @@ -126,7 +126,7 @@ def createModule(cores): cores[j] += '_' + str(i) i += 1 j += 1 - + addrs = "" insts = "" muxs = "" -- cgit v1.2.3 From a8730df1d75d06193335c65b9c9e92c3573ff93d Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Thu, 24 Sep 2015 22:23:30 -0400 Subject: Convert to something a bit more object-oriented, to simplify adding additional methods for things like .h and .mk files. --- config/config.py | 437 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 239 insertions(+), 198 deletions(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index bdbda1a..29179e4 100755 --- a/config/config.py +++ b/config/config.py @@ -4,209 +4,250 @@ import argparse import re -import sys -if sys.version > '3': - import configparser -else: - import ConfigParser as configparser - -# defaults -config = 'config.cfg' -outfile = 'core_selector.v' -section = '' -cores = [] - -# added cores for TRNG, muxed through trng.v -trng_cores = ['avalanche_entropy', 'rosc_entropy', 'trng_mixer', 'trng_csprng'] - -# parse the command line -def cmdParse(): - global config, outfile, section, cores +import ConfigParser +def main(): parser = argparse.ArgumentParser() - parser.add_argument('--cores', help='comma-delimited list of cores') - parser.add_argument('-c', '--config', default=config, - help='config file (default "%s")' % config) - parser.add_argument('-s', '--section', help='config file section') - parser.add_argument('-o', '--outfile', - help='output file (default "%s")' % outfile) + parser.add_argument("--cores", help = "comma-delimited list of cores") + parser.add_argument("-c", "--config", default = "config.cfg", help = "config file") + parser.add_argument("-s", "--section", help = "config file section") + parser.add_argument("-o", "--outfile", default = "core_selector.v", help = "output file") args = parser.parse_args() - if args.cores: - cores = re.split(',\s*', args.cores) - if args.config: - config = args.config - if args.outfile: - outfile = args.outfile - if args.section: - section = args.section - -# parse the config file -def configParse(section): - cfg = configparser.ConfigParser() - try: - with open(config, 'r') as f: - cfg.readfp(f) - except (IOError, configparser.MissingSectionHeaderError) as e: - print e - exit(1); - - try: - if not section: - section = cfg.get('default', 'default') - cores = cfg.get(section, 'cores') - except (configparser.NoSectionError, configparser.NoOptionError) as e: - print e - exit(1); - - return re.split(r',\s*', cores) - -# create an entry in the Core Address Table -def createAddr(core, corenum): - return " localparam CORE_ADDR_{:21s} = 9'h{:02x};\n".format(core.upper(), corenum) - -# create an instantiation of the core -# This is complicated because TRNG is a mux for 5 cores. -def createInstance(core): - core_stripped = re.sub('_\d+$', '', core) - if core_stripped == 'trng': - s3 = "(addr_core_num >= CORE_ADDR_TRNG) && (addr_core_num <= CORE_ADDR_TRNG_CSPRNG)" - s4 = " wire [3:0] trng_prefix = addr_core_num[3:0] - CORE_ADDR_TRNG;\n" - s5 = "{trng_prefix, addr_core_reg}" - s6 = ",\n\n .avalanche_noise(noise),\n .debug(debug)" - else: - s3 = "(addr_core_num == CORE_ADDR_{0})".format(core.upper()) - s4 = "" - s5 = "addr_core_reg" - s6 = "" - - return "\ - //----------------------------------------------------------------\n\ - // {1}\n\ - //----------------------------------------------------------------\n\ - wire enable_{0} = {3};\n\ - wire [31: 0] read_data_{0};\n\ - wire error_{0};\n\ -{4}\n\ - {2} {0}_inst\n\ - (\n\ - .clk(sys_clk),\n\ - .reset_n(~sys_rst),\n\ -\n\ - .cs(enable_{0} & (sys_eim_rd | sys_eim_wr)),\n\ - .we(sys_eim_wr),\n\ -\n\ - .address({5}),\n\ - .write_data(sys_write_data),\n\ - .read_data(read_data_{0}){6}\n\ - );\n\n\n".format(core, core.upper(), core_stripped, s3, s4, s5, s6) - -# create an entry in the Output (Read Data) Multiplexer -def createMux(core, core0): - return "\ - CORE_ADDR_{0}:\n\ - begin\n\ - sys_read_data_mux = read_data_{1};\n\ - sys_error_mux = error_{1};\n\ - end\n".format(core.upper(), core0) - -# create the core_selector module -def createModule(cores): - cores = ['board_regs', 'comm_regs'] + cores - - # if multiple instances of a core, number them - for a in set([x for x in cores if cores.count(x) > 1]): - i = 0 - j = 0 - while (1): + cores = args.cores + + if not cores: try: - j = cores.index(a, j) - except ValueError: - break - cores[j] += '_' + str(i) - i += 1 - j += 1 - - addrs = "" - insts = "" - muxs = "" - corenum = 0 + cfg = ConfigParser.RawConfigParser() + with open(args.config, "r") as f: + cfg.readfp(f) + section = args.section or cfg.get("default", "default") + cores = cfg.get(section, "cores") + except (IOError, ConfigParser.MissingSectionHeaderError,ConfigParser.NoSectionError, configparser.NoOptionError) as e: + exit(str(e)) + + cores = re.split(r",\s*", cores) + + cores = [Core.new(core) for core in ["board_regs", "comm_regs"] + cores] + core_number = 0 for core in cores: - addrs += createAddr(core, corenum) - insts += createInstance(core) - muxs += createMux(core, core) - corenum += 1 - if core == 'trng': - for tcore in trng_cores: - addrs += createAddr(tcore, corenum) - muxs += createMux(tcore, core) - corenum += 1 - - # write the boilerplate and all per-core bits - with open(outfile, 'w') as f: - f.write("\ -// NOTE: This file is generated; do not edit by hand.\n\ -\n\ -module core_selector\n\ - (\n\ - input wire sys_clk,\n\ - input wire sys_rst,\n\ -\n\ - input wire [16: 0] sys_eim_addr,\n\ - input wire sys_eim_wr,\n\ - input wire sys_eim_rd,\n\ - output wire [31: 0] sys_read_data,\n\ - input wire [31: 0] sys_write_data,\n\ - output wire sys_error,\n\ -\n\ - input wire noise,\n\ - output wire [7 : 0] debug\n\ - );\n\ -\n\ -\n\ - //----------------------------------------------------------------\n\ - // Address Decoder\n\ - //----------------------------------------------------------------\n\ - // upper 9 bits specify core being addressed\n\ - wire [ 8: 0] addr_core_num = sys_eim_addr[16: 8];\n\ - // lower 8 bits specify register offset in core\n\ - wire [ 7: 0] addr_core_reg = sys_eim_addr[ 7: 0];\n\ -\n\n\ - //----------------------------------------------------------------\n\ - // Core Address Table\n\ - //----------------------------------------------------------------\n\ -{0}\n\ -\n\ -{1}\n\ - //----------------------------------------------------------------\n\ - // Output (Read Data) Multiplexer\n\ - //----------------------------------------------------------------\n\ - reg [31: 0] sys_read_data_mux;\n\ - assign sys_read_data = sys_read_data_mux;\n\ - reg sys_error_mux;\n\ - assign sys_error = sys_error_mux;\n\ -\n\ - always @*\n\ -\n\ - case (addr_core_num)\n\ -{2}\n\ - default:\n\ - begin\n\ - sys_read_data_mux = {{32{{1'b0}}}};\n\ - sys_error_mux = 1;\n\ - end\n\ - endcase\n\ -\n\ -\n\ -endmodule\n\ -\n\ -\n\ -//======================================================================\n\ -// EOF core_selector.v\n\ -//======================================================================\n".format(addrs, insts, muxs)) + core_number = core.assign_core_number(core_number) + + with open(args.outfile, "w") as f: + f.write(createModule_template.format( + addrs = "".join(core.createAddr() for core in cores), + insts = "".join(core.createInstance() for core in cores), + muxes = "".join(core.createMux() for core in cores))) + + +class Core(object): + + _instance_count = {} + special_class = {} + + def __init__(self, name): + self.name = name + self.core_number = None + 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) + + def assign_core_number(self, n): + self.core_number = n + return n + 1 + + @property + def instance_name(self): + if self._instance_count[self.name] > 1: + return "{}_{}".format(self.name, self.instance_number) + else: + return self.name + + @property + def upper_instance_name(self): + return self.instance_name.upper() + + @property + def createInstance_template(self): + return createInstance_template_generic + + def createInstance(self): + return self.createInstance_template.format(core = self) + + def createAddr(self): + return createAddr_template.format(core = self) + + def createMux(self): + return createMux_template.format(core = self, core0 = self) + + +class SubCore(Core): + + def __init__(self, name, parent): + super(SubCore, self).__init__(name) + self.parent = parent + + def createMux(self): + return createMux_template.format(core = self, core0 = self.parent) + + +class TRNGCore(Core): + + def __init__(self, name): + super(TRNGCore, self).__init__(name) + self.subcores = tuple(SubCore(name, self) for name in ("avalanche_entropy", "rosc_entropy", "trng_mixer", "trng_csprng")) + + def assign_core_number(self, n): + n = super(TRNGCore, self).assign_core_number(n) + for subcore in self.subcores: + n = subcore.assign_core_number(n) + return n + + @property + def createInstance_template(self): + return createInstance_template_TRNG + + 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) + +Core.special_class["trng"] = TRNGCore + + +createAddr_template = """\ + localparam CORE_ADDR_{core.upper_instance_name:21s} = 9'h{core.core_number:02x}; +""" + +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}; + + {core.name} {core.instance_name}_inst + ( + .clk(sys_clk), + .reset_n(~sys_rst), + + .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}) + ); + + +""" + +createInstance_template_TRNG = """\ + //---------------------------------------------------------------- + // {core.upper_instance_name} + //---------------------------------------------------------------- + wire enable_{core.instance_name} = (addr_core_num >= CORE_ADDR_TRNG) && (addr_core_num <= CORE_ADDR_TRNG_CSPRNG); + wire [31: 0] read_data_{core.instance_name}; + wire error_{core.instance_name}; + wire [3:0] trng_prefix = addr_core_num[3:0] - CORE_ADDR_TRNG; + + {core.name} {core.instance_name}_inst + ( + .clk(sys_clk), + .reset_n(~sys_rst), + + .cs(enable_{core.instance_name} & (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_{core.instance_name}), + + .avalanche_noise(noise), + .debug(debug) + ); + + +""" + +createMux_template = """\ + CORE_ADDR_{core.upper_instance_name}: + begin + sys_read_data_mux = read_data_{core0.instance_name}; + sys_error_mux = error_{core0.instance_name}; + end +""" + +createModule_template = """\ +// NOTE: This file is generated; do not edit by hand. + +module core_selector + ( + input wire sys_clk, + input wire sys_rst, + + input wire [16: 0] sys_eim_addr, + input wire sys_eim_wr, + input wire sys_eim_rd, + output wire [31: 0] sys_read_data, + input wire [31: 0] sys_write_data, + 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 + //---------------------------------------------------------------- +{addrs} + +{insts} + //---------------------------------------------------------------- + // 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) +{muxes} + default: + begin + sys_read_data_mux = {{32{{1'b0}}}}; + sys_error_mux = 1; + end + endcase + + +endmodule + + +//====================================================================== +// EOF core_selector.v +//====================================================================== +""" # main -cmdParse() -if not cores: - cores = configParse(section) -createModule(cores) + + +if __name__ == "__main__": + main() -- cgit v1.2.3 From 0ddd4002f9cf59e72a6f2ec1645c2b4569b3ebc3 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Thu, 24 Sep 2015 23:16:50 -0400 Subject: Git rid of commas in config language, add some comments. --- config/config.cfg | 6 +-- config/config.py | 117 +++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 83 insertions(+), 40 deletions(-) (limited to 'config') diff --git a/config/config.cfg b/config/config.cfg index 360988e..65659f7 100644 --- a/config/config.cfg +++ b/config/config.cfg @@ -4,7 +4,7 @@ default = rsa [hash-only] -cores = sha1, sha256, sha512 +cores = sha1 sha256 sha512 [trng-only] cores = trng @@ -13,7 +13,7 @@ cores = trng cores = modexp [rsa] -cores = sha256, aes, trng, modexp +cores = sha256 aes trng modexp [multi-test] -cores = sha256, aes, aes, chacha, aes +cores = sha256 aes aes chacha aes diff --git a/config/config.py b/config/config.py index 29179e4..74a9007 100755 --- a/config/config.py +++ b/config/config.py @@ -1,48 +1,67 @@ #!/usr/bin/env python -# -# Generate core_selector.v for a set of cores - -import argparse -import re -import ConfigParser +""" +Generate core_selector.v for a set of cores. +""" def main(): - parser = argparse.ArgumentParser() - parser.add_argument("--cores", help = "comma-delimited list of cores") - parser.add_argument("-c", "--config", default = "config.cfg", help = "config file") + """ + Parse arguments and config file, generate core list, generate output. + """ + + from argparse import ArgumentParser, FileType, ArgumentDefaultsHelpFormatter + from ConfigParser import RawConfigParser + from sys import exit + + parser = ArgumentParser(description = __doc__, formatter_class = ArgumentDefaultsHelpFormatter) + parser.add_argument("-c", "--config", help = "config file", default = "config.cfg", type = FileType("r")) + parser.add_argument("-d", "--debug", help = "enable debugging", action = "store_true") + parser.add_argument("-o", "--outfile", help = "output file", default = "core_selector.v", type = FileType("w")) parser.add_argument("-s", "--section", help = "config file section") - parser.add_argument("-o", "--outfile", default = "core_selector.v", help = "output file") + parser.add_argument("core", help = "name(s) of core(s)", nargs = "*") args = parser.parse_args() - cores = args.cores - - if not cores: - try: - cfg = ConfigParser.RawConfigParser() - with open(args.config, "r") as f: - cfg.readfp(f) + try: + if args.core: + cores = args.core + else: + cfg = RawConfigParser() + cfg.readfp(args.config) section = args.section or cfg.get("default", "default") - cores = cfg.get(section, "cores") - except (IOError, ConfigParser.MissingSectionHeaderError,ConfigParser.NoSectionError, configparser.NoOptionError) as e: - exit(str(e)) + cores = cfg.get(section, "cores").split() - cores = re.split(r",\s*", cores) + cores.insert(0, "board_regs") + cores.insert(1, "comm_regs") - cores = [Core.new(core) for core in ["board_regs", "comm_regs"] + cores] - core_number = 0 - for core in cores: - core_number = core.assign_core_number(core_number) + cores = [Core.new(core) for core in cores] + core_number = 0 + for core in cores: + core_number = core.assign_core_number(core_number) - with open(args.outfile, "w") as f: - f.write(createModule_template.format( + args.outfile.write(createModule_template.format( addrs = "".join(core.createAddr() for core in cores), insts = "".join(core.createInstance() for core in cores), muxes = "".join(core.createMux() for core in cores))) + except Exception, e: + if args.debug: + raise + exit(str(e)) + class Core(object): + """ + Data and methods for a generic core. We can use this directly for + most cores, a few are weird and require subclassing to override + particular methods. + """ + + # Class variable tracking how many times a particular core has + # been instantiated. This controls instance numbering. _instance_count = {} + + # Map from core name to subclass for the special case cores. + special_class = {} def __init__(self, name): @@ -70,12 +89,8 @@ class Core(object): def upper_instance_name(self): return self.instance_name.upper() - @property - def createInstance_template(self): - return createInstance_template_generic - def createInstance(self): - return self.createInstance_template.format(core = self) + return createInstance_template_generic.format(core = self) def createAddr(self): return createAddr_template.format(core = self) @@ -85,6 +100,9 @@ class Core(object): class SubCore(Core): + """" + Override mux handling for TRNG's sub-cores. + """ def __init__(self, name, parent): super(SubCore, self).__init__(name) @@ -95,6 +113,12 @@ class SubCore(Core): class TRNGCore(Core): + """ + The TRNG core has an internal mux and a collection of sub-cores. + 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 + a different instance template in the hope that it is easier to read. + """ def __init__(self, name): super(TRNGCore, self).__init__(name) @@ -106,9 +130,8 @@ class TRNGCore(Core): n = subcore.assign_core_number(n) return n - @property - def createInstance_template(self): - return createInstance_template_TRNG + 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) @@ -116,13 +139,26 @@ class TRNGCore(Core): def createMux(self): return super(TRNGCore, self).createMux() + "".join(subcore.createMux() for subcore in self.subcores) +# Hook TRNGCore in as the handler for "trng" core instances. + Core.special_class["trng"] = TRNGCore +# Add other special cases here as needed. + + +# 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 +# the indentation right) when the're separate. + +# Template used by .createAddr() methods. createAddr_template = """\ localparam CORE_ADDR_{core.upper_instance_name:21s} = 9'h{core.core_number:02x}; """ +# Template used by Core.createInstance(). + createInstance_template_generic = """\ //---------------------------------------------------------------- // {core.upper_instance_name} @@ -147,6 +183,10 @@ createInstance_template_generic = """\ """ +# 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} @@ -175,6 +215,8 @@ createInstance_template_TRNG = """\ """ +# Template for .createMux() methods. + createMux_template = """\ CORE_ADDR_{core.upper_instance_name}: begin @@ -183,6 +225,8 @@ createMux_template = """\ end """ +# Top-level (createModule) template. + createModule_template = """\ // NOTE: This file is generated; do not edit by hand. @@ -246,8 +290,7 @@ endmodule //====================================================================== """ -# main - +# Run main program. if __name__ == "__main__": main() -- cgit v1.2.3 From fbaa09c3192dcbe21da694b1a35eead58f10e761 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Fri, 25 Sep 2015 14:10:47 -0400 Subject: Configure makefile vfiles list too. --- config/config.cfg | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- config/config.py | 38 +++++++++++++++++------ 2 files changed, 119 insertions(+), 10 deletions(-) (limited to 'config') diff --git a/config/config.cfg b/config/config.cfg index 65659f7..8749b55 100644 --- a/config/config.cfg +++ b/config/config.cfg @@ -1,7 +1,19 @@ # Config file for the Cryptech Novena FPGA framework. +# +# At present, there are three kinds of variables 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. [default] -default = rsa +default-section = rsa [hash-only] cores = sha1 sha256 sha512 @@ -17,3 +29,80 @@ cores = sha256 aes trng modexp [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] +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] +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] +vfiles = + math/modexp/src/rtl/adder32.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/shl32.v + math/modexp/src/rtl/shr32.v diff --git a/config/config.py b/config/config.py index 74a9007..6a5e532 100755 --- a/config/config.py +++ b/config/config.py @@ -13,34 +13,41 @@ def main(): from sys import exit parser = ArgumentParser(description = __doc__, formatter_class = ArgumentDefaultsHelpFormatter) - parser.add_argument("-c", "--config", help = "config file", default = "config.cfg", type = FileType("r")) parser.add_argument("-d", "--debug", help = "enable debugging", action = "store_true") - parser.add_argument("-o", "--outfile", help = "output file", default = "core_selector.v", type = FileType("w")) 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("core", help = "name(s) of core(s)", nargs = "*") args = parser.parse_args() try: + cfg = RawConfigParser() + cfg.readfp(args.config) + if args.core: cores = args.core else: - cfg = RawConfigParser() - cfg.readfp(args.config) - section = args.section or cfg.get("default", "default") + section = args.section or cfg.get("default", "default-section") cores = cfg.get(section, "cores").split() cores.insert(0, "board_regs") cores.insert(1, "comm_regs") - cores = [Core.new(core) for core in cores] + cores = tuple(Core.new(core) for core in cores) core_number = 0 for core in cores: core_number = core.assign_core_number(core_number) + for core in cores[2:]: + core.add_vfiles(cfg) - args.outfile.write(createModule_template.format( - addrs = "".join(core.createAddr() for core in cores), + args.verilog.write(createModule_template.format( + addrs = "".join(core.createAddr() for core in cores), insts = "".join(core.createInstance() for core in cores), - muxes = "".join(core.createMux() 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))) except Exception, e: if args.debug: @@ -67,6 +74,7 @@ class Core(object): def __init__(self, name): self.name = name self.core_number = None + self.vfiles = () self.instance_number = self._instance_count.get(name, 0) self._instance_count[name] = self.instance_number + 1 @@ -78,6 +86,10 @@ class Core(object): self.core_number = n return n + 1 + def add_vfiles(self, cfg): + if self.instance_number == 0: + self.vfiles = cfg.get(self.name, "vfiles").split() + @property def instance_name(self): if self._instance_count[self.name] > 1: @@ -98,6 +110,8 @@ class Core(object): def createMux(self): return createMux_template.format(core = self, core0 = self) + def listVfiles(self): + return "".join(" \\\n\t$(core_tree)/" + vfile for vfile in self.vfiles) class SubCore(Core): """" @@ -290,6 +304,12 @@ endmodule //====================================================================== """ +# Template for makefile snippet listing Verilog source files. + +listVfiles_template = """\ +vfiles +={vfiles} +""" + # Run main program. if __name__ == "__main__": -- cgit v1.2.3 From 44626ff57b30a5db18766022430199c7eec8cbd6 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Fri, 25 Sep 2015 18:18:30 -0400 Subject: Track filename changes to modexp core that took place ages ago. --- config/config.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'config') diff --git a/config/config.cfg b/config/config.cfg index 8749b55..5f3cf21 100644 --- a/config/config.cfg +++ b/config/config.cfg @@ -95,7 +95,7 @@ vfiles = [modexp] vfiles = - math/modexp/src/rtl/adder32.v + math/modexp/src/rtl/adder.v math/modexp/src/rtl/blockmem1r1w.v math/modexp/src/rtl/blockmem2r1wptr.v math/modexp/src/rtl/blockmem2r1w.v @@ -104,5 +104,5 @@ vfiles = math/modexp/src/rtl/modexp_core.v math/modexp/src/rtl/montprod.v math/modexp/src/rtl/residue.v - math/modexp/src/rtl/shl32.v - math/modexp/src/rtl/shr32.v + math/modexp/src/rtl/shl.v + math/modexp/src/rtl/shr.v -- cgit v1.2.3 From 9c67b22956ad8f49e71a4caef20eb246feb81ce1 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Fri, 25 Sep 2015 18:18:54 -0400 Subject: Incomplete attempt to track changes to core_selector architecture. The board_regs and comm_regs cores handle reset differently, but there's also this sys_ena wire which appeared out of the ether one day and is not yet in this movie. This version does NOT synthesize (nor did the previous ones, but now we know it...). --- config/config.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index 6a5e532..65c540f 100755 --- a/config/config.py +++ b/config/config.py @@ -126,6 +126,16 @@ class SubCore(Core): return createMux_template.format(core = self, core0 = self.parent) +class BoardCore(Core): + """ + Board-level cores have a slightly different API, which we handle + with a different template. + """ + + def createInstance(self): + return createInstance_template_board.format(core = self) + + class TRNGCore(Core): """ The TRNG core has an internal mux and a collection of sub-cores. @@ -153,11 +163,12 @@ class TRNGCore(Core): def createMux(self): return super(TRNGCore, self).createMux() + "".join(subcore.createMux() for subcore in self.subcores) -# Hook TRNGCore in as the handler for "trng" core instances. +# Hook special classes in as handlers for the cores that require them -Core.special_class["trng"] = TRNGCore - -# Add other special cases here as needed. +Core.special_class.update( + board_regs = BoardCore, + comm_regs = BoardCore, + trng = TRNGCore) # Templates (format strings), here instead of inline in the functions @@ -177,7 +188,7 @@ createInstance_template_generic = """\ //---------------------------------------------------------------- // {core.upper_instance_name} //---------------------------------------------------------------- - wire enable_{core.instance_name} = (addr_core_num == CORE_ADDR_{core.upper_instance_name}); + wire enable_{core.instance_name} = sys_ena && (addr_core_num == CORE_ADDR_{core.upper_instance_name}); wire [31: 0] read_data_{core.instance_name}; wire error_{core.instance_name}; @@ -195,11 +206,43 @@ createInstance_template_generic = """\ ); +""" + +# Template used by BoardCore.createInstance(). This has minor +# differences from the generic template, maybe we can merge them, or +# maybe we can do something about the (gratuitous?) differences that +# make this necessary. + +createInstance_template_board = """\ + //---------------------------------------------------------------- + // {core.upper_instance_name} + //---------------------------------------------------------------- + wire enable_{core.instance_name} = sys_ena && (addr_core_num == CORE_ADDR_{core.upper_instance_name}); + wire [31: 0] read_data_{core.instance_name}; + wire error_{core.instance_name}; + + {core.name} {core.instance_name}_inst + ( + .clk(sys_clk), + .rst(sys_rst), + + .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}), + .error(error_{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. +# +# Should this also be checking sys_ena? Not obvious to me either way. createInstance_template_TRNG = """\ //---------------------------------------------------------------- -- cgit v1.2.3 From d3a2b477d0411b006b7f16256d0b2765ea765a83 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Fri, 25 Sep 2015 18:45:35 -0400 Subject: Minor cleanup. --- config/config.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index 65c540f..ddf7d0b 100755 --- a/config/config.py +++ b/config/config.py @@ -111,7 +111,18 @@ class Core(object): return createMux_template.format(core = self, core0 = self) def listVfiles(self): - return "".join(" \\\n\t$(core_tree)/" + vfile for vfile in self.vfiles) + return "".join(" \\\n\t$(CORE_TREE)/" + vfile for vfile in self.vfiles) + + +class BoardCore(Core): + """ + Board-level cores have a slightly different API, which we handle + with a different template, at least for now. + """ + + def createInstance(self): + return createInstance_template_board.format(core = self) + class SubCore(Core): """" @@ -126,16 +137,6 @@ class SubCore(Core): return createMux_template.format(core = self, core0 = self.parent) -class BoardCore(Core): - """ - Board-level cores have a slightly different API, which we handle - with a different template. - """ - - def createInstance(self): - return createInstance_template_board.format(core = self) - - class TRNGCore(Core): """ The TRNG core has an internal mux and a collection of sub-cores. @@ -144,9 +145,11 @@ class TRNGCore(Core): a different instance template in the hope that it is easier to read. """ + subcore_names = ("avalanche_entropy", "rosc_entropy", "trng_mixer", "trng_csprng") + def __init__(self, name): super(TRNGCore, self).__init__(name) - self.subcores = tuple(SubCore(name, self) for name in ("avalanche_entropy", "rosc_entropy", "trng_mixer", "trng_csprng")) + self.subcores = tuple(SubCore(name, self) for name in self.subcore_names) def assign_core_number(self, n): n = super(TRNGCore, self).assign_core_number(n) -- cgit v1.2.3 From 19e4044fcf47360dcc5aa68f6eae5a62a6cdb61b Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Sat, 26 Sep 2015 13:21:01 -0400 Subject: Sorted out reset pins (I think). Seems our various core authors have different opinions about whether reset should be high or low, and the core selector code is responsible for making this right. Hmm. Address map may still be wrong, as addressing scheme seems to have changed while the core_select branch was gathering dust. --- config/config.py | 69 ++++++++++++++++++-------------------------------- config/core_selector.v | 4 +-- config/core_vfiles.mk | 34 +++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 47 deletions(-) create mode 100644 config/core_vfiles.mk (limited to 'config') diff --git a/config/config.py b/config/config.py index ddf7d0b..970b339 100755 --- a/config/config.py +++ b/config/config.py @@ -101,6 +101,10 @@ class Core(object): def upper_instance_name(self): return self.instance_name.upper() + @property + def reset_pin(self): + return ".rst(sys_rst)" + def createInstance(self): return createInstance_template_generic.format(core = self) @@ -114,14 +118,15 @@ class Core(object): return "".join(" \\\n\t$(CORE_TREE)/" + vfile for vfile in self.vfiles) -class BoardCore(Core): +class InvertedResetCore(Core): """ - Board-level cores have a slightly different API, which we handle - with a different template, at least for now. + Core which inverts the reset signal. Seems to vary by author. + No, I don't know why we don't just pick one convention or the other. """ - def createInstance(self): - return createInstance_template_board.format(core = self) + @property + def reset_pin(self): + return ".reset_n(~sys_rst)" class SubCore(Core): @@ -137,7 +142,7 @@ class SubCore(Core): return createMux_template.format(core = self, core0 = self.parent) -class TRNGCore(Core): +class TRNGCore(InvertedResetCore): """ The TRNG core has an internal mux and a collection of sub-cores. Mostly this means that our method calls have to iterate over all @@ -166,12 +171,16 @@ class TRNGCore(Core): def createMux(self): return super(TRNGCore, self).createMux() + "".join(subcore.createMux() for subcore in self.subcores) -# Hook special classes in as handlers for the cores that require them +# Hook special classes in as handlers for the cores that require them. Core.special_class.update( - board_regs = BoardCore, - comm_regs = BoardCore, - trng = TRNGCore) + trng = TRNGCore, + aes = InvertedResetCore, + chacha = InvertedResetCore, + sha1 = InvertedResetCore, + sha256 = InvertedResetCore, + sha512 = InvertedResetCore, + modexp = InvertedResetCore) # Templates (format strings), here instead of inline in the functions @@ -191,14 +200,14 @@ createInstance_template_generic = """\ //---------------------------------------------------------------- // {core.upper_instance_name} //---------------------------------------------------------------- - wire enable_{core.instance_name} = sys_ena && (addr_core_num == CORE_ADDR_{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}; {core.name} {core.instance_name}_inst ( .clk(sys_clk), - .reset_n(~sys_rst), + {core.reset_pin}, .cs(enable_{core.instance_name} & (sys_eim_rd | sys_eim_wr)), .we(sys_eim_wr), @@ -209,43 +218,11 @@ createInstance_template_generic = """\ ); -""" - -# Template used by BoardCore.createInstance(). This has minor -# differences from the generic template, maybe we can merge them, or -# maybe we can do something about the (gratuitous?) differences that -# make this necessary. - -createInstance_template_board = """\ - //---------------------------------------------------------------- - // {core.upper_instance_name} - //---------------------------------------------------------------- - wire enable_{core.instance_name} = sys_ena && (addr_core_num == CORE_ADDR_{core.upper_instance_name}); - wire [31: 0] read_data_{core.instance_name}; - wire error_{core.instance_name}; - - {core.name} {core.instance_name}_inst - ( - .clk(sys_clk), - .rst(sys_rst), - - .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}), - .error(error_{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. -# -# Should this also be checking sys_ena? Not obvious to me either way. createInstance_template_TRNG = """\ //---------------------------------------------------------------- @@ -259,7 +236,7 @@ createInstance_template_TRNG = """\ {core.name} {core.instance_name}_inst ( .clk(sys_clk), - .reset_n(~sys_rst), + {core.reset_pin}, .cs(enable_{core.instance_name} & (sys_eim_rd | sys_eim_wr)), .we(sys_eim_wr), @@ -353,6 +330,8 @@ endmodule # Template for makefile snippet listing Verilog source files. listVfiles_template = """\ +# NOTE: This file is generated; do not edit by hand. + vfiles +={vfiles} """ diff --git a/config/core_selector.v b/config/core_selector.v index 4debd60..731b494 100644 --- a/config/core_selector.v +++ b/config/core_selector.v @@ -51,7 +51,7 @@ module core_selector board_regs board_regs_inst ( .clk(sys_clk), - .reset_n(~sys_rst), + .rst(sys_rst), .cs(enable_board_regs & (sys_eim_rd | sys_eim_wr)), .we(sys_eim_wr), @@ -72,7 +72,7 @@ module core_selector comm_regs comm_regs_inst ( .clk(sys_clk), - .reset_n(~sys_rst), + .rst(sys_rst), .cs(enable_comm_regs & (sys_eim_rd | sys_eim_wr)), .we(sys_eim_wr), diff --git a/config/core_vfiles.mk b/config/core_vfiles.mk new file mode 100644 index 0000000..bd1c6d4 --- /dev/null +++ b/config/core_vfiles.mk @@ -0,0 +1,34 @@ +# 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)/math/modexp/src/rtl/adder.v \ + $(CORE_TREE)/math/modexp/src/rtl/blockmem1r1w.v \ + $(CORE_TREE)/math/modexp/src/rtl/blockmem2r1wptr.v \ + $(CORE_TREE)/math/modexp/src/rtl/blockmem2r1w.v \ + $(CORE_TREE)/math/modexp/src/rtl/blockmem2rptr1w.v \ + $(CORE_TREE)/math/modexp/src/rtl/modexp.v \ + $(CORE_TREE)/math/modexp/src/rtl/modexp_core.v \ + $(CORE_TREE)/math/modexp/src/rtl/montprod.v \ + $(CORE_TREE)/math/modexp/src/rtl/residue.v \ + $(CORE_TREE)/math/modexp/src/rtl/shl.v \ + $(CORE_TREE)/math/modexp/src/rtl/shr.v -- cgit v1.2.3 From cf8167215459811f8047f7c6d4f5972d924f6689 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Sun, 27 Sep 2015 13:17:55 -0400 Subject: Comments noting the strange history of the addressing scheme. --- config/config.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'config') diff --git a/config/config.py b/config/config.py index 970b339..4648f9d 100755 --- a/config/config.py +++ b/config/config.py @@ -3,6 +3,44 @@ Generate core_selector.v for a set of cores. """ +# History of cryptech bus addressing scheme, as best I understand it. +# +# The old old addressing scheme that Joachim and Paul came up with +# was: +# +# 3 bits of segment selector [16:14] +# 6 bits of core selector [13:8] +# 8 bits of register selector [7:0] +# +# modexp6s needed more register bits than that, so Pavel changed +# addressing within the math segment to: +# +# 3 bits of segment selector [16:14] +# 4 bits of core selector [13:10] +# 10 bits of register selector [9:0] +# +# Meanwhile, Paul eliminated segments entirely when writing the +# ancestor of this script, resulting in: +# +# 9 bits of core selector [16:8] +# 8 bits of register selector [7:0] +# +# Taking Pavel's and Paul's changes together, we want: +# +# 7 bits of core selector [16:10] +# 10 bits of register selector [9:0] +# +# Open issue: what effect does all this have on the sub-core muxing +# within trng cores? trng core plus its (currently) four sub-cores +# still takes up more than one new core slot even if trng uses the old +# scheme internally. How many slots should we allocate, and what +# addressing scheme is the trng core expecting to see? + +# Unrelated: Timing delays. Paul added extra registers to slow cores +# other than modexps6 down by one clock cycle, to compensate for the +# one cycle delay that seems to be built into the block memories that +# modexps6 uses. Templates will need to reflect that somehow. + def main(): """ Parse arguments and config file, generate core list, generate output. -- cgit v1.2.3 From 0ef997a7567156ed271f36b64e077bd75c9e1798 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Sun, 27 Sep 2015 18:58:10 -0400 Subject: Wedge modexps6 into the addressing scheme. Adjust timing of other cores. Tweak TRNG templates to support multiple instances, more for consistency than than because we really expect multiple TRNGs. --- config/config.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++--- config/core_selector.v | 44 ++++++++++++++++++++------ 2 files changed, 113 insertions(+), 15 deletions(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index 4648f9d..bf77a36 100755 --- a/config/config.py +++ b/config/config.py @@ -35,6 +35,11 @@ Generate core_selector.v for a set of cores. # still takes up more than one new core slot even if trng uses the old # scheme internally. How many slots should we allocate, and what # addressing scheme is the trng core expecting to see? +# +# So perhaps a better plan would be to keep Paul's scheme and just +# give modexps6 four core's worth of space, passing a 10 bit composite +# address constructed in much the same way as the trng template +# already does. # Unrelated: Timing delays. Paul added extra registers to slow cores # other than modexps6 down by one clock cycle, to compensate for the @@ -200,6 +205,10 @@ class TRNGCore(InvertedResetCore): n = subcore.assign_core_number(n) return n + @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) @@ -209,6 +218,20 @@ class TRNGCore(InvertedResetCore): def createMux(self): return super(TRNGCore, self).createMux() + "".join(subcore.createMux() for subcore in self.subcores) + +class ModExpS6Core(Core): + + 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) + + # Hook special classes in as handlers for the cores that require them. Core.special_class.update( @@ -218,7 +241,8 @@ Core.special_class.update( sha1 = InvertedResetCore, sha256 = InvertedResetCore, sha512 = InvertedResetCore, - modexp = InvertedResetCore) + modexp = InvertedResetCore, + modexps6 = ModExpS6Core) # Templates (format strings), here instead of inline in the functions @@ -255,6 +279,38 @@ createInstance_template_generic = """\ .read_data(read_data_{core.instance_name}) ); + reg [31: 0] read_data_{core.instance_name}_reg; + always @(posedge sys_clk) + read_data_{core.instance_name}_reg <= read_data_{core.instance_name}; + + +""" + +# Template used by ModExpS6Core.createInstance(). This is different +# enough from the base template that it's easier to make this separate. + +createInstance_template_ModExpS6 = """\ + //---------------------------------------------------------------- + // {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} + 3); + wire [31: 0] read_data_{core.instance_name}; + wire error_{core.instance_name}; + wire [1:0] {core.instance_name}_prefix = addr_core_num[1: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}) + ); + """ @@ -266,10 +322,10 @@ createInstance_template_TRNG = """\ //---------------------------------------------------------------- // {core.upper_instance_name} //---------------------------------------------------------------- - wire enable_{core.instance_name} = (addr_core_num >= CORE_ADDR_TRNG) && (addr_core_num <= CORE_ADDR_TRNG_CSPRNG); + wire enable_{core.instance_name} = (addr_core_num >= CORE_ADDR_{core.upper_instance_name}) && (addr_core_num <= CORE_ADDR_{core.last_subcore_upper_instance_name}); wire [31: 0] read_data_{core.instance_name}; wire error_{core.instance_name}; - wire [3:0] trng_prefix = addr_core_num[3:0] - CORE_ADDR_TRNG; + wire [3:0] {core.instance_name}_prefix = addr_core_num[3:0] - CORE_ADDR_{core.upper_instance_name}; {core.name} {core.instance_name}_inst ( @@ -279,7 +335,7 @@ createInstance_template_TRNG = """\ .cs(enable_{core.instance_name} & (sys_eim_rd | sys_eim_wr)), .we(sys_eim_wr), - .address({{trng_prefix, addr_core_reg}}), + .address({{{core.instance_name}_prefix, addr_core_reg}}), .write_data(sys_write_data), .read_data(read_data_{core.instance_name}), @@ -287,6 +343,10 @@ createInstance_template_TRNG = """\ .debug(debug) ); + reg [31: 0] read_data_{core.instance_name}_reg; + always @(posedge sys_clk) + read_data_{core.instance_name}_reg <= read_data_{core.instance_name}; + """ @@ -295,11 +355,25 @@ createInstance_template_TRNG = """\ createMux_template = """\ CORE_ADDR_{core.upper_instance_name}: begin - sys_read_data_mux = read_data_{core0.instance_name}; + sys_read_data_mux = read_data_{core0.instance_name}_reg; sys_error_mux = error_{core0.instance_name}; 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: + begin + sys_read_data_mux = read_data_{core.instance_name}; + sys_error_mux = error_{core.instance_name}; + end +""" + + # Top-level (createModule) template. createModule_template = """\ diff --git a/config/core_selector.v b/config/core_selector.v index 731b494..16d1a09 100644 --- a/config/core_selector.v +++ b/config/core_selector.v @@ -61,6 +61,10 @@ module core_selector .read_data(read_data_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 @@ -82,6 +86,10 @@ module core_selector .read_data(read_data_comm_regs) ); + reg [31: 0] read_data_comm_regs_reg; + always @(posedge sys_clk) + read_data_comm_regs_reg <= read_data_comm_regs; + //---------------------------------------------------------------- // SHA256 @@ -103,6 +111,10 @@ module core_selector .read_data(read_data_sha256) ); + reg [31: 0] read_data_sha256_reg; + always @(posedge sys_clk) + read_data_sha256_reg <= read_data_sha256; + //---------------------------------------------------------------- // AES @@ -124,6 +136,10 @@ module core_selector .read_data(read_data_aes) ); + reg [31: 0] read_data_aes_reg; + always @(posedge sys_clk) + read_data_aes_reg <= read_data_aes; + //---------------------------------------------------------------- // TRNG @@ -149,6 +165,10 @@ module core_selector .debug(debug) ); + reg [31: 0] read_data_trng_reg; + always @(posedge sys_clk) + read_data_trng_reg <= read_data_trng; + //---------------------------------------------------------------- // MODEXP @@ -170,6 +190,10 @@ module core_selector .read_data(read_data_modexp) ); + reg [31: 0] read_data_modexp_reg; + always @(posedge sys_clk) + read_data_modexp_reg <= read_data_modexp; + //---------------------------------------------------------------- @@ -185,52 +209,52 @@ module core_selector case (addr_core_num) CORE_ADDR_BOARD_REGS: begin - sys_read_data_mux = read_data_board_regs; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + sys_read_data_mux = read_data_trng_reg; sys_error_mux = error_trng; end CORE_ADDR_MODEXP: begin - sys_read_data_mux = read_data_modexp; + sys_read_data_mux = read_data_modexp_reg; sys_error_mux = error_modexp; end -- cgit v1.2.3 From 54516bb49c631f447dbd443557fbde3285074c8a Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Sun, 27 Sep 2015 19:20:26 -0400 Subject: Add "requires" option. --- config/config.cfg | 8 +++++++- config/config.py | 4 ++++ config/core_vfiles.mk | 8 ++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'config') diff --git a/config/config.cfg b/config/config.cfg index 5f3cf21..9bb01ae 100644 --- a/config/config.cfg +++ b/config/config.cfg @@ -1,6 +1,6 @@ # Config file for the Cryptech Novena FPGA framework. # -# At present, there are three kinds of variables in this file. +# At present, there are four kinds of variables in this file: # # default-section: Name of the configuration to build if the user # doesn't specify one. Only meaningful in the default section. @@ -11,6 +11,11 @@ # 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. [default] default-section = rsa @@ -52,6 +57,7 @@ vfiles = 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 diff --git a/config/config.py b/config/config.py index bf77a36..814826f 100755 --- a/config/config.py +++ b/config/config.py @@ -132,6 +132,10 @@ class Core(object): def add_vfiles(self, cfg): if self.instance_number == 0: self.vfiles = cfg.get(self.name, "vfiles").split() + if cfg.has_option(self.name, "requires"): + for required in cfg.get(self.name, "requires").split(): + if required not in self._instance_count: + self.vfiles.extend(cfg.get(required, "vfiles").split()) @property def instance_name(self): diff --git a/config/core_vfiles.mk b/config/core_vfiles.mk index bd1c6d4..8def572 100644 --- a/config/core_vfiles.mk +++ b/config/core_vfiles.mk @@ -21,6 +21,14 @@ vfiles += \ $(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/modexp/src/rtl/adder.v \ $(CORE_TREE)/math/modexp/src/rtl/blockmem1r1w.v \ $(CORE_TREE)/math/modexp/src/rtl/blockmem2r1wptr.v \ -- cgit v1.2.3 From fdd81bb1df1df3cad091ea0076a0e6207f0e8f3d Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Sun, 27 Sep 2015 20:36:19 -0400 Subject: Comments. --- config/config.py | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index 814826f..0ec1274 100755 --- a/config/config.py +++ b/config/config.py @@ -25,26 +25,36 @@ Generate core_selector.v for a set of cores. # 9 bits of core selector [16:8] # 8 bits of register selector [7:0] # -# Taking Pavel's and Paul's changes together, we want: +# Taking Pavel's and Paul's changes together, we'd get: # # 7 bits of core selector [16:10] # 10 bits of register selector [9:0] # -# Open issue: what effect does all this have on the sub-core muxing -# within trng cores? trng core plus its (currently) four sub-cores -# still takes up more than one new core slot even if trng uses the old -# scheme internally. How many slots should we allocate, and what -# addressing scheme is the trng core expecting to see? -# -# So perhaps a better plan would be to keep Paul's scheme and just -# give modexps6 four core's worth of space, passing a 10 bit composite -# address constructed in much the same way as the trng template -# already does. +# Except that this would waste space for most cores, and make things +# very confusing for the TRNG cores. So, instead, we keep Paul's +# two-level (no segment) scheme and handle modexps6 as a set of four +# consecutive "cores" with a 10-bit composite register selector. + +# The modexps6 core also 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. -# Unrelated: Timing delays. Paul added extra registers to slow cores -# other than modexps6 down by one clock cycle, to compensate for the -# one cycle delay that seems to be built into the block memories that -# modexps6 uses. Templates will need to reflect that somehow. +# To Do: +# +# - Move reset-high/reset-low to a boolean variable in the config +# file, simplify Core classes accordingly. +# +# - Consider automating the one-clock-cycle delay stuff by adding +# another boolean flag to the config file. Default would be no +# delay, if any included core sets the "I use block memories" flag, +# 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. +# +# - Figure out whether this really belongs in the novena repository at +# all, seems more generic than that. def main(): """ @@ -224,6 +234,11 @@ class TRNGCore(InvertedResetCore): 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) @@ -237,6 +252,7 @@ class ModExpS6Core(Core): # Hook special classes in as handlers for the cores that require them. +# Moving the reset-high/reset-low logic to the config file should simplify this. Core.special_class.update( trng = TRNGCore, -- cgit v1.2.3 From 6894db11d641b37c26a0184b43dc87eb00bd36a6 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Mon, 28 Sep 2015 07:45:33 -0400 Subject: ModExpS6 top is called modexps6_wrapper, not modexps6, sigh. --- config/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index 0ec1274..2a11bd6 100755 --- a/config/config.py +++ b/config/config.py @@ -318,7 +318,7 @@ createInstance_template_ModExpS6 = """\ wire error_{core.instance_name}; wire [1:0] {core.instance_name}_prefix = addr_core_num[1:0] - CORE_ADDR_{core.upper_instance_name}; - {core.name} {core.instance_name}_inst + {core.name}_wrapper {core.instance_name}_inst ( .clk(sys_clk), {core.reset_pin}, -- cgit v1.2.3 From 438a6d8e02afdea04e30f8782d4a701e119b3703 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Mon, 28 Sep 2015 19:17:33 -0400 Subject: Handle reset high/low logic in the config file. Connect error signals. --- config/config.cfg | 1 + config/config.py | 79 ++++++++++++++++++++++++++++---------------------- config/core_selector.v | 16 ++++++---- 3 files changed, 57 insertions(+), 39 deletions(-) (limited to 'config') diff --git a/config/config.cfg b/config/config.cfg index 9bb01ae..a4120b1 100644 --- a/config/config.cfg +++ b/config/config.cfg @@ -86,6 +86,7 @@ vfiles = cipher/chacha/src/rtl/chacha_qr.v [modexps6] +reset_high = true vfiles = math/modexps6/src/rtl/modexps6_adder64_carry32.v math/modexps6/src/rtl/modexps6_buffer_core.v diff --git a/config/config.py b/config/config.py index 2a11bd6..3ae809b 100755 --- a/config/config.py +++ b/config/config.py @@ -56,14 +56,14 @@ Generate core_selector.v for a set of cores. # - Figure out whether this really belongs in the novena repository at # all, seems more generic than that. + def main(): """ Parse arguments and config file, generate core list, generate output. """ - from argparse import ArgumentParser, FileType, ArgumentDefaultsHelpFormatter - from ConfigParser import RawConfigParser - from sys import exit + from argparse import ArgumentParser, FileType, ArgumentDefaultsHelpFormatter + from sys import exit parser = ArgumentParser(description = __doc__, formatter_class = ArgumentDefaultsHelpFormatter) parser.add_argument("-d", "--debug", help = "enable debugging", action = "store_true") @@ -88,11 +88,16 @@ def main(): cores.insert(1, "comm_regs") cores = tuple(Core.new(core) for core in cores) + core_number = 0 for core in cores: core_number = core.assign_core_number(core_number) - for core in cores[2:]: - core.add_vfiles(cfg) + + cores[0].reset_high = True + cores[1].reset_high = True + + for core in cores: + core.configure(cfg) args.verilog.write(createModule_template.format( addrs = "".join(core.createAddr() for core in cores), @@ -108,6 +113,28 @@ def main(): exit(str(e)) +try: + import ConfigParser as configparser +except ImportError: + import configparser + +class RawConfigParser(configparser.RawConfigParser): + """ + RawConfigParser with a few extensions. + """ + + def getboolean(self, section, option, default = False): + if self.has_option(section, option): + return super(RawConfigParser, self).getboolean(section, option) + else: + return default + + def getvalues(self, section, option): + if self.has_option(section, option): + for value in self.get(section, option).split(): + yield value + + class Core(object): """ Data and methods for a generic core. We can use this directly for @@ -127,7 +154,8 @@ class Core(object): def __init__(self, name): self.name = name self.core_number = None - self.vfiles = () + self.vfiles = [] + self.reset_high = False self.instance_number = self._instance_count.get(name, 0) self._instance_count[name] = self.instance_number + 1 @@ -139,13 +167,13 @@ class Core(object): self.core_number = n return n + 1 - def add_vfiles(self, cfg): + def configure(self, cfg): if self.instance_number == 0: - self.vfiles = cfg.get(self.name, "vfiles").split() - if cfg.has_option(self.name, "requires"): - for required in cfg.get(self.name, "requires").split(): - if required not in self._instance_count: - self.vfiles.extend(cfg.get(required, "vfiles").split()) + self.vfiles.extend(cfg.getvalues(self.name, "vfiles")) + for required in cfg.getvalues(self.name, "requires"): + if required not in self._instance_count: + self.vfiles.extend(cfg.getvalues(required, "vfiles")) + self.reset_high = cfg.getboolean(self.name, "reset_high", self.reset_high) @property def instance_name(self): @@ -160,7 +188,7 @@ class Core(object): @property def reset_pin(self): - return ".rst(sys_rst)" + return ".rst(sys_rst)" if self.reset_high else ".reset_n(~sys_rst)" def createInstance(self): return createInstance_template_generic.format(core = self) @@ -175,17 +203,6 @@ class Core(object): return "".join(" \\\n\t$(CORE_TREE)/" + vfile for vfile in self.vfiles) -class InvertedResetCore(Core): - """ - Core which inverts the reset signal. Seems to vary by author. - No, I don't know why we don't just pick one convention or the other. - """ - - @property - def reset_pin(self): - return ".reset_n(~sys_rst)" - - class SubCore(Core): """" Override mux handling for TRNG's sub-cores. @@ -199,7 +216,7 @@ class SubCore(Core): return createMux_template.format(core = self, core0 = self.parent) -class TRNGCore(InvertedResetCore): +class TRNGCore(Core): """ The TRNG core has an internal mux and a collection of sub-cores. Mostly this means that our method calls have to iterate over all @@ -252,16 +269,9 @@ class ModExpS6Core(Core): # Hook special classes in as handlers for the cores that require them. -# Moving the reset-high/reset-low logic to the config file should simplify this. Core.special_class.update( trng = TRNGCore, - aes = InvertedResetCore, - chacha = InvertedResetCore, - sha1 = InvertedResetCore, - sha256 = InvertedResetCore, - sha512 = InvertedResetCore, - modexp = InvertedResetCore, modexps6 = ModExpS6Core) @@ -296,7 +306,8 @@ createInstance_template_generic = """\ .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_{core.instance_name}) + .read_data(read_data_{core.instance_name}), + .error(error_{core.instance_name}) ); reg [31: 0] read_data_{core.instance_name}_reg; @@ -315,7 +326,6 @@ createInstance_template_ModExpS6 = """\ //---------------------------------------------------------------- wire enable_{core.instance_name} = (addr_core_num >= CORE_ADDR_{core.upper_instance_name}) && (addr_core_num <= CORE_ADDR_{core.upper_instance_name} + 3); wire [31: 0] read_data_{core.instance_name}; - wire error_{core.instance_name}; wire [1:0] {core.instance_name}_prefix = addr_core_num[1:0] - CORE_ADDR_{core.upper_instance_name}; {core.name}_wrapper {core.instance_name}_inst @@ -358,6 +368,7 @@ createInstance_template_TRNG = """\ .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) diff --git a/config/core_selector.v b/config/core_selector.v index 16d1a09..cc7ca14 100644 --- a/config/core_selector.v +++ b/config/core_selector.v @@ -58,7 +58,8 @@ module core_selector .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_board_regs) + .read_data(read_data_board_regs), + .error(error_board_regs) ); reg [31: 0] read_data_board_regs_reg; @@ -83,7 +84,8 @@ module core_selector .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_comm_regs) + .read_data(read_data_comm_regs), + .error(error_comm_regs) ); reg [31: 0] read_data_comm_regs_reg; @@ -108,7 +110,8 @@ module core_selector .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_sha256) + .read_data(read_data_sha256), + .error(error_sha256) ); reg [31: 0] read_data_sha256_reg; @@ -133,7 +136,8 @@ module core_selector .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_aes) + .read_data(read_data_aes), + .error(error_aes) ); reg [31: 0] read_data_aes_reg; @@ -160,6 +164,7 @@ module core_selector .address({trng_prefix, addr_core_reg}), .write_data(sys_write_data), .read_data(read_data_trng), + .error(error_trng), .avalanche_noise(noise), .debug(debug) @@ -187,7 +192,8 @@ module core_selector .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_modexp) + .read_data(read_data_modexp), + .error(error_modexp) ); reg [31: 0] read_data_modexp_reg; -- cgit v1.2.3 From 28a2e6633ca414ffa58bd718ca89ec6b3ba723ef Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Mon, 28 Sep 2015 19:30:25 -0400 Subject: RawConfigParser doesn't support super(). --- config/config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index 3ae809b..57dbddc 100755 --- a/config/config.py +++ b/config/config.py @@ -125,7 +125,8 @@ class RawConfigParser(configparser.RawConfigParser): def getboolean(self, section, option, default = False): if self.has_option(section, option): - return super(RawConfigParser, self).getboolean(section, option) + # RawConfigParser is an old-stle class, super() doesn't work, feh. + return configparser.RawConfigParser.getboolean(self, section, option) else: return default -- cgit v1.2.3 From e3eb4913425d4f48967c0af8213a41d49a470e62 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Mon, 28 Sep 2015 19:36:30 -0400 Subject: ModExpS6 has no error output. --- config/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index 57dbddc..26385d0 100755 --- a/config/config.py +++ b/config/config.py @@ -401,7 +401,7 @@ createMux_modexps6_template = """\ CORE_ADDR_{core.upper_instance_name} + 3: begin sys_read_data_mux = read_data_{core.instance_name}; - sys_error_mux = error_{core.instance_name}; + sys_error_mux = 0; end """ -- cgit v1.2.3 From ff4cf7a0530218cb86a860c803e6fccdafcff385 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Mon, 28 Sep 2015 22:03:48 -0400 Subject: Comment update. --- config/config.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index 26385d0..c0c3c5e 100755 --- a/config/config.py +++ b/config/config.py @@ -1,9 +1,10 @@ #!/usr/bin/env python + """ -Generate core_selector.v for a set of cores. +Generate core_selector.v and core_vfiles.mk for a set of cores. """ -# History of cryptech bus addressing scheme, as best I understand it. +# History of Cryptech bus addressing scheme, as best I understand it. # # The old old addressing scheme that Joachim and Paul came up with # was: @@ -33,7 +34,7 @@ Generate core_selector.v for a set of cores. # Except that this would waste space for most cores, and make things # very confusing for the TRNG cores. So, instead, we keep Paul's # two-level (no segment) scheme and handle modexps6 as a set of four -# consecutive "cores" with a 10-bit composite register selector. +# contiguous "cores" with a 10-bit composite register selector. # The modexps6 core also drags in a one clock cycle delay to other # cores, to compensate for the extra clock cycle consumed by the block @@ -41,9 +42,6 @@ Generate core_selector.v for a set of cores. # To Do: # -# - Move reset-high/reset-low to a boolean variable in the config -# file, simplify Core classes accordingly. -# # - Consider automating the one-clock-cycle delay stuff by adding # another boolean flag to the config file. Default would be no # delay, if any included core sets the "I use block memories" flag, -- cgit v1.2.3 From c421ca5e30120861006a6a0ca0ba3f23b14d88ed Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Tue, 29 Sep 2015 00:04:01 -0400 Subject: Sick hacks to compensate for sparse MUX within TRNG core. --- config/config.py | 52 ++++++++++++++++++++++++++++++++++++++++++-------- config/core_selector.v | 12 ++++++------ 2 files changed, 50 insertions(+), 14 deletions(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index c0c3c5e..3cb69db 100755 --- a/config/config.py +++ b/config/config.py @@ -36,6 +36,32 @@ Generate core_selector.v and core_vfiles.mk for a set of cores. # two-level (no segment) scheme and handle modexps6 as a set of four # contiguous "cores" with a 10-bit composite register selector. +# Gah: the TRNG core's internal multiplexer doesn't allocate cores +# contiguously, there's a gap, and one just has to know what the +# offsets are. So we need to adjust for all of that. Feh. In theory +# we could hide the gap from the outside world, as it's just a matter +# of (magic) constant offsets on top of the ones we're already +# fiddling with in the core_selector mux. See +# core/rng/trng/src/rtl/trng.v for the authoritative list, but the +# magic offsets for the high 4 bits of the 12-bit TRNG address are: +# +# 0: trng +# 1: - +# 2: - +# 3: - +# 4: - +# 5: entropy1 (avalanche) +# 6: entropy2 (rosc) +# 7: - +# 8: - +# 9: - +# a: mixer +# b: csprng +# c: - +# d: - +# e: - +# f: - + # The modexps6 core also 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. @@ -217,23 +243,33 @@ class SubCore(Core): class TRNGCore(Core): """ - The TRNG core has an internal mux and a collection of sub-cores. + 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 - a different instance template in the hope that it is easier to read. + different templates, and fiddle with addresses a bit. + + Mux numbers have to be dug out of the TRNG Verilog source. """ - subcore_names = ("avalanche_entropy", "rosc_entropy", "trng_mixer", "trng_csprng") + # TRNG subcore name -> internal mux number. + subcore_parameters = dict(avalanche_entropy = 0x5, + rosc_entropy = 0x6, + trng_mixer = 0xa, + trng_csprng = 0xb) def __init__(self, name): super(TRNGCore, self).__init__(name) - self.subcores = tuple(SubCore(name, self) for name in self.subcore_names) + 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: - n = subcore.assign_core_number(n) - return n + subcore.assign_core_number(self.core_number + self.subcore_parameters[subcore.name]) + return n + 15 @property def last_subcore_upper_instance_name(self): @@ -323,7 +359,7 @@ createInstance_template_ModExpS6 = """\ //---------------------------------------------------------------- // {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} + 3); + 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}; @@ -351,7 +387,7 @@ 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.last_subcore_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}; diff --git a/config/core_selector.v b/config/core_selector.v index cc7ca14..90b688e 100644 --- a/config/core_selector.v +++ b/config/core_selector.v @@ -34,11 +34,11 @@ module core_selector 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_MODEXP = 9'h09; + localparam CORE_ADDR_AVALANCHE_ENTROPY = 9'h09; + localparam CORE_ADDR_ROSC_ENTROPY = 9'h0a; + localparam CORE_ADDR_TRNG_MIXER = 9'h0e; + localparam CORE_ADDR_TRNG_CSPRNG = 9'h0f; + localparam CORE_ADDR_MODEXP = 9'h14; //---------------------------------------------------------------- @@ -148,7 +148,7 @@ module core_selector //---------------------------------------------------------------- // TRNG //---------------------------------------------------------------- - wire enable_trng = (addr_core_num >= CORE_ADDR_TRNG) && (addr_core_num <= CORE_ADDR_TRNG_CSPRNG); + 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; -- cgit v1.2.3 From c71a4b55a2c11349d3de2cd503eb058b384f5d34 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Tue, 29 Sep 2015 18:09:04 -0400 Subject: Add support for error_wire and block_memory options. --- config/config.cfg | 17 ++++++++- config/config.py | 99 +++++++++++++++++++++++++++++--------------------- config/core_selector.v | 43 ++++++---------------- 3 files changed, 85 insertions(+), 74 deletions(-) (limited to 'config') diff --git a/config/config.cfg b/config/config.cfg index a4120b1..7e4571c 100644 --- a/config/config.cfg +++ b/config/config.cfg @@ -1,6 +1,6 @@ # Config file for the Cryptech Novena FPGA framework. # -# At present, there are four kinds of variables in this file: +# 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. @@ -16,6 +16,16 @@ # 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. +# +# reset_high: boolean indicating whether the core uses active reset. +# +# 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 @@ -86,7 +96,9 @@ vfiles = cipher/chacha/src/rtl/chacha_qr.v [modexps6] -reset_high = true +block_memory = yes +reset_high = yes +error_wire = no vfiles = math/modexps6/src/rtl/modexps6_adder64_carry32.v math/modexps6/src/rtl/modexps6_buffer_core.v @@ -101,6 +113,7 @@ vfiles = 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 diff --git a/config/config.py b/config/config.py index 3cb69db..1c5e5d0 100755 --- a/config/config.py +++ b/config/config.py @@ -36,35 +36,24 @@ Generate core_selector.v and core_vfiles.mk for a set of cores. # two-level (no segment) scheme and handle modexps6 as a set of four # contiguous "cores" with a 10-bit composite register selector. -# Gah: the TRNG core's internal multiplexer doesn't allocate cores +# At present, TRNG core's internal multiplexer doesn't allocate cores # contiguously, there's a gap, and one just has to know what the -# offsets are. So we need to adjust for all of that. Feh. In theory -# we could hide the gap from the outside world, as it's just a matter -# of (magic) constant offsets on top of the ones we're already -# fiddling with in the core_selector mux. See -# core/rng/trng/src/rtl/trng.v for the authoritative list, but the -# magic offsets for the high 4 bits of the 12-bit TRNG address are: +# offsets are. Current theory is that we'll fix the TRNG core to get +# rid of this problem, but for now the workaround requires this script +# to know the magic offsets for the high 4 bits of the 12-bit TRNG +# address: # -# 0: trng -# 1: - -# 2: - -# 3: - -# 4: - -# 5: entropy1 (avalanche) -# 6: entropy2 (rosc) -# 7: - -# 8: - -# 9: - -# a: mixer -# b: csprng -# c: - -# d: - -# e: - -# f: - - -# The modexps6 core also 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. +# 0x0: trng +# 0x5: entropy1 (avalanche) +# 0x6: entropy2 (rosc) +# 0xa: mixer +# 0xb: csprng + +# The modexps6 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 +# solution for this, because we're going to run into this problem for +# any core that handles arguments big enough to require block memory. # To Do: # @@ -123,6 +112,8 @@ def main(): for core in cores: core.configure(cfg) + Core.need_one_cycle_delay = any(core.block_memory for core in cores) + args.verilog.write(createModule_template.format( addrs = "".join(core.createAddr() for core in cores), insts = "".join(core.createInstance() for core in cores), @@ -172,15 +163,22 @@ class Core(object): _instance_count = {} - # Map from core name to subclass for the special case cores. + # 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 = False + def __init__(self, name): self.name = name self.core_number = None self.vfiles = [] self.reset_high = False + 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 @@ -199,6 +197,8 @@ class Core(object): if required not in self._instance_count: self.vfiles.extend(cfg.getvalues(required, "vfiles")) self.reset_high = cfg.getboolean(self.name, "reset_high", self.reset_high) + self.error_wire = cfg.getboolean(self.name, "error_wire", self.error_wire) + self.block_memory = cfg.getboolean(self.name, "block_memory", self.block_memory) @property def instance_name(self): @@ -215,6 +215,22 @@ class Core(object): def reset_pin(self): return ".rst(sys_rst)" if self.reset_high else ".reset_n(~sys_rst)" + @property + def error_port(self): + return ",\n .error(error_{core.instance_name})".format(core = self) if self.error_wire else "" + + @property + def one_cycle_delay(self): + return one_cycle_delay_template.format(core = self) if self.need_one_cycle_delay and not self.block_memory else "" + + @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 "") + + @property + def mux_error_reg(self): + return "error_" + self.instance_name if self.error_wire else "0" + def createInstance(self): return createInstance_template_generic.format(core = self) @@ -300,7 +316,7 @@ class ModExpS6Core(Core): return createInstance_template_ModExpS6.format(core = self) def createMux(self): - return createMux_modexps6_template.format(core = self) + return createMux_modexps6_template.format(core = self, core0 = self) # Hook special classes in as handlers for the cores that require them. @@ -341,14 +357,10 @@ createInstance_template_generic = """\ .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_{core.instance_name}), - .error(error_{core.instance_name}) + .read_data(read_data_{core.instance_name}){core.error_port} ); - reg [31: 0] read_data_{core.instance_name}_reg; - always @(posedge sys_clk) - read_data_{core.instance_name}_reg <= read_data_{core.instance_name}; - +{core.one_cycle_delay} """ @@ -409,11 +421,16 @@ createInstance_template_TRNG = """\ .debug(debug) ); +{core.one_cycle_delay} + +""" + +# Template for one-cycle delay code. + +one_cycle_delay_template = """\ reg [31: 0] read_data_{core.instance_name}_reg; always @(posedge sys_clk) read_data_{core.instance_name}_reg <= read_data_{core.instance_name}; - - """ # Template for .createMux() methods. @@ -421,8 +438,8 @@ createInstance_template_TRNG = """\ createMux_template = """\ CORE_ADDR_{core.upper_instance_name}: begin - sys_read_data_mux = read_data_{core0.instance_name}_reg; - sys_error_mux = error_{core0.instance_name}; + sys_read_data_mux = {core0.mux_data_reg}; + sys_error_mux = {core0.mux_error_reg}; end """ @@ -434,8 +451,8 @@ createMux_modexps6_template = """\ CORE_ADDR_{core.upper_instance_name} + 2, CORE_ADDR_{core.upper_instance_name} + 3: begin - sys_read_data_mux = read_data_{core.instance_name}; - sys_error_mux = 0; + sys_read_data_mux = {core0.mux_data_reg}; + sys_error_mux = {core0.mux_error_reg}; end """ diff --git a/config/core_selector.v b/config/core_selector.v index 90b688e..0f60771 100644 --- a/config/core_selector.v +++ b/config/core_selector.v @@ -62,9 +62,6 @@ module core_selector .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; //---------------------------------------------------------------- @@ -88,9 +85,6 @@ module core_selector .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; //---------------------------------------------------------------- @@ -114,9 +108,6 @@ module core_selector .error(error_sha256) ); - reg [31: 0] read_data_sha256_reg; - always @(posedge sys_clk) - read_data_sha256_reg <= read_data_sha256; //---------------------------------------------------------------- @@ -140,9 +131,6 @@ module core_selector .error(error_aes) ); - reg [31: 0] read_data_aes_reg; - always @(posedge sys_clk) - read_data_aes_reg <= read_data_aes; //---------------------------------------------------------------- @@ -170,9 +158,6 @@ module core_selector .debug(debug) ); - reg [31: 0] read_data_trng_reg; - always @(posedge sys_clk) - read_data_trng_reg <= read_data_trng; //---------------------------------------------------------------- @@ -192,13 +177,9 @@ module core_selector .address(addr_core_reg), .write_data(sys_write_data), - .read_data(read_data_modexp), - .error(error_modexp) + .read_data(read_data_modexp) ); - reg [31: 0] read_data_modexp_reg; - always @(posedge sys_clk) - read_data_modexp_reg <= read_data_modexp; @@ -215,53 +196,53 @@ module core_selector case (addr_core_num) CORE_ADDR_BOARD_REGS: begin - sys_read_data_mux = read_data_board_regs_reg; + sys_read_data_mux = read_data_board_regs; sys_error_mux = error_board_regs; end CORE_ADDR_COMM_REGS: begin - sys_read_data_mux = read_data_comm_regs_reg; + sys_read_data_mux = read_data_comm_regs; sys_error_mux = error_comm_regs; end CORE_ADDR_SHA256: begin - sys_read_data_mux = read_data_sha256_reg; + sys_read_data_mux = read_data_sha256; sys_error_mux = error_sha256; end CORE_ADDR_AES: begin - sys_read_data_mux = read_data_aes_reg; + sys_read_data_mux = read_data_aes; sys_error_mux = error_aes; end CORE_ADDR_TRNG: begin - sys_read_data_mux = read_data_trng_reg; + sys_read_data_mux = read_data_trng; sys_error_mux = error_trng; end CORE_ADDR_AVALANCHE_ENTROPY: begin - sys_read_data_mux = read_data_trng_reg; + sys_read_data_mux = read_data_trng; sys_error_mux = error_trng; end CORE_ADDR_ROSC_ENTROPY: begin - sys_read_data_mux = read_data_trng_reg; + sys_read_data_mux = read_data_trng; sys_error_mux = error_trng; end CORE_ADDR_TRNG_MIXER: begin - sys_read_data_mux = read_data_trng_reg; + sys_read_data_mux = read_data_trng; sys_error_mux = error_trng; end CORE_ADDR_TRNG_CSPRNG: begin - sys_read_data_mux = read_data_trng_reg; + sys_read_data_mux = read_data_trng; sys_error_mux = error_trng; end CORE_ADDR_MODEXP: begin - sys_read_data_mux = read_data_modexp_reg; - sys_error_mux = error_modexp; + sys_read_data_mux = read_data_modexp; + sys_error_mux = 0; end default: -- cgit v1.2.3 From 47508ec70ea2c85cb1541b1c3a214439357ad735 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Tue, 29 Sep 2015 21:38:00 -0400 Subject: Attempting to optimize out the one-cycle delay didn't work, relatively low priority, so just disable the optimization for now. --- config/config.py | 11 +++++++++-- config/core_selector.v | 38 ++++++++++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 12 deletions(-) (limited to 'config') diff --git a/config/config.py b/config/config.py index 1c5e5d0..0f3818f 100755 --- a/config/config.py +++ b/config/config.py @@ -112,7 +112,14 @@ def main(): for core in cores: core.configure(cfg) - Core.need_one_cycle_delay = any(core.block_memory for core in cores) + if False: + + # For some reason, attempting to optimize out the delay + # code entirely results in a non-working bitstream. Don't + # know why, disabling the optimization works, so just do + # that for now. + + Core.need_one_cycle_delay = any(core.block_memory for core in cores) args.verilog.write(createModule_template.format( addrs = "".join(core.createAddr() for core in cores), @@ -170,7 +177,7 @@ class Core(object): # Class variable recording whether we need a one-cycle delay to # compensate for block memories. - need_one_cycle_delay = False + need_one_cycle_delay = True def __init__(self, name): self.name = name diff --git a/config/core_selector.v b/config/core_selector.v index 0f60771..3c0a31f 100644 --- a/config/core_selector.v +++ b/config/core_selector.v @@ -62,6 +62,9 @@ module core_selector .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; //---------------------------------------------------------------- @@ -85,6 +88,9 @@ module core_selector .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; //---------------------------------------------------------------- @@ -108,6 +114,9 @@ module core_selector .error(error_sha256) ); + reg [31: 0] read_data_sha256_reg; + always @(posedge sys_clk) + read_data_sha256_reg <= read_data_sha256; //---------------------------------------------------------------- @@ -131,6 +140,9 @@ module core_selector .error(error_aes) ); + reg [31: 0] read_data_aes_reg; + always @(posedge sys_clk) + read_data_aes_reg <= read_data_aes; //---------------------------------------------------------------- @@ -158,6 +170,9 @@ module core_selector .debug(debug) ); + reg [31: 0] read_data_trng_reg; + always @(posedge sys_clk) + read_data_trng_reg <= read_data_trng; //---------------------------------------------------------------- @@ -180,6 +195,9 @@ module core_selector .read_data(read_data_modexp) ); + reg [31: 0] read_data_modexp_reg; + always @(posedge sys_clk) + read_data_modexp_reg <= read_data_modexp; @@ -196,52 +214,52 @@ module core_selector case (addr_core_num) CORE_ADDR_BOARD_REGS: begin - sys_read_data_mux = read_data_board_regs; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + sys_read_data_mux = read_data_trng_reg; sys_error_mux = error_trng; end CORE_ADDR_MODEXP: begin - sys_read_data_mux = read_data_modexp; + sys_read_data_mux = read_data_modexp_reg; sys_error_mux = 0; end -- cgit v1.2.3