Merge branch 'master' into gg_ci_cd_dev

This commit is contained in:
ganeshgore 2021-03-01 22:21:29 -07:00 committed by GitHub
commit f0294d1339
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
188 changed files with 52594 additions and 279 deletions

View File

@ -13,7 +13,7 @@ Template
.. code-block:: xml
<configuration_protocol>
<organization type="<string>" circuit_model_name="<string>"/>
<organization type="<string>" circuit_model_name="<string>" num_regions="<int>"/>
</configuration_protocol>
.. option:: type="scan_chain|memory_bank|standalone"

View File

@ -12,6 +12,10 @@ write_fabric_verilog
Specify the output directory for the Verilog netlists. For example, ``--file /temp/fabric_netlist/``
.. option:: --default_net_type <string>
Specify the default net type for the Verilog netlists. Currently, supported types are ``none`` and ``wire``. Default value: ``none``.
.. option:: --explicit_port_mapping
Use explicit port mapping when writing the Verilog netlists

View File

@ -1214,6 +1214,16 @@ CircuitModelId CircuitLibrary::add_model(const enum e_circuit_model_type& type)
/* Build the fast look-up for circuit models */
build_model_lookup();
/* Add a placeholder in the fast look-up for model port
* This is to avoid memory holes when a circuit model
* does not have any ports.
* As a result, the fast look-up may not even create an entry
* for this model id, which cause fast look-up abort when there is
* a query on the model
*/
model_port_lookup_.resize(model_ids_.size());
model_port_lookup_[model_id].resize(NUM_CIRCUIT_MODEL_PORT_TYPES);
return model_id;
}

View File

@ -22,27 +22,33 @@ BasicPort::BasicPort() {
/* By default we set an invalid port, which size is 0 */
lsb_ = 1;
msb_ = 0;
origin_port_width_ = -1;
}
/* Quick constructor */
BasicPort::BasicPort(const char* name, const size_t& lsb, const size_t& msb) {
set_name(std::string(name));
set_width(lsb, msb);
set_origin_port_width(-1);
}
BasicPort::BasicPort(const std::string& name, const size_t& lsb, const size_t& msb) {
set_name(name);
set_width(lsb, msb);
set_origin_port_width(-1);
}
BasicPort::BasicPort(const char* name, const size_t& width) {
set_name(std::string(name));
set_width(width);
set_origin_port_width(-1);
}
BasicPort::BasicPort(const std::string& name, const size_t& width) {
set_name(name);
set_width(width);
set_origin_port_width(-1);
}
/* Copy constructor */
@ -107,6 +113,11 @@ bool BasicPort::contained(const BasicPort& portA) const {
return ( lsb_ <= portA.get_lsb() && portA.get_msb() <= msb_ );
}
/* Set original port width */
size_t BasicPort::get_origin_port_width() const {
return origin_port_width_;
}
/************************************************************************
* Overloaded operators
***********************************************************************/
@ -142,6 +153,7 @@ void BasicPort::set(const BasicPort& basic_port) {
name_ = basic_port.get_name();
lsb_ = basic_port.get_lsb();
msb_ = basic_port.get_msb();
origin_port_width_ = basic_port.get_origin_port_width();
return;
}
@ -185,6 +197,11 @@ void BasicPort::set_msb(const size_t& msb) {
return;
}
void BasicPort::set_origin_port_width(const size_t& origin_port_width) {
origin_port_width_ = origin_port_width;
return;
}
/* Increase the port width */
void BasicPort::expand(const size_t& width) {
if (0 == width) {
@ -291,6 +308,8 @@ void BasicPort::merge(const BasicPort& portA) {
lsb_ = std::min((int)lsb_, (int)portA.get_lsb());
/* MSB follows the minium MSB of the two ports */
msb_ = std::max((int)msb_, (int)portA.get_msb());
/* Origin port width follows the maximum of the two ports */
msb_ = std::max((int)origin_port_width_, (int)portA.get_origin_port_width());
return;
}

View File

@ -31,6 +31,7 @@ class BasicPort {
std::vector<size_t> pins() const; /* Make a range of the pin indices */
bool mergeable(const BasicPort& portA) const; /* Check if a port can be merged with this port */
bool contained(const BasicPort& portA) const; /* Check if a port is contained by this port */
size_t get_origin_port_width() const;
public: /* Mutators */
void set(const BasicPort& basic_port); /* copy */
void set_name(const std::string& name); /* set the port LSB and MSB */
@ -45,12 +46,14 @@ class BasicPort {
void reset(); /* Reset to initial port */
void combine(const BasicPort& port); /* Combine two ports */
void merge(const BasicPort& portA);
void set_origin_port_width(const size_t& origin_port_width);
private: /* internal functions */
void make_invalid(); /* Make a port invalid */
private: /* Internal Data */
std::string name_; /* Name of this port */
size_t msb_; /* Most Significant Bit of this port */
size_t lsb_; /* Least Significant Bit of this port */
size_t origin_port_width_; /* Original port width of a port, used by traceback port conversion history */
};
/* Configuration ports:

View File

@ -47,6 +47,7 @@ int repack(OpenfpgaContext& openfpga_ctx,
openfpga_ctx.mutable_vpr_clustering_annotation(),
openfpga_ctx.vpr_bitstream_annotation(),
repack_design_constraints,
openfpga_ctx.arch().circuit_lib,
cmd_context.option_enable(cmd, opt_verbose));
build_physical_lut_truth_tables(openfpga_ctx.mutable_vpr_clustering_annotation(),

View File

@ -30,6 +30,7 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
CommandOptionId opt_include_timing = cmd.option("include_timing");
CommandOptionId opt_print_user_defined_template = cmd.option("print_user_defined_template");
CommandOptionId opt_default_net_type = cmd.option("default_net_type");
CommandOptionId opt_verbose = cmd.option("verbose");
/* This is an intermediate data structure which is designed to modularize the FPGA-Verilog
@ -40,6 +41,9 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx,
options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping));
options.set_include_timing(cmd_context.option_enable(cmd, opt_include_timing));
options.set_print_user_defined_template(cmd_context.option_enable(cmd, opt_print_user_defined_template));
if (true == cmd_context.option_enable(cmd, opt_default_net_type)) {
options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type));
}
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
options.set_compress_routing(openfpga_ctx.flow_manager().compress_routing());

View File

@ -36,6 +36,10 @@ ShellCommandId add_openfpga_write_fabric_verilog_command(openfpga::Shell<Openfpg
/* Add an option '--print_user_defined_template' */
shell_cmd.add_option("print_user_defined_template", false, "Generate a template Verilog files for user-defined circuit models");
/* Add an option '--default_net_type' */
CommandOptionId default_net_type_opt = shell_cmd.add_option("default_net_type", false, "Set the default net type for Verilog netlists. Default value is 'none'");
shell_cmd.set_option_require_value(default_net_type_opt, openfpga::OPT_STRING);
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");

View File

@ -368,14 +368,14 @@ int build_top_module(ModuleManager& module_manager,
compact_routing_hierarchy);
} else {
VTR_ASSERT_SAFE(false == fabric_key.empty());
/* Give a warning message that the fabric key may overwrite existing region organization.
* Only applicable when number of regions defined in configuration protocol is different
* than the number of regions defined in the fabric key
/* Throw a fatal error when the fabric key has a mismatch in region organization.
* between architecture file and fabric key
*/
if (size_t(config_protocol.num_regions()) != fabric_key.regions().size()) {
VTR_LOG_WARN("Fabric key will overwrite the region organization (='%ld') than architecture definition (=%d)!\n",
fabric_key.regions().size(),
config_protocol.num_regions());
VTR_LOG_ERROR("Fabric key has a different number of configurable regions (='%ld') than architecture definition (=%d)!\n",
fabric_key.regions().size(),
config_protocol.num_regions());
return CMD_EXEC_FATAL_ERROR;
}
status = load_top_module_memory_modules_from_fabric_key(module_manager, top_module,

View File

@ -2,6 +2,7 @@
* Memember functions for data structure FabricVerilogOption
******************************************************************************/
#include "vtr_assert.h"
#include "vtr_log.h"
#include "fabric_verilog_options.h"
@ -17,6 +18,7 @@ FabricVerilogOption::FabricVerilogOption() {
explicit_port_mapping_ = false;
compress_routing_ = false;
print_user_defined_template_ = false;
default_net_type_ = VERILOG_DEFAULT_NET_TYPE_NONE;
verbose_output_ = false;
}
@ -43,6 +45,10 @@ bool FabricVerilogOption::print_user_defined_template() const {
return print_user_defined_template_;
}
e_verilog_default_net_type FabricVerilogOption::default_net_type() const {
return default_net_type_;
}
bool FabricVerilogOption::verbose_output() const {
return verbose_output_;
}
@ -70,6 +76,20 @@ void FabricVerilogOption::set_print_user_defined_template(const bool& enabled) {
print_user_defined_template_ = enabled;
}
void FabricVerilogOption::set_default_net_type(const std::string& default_net_type) {
/* Decode from net type string */;
if (default_net_type == std::string(VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE])) {
default_net_type_ = VERILOG_DEFAULT_NET_TYPE_NONE;
} else if (default_net_type == std::string(VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE])) {
default_net_type_ = VERILOG_DEFAULT_NET_TYPE_WIRE;
} else {
VTR_LOG_WARN("Invalid default net type: '%s'! Expect ['%s'|'%s']\n",
default_net_type.c_str(),
VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE],
VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE]);
}
}
void FabricVerilogOption::set_verbose_output(const bool& enabled) {
verbose_output_ = enabled;
}

View File

@ -5,6 +5,7 @@
* Include header files required by the data structure definition
*******************************************************************/
#include <string>
#include "verilog_port_types.h"
/* Begin namespace openfpga */
namespace openfpga {
@ -21,6 +22,7 @@ class FabricVerilogOption {
bool include_timing() const;
bool explicit_port_mapping() const;
bool compress_routing() const;
e_verilog_default_net_type default_net_type() const;
bool print_user_defined_template() const;
bool verbose_output() const;
public: /* Public mutators */
@ -29,6 +31,7 @@ class FabricVerilogOption {
void set_explicit_port_mapping(const bool& enabled);
void set_compress_routing(const bool& enabled);
void set_print_user_defined_template(const bool& enabled);
void set_default_net_type(const std::string& default_net_type);
void set_verbose_output(const bool& enabled);
private: /* Internal Data */
std::string output_directory_;
@ -36,6 +39,7 @@ class FabricVerilogOption {
bool explicit_port_mapping_;
bool compress_routing_;
bool print_user_defined_template_;
e_verilog_default_net_type default_net_type_;
bool verbose_output_;
};

View File

@ -88,12 +88,12 @@ void fpga_fabric_verilog(ModuleManager &module_manager,
options);
/* Generate primitive Verilog modules, which are corner stones of FPGA fabric
* Note that this function MUST be called before Verilog generation of
* core logic (i.e., logic blocks and routing resources) !!!
* This is because that this function will add the primitive Verilog modules to
* the module manager.
* Without the modules in the module manager, core logic generation is not possible!!!
*/
* Note that this function MUST be called before Verilog generation of
* core logic (i.e., logic blocks and routing resources) !!!
* This is because that this function will add the primitive Verilog modules to
* the module manager.
* Without the modules in the module manager, core logic generation is not possible!!!
*/
print_verilog_submodule(module_manager, netlist_manager,
mux_lib, decoder_lib, circuit_lib,
submodule_dir_path,
@ -105,14 +105,14 @@ void fpga_fabric_verilog(ModuleManager &module_manager,
const_cast<const ModuleManager &>(module_manager),
device_rr_gsb,
rr_dir_path,
options.explicit_port_mapping());
options);
} else {
VTR_ASSERT(false == options.compress_routing());
print_verilog_flatten_routing_modules(netlist_manager,
const_cast<const ModuleManager &>(module_manager),
device_rr_gsb,
rr_dir_path,
options.explicit_port_mapping());
options);
}
/* Generate grids */
@ -120,14 +120,14 @@ void fpga_fabric_verilog(ModuleManager &module_manager,
const_cast<const ModuleManager &>(module_manager),
device_ctx, device_annotation,
lb_dir_path,
options.explicit_port_mapping(),
options,
options.verbose_output());
/* Generate FPGA fabric */
print_verilog_top_module(netlist_manager,
const_cast<const ModuleManager &>(module_manager),
src_dir_path,
options.explicit_port_mapping());
options);
/* Generate an netlist including all the fabric-related netlists */
print_verilog_fabric_include_netlist(const_cast<const NetlistManager &>(netlist_manager),

View File

@ -46,7 +46,8 @@ static
void print_verilog_mux_local_decoder_module(std::fstream& fp,
const ModuleManager& module_manager,
const DecoderLibrary& decoder_lib,
const DecoderId& decoder) {
const DecoderId& decoder,
const e_verilog_default_net_type& default_net_type) {
/* Get the number of inputs */
size_t addr_size = decoder_lib.addr_size(decoder);
size_t data_size = decoder_lib.data_size(decoder);
@ -73,7 +74,7 @@ void print_verilog_mux_local_decoder_module(std::fstream& fp,
VTR_ASSERT(true == decoder_lib.use_data_inv_port(decoder));
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id);
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* Finish dumping ports */
print_verilog_comment(fp, std::string("----- BEGIN Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----"));
@ -164,7 +165,8 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana
NetlistManager& netlist_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir) {
const std::string& submodule_dir,
const e_verilog_default_net_type& default_net_type) {
std::string verilog_fname(submodule_dir + std::string(LOCAL_ENCODER_VERILOG_FILE_NAME));
/* Create the file stream */
@ -212,7 +214,7 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana
/* Generate Verilog modules for the found unique local encoders */
for (const auto& decoder : decoder_lib.decoders()) {
print_verilog_mux_local_decoder_module(fp, module_manager, decoder_lib, decoder);
print_verilog_mux_local_decoder_module(fp, module_manager, decoder_lib, decoder, default_net_type);
}
/* Close the file stream */
@ -253,7 +255,8 @@ static
void print_verilog_arch_decoder_module(std::fstream& fp,
const ModuleManager& module_manager,
const DecoderLibrary& decoder_lib,
const DecoderId& decoder) {
const DecoderId& decoder,
const e_verilog_default_net_type& default_net_type) {
/* Get the number of inputs */
size_t addr_size = decoder_lib.addr_size(decoder);
size_t data_size = decoder_lib.data_size(decoder);
@ -287,7 +290,7 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
}
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id);
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* Finish dumping ports */
print_verilog_comment(fp, std::string("----- BEGIN Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----"));
@ -406,7 +409,8 @@ static
void print_verilog_arch_decoder_with_data_in_module(std::fstream& fp,
const ModuleManager& module_manager,
const DecoderLibrary& decoder_lib,
const DecoderId& decoder) {
const DecoderId& decoder,
const e_verilog_default_net_type& default_net_type) {
/* Get the number of inputs */
size_t addr_size = decoder_lib.addr_size(decoder);
size_t data_size = decoder_lib.data_size(decoder);
@ -444,7 +448,7 @@ void print_verilog_arch_decoder_with_data_in_module(std::fstream& fp,
}
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id);
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* Finish dumping ports */
print_verilog_comment(fp, std::string("----- BEGIN Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----"));
@ -548,7 +552,8 @@ void print_verilog_arch_decoder_with_data_in_module(std::fstream& fp,
void print_verilog_submodule_arch_decoders(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const DecoderLibrary& decoder_lib,
const std::string& submodule_dir) {
const std::string& submodule_dir,
const e_verilog_default_net_type& default_net_type) {
std::string verilog_fname(submodule_dir + std::string(ARCH_ENCODER_VERILOG_FILE_NAME));
/* Create the file stream */
@ -566,9 +571,9 @@ void print_verilog_submodule_arch_decoders(const ModuleManager& module_manager,
/* Generate Verilog modules for the found unique local encoders */
for (const auto& decoder : decoder_lib.decoders()) {
if (true == decoder_lib.use_data_in(decoder)) {
print_verilog_arch_decoder_with_data_in_module(fp, module_manager, decoder_lib, decoder);
print_verilog_arch_decoder_with_data_in_module(fp, module_manager, decoder_lib, decoder, default_net_type);
} else {
print_verilog_arch_decoder_module(fp, module_manager, decoder_lib, decoder);
print_verilog_arch_decoder_module(fp, module_manager, decoder_lib, decoder, default_net_type);
}
}
@ -583,5 +588,4 @@ void print_verilog_submodule_arch_decoders(const ModuleManager& module_manager,
VTR_LOG("Done\n");
}
} /* end namespace openfpga */

View File

@ -14,6 +14,7 @@
#include "decoder_library.h"
#include "module_manager.h"
#include "netlist_manager.h"
#include "verilog_port_types.h"
/********************************************************************
* Function declaration
@ -26,12 +27,14 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana
NetlistManager& netlist_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir);
const std::string& submodule_dir,
const e_verilog_default_net_type& default_net_type);
void print_verilog_submodule_arch_decoders(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const DecoderLibrary& decoder_lib,
const std::string& submodule_dir);
const std::string& submodule_dir,
const e_verilog_default_net_type& default_net_type);
} /* end namespace openfpga */

View File

@ -150,7 +150,8 @@ static
void print_verilog_invbuf_module(const ModuleManager& module_manager,
std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
const CircuitModelId& circuit_model,
const e_verilog_default_net_type& default_net_type) {
/* Ensure a valid file handler*/
VTR_ASSERT(true == valid_file_stream(fp));
@ -171,7 +172,7 @@ void print_verilog_invbuf_module(const ModuleManager& module_manager,
VTR_ASSERT(true == module_manager.valid_module_id(module_id));
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id);
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* Finish dumping ports */
/* Assign logics : depending on topology */
@ -207,7 +208,8 @@ static
void print_verilog_passgate_module(const ModuleManager& module_manager,
std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
const CircuitModelId& circuit_model,
const e_verilog_default_net_type& default_net_type) {
/* Ensure a valid file handler*/
VTR_ASSERT(true == valid_file_stream(fp));
@ -255,7 +257,7 @@ void print_verilog_passgate_module(const ModuleManager& module_manager,
VTR_ASSERT(true == module_manager.valid_module_id(module_id));
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id);
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* Finish dumping ports */
/* Dump logics: we propagate input to the output when the gate is '1'
@ -416,7 +418,8 @@ static
void print_verilog_gate_module(const ModuleManager& module_manager,
std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
const CircuitModelId& circuit_model,
const e_verilog_default_net_type& default_net_type) {
/* Ensure a valid file handler*/
VTR_ASSERT(true == valid_file_stream(fp));
@ -436,7 +439,7 @@ void print_verilog_gate_module(const ModuleManager& module_manager,
VTR_ASSERT(true == module_manager.valid_module_id(module_id));
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id);
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* Finish dumping ports */
/* Dump logics */
@ -469,7 +472,8 @@ void print_verilog_gate_module(const ModuleManager& module_manager,
static
void print_verilog_constant_generator_module(const ModuleManager& module_manager,
std::fstream& fp,
const size_t& const_value) {
const size_t& const_value,
const e_verilog_default_net_type& default_net_type) {
/* Find the module in module manager */
std::string module_name = generate_const_value_module_name(const_value);
ModuleId const_val_module = module_manager.find_module(module_name);
@ -479,7 +483,7 @@ void print_verilog_constant_generator_module(const ModuleManager& module_manager
VTR_ASSERT(true == valid_file_stream(fp));
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, const_val_module);
print_verilog_module_declaration(fp, module_manager, const_val_module, default_net_type);
/* Finish dumping ports */
/* Find the only output*/
@ -500,7 +504,8 @@ void print_verilog_constant_generator_module(const ModuleManager& module_manager
void print_verilog_submodule_essentials(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const std::string& submodule_dir,
const CircuitLibrary& circuit_lib) {
const CircuitLibrary& circuit_lib,
const e_verilog_default_net_type& default_net_type) {
/* TODO: remove .bak when this part is completed and tested */
std::string verilog_fname = submodule_dir + std::string(ESSENTIALS_VERILOG_FILE_NAME);
@ -515,13 +520,13 @@ void print_verilog_submodule_essentials(const ModuleManager& module_manager,
VTR_LOG("Generating Verilog netlist '%s' for essential gates...",
verilog_fname.c_str());
print_verilog_file_header(fp, "Essential gates");
print_verilog_file_header(fp, "Essential gates");
/* Print constant generators */
/* VDD */
print_verilog_constant_generator_module(module_manager, fp, 0);
print_verilog_constant_generator_module(module_manager, fp, 0, default_net_type);
/* GND */
print_verilog_constant_generator_module(module_manager, fp, 1);
print_verilog_constant_generator_module(module_manager, fp, 1, default_net_type);
for (const auto& circuit_model : circuit_lib.models()) {
/* By pass user-defined modules */
@ -529,19 +534,19 @@ void print_verilog_submodule_essentials(const ModuleManager& module_manager,
continue;
}
if (CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(circuit_model)) {
print_verilog_invbuf_module(module_manager, fp, circuit_lib, circuit_model);
print_verilog_invbuf_module(module_manager, fp, circuit_lib, circuit_model, default_net_type);
continue;
}
if (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(circuit_model)) {
print_verilog_passgate_module(module_manager, fp, circuit_lib, circuit_model);
print_verilog_passgate_module(module_manager, fp, circuit_lib, circuit_model, default_net_type);
continue;
}
if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(circuit_model)) {
print_verilog_gate_module(module_manager, fp, circuit_lib, circuit_model);
print_verilog_gate_module(module_manager, fp, circuit_lib, circuit_model, default_net_type);
continue;
}
}
/* Close file handler*/
fp.close();

View File

@ -8,6 +8,7 @@
#include "circuit_library.h"
#include "module_manager.h"
#include "netlist_manager.h"
#include "verilog_port_types.h"
/********************************************************************
* Function declaration
@ -19,7 +20,8 @@ namespace openfpga {
void print_verilog_submodule_essentials(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const std::string& submodule_dir,
const CircuitLibrary& circuit_lib);
const CircuitLibrary& circuit_lib,
const e_verilog_default_net_type& default_net_type);
} /* end namespace openfpga */

View File

@ -58,6 +58,9 @@ void print_verilog_top_random_testbench_ports(std::fstream& fp,
const VprNetlistAnnotation& netlist_annotation) {
/* Validate the file stream */
valid_file_stream(fp);
print_verilog_default_net_type_declaration(fp,
VERILOG_DEFAULT_NET_TYPE_NONE);
/* Print the declaration for the module */
fp << "module " << circuit_name << FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX << ";" << std::endl;

View File

@ -61,13 +61,16 @@ namespace openfpga {
* | |
* +---------------------------------------+
*
* Note that the primitive may be mapped to a standard cell, we force to use
* explict port mapping. This aims to avoid any port sequence issues!!!
*
*******************************************************************/
static
void print_verilog_primitive_block(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const std::string& subckt_dir,
t_pb_graph_node* primitive_pb_graph_node,
const bool& use_explicit_mapping,
const FabricVerilogOption& options,
const bool& verbose) {
/* Ensure a valid pb_graph_node */
if (nullptr == primitive_pb_graph_node) {
@ -107,7 +110,11 @@ void print_verilog_primitive_block(NetlistManager& netlist_manager,
module_manager.module_name(primitive_module).c_str());
/* Write the verilog module */
write_verilog_module_to_file(fp, module_manager, primitive_module, use_explicit_mapping);
write_verilog_module_to_file(fp,
module_manager,
primitive_module,
true,
options.default_net_type());
/* Close file handler */
fp.close();
@ -141,7 +148,7 @@ void rec_print_verilog_logical_tile(NetlistManager& netlist_manager,
const VprDeviceAnnotation& device_annotation,
const std::string& subckt_dir,
t_pb_graph_node* physical_pb_graph_node,
const bool& use_explicit_mapping,
const FabricVerilogOption& options,
const bool& verbose) {
/* Check cur_pb_graph_node*/
@ -167,21 +174,18 @@ void rec_print_verilog_logical_tile(NetlistManager& netlist_manager,
module_manager, device_annotation,
subckt_dir,
&(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]),
use_explicit_mapping,
options,
verbose);
}
}
/* For leaf node, a primitive Verilog module will be generated.
* Note that the primitive may be mapped to a standard cell, we force to use
* explict port mapping. This aims to avoid any port sequence issues!!!
*/
/* For leaf node, a primitive Verilog module will be generated. */
if (true == is_primitive_pb_type(physical_pb_type)) {
print_verilog_primitive_block(netlist_manager,
module_manager,
subckt_dir,
physical_pb_graph_node,
true,
options,
verbose);
/* Finish for primitive node, return */
return;
@ -220,7 +224,11 @@ void rec_print_verilog_logical_tile(NetlistManager& netlist_manager,
print_verilog_comment(fp, std::string("----- BEGIN Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----"));
/* Write the verilog module */
write_verilog_module_to_file(fp, module_manager, pb_module, use_explicit_mapping);
write_verilog_module_to_file(fp,
module_manager,
pb_module,
options.explicit_port_mapping(),
options.default_net_type());
print_verilog_comment(fp, std::string("----- END Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----"));
@ -245,7 +253,7 @@ void print_verilog_logical_tile_netlist(NetlistManager& netlist_manager,
const VprDeviceAnnotation& device_annotation,
const std::string& subckt_dir,
t_pb_graph_node* pb_graph_head,
const bool& use_explicit_mapping,
const FabricVerilogOption& options,
const bool& verbose) {
VTR_LOG("Writing Verilog netlists for logic tile '%s' ...",
@ -264,7 +272,7 @@ void print_verilog_logical_tile_netlist(NetlistManager& netlist_manager,
device_annotation,
subckt_dir,
pb_graph_head,
use_explicit_mapping,
options,
verbose);
VTR_LOG("Done\n");
@ -285,7 +293,7 @@ void print_verilog_physical_tile_netlist(NetlistManager& netlist_manager,
const std::string& subckt_dir,
t_physical_tile_type_ptr phy_block_type,
const e_side& border_side,
const bool& use_explicit_mapping) {
const FabricVerilogOption& options) {
/* Give a name to the Verilog netlist */
/* Create the file name for Verilog */
std::string verilog_fname(subckt_dir
@ -321,7 +329,11 @@ void print_verilog_physical_tile_netlist(NetlistManager& netlist_manager,
/* Write the verilog module */
print_verilog_comment(fp, std::string("----- BEGIN Grid Verilog module: " + module_manager.module_name(grid_module) + " -----"));
write_verilog_module_to_file(fp, module_manager, grid_module, use_explicit_mapping);
write_verilog_module_to_file(fp,
module_manager,
grid_module,
options.explicit_port_mapping(),
options.default_net_type());
print_verilog_comment(fp, std::string("----- END Grid Verilog module: " + module_manager.module_name(grid_module) + " -----"));
@ -350,7 +362,7 @@ void print_verilog_grids(NetlistManager& netlist_manager,
const DeviceContext& device_ctx,
const VprDeviceAnnotation& device_annotation,
const std::string& subckt_dir,
const bool& use_explicit_mapping,
const FabricVerilogOption& options,
const bool& verbose) {
/* Create a vector to contain all the Verilog netlist names that have been generated in this function */
std::vector<std::string> netlist_names;
@ -374,7 +386,7 @@ void print_verilog_grids(NetlistManager& netlist_manager,
device_annotation,
subckt_dir,
logical_tile.pb_graph_head,
use_explicit_mapping,
options,
verbose);
}
VTR_LOG("Writing logical tiles...");
@ -408,7 +420,7 @@ void print_verilog_grids(NetlistManager& netlist_manager,
subckt_dir,
&physical_tile,
io_type_side,
use_explicit_mapping);
options);
}
continue;
} else {
@ -418,7 +430,7 @@ void print_verilog_grids(NetlistManager& netlist_manager,
subckt_dir,
&physical_tile,
NUM_SIDES,
use_explicit_mapping);
options);
}
}
VTR_LOG("Building physical tiles...");

View File

@ -9,6 +9,7 @@
#include "module_manager.h"
#include "netlist_manager.h"
#include "vpr_device_annotation.h"
#include "fabric_verilog_options.h"
/********************************************************************
* Function declaration
@ -22,7 +23,7 @@ void print_verilog_grids(NetlistManager& netlist_manager,
const DeviceContext& device_ctx,
const VprDeviceAnnotation& device_annotation,
const std::string& subckt_dir,
const bool& use_explicit_mapping,
const FabricVerilogOption& options,
const bool& verbose);

View File

@ -33,7 +33,7 @@ void print_verilog_submodule_luts(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
std::string verilog_fname = submodule_dir + std::string(LUTS_VERILOG_FILE_NAME);
std::fstream fp;
@ -60,7 +60,8 @@ void print_verilog_submodule_luts(const ModuleManager& module_manager,
ModuleId lut_module = module_manager.find_module(circuit_lib.model_name(lut_model));
VTR_ASSERT(true == module_manager.valid_module_id(lut_module));
write_verilog_module_to_file(fp, module_manager, lut_module,
use_explicit_port_map || circuit_lib.dump_explicit_port_map(lut_model));
options.explicit_port_mapping() || circuit_lib.dump_explicit_port_map(lut_model),
options.default_net_type());
}
/* Close the file handler */

View File

@ -10,6 +10,7 @@
#include "circuit_library.h"
#include "module_manager.h"
#include "netlist_manager.h"
#include "fabric_verilog_options.h"
/********************************************************************
* Function declaration
@ -22,7 +23,7 @@ void print_verilog_submodule_luts(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir,
const bool& use_explicit_port_map);
const FabricVerilogOption& options);
} /* end namespace openfpga */

View File

@ -47,7 +47,7 @@ void print_verilog_mux_memory_module(const ModuleManager& module_manager,
std::fstream& fp,
const CircuitModelId& mux_model,
const MuxGraph& mux_graph,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
/* Multiplexers built with different technology is in different organization */
switch (circuit_lib.design_tech_type(mux_model)) {
case CIRCUIT_MODEL_DESIGN_CMOS: {
@ -59,7 +59,8 @@ void print_verilog_mux_memory_module(const ModuleManager& module_manager,
VTR_ASSERT(true == module_manager.valid_module_id(mem_module));
/* Write the module content in Verilog format */
write_verilog_module_to_file(fp, module_manager, mem_module,
use_explicit_port_map || circuit_lib.dump_explicit_port_map(mux_model));
options.explicit_port_mapping() || circuit_lib.dump_explicit_port_map(mux_model),
options.default_net_type());
/* Add an empty line as a splitter */
fp << std::endl;
@ -101,7 +102,7 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
/* Plug in with the mux subckt */
std::string verilog_fname(submodule_dir + std::string(MEMORIES_VERILOG_FILE_NAME));
@ -129,7 +130,12 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager,
continue;
}
/* Create a Verilog module for the memories used by the multiplexer */
print_verilog_mux_memory_module(module_manager, circuit_lib, fp, mux_model, mux_graph, use_explicit_port_map);
print_verilog_mux_memory_module(module_manager,
circuit_lib,
fp,
mux_model,
mux_graph,
options);
}
/* Create the memory circuits for non-MUX circuit models.
@ -174,7 +180,8 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager,
VTR_ASSERT(true == module_manager.valid_module_id(mem_module));
/* Write the module content in Verilog format */
write_verilog_module_to_file(fp, module_manager, mem_module,
use_explicit_port_map || circuit_lib.dump_explicit_port_map(model));
options.explicit_port_mapping() || circuit_lib.dump_explicit_port_map(model),
options.default_net_type());
/* Add an empty line as a splitter */
fp << std::endl;

View File

@ -11,6 +11,7 @@
#include "mux_library.h"
#include "module_manager.h"
#include "netlist_manager.h"
#include "fabric_verilog_options.h"
/********************************************************************
* Function declaration
@ -24,7 +25,7 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir,
const bool& use_explicit_port_map);
const FabricVerilogOption& options);
} /* end namespace openfpga */

View File

@ -65,6 +65,7 @@ static
BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manager,
const ModuleId& module_id,
const ModuleNetId& module_net) {
BasicPort port_to_return;
/* Check all the sink modules of the net,
* if we have a source module is the current module, this is not local wire
*/
@ -73,7 +74,10 @@ BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manag
/* Here, this is not a local wire, return the port name of the src_port */
ModulePortId net_src_port = module_manager.net_source_ports(module_id, module_net)[src_id];
size_t src_pin_index = module_manager.net_source_pins(module_id, module_net)[src_id];
return BasicPort(module_manager.module_port(module_id, net_src_port).get_name(), src_pin_index, src_pin_index);
port_to_return.set(module_manager.module_port(module_id, net_src_port));
port_to_return.set_width(src_pin_index, src_pin_index);
port_to_return.set_origin_port_width(module_manager.module_port(module_id, net_src_port).get_width());
return port_to_return;
}
}
@ -83,7 +87,10 @@ BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manag
/* Here, this is not a local wire, return the port name of the sink_port */
ModulePortId net_sink_port = module_manager.net_sink_ports(module_id, module_net)[sink_id];
size_t sink_pin_index = module_manager.net_sink_pins(module_id, module_net)[sink_id];
return BasicPort(module_manager.module_port(module_id, net_sink_port).get_name(), sink_pin_index, sink_pin_index);
port_to_return.set(module_manager.module_port(module_id, net_sink_port));
port_to_return.set_width(sink_pin_index, sink_pin_index);
port_to_return.set_origin_port_width(module_manager.module_port(module_id, net_sink_port).get_width());
return port_to_return;
}
}
@ -110,8 +117,11 @@ BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manag
net_name += std::string("_") + std::to_string(net_src_instance) + std::string("_");
net_name += module_manager.module_port(net_src_module, net_src_port).get_name();
}
return BasicPort(net_name, net_src_pin, net_src_pin);
port_to_return.set_name(net_name);
port_to_return.set_width(net_src_pin, net_src_pin);
port_to_return.set_origin_port_width(module_manager.module_port(net_src_module, net_src_port).get_width());
return port_to_return;
}
/********************************************************************
@ -422,6 +432,7 @@ void write_verilog_instance_to_file(std::fstream& fp,
/* Create the port name and width to be used by the instance */
std::vector<BasicPort> instance_ports;
std::vector<bool> instance_ports_is_single_bit;
for (size_t child_pin : child_port.pins()) {
/* Find the net linked to the pin */
ModuleNetId net = module_manager.module_instance_port_net(parent_module, child_module, instance_id,
@ -431,6 +442,7 @@ void write_verilog_instance_to_file(std::fstream& fp,
/* We give the same port name as child module, this case happens to global ports */
instance_port.set_name(generate_verilog_undriven_local_wire_name(module_manager, parent_module, child_module, instance_id, child_port_id));
instance_port.set_width(child_pin, child_pin);
instance_port.set_origin_port_width(module_manager.module_port(child_module, child_port_id).get_width());
} else {
/* Find the name for this child port */
instance_port = generate_verilog_port_for_module_net(module_manager, parent_module, net);
@ -464,7 +476,8 @@ void write_verilog_instance_to_file(std::fstream& fp,
void write_verilog_module_to_file(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id,
const bool& use_explicit_port_map) {
const bool& use_explicit_port_map,
const e_verilog_default_net_type& default_net_type) {
VTR_ASSERT(true == valid_file_stream(fp));
@ -472,7 +485,7 @@ void write_verilog_module_to_file(std::fstream& fp,
VTR_ASSERT(module_manager.valid_module_id(module_id));
/* Print module declaration */
print_verilog_module_declaration(fp, module_manager, module_id);
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* Print an empty line as splitter */
fp << std::endl;
@ -481,6 +494,12 @@ void write_verilog_module_to_file(std::fstream& fp,
std::map<std::string, std::vector<BasicPort>> local_wires = find_verilog_module_local_wires(module_manager, module_id);
for (std::pair<std::string, std::vector<BasicPort>> port_group : local_wires) {
for (const BasicPort& local_wire : port_group.second) {
/* When default net type is wire, we can skip single-bit wires whose LSB is 0 */
if ( (VERILOG_DEFAULT_NET_TYPE_WIRE == default_net_type)
&& (1 == local_wire.get_width())
&& (0 == local_wire.get_lsb())) {
continue;
}
fp << generate_verilog_port(VERILOG_PORT_WIRE, local_wire) << ";" << std::endl;
}
}
@ -515,6 +534,9 @@ void write_verilog_module_to_file(std::fstream& fp,
/* Print an empty line as splitter */
fp << std::endl;
/* Print an empty line as splitter */
fp << std::endl;
}
} /* end namespace openfpga */

View File

@ -6,6 +6,7 @@
*******************************************************************/
#include <fstream>
#include "module_manager.h"
#include "verilog_port_types.h"
/********************************************************************
* Function declaration
@ -17,7 +18,8 @@ namespace openfpga {
void write_verilog_module_to_file(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id,
const bool& use_explicit_port_map);
const bool& use_explicit_port_map,
const e_verilog_default_net_type& default_net_type);
} /* end namespace openfpga */

View File

@ -121,7 +121,8 @@ void print_verilog_cmos_mux_branch_module_behavioral(ModuleManager& module_manag
std::fstream& fp,
const CircuitModelId& mux_model,
const std::string& module_name,
const MuxGraph& mux_graph) {
const MuxGraph& mux_graph,
const e_verilog_default_net_type& default_net_type) {
/* Get the tgate model */
CircuitModelId tgate_model = circuit_lib.pass_gate_logic_model(mux_model);
@ -160,7 +161,7 @@ void print_verilog_cmos_mux_branch_module_behavioral(ModuleManager& module_manag
BasicPort mem_port("mem", num_mems);
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, mux_module);
print_verilog_module_declaration(fp, module_manager, mux_module, default_net_type);
/* Print the internal logic in behavioral Verilog codes */
/* Get the default value of SRAM ports */
@ -509,6 +510,7 @@ void generate_verilog_rram_mux_branch_module(ModuleManager& module_manager,
const CircuitModelId& circuit_model,
const std::string& module_name,
const MuxGraph& mux_graph,
const e_verilog_default_net_type& default_net_type,
const bool& use_structural_verilog) {
/* Make sure we have a valid file handler*/
VTR_ASSERT(true == valid_file_stream(fp));
@ -559,7 +561,7 @@ void generate_verilog_rram_mux_branch_module(ModuleManager& module_manager,
BasicPort wl_port(circuit_lib.port_prefix(mux_wl_ports[0]), num_mems + 1);
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id);
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* Print the internal logic in either structural or behavioral Verilog codes */
if (true == use_structural_verilog) {
@ -583,6 +585,7 @@ void generate_verilog_mux_branch_module(ModuleManager& module_manager,
const CircuitModelId& mux_model,
const MuxGraph& mux_graph,
const bool& use_explicit_port_map,
const e_verilog_default_net_type& default_net_type,
std::map<std::string, bool>& branch_mux_module_is_outputted) {
std::string module_name = generate_mux_branch_subckt_name(circuit_lib, mux_model, mux_graph.num_inputs(), mux_graph.num_memory_bits(), VERILOG_MUX_BASIS_POSTFIX);
@ -608,16 +611,29 @@ void generate_verilog_mux_branch_module(ModuleManager& module_manager,
ModuleId mux_module = module_manager.find_module(module_name);
VTR_ASSERT(true == module_manager.valid_module_id(mux_module));
write_verilog_module_to_file(fp, module_manager, mux_module,
use_explicit_port_map || circuit_lib.dump_explicit_port_map(mux_model));
use_explicit_port_map || circuit_lib.dump_explicit_port_map(mux_model),
default_net_type);
/* Add an empty line as a splitter */
fp << std::endl;
} else {
/* Behavioral verilog requires customized generation */
print_verilog_cmos_mux_branch_module_behavioral(module_manager, circuit_lib, fp, mux_model, module_name, mux_graph);
print_verilog_cmos_mux_branch_module_behavioral(module_manager,
circuit_lib,
fp,
mux_model,
module_name,
mux_graph,
default_net_type);
}
break;
case CIRCUIT_MODEL_DESIGN_RRAM:
generate_verilog_rram_mux_branch_module(module_manager, circuit_lib, fp, mux_model, module_name, mux_graph,
generate_verilog_rram_mux_branch_module(module_manager,
circuit_lib,
fp,
mux_model,
module_name,
mux_graph,
default_net_type,
circuit_lib.dump_structural_verilog(mux_model));
break;
default:
@ -1084,7 +1100,8 @@ void generate_verilog_rram_mux_module(ModuleManager& module_manager,
std::fstream& fp,
const CircuitModelId& circuit_model,
const std::string& module_name,
const MuxGraph& mux_graph) {
const MuxGraph& mux_graph,
const e_verilog_default_net_type& default_net_type) {
/* Error out for the conditions where we are not yet supported! */
if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) {
/* RRAM LUT is not supported now... */
@ -1169,7 +1186,7 @@ void generate_verilog_rram_mux_module(ModuleManager& module_manager,
}
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id);
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* TODO: Print the internal logic in Verilog codes */
generate_verilog_rram_mux_module_multiplexing_structure(module_manager, circuit_lib, fp, module_id, circuit_model, mux_graph);
@ -1194,7 +1211,8 @@ void generate_verilog_mux_module(ModuleManager& module_manager,
std::fstream& fp,
const CircuitModelId& mux_model,
const MuxGraph& mux_graph,
const bool& use_explicit_port_map) {
const bool& use_explicit_port_map,
const e_verilog_default_net_type& default_net_type) {
std::string module_name = generate_mux_subckt_name(circuit_lib, mux_model,
find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()),
std::string(""));
@ -1208,15 +1226,21 @@ void generate_verilog_mux_module(ModuleManager& module_manager,
write_verilog_module_to_file(fp, module_manager, mux_module,
( use_explicit_port_map
|| circuit_lib.dump_explicit_port_map(mux_model)
|| circuit_lib.dump_explicit_port_map(circuit_lib.pass_gate_logic_model(mux_model)) )
);
|| circuit_lib.dump_explicit_port_map(circuit_lib.pass_gate_logic_model(mux_model)) ),
default_net_type);
/* Add an empty line as a splitter */
fp << std::endl;
break;
}
case CIRCUIT_MODEL_DESIGN_RRAM:
/* TODO: RRAM-based Multiplexer Verilog module generation */
generate_verilog_rram_mux_module(module_manager, circuit_lib, fp, mux_model, module_name, mux_graph);
generate_verilog_rram_mux_module(module_manager,
circuit_lib,
fp,
mux_model,
module_name,
mux_graph,
default_net_type);
break;
default:
VTR_LOGF_ERROR(__FILE__, __LINE__,
@ -1236,7 +1260,7 @@ void print_verilog_submodule_mux_primitives(ModuleManager& module_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
/* Output primitive cells for MUX modules */
std::string verilog_fname(submodule_dir + std::string(MUX_PRIMITIVES_VERILOG_FILE_NAME));
@ -1266,7 +1290,9 @@ void print_verilog_submodule_mux_primitives(ModuleManager& module_manager,
/* Create branch circuits, which are N:1 one-level or 2:1 tree-like MUXes */
for (auto branch_mux_graph : branch_mux_graphs) {
generate_verilog_mux_branch_module(module_manager, circuit_lib, fp, mux_circuit_model,
branch_mux_graph, use_explicit_port_map,
branch_mux_graph,
options.explicit_port_mapping(),
options.default_net_type(),
branch_mux_module_is_outputted);
}
}
@ -1292,7 +1318,7 @@ void print_verilog_submodule_mux_top_modules(ModuleManager& module_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
/* Output top-level MUX modules */
std::string verilog_fname(submodule_dir + std::string(MUXES_VERILOG_FILE_NAME));
@ -1308,13 +1334,18 @@ void print_verilog_submodule_mux_top_modules(ModuleManager& module_manager,
print_verilog_file_header(fp, "Multiplexers");
/* Generate unique Verilog modules for the multiplexers */
for (auto mux : mux_lib.muxes()) {
const MuxGraph& mux_graph = mux_lib.mux_graph(mux);
CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux);
/* Create MUX circuits */
generate_verilog_mux_module(module_manager, circuit_lib, fp, mux_circuit_model, mux_graph, use_explicit_port_map);
generate_verilog_mux_module(module_manager,
circuit_lib,
fp,
mux_circuit_model,
mux_graph,
options.explicit_port_mapping(),
options.default_net_type());
}
/* Close the file stream */
@ -1342,20 +1373,20 @@ void print_verilog_submodule_muxes(ModuleManager& module_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
print_verilog_submodule_mux_primitives(module_manager,
netlist_manager,
mux_lib,
circuit_lib,
submodule_dir,
use_explicit_port_map);
options);
print_verilog_submodule_mux_top_modules(module_manager,
netlist_manager,
mux_lib,
circuit_lib,
submodule_dir,
use_explicit_port_map);
options);
}
} /* end namespace openfpga */

View File

@ -12,6 +12,7 @@
#include "mux_library.h"
#include "module_manager.h"
#include "netlist_manager.h"
#include "fabric_verilog_options.h"
/********************************************************************
* Function declaration
@ -25,7 +26,7 @@ void print_verilog_submodule_muxes(ModuleManager& module_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir,
const bool& use_explicit_port_map);
const FabricVerilogOption& options);
} /* end namespace openfpga */

View File

@ -1,6 +1,22 @@
#ifndef VERILOG_PORT_TYPES_H
#define VERILOG_PORT_TYPES_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include <string>
#include <array>
/* Begin namespace openfpga */
namespace openfpga {
enum e_verilog_default_net_type {
VERILOG_DEFAULT_NET_TYPE_NONE,
VERILOG_DEFAULT_NET_TYPE_WIRE,
NUM_VERILOG_DEFAULT_NET_TYPES,
};
constexpr std::array<const char*, NUM_VERILOG_DEFAULT_NET_TYPES> VERILOG_DEFAULT_NET_TYPE_STRING = {{"none", "wire"}}; //String versions of default net types
enum e_dump_verilog_port_type {
VERILOG_PORT_INPUT,
VERILOG_PORT_OUTPUT,
@ -12,5 +28,7 @@ enum e_dump_verilog_port_type {
};
constexpr std::array<const char*, NUM_VERILOG_PORT_TYPES> VERILOG_PORT_TYPE_STRING = {{"input", "output", "inout", "wire", "reg", ""}}; /* string version of enum e_verilog_port_type */
} /* End namespace openfpga*/
#endif

View File

@ -448,6 +448,9 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
std::string title = std::string("Verilog netlist for pre-configured FPGA fabric by design: ") + circuit_name;
print_verilog_file_header(fp, title);
print_verilog_default_net_type_declaration(fp,
VERILOG_DEFAULT_NET_TYPE_NONE);
/* Print module declaration and ports */
print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation);

View File

@ -80,7 +80,7 @@ void print_verilog_routing_connection_box_unique_module(NetlistManager& netlist_
const std::string& subckt_dir,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
/* Create the netlist */
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
std::string verilog_fname(subckt_dir + generate_connection_block_netlist_name(cb_type, gsb_coordinate, std::string(VERILOG_NETLIST_FILE_POSTFIX)));
@ -98,7 +98,10 @@ void print_verilog_routing_connection_box_unique_module(NetlistManager& netlist_
VTR_ASSERT(true == module_manager.valid_module_id(cb_module));
/* Write the verilog module */
write_verilog_module_to_file(fp, module_manager, cb_module, use_explicit_port_map);
write_verilog_module_to_file(fp,
module_manager, cb_module,
options.explicit_port_mapping(),
options.default_net_type());
/* Add an empty line as a splitter */
fp << std::endl;
@ -180,7 +183,7 @@ void print_verilog_routing_switch_box_unique_module(NetlistManager& netlist_mana
const ModuleManager& module_manager,
const std::string& subckt_dir,
const RRGSB& rr_gsb,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
/* Create the netlist */
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
std::string verilog_fname(subckt_dir + generate_routing_block_netlist_name(SB_VERILOG_FILE_NAME_PREFIX, gsb_coordinate, std::string(VERILOG_NETLIST_FILE_POSTFIX)));
@ -198,7 +201,11 @@ void print_verilog_routing_switch_box_unique_module(NetlistManager& netlist_mana
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
/* Write the verilog module */
write_verilog_module_to_file(fp, module_manager, sb_module, use_explicit_port_map);
write_verilog_module_to_file(fp,
module_manager,
sb_module,
options.explicit_port_mapping(),
options.default_net_type());
/* Close file handler */
fp.close();
@ -219,7 +226,7 @@ void print_verilog_flatten_connection_block_modules(NetlistManager& netlist_mana
const DeviceRRGSB& device_rr_gsb,
const std::string& subckt_dir,
const t_rr_type& cb_type,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
/* Build unique X-direction connection block modules */
vtr::Point<size_t> cb_range = device_rr_gsb.get_gsb_range();
@ -237,7 +244,7 @@ void print_verilog_flatten_connection_block_modules(NetlistManager& netlist_mana
module_manager,
subckt_dir,
rr_gsb, cb_type,
use_explicit_port_map);
options);
}
}
}
@ -255,7 +262,7 @@ void print_verilog_flatten_routing_modules(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const DeviceRRGSB& device_rr_gsb,
const std::string& subckt_dir,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
/* Create a vector to contain all the Verilog netlist names that have been generated in this function */
std::vector<std::string> netlist_names;
@ -272,13 +279,23 @@ void print_verilog_flatten_routing_modules(NetlistManager& netlist_manager,
module_manager,
subckt_dir,
rr_gsb,
use_explicit_port_map);
options);
}
}
print_verilog_flatten_connection_block_modules(netlist_manager, module_manager, device_rr_gsb, subckt_dir, CHANX, use_explicit_port_map);
print_verilog_flatten_connection_block_modules(netlist_manager,
module_manager,
device_rr_gsb,
subckt_dir,
CHANX,
options);
print_verilog_flatten_connection_block_modules(netlist_manager, module_manager, device_rr_gsb, subckt_dir, CHANY, use_explicit_port_map);
print_verilog_flatten_connection_block_modules(netlist_manager,
module_manager,
device_rr_gsb,
subckt_dir,
CHANY,
options);
/*
VTR_LOG("Writing header file for routing submodules '%s'...",
@ -306,7 +323,7 @@ void print_verilog_unique_routing_modules(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const DeviceRRGSB& device_rr_gsb,
const std::string& subckt_dir,
const bool& use_explicit_port_map) {
const FabricVerilogOption& options) {
/* Create a vector to contain all the Verilog netlist names that have been generated in this function */
std::vector<std::string> netlist_names;
@ -317,7 +334,7 @@ void print_verilog_unique_routing_modules(NetlistManager& netlist_manager,
module_manager,
subckt_dir,
unique_mirror,
use_explicit_port_map);
options);
}
/* Build unique X-direction connection block modules */
@ -328,7 +345,7 @@ void print_verilog_unique_routing_modules(NetlistManager& netlist_manager,
module_manager,
subckt_dir,
unique_mirror, CHANX,
use_explicit_port_map);
options);
}
/* Build unique X-direction connection block modules */
@ -339,7 +356,7 @@ void print_verilog_unique_routing_modules(NetlistManager& netlist_manager,
module_manager,
subckt_dir,
unique_mirror, CHANY,
use_explicit_port_map);
options);
}
/*

View File

@ -9,6 +9,7 @@
#include "module_manager.h"
#include "netlist_manager.h"
#include "device_rr_gsb.h"
#include "fabric_verilog_options.h"
/********************************************************************
* Function declaration
@ -21,13 +22,13 @@ void print_verilog_flatten_routing_modules(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const DeviceRRGSB& device_rr_gsb,
const std::string& subckt_dir,
const bool& use_explicit_port_map);
const FabricVerilogOption& options);
void print_verilog_unique_routing_modules(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const DeviceRRGSB& device_rr_gsb,
const std::string& subckt_dir,
const bool& use_explicit_port_map);
const FabricVerilogOption& options);
} /* end namespace openfpga */

View File

@ -48,13 +48,15 @@ void print_verilog_submodule(ModuleManager& module_manager,
print_verilog_submodule_essentials(const_cast<const ModuleManager&>(module_manager),
netlist_manager,
submodule_dir,
circuit_lib);
circuit_lib,
fpga_verilog_opts.default_net_type());
/* Decoders for architecture */
print_verilog_submodule_arch_decoders(const_cast<const ModuleManager&>(module_manager),
netlist_manager,
decoder_lib,
submodule_dir);
submodule_dir,
fpga_verilog_opts.default_net_type());
/* Routing multiplexers */
/* NOTE: local decoders generation must go before the MUX generation!!!
@ -63,35 +65,38 @@ void print_verilog_submodule(ModuleManager& module_manager,
print_verilog_submodule_mux_local_decoders(const_cast<const ModuleManager&>(module_manager),
netlist_manager,
mux_lib, circuit_lib,
submodule_dir);
submodule_dir,
fpga_verilog_opts.default_net_type());
print_verilog_submodule_muxes(module_manager, netlist_manager, mux_lib, circuit_lib,
submodule_dir,
fpga_verilog_opts.explicit_port_mapping());
fpga_verilog_opts);
/* LUTes */
print_verilog_submodule_luts(const_cast<const ModuleManager&>(module_manager),
netlist_manager, circuit_lib,
submodule_dir,
fpga_verilog_opts.explicit_port_mapping());
fpga_verilog_opts);
/* Hard wires */
print_verilog_submodule_wires(const_cast<const ModuleManager&>(module_manager),
netlist_manager, circuit_lib,
submodule_dir);
submodule_dir,
fpga_verilog_opts.default_net_type());
/* 4. Memories */
print_verilog_submodule_memories(const_cast<const ModuleManager&>(module_manager),
netlist_manager,
mux_lib, circuit_lib,
submodule_dir,
fpga_verilog_opts.explicit_port_mapping());
fpga_verilog_opts);
/* 5. Dump template for all the modules */
if (true == fpga_verilog_opts.print_user_defined_template()) {
print_verilog_submodule_templates(const_cast<const ModuleManager&>(module_manager),
circuit_lib,
submodule_dir);
submodule_dir,
fpga_verilog_opts.default_net_type());
}
/* Create a header file to include all the subckts */

View File

@ -66,15 +66,17 @@ void print_verilog_submodule_timing(std::fstream& fp,
CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge);
size_t src_pin = circuit_lib.timing_edge_src_pin(timing_edge);
BasicPort src_port_info(circuit_lib.port_lib_name(src_port), src_pin, src_pin);
src_port_info.set_origin_port_width(src_port_info.get_width());
CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge);
size_t sink_pin = circuit_lib.timing_edge_sink_pin(timing_edge);
BasicPort sink_port_info(circuit_lib.port_lib_name(sink_port), sink_pin, sink_pin);
sink_port_info.set_origin_port_width(sink_port_info.get_width());
fp << "\t\t";
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, src_port_info);
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, src_port_info, false);
fp << " => ";
fp << generate_verilog_port(VERILOG_PORT_CONKT, sink_port_info) << ")";
fp << generate_verilog_port(VERILOG_PORT_CONKT, sink_port_info, false) << ")";
fp << " = ";
fp << "(" << std::setprecision(FLOAT_PRECISION) << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_RISE) / VERILOG_SIM_TIMESCALE;
fp << ", ";
@ -132,7 +134,8 @@ void add_user_defined_verilog_modules(ModuleManager& module_manager,
static
void print_one_verilog_template_module(const ModuleManager& module_manager,
std::fstream& fp,
const std::string& module_name) {
const std::string& module_name,
const e_verilog_default_net_type& default_net_type) {
/* Ensure a valid file handler*/
VTR_ASSERT(true == valid_file_stream(fp));
@ -144,7 +147,7 @@ void print_one_verilog_template_module(const ModuleManager& module_manager,
VTR_ASSERT(ModuleId::INVALID() != template_module);
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, template_module);
print_verilog_module_declaration(fp, module_manager, template_module, default_net_type);
/* Finish dumping ports */
print_verilog_comment(fp, std::string("----- Internal logic should start here -----"));
@ -170,7 +173,8 @@ void print_one_verilog_template_module(const ModuleManager& module_manager,
********************************************************************/
void print_verilog_submodule_templates(const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir) {
const std::string& submodule_dir,
const e_verilog_default_net_type& default_net_type) {
std::string verilog_fname(submodule_dir + USER_DEFINED_TEMPLATE_VERILOG_FILE_NAME);
/* Create the file stream */
@ -196,7 +200,10 @@ void print_verilog_submodule_templates(const ModuleManager& module_manager,
continue;
}
/* Print a Verilog template for the circuit model */
print_one_verilog_template_module(module_manager, fp, circuit_lib.model_name(model));
print_one_verilog_template_module(module_manager,
fp,
circuit_lib.model_name(model),
default_net_type);
}
/* close file stream */

View File

@ -8,6 +8,7 @@
#include <string>
#include "module_manager.h"
#include "circuit_library.h"
#include "verilog_port_types.h"
/********************************************************************
* Function declaration
@ -25,7 +26,8 @@ void add_user_defined_verilog_modules(ModuleManager& module_manager,
void print_verilog_submodule_templates(const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir);
const std::string& submodule_dir,
const e_verilog_default_net_type& default_net_type);
} /* end namespace openfpga */

View File

@ -823,9 +823,10 @@ void rec_print_verilog_testbench_primitive_module_signal_initialization(std::fst
/* Only for formal verification: deposite a zero signal values */
/* Initialize each input port */
BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port));
input_port_info.set_origin_port_width(input_port_info.get_width());
fp << "\t\t$deposit(";
fp << child_hie_path << ".";
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info);
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info, false);
fp << ", " << circuit_lib.port_size(input_port) << "'b" << std::string(circuit_lib.port_size(input_port), '0');
fp << ");" << std::endl;
}
@ -834,9 +835,10 @@ void rec_print_verilog_testbench_primitive_module_signal_initialization(std::fst
/* Regular case: deposite initial signal values: a random value */
for (const auto& input_port : circuit_input_ports) {
BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port));
input_port_info.set_origin_port_width(input_port_info.get_width());
fp << "\t\t$deposit(";
fp << child_hie_path << ".";
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info);
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info, false);
fp << ", $random % 2 ? 1'b1 : 1'b0);" << std::endl;
}

View File

@ -37,7 +37,7 @@ namespace openfpga {
void print_verilog_top_module(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const std::string& verilog_dir,
const bool& use_explicit_mapping) {
const FabricVerilogOption& options) {
/* Create a module as the top-level fabric, and add it to the module manager */
std::string top_module_name = generate_fpga_top_module_name();
ModuleId top_module = module_manager.find_module(top_module_name);
@ -59,7 +59,11 @@ void print_verilog_top_module(NetlistManager& netlist_manager,
print_verilog_file_header(fp, std::string("Top-level Verilog module for FPGA"));
/* Write the module content in Verilog format */
write_verilog_module_to_file(fp, module_manager, top_module, use_explicit_mapping);
write_verilog_module_to_file(fp,
module_manager,
top_module,
options.explicit_port_mapping(),
options.default_net_type());
/* Add an empty line as a splitter */
fp << std::endl;

View File

@ -7,6 +7,7 @@
#include <string>
#include "module_manager.h"
#include "netlist_manager.h"
#include "fabric_verilog_options.h"
/********************************************************************
* Function declaration
@ -18,7 +19,7 @@ namespace openfpga {
void print_verilog_top_module(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const std::string& verilog_dir,
const bool& use_explicit_mapping);
const FabricVerilogOption& options);
} /* end namespace openfpga */

View File

@ -578,6 +578,9 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
/* Validate the file stream */
valid_file_stream(fp);
print_verilog_default_net_type_declaration(fp,
VERILOG_DEFAULT_NET_TYPE_NONE);
/* Print module definition */
fp << "module " << circuit_name << std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX);
fp << ";" << std::endl;

View File

@ -38,7 +38,8 @@ static
void print_verilog_wire_module(const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
std::fstream& fp,
const CircuitModelId& wire_model) {
const CircuitModelId& wire_model,
const e_verilog_default_net_type& default_net_type) {
/* Ensure a valid file handler*/
VTR_ASSERT(true == valid_file_stream(fp));
@ -58,7 +59,7 @@ void print_verilog_wire_module(const ModuleManager& module_manager,
VTR_ASSERT(true == module_manager.valid_module_id(wire_module));
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, wire_module);
print_verilog_module_declaration(fp, module_manager, wire_module, default_net_type);
/* Finish dumping ports */
/* Print the internal logic of Verilog module */
@ -95,7 +96,8 @@ void print_verilog_wire_module(const ModuleManager& module_manager,
void print_verilog_submodule_wires(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir) {
const std::string& submodule_dir,
const e_verilog_default_net_type& default_net_type) {
std::string verilog_fname(submodule_dir + std::string(WIRES_VERILOG_FILE_NAME));
/* Create the file stream */
@ -117,7 +119,7 @@ void print_verilog_submodule_wires(const ModuleManager& module_manager,
if (!circuit_lib.model_verilog_netlist(model).empty()) {
continue;
}
print_verilog_wire_module(module_manager, circuit_lib, fp, model);
print_verilog_wire_module(module_manager, circuit_lib, fp, model, default_net_type);
}
print_verilog_comment(fp, std::string("----- END Verilog modules for regular wires -----"));

View File

@ -10,6 +10,7 @@
#include "circuit_library.h"
#include "module_manager.h"
#include "netlist_manager.h"
#include "verilog_port_types.h"
/********************************************************************
* Function declaration
@ -21,7 +22,8 @@ namespace openfpga {
void print_verilog_submodule_wires(const ModuleManager& module_manager,
NetlistManager& netlist_manager,
const CircuitLibrary& circuit_lib,
const std::string& submodule_dir);
const std::string& submodule_dir,
const e_verilog_default_net_type& default_net_type);
} /* end namespace openfpga */

View File

@ -26,6 +26,18 @@
/* begin namespace openfpga */
namespace openfpga {
/************************************************
* Generate the declaration for default net type
***********************************************/
void print_verilog_default_net_type_declaration(std::fstream& fp,
const e_verilog_default_net_type& default_net_type) {
VTR_ASSERT(true == valid_file_stream(fp));
fp << "//----- Default net type -----" << std::endl;
fp << "`default_nettype " << VERILOG_DEFAULT_NET_TYPE_STRING[default_net_type] << std::endl;
fp << std::endl;
}
/************************************************
* Generate header comments for a Verilog netlist
* include the description
@ -184,7 +196,9 @@ void print_verilog_module_definition(std::fstream& fp,
* Print a Verilog module ports based on the module id
***********************************************/
void print_verilog_module_ports(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id) {
const ModuleManager& module_manager,
const ModuleId& module_id,
const e_verilog_default_net_type& default_net_type) {
VTR_ASSERT(true == valid_file_stream(fp));
/* port type2type mapping */
@ -222,38 +236,39 @@ void print_verilog_module_ports(std::fstream& fp,
}
}
/* Output any port that is also wire connection */
fp << std::endl;
fp << "//----- BEGIN wire-connection ports -----" << std::endl;
for (const auto& kv : port_type2type_map) {
for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) {
/* Skip the ports that are not registered */
ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name());
VTR_ASSERT(ModulePortId::INVALID() != port_id);
if (false == module_manager.port_is_wire(module_id, port_id)) {
continue;
}
/* Output any port that is also wire connection when default net type is not wire! */
if (VERILOG_DEFAULT_NET_TYPE_WIRE != default_net_type) {
fp << std::endl;
fp << "//----- BEGIN wire-connection ports -----" << std::endl;
for (const auto& kv : port_type2type_map) {
for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) {
/* Skip the ports that are not registered */
ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name());
VTR_ASSERT(ModulePortId::INVALID() != port_id);
if (false == module_manager.port_is_wire(module_id, port_id)) {
continue;
}
/* Print pre-processing flag for a port, if defined */
std::string preproc_flag = module_manager.port_preproc_flag(module_id, port_id);
if (false == preproc_flag.empty()) {
/* Print an ifdef Verilog syntax */
print_verilog_preprocessing_flag(fp, preproc_flag);
}
/* Print pre-processing flag for a port, if defined */
std::string preproc_flag = module_manager.port_preproc_flag(module_id, port_id);
if (false == preproc_flag.empty()) {
/* Print an ifdef Verilog syntax */
print_verilog_preprocessing_flag(fp, preproc_flag);
}
/* Print port */
fp << generate_verilog_port(VERILOG_PORT_WIRE, port);
fp << ";" << std::endl;
/* Print port */
fp << generate_verilog_port(VERILOG_PORT_WIRE, port);
fp << ";" << std::endl;
if (false == preproc_flag.empty()) {
/* Print an endif to pair the ifdef */
print_verilog_endif(fp);
if (false == preproc_flag.empty()) {
/* Print an endif to pair the ifdef */
print_verilog_endif(fp);
}
}
}
fp << "//----- END wire-connection ports -----" << std::endl;
fp << std::endl;
}
fp << "//----- END wire-connection ports -----" << std::endl;
fp << std::endl;
/* Output any port that is registered */
fp << std::endl;
@ -295,12 +310,18 @@ void print_verilog_module_ports(std::fstream& fp,
* <tab><port definition with direction>
***********************************************/
void print_verilog_module_declaration(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id) {
const ModuleManager& module_manager,
const ModuleId& module_id,
const e_verilog_default_net_type& default_net_type) {
VTR_ASSERT(true == valid_file_stream(fp));
/* Apply default net type from user's option */
print_verilog_default_net_type_declaration(fp,
default_net_type);
print_verilog_module_definition(fp, module_manager, module_id);
print_verilog_module_ports(fp, module_manager, module_id);
print_verilog_module_ports(fp, module_manager, module_id, default_net_type);
}
@ -429,13 +450,18 @@ void print_verilog_module_end(std::fstream& fp,
fp << "endmodule" << std::endl;
print_verilog_comment(fp, std::string("----- END Verilog module for " + module_name + " -----"));
fp << std::endl;
/* Reset default net type to be none */
print_verilog_default_net_type_declaration(fp,
VERILOG_DEFAULT_NET_TYPE_NONE);
}
/************************************************
* Generate a string of a Verilog port
***********************************************/
std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_port_type,
const BasicPort& port_info) {
const BasicPort& port_info,
const bool& must_print_port_size) {
std::string verilog_line;
/* Ensure the port type is valid */
@ -447,8 +473,22 @@ std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_p
* others require a format of <port_type> [<lsb>:<msb>] <port_name>
*/
if (VERILOG_PORT_CONKT == verilog_port_type) {
/* When LSB == MSB, we can use a simplified format <port_type>[<lsb>]*/
if ( 1 == port_info.get_width()) {
/* Simplication:
* - When LSB == MSB == 0, we do not need to specify size when the user option allows
* Note that user option is essential, otherwise what could happen is that
* a multi-bit verilog port used in instance port mapping is printed as a single-bit net
* For example,
* input [1:0] in;
* inv inv_inst (.A(in), .Y(out));
* The original port width is the reference to backtrace the defintion of the port
* - When LSB == MSB, we can use a simplified format <port_type>[<lsb>]
*/
if ((false == must_print_port_size)
&& (1 == port_info.get_width())
&& (0 == port_info.get_lsb())
&& (1 == port_info.get_origin_port_width())) {
size_str.clear();
} else if ((1 == port_info.get_width()) && (0 != port_info.get_lsb())) {
size_str = "[" + std::to_string(port_info.get_lsb()) + "]";
}
verilog_line = port_info.get_name() + size_str;
@ -557,7 +597,7 @@ std::string generate_verilog_ports(const std::vector<BasicPort>& merged_ports) {
VTR_ASSERT(0 < merged_ports.size());
if ( 1 == merged_ports.size()) {
/* Use connection type of verilog port */
return generate_verilog_port(VERILOG_PORT_CONKT, merged_ports[0]);
return generate_verilog_port(VERILOG_PORT_CONKT, merged_ports[0], false);
}
std::string verilog_line = "{";
@ -566,7 +606,7 @@ std::string generate_verilog_ports(const std::vector<BasicPort>& merged_ports) {
if (&port != &merged_ports[0]) {
verilog_line += ", ";
}
verilog_line += generate_verilog_port(VERILOG_PORT_CONKT, port);
verilog_line += generate_verilog_port(VERILOG_PORT_CONKT, port, false);
}
verilog_line += "}";

View File

@ -31,6 +31,9 @@ namespace openfpga {
* as well maintain a easy way to identify the functions
*/
void print_verilog_default_net_type_declaration(std::fstream& fp,
const e_verilog_default_net_type& default_net_type);
void print_verilog_file_header(std::fstream& fp,
const std::string& usage);
@ -56,10 +59,14 @@ void print_verilog_module_definition(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id);
void print_verilog_module_ports(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id);
const ModuleManager& module_manager,
const ModuleId& module_id,
const e_verilog_default_net_type& default_net_type);
void print_verilog_module_declaration(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id);
const ModuleManager& module_manager,
const ModuleId& module_id,
const e_verilog_default_net_type& default_net_type);
void print_verilog_module_instance(std::fstream& fp,
const ModuleManager& module_manager,
@ -78,7 +85,8 @@ void print_verilog_module_end(std::fstream& fp,
const std::string& module_name);
std::string generate_verilog_port(const enum e_dump_verilog_port_type& dump_port_type,
const BasicPort& port_info);
const BasicPort& port_info,
const bool& must_print_port_size = true);
bool two_verilog_ports_mergeable(const BasicPort& portA,
const BasicPort& portB);

View File

@ -18,31 +18,6 @@
/* begin namespace openfpga */
namespace openfpga {
/***************************************************************************************
* Identify if LUT is used as wiring
* In this case, LUT functions as a buffer
* +------+
* in0 -->|--- |
* | \ |
* in1 -->| --|--->out
* ...
*
* Note that this function judge the LUT operating mode from the input nets and output
* nets that are mapped to inputs and outputs.
* If the output net appear in the list of input nets, this LUT is used as a wire
***************************************************************************************/
static
bool is_wired_lut(const std::vector<AtomNetId>& input_nets,
const AtomNetId& output_net) {
for (const AtomNetId& input_net : input_nets) {
if (input_net == output_net) {
return true;
}
}
return false;
}
/***************************************************************************************
* Create pin rotation map for a LUT
***************************************************************************************/
@ -157,6 +132,13 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb,
std::vector<int> rotated_pin_map = generate_lut_rotated_input_pin_map(input_nets, atom_ctx, atom_blk, device_annotation, circuit_lib, pb_graph_node);
adapt_tt = lut_truth_table_adaption(orig_tt, rotated_pin_map);
VTR_LOGV(verbose, "Driver atom block: '%ld'\n", size_t(atom_blk));
VTR_LOGV(verbose, "Pb atom blocks:");
for (const AtomBlockId& pb_atom_blk : physical_pb.atom_blocks(lut_pb_id)) {
VTR_LOGV(verbose, "'%ld', ", size_t(pb_atom_blk));
}
VTR_LOGV(verbose, "\n");
}
/* Adapt the truth table for fracturable lut implementation and add to physical pb */
@ -184,6 +166,12 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb,
VTR_ASSERT(AtomNetId::INVALID() != output_net);
VTR_LOGV(verbose, "Output net: %s\n", atom_ctx.nlist.net_name(output_net).c_str());
VTR_LOGV(verbose,
"Truth table before adaption to fracturable LUT'\n");
for (const std::string& tt_line : truth_table_to_string(adapt_tt)) {
VTR_LOGV(verbose, "\t%s\n", tt_line.c_str());
}
VTR_LOGV(verbose,
"Add following truth table to pb_graph_pin '%s[%d]'\n",
output_pin->port->name, output_pin->pin_number);

View File

@ -259,13 +259,25 @@ std::vector<int> find_pb_route_remapped_source_pb_pin(const t_pb* pb,
/* Only care the pin has the same parent port as source_pb_pin
* Due to that the source_pb_pin may be swapped during routing
* the pb_route is out-of-date
*
* For those parent port is defined as non-equivalent,
* the source pin and the pin recorded in the routing trace must match!
*
* TODO: should update pb_route by post routing results
* On the other side, the swapping can only happen between equivalent pins
* in a port. So the port must match here!
*/
if (source_pb_pin->port == pb->pb_route.at(pin).pb_graph_pin->port) {
pb_route_indices.push_back(pin);
}
if (PortEquivalence::FULL == source_pb_pin->port->equivalent) {
if (source_pb_pin->port == pb->pb_route.at(pin).pb_graph_pin->port) {
pb_route_indices.push_back(pin);
}
} else {
/* NOTE: INSTANCE is NOT supported! We support only NONE equivalent */
VTR_ASSERT (PortEquivalence::NONE == source_pb_pin->port->equivalent);
if (source_pb_pin == pb->pb_route.at(pin).pb_graph_pin) {
pb_route_indices.push_back(pin);
}
}
}
return pb_route_indices;
@ -695,6 +707,44 @@ void repack_clusters(const AtomContext& atom_ctx,
}
}
/***************************************************************************************
* VPR's packer may create wire LUTs for routing
* Repacker will not remove these wire LUTs
* But repacker may create more wire LUTs for routing
* by exploiting the routability of the physical mode of a programmable block
* This is why this annotation is required
***************************************************************************************/
static
void identify_physical_pb_wire_lut_created_by_repack(VprClusteringAnnotation& cluster_annotation,
const AtomContext& atom_ctx,
const ClusteringContext& cluster_ctx,
const VprDeviceAnnotation& device_annotation,
const CircuitLibrary& circuit_lib,
const bool& verbose) {
vtr::ScopedStartFinishTimer timer("Identify wire LUTs created by repacking");
int wire_lut_counter = 0;
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
PhysicalPb& physical_pb = cluster_annotation.mutable_physical_pb(blk_id);
/* Find the LUT physical pb id */
for (const PhysicalPbId& primitive_pb : physical_pb.primitive_pbs()) {
CircuitModelId circuit_model = device_annotation.pb_type_circuit_model(physical_pb.pb_graph_node(primitive_pb)->pb_type);
VTR_ASSERT(true == circuit_lib.valid_model_id(circuit_model));
if (CIRCUIT_MODEL_LUT != circuit_lib.model_type(circuit_model)) {
continue;
}
/* Reach here, we have a LUT to deal with. Find the wire LUT that mapped to the LUT */
wire_lut_counter += identify_one_physical_pb_wire_lut_created_by_repack(physical_pb, primitive_pb, device_annotation, atom_ctx, circuit_lib, verbose);
}
}
VTR_LOG("Identified %d wire LUTs created by repacker\n",
wire_lut_counter);
}
/***************************************************************************************
* Top-level function to pack physical pb_graph
* This function will do :
@ -712,6 +762,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints,
const CircuitLibrary& circuit_lib,
const bool& verbose) {
/* build the routing resource graph for each logical tile */
@ -726,6 +777,16 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
bitstream_annotation,
design_constraints,
verbose);
/* Annnotate wire LUTs that are ONLY created by repacker!!!
* This is a MUST RUN!
*/
identify_physical_pb_wire_lut_created_by_repack(clustering_annotation,
atom_ctx,
clustering_ctx,
device_annotation,
circuit_lib,
verbose);
}
} /* end namespace openfpga */

View File

@ -10,6 +10,7 @@
#include "vpr_routing_annotation.h"
#include "vpr_bitstream_annotation.h"
#include "repack_design_constraints.h"
#include "circuit_library.h"
/********************************************************************
* Function declaration
@ -25,6 +26,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints,
const CircuitLibrary& circuit_lib,
const bool& verbose);
} /* end namespace openfpga */

View File

@ -505,5 +505,28 @@ std::vector<bool> build_frac_lut_bitstream(const CircuitLibrary& circuit_lib,
return lut_bitstream;
}
/***************************************************************************************
* Identify if LUT is used as wiring
* In this case, LUT functions as a buffer
* +------+
* in0 -->|--- |
* | \ |
* in1 -->| --|--->out
* ...
*
* Note that this function judge the LUT operating mode from the input nets and output
* nets that are mapped to inputs and outputs.
* If the output net appear in the list of input nets, this LUT is used as a wire
***************************************************************************************/
bool is_wired_lut(const std::vector<AtomNetId>& input_nets,
const AtomNetId& output_net) {
for (const AtomNetId& input_net : input_nets) {
if (input_net == output_net) {
return true;
}
}
return false;
}
} /* end namespace openfpga */

View File

@ -39,6 +39,9 @@ std::vector<bool> build_frac_lut_bitstream(const CircuitLibrary& circuit_lib,
const std::map<const t_pb_graph_pin*, AtomNetlist::TruthTable>& truth_tables,
const size_t& default_sram_bit_value);
bool is_wired_lut(const std::vector<AtomNetId>& input_nets,
const AtomNetId& output_net);
} /* end namespace openfpga */
#endif

View File

@ -2,6 +2,8 @@
* Function to perform fundamental operation for the physical pb using
* data structures
***********************************************************************/
#include <algorithm>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
@ -10,6 +12,7 @@
#include "openfpga_tokenizer.h"
#include "openfpga_naming.h"
#include "lut_utils.h"
#include "pb_type_utils.h"
#include "physical_pb_utils.h"
@ -399,4 +402,132 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
}
}
/***************************************************************************************
* This function will identify all the wire LUTs that is created by repacker only
* under a physical pb
*
* A practical example of wire LUT that is created by VPR packer:
*
* LUT
* +------------+
* | |
* netA ---->+----+ |
* | |-------+-----> netC
* netB ---->+----+ |
* | |
* netC ---->+------------+-----> netC
* | |
* +------------+
*
* A fracturable LUT may be mapped to two functions:
* - a function which involves netA, netB and netC
* the function is defined in an atom block atomA
* In this case, netC's driver block in atom context is atomA
* - a function which just wire netC through the LUT
* the function is NOT defined in any atom block
* Such wire LUT is created by VPR's packer
*
* THIS CASE IS WHAT THIS FUNCTION IS HANDLING
* A practical example of wire LUT that is created by repacker:
*
* LUT
* +------------+
* | |
* netA ---->+----+ |
* | |-------+-----> netC
* netB ---->+----+ |
* | |
* netD ---->+------------+-----> netD
* | |
* +------------+
*
* A fracturable LUT may be mapped to two functions:
* - a function which involves netA, netB and netC
* the function is defined in an atom block atomA
* In this case, netC's driver block in atom context is atomA
* - a function which just wire netD through the LUT
* the function is NOT defined in any atom block
* netD is driven by another atom block atomB which is not mapped to the LUT
* Such wire LUT is created by repacker
*
* Return the number of wire LUTs that are found
***************************************************************************************/
int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb,
const PhysicalPbId& lut_pb_id,
const VprDeviceAnnotation& device_annotation,
const AtomContext& atom_ctx,
const CircuitLibrary& circuit_lib,
const bool& verbose) {
int wire_lut_counter = 0;
const t_pb_graph_node* pb_graph_node = physical_pb.pb_graph_node(lut_pb_id);
CircuitModelId lut_model = device_annotation.pb_type_circuit_model(physical_pb.pb_graph_node(lut_pb_id)->pb_type);
VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(lut_model));
/* Find all the nets mapped to each inputs */
std::vector<AtomNetId> input_nets;
for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) {
for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) {
/* Skip the input pin that do not drive by LUT MUXes */
CircuitPortId circuit_port = device_annotation.pb_circuit_port(pb_graph_node->input_pins[iport][ipin].port);
if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) {
continue;
}
input_nets.push_back(physical_pb.pb_graph_pin_atom_net(lut_pb_id, &(pb_graph_node->input_pins[iport][ipin])));
}
}
/* Find all the nets mapped to each outputs */
for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) {
for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) {
const t_pb_graph_pin* output_pin = &(pb_graph_node->output_pins[iport][ipin]);
/* Skip the output ports that are not driven by LUT MUXes */
CircuitPortId circuit_port = device_annotation.pb_circuit_port(output_pin->port);
if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) {
continue;
}
AtomNetId output_net = physical_pb.pb_graph_pin_atom_net(lut_pb_id, output_pin);
/* Bypass unmapped pins */
if (AtomNetId::INVALID() == output_net) {
continue;
}
/* Exclude all the LUTs that
* - have been used as wires
* - the driver atom block of the output_net is part of the atom blocks
* If so, the driver atom block is already mapped to this pb
* and the LUT is not used for wiring
*/
if (true == physical_pb.is_wire_lut_output(lut_pb_id, output_pin)) {
continue;
}
std::vector<AtomBlockId> pb_atom_blocks = physical_pb.atom_blocks(lut_pb_id);
if (pb_atom_blocks.end() != std::find(pb_atom_blocks.begin(), pb_atom_blocks.end(), atom_ctx.nlist.net_driver_block(output_net))) {
continue;
}
/* Bypass the net is NOT routed through the LUT */
if (false == is_wired_lut(input_nets, output_net)) {
continue;
}
/* Print debug info */
VTR_LOGV(verbose,
"Identify physical pb_graph pin '%s.%s[%d]' as wire LUT output created by repacker\n",
output_pin->parent_node->pb_type->name,
output_pin->port->name,
output_pin->pin_number);
/* Label the pins in physical_pb as driven by wired LUT*/
physical_pb.set_wire_lut_output(lut_pb_id, output_pin, true);
wire_lut_counter++;
}
}
return wire_lut_counter;
}
} /* end namespace openfpga */

View File

@ -10,8 +10,10 @@
#include <vector>
#include "physical_types.h"
#include "vpr_device_annotation.h"
#include "vpr_clustering_annotation.h"
#include "vpr_bitstream_annotation.h"
#include "vpr_context.h"
#include "circuit_library.h"
#include "physical_pb.h"
/********************************************************************
@ -33,6 +35,13 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
const VprBitstreamAnnotation& bitstream_annotation,
const bool& verbose);
int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb,
const PhysicalPbId& lut_pb_id,
const VprDeviceAnnotation& device_annotation,
const AtomContext& atom_ctx,
const CircuitLibrary& circuit_lib,
const bool& verbose);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,225 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Team: Virginia Tech Secure Embedded Systems (SES) Lab
// Implementer: Ege Gulcan
//
// Create Date: 17:21:26 11/13/2013
// Design Name:
// Module Name: simon_datapath_shiftreg
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module simon_datapath_shiftreg(clk,data_in,data_rdy,key_in,cipher_out,round_counter,bit_counter);
input clk,data_in,key_in;
input [1:0] data_rdy;
input round_counter;
output cipher_out;
output [5:0] bit_counter;
reg [55:0] shifter1;
reg [63:0] shifter2;
reg shift_in1,shift_in2;
wire shift_out1,shift_out2;
reg shifter_enable1,shifter_enable2;
reg fifo_ff63,fifo_ff62,fifo_ff61,fifo_ff60,fifo_ff59,fifo_ff58,fifo_ff57,fifo_ff56;
reg lut_ff63,lut_ff62,lut_ff61,lut_ff60,lut_ff59,lut_ff58,lut_ff57,lut_ff56;
reg lut_ff_input,fifo_ff_input;
reg lut_rol1,lut_rol2,lut_rol8;
reg s1,s4,s5,s6,s7;
reg [1:0] s3;
reg [5:0] bit_counter;
wire lut_out;
// Shift Register1 FIFO 56x1 Begin
// 56x1 Shift register to store the upper word
always @(posedge clk)
begin
if(shifter_enable1)
begin
shifter1 <= {shift_in1, shifter1[55:1]};
end
end
assign shift_out1 = shifter1[0];
// Shift Register1 End
// Shift Register2 FIFO 64x1 Begin
// 64x1 Shift register to store the lower word
always @(posedge clk)
begin
if(shifter_enable2)
begin
shifter2 <= {shift_in2, shifter2[63:1]};
end
end
assign shift_out2 = shifter2[0];
// Shift Register2 End
// 8 Flip-Flops to store the most significant 8 bits of the upper word at even rounds
// Denoted as Shift Register Up (SRU) in Figure 5
always@(posedge clk)
begin
if(shifter_enable1)
begin
fifo_ff63 <= fifo_ff_input;
fifo_ff62 <= fifo_ff63;
fifo_ff61 <= fifo_ff62;
fifo_ff60 <= fifo_ff61;
fifo_ff59 <= fifo_ff60;
fifo_ff58 <= fifo_ff59;
fifo_ff57 <= fifo_ff58;
fifo_ff56 <= fifo_ff57;
end
end
// 8 Flip-Flops to store the most significant 8 bits of the upper word at odd rounds
// Denoted as Shift Register Down (SRD) in Figure 5
always@(posedge clk)
begin
lut_ff63 <= lut_ff_input;
lut_ff62 <= lut_ff63;
lut_ff61 <= lut_ff62;
lut_ff60 <= lut_ff61;
lut_ff59 <= lut_ff60;
lut_ff58 <= lut_ff59;
lut_ff57 <= lut_ff58;
lut_ff56 <= lut_ff57;
end
// FIFO 64x1 Input MUX
// Input of the lower FIFO is always the output of the upper FIFO
always@(*)
begin
shift_in2 = shift_out1;
end
// FIFO 56x1 Input MUX
// Input of the upper FIFO depends on the select line S1
always@(*)
begin
if(s1==0)
shift_in1 = lut_ff56;
else
shift_in1 = fifo_ff56;
end
// FIFO FF Input MUX
// The input of FIFO_FF can be the input plaintext, output of 56x1 FIFO or the output of LUT
always@(*)
begin
if(s3==0)
fifo_ff_input = data_in;
else if(s3==1)
fifo_ff_input = shift_out1;
else if(s3==2)
fifo_ff_input = lut_out;
else
fifo_ff_input = 1'bx; // Debugging
end
// LUT FF Input MUX
// The input of the LUT_FF is either the output of 56x1 FIFO or the output of LUT
always@(*)
begin
if(s5==0)
lut_ff_input = shift_out1;
else
lut_ff_input = lut_out;
end
// LUT Input MUX
always@(*)
begin
if(s7==0)
lut_rol1 = fifo_ff63;
else
lut_rol1 = lut_ff63;
if(s4==0)
lut_rol2 = fifo_ff62;
else
lut_rol2 = lut_ff62;
if(s6==0)
lut_rol8 = fifo_ff56;
else
lut_rol8 = lut_ff56;
end
//Selection MUX
always@(*)
begin
// For the first 8 bits of each even round OR for all the bits after the first 8 bits in odd rounds OR loading the plaintext
if((round_counter==0 && bit_counter<8)||(round_counter==1 && bit_counter>7)||(data_rdy==1))
s1 = 1;
else
s1 = 0;
if(data_rdy==1) // Loading plaintext
s3 = 0;
else if(round_counter==0) // Even rounds
s3 = 1;
else if(round_counter==1) // Odd rounds
s3 = 2;
else
s3 = 1'bx; // For debugging
if(round_counter==0) // Even rounds
s6 = 0;
else
s6 = 1;
s4 = s6;
s7 = s6;
s5 = ~s6;
end
// SHIFTER ENABLES
// Two shift registers are enabled when the plaintext is being loaded (1) or when the block cipher is running (3)
always@(*)
begin
if(data_rdy==1 || data_rdy==3)
begin
shifter_enable1 = 1;
shifter_enable2 = 1;
end
else
begin
shifter_enable1 = 0;
shifter_enable2 = 0;
end
end
// The bit_counter value is incremented in each clock cycle when the block cipher is running
always@(posedge clk)
begin
if(data_rdy==0)
bit_counter <= 0;
else if(data_rdy==3)
bit_counter <= bit_counter + 1;
else
bit_counter <= bit_counter;
end
// The new computed value
assign lut_out = (lut_rol1 & lut_rol8) ^ shift_out2 ^ lut_rol2 ^ key_in;
// The global output that gives the ciphertext value
assign cipher_out = lut_out;
endmodule

View File

@ -0,0 +1,241 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Team: Virginia Tech Secure Embedded Systems (SES) Lab
// Implementer: Ege Gulcan
//
// Create Date: 16:55:06 11/12/2013
// Design Name:
// Module Name: simon_key_expansion_shiftreg
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module simon_key_expansion_shiftreg(clk,data_in,key_out,data_rdy,bit_counter,round_counter_out);
input clk;
input data_in;
input [1:0] data_rdy;
input [5:0] bit_counter;
output key_out;
output round_counter_out;
reg [59:0] shifter1;
reg [63:0] shifter2;
reg shift_in1,shift_in2;
wire shift_out1,shift_out2;
reg shifter_enable1,shifter_enable2;
reg lut_ff_enable,fifo_ff_enable;
wire lut_out;
reg lut_in3;
reg s2,s3;
reg [1:0] s1;
reg [6:0] round_counter;
reg z_value;
reg fifo_ff0,fifo_ff1,fifo_ff2,fifo_ff3;
//(* shreg_extract = "no" *)
reg lut_ff0,lut_ff1,lut_ff2,lut_ff3;
//Constant value Z ROM
reg [0:67] Z = 68'b10101111011100000011010010011000101000010001111110010110110011101011;
reg c;
/////////////////////////////////////////
//// BEGIN CODE ////////////////////////
///////////////////////////////////////
// Least bit of the round counter is sent to the datapath to check if it is even or odd
assign round_counter_out = round_counter[0];
// Shift Register1 FIFO 60x1 Begin
// 60x1 shift register storing the 60 most significant bits of the upper word of the key
always @(posedge clk)
begin
if(shifter_enable1)
begin
shifter1 <= {shift_in1, shifter1[59:1]};
end
end
assign shift_out1 = shifter1[0];
// Shift Register1 End
// Shift Register2 FIFO 64x1 Begin
// 64x1 shift register storing the lower word of the key
always @(posedge clk)
begin
if(shifter_enable2)
begin
shifter2 <= {shift_in2, shifter2[63:1]};
end
end
assign shift_out2 = shifter2[0];
// Shift Register2 End
// 4 flip-flops storing the least significant 4 bits of the upper word in the first round
always @(posedge clk)
begin
if(fifo_ff_enable)
begin
fifo_ff3 <= shift_out1;
fifo_ff2 <= fifo_ff3;
fifo_ff1 <= fifo_ff2;
fifo_ff0 <= fifo_ff1;
end
end
// 4 flip-flops storing the least significant 4 bits of the upper word after the first round
always@(posedge clk)
begin
if(lut_ff_enable)
begin
lut_ff3 <= lut_out;
lut_ff2 <= lut_ff3;
lut_ff1 <= lut_ff2;
lut_ff0 <= lut_ff1;
end
end
//FIFO 64x1 Input MUX
always@(*)
begin
if(data_rdy==2)
shift_in2 = fifo_ff0;
else if(data_rdy==3 && (round_counter<1 || bit_counter>3))
shift_in2 = fifo_ff0;
else if(data_rdy==3 && bit_counter<4 && round_counter>0)
shift_in2 = lut_ff0;
else
shift_in2 = 1'bx;
end
//LUT >>3 Input MUX
always@(*)
begin
if(s2==0)
lut_in3 = fifo_ff3;
else
lut_in3 = lut_ff3;
end
//FIFO 60x1 Input MUX
always@(*)
begin
if(s1==0)
shift_in1 = fifo_ff0;
else if(s1==1)
shift_in1 = data_in;
else if(s1==2)
shift_in1 = lut_out;
else if(s1==3)
shift_in1 = lut_ff0;
else
shift_in1 = 1'bx;
end
//S2 MUX
always@(*)
begin
if(bit_counter==0 && round_counter!=0)
s2 = 1;
else
s2 = 0;
end
//S1 MUX
always@(*)
begin
if(data_rdy==2)
s1 = 1;
else if(data_rdy==3 && bit_counter<4 && round_counter==0)
s1 = 0;
else if(data_rdy==3 && bit_counter<4 && round_counter>0)
s1 = 3;
else
s1 = 2;
end
// LUT FF ENABLE MUX
// LUT FFs are used only at the first four clock cycles of each round
always@(*)
begin
if(data_rdy==3 && bit_counter<4)
lut_ff_enable = 1;
else
lut_ff_enable = 0;
end
//FIFO FF ENABLE MUX
always@(*)
begin
if(data_rdy==2 || data_rdy==3)
fifo_ff_enable = 1;
else
fifo_ff_enable = 0;
end
//SHIFTER ENABLES
// Shifters are enabled when the key is loaded or block cipher is running
always@(*)
begin
if(data_rdy==2 || data_rdy==3)
shifter_enable1 = 1;
else
shifter_enable1 = 0;
if(data_rdy==2 || data_rdy==3)
shifter_enable2 = 1;
else
shifter_enable2 = 0;
end
//Round Counter
always@(posedge clk)
begin
if(data_rdy==3 && bit_counter==63)
round_counter <= round_counter + 1;
else if(data_rdy==0)
round_counter <= 0;
else
round_counter <= round_counter;
end
// The necessary bit of the constant Z is selected by the round counter
always @(*)
begin
if(bit_counter==0)
z_value = Z[round_counter];
else
z_value = 0;
end
// The value of c is 1 at the first two cycles of each round only
always @(*)
begin
if(bit_counter==0 || bit_counter==1)
c = 0;
else
c = 1;
end
// New computed key bit
assign lut_out = shift_out2 ^ lut_in3 ^ shift_out1 ^ z_value ^ c;
// Output key bit that is connected to the datapath
assign key_out = shift_out2;
endmodule

View File

@ -0,0 +1,45 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Team: Virginia Tech Secure Embedded Systems (SES) Lab
// Implementer: Ege Gulcan
//
// Create Date: 19:14:37 11/13/2013
// Design Name:
// Module Name: top_module
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module Simon_bit_serial_top(clk,data_in,data_rdy,cipher_out);
input clk,data_in;
input [1:0] data_rdy;
output cipher_out;
wire key;
wire [5:0] bit_counter;
wire round_counter_out;
/*
data_rdy=0 -> Reset, Idle
data_rdy=1 -> Load Plaintext
data_rdy=2 -> Load Key
data_rdy=3 -> Run (keep at 3 while the block cipher is running)
*/
simon_datapath_shiftreg datapath(.clk(clk), .data_in(data_in), .data_rdy(data_rdy), .key_in(key),
. cipher_out(cipher_out), .round_counter(round_counter_out), .bit_counter(bit_counter));
simon_key_expansion_shiftreg key_exp(.clk(clk), .data_in(data_in), .data_rdy(data_rdy), .key_out(key), .bit_counter(bit_counter),
.round_counter_out(round_counter_out));
endmodule

View File

@ -0,0 +1,143 @@
/*-------------------------------------------------------------------
CM_FIFO_1x
Communication Manager (CM) FIFO, using 1 RAM block.
18-bit write port (512 deep), 9-bit read port (1024 deep).
The LSB on the write port will be the first byte to appear on
the read port.
Valid data appears on the output data port without first
having to do a pop.
Over-run and under-run protection are both implemented:
reads when empty will be ignored and provide invalid data,
writes when full will be ignored.
-------------------------------------------------------------------*/
`timescale 1ns / 10ps
module CM_FIFO_1x (
rst,
push_clk,
push,
din,
full,
push_flag,
overflow,
pop_clk,
pop,
dout,
empty,
pop_flag,
CM_FIFO_1x_din_o ,
CM_FIFO_1x_push_int_o ,
CM_FIFO_1x_pop_int_o ,
CM_FIFO_1x_push_clk_o ,
CM_FIFO_1x_pop_clk_o ,
CM_FIFO_1x_rst_o ,
CM_FIFO_1x_almost_full_i ,
CM_FIFO_1x_almost_empty_i ,
CM_FIFO_1x_push_flag_i ,
CM_FIFO_1x_pop_flag_i ,
CM_FIFO_1x_dout_i
);
input rst;
input push_clk;
input push;
input [17:0] din;
output full;
output [3:0] push_flag;
output overflow;
input pop_clk;
input pop;
output [8:0] dout;
output empty;
output [3:0] pop_flag;
output [17:0] CM_FIFO_1x_din_o ;
output CM_FIFO_1x_push_int_o ;
output CM_FIFO_1x_pop_int_o ;
output CM_FIFO_1x_push_clk_o ;
output CM_FIFO_1x_pop_clk_o ;
output CM_FIFO_1x_rst_o ;
input CM_FIFO_1x_almost_full_i ;
input CM_FIFO_1x_almost_empty_i ;
input [3:0] CM_FIFO_1x_push_flag_i ;
input [3:0] CM_FIFO_1x_pop_flag_i ;
input [8:0] CM_FIFO_1x_dout_i ;
reg overflow;
wire push_int;
wire pop_int;
reg pop_r1, pop_r2, pop_r3;
// over-run/under-run protection
assign push_int = full ? 1'b0 : push;
// changed to match the current S2 functionality
//assign pop_int = empty ? 1'b0 : pop;
assign pop_int = empty ? 1'b0 : (pop_r2 ^ pop_r3);
assign CM_FIFO_1x_din_o = din;
assign CM_FIFO_1x_push_int_o = push_int;
assign CM_FIFO_1x_pop_int_o = pop_int;
assign CM_FIFO_1x_push_clk_o = push_clk;
assign CM_FIFO_1x_pop_clk_o = pop_clk;
assign CM_FIFO_1x_rst_o = rst;
assign almost_full = CM_FIFO_1x_almost_full_i;
assign almost_empty = CM_FIFO_1x_almost_empty_i;
assign push_flag = CM_FIFO_1x_push_flag_i;
assign pop_flag = CM_FIFO_1x_pop_flag_i;
assign dout = CM_FIFO_1x_dout_i;
assign full = (push_flag == 4'h0);
assign empty = (pop_flag == 4'h0);
// overflow detection
always @(posedge push_clk or posedge rst)
if (rst)
overflow <= 0;
else
if (push && full)
overflow <= 1;
else
overflow <= 0;
/// Synchronize SPI FIFO Read to SPI CLock due to delay
always @(posedge pop_clk or posedge rst)
if (rst) begin
pop_r1 <= 1'b0;
pop_r2 <= 1'b0;
pop_r3 <= 1'b0;
end
else begin
pop_r1 <= pop;
pop_r2 <= pop_r1;
pop_r3 <= pop_r2;
end
endmodule

View File

@ -0,0 +1,152 @@
/*-----------------------------------------------------------------------------
CM_FIFO_autodrain
This module will auto-drain (read from) the CM FIFO when RingBufferMode
is enabled. It will stop on packet boundaries (designated by bit 8 of
the FIFO data).
-----------------------------------------------------------------------------*/
`timescale 1ns / 10ps
module CM_FIFO_autodrain (
input rst,
input FFE_CLK_gclk,
input RingBufferMode,
input [3:0] CM_FIFO_PushFlags,
input CM_FIFO_Empty,
input CM_FIFO_PopFromTLC,
input [8:0] CM_FIFO_ReadData,
output CM_FIFO_Pop,
output busy,
output TP1,
output TP2
);
// state definitions
localparam ST_IDLE = 3'b000;
localparam ST_SETBUSY1 = 3'b001;
localparam ST_SETBUSY2 = 3'b010;
localparam ST_WAIT = 3'b011;
localparam ST_READ = 3'b100;
wire SOP_Marker;
wire FIFO_AutoRead_Threshold;
reg RingBufferMode_r1;
reg RingBufferMode_r2;
reg [2:0] state;
reg busy_reg;
reg CM_FIFO_PopAutoDrain;
assign SOP_Marker = CM_FIFO_ReadData[8];
/* PUSH_FLAG:
0x0: full
0x1: empty
0x2: room for 1/2 to (full - 1)
0x3: room for 1/4 to (1/2 -1)
0x4: room for 64 to (1/4 - 1)
0xA: room for 32 to 63
0xB: room for 16 to 31
0xC: room for 8 to 15
0xD: room for 4 to 7
0xE: room for 2 to 3
0xF: room for 1
others: reserved */
assign FIFO_AutoRead_Threshold = ((CM_FIFO_PushFlags == 4'h0) || (CM_FIFO_PushFlags[3])); // full or (63 or less) 16-bit words
// sync RingBufferMode to the FFE clk
always @(posedge rst or posedge FFE_CLK_gclk)
if (rst) begin
RingBufferMode_r1 <= 0;
RingBufferMode_r2 <= 0;
end
else begin
RingBufferMode_r1 <= RingBufferMode;
RingBufferMode_r2 <= RingBufferMode_r1;
end
// state machine
always @(posedge rst or posedge FFE_CLK_gclk)
if (rst)
state <= ST_IDLE;
else
case (state)
ST_IDLE: if (RingBufferMode_r2)
state <= ST_SETBUSY1;
else
state <= ST_IDLE;
ST_SETBUSY1: state <= ST_SETBUSY2; // allow time for the FIFO read clock to switch safely
ST_SETBUSY2: state <= ST_WAIT;
ST_WAIT: if (!RingBufferMode_r2)
state <= ST_IDLE;
else
state <= ST_READ;
ST_READ: if (SOP_Marker && !RingBufferMode_r2)
state <= ST_SETBUSY1; // goto ST_SETBUSY1 to allow time to switch to SPI_SCLK
else
state <= ST_READ;
endcase
// busy
wire busy_reg_reset;
assign busy_reg_reset = rst || !RingBufferMode;
always @(posedge busy_reg_reset or posedge FFE_CLK_gclk)
if (busy_reg_reset)
busy_reg <= 0;
else
case (busy_reg)
1'b0: if ((state == ST_IDLE) && (RingBufferMode_r2))
busy_reg <= 1;
else
busy_reg <= 0;
1'b1: if (((state == ST_SETBUSY1) && !RingBufferMode_r2) || (state == ST_IDLE))
busy_reg <= 0;
else
busy_reg <= 1;
endcase
// FIFO Read control
always @(*)
if (state == ST_READ) // pop only allowed in ST_READ state...
if (!CM_FIFO_Empty) // ...and FIFO not empty
if (!SOP_Marker) // if not on SOP marker, keep reading
CM_FIFO_PopAutoDrain <= 1;
else // (SOP_Marker)
if (FIFO_AutoRead_Threshold && RingBufferMode_r2) // if SOP marker, read next packet if FIFO is at or past threshold and RingBufferMode still on
CM_FIFO_PopAutoDrain <= 1;
else
CM_FIFO_PopAutoDrain <= 0; // else pop=0
else // (CM_FIFO_Empty)
CM_FIFO_PopAutoDrain <= 0;
else // (state != ST_READ)
CM_FIFO_PopAutoDrain <= 0;
assign CM_FIFO_Pop = busy_reg ? CM_FIFO_PopAutoDrain : CM_FIFO_PopFromTLC;
assign busy = busy_reg;
assign TP1 = FIFO_AutoRead_Threshold;
assign TP2 = 0;
endmodule

View File

@ -0,0 +1,291 @@
// 4k deep CM
// This module bypasses the FFEControlMememoryMux since the addressing of the individual RAM blocks
// is not the same when coming from the TLC vs. FFE, and dynamic code updates must be supported for
// the fabric RAM's.
// Note: in order for this to work correctly, RdClk and WrClk must be the same (tied together externally).
`timescale 1ns / 10ps
`include "ulpsh_rtl_defines.v"
module FFEControlMemory_4k (
// General Interface
input ResetIn,
input SPI_clk,
input TLC_FFE_clk2x_muxed, // already muxed based on UseFastClock from TLC
input MemSelect_en, // MemorySelect and enable from TLC
input [2:0] MemSelect,
input FFE_clock_halfperiod,
input [11:0] Address_TLC, // TLC address is used for both TLC reads and writes
input [35:0] MemoryMux_in,
output [35:0] MemoryMux_out,
//Read Interface
input [11:0] ReadAddress_FFE,
output [35:0] ReadData,
input ReadEnable_TLC,
input ReadEnable_FFE,
//Write Interface
input [35:0] WriteData_TLC,
input WriteEnable_TLC,
// ASSP RAM interface - left bank
output assp_lb_ram0_clk,
output [8:0] assp_lb_ram0_addr,
output [35:0] assp_lb_ram0_wr_data,
input [35:0] assp_lb_ram0_rd_data,
output assp_lb_ram0_wr_en,
output assp_lb_ram0_rd_en,
output [3:0] assp_lb_ram0_wr_be,
// ASSP RAM interface - right bank
output assp_rb_ram1_clk,
output [8:0] assp_rb_ram1_addr,
output [35:0] assp_rb_ram1_wr_data,
input [35:0] assp_rb_ram1_rd_data,
output assp_rb_ram1_wr_en,
output assp_rb_ram1_rd_en,
output [3:0] assp_rb_ram1_wr_be,
// ASSP RAM interface - 8k - left bank
output assp_lb_ram8k_clk,
output [11:0] assp_lb_ram8k_addr,
output [16:0] assp_lb_ram8k_wr_data,
input [16:0] assp_lb_ram8k_rd_data,
output assp_lb_ram8k_wr_en,
output assp_lb_ram8k_rd_en,
output [1:0] assp_lb_ram8k_wr_be,
//AP2
output [8:0] FFEControlMemory_4k_Address_TLC_o ,
output [8:0] FFEControlMemory_4k_ReadAddress_muxed_o ,
output FFEControlMemory_4k_ram5_wr_en_o,
output FFEControlMemory_4k_ram5_rd_en_o,
output FFEControlMemory_4k_SPI_clk_o,
output FFEControlMemory_4k_TLC_FFE_clk2x_muxed_o,
output [35:0] FFEControlMemory_4k_WriteData_TLC_o ,
input [35:0] FFEControlMemory_4k_ram5_rd_data_i ,
output FFEControlMemory_4k_ram4_wr_en_o ,
output FFEControlMemory_4k_ram4_rd_en_o,
input [35:0] FFEControlMemory_4k_ram4_rd_data_i,
output [9:0] FFEControlMemory_4k_fabric_ram1Kx9_addr_o,
output FFEControlMemory_4k_ram1_wr_en_o ,
output FFEControlMemory_4k_ram1_rd_en_o ,
input [8:0] FFEControlMemory_4k_ram1_rd_data_i
);
wire [11:0] ReadAddress_muxed;
wire Select_from_TLC;
wire ram0_wr_en;
wire ram1_wr_en;
wire ram2_wr_en;
wire ram3_wr_en;
wire ram4_wr_en;
wire ram5_wr_en;
wire ram0_rd_en;
wire ram1_rd_en;
wire ram2_rd_en;
wire ram3_rd_en;
wire ram4_rd_en;
wire ram5_rd_en;
wire [11:0] assp_ram8k_addr;
wire [9:0] fabric_ram1Kx9_addr;
wire [16:0] ram0_rd_data;
wire [8:0] ram1_rd_data;
wire [35:0] ram2_rd_data;
wire [35:0] ram3_rd_data;
wire [35:0] ram4_rd_data;
wire [35:0] ram5_rd_data;
reg [35:0] lower2k_rd_data;
reg [16:0] lower2k_rd_data_phase0, lower2k_rd_data_phase1;
reg ReadAddress_muxed_bit0_r1;
reg [2:0] ram_rd_select;
reg [35:0] ram_rd_data;
wire [8:0] assp_ram_addr;
// RAM blocks are arranged as follows:
// RAM 0: 0-2k: 4Kx17 (double-clocked to create the lower 34 bits of each uInstruction)
// RAM 1: 0-2k: 1024x9 (one-half of the 1024x9 word is used for the remaining 2 bits of each uInstruction)
// RAM 2,3: 2k-3k: ASSP RAM's (formerly 0k-1k in the 2k CM)
// RAM 4,5: 3k-4k: fabric RAM's (formerly 1k-2k in the 2k CM)
assign Select_from_TLC = (MemSelect_en && (MemSelect == 3'h0 || MemSelect == 3'h4 || MemSelect == 3'h5));
// memory mux to pass data back to TLC
assign MemoryMux_out = Select_from_TLC ? ReadData : MemoryMux_in;
// mux between the TLC and FFE control signals
assign ReadAddress_muxed = Select_from_TLC ? Address_TLC : ReadAddress_FFE;
assign ReadEnable_muxed = Select_from_TLC ? ReadEnable_TLC : ReadEnable_FFE;
// generate the read address for the 4Kx17 ASSP RAM
assign assp_ram8k_addr = Select_from_TLC ? Address_TLC : {ReadAddress_FFE[10:0], FFE_clock_halfperiod};
/// generate the read address for the 1Kx9 fabric RAM
assign fabric_ram1Kx9_addr = Select_from_TLC ? Address_TLC : ReadAddress_FFE[10:1];
// write enables for each RAM block
// note: fabric RAM's cannot use MemSelect_en since these RAM's may be updated during run-time.
assign ram0_wr_en = (MemSelect_en && MemSelect == 3'h4 && WriteEnable_TLC);
assign ram1_wr_en = (MemSelect_en && MemSelect == 3'h5 && WriteEnable_TLC);
assign ram2_wr_en = (MemSelect_en && MemSelect == 3'h0 && WriteEnable_TLC && Address_TLC[10:9] == 2'b00);
assign ram3_wr_en = (MemSelect_en && MemSelect == 3'h0 && WriteEnable_TLC && Address_TLC[10:9] == 2'b01);
assign ram4_wr_en = ( MemSelect == 3'h0 && WriteEnable_TLC && Address_TLC[10:9] == 2'b10);
assign ram5_wr_en = ( MemSelect == 3'h0 && WriteEnable_TLC && Address_TLC[10:9] == 2'b11);
// read enables for each RAM block
assign ram0_rd_en = (MemSelect_en && MemSelect == 3'h4) ? ReadEnable_TLC : (ReadEnable_FFE && ReadAddress_FFE[11] == 1'b0);
assign ram1_rd_en = (MemSelect_en && MemSelect == 3'h5) ? ReadEnable_TLC : (ReadEnable_FFE && ReadAddress_FFE[11] == 1'b0 && FFE_clock_halfperiod);
assign ram2_rd_en = (MemSelect_en && MemSelect == 3'h0) ? (ReadEnable_TLC && Address_TLC[10:9] == 2'b00) : (ReadEnable_FFE && FFE_clock_halfperiod && ReadAddress_FFE[11:9] == 3'b100 && FFE_clock_halfperiod);
assign ram3_rd_en = (MemSelect_en && MemSelect == 3'h0) ? (ReadEnable_TLC && Address_TLC[10:9] == 2'b01) : (ReadEnable_FFE && FFE_clock_halfperiod && ReadAddress_FFE[11:9] == 3'b101 && FFE_clock_halfperiod);
assign ram4_rd_en = (MemSelect_en && MemSelect == 3'h0) ? (ReadEnable_TLC && Address_TLC[10:9] == 2'b10) : (ReadEnable_FFE && FFE_clock_halfperiod && ReadAddress_FFE[11:9] == 3'b110 && FFE_clock_halfperiod);
assign ram5_rd_en = (MemSelect_en && MemSelect == 3'h0) ? (ReadEnable_TLC && Address_TLC[10:9] == 2'b11) : (ReadEnable_FFE && FFE_clock_halfperiod && ReadAddress_FFE[11:9] == 3'b111 && FFE_clock_halfperiod);
// RAM 5 (fabric)
assign FFEControlMemory_4k_Address_TLC_o[8:0] = Address_TLC[8:0];
assign FFEControlMemory_4k_ReadAddress_muxed_o[8:0] = ReadAddress_muxed[8:0];
assign FFEControlMemory_4k_ram5_wr_en_o = ram5_wr_en ;
assign FFEControlMemory_4k_ram5_rd_en_o = ram5_rd_en;
assign FFEControlMemory_4k_SPI_clk_o = SPI_clk;
assign FFEControlMemory_4k_TLC_FFE_clk2x_muxed_o = TLC_FFE_clk2x_muxed;
assign FFEControlMemory_4k_WriteData_TLC_o = WriteData_TLC;
assign ram5_rd_data = FFEControlMemory_4k_ram5_rd_data_i;
assign FFEControlMemory_4k_ram4_wr_en_o = ram4_wr_en ;
assign FFEControlMemory_4k_ram4_rd_en_o = ram4_rd_en;
assign ram4_rd_data = FFEControlMemory_4k_ram4_rd_data_i;
// mappings to the ASSP RAM's
assign assp_ram_addr = (MemSelect_en && MemSelect == 3'h0) ? Address_TLC[8:0] : ReadAddress_muxed[8:0];
// RAM 3 (ASSP right bank)
// note: the port names are still called "ram1" to maintain compatibility with the 2k CM variant
assign assp_rb_ram1_clk = TLC_FFE_clk2x_muxed;
assign assp_rb_ram1_addr = assp_ram_addr;
assign assp_rb_ram1_wr_data = WriteData_TLC;
assign ram3_rd_data = assp_rb_ram1_rd_data;
assign assp_rb_ram1_wr_en = ram3_wr_en;
assign assp_rb_ram1_rd_en = ram3_rd_en;
assign assp_rb_ram1_wr_be = 4'b1111;
// RAM 2 (ASSP left bank)
// note: the port names are still called "ram0" to maintain compatibility with the 2k CM variant
assign assp_lb_ram0_clk = TLC_FFE_clk2x_muxed;
assign assp_lb_ram0_addr = assp_ram_addr;
assign assp_lb_ram0_wr_data = WriteData_TLC;
assign ram2_rd_data = assp_lb_ram0_rd_data;
assign assp_lb_ram0_wr_en = ram2_wr_en;
assign assp_lb_ram0_rd_en = ram2_rd_en;
assign assp_lb_ram0_wr_be = 4'b1111;
assign FFEControlMemory_4k_fabric_ram1Kx9_addr_o = fabric_ram1Kx9_addr;
assign FFEControlMemory_4k_ram1_wr_en_o = ram1_wr_en ;
assign FFEControlMemory_4k_ram1_rd_en_o = ram1_rd_en;
assign FFEControlMemory_4k_SPI_clk_o = SPI_clk;
assign ram1_rd_data = FFEControlMemory_4k_ram1_rd_data_i;
// RAM 0 (ASSP 8k left bank)
assign assp_lb_ram8k_clk = TLC_FFE_clk2x_muxed;
assign assp_lb_ram8k_addr = assp_ram8k_addr;
assign assp_lb_ram8k_wr_data = WriteData_TLC;
assign ram0_rd_data = assp_lb_ram8k_rd_data;
assign assp_lb_ram8k_wr_en = ram0_wr_en;
assign assp_lb_ram8k_rd_en = ram0_rd_en;
assign assp_lb_ram8k_wr_be = 2'b11;
// latch the 4Kx17 read data
always @(posedge TLC_FFE_clk2x_muxed) begin
if (FFE_clock_halfperiod)
lower2k_rd_data_phase0 <= ram0_rd_data;
if (!FFE_clock_halfperiod)
lower2k_rd_data_phase1 <= ram0_rd_data;
if (FFE_clock_halfperiod)
ReadAddress_muxed_bit0_r1 <= ReadAddress_muxed[0];
end
// assemble the read data for the lower 2k (ram0/ram1)
always @(*)
if (FFE_clock_halfperiod == 0)
if (ReadAddress_muxed_bit0_r1 == 0)
lower2k_rd_data <= {ram1_rd_data[1:0], ram0_rd_data[16:0], lower2k_rd_data_phase0[16:0]};
else
lower2k_rd_data <= {ram1_rd_data[3:2], ram0_rd_data[16:0], lower2k_rd_data_phase0[16:0]};
else
if (ReadAddress_muxed_bit0_r1 == 0)
lower2k_rd_data <= {ram1_rd_data[1:0], lower2k_rd_data_phase1[16:0], lower2k_rd_data_phase0[16:0]};
else
lower2k_rd_data <= {ram1_rd_data[3:2], lower2k_rd_data_phase1[16:0], lower2k_rd_data_phase0[16:0]};
// mux the read data from each RAM block, for the FFE
always @(posedge TLC_FFE_clk2x_muxed)
if (FFE_clock_halfperiod)
ram_rd_select <= ReadAddress_muxed[11:9];
always @(*)
if (MemSelect_en)
// TLC is reading
if (MemSelect == 3'h0)
case (ram_rd_select[1:0])
2'b00: ram_rd_data <= ram2_rd_data;
2'b01: ram_rd_data <= ram3_rd_data;
2'b10: ram_rd_data <= ram4_rd_data;
2'b11: ram_rd_data <= ram5_rd_data;
endcase
else
if (MemSelect == 3'h4)
ram_rd_data <= ram0_rd_data;
else
// assume select=5 to reduce logic
//if (MemSelect == 3'h5)
ram_rd_data <= ram1_rd_data;
//else
// ram_rd_data <= 0;
else
// FFE is reading
if (ram_rd_select[2])
// upper 2k
case(ram_rd_select[1:0])
2'b00: ram_rd_data <= ram2_rd_data;
2'b01: ram_rd_data <= ram3_rd_data;
2'b10: ram_rd_data <= ram4_rd_data;
2'b11: ram_rd_data <= ram5_rd_data;
endcase
else
// lower 2k
ram_rd_data <= lower2k_rd_data;
assign ReadData = ram_rd_data;
endmodule

View File

@ -0,0 +1,38 @@
`timescale 1ns / 10ps
module FFEDataMemoryMux (
input Select,
input [9:0] ReadAddressIn0,
input [9:0] ReadAddressIn1,
output[9:0] ReadAddressOut,
input [9:0] WriteAddressIn0,
input [9:0] WriteAddressIn1,
output[9:0] WriteAddressOut,
input [35:0] DataToMemoryIn0,
input [35:0] DataToMemoryIn1,
output[35:0] DataToMemoryOut,
input [35:0] DataFromMemoryIn0,
input [35:0] DataFromMemoryIn1,
output[35:0] DataFromMemoryOut,
input ReadEnable0,
input ReadEnable1,
output ReadEnable,
input WriteEnable0,
input WriteEnable1,
output WriteEnable
);
assign ReadAddressOut = (Select) ? ReadAddressIn1 : ReadAddressIn0;
assign WriteAddressOut = (Select) ? WriteAddressIn1 : WriteAddressIn0;
assign DataToMemoryOut = (Select) ? DataToMemoryIn1 : DataToMemoryIn0;
assign DataFromMemoryOut = (Select) ? DataFromMemoryIn1 : DataFromMemoryIn0;
assign ReadEnable = (Select) ? ReadEnable1 : ReadEnable0;
assign WriteEnable = (Select) ? WriteEnable1 : WriteEnable0;
endmodule

View File

@ -0,0 +1,476 @@
// -----------------------------------------------------------------------------
// title : FFE_ALU.v
// project : ULP Sensor Hub
// description : 32-bit ALU
// -----------------------------------------------------------------------------
// copyright (c) 2013, QuickLogic Corporation
// -----------------------------------------------------------------------------
// History :
// date version author description
//
// -----------------------------------------------------------------------------
// date version author description
// 10-31-2013 1.1 Anthony Le Add AND function to code
// Details:
// 1. Add new bus signal xT30 as 32-bit for output of AND function
// 2. Assign a temporary 32bit bus to hold the concatenation of MailBox bit:
// Mailbox32bit = {8'b0, MailBox[7:0], 16'h0};
// 3. Add code to perform AND function between Mailbox32bit and xT23
// 4. Add mux function between xT30 and MailBox in using signal[38]
// 5. Expected the Synthesis to remove all unused logics
//
// 11-29-2013 1.2 Anthony Le Add additional comparison functions
// Details:
// 1. Current system supports only three jump functions:
// a. JMP: jump
// b. JMPNEZ: jump when result is not equal to zero
// c. JMPGEZ: jump when result is greater or equal to zero
// 2. Add four more compriason jump functions
// a. JMPEQZ: jump when result is equal to zero
// b. JMPLTZ: jump when result is less than zero
// c. JMPLEZ: jump when result is less than or equal to zero
// d. JMPGTZ: jump when result is greater than zero
// 3. Re-use the three control signals[19:17]
// 4. Use an 8-to-1 mux for JUMP logic
// 5. Update xJumpFlag from wire to reg type
//
//
// -----------------------------------------------------------------------------
`timescale 1ns / 10ps
`include "ulpsh_rtl_defines.v"
module FFE_ALU (
input [31:0] xReadData1,
input [31:0] xReadData2,
input [63:0] signals,
input ClockIn,
input Clock_x2In,
input FFE_clock_halfperiod,
input [15:0] TimeStampIn,
input [31:0] MailboxIn,
input [3:0] SM_InterruptIn,
input MultClockIn,
input [3:0] MultStateIn,
output [8:0] xIndexRegister,
output [31:0] xWriteData,
output reg xJumpFlag,
input Save_BG_registers,
input Restore_BG_registers,
output [31:0] mult_in1,
output [31:0] mult_in2,
output mult_enable,
input [63:0] mult_out
);
wire [31:0] xT0, xT1, xT2;
//wire [31:0] xT3; // defined below, depending on the multiplier implementation
wire [31:0] xT4;
reg [31:0] xT5;
wire [31:0] xT6, xT7, xT8, xT9;
wire [31:0] xT10, xT11, xT12, xT13, xT14, xT15, xT16, xT17, xT18, xT19, xT20, xT21, xT22;
reg [31:0] xT23;
wire [31:0] xT24, xT25;
wire [8:0] xT26, xT27, xT28;
reg [8:0] xT29;
wire [31:0] xT30;
wire signed [31:0] xT12_signed;
wire f0;
reg f2, f5, f2_BG, f5_BG;
wire f3, f6;
reg f2_latched, f2_BG_latched;
reg [31:0] xT5_latched;
reg f5_latched, f5_BG_latched;
reg [8:0] xT29_latched;
// compiler options, from rtl_defines.v
// ENABLE_FFE_F0_EXTENDED_DM
// ENABLE_FFE_F0_SINGLE_DM
// ENABLE_FFE_F0_PROGRAMMABLE_SEG0_OFFSET
// FFE_F0_SEG0_OFFSET [value]
// compiler directives related to CM size:
// ENABLE_FFE_F0_CM_SIZE_2K
// ENABLE_FFE_F0_CM_SIZE_4K
// ENABLE_FFE_F0_CM_SIZE_3K (future support if needed)
// select the multiplier implementation
`define ASSP_MULT
`ifdef FullSingleCycle
wire [63:0] xT3;
wire [63:0] xT1extended, xT2extended;
assign xT1extended[63:0] = { {32{xT1[31]}}, xT1[31:0] };
assign xT2extended[63:0] = { {32{xT2[31]}}, xT2[31:0] };
assign xT3 = xT1extended * xT2extended;
assign xT4 = (xT3 >> 16);
`elsif Handicapped
wire [31:0] xT3;
assign xT3 = xT1 + xT2; // replace multiplier with adder
assign xT4 = xT3;
`elsif MultiCycle
wire [31:0] xT3;
Multiplier Multiplier_1 (
.ClockIn ( MultClockIn ),
.StateIn ( MultStateIn ),
.Arg1In ( xT1 ),
.Arg2In ( xT2 ),
.ResultOut ( xT3 )
);
assign xT4 = xT3;
`elsif ASSP_MULT
wire [63:0] xT3;
assign xT3 = mult_out;
assign xT4 = (xT3 >> 16);
`else
wire [31:0] xT3;
assign xT3 = 0;
assign xT4 = 0;
`endif
// drive the outputs for the ASSP multiplier
assign mult_in1 = xT1;
assign mult_in2 = xT2;
assign mult_enable = signals[5];
assign xT22 = signals[2] ? (xReadData1<<16) : xReadData1;
always @(*)
case (signals[1:0])
2'b00: xT23 <= xReadData2;
2'b01: xT23 <= MailboxIn;
2'b10: xT23 <= {TimeStampIn[15:0], 16'b0};
2'b11: xT23 <= {7'b0, xT29[8:0], 16'b0}; // IndexReg
endcase
assign xT24 = signals[3] ? {12'b0, SM_InterruptIn[3:0], 16'b0} : xT23;
assign xT30 = xReadData1 & xT24;
assign xT9 = signals[38] ? xT30 : xT24;
assign xT21 = xReadData1 | xT24;
assign xT25 = signals[39] ? xT21 : xT9;
assign xT0 = signals[4] ? xT25 : xT22;
assign xT12_signed = xT12;
// remove these muxes to save space
//assign xT1 = signals[5] ? xT0 : xT1; // this mux (latch) keeps the multiplier inputs stable, to save power
//assign xT2 = signals[5] ? xT25 : xT2; // this mux (latch) keeps the multiplier inputs stable, to save power
assign xT1 = xT0;
assign xT2 = xT25;
assign xT7 = signals[5] ? xT4 : xT25;
assign xT10 = signals[8] ? ~xT7 : xT7;
assign xT11 = signals[8] ? 32'b1 : 32'b0;
assign xT13 = signals[9] ? xT7 : xT10;
assign xT6 = signals[6] ? xT22 : xT5;
assign xT8 = signals[7] ? xT6 : 32'b0;
assign xT12 = xT8 + xT10 + xT11;
assign xT14 = (xT12_signed >>> 1);
assign xT16 = signals[11] ? xT14 : xT12;
assign xT19 = signals[12] ? xT16 : xT6;
assign f0 = xT12[31];
// Sign bit
`ifndef ENABLE_FFE_F0_SINGLE_DM
// double DM, default behavior
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod) begin
if (Restore_BG_registers)
f2 <= f2_BG;
else
f2 <= signals[10] ? f0 : f2;
if (Save_BG_registers)
f2_BG <= f2;
else
f2_BG <= f2_BG;
end
end
`else
// 2k CM
always @(posedge ClockIn) begin
if (Restore_BG_registers)
f2 <= f2_BG;
else
f2 <= signals[10] ? f0 : f2;
if (Save_BG_registers)
f2_BG <= f2;
else
f2_BG <= f2_BG;
end
`endif
`else
// single DM
always @(posedge Clock_x2In) begin
if (!FFE_clock_halfperiod) begin
if (Restore_BG_registers)
f2_latched <= f2_BG;
else
f2_latched <= signals[10] ? f0 : f2;
if (Save_BG_registers)
f2_BG_latched <= f2;
else
f2_BG_latched <= f2_BG;
end
end
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod) begin
f2 <= f2_latched;
f2_BG <= f2_BG_latched;
end
end
`else
always @(posedge ClockIn) begin
f2 <= f2_latched;
f2_BG <= f2_BG_latched;
end
`endif
`endif
assign f6 = signals[33] ? (f2) : (f0);
assign f3 = signals[35] ? !f5 : f6;
assign xT15 = (f3) ? xT13 : xT19;
assign xT17 = signals[13] ? xT15 : xT16;
assign xT18 = (xT17 << 1);
assign xT20 = signals[14] ? xT18 : xT17;
assign xWriteData = xT20;
// accumulator
`ifndef ENABLE_FFE_F0_SINGLE_DM
// double DM, default behavior
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod)
xT5 <= signals[16] ? xT20 : xT5;
end
`else
always @(posedge ClockIn) begin
xT5 <= signals[16] ? xT20 : xT5;
end
`endif
`else
// single DM
always @(posedge Clock_x2In) begin
if (!FFE_clock_halfperiod)
xT5_latched <= signals[16] ? xT20 : xT5;
end
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In)
if (FFE_clock_halfperiod)
xT5 <= xT5_latched;
`else
always @(posedge ClockIn)
xT5 <= xT5_latched;
`endif
`endif
// NEZ flag
`ifndef ENABLE_FFE_F0_SINGLE_DM
// double DM, default behavior
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod) begin
if (Restore_BG_registers)
f5 <= f5_BG;
else
f5 <= signals[15] ? f5 : (xT20 != 32'b0);
if (Save_BG_registers)
f5_BG <= f5;
else
f5_BG <= f5_BG;
end
end
`else
always @(posedge ClockIn) begin
if (Restore_BG_registers)
f5 <= f5_BG;
else
f5 <= signals[15] ? f5 : (xT20 != 32'b0);
if (Save_BG_registers)
f5_BG <= f5;
else
f5_BG <= f5_BG;
end
`endif
`else
// single DM
always @(posedge Clock_x2In) begin
if (!FFE_clock_halfperiod) begin
if (Restore_BG_registers)
f5_latched <= f5_BG;
//f5_latched <= f5_BG_latched;
else
f5_latched <= signals[15] ? f5 : (xT20 != 32'b0);
//f5_latched <= signals[15] ? f5_latched : (xT20 != 32'b0);
if (Save_BG_registers)
f5_BG_latched <= f5;
//f5_BG_latched <= f5_latched;
else
f5_BG_latched <= f5_BG;
//f5_BG_latched <= f5_BG_latched;
end
end
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod) begin
f5 <= f5_latched;
f5_BG <= f5_BG_latched;
end
end
`else
always @(posedge ClockIn) begin
f5 <= f5_latched;
f5_BG <= f5_BG_latched;
end
`endif
`endif
always @(*)
begin
case ({signals[19], signals[18], signals[17]})
3'b000: xJumpFlag = 1'b0; // no jump
3'b001: xJumpFlag = 1'b1; // JMP (unconditional jump)
3'b010: xJumpFlag = f5; // JMPNEZ (jump if NEZflag)
3'b011: xJumpFlag = !f5; // JMPEQZ (jump if !NEZflag)
3'b100: xJumpFlag = !f2; // JMPGEZ (jump if !SignBit)
3'b101: xJumpFlag = f2; // JMPLTZ (jump if SignBit)
3'b110: xJumpFlag = !(!f2 && f5); // JMPLEZ (jump if SignBit or !NEZflag)
3'b111: xJumpFlag = !f2 && f5; // JMPGTZ (jump if !SignBit and NEZflag)
default: xJumpFlag = 1'b0;
endcase
end
// Index register code
assign xT26 = xT29 + 1;
assign xT27 = signals[24] ? xT26 : 9'b0;
assign xT28 = signals[26] ? xT20[24:16] : xT27; // assign the integer portion of xT20, or xT27
// Index Register
`ifndef ENABLE_FFE_F0_SINGLE_DM
// double DM, default behavior
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod) begin
if (signals[25])
xT29 <= xT28;
else
xT29 <= xT29;
end
end
`else
always @(posedge ClockIn) begin
if (signals[25])
xT29 <= xT28;
else
xT29 <= xT29;
end
`endif
`else
// single DM
always @(posedge Clock_x2In) begin
if (!FFE_clock_halfperiod) begin
if (signals[25])
xT29_latched <= xT28;
else
xT29_latched <= xT29;
end
end
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In)
if (FFE_clock_halfperiod)
xT29 <= xT29_latched;
`else
always @(posedge ClockIn)
xT29 <= xT29_latched;
`endif
`endif
assign xIndexRegister = xT29;
// prevent logic duplication
//pragma attribute xT0 preserve_driver true
//pragma attribute xT1 preserve_driver true
//pragma attribute xT2 preserve_driver true
//pragma attribute xT3 preserve_driver true
//pragma attribute xT4 preserve_driver true
//pragma attribute xT5 preserve_driver true
//pragma attribute xT6 preserve_driver true
//pragma attribute xT7 preserve_driver true
//pragma attribute xT8 preserve_driver true
//pragma attribute xT9 preserve_driver true
//pragma attribute xT10 preserve_driver true
//pragma attribute xT11 preserve_driver true
//pragma attribute xT12 preserve_driver true
//pragma attribute xT13 preserve_driver true
//pragma attribute xT14 preserve_driver true
//pragma attribute xT15 preserve_driver true
//pragma attribute xT16 preserve_driver true
//pragma attribute xT17 preserve_driver true
//pragma attribute xT18 preserve_driver true
//pragma attribute xT19 preserve_driver true
//pragma attribute xT20 preserve_driver true
//pragma attribute xT20 preserve_driver true
//pragma attribute xT21 preserve_driver true
//pragma attribute xT22 preserve_driver true
//pragma attribute xT23 preserve_driver true
//pragma attribute xT24 preserve_driver true
//pragma attribute xT25 preserve_driver true
//pragma attribute xT26 preserve_driver true
//pragma attribute xT27 preserve_driver true
//pragma attribute xT28 preserve_driver true
//pragma attribute xT29 preserve_driver true
//pragma attribute xT30 preserve_driver true
//pragma attribute xT12_signed preserve_driver true
//pragma attribute f0 preserve_driver true
//pragma attribute f2 preserve_driver true
//pragma attribute f5 preserve_driver true
//pragma attribute f3 preserve_driver true
//pragma attribute f6 preserve_driver true
endmodule

View File

@ -0,0 +1,964 @@
/* -----------------------------------------------------------------------------
title : FlexFusionEngine Control
project : Jim-Bob Hardware Sensor Hub
-----------------------------------------------------------------------------
platform : Alabama test chip
standard : Verilog 2001
-----------------------------------------------------------------------------
description: Module for controlling the FlexFusionEngine
-----------------------------------------------------------------------------
copyright (c) 2013, QuickLogic Corporation
-----------------------------------------------------------------------------
History :
Date Version Author Description
2013/03/21 1.0 Jason Lew Created
2013/05/02 1.1 Jason Lew Migrated from FFEAT v21d
2013/06/14 1.2 Randy O. Corrected assignment to DataMemReadAddr's b/c it wasn't using IndexReg properly.
Corrected assignment to MemReadData's b/c it shouldn't use IndexReg.
2013/06/26 1.3 Randy O. Made the Signals bus 64 bits wide instead of 32, since it needs to be at least as wide as the one in microopdecodes.v
2013/07/01 1.4 Randy O. Cosmetic changes to improve readability.
Removed DataMem1WriteData_int & DataMem2WriteData_int since they were unused.
2013/07/08 1.5 Randy O. Added unit delays to aid in functional sim.
2014/05/21 1.6 Glen G. Added ability to read/write expanded Sensor Manager Memory
-----------------------------------------------------------------------------
Comments: This solution is specifically for implementing into the Alabama
test chip. Verification will be done using the Jim-Bob Sensor Board
------------------------------------------------------------------------------*/
`include "ulpsh_rtl_defines.v"
`timescale 1ns / 10ps
module FFE_Control ( // named RunFlexFusionEngine in C source
input ClockIn,
input Clock_x2In,
input ResetIn,
input StartIn,
output StartSMOut,
input [15:0] TimeStampIn,
input [31:0] MailboxIn,
input [3:0] SM_InterruptIn,
output [11:0] ControlMemAddressOut,
output reg ControlMemReadEnableOut,
output [9:0] SensorMemReadAddressOut, // Expanded for Rel 0 on 6/18
output SensorMemReadEnableOut,
output [9:0] SensorMemWriteAddressOut, // New for Rel 0 on 6/18
output SensorMemWriteEnableOut, // New for Rel 0 on 6/18
input [35:0] ControlMemDataIn,
input [35:0] Mem1ReadData,
input [35:0] Mem2ReadData,
input [17:0] SensorMemReadDataIn,
input SensorMemBusyIn,
output [8:0] SensorMemWriteDataOut, // New for Rel 0 on 6/18
output BusyOut,
output DataMem1ReadEnable,
output DataMem2ReadEnable,
output DataMem1WriteEnable,
output DataMem2WriteEnable,
output [9:0] DataMem1ReadAddressOut,
output [9:0] DataMem1WriteAddressOut,
output [35:0] DataMem1WriteDataOut,
output [9:0] DataMem2ReadAddressOut,
output [9:0] DataMem2WriteAddressOut,
output [35:0] DataMem2WriteDataOut,
output reg FFE_clock_halfperiod,
input MultClockIn,
input [3:0] MultStateIn,
// Status data
input SMBusyIn,
output reg SMOverrunOut,
// CM FIFO controls
output [17:0] CMWriteDataOut,
output CMWriteEnableOut,
output [7:0] InterruptMsgOut,
// interface to ASSP multiplier
output [31:0] mult_in1,
output [31:0] mult_in2,
output mult_enable,
input [63:0] mult_out,
output TP1,
output TP2,
output TP3
);
// compiler directives related to CM size:
// ENABLE_FFE_F0_CM_SIZE_2K
// ENABLE_FFE_F0_CM_SIZE_4K
// ENABLE_FFE_F0_CM_SIZE_3K (future support if needed)
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
reg [11:0] xPC;
wire [11:0] xJumpAddress;
reg [11:0] PC_BG;
`else
// 2k CM (3k CM support may be added in the future)
reg [10:0] xPC;
wire [10:0] xJumpAddress;
reg [10:0] PC_BG;
`endif
reg BusyOut_reg, BusyOut_r1;
reg Start_r1, Start_r2, Start_r3;
wire [31:0] Mem1ReadDataToALU;
wire [31:0] Mem2ReadDataToALU;
wire [8:0] MicroOpCode;
wire [63:0] Signals; // the width of Signals is defined to be way larger than it needs to be (today), extra bits should get optimized out.
wire [8:0] xIndexRegister;
wire [31:0] xWriteData;
wire xJumpFlag;
wire [35:0] Mem1ReadDataX;
wire [35:0] Mem2ReadDataX;
reg [7:0] InterruptMsg_reg;
reg StartSM_reg;
reg [15:0] TimeStamp_r1, TimeStamp_r2, TimeStamp_synced;
reg f5_BG;
reg f2_BG;
reg BGcontinue_pending;
reg BGsave_pending;
reg BGstop_pending;
reg BG_active;
reg Start_pending;
wire Start_detected;
wire Save_BG_registers;
wire Restore_BG_registers;
wire Clear_PC;
wire Disable_DataMem_WrEn;
reg [2:0] Thread_switch_cnt;
parameter [2:0] THREAD_SWITCH_CNT_DONE = 3'b111;
// standard-depth DM addresses (9 bits)
wire [8:0] DataMem1ReadAddressOut_std;
wire [8:0] DataMem1WriteAddressOut_std;
wire [8:0] DataMem2ReadAddressOut_std;
wire [8:0] DataMem2WriteAddressOut_std;
wire [9:0] DataMem1WriteAddressOut_trans;
wire [9:0] DataMem2WriteAddressOut_trans;
wire [9:0] DataMem1ReadAddressOut_trans;
wire [9:0] DataMem2ReadAddressOut_trans;
reg [9:0] DataMem2ReadAddressOut_trans_hold;
reg DataMem1ReadAddressOut_trans_MSB_r1;
wire [9:0] DataMem1WriteAddressOut_mux;
wire [9:0] DataMem1ReadAddressOut_mux;
wire DataMem1ReadEnable_mux;
wire DataMem1WriteEnable_mux;
wire [9:0] DataMem1WriteAddressOut_split;
wire [9:0] DataMem2WriteAddressOut_split;
wire [9:0] DataMem1ReadAddressOut_split;
wire [9:0] DataMem2ReadAddressOut_split;
wire DataMem1ReadEnable_split;
wire DataMem1WriteEnable_split;
wire DataMem2ReadEnable_split;
wire DataMem2WriteEnable_split;
//reg FFE_clock_halfperiod;
wire DataMem1ReadEnable_std;
wire DataMem2ReadEnable_std;
reg DataMem2ReadEnable_std_hold;
wire DataMem1WriteEnable_std;
wire DataMem2WriteEnable_std;
reg [31:0] Mem1ReadData_latched;
reg [31:0] Mem2ReadData_latched;
wire ClockIn_dly1;
wire ClockIn_dly2;
wire ClockIn_dly3;
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
reg SensorMemReadEnable_reg;
reg SensorMemWriteEnable_reg;
reg [9:0] SensorMemReadAddress_reg;
reg [9:0] SensorMemWriteAddress_reg;
reg CMWriteEnable_reg;
`endif
// compiler options, from rtl_defines.v
// ENABLE_FFE_F0_EXTENDED_DM
// ENABLE_FFE_F0_SINGLE_DM
// ENABLE_FFE_F0_PROGRAMMABLE_SEG0_OFFSET
// FFE_F0_SEG0_OFFSET [value]
`ifdef FFE_F0_SEG0_OFFSET
parameter [8:0] Segment0_offset = `FFE_F0_SEG0_OFFSET;
`endif
`ifdef ENABLE_FFE_F0_EXTENDED_DM
reg [9:0] CurrentSegment_offset;
reg DataMem2ReadAddress_MSB_r1;
`endif
`ifdef ENABLE_FFE_F0_SINGLE_DM
reg [31:16] WriteData_latched;
reg sig37_latched;
`endif
// sync the timestamp to this clock domain
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
`else
always @(posedge ClockIn) begin
`endif
TimeStamp_r1 <= TimeStampIn;
TimeStamp_r2 <= TimeStamp_r1;
if (TimeStamp_r1 == TimeStamp_r2)
TimeStamp_synced <= TimeStamp_r2;
else
TimeStamp_synced <= TimeStamp_synced;
end
FFE_ALU u_FFE_ALU (
.xReadData1 ( Mem1ReadDataToALU[31:0] ),
.xReadData2 ( Mem2ReadDataToALU[31:0] ),
.signals ( Signals ),
.ClockIn ( ClockIn ),
.Clock_x2In ( Clock_x2In ),
.FFE_clock_halfperiod ( FFE_clock_halfperiod ),
.MultClockIn ( MultClockIn ),
.MultStateIn ( MultStateIn ),
.TimeStampIn ( TimeStamp_synced ),
.MailboxIn ( MailboxIn ),
.SM_InterruptIn ( SM_InterruptIn ),
.xIndexRegister ( xIndexRegister ),
.xWriteData ( xWriteData ),
.xJumpFlag ( xJumpFlag ),
.Save_BG_registers ( Save_BG_registers ),
.Restore_BG_registers ( Restore_BG_registers ),
.mult_in1 ( mult_in1 ),
.mult_in2 ( mult_in2 ),
.mult_enable ( mult_enable ),
.mult_out ( mult_out )
);
decodeMicroOpCode U_decodeMicroOpCode (
.MicroOpCode ( MicroOpCode ),
.Signals ( Signals )
);
// Fetch Micro OpCode from Control Memory
// then needs to be decoded for the various control signals to the ALU (these are called 'signals')
assign MicroOpCode = BusyOut_reg ? ControlMemDataIn[8:0] : 9'b0; // xMicroOpCode (hold at zero if FFE is not running because of single port ASSP RAMs
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
assign xJumpAddress = ControlMemDataIn[20:9];
`else
// 2k CM
assign xJumpAddress = ControlMemDataIn[19:9];
`endif
// standard (legacy) control/address signals for the DM's
assign DataMem1ReadEnable_std = Signals[20];
assign DataMem2ReadEnable_std = Signals[21];
assign DataMem1WriteEnable_std = Disable_DataMem_WrEn ? 1'b0 : (Signals[22] && BusyOut_reg);
assign DataMem2WriteEnable_std = Disable_DataMem_WrEn ? 1'b0 : (Signals[23] && BusyOut_reg);
assign DataMem1WriteAddressOut_std = Signals[34] ? (ControlMemDataIn[17:9] + xIndexRegister) : ControlMemDataIn[17:9];
assign DataMem2WriteAddressOut_std = Signals[34] ? (ControlMemDataIn[17:9] + xIndexRegister) : ControlMemDataIn[17:9];
assign DataMem1ReadAddressOut_std = Signals[28] ? (ControlMemDataIn[26:18] + xIndexRegister) : ControlMemDataIn[26:18];
assign DataMem2ReadAddressOut_std = Signals[29] ? (ControlMemDataIn[35:27] + xIndexRegister) : ControlMemDataIn[35:27];
// translate DM read/write addresses if an extended-length DM is specified
`ifdef ENABLE_FFE_F0_EXTENDED_DM
// extended-length DM
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
CurrentSegment_offset <= 0;
else
if (Signals[44] && FFE_clock_halfperiod) // seg_offset being written
CurrentSegment_offset <= ControlMemDataIn[32:23];
`else
always @(posedge ClockIn or posedge ResetIn)
if (ResetIn)
CurrentSegment_offset <= 0;
else
if (Signals[44]) // seg_offset being written
CurrentSegment_offset <= ControlMemDataIn[32:23];
`endif
// translate addresses to handle extended data memory(ies)
assign DataMem1WriteAddressOut_trans = (DataMem1WriteAddressOut_std < Segment0_offset) ?
{1'b0, DataMem1WriteAddressOut_std[8:0]} :
({1'b0, DataMem1WriteAddressOut_std} + {1'b0, CurrentSegment_offset});
assign DataMem2WriteAddressOut_trans = (DataMem2WriteAddressOut_std < Segment0_offset) ?
{1'b0, DataMem2WriteAddressOut_std[8:0]} :
({1'b0, DataMem2WriteAddressOut_std} + {1'b0, CurrentSegment_offset});
assign DataMem1ReadAddressOut_trans = (DataMem1ReadAddressOut_std < Segment0_offset) ?
{1'b0, DataMem1ReadAddressOut_std[8:0]} :
({1'b0, DataMem1ReadAddressOut_std} + {1'b0, CurrentSegment_offset});
assign DataMem2ReadAddressOut_trans = (DataMem2ReadAddressOut_std < Segment0_offset) ?
{1'b0, DataMem2ReadAddressOut_std[8:0]} :
({1'b0, DataMem2ReadAddressOut_std} + {1'b0, CurrentSegment_offset});
`else
// standard-length DM (could be single or double)
assign DataMem1WriteAddressOut_trans = {1'b0, DataMem1WriteAddressOut_std};
assign DataMem2WriteAddressOut_trans = {1'b0, DataMem2WriteAddressOut_std};
assign DataMem1ReadAddressOut_trans = {1'b0, DataMem1ReadAddressOut_std};
assign DataMem2ReadAddressOut_trans = {1'b0, DataMem2ReadAddressOut_std};
`endif
// mux the DM1/DM2 addresses into a single logical DM1 address if a single-DM design is specified
`ifdef ENABLE_FFE_F0_SINGLE_DM
// single DM
// keep track of the half-period (0 or 1) within a single FFE clock, by using the 2x FFE clock.
// FFE_clock_halfperiod should be 0 when the 1x clock is low, 1 when the 1x clock is high (it's registered here to help eliminate timing issues).
buff buff_clockin_dly1 (.A(ClockIn), .Q(ClockIn_dly1));
buff buff_clockin_dly2 (.A(ClockIn_dly1), .Q(ClockIn_dly2));
buff buff_clockin_dly3 (.A(ClockIn_dly2), .Q(ClockIn_dly3));
//pragma attribute buff_clockin_dly1 dont_touch true
//pragma attribute buff_clockin_dly2 dont_touch true
//pragma attribute buff_clockin_dly3 dont_touch true
assign #3 ClockIn_dly4 = ClockIn_dly3;
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
FFE_clock_halfperiod <= 0;
else
FFE_clock_halfperiod <= #1 ClockIn_dly4;
/*
if (BusyOut_reg)
FFE_clock_halfperiod <= !FFE_clock_halfperiod;
else
FFE_clock_halfperiod <= 0;
*/
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn) begin
DataMem2ReadAddressOut_trans_hold <= 0;
DataMem2ReadEnable_std_hold <= 0;
end
else begin
if (!FFE_clock_halfperiod) begin
DataMem2ReadAddressOut_trans_hold <= DataMem2ReadAddressOut_trans;
DataMem2ReadEnable_std_hold <= DataMem2ReadEnable_std;
end
end
// on half-period 0, drive the DM1 read address and read enable
// on half-period 1, drive the DM2 read address and read enable
// drive the write address on both half-periods, and the write enable on half-period 0
assign DataMem1ReadAddressOut_mux = FFE_clock_halfperiod ? DataMem2ReadAddressOut_trans_hold : DataMem1ReadAddressOut_trans;
assign DataMem1ReadEnable_mux = FFE_clock_halfperiod ? DataMem2ReadEnable_std_hold : DataMem1ReadEnable_std;
assign DataMem1WriteAddressOut_mux = DataMem1WriteAddressOut_trans; // note: DM1 write address = DM2 write address
assign DataMem1WriteEnable_mux = FFE_clock_halfperiod ? 0 : DataMem1WriteEnable_std;
`else
// double DM
// FFE_clock_halfperiod should never be used in this case. Assign it to 0.
always @(*)
FFE_clock_halfperiod <= 0;
`endif
// split the muxed RAM control signals across both physical memories if an extended-depth DM is specified.
// (if an extended-depth DM is specified, it must also be a single DM)
`ifdef ENABLE_FFE_F0_EXTENDED_DM
// extended-length DM
// note that the DM2 "_mux" signals are not defined, since it's assumed that an extended-length DM is also a single-DM
assign DataMem1ReadAddressOut_split = DataMem1ReadAddressOut_mux;
assign DataMem1ReadEnable_split = (DataMem1ReadAddressOut_mux[9] == 1'b0) ? DataMem1ReadEnable_mux : 1'b0;
assign DataMem1WriteAddressOut_split = DataMem1WriteAddressOut_mux;
// assign DataMem1WriteEnable_split = (DataMem1WriteAddressOut_mux[9] == 1'b0) ? DataMem1WriteEnable_split : 1'b0; // original
assign DataMem1WriteEnable_split = (DataMem1WriteAddressOut_mux[9] == 1'b0) ? DataMem1WriteEnable_mux : 1'b0; // Anthony Le 11-01-2014
assign DataMem2ReadAddressOut_split = DataMem1ReadAddressOut_mux;
assign DataMem2ReadEnable_split = (DataMem1ReadAddressOut_mux[9] == 1'b1) ? DataMem1ReadEnable_mux : 1'b0;
assign DataMem2WriteAddressOut_split = DataMem1WriteAddressOut_mux;
// assign DataMem2WriteEnable_split = (DataMem1WriteAddressOut_mux[9] == 1'b1) ? DataMem1WriteEnable_split : 1'b0; // original
assign DataMem2WriteEnable_split = (DataMem1WriteAddressOut_mux[9] == 1'b1) ? DataMem1WriteEnable_mux : 1'b0; // Anthony Le 11-01-2014
`endif
// drive the outputs for the DM control/address
`ifdef ENABLE_FFE_F0_EXTENDED_DM
// extended-length DM (must be single DM as well)
// must use the translated then muxed then split signals...
assign DataMem1ReadEnable = DataMem1ReadEnable_split;
assign DataMem1WriteEnable = DataMem1WriteEnable_split;
assign DataMem1WriteAddressOut = DataMem1WriteAddressOut_split;
assign DataMem1ReadAddressOut = DataMem1ReadAddressOut_split;
assign DataMem2ReadEnable = DataMem2ReadEnable_split;
assign DataMem2WriteEnable = DataMem2WriteEnable_split;
assign DataMem2WriteAddressOut = DataMem2WriteAddressOut_split;
assign DataMem2ReadAddressOut = DataMem2ReadAddressOut_split;
`else
// standard-length DM
`ifdef ENABLE_FFE_F0_SINGLE_DM
// standard-length single DM
// must use the non-translated then muxed signals
// note that physical DM2 is unused, so those outputs are grounded.
assign DataMem1ReadEnable = DataMem1ReadEnable_mux;
assign DataMem1WriteEnable = DataMem1WriteEnable_mux;
assign DataMem1WriteAddressOut = DataMem1WriteAddressOut_mux;
assign DataMem1ReadAddressOut = DataMem1ReadAddressOut_mux;
assign DataMem2ReadEnable = 0;
assign DataMem2WriteEnable = 0;
assign DataMem2WriteAddressOut = 0;
assign DataMem2ReadAddressOut = 0;
`else
// standard-length double DM (legacy)
// use the standard signals
assign DataMem1WriteAddressOut = {1'b0, DataMem1WriteAddressOut_std};
assign DataMem2WriteAddressOut = {1'b0, DataMem2WriteAddressOut_std};
assign DataMem1ReadAddressOut = {1'b0, DataMem1ReadAddressOut_std};
assign DataMem2ReadAddressOut = {1'b0, DataMem2ReadAddressOut_std};
assign DataMem1ReadEnable = DataMem1ReadEnable_std;
assign DataMem2ReadEnable = DataMem2ReadEnable_std;
assign DataMem1WriteEnable = DataMem1WriteEnable_std;
assign DataMem2WriteEnable = DataMem2WriteEnable_std;
`endif
`endif
`ifdef ENABLE_FFE_F0_SINGLE_DM
// single DM, extended or standard length
// hold the write data so it can be written to the CM FIFO or SM Mem correctly, when a single DM is used
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn) begin
WriteData_latched <= 0;
sig37_latched <= 0;
end
else begin
if (!FFE_clock_halfperiod) begin
sig37_latched <= Signals[37];
//if (!FFE_clock_halfperiod && (CMWriteEnableOut || SensorMemWriteEnableOut || Signals[36]))
if (Signals[30] || Signals[40] || Signals[36]) // CM write or SM write or Interrupt msg write
WriteData_latched <= xWriteData[31:16];
end
end
//assign CMWriteDataOut = {1'b0, WriteData_latched[31:24], Signals[37], WriteData_latched[23:16]};
assign CMWriteDataOut = {1'b0, WriteData_latched[31:24], sig37_latched, WriteData_latched[23:16]};
assign SensorMemWriteDataOut = WriteData_latched[24:16];
`else
// double DM (legacy)
assign CMWriteDataOut = {1'b0, xWriteData[31:24], Signals[37], xWriteData[23:16]};
assign SensorMemWriteDataOut = xWriteData[24:16];
`endif
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
// this is done to make sure that all of these signals are stable when the 1x clock occurs.
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn) begin
SensorMemReadEnable_reg <= 0;
SensorMemWriteEnable_reg <= 0;
SensorMemReadAddress_reg <= 0;
SensorMemWriteAddress_reg <= 0;
CMWriteEnable_reg <= 0;
end
else begin
if (!FFE_clock_halfperiod ) begin
SensorMemReadEnable_reg <= DataMem1ReadEnable_std;
SensorMemWriteEnable_reg <= Disable_DataMem_WrEn ? 1'b0 : (Signals[40] && BusyOut_reg);
SensorMemReadAddress_reg <= Signals[28] ? (ControlMemDataIn[27:18] + xIndexRegister) : ControlMemDataIn[27:18];
SensorMemWriteAddress_reg <= Signals[34] ? (ControlMemDataIn[18:9] + xIndexRegister) : ControlMemDataIn[18:9];
CMWriteEnable_reg <= Disable_DataMem_WrEn ? 1'b0 : (Signals[30] && BusyOut_reg); // Write enable to CM FIFO
end
end
assign SensorMemReadEnableOut = SensorMemReadEnable_reg;
assign SensorMemWriteEnableOut = SensorMemWriteEnable_reg;
assign SensorMemReadAddressOut = SensorMemReadAddress_reg;
assign SensorMemWriteAddressOut = SensorMemWriteAddress_reg;
assign CMWriteEnableOut = CMWriteEnable_reg;
`else
// 2k CM
assign SensorMemReadEnableOut = DataMem1ReadEnable_std;
assign SensorMemWriteEnableOut = Disable_DataMem_WrEn ? 1'b0 : (Signals[40] && BusyOut_reg);
assign SensorMemReadAddressOut = (Signals[28] ? (ControlMemDataIn[27:18] + xIndexRegister) : ControlMemDataIn[27:18]);
assign SensorMemWriteAddressOut = Signals[34] ? (ControlMemDataIn[18:9] + xIndexRegister) : ControlMemDataIn[18:9];
assign CMWriteEnableOut = Disable_DataMem_WrEn ? 1'b0 : (Signals[30] && BusyOut_reg); // Write enable to CM FIFO
`endif
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
assign ControlMemAddressOut = xPC;
`else
// 2k CM
assign ControlMemAddressOut = {1'b0, xPC};
`endif
assign DataMem1WriteDataOut = {4'b0000,xWriteData};
assign DataMem2WriteDataOut = {4'b0000,xWriteData};
// latch the read data from the DM(s)
`ifdef ENABLE_FFE_F0_SINGLE_DM
`ifdef ENABLE_FFE_F0_EXTENDED_DM
// extended-length single-DM
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
DataMem1ReadAddressOut_trans_MSB_r1 <= 0;
else
if (!FFE_clock_halfperiod)
DataMem1ReadAddressOut_trans_MSB_r1 <= DataMem1ReadAddressOut_trans[9];
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
Mem1ReadData_latched <= 0;
else
if (FFE_clock_halfperiod)
Mem1ReadData_latched <= DataMem1ReadAddressOut_trans_MSB_r1 ? Mem2ReadData : Mem1ReadData; // read from the correct physical DM
// store the (logical) DM2 read address' MSB, so it can be used on the following clock to select the correct physical DM
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
DataMem2ReadAddress_MSB_r1 <= 0;
else
if (FFE_clock_halfperiod)
DataMem2ReadAddress_MSB_r1 <= DataMem2ReadAddressOut_trans[9];
`else
always @(posedge ClockIn or posedge ResetIn)
if (ResetIn)
DataMem2ReadAddress_MSB_r1 <= 0;
else
DataMem2ReadAddress_MSB_r1 <= DataMem2ReadAddressOut_trans[9];
`endif
always @(*)
Mem2ReadData_latched <= DataMem2ReadAddress_MSB_r1 ? Mem2ReadData : Mem1ReadData; // read from the correct physical DM
// note that Mem2ReadData_latched will only be valid on the first half-period
// note that ReadData2 can be registered as well, to make FFE clock-to-clock timing easier (at the cost of more FFs).
`else
// standard-length single-DM, latch & hold at the appropriate half-periods
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
Mem1ReadData_latched <= 0;
else
if (FFE_clock_halfperiod)
Mem1ReadData_latched <= Mem1ReadData;
else
Mem1ReadData_latched <= Mem1ReadData_latched;
always @(*)
Mem2ReadData_latched <= Mem1ReadData;
// note that ReadData2 can be registered as well, to make FFE clock-to-clock timing easier (at the cost of more FFs).
`endif
`else
// standard-length double-DM, pass-thru
always @(*) begin
Mem1ReadData_latched <= Mem1ReadData;
Mem2ReadData_latched <= Mem2ReadData;
end
`endif
assign Mem1ReadDataX = Mem1ReadData_latched[31:0];
//a mux that switches between data read from FFEDM2 or SMSM
assign Mem2ReadDataX = Signals[27] ? {SensorMemReadDataIn[16:9], SensorMemReadDataIn[7:0], 16'b0} : Mem2ReadData_latched[31:0];
assign Mem1ReadDataToALU = Mem1ReadDataX;
assign Mem2ReadDataToALU = Mem2ReadDataX;
// toggle StartSM each time Signals[31] is active
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
StartSM_reg <= 0;
else
if (FFE_clock_halfperiod && Signals[31])
StartSM_reg <= !StartSM_reg;
else
StartSM_reg <= StartSM_reg;
`else
always @(posedge ClockIn or posedge ResetIn)
if (ResetIn)
StartSM_reg <= 0;
else
if (Signals[31])
StartSM_reg <= !StartSM_reg;
else
StartSM_reg <= StartSM_reg;
`endif
assign StartSMOut = StartSM_reg;
// de-glitch the interrupt msg signal since it comes out of the decoder and data mem
`ifdef ENABLE_FFE_F0_SINGLE_DM
// single DM
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
always @(posedge Clock_x2In)
InterruptMsg_reg <= (FFE_clock_halfperiod && Signals[36]) ? WriteData_latched[23:16] : 8'b0;
`else
// 2k CM
always @(posedge ClockIn)
InterruptMsg_reg <= Signals[36] ? WriteData_latched[23:16] : 8'b0;
`endif
`else
// double DM, legacy behavior
always @(posedge ClockIn)
InterruptMsg_reg <= Signals[36] ? xWriteData[23:16] : 8'b0;
`endif
assign InterruptMsgOut = InterruptMsg_reg;
// sync to local clock
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
`else
always @(posedge ClockIn) begin
`endif
Start_r1 <= StartIn;
Start_r2 <= Start_r1;
Start_r3 <= Start_r2;
end
assign Start_detected = (Start_r1 != Start_r2) || (Start_r2 != Start_r3);
// Program Counter to step through the Control Memory
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn) begin
`else
always @(posedge ClockIn or posedge ResetIn) begin
`endif
if (ResetIn) begin
xPC <= 0;
BusyOut_reg <= 1'b0;
BusyOut_r1 <= 1'b0;
ControlMemReadEnableOut <= 1'b0;
SMOverrunOut <= 1'b0;
end else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
begin
BusyOut_r1 <= BusyOut_reg;
if (BusyOut_reg && BusyOut_r1) begin // make sure the 1st control word appears on the RAM outputs... requires one clock cycle after the read enable is turned on.
if (!Signals[32]) begin // !Signals[32] = continue running = !STOP
if (Restore_BG_registers)
xPC <= PC_BG;
else
if (Clear_PC)
xPC <= 0;
else
// hold the PC while switching threads
if (BG_active &&
((Start_detected || BGsave_pending) ||
(BGcontinue_pending && (Thread_switch_cnt != THREAD_SWITCH_CNT_DONE))))
xPC <= xPC;
else
if (xJumpFlag)
xPC <= xJumpAddress;
else
xPC <= xPC + 1;
end else begin // Signals[32] = STOP
xPC <= 0;
if (!BG_active) begin // FG mode
BusyOut_reg <= 1'b0;
ControlMemReadEnableOut <= 1'b0;
end else begin // BG mode
ControlMemReadEnableOut <= 1'b1;
if (BGstop_pending && (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE) && !Start_pending && !Start_detected)
BusyOut_reg <= 1'b0;
else
BusyOut_reg <= 1'b1;
end
end
end else // new start condition not detected, keep running
if (Start_detected) begin
if (SMBusyIn) begin
SMOverrunOut <= 1'b1;
end else begin
BusyOut_reg <= 1'b1;
ControlMemReadEnableOut <= 1'b1;
end
end
end
end
assign BusyOut = BusyOut_reg;
// --- BG thread support
// Signals[42] = SetBGflag (instruction modifier)
// Signals[43] = BGcontinue (instruction)
// Start_pending, flag to latch the start event, in case it happens right as we're switching to the BG thread or while running the BG thread.
// This needs to be latched so the FG thread can be started immediately once we've switched out of the BG thread.
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
Start_pending <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
case (Start_pending)
1'b0: if (Start_detected && // start detected AND...
(Signals[42] || // ...SetBGflag active (about to start or continue BG)...OR...
BG_active)) // ...BG active (switching to BG, running BG, about to stop/end BG, stopping BG)
Start_pending <= 1;
1'b1: if (!BG_active) // clear this flag when BG_active goes away
Start_pending <= 0;
endcase
// BG_pending counter, used instead of individual state machines for each type of context switch
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
Thread_switch_cnt <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
if (BGsave_pending || BGcontinue_pending || BGstop_pending)
if (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE)
Thread_switch_cnt <= 0;
else
Thread_switch_cnt <= Thread_switch_cnt + 1;
else
Thread_switch_cnt <= 0;
// BGcontinue_pending, flag that goes active while resuming the BG thread (BGcontinue instruction)
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
BGcontinue_pending <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
case (BGcontinue_pending)
1'b0: if (Signals[43])
BGcontinue_pending <= 1;
1'b1: if (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE)
BGcontinue_pending <= 0;
endcase
// BGsave_pending, flag that goes active while saving the state of the BG thread (BG_continue or BG thread interrupted by the sample timer)
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
BGsave_pending <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
case (BGsave_pending)
1'b0: if (BG_active && // in the BG thread...AND...
(Start_detected || // ...started detected...OR...
(BGcontinue_pending && (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE) && Start_pending))) // ...about to complete BGcontinue AND start was detected
BGsave_pending <= 1;
1'b1: if (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE)
BGsave_pending <= 0;
endcase
// BGstop_pending, flag that goes active while stopping the BG thread (normal completion)
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
BGstop_pending <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
case (BGstop_pending)
1'b0: if (BG_active && Signals[32])
BGstop_pending <= 1;
1'b1: if (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE)
BGstop_pending <= 0;
endcase
// BG_active, flag that is active while switching to, in, or switching from, the BG thread
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
BG_active <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
case (BG_active)
1'b0: if (Signals[42]) // SetBGactive (entering BG mode, either via start BG or continue BG)
BG_active <= 1;
1'b1: if ((BGsave_pending || BGstop_pending) && (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE)) // done switching out of BG mode
BG_active <= 0;
endcase
// Control signal used to save the BG copy of the PC and ALU flags
assign Save_BG_registers = (BGsave_pending && (Thread_switch_cnt == 1));
// clock-by-clock sequence of events:
// {BGsave_pending,Thread_switch_cnt}
// 0,0 - Start detected, last BG instruction, hold PC
// 1,0 - hold PC, disable DataMemWrEn
// 1,1 - hold PC, save PC & flags (Save_BG_registers active), disable DataMemWrEn
// 1,2 - clear PC, disable DataMemWrEn
// 1,3 - hold PC (driving into CodeMem), disable DataMemWrEn
// 1,4 - hold PC (CodeMem available, driving DataMem), disable DataMemWrEn
// 1,5 - hold PC (DataMem available), disable DataMemWrEn
// 1,6 - hold PC (extraneous), disable DataMemWrEn
// 1,7 - hold PC (extraneous), disable DataMemWrEn
// 0,0 - continue running normally (now in FG thread)
// Control signal used to restore the BG state of the PC and ALU flags
assign Restore_BG_registers = (BGcontinue_pending && (Thread_switch_cnt == 1));
// clock-by-clock sequence of events:
// {BGcontinue_pending,Thread_switch_cnt} - action(s)
// 0,0 - BGcontinue();
// 1,0 - NOP;, disable DataMemWrEn
// 1,1 - load PC & flags (Restore_BG_registers active), disable DataMemWrEn
// 1,2 - hold PC (driving into CodeMem), disable DataMemWrEn
// 1,3 - hold PC (CodeMem available, driving DataMem), disable DataMemWrEn
// 1,4 - hold PC (DataMem available), disable DataMemWrEn
// 1,5 - hold PC (extraneous), disable DataMemWrEn
// 1,6 - hold PC (extraneous), disable DataMemWrEn
// 1,7 - increment PC, disable DataMemWrEn
// 0,0 - continue running normally (now in BG thread)
// Control signal used to reset the PC (during BGstop or BGsave)
assign Clear_PC = ((BGsave_pending && (Thread_switch_cnt == 2)) || (BGstop_pending));
// Control signal used to disable the FFE DataMem write enable, while resuming the BG thread
assign Disable_DataMem_WrEn = (BGcontinue_pending);
// BG copy of the PC
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
PC_BG <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
if (Save_BG_registers)
PC_BG <= xPC;
else
PC_BG <= PC_BG;
// test points
assign TP1 = 0;
assign TP2 = 0;
assign TP3 = 0;
endmodule

View File

@ -0,0 +1,59 @@
`timescale 1ns / 10ps
// algorithm file = 'ulpsh_s2_main_JB4_BMI160_AK09911_PD.alg'
// UlpshType = S2_1KDM
module decodeMicroOpCode (MicroOpCode, Signals);
input [8:0] MicroOpCode;
output [45:0] Signals;
wire [45:0] Signals;
assign Signals[0] = (MicroOpCode == 9'h00e) || 0;
assign Signals[1] = (MicroOpCode == 9'h012) || (MicroOpCode == 9'h013) || 0;
assign Signals[2] = 0;
assign Signals[3] = 0;
assign Signals[4] = (MicroOpCode == 9'h038) || 0;
assign Signals[5] = (MicroOpCode == 9'h016) || (MicroOpCode == 9'h017) || (MicroOpCode == 9'h021) || (MicroOpCode == 9'h034) || (MicroOpCode == 9'h035) || (MicroOpCode == 9'h036) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h040) || (MicroOpCode == 9'h041) || (MicroOpCode == 9'h042) || (MicroOpCode == 9'h045) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h04e) || (MicroOpCode == 9'h04f) || 0;
assign Signals[6] = (MicroOpCode == 9'h00a) || (MicroOpCode == 9'h014) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h024) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h02d) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || (MicroOpCode == 9'h050) || 0;
assign Signals[7] = (MicroOpCode == 9'h00a) || (MicroOpCode == 9'h014) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h024) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h02d) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h035) || (MicroOpCode == 9'h036) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h050) || 0;
assign Signals[8] = (MicroOpCode == 9'h00a) || (MicroOpCode == 9'h024) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h03b) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || 0;
assign Signals[9] = (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03b) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || 0;
assign Signals[10] = (MicroOpCode == 9'h007) || (MicroOpCode == 9'h008) || (MicroOpCode == 9'h009) || (MicroOpCode == 9'h00a) || (MicroOpCode == 9'h00d) || (MicroOpCode == 9'h00e) || (MicroOpCode == 9'h010) || (MicroOpCode == 9'h012) || (MicroOpCode == 9'h013) || (MicroOpCode == 9'h014) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h022) || (MicroOpCode == 9'h024) || (MicroOpCode == 9'h025) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h036) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h03a) || (MicroOpCode == 9'h03c) || (MicroOpCode == 9'h03d) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h040) || (MicroOpCode == 9'h041) || (MicroOpCode == 9'h042) || (MicroOpCode == 9'h046) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h04e) || (MicroOpCode == 9'h04f) || (MicroOpCode == 9'h050) || 0;
assign Signals[11] = (MicroOpCode == 9'h037) || (MicroOpCode == 9'h049) || 0;
assign Signals[12] = (MicroOpCode == 9'h03b) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || 0;
assign Signals[13] = (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03b) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || 0;
assign Signals[14] = 0;
assign Signals[15] = (MicroOpCode == 9'h038) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h04a) || 0;
assign Signals[16] = (MicroOpCode == 9'h034) || (MicroOpCode == 9'h035) || (MicroOpCode == 9'h048) || 0;
assign Signals[17] = (MicroOpCode == 9'h00f) || (MicroOpCode == 9'h011) || (MicroOpCode == 9'h015) || (MicroOpCode == 9'h01c) || (MicroOpCode == 9'h029) || 0;
assign Signals[18] = (MicroOpCode == 9'h00b) || (MicroOpCode == 9'h00f) || (MicroOpCode == 9'h01f) || (MicroOpCode == 9'h029) || 0;
assign Signals[19] = (MicroOpCode == 9'h015) || (MicroOpCode == 9'h01f) || (MicroOpCode == 9'h029) || (MicroOpCode == 9'h031) || 0;
assign Signals[20] = (MicroOpCode == 9'h001) || (MicroOpCode == 9'h002) || (MicroOpCode == 9'h009) || (MicroOpCode == 9'h00c) || (MicroOpCode == 9'h016) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h025) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h02c) || (MicroOpCode == 9'h02d) || (MicroOpCode == 9'h032) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h034) || (MicroOpCode == 9'h035) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h03c) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h042) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h048) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04d) || (MicroOpCode == 9'h04f) || 0;
assign Signals[21] = (MicroOpCode == 9'h004) || (MicroOpCode == 9'h008) || (MicroOpCode == 9'h009) || (MicroOpCode == 9'h00c) || (MicroOpCode == 9'h010) || (MicroOpCode == 9'h013) || (MicroOpCode == 9'h016) || (MicroOpCode == 9'h019) || (MicroOpCode == 9'h01b) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h023) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h02a) || (MicroOpCode == 9'h02c) || (MicroOpCode == 9'h02d) || (MicroOpCode == 9'h02e) || (MicroOpCode == 9'h030) || (MicroOpCode == 9'h032) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h034) || (MicroOpCode == 9'h035) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h03a) || (MicroOpCode == 9'h03c) || (MicroOpCode == 9'h03d) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h041) || (MicroOpCode == 9'h042) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h045) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h048) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04d) || (MicroOpCode == 9'h04f) || (MicroOpCode == 9'h050) || 0;
assign Signals[22] = (MicroOpCode == 9'h002) || (MicroOpCode == 9'h003) || (MicroOpCode == 9'h007) || (MicroOpCode == 9'h008) || (MicroOpCode == 9'h009) || (MicroOpCode == 9'h00d) || (MicroOpCode == 9'h00e) || (MicroOpCode == 9'h010) || (MicroOpCode == 9'h012) || (MicroOpCode == 9'h013) || (MicroOpCode == 9'h014) || (MicroOpCode == 9'h016) || (MicroOpCode == 9'h017) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h022) || (MicroOpCode == 9'h024) || (MicroOpCode == 9'h025) || (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h02a) || (MicroOpCode == 9'h02b) || (MicroOpCode == 9'h02c) || (MicroOpCode == 9'h02d) || (MicroOpCode == 9'h02e) || (MicroOpCode == 9'h02f) || (MicroOpCode == 9'h030) || (MicroOpCode == 9'h032) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h036) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03a) || (MicroOpCode == 9'h03b) || (MicroOpCode == 9'h03c) || (MicroOpCode == 9'h03d) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h040) || (MicroOpCode == 9'h041) || (MicroOpCode == 9'h042) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h045) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || (MicroOpCode == 9'h04e) || (MicroOpCode == 9'h04f) || (MicroOpCode == 9'h050) || 0;
assign Signals[23] = 0;
assign Signals[24] = 0;
assign Signals[25] = (MicroOpCode == 9'h021) || 0;
assign Signals[26] = (MicroOpCode == 9'h021) || 0;
assign Signals[27] = (MicroOpCode == 9'h002) || (MicroOpCode == 9'h003) || 0;
assign Signals[28] = (MicroOpCode == 9'h04d) || 0;
assign Signals[29] = (MicroOpCode == 9'h023) || (MicroOpCode == 9'h02e) || (MicroOpCode == 9'h03d) || (MicroOpCode == 9'h04d) || 0;
assign Signals[30] = (MicroOpCode == 9'h018) || (MicroOpCode == 9'h019) || (MicroOpCode == 9'h01a) || (MicroOpCode == 9'h01b) || 0;
assign Signals[31] = (MicroOpCode == 9'h006) || 0;
assign Signals[32] = (MicroOpCode == 9'h01e) || 0;
assign Signals[33] = (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || 0;
assign Signals[34] = (MicroOpCode == 9'h022) || (MicroOpCode == 9'h02a) || (MicroOpCode == 9'h02b) || (MicroOpCode == 9'h02c) || (MicroOpCode == 9'h03a) || (MicroOpCode == 9'h03c) || (MicroOpCode == 9'h03d) || (MicroOpCode == 9'h04e) || (MicroOpCode == 9'h04f) || 0;
assign Signals[35] = (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || 0;
assign Signals[36] = (MicroOpCode == 9'h01d) || 0;
assign Signals[37] = (MicroOpCode == 9'h018) || (MicroOpCode == 9'h019) || 0;
assign Signals[38] = (MicroOpCode == 9'h00d) || (MicroOpCode == 9'h00e) || (MicroOpCode == 9'h010) || 0;
assign Signals[39] = 0;
assign Signals[40] = (MicroOpCode == 9'h005) || 0;
assign Signals[41] = 0;
assign Signals[42] = 0;
assign Signals[43] = 0;
assign Signals[44] = (MicroOpCode == 9'h01c) || 0;
assign Signals[45] = 0;
endmodule

View File

@ -0,0 +1,70 @@
// -----------------------------------------------------------------------------
// title : Sensor Manager Memory Module
// project : ULP Sensor Hub
// -----------------------------------------------------------------------------
// file : SMEMemoryMux.v
// author : OCTO
// company : QuickLogic Corp
// created : 2012/??/??
// last update : 2014/05/20
// platform : PolarPro III
// standard : Verilog 2001
// -----------------------------------------------------------------------------
// description: The Sensor Manger Memory Mux selects between several sources
// for passing both read and write information.
// -----------------------------------------------------------------------------
// copyright (c) 2013
// -----------------------------------------------------------------------------
// revisions :
// date version author description
// 2014/05/20 1.0 Glen Gomes Updated -> Added support for a second
// memory block by adding
// address bits.
// -----------------------------------------------------------------------------
// Comments: This solution is specifically for use with the QuickLogic
// PolarPro III S2 device.
// -----------------------------------------------------------------------------
`timescale 1ns / 10ps
module SMEMemoryMux (
input Select,
input [9:0] ReadAddressIn0, // Expanded for Rel 0 on 6/18
input [9:0] ReadAddressIn1, // Expanded for Rel 0 on 6/18
output[9:0] ReadAddressOut, // Expanded for Rel 0 on 6/18
input [9:0] WriteAddressIn0,
input [9:0] WriteAddressIn1,
output[9:0] WriteAddressOut,
input [8:0] DataToMemoryIn0,
input [8:0] DataToMemoryIn1,
output[8:0] DataToMemoryOut,
input [17:0] DataFromMemoryIn0,
input [17:0] DataFromMemoryIn1,
output[17:0] DataFromMemoryOut,
input ReadEnableIn0,
input ReadEnableIn1,
output ReadEnableOut,
input WriteEnableIn0,
input WriteEnableIn1,
output WriteEnableOut,
input ReadClockIn0,
input ReadClockIn1,
output ReadClockOut
);
assign ReadAddressOut = (Select) ? ReadAddressIn1 : ReadAddressIn0;
assign WriteAddressOut = (Select) ? WriteAddressIn1 : WriteAddressIn0;
assign DataToMemoryOut = (Select) ? DataToMemoryIn1 : DataToMemoryIn0;
assign DataFromMemoryOut = (Select) ? DataFromMemoryIn1 : DataFromMemoryIn0;
assign ReadEnableOut = (Select) ? ReadEnableIn1 : ReadEnableIn0;
assign WriteEnableOut = (Select) ? WriteEnableIn1 : WriteEnableIn0;
assign ReadClockOut = (Select) ? ReadClockIn1 : ReadClockIn0;
endmodule

View File

@ -0,0 +1,112 @@
// -----------------------------------------------------------------------------
// title : Sensor Manager Memory Module
// project : ULP Sensor Hub
// -----------------------------------------------------------------------------
// file : SMMemory.v
// author : OCTO
// company : QuickLogic Corp
// created : 2012/??/??
// last update : 2014/05/20
// platform : PolarPro III
// standard : Verilog 2001
// -----------------------------------------------------------------------------
// description: The Sensor Manger Memory performs several tasks. These include
// storing Sensor Manager Instructions, Sensor Data, and FFE mail
// box data. This memory consists of several physical memory
// blocks.
// -----------------------------------------------------------------------------
// copyright (c) 2013
// -----------------------------------------------------------------------------
// revisions :
// date version author description
// 2014/05/20 1.0 Glen Gomes Updated -> Added a second memory block
// -----------------------------------------------------------------------------
// Comments: This solution is specifically for use with the QuickLogic
// PolarPro III S2 device.
// -----------------------------------------------------------------------------
`timescale 1ns / 10ps
module SMMemory (
// General Interface
input ResetIn,
input SMBusyIn,
//Read Interface
input [9:0] ReadAddressIn,
output [17:0] ReadDataOut,
input ReadSelectIn,
input ReadClockIn,
//Write Interface
input [9:0] WriteAddressIn,
input [8:0] WriteDataIn,
input WriteSelectIn,
input [9:0] WriteAddressIn_TLC,
input [8:0] WriteDataIn_TLC,
input WriteSelectIn_TLC,
input WriteClockIn,
output [9:0] SMMemory_WriteAddressIn_TLC_o,
output [8:0] SMMemory_ReadAddressIn_o,
output SMMemory_WriteSelectIn_TLC_o,
output SMMemory_ReadSelect_RAM0_o,
output SMMemory_WriteClockIn_o,
output SMMemory_ReadClockIn_o,
output [8:0] SMMemory_WriteDataIn_TLC_o,
input [17:0] SMMemory_ReadDataOut_SRAM_i,
output [9:0] SMMemory_WriteAddressIn_o,
output SMMemory_WriteSelectIn_o,
output SMMemory_ReadSelect_RAM1_o,
output SMMemory_WriteDataIn_o,
input [17:0] SMMemory_ReadDataOut_SRAM1_i
);
// Define local variables
//
wire [17:0] ReadDataOut_SRAM;
wire [17:0] ReadDataOut_SRAM_1;
reg ReadDataSel;
wire ReadSelect_RAM0;
wire ReadSelect_RAM1;
wire SMMemoryBankSelect;
// generate individual read enables
assign ReadSelect_RAM0 = ReadSelectIn && !ReadAddressIn[9];
assign ReadSelect_RAM1 = ReadSelectIn && ReadAddressIn[9];
// Mux the read data
always @(posedge ReadClockIn)
ReadDataSel <= ReadAddressIn[9];
assign SMMemoryBankSelect = SMBusyIn ? ReadAddressIn[9] : ReadDataSel;
assign ReadDataOut = SMMemoryBankSelect ? ReadDataOut_SRAM_1: ReadDataOut_SRAM;
// Instantiate the Memory Blocks
//
assign SMMemory_WriteAddressIn_TLC_o = WriteAddressIn_TLC;
assign SMMemory_ReadAddressIn_o[8:0] = ReadAddressIn[8:0];
assign SMMemory_WriteSelectIn_TLC_o = WriteSelectIn_TLC;
assign SMMemory_ReadSelect_RAM0_o = ReadSelect_RAM0;
assign SMMemory_WriteClockIn_o = WriteClockIn;
assign SMMemory_ReadClockIn_o = ReadClockIn;
assign SMMemory_WriteDataIn_TLC_o = WriteDataIn_TLC;
assign ReadDataOut_SRAM = SMMemory_ReadDataOut_SRAM_i;
assign SMMemory_WriteAddressIn_o = WriteAddressIn;
assign SMMemory_WriteSelectIn_o = WriteSelectIn;
assign SMMemory_ReadSelect_RAM1_o = ReadSelect_RAM1;
assign SMMemory_WriteDataIn_o = WriteDataIn;
assign ReadDataOut_SRAM1 = SMMemory_ReadDataOut_SRAM1_i;
endmodule

View File

@ -0,0 +1,292 @@
/*------------------------------------------------------------------------------
SPI_slave
SPI slave interface, designed for the ULP Sensor Hub.
This module is designed to be as small and simple as possible, while
supporting the ULP Sensor Hub. Only supports SPI Mode 0 (CPOL=CPHA=0)...
which means that input data is latched on the positive edge of SPI_SCLK,
and driven out on the negative edge of SPI_SCLK, with the base value of
SPI_SCLK being 0.
SPI Protocol:
Writes: MOSI: A0 + D0 + D1 + ... + Dn
MISO: xx + xx + xx + ... + xx
Reads: MOSI: A0 + xx + xx + ... + xx
MISO: xx + xx + D0 + ... + Dn
A0 = [1-bit R/W: 1=write, 0=read] + [7-bit address]
Dn = valid data byte
xx = don't-care data byte
It is assumed that the MSb is transmitted first, and the LSb last.
The address is latched, and auto-incremented to support burst reads/writes.
The address, when 0d11, jumps back to 0d07, to support repeated (burst)
reads to/from the memory data port. The logic to re-map addresses above
0d11, that previously was in TLC.v, can now be removed. New registers
above 0d11 may now be added if needed.
This SPI slave requires extra edges on SPI_SCLK to complete any write
operation. This may be accomplished in any one of several ways:
1. A (non-destructive) read should be performed following the last
write operation.
2. SPI_SCLK should be toggled after SPI_SS goes inactive
(a free-running SPI_SCLK would accomplish this).
3. A few extra bits (totaling less than a full byte) should be
transmitted by the master. These extra bits will be ignored by
this core, but will provide the clocks needed to generated the
wr_data_valid pulse.
4. A "null" transaction should be performed following the last
write transaction, during which the address byte is transmitted
by the SPI master followed by 0 bytes of read/write data.
------------------------------------------------------------------------------*/
`timescale 1ns / 1ns
`include "SensorHubDefines.v"
module SPI_slave (
input rst, // system/global reset (active-high)
// SPI interface
input SPI_SCLK, // base value 0 (mode 0)
input SPI_MOSI, // master out, slave in
output SPI_MISO, // master in, slave out
input SPI_SS, // slave select (active-low)
// internal interface
output [6:0] addr,
output [7:0] wr_data,
output wr_data_valid, // active high
input [7:0] rd_data,
output rd_data_ack
);
parameter WR = 1'b1;
parameter RD = 1'b0;
wire rst_int;
reg [7:0] shift_in;
reg [7:0] shift_out;
reg [2:0] bit_cnt, bit_cnt_neg;
reg rcv_byte_valid;
reg addr_has_been_latched;
reg first_data_has_been_latched;
reg [6:0] addr_reg;
reg write_readn;
reg [7:0] write_data_reg;
reg wr_data_valid_reg;
reg write_pending;
reg rd_data_ack_reg;
// rst_int is active when the global rst occurs or when the SPI interface is idle.
// Some logic needs to remain active after a SPI transaction occurs, so rst will be used in those cases.
assign rst_int = rst || SPI_SS;
// input shift register
always @(posedge rst_int or posedge SPI_SCLK)
if (rst_int)
shift_in <= 8'b0;
else
if (!SPI_SS)
shift_in <= {shift_in[6:0], SPI_MOSI};
else
shift_in <= shift_in;
// bit counter
always @(posedge rst_int or posedge SPI_SCLK)
if (rst_int)
bit_cnt <= 3'b0;
else
if (!SPI_SS)
bit_cnt <= bit_cnt + 1;
else
bit_cnt <= 3'b0;
// byte valid, active for 1 clk every time a full byte has been received from the master
always @(posedge rst_int or posedge SPI_SCLK)
if (rst_int)
rcv_byte_valid <= 1'b0;
else
if (rcv_byte_valid) // added to guarantee that rcv_byte_valid is only active for 1 clock
rcv_byte_valid <= 1'b0;
else
if (!SPI_SS && (bit_cnt == 3'b111))
rcv_byte_valid <= 1'b1;
else
rcv_byte_valid <= 1'b0;
// flags for keeping track of the address byte and 1st data byte
always @(posedge rst_int or posedge SPI_SCLK)
if (rst_int) begin
addr_has_been_latched <= 1'b0; // flag that gets set after the addr has been received (and latched)
first_data_has_been_latched <= 1'b0; // flag that gets set after the 1st data byte has been received (and latched)
end
else begin
// if (SPI_SS) // if SPI interface is idle
// addr_has_been_latched <= 1'b0;
// else
// the above is not necessary since the async rst includes SPI_SS
if (rcv_byte_valid)
addr_has_been_latched <= 1'b1; // set flag after first byte (the address) is received, keep at 1 until transaction is over
else
addr_has_been_latched <= addr_has_been_latched;
// if (SPI_SS) // if SPI interface is idle
// first_data_has_been_latched <= 1'b0;
// else
// the above is not necessary since the async rst includes SPI_SS
if (addr_has_been_latched && rcv_byte_valid)
first_data_has_been_latched <= 1'b1;
else
first_data_has_been_latched <= first_data_has_been_latched;
end
// address register, direction control flag
always @(posedge rst or posedge SPI_SCLK) // don't use rst_int so these signals will remain active even after SPI_SS has gone inactive
if (rst) begin
addr_reg <= 7'b0;
write_readn <= 1'b0; // flag that signifies a write vs. read transaction
end
else begin
if (!addr_has_been_latched && rcv_byte_valid)
write_readn <= shift_in[7]; // the direction (r/w) flag is in the MSb of the address byte.
else
write_readn <= write_readn;
if (!addr_has_been_latched)
if (rcv_byte_valid)
addr_reg <= shift_in[6:0]; // latch the new address, located in the lowest 7 bits of the address byte.
else
addr_reg <= addr_reg;
else // addr_has_been_latched
// if (((write_readn == WR) && wr_data_valid_reg) || ((write_readn == RD) && rcv_byte_valid))
// addr_reg <= addr_reg + 1;
// else
// addr_reg <= addr_reg;
// during writes, make addr_reg wrap back to MemDataByte0 after MemDataByte4
if ((write_readn == WR) && wr_data_valid_reg)
if (addr_reg == `MemDataByte4)
addr_reg <= `MemDataByte0;
else
addr_reg <= addr_reg + 1;
else
// during reads, do not increment addr_reg when accessing CM_FIFO_Data
//if ((write_readn == RD) && rcv_byte_valid)
if ((write_readn == RD) && rd_data_ack_reg)
if (addr_reg == `CM_FIFO_Data)
addr_reg <= addr_reg;
else
addr_reg <= addr_reg + 1;
else
addr_reg <= addr_reg;
end
// write_pending flag, so writes eventually get sent to the internal interface when more SPI_SCLK edges occur
always @(posedge rst or posedge SPI_SCLK) // don't use rst_int since this may need to stay active after SPI_SS goes inactive
if (rst)
write_pending <= 1'b0;
else
if (wr_data_valid_reg)
write_pending <= 1'b0;
else
if ((write_readn == WR) && !SPI_SS && addr_has_been_latched && (bit_cnt == 3'b111)) // can't use rcv_byte_valid since there may not be extra clocks after this byte is being written
write_pending <= 1'b1;
else
write_pending <= write_pending;
// write data valid signal
always @(posedge rst or posedge SPI_SCLK) // don't use rst_int since this may need to be set after SPI_SS goes inactive
if (rst)
wr_data_valid_reg <= 1'b0;
else
if (wr_data_valid_reg)
wr_data_valid_reg <= 1'b0;
else
if (write_pending)
wr_data_valid_reg <= 1'b1;
else
wr_data_valid_reg <= wr_data_valid_reg;
always @(posedge rst or posedge SPI_SCLK) // don't use rst_int since this needs to stay valid after SPI_SS goes inactive
if (rst)
write_data_reg <= 8'b0;
else
if (!SPI_SS && (bit_cnt == 3'b111))
write_data_reg <= {shift_in[6:0], SPI_MOSI};
else
write_data_reg <= write_data_reg;
// output shift register
always @(posedge rst_int or negedge SPI_SCLK)
if (rst_int) begin
bit_cnt_neg <= 3'b0;
shift_out <= 8'b0;
end
else begin
if (!SPI_SS) begin
bit_cnt_neg <= bit_cnt_neg + 1;
if (addr_has_been_latched && (bit_cnt_neg == 7))
shift_out <= rd_data;
else
shift_out <= {shift_out[6:0], 1'b0};
end
else begin
bit_cnt_neg <= 3'b0;
shift_out <= shift_out;
end
end
// read data acknowledge. this is required to pop data from the CM FIFO
always @(posedge rst_int or posedge SPI_SCLK)
if (rst_int)
rd_data_ack_reg <= 1'b0;
else
//if ( addr_has_been_latched && (write_readn == RD) && (bit_cnt == 3'b111) )
if ( addr_has_been_latched && (write_readn == RD) && rcv_byte_valid)
rd_data_ack_reg <= 1'b1;
else
rd_data_ack_reg <= 1'b0;
// assignments to the outputs
//assign SPI_MISO = SPI_SS ? 1'bz : shift_out[7];
assign SPI_MISO = shift_out[7];//AP2 doesn't support tristate
assign addr = addr_reg;
assign wr_data = write_data_reg;
assign wr_data_valid = wr_data_valid_reg;
assign rd_data_ack = rd_data_ack_reg;
endmodule

View File

@ -0,0 +1,65 @@
`ifndef SensorHub_Definitions
`define SensorHub_Definitions
// Communication Manager register offsets
`define CommandReg 7'h00
`define StatusReg 7'h01
`define milSecSample 7'h02
`define InterruptCtrl 7'h03
`define InterruptStat 7'h04
`define CalValueLow 7'h05
`define CalValueHi 7'h06
`define Reserved_10 7'h07
`define Reserved_11 7'h08
`define Reserved_12 7'h09
`define Reserved_13 7'h0A
`define Reserved_14 7'h0B
`define CM_FIFO_Data 7'h0C
`define CM_Control 7'h0D
`define CM_Status 7'h0E
`define CM_FIFO_Flags_0 7'h0F
`define Reserved_1 7'h10 /* reserved for CM_FIFO_Flags_23 */
`define MailboxToFFE_0 7'h11
`define MailboxToFFE_1 7'h12
`define MailboxToFFE_2 7'h13
`define MailboxToFFE_3 7'h14
`define InterruptFFEMsg 7'h15
`define Reserved_5 7'h16
`define Reserved_6 7'h17
`define Reserved_7 7'h18
`define RunTimeAdrReg 7'h19
`define DemoLedCtrlReg 7'h1A /* Register to control demo LEDs */
`define ClocksControl 7'h1B
`define SleepControl 7'h1C
`define RunTimeAdrReg_Upr 7'h1D /* New for Rel 0 on 6/18 */
`define MemAddrLow 7'h20
`define MemAddrHigh 7'h21
`define MemSelect 7'h22
`define MemDataByte0 7'h28
`define MemDataByte1 7'h29
`define MemDataByte2 7'h2A
`define MemDataByte3 7'h2B
`define MemDataByte4 7'h2C
`define CtrlSensorManager 8'h00
`define CtrlReceiveAddress 8'h01
`define CtrlRunTimeAddress 8'h02
`define MasterPreLo 8'h08
`define MasterPreHi 8'h09
`define MasterCTR 8'h0A
`define MasterTXR 8'h0B
`define MasterCR 8'h0C
`define CR_START 8'b1000_0000
`define CR_STOP 8'b0100_0000
`define CR_READ 8'b0010_0000
`define CR_WRITE 8'b0001_0000
`define CR_NAK 8'b0000_1000
// `define CR_POLL 8'b0000_0100
`define CR_IACK 8'b0000_0001
`endif

View File

@ -0,0 +1,960 @@
// -----------------------------------------------------------------------------
// title : Sensor Manager Main Routine
// project : ULP Sensor Hub
// -----------------------------------------------------------------------------
// file : SensorManager.v
// author : OCTO
// company : QuickLogic Corp
// created : 2012/??/??
// last update : 2013/12/06
// platform : PolarPro III
// standard : Verilog 2001
// -----------------------------------------------------------------------------
// description: The Sensor Manger is responsible for controlling various
// external sensors and storing the resulting data in Sensor
// Manager Memory. These include performing transfers between
// Sensor Memory and various registers.
// -----------------------------------------------------------------------------
// copyright (c) 2013
// -----------------------------------------------------------------------------
// revisions :
// date version author description
// 2013/12/06 1.0 Glen Gomes Updated -> Mostly re-written
// -----------------------------------------------------------------------------
// Comments: This solution is specifically for use with the QuickLogic
// PolarPro III device.
// -----------------------------------------------------------------------------
`timescale 1ns / 10ps
module SensorManager (
// General interface
ClockIn,
ResetIn,
StartFromFFE,
StartFromTLC,
BusyOut,
TimeStamp_Delta_i,
TimeStamp_Delta_Tog_i,
SensorInterrupt_0_i,
SensorInterrupt_1_i,
SensorInterrupt_2_i,
SensorInterrupt_3_i,
SensorInterrupt_0_o,
SensorInterrupt_1_o,
SensorInterrupt_2_o,
SensorInterrupt_3_o,
CtrlRunTimeAddressSM,
CtrlRunTimeAddressOut,
CtrlRunTimeAddressReg,
MemReadAddressOut,
MemReadEnableOut,
MemReadDataIn,
MemWriteAddressOut,
MemWriteEnableOut,
MemWriteDataOut,
MemClockOut,
I2C_wb_adr_o,
I2C_wb_dat_o,
I2C_wb_dat_i,
I2C_wb_we_o,
I2C_wb_stb_o,
I2C_wb_cyc_o,
I2C_wb_ack_i,
I2C_tip_i,
TP1,
TP2,
TP3,
SmClockSelect_o
);
//-----Port Signals--------------------
//
input ClockIn;
input ResetIn;
input StartFromFFE;
input StartFromTLC;
output BusyOut;
input [15:0] TimeStamp_Delta_i;
input TimeStamp_Delta_Tog_i;
input SensorInterrupt_0_i;
input SensorInterrupt_1_i;
input SensorInterrupt_2_i;
input SensorInterrupt_3_i;
output SensorInterrupt_0_o;
output SensorInterrupt_1_o;
output SensorInterrupt_2_o;
output SensorInterrupt_3_o;
input CtrlRunTimeAddressSM;
input [9:0] CtrlRunTimeAddressOut;
output [9:0] CtrlRunTimeAddressReg;
output [9:0] MemReadAddressOut; // Expanded for Rel 0 on 6/18
output MemReadEnableOut;
input [17:0] MemReadDataIn;
output [9:0] MemWriteAddressOut;
output MemWriteEnableOut;
output [8:0] MemWriteDataOut;
output MemClockOut;
output [2:0] I2C_wb_adr_o;
output [7:0] I2C_wb_dat_o;
input [7:0] I2C_wb_dat_i;
output I2C_wb_we_o;
output I2C_wb_stb_o;
output I2C_wb_cyc_o;
input I2C_wb_ack_i;
input I2C_tip_i;
output TP1;
output TP2;
output TP3;
output SmClockSelect_o;
wire ClockIn;
wire ResetIn;
wire StartFromFFE;
wire StartFromTLC;
wire BusyOut;
wire [15:0] TimeStamp_Delta_i;
wire TimeStamp_Delta_Tog_i;
wire SensorInterrupt_0_i;
wire SensorInterrupt_1_i;
wire SensorInterrupt_2_i;
wire SensorInterrupt_3_i;
reg SensorInterrupt_0_o;
reg SensorInterrupt_1_o;
reg SensorInterrupt_2_o;
reg SensorInterrupt_3_o;
wire CtrlRunTimeAddressSM;
wire [9:0] CtrlRunTimeAddressOut;
reg [9:0] CtrlRunTimeAddressReg;
wire [9:0] MemReadAddressOut; // Expanded for Rel 0 on 6/18
wire MemReadEnableOut;
wire [17:0] MemReadDataIn;
wire [9:0] MemWriteAddressOut;
wire MemWriteEnableOut;
reg [8:0] MemWriteDataOut;
wire [2:0] I2C_wb_adr_o;
wire [7:0] I2C_wb_dat_o;
wire [7:0] I2C_wb_dat_i;
wire I2C_wb_we_o;
wire I2C_wb_stb_o;
wire I2C_wb_cyc_o;
wire I2C_wb_ack_i;
wire I2C_tip_i;
wire MemClockOut;
wire TP1;
wire TP2;
wire TP3;
reg SmClockSelect_o;
//-----Internal Signals--------------------
//
wire wb_cyc;
wire wb_we;
wire wb_stb;
wire wb_ack;
reg wb_ack_sm;
wire wb_busy_poll;
reg [9:0] CtrlReceiveAddressReg;
reg [5:0] CtrlMailBoxSegmentCtr;
reg CtrlMailBoxSegmentCtr_ce;
reg [9:2] CtrlMailBoxTablePtr;
reg [9:0] CtrlMailBoxJumpInstPtr;
reg CtrlMailBoxJumpInstCycle;
reg CtrlMailBoxJumpInstCycle_ce;
wire [9:0] StateMachineCtrlMemAddr;
wire [7:0] i2c_masterDataToMem;
wire save_reg_2_mem;
wire control_sensor_manager_reg_dcd;
wire control_receive_reg_dcd;
wire control_runtime_reg_dcd;
wire control_jump_reg_dcd;
wire control_mailbox_tbl_ptr_dcd;
wire control_mailbox_jump_inst_ptr_dcd;
reg RunSM;
wire BusySM;
wire StartIn_stb;
reg StartFromFFE_1ff;
reg StartFromFFE_2ff;
reg StartFromFFE_3ff;
reg StartFromFFE_4ff;
reg StartFromFFE_5ff;
reg StartFromFFE_6ff;
reg StartFromTLC_1ff;
reg StartFromTLC_2ff;
reg CtrlRunTimeAddressSM_1ff;
reg CtrlRunTimeAddressSM_2ff;
reg s1_BusyOut, s2_BusyOut;
// Define write enable controls for each TimeStamp register
//
wire SensorInterrupt_event_reg_we_dcd;
wire SensorInterrupt_event_mask_we_dcd;
reg SensorInterrupt_event_mask_0;
reg SensorInterrupt_event_mask_1;
reg SensorInterrupt_event_mask_2;
reg SensorInterrupt_event_mask_3;
// Delta Time Stamp registers for each sensor
//
reg [7:0] TimeStamp_Delta_sensor_0;
reg [7:0] TimeStamp_Delta_sensor_1;
reg [7:0] TimeStamp_Delta_sensor_2;
reg [7:0] TimeStamp_Delta_sensor_3;
reg [15:0] TimeStamp_Delta_capt;
reg [15:0] TimeStamp_Delta_readback;
reg TimeStamp_Delta_Tog_1ff;
reg TimeStamp_Delta_Tog_2ff;
reg TimeStamp_Delta_Tog_3ff;
// Meta-state registers for each sensor interrupt
//
reg SensorInterrupt_0_1ff;
reg SensorInterrupt_0_2ff;
reg SensorInterrupt_0_3ff;
reg SensorInterrupt_1_1ff;
reg SensorInterrupt_1_2ff;
reg SensorInterrupt_1_3ff;
reg SensorInterrupt_2_1ff;
reg SensorInterrupt_2_2ff;
reg SensorInterrupt_2_3ff;
reg SensorInterrupt_3_1ff;
reg SensorInterrupt_3_2ff;
reg SensorInterrupt_3_3ff;
// Wait Instruction Registers
//
wire control_wait_instr_reg_dcd;
reg [12:0] control_wait_instr_cntr;
reg [12:0] control_wait_instr_cntr_nxt;
reg control_wait_instr_cntr_tc;
reg control_wait_instr_cntr_tc_nxt;
reg control_wait_instr_busy;
wire control_wait_instr_busy_nxt;
//------Define Parameters---------
//
//
// Define the various address spaces
//
// Note: These correspond to bits [7:3] of the register address field.
//
parameter SENSOR_MANAGER_ADR = 5'h0;
parameter I2C_MASTER_ADR = 5'h1;
parameter TIMESTAMP_DELTA_ADR = 5'h2;
//
// Define the available registers in the Sensor Manager
//
// Note: These correspond to bits [2:0] of the register address field.
//
parameter CONTROL_SENSOR_MANAGER_ADDRESS = 3'h0;
parameter CONTROL_RECEIVE_ADDRESS = 3'h1;
parameter CONTROL_RUNTIME_ADDRESS = 3'h2;
parameter CONTROL_WAIT_INSTR_ADDRESS = 3'h4;
parameter CONTROL_MAILBOX_TABLE_PTR = 3'h5;
parameter CONTROL_MAILBOX_JUMP_INST_PTR = 3'h6;
parameter CONTROL_JUMP_ADDRESS = 3'h7;
//
// Define the key registers in the I2C Master IP
//
// Note: These correspond to bits [2:0] of the register address field.
//
parameter I2C_MASTER_PRELO = 3'h0;
parameter I2C_MASTER_PREHI = 3'h1;
parameter I2C_MASTER_CTR = 3'h2;
parameter I2C_MASTER_TXR = 3'h3;
parameter I2C_MASTER_CR = 3'h4;
// Define the available registers in the TimeStamp Logic
//
// Note: These correspond to bits [2:0] of the register address field.
//
parameter TIMESTAMP_DELTA_SENSOR_0 = 3'h0;
parameter TIMESTAMP_DELTA_SENSOR_1 = 3'h1;
parameter TIMESTAMP_DELTA_SENSOR_2 = 3'h2;
parameter TIMESTAMP_DELTA_SENSOR_3 = 3'h3;
parameter TIMESTAMP_DELTA_GENERIC_LSB = 3'h4;
parameter TIMESTAMP_DELTA_GENERIC_MSB = 3'h5;
parameter TIMESTAMP_DELTA_INT_EVENT = 3'h6;
//
// Define the default location of the Mail Box structure in SM Memory
//
parameter MAILBOX_SM_ADDRESS = 8'hFF; // Note: This is "3FC" shifted by two to the right
//------Logic Operations----------
//
// I2C Interface to the Right Bank ASSP
//
assign I2C_wb_dat_o = MemReadDataIn[15:8];
assign i2c_masterDataToMem = I2C_wb_dat_i;
assign I2C_wb_we_o = wb_we;
assign I2C_wb_stb_o = wb_stb;
// Decode the Wishbone bus address space(s)
//
assign I2C_wb_cyc_o = (MemReadDataIn[7:3] == I2C_MASTER_ADR) & wb_cyc & ~CtrlMailBoxJumpInstCycle;
// Define the write enables controls for each register
//
assign control_sensor_manager_reg_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_SENSOR_MANAGER_ADDRESS}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign control_runtime_reg_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_RUNTIME_ADDRESS}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign control_wait_instr_reg_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_WAIT_INSTR_ADDRESS}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign control_receive_reg_dcd = ((MemReadDataIn[7:0] == { SENSOR_MANAGER_ADR, CONTROL_RECEIVE_ADDRESS})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_0})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_1})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_2})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_3})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_GENERIC_MSB})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_GENERIC_LSB})) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
// Define the write enable for the Interrupt event of the Time Stamp Logic
//
// Note: This write occurs after the write of interrupt data to SM Memory
//
assign SensorInterrupt_event_reg_we_dcd = (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_INT_EVENT}) & wb_cyc & wb_stb & ~wb_we & wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign SensorInterrupt_event_mask_we_dcd = (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_INT_EVENT}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign TimeStamp_Delta_lsb_reg_we_dcd = (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_GENERIC_LSB}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
// Deterimine if the current cycle is a write to the instruction pointer.
//
// Note: This only happens during the "jump" instruction
//
// This signals the Sensor Manager Statemachine that the current cycle
// is a "jump" and to load the register data value into the instruction
// pointer at the end of the current "register write" instruction.
//
assign control_jump_reg_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_JUMP_ADDRESS}) & ~CtrlMailBoxJumpInstCycle;
// Determine if the current cycle is the start of a Mail Box based Jump
// sequence.
//
// Note: The value of the bits in the Mail Box region of SM Memory determine
// if the current jump address should be loaded into the instruction
// pointer or if it should be ignored.
//
assign control_mailbox_tbl_ptr_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_MAILBOX_TABLE_PTR}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign control_mailbox_jump_inst_ptr_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_MAILBOX_JUMP_INST_PTR}) & wb_cyc & wb_stb & wb_we & wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
// Determine if the current address should include a write to the Sensor Manager's Memory
//
// Note: There is currently only one address but this may expand with, for
// example, a TimeStamp function.
//
assign save_reg_2_mem = ((MemReadDataIn[7:0] == { I2C_MASTER_ADR, I2C_MASTER_CR}) & MemReadDataIn[13] & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_0}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_1}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_2}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_3}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_GENERIC_LSB}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_GENERIC_MSB}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_INT_EVENT}) & ~CtrlMailBoxJumpInstCycle);
// Determine if the Wishbone device requires monitoring its busy signal
//
// Note: The only device currently supported is the I2C Master IP. This IP
// will generate a I2C bus cycle when the "read" or "write"
// bits are set in the control register.
//
assign wb_busy_poll = ((MemReadDataIn[7:0] == {I2C_MASTER_ADR, I2C_MASTER_CR }) & (MemReadDataIn[12] | MemReadDataIn[13]) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_WAIT_INSTR_ADDRESS}) & ~CtrlMailBoxJumpInstCycle);
// Determine when to start the Sensor Manager Statemachine
//
// Note: Use double-rank synchronization to resolve meta-stability issues.
//
// Simulation shows these signals toggle from TLC.v clock domain to
// the Sensor Manager's.
//
assign StartIn_stb = (StartFromFFE_5ff ^ StartFromFFE_6ff)
| (StartFromTLC_1ff ^ StartFromTLC_2ff);
// Define the Sensor Manager Control Registers
//
always @(posedge ClockIn or posedge ResetIn)
begin
if (ResetIn)
begin
wb_ack_sm <= 1'b0;
StartFromFFE_1ff <= 1'b0;
StartFromFFE_2ff <= 1'b0;
StartFromFFE_3ff <= 1'b0;
StartFromFFE_4ff <= 1'b0;
StartFromFFE_5ff <= 1'b0;
StartFromFFE_6ff <= 1'b0;
StartFromTLC_1ff <= 1'b0;
StartFromTLC_2ff <= 1'b0;
RunSM <= 1'b0;
CtrlReceiveAddressReg <= 10'h0;
CtrlRunTimeAddressReg <= 10'h0;
CtrlRunTimeAddressSM_1ff <= 1'b0;
CtrlRunTimeAddressSM_2ff <= 1'b0;
TimeStamp_Delta_sensor_0 <= 8'h0;
TimeStamp_Delta_sensor_1 <= 8'h0;
TimeStamp_Delta_sensor_2 <= 8'h0;
TimeStamp_Delta_sensor_3 <= 8'h0;
SensorInterrupt_0_1ff <= 4'h0;
SensorInterrupt_0_2ff <= 4'h0;
SensorInterrupt_0_3ff <= 4'h0;
SensorInterrupt_1_1ff <= 4'h0;
SensorInterrupt_1_2ff <= 4'h0;
SensorInterrupt_1_3ff <= 4'h0;
SensorInterrupt_2_1ff <= 4'h0;
SensorInterrupt_2_2ff <= 4'h0;
SensorInterrupt_2_3ff <= 4'h0;
SensorInterrupt_3_1ff <= 4'h0;
SensorInterrupt_3_2ff <= 4'h0;
SensorInterrupt_3_3ff <= 4'h0;
SensorInterrupt_0_o <= 1'b0;
SensorInterrupt_1_o <= 1'b0;
SensorInterrupt_2_o <= 1'b0;
SensorInterrupt_3_o <= 1'b0;
SensorInterrupt_event_mask_0 <= 1'b0;
SensorInterrupt_event_mask_1 <= 1'b0;
SensorInterrupt_event_mask_2 <= 1'b0;
SensorInterrupt_event_mask_3 <= 1'b0;
TimeStamp_Delta_capt <= 16'h0;
TimeStamp_Delta_readback <= 16'h0;
TimeStamp_Delta_Tog_1ff <= 1'b0;
TimeStamp_Delta_Tog_2ff <= 1'b0;
TimeStamp_Delta_Tog_3ff <= 1'b0;
CtrlMailBoxSegmentCtr <= 6'h0;
CtrlMailBoxSegmentCtr_ce <= 1'b0;
CtrlMailBoxTablePtr <= MAILBOX_SM_ADDRESS;
CtrlMailBoxJumpInstPtr <= 10'h0;
CtrlMailBoxJumpInstCycle <= 1'b0;
CtrlMailBoxJumpInstCycle_ce <= 1'b0;
control_wait_instr_cntr <= 13'h0;
control_wait_instr_cntr_tc <= 1'b0;
control_wait_instr_busy <= 1'b0;
end
else
begin
wb_ack_sm <= ((MemReadDataIn[7:3] == SENSOR_MANAGER_ADR )
| (MemReadDataIn[7:3] == TIMESTAMP_DELTA_ADR)
| (CtrlMailBoxJumpInstCycle)) & wb_cyc & wb_stb & ~wb_ack_sm;
// Double-rank synchronization between clock domains to avoid meta-state issues
//
StartFromFFE_1ff <= StartFromFFE;
StartFromFFE_2ff <= StartFromFFE_1ff;
StartFromFFE_3ff <= StartFromFFE_2ff;
StartFromFFE_4ff <= StartFromFFE_3ff;
StartFromFFE_5ff <= StartFromFFE_4ff;
StartFromFFE_6ff <= StartFromFFE_5ff;
StartFromTLC_1ff <= StartFromTLC;
StartFromTLC_2ff <= StartFromTLC_1ff;
CtrlRunTimeAddressSM_1ff <= CtrlRunTimeAddressSM;
CtrlRunTimeAddressSM_2ff <= CtrlRunTimeAddressSM_1ff;
// Define the Sensor Manager Control Register
//
// Note: A write of "0" to bit "0" of Sensor Manager Register "0" stops execution.
//
// The remaining bits of the "control" register can be used for other purposes.
//
if (StartIn_stb)
RunSM <= 1'b1;
else if (control_sensor_manager_reg_dcd)
RunSM <= MemReadDataIn[8];
// Define the Sensor Manager Receive Address Register
//
if (control_receive_reg_dcd)
CtrlReceiveAddressReg <= MemReadDataIn[17:8];
// Define the Sensor Manager Run-time Address Register
//
if (control_runtime_reg_dcd)
CtrlRunTimeAddressReg <= MemReadDataIn[17:8];
else if ( CtrlRunTimeAddressSM_1ff ^ CtrlRunTimeAddressSM_2ff)
CtrlRunTimeAddressReg <= CtrlRunTimeAddressOut;
// Synchronize the interrupt inputs to avoid meta-state issues
//
SensorInterrupt_0_1ff <= SensorInterrupt_0_i;
SensorInterrupt_0_2ff <= SensorInterrupt_0_1ff;
SensorInterrupt_0_3ff <= SensorInterrupt_0_2ff;
SensorInterrupt_1_1ff <= SensorInterrupt_1_i;
SensorInterrupt_1_2ff <= SensorInterrupt_1_1ff;
SensorInterrupt_1_3ff <= SensorInterrupt_1_2ff;
SensorInterrupt_2_1ff <= SensorInterrupt_2_i;
SensorInterrupt_2_2ff <= SensorInterrupt_2_1ff;
SensorInterrupt_2_3ff <= SensorInterrupt_2_2ff;
SensorInterrupt_3_1ff <= SensorInterrupt_3_i;
SensorInterrupt_3_2ff <= SensorInterrupt_3_1ff;
SensorInterrupt_3_3ff <= SensorInterrupt_3_2ff;
TimeStamp_Delta_Tog_1ff <= TimeStamp_Delta_Tog_i;
TimeStamp_Delta_Tog_2ff <= TimeStamp_Delta_Tog_1ff;
TimeStamp_Delta_Tog_3ff <= TimeStamp_Delta_Tog_2ff;
// Capture the external TimeStamp from the Communication Manager.
//
// Note: The Communication Manager uses the 32KHz clock for the
// TimeStamp function. In the current application, this is not
// the same clock used for the Sensor Manager. However, the
// Sensor Manager's clock is currently significantly faster than
// the 32KHz clock and can capture the TimeStamp value reliably
// when is receives the TimeStamp toggle signal from the
// Communication Manager.
//
// This scheme may need to be revisted if the clock assignments
// change on future designs.
//
if (TimeStamp_Delta_Tog_2ff ^ TimeStamp_Delta_Tog_3ff)
TimeStamp_Delta_capt <= TimeStamp_Delta_i;
// Capture the TimeStamp Value for a "generic" TimeStamp write to SM
// Memory.
//
// Note: The entire TimeStamp value is captured when a write of the
// LSB value to SM Memory is triggered. This allows for the
// writting of the MSB bits without the danger of the TimeStamp
// value changing between writes of each TimeStamp byte to
// SM Memory.
//
if (TimeStamp_Delta_lsb_reg_we_dcd)
TimeStamp_Delta_readback <= TimeStamp_Delta_capt;
// Capture the time stamp delta when an interrupt is detected.
//
// Note: See below for the definition of the bit operations.
//
if (SensorInterrupt_0_2ff && (!SensorInterrupt_0_3ff))
TimeStamp_Delta_sensor_0 <= TimeStamp_Delta_capt;
if (SensorInterrupt_1_2ff && (!SensorInterrupt_1_3ff))
TimeStamp_Delta_sensor_1 <= TimeStamp_Delta_capt;
if (SensorInterrupt_2_2ff && (!SensorInterrupt_2_3ff))
TimeStamp_Delta_sensor_2 <= TimeStamp_Delta_capt;
if (SensorInterrupt_3_2ff && (!SensorInterrupt_3_3ff))
TimeStamp_Delta_sensor_3 <= TimeStamp_Delta_capt;
// Set the Interrupt Status Mask bits
//
// Note: These bits are used "ANDed" with the write signal to clear
// individual status bits.
//
// The alternate way is to write the interrupt status once
// at the end of a series of SM code segments. However, there
// may be a significant amount of time between TimeStamp value
// capture and a single status being written to memory. This
// can allow the interrupt status to change after the TimeStamp
// is written to memory. This could result in the assumption
// of a good TimeStamp when, in fact, the TimeStamp is not
// valid.
//
if (SensorInterrupt_event_mask_we_dcd)
begin
SensorInterrupt_event_mask_0 <= MemReadDataIn[8];
SensorInterrupt_event_mask_1 <= MemReadDataIn[9];
SensorInterrupt_event_mask_2 <= MemReadDataIn[10];
SensorInterrupt_event_mask_3 <= MemReadDataIn[11];
end
// Set the interrupt event bit for each sensor when an interrupt is
// detected.
//
// Note: Without this "interrupt event bit" is may not be possible to
// know for certain if an interrupt happened. For example,
// a value of "0" may be correct given the right
// sampling period.
//
// These status bits assume a positive (i.e. low-to-high)
// interrupt assertion.
//
// All interrupts are cleared when this register is read.
//
if (SensorInterrupt_event_reg_we_dcd && SensorInterrupt_event_mask_0)
SensorInterrupt_0_o <= 1'h0;
else if (SensorInterrupt_0_2ff && (!SensorInterrupt_0_3ff))
SensorInterrupt_0_o <= 1'h1;
if (SensorInterrupt_event_reg_we_dcd && SensorInterrupt_event_mask_1)
SensorInterrupt_1_o <= 1'h0;
else if (SensorInterrupt_1_2ff && (!SensorInterrupt_1_3ff))
SensorInterrupt_1_o <= 1'h1;
if (SensorInterrupt_event_reg_we_dcd && SensorInterrupt_event_mask_2)
SensorInterrupt_2_o <= 1'h0;
else if (SensorInterrupt_2_2ff && (!SensorInterrupt_2_3ff))
SensorInterrupt_2_o <= 1'h1;
if (SensorInterrupt_event_reg_we_dcd && SensorInterrupt_event_mask_3)
SensorInterrupt_3_o <= 1'h0;
else if (SensorInterrupt_3_2ff && (!SensorInterrupt_3_3ff))
SensorInterrupt_3_o <= 1'h1;
// Mail Box Bit Counter
//
// Note: Reset Bit Counter between SM Sessions.
//
// This counter selects the Mail Box bits corresponding to each
// SM code segment.
//
if (!BusySM)
CtrlMailBoxSegmentCtr <= 6'h0;
else if (CtrlMailBoxSegmentCtr_ce)
CtrlMailBoxSegmentCtr <= CtrlMailBoxSegmentCtr + 1'b1;
CtrlMailBoxSegmentCtr_ce <= wb_cyc & wb_stb & wb_we & ~wb_ack_sm & CtrlMailBoxJumpInstCycle;
// Mail Box Table Address Pointer
//
// Note: This is the location in SM Memory where the Mail Box is
// located. Typically, the mail box will be in the last four
// 18-bit words in SM Memory.
//
// This value can be dynamically changed by instructions in SM
// memory.
//
if (control_mailbox_tbl_ptr_dcd)
CtrlMailBoxTablePtr <= MemReadDataIn[17:10];
// Mail Box Jump Address
//
// Note: This address must be temporarily storged while the Mail Box
// bits are being read from SM Memory.
//
// Based on the Mail Box bit for the current code segment, this
// jump address may or may not be used for a jump.
//
if (control_mailbox_jump_inst_ptr_dcd)
CtrlMailBoxJumpInstPtr <= MemReadDataIn[17:8];
// Mail Box Jump Decode Cycle Flag
//
// Note: This flags that the current SM write cycle is a Mail Box Jump
// decode operation.
//
// The data from SM Memory consist of Mail Box bits and should
// not be decoded as a SM "write" instruction would.
//
// The decode consists of selecting the correct bit from the
// Mail Box for the current SM code segment. Based on the state
// of this bit (i.e. 0 - No Jump; 1 - Jump), the SM instruction
// pointer will either proceed with the next instruction address
// or jump to a new code segment.
//
if (control_mailbox_jump_inst_ptr_dcd)
CtrlMailBoxJumpInstCycle <= 1'b1;
else if (CtrlMailBoxJumpInstCycle_ce)
CtrlMailBoxJumpInstCycle <= 1'b0;
CtrlMailBoxJumpInstCycle_ce <= wb_cyc & wb_stb & wb_we & wb_ack_sm & ~control_mailbox_jump_inst_ptr_dcd;
// Wait Instruction Register
//
if (control_wait_instr_reg_dcd || control_wait_instr_busy)
begin
control_wait_instr_cntr <= control_wait_instr_cntr_nxt;
control_wait_instr_cntr_tc <= control_wait_instr_cntr_tc_nxt;
end
control_wait_instr_busy <= control_wait_instr_busy_nxt;
end
end
// Define the Wait Instruction Busy signal
//
// Note: This busy starts with the first write and ends when the counter is done.
//
// This is an N-1 counter. Therefore, a value of "0" means an "N" of "1".
// Therefore, there should be one cycle of busy even with a value of "0".
//
assign control_wait_instr_busy_nxt = (~control_wait_instr_busy & control_wait_instr_reg_dcd)
| ( control_wait_instr_busy & ~control_wait_instr_cntr_tc);
// Define the operation of the Wait Instruction Counter
//
always @(MemReadDataIn or
control_wait_instr_busy or
control_wait_instr_cntr
)
begin
case({control_wait_instr_busy, MemReadDataIn[17]})
2'b00: // MSB == 0 then count 1-to-1
begin
control_wait_instr_cntr_nxt <= {4'h0, MemReadDataIn[16:8] };
control_wait_instr_cntr_tc_nxt <= ( MemReadDataIn[16:8] == 9'h0);
end
2'b01: // MSB == 1 then count 16-to-1
begin
control_wait_instr_cntr_nxt <= { MemReadDataIn[16:8], 4'hF}; // Remember: N-1 means that "0" should be one wait period
control_wait_instr_cntr_tc_nxt <= 1'b0;
end
2'b10: // Normal Count
begin
control_wait_instr_cntr_nxt <= control_wait_instr_cntr - 13'h1;
control_wait_instr_cntr_tc_nxt <= (control_wait_instr_cntr == 13'h1);
end
2'b11: // Normal Count - The value was shift << 4 so it is already 16x larger at loading time
begin
control_wait_instr_cntr_nxt <= control_wait_instr_cntr - 13'h1;
control_wait_instr_cntr_tc_nxt <= (control_wait_instr_cntr == 13'h1);
end
endcase
end
// Use the "run" bit to signal when the statemachine is "busy" in addition to
// the statemachine busy bit.
//
assign BusyOut = RunSM | BusySM;
// Define the Sensor Manager Memory's read address
//
// Note: StateMachine is allowed to read all of SensorManager Memory
//
// The Sensor Manager Memory's "read" port is 10-bits (i.e. [9:0])
//
// Select the Mail Box Address pointer during Mail Box Jump operations.
// The location pointed to contains Mail Box Jump enable bits AND NOT
// SM instructions.
//
assign MemReadAddressOut = CtrlMailBoxJumpInstCycle ? {CtrlMailBoxTablePtr, CtrlMailBoxSegmentCtr[5:4]}
: StateMachineCtrlMemAddr ;
// Limit the register write function to the upper half of the Sensor Manager's Memory space
//
// Note: The Sensor Manager Memory's "write" port address is 10-bits (i.e. [9:0])
//
assign MemWriteAddressOut = CtrlReceiveAddressReg;
// Define the Data to be written to Sensor Memory
//
// Note: The I2C Master IP only outputs byte wide values
//
// For the current design, the following are read back:
// - I2C Master IP is read back
// - TimeStamp registers for four sensors
// - TimeSTamp related interrupt event register
//
// Only the I2C Master IP was supported in previous designs
//
always @(MemReadDataIn or
MemWriteDataOut or
i2c_masterDataToMem or
TimeStamp_Delta_sensor_0 or
TimeStamp_Delta_sensor_1 or
TimeStamp_Delta_sensor_2 or
TimeStamp_Delta_sensor_3 or
TimeStamp_Delta_readback or
SensorInterrupt_0_o or
SensorInterrupt_1_o or
SensorInterrupt_2_o or
SensorInterrupt_3_o
)
begin
case(MemReadDataIn[7:3])
I2C_MASTER_ADR: MemWriteDataOut <= {1'b0, i2c_masterDataToMem};
TIMESTAMP_DELTA_ADR:
begin
case(MemReadDataIn[2:0])
TIMESTAMP_DELTA_SENSOR_0 : MemWriteDataOut <= {1'b0, TimeStamp_Delta_sensor_0};
TIMESTAMP_DELTA_SENSOR_1 : MemWriteDataOut <= {1'b0, TimeStamp_Delta_sensor_1};
TIMESTAMP_DELTA_SENSOR_2 : MemWriteDataOut <= {1'b0, TimeStamp_Delta_sensor_2};
TIMESTAMP_DELTA_SENSOR_3 : MemWriteDataOut <= {1'b0, TimeStamp_Delta_sensor_3};
TIMESTAMP_DELTA_GENERIC_LSB : MemWriteDataOut <= {1'b0, TimeStamp_Delta_readback[7:0]};
TIMESTAMP_DELTA_GENERIC_MSB : MemWriteDataOut <= {1'b0, TimeStamp_Delta_readback[15:8]};
TIMESTAMP_DELTA_INT_EVENT : MemWriteDataOut <= {4'h0, SensorInterrupt_3_o,
SensorInterrupt_2_o,
SensorInterrupt_1_o,
SensorInterrupt_0_o};
default: MemWriteDataOut <= {1'b0, i2c_masterDataToMem};
endcase
end
default: MemWriteDataOut <= {1'b0, i2c_masterDataToMem};
endcase
end
// Define the Sensor Manager Memory's clock
//
// Note: This is currently a flow through but this may change in future designs.
//
assign MemClockOut = ClockIn;
// Combine all Wishbone bus acknowledges
//
// Note: Only one acknowledge should happen at a time.
//
assign wb_ack = wb_ack_sm | I2C_wb_ack_i;
// Multiplex the address to the I2C Master IP when performing an I2C read
//
// Note: The address must be switched from the I2C "Control" Register to the I2C "Transmit/Receive" data address.
//
// This only affects the I2C Master IP and does not affect any other device on the Wishbone bus.
//
assign I2C_wb_adr_o = ((MemReadDataIn[7:0] == {I2C_MASTER_ADR, I2C_MASTER_CR}) & MemReadDataIn[13] & (~wb_we))
? I2C_MASTER_TXR : MemReadDataIn[2:0];
//------Instantiate Modules----------------
//
// Instantiate the Sensor Manager Statemachine
//
StateMachine StateMachine_inst (
.CLK_IN ( ClockIn ),
.RESET_IN ( ResetIn ),
.RUNTIME_ADDRESS ( CtrlRunTimeAddressReg ),
.CONTROL_JUMP_REG_DCD ( control_jump_reg_dcd ),
.SAVE_REG_2_MEM ( save_reg_2_mem ),
.MAILBOX_JUMP_INST_CYCLE (CtrlMailBoxJumpInstCycle ),
.MAILBOX_JUMP_INST_PTR (CtrlMailBoxJumpInstPtr ),
.MAILBOX_SEGMENT_CTR (CtrlMailBoxSegmentCtr[3:0] ),
.WB_ACK_I ( wb_ack ),
.WB_BUSY_I ( I2C_tip_i | control_wait_instr_busy ),
.WB_BUSY_POLL_I ( wb_busy_poll ),
.WB_WE_O ( wb_we ),
.WB_STB_O ( wb_stb ),
.WB_CYC_O ( wb_cyc ),
.SM_CNTL_REG_RUN ( RunSM ),
.SM_READ_DATA ( MemReadDataIn ), // Data "Byte" is MemReadDataIn[17:8]
.SM_INSTR_PTR ( StateMachineCtrlMemAddr ),
.SM_READ_SELECT ( MemReadEnableOut ),
.SM_WRITE_SELECT ( MemWriteEnableOut ),
.SM_BUSY ( BusySM )
);
// test points
//
assign TP1 = I2C_tip_i;
assign TP2 = BusyOut;
assign TP3 = 0;
// Logic to generate SmClockSelect_o
wire d_SmClockSelect;
always @(posedge ClockIn or posedge ResetIn)
begin
if (ResetIn)
begin
s1_BusyOut <= 1'b0;
s2_BusyOut <= 1'b0;
SmClockSelect_o <= 1'b0;
end
else
begin
s1_BusyOut <= BusyOut;
s2_BusyOut <= s1_BusyOut;
SmClockSelect_o <= d_SmClockSelect;
end
end
assign d_SmClockSelect = SmClockSelect_o ? ((!s1_BusyOut && s2_BusyOut) ? 1'b0 : 1'b1) : ((StartFromFFE_1ff ^ StartFromFFE_2ff) ? 1'b1: 1'b0);
endmodule

View File

@ -0,0 +1,608 @@
// -----------------------------------------------------------------------------
// title : Sensor Manager Statemachine
// project : ULP Sensor Hub
// -----------------------------------------------------------------------------
// file : StateMachine.v
// author : Glen Gomes
// company : QuickLogic Corp
// created : 2013/12/06
// last update : 2013/12/06
// platform : PolarPro III
// standard : Verilog 2001
// -----------------------------------------------------------------------------
// description: The Sensor Manger Statemachine is responsible for controlling the
// operations of the Sensor Manager. These include performing
// transfers between Sensor Memory and various registers.
// -----------------------------------------------------------------------------
// copyright (c) 2013
// -----------------------------------------------------------------------------
// revisions :
// date version author description
// 2013/12/06 1.0 Glen Gomes created
// 2014/05/27 1.1 Glen Gomes Updated for Tay
// -----------------------------------------------------------------------------
// Comments: This solution is specifically for use with the QuickLogic
// PolarPro III device.
// -----------------------------------------------------------------------------
`timescale 1ns/10ps
module StateMachine (
CLK_IN,
RESET_IN,
RUNTIME_ADDRESS,
CONTROL_JUMP_REG_DCD,
SAVE_REG_2_MEM,
MAILBOX_JUMP_INST_CYCLE,
MAILBOX_JUMP_INST_PTR,
MAILBOX_SEGMENT_CTR,
WB_ACK_I,
WB_BUSY_I,
WB_BUSY_POLL_I,
WB_WE_O,
WB_STB_O,
WB_CYC_O,
SM_CNTL_REG_RUN,
SM_READ_DATA,
SM_INSTR_PTR,
SM_READ_SELECT,
SM_WRITE_SELECT,
SM_BUSY
);
//-----Port Signals--------------------
//
input CLK_IN;
input RESET_IN;
input [9:0] RUNTIME_ADDRESS;
input CONTROL_JUMP_REG_DCD;
input SAVE_REG_2_MEM;
input MAILBOX_JUMP_INST_CYCLE;
input [9:0] MAILBOX_JUMP_INST_PTR;
input [3:0] MAILBOX_SEGMENT_CTR;
input WB_ACK_I;
input WB_BUSY_I;
input WB_BUSY_POLL_I;
output WB_WE_O;
output WB_STB_O;
output WB_CYC_O;
input SM_CNTL_REG_RUN;
input [17:0] SM_READ_DATA;
output [9:0] SM_INSTR_PTR;
output SM_READ_SELECT;
output SM_WRITE_SELECT;
output SM_BUSY;
wire CLK_IN;
wire RESET_IN;
wire [9:0] RUNTIME_ADDRESS;
wire CONTROL_JUMP_REG_DCD;
wire SAVE_REG_2_MEM;
wire MAILBOX_JUMP_INST_CYCLE;
wire [9:0] MAILBOX_JUMP_INST_PTR;
wire [3:0] MAILBOX_SEGMENT_CTR;
wire WB_ACK_I;
wire WB_BUSY_I;
wire WB_BUSY_POLL_I;
reg WB_WE_O;
reg wb_we_o_nxt;
reg WB_STB_O;
reg wb_stb_o_nxt;
reg WB_CYC_O;
reg wb_cyc_o_nxt;
wire SM_CNTL_REG_RUN;
wire [17:0] SM_READ_DATA;
reg [9:0] SM_INSTR_PTR;
reg [9:0] sm_instr_ptr_nxt;
reg SM_READ_SELECT;
reg sm_read_select_nxt;
reg SM_WRITE_SELECT;
reg sm_write_select_nxt;
reg SM_BUSY;
reg sm_busy_nxt;
//-----Internal Signals--------------------
//
//
// Define the Statemachine registers
//
reg [3:0] sensor_manager_sm;
reg [3:0] sensor_manager_sm_nxt;
//
// Define the Instruction Pointer variables
//
reg sm_instr_ptr_ce;
reg sm_instr_ptr_ce_nxt;
reg sm_instr_ptr_ld;
reg sm_instr_ptr_ld_nxt;
//reg sm_instr_ptr_sel;
//reg sm_instr_ptr_sel_nxt;
reg mailbox_jump_inst_ptr_ld;
//------Define Parameters---------
//
//
// Define the Sensor Manager Statemachine States
//
// Note: These states are chosen to allow for overlap of various signals
// during operation. This overlap should help reduce timing
// dependancies.
//
parameter SM_IDLE = 4'h0;
parameter SM_INC_PTR = 4'h1;
parameter SM_INST_RD = 4'h2;
//parameter SM_INST_DCD = 4'h3; // Note: Will be used for TimeStamp Support in a future design
parameter SM_REG_WR = 4'h4;
parameter SM_REG_RD = 4'h5;
parameter SM_WAIT_BUSY_ON = 4'h6;
parameter SM_WAIT_BUSY_OFF = 4'h7;
//
// Sensor Manager Initialization Start Address
//
// Note: The previous IP used the reset of the "RuntimeAddress" register to
// select the sensor initialization code. This value explicity selects
// the value for the start (or re-start) of initialization.
//
parameter SM_INIT_INSTR_ADR = 10'h0; // Address for the start in initialization instructions
//------Logic Operations----------
//
//
// Define the Instruction Pointer
//
// Note: This pointer can start at either the sensor initialization code start
// address or the run-time code start address.
//
always @( SM_INSTR_PTR or
sm_instr_ptr_ld or
sm_instr_ptr_ce or
SM_READ_DATA or
CONTROL_JUMP_REG_DCD or
RUNTIME_ADDRESS or
MAILBOX_JUMP_INST_CYCLE or
MAILBOX_JUMP_INST_PTR
)
begin
case({sm_instr_ptr_ld, sm_instr_ptr_ce})
2'b00: sm_instr_ptr_nxt <= SM_INSTR_PTR; // Hold Current Value
2'b01: sm_instr_ptr_nxt <= SM_INSTR_PTR + 1'b1; // Increment to the next address
2'b10:
begin
case({MAILBOX_JUMP_INST_CYCLE, CONTROL_JUMP_REG_DCD})
2'b00: sm_instr_ptr_nxt <= RUNTIME_ADDRESS; // Run-time Code Address
2'b01: sm_instr_ptr_nxt <= SM_READ_DATA[17:8]; // Jump Address
default: sm_instr_ptr_nxt <= MAILBOX_JUMP_INST_PTR; // Mail Box Jump Address
endcase
end
2'b11: sm_instr_ptr_nxt <= SM_INSTR_PTR; // Hold Current Value
endcase
end
// Select the Mail Box Jump Enable Bit
//
// Note: Mail Box Jump enable bits are spread over 16-bits of the 18-bits from
// SM Memory.
//
always @( MAILBOX_SEGMENT_CTR or
SM_READ_DATA or
mailbox_jump_inst_ptr_ld
)
begin
case(MAILBOX_SEGMENT_CTR)
4'h0: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[0];
4'h1: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[1];
4'h2: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[2];
4'h3: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[3];
4'h4: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[4];
4'h5: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[5];
4'h6: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[6];
4'h7: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[7];
4'h8: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[9];
4'h9: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[10];
4'hA: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[11];
4'hB: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[12];
4'hC: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[13];
4'hD: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[14];
4'hE: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[15];
4'hF: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[16];
endcase
end
// Define the registers associated with the Sensor Manager Statemachine
//
always @(posedge CLK_IN or posedge RESET_IN)
begin
if (RESET_IN)
begin
sensor_manager_sm <= SM_IDLE;
SM_INSTR_PTR <= 10'h0;
sm_instr_ptr_ce <= 1'b0;
sm_instr_ptr_ld <= 1'b0;
WB_WE_O <= 1'b0;
WB_STB_O <= 1'b0;
WB_CYC_O <= 1'b0;
SM_READ_SELECT <= 1'b0;
SM_WRITE_SELECT <= 1'b0;
SM_BUSY <= 1'b0;
end
else
begin
sensor_manager_sm <= sensor_manager_sm_nxt;
SM_INSTR_PTR <= sm_instr_ptr_nxt;
sm_instr_ptr_ce <= sm_instr_ptr_ce_nxt;
sm_instr_ptr_ld <= sm_instr_ptr_ld_nxt;
WB_WE_O <= wb_we_o_nxt;
WB_STB_O <= wb_stb_o_nxt;
WB_CYC_O <= wb_cyc_o_nxt;
SM_READ_SELECT <= sm_read_select_nxt;
SM_WRITE_SELECT <= sm_write_select_nxt;
SM_BUSY <= sm_busy_nxt;
end
end
// Define the Sensor Manager Statemachine
//
always @( sensor_manager_sm or
SM_CNTL_REG_RUN or
CONTROL_JUMP_REG_DCD or
SAVE_REG_2_MEM or
WB_BUSY_I or
WB_BUSY_POLL_I or
WB_ACK_I or
MAILBOX_JUMP_INST_CYCLE or
mailbox_jump_inst_ptr_ld
)
begin
case(sensor_manager_sm)
SM_IDLE:
begin
case(SM_CNTL_REG_RUN)
1'b0: // No Activity
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
end
1'b1: // Start at the Sensor Run-Time Code
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b1;
end
endcase
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
SM_INC_PTR:
begin
sensor_manager_sm_nxt <= SM_INST_RD;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b1;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
SM_INST_RD:
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
SM_REG_WR:
begin
sm_read_select_nxt <= 1'b0;
case(SM_CNTL_REG_RUN)
1'b0: // A write of "0" to bit "0" of the Command register at address "0" turns off
// the Sensor Manager's Statemachine
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
1'b1: // Sensor Manager Statemachine is not stopped; continue processing
begin
sm_busy_nxt <= 1'b1;
case({WB_BUSY_POLL_I, WB_ACK_I})
2'b00: // Wait for Wish Bone Acknowledge and no need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b01: // Wish Bone Acknowledge Received and no need to wait for transfer complete
begin
case(SAVE_REG_2_MEM)
1'b0:
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ld_nxt <= CONTROL_JUMP_REG_DCD
| (MAILBOX_JUMP_INST_CYCLE & mailbox_jump_inst_ptr_ld);
sm_instr_ptr_ce_nxt <= ~ CONTROL_JUMP_REG_DCD
& ~ MAILBOX_JUMP_INST_CYCLE;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
1'b1:
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
endcase
end
2'b10: // Wait for Wish Bone Acknowledge and will need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b11: // Acknowledge received but need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_ON;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
endcase
end
SM_REG_RD:
begin
sm_busy_nxt <= 1'b1;
sm_read_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
case(WB_ACK_I)
1'b0: // Waiting for Wish Bone Acknowledge
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
1'b1: // Got Wish Bone Acknowledge
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ld_nxt <= CONTROL_JUMP_REG_DCD;
sm_instr_ptr_ce_nxt <= ~CONTROL_JUMP_REG_DCD;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
SM_WAIT_BUSY_ON:
begin
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
case(WB_BUSY_I)
1'b0: sensor_manager_sm_nxt <= SM_WAIT_BUSY_ON; // Wait for Busy from I/F
1'b1: sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF; // Got Busy from I/F
endcase
end
SM_WAIT_BUSY_OFF:
begin
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
case({SAVE_REG_2_MEM, WB_BUSY_I})
2'b00: // Wishbone transfer complete; no need to write anything to Sensor Manager Memory
//
// Note: Writes to the command register do not enter this state.
// Therefore, there is no need to check for the end of processing.
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ce_nxt <= 1'b1;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
2'b01: // Wait for Wishbone transfer to complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
2'b10: // Wishbone transfer complete; Write resulting register value to Sensor Manager Memory
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b11: // Wait for Wishbone transfer to complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
default:
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
endmodule

View File

@ -0,0 +1,128 @@
`timescale 1ns / 10ps
module SystemClockControl (
OperatingClockRef_i,
Clock32KIn_i,
SPIClock_i,
ResetIn_i,
FfeClkSelect_i,
SmClkSelect_i,
SmSpeedSelect_i,
SpiClkSelect_i,
ClkSourceSelect_i,
Clk32KhzEnable_i,
MainClkEnable_i,
FfeClkEnable_i,
CM_AutoDrain_Busy,
SmClock_o,
FfeClock_o,
FfeClock_x2_o,
clock_32KHz_o,
multiplierClk_o,
ClockGen_State_o,
CM_FIFO_ReadClk,
clk_ringosc_i,
clk_ringosc_x2_i,
enable_i,
clk_cal_value_o,
assp_ringosc_en_o
);
// IO Declaration
input OperatingClockRef_i;
input Clock32KIn_i;
input SPIClock_i;
input ResetIn_i;
input [2:0] FfeClkSelect_i;
input [2:0] SmClkSelect_i;
input SmSpeedSelect_i;
input SpiClkSelect_i;
input ClkSourceSelect_i;
input Clk32KhzEnable_i;
input MainClkEnable_i;
input FfeClkEnable_i;
input CM_AutoDrain_Busy;
output SmClock_o;
output FfeClock_o;
output FfeClock_x2_o;
output clock_32KHz_o;
output multiplierClk_o;
output [3:0] ClockGen_State_o;
output CM_FIFO_ReadClk;
input clk_ringosc_i;
input clk_ringosc_x2_i;
input enable_i;
output [15:0] clk_cal_value_o;
output assp_ringosc_en_o;
reg multiplierClk_o;
wire [3:0] ClockGen_State_o;
wire CM_FIFO_ReadClk;
wire assp_ringosc_en_o;
// Internal Signals Declaration
wire highSpeedClock, highSpeedClock_buff, highSpeedClock_x2_buff;
reg [6:0] ClockDiv;
wire FfeClock;
reg SmClock;
wire RingOscEnable;
wire ring_osc_clk;
wire OperatingClockRef;
// Operations
// Gating the enternal osc
// assign OperatingClockRef = OperatingClockRef_i && MainClkEnable_i;
assign OperatingClockRef = OperatingClockRef_i;
// CM FIFO AutoDrain Read Clock
// assign CM_FIFO_ReadClk = CM_AutoDrain_Busy ? (FfeClock && FfeClkEnable_i): SPIClock_i;
assign CM_FIFO_ReadClk = CM_AutoDrain_Busy ? highSpeedClock_buff : SPIClock_i;
// Ring Osclilator enable when the when weither FFE or SM is busy
// assign RingOscEnable = !ResetIn_i && MainClkEnable_i && ClkSourceSelect_i;
// Logic to gate 32KHz clock when the ULPSH goes to sleep
// Only static power consumption
assign clock_32KHz_o = Clock32KIn_i && Clk32KhzEnable_i;
// Logic to select between the external high speed clock and the internal ring oscillation
// and main clock division
// assign highSpeedClock = ClkSourceSelect_i ? ring_osc_clk : OperatingClockRef;
buff buff_highSpeedClock (.A(clk_ringosc_i), .Q(highSpeedClock_buff)); // don't use a clock network for this
//pragma attribute buff_highSpeedClock dont_touch true
buff buff_highSpeedClock_x2 (.A(clk_ringosc_x2_i), .Q(highSpeedClock_x2_buff)); // don't use a clock network for this
//pragma attribute buff_highSpeedClock_x2 dont_touch true
// FFE CLK and SM CLK select and masking
// assign FfeClock_o = SpiClkSelect_i ? SPIClock_i : FfeClock && FfeClkEnable_i;
// assign SmClock_o = SmSpeedSelect_i ? SmClock : (SpiClkSelect_i ? SPIClock_i : FfeClock);
assign FfeClock_o = SpiClkSelect_i ? SPIClock_i : highSpeedClock_buff;
assign FfeClock_x2_o = SpiClkSelect_i ? SPIClock_i : highSpeedClock_x2_buff;
assign SmClock_o = SpiClkSelect_i ? SPIClock_i : highSpeedClock_buff;
ring_osc_adjust ring_osc_adjust_1 (
.reset_i ( ResetIn_i ),
.clk_ringosc_i ( clk_ringosc_i ),
.clk_32khz_i ( Clock32KIn_i ),
.enable_i ( enable_i ),
.cal_val_o ( clk_cal_value_o )
);
assign assp_ringosc_en_o = ClkSourceSelect_i || MainClkEnable_i;
endmodule

View File

@ -0,0 +1,731 @@
/*------------------------------------------------------------------------------------------
Title: TLC.v
Description:
--------------------------------------------------------------------------------------------
Revision History:
--------------------------------------------------------------------------------------------
To Do:
------------------------------------------------------------------------------------------*/
`timescale 1ns / 10ps
`include "SensorHubDefines.v"
`include "ulpsh_rtl_defines.v"
module TLC (
// General interface
input SPI_SCLK,
input FFE_Clock,
input Clock32KIn,
input ResetIn,
output SW_Reset,
output reg RingOsc_cal_en,
output reg [2:0] RingOsc_select,
input [15:0] RingOsc_cal_value,
input I2C_Master_Error,
input FFEBusyIn,
input SMBusyIn,
input SMOverrunIn,
output StartFFEOut,
// output InitSMOut, // Removed for Rel 0 on 6/18
output StartSMOut,
output reg [15:0] TimeStampOut,
output reg TimeStampOut_Tog,
output UseFastClockOut,
input [7:0] InterruptMsgFromFFEIn,
output InterruptPinOut,
input SensorInterruptIn,
output [31:0] FFE_Mailbox_Out,
input [9:0] CtrlRunTimeAddressReg, // Expanded for Rel 0 on 6/18
output reg [9:0] CtrlRunTimeAddressOut, // Expanded for Rel 0 on 6/18
output reg CtrlRunTimeAddressSM,
// Interface to SPI Slave
input [6:0] RegAddrIn,
input [7:0] RegDataIn,
output reg [7:0] RegDataOut,
input RegWriteEnableIn,
input RegReadDataAckIn,
// Interface to memories
output TLCDrivingFFEControlMem,
output TLCDrivingFFEDataMem1,
output TLCDrivingFFEDataMem2,
output TLCDrivingSMMem,
output TLCDrivingCMMem,
output MemorySelect_en,
output [2:0] MemorySelect,
output [11:0] MemoryAddressOut,
output [35:0] MemoryDataOut,
input [35:0] MemoryDataIn,
output reg MemoryReadEnableOut,
output reg MemoryWriteEnableOut,
output MemoryClockOut,
// Interface to Communication Manager FIFO
output reg CM_FIFO_ReadEnable,
input [8:0] CM_FIFO_ReadData,
input [3:0] CM_FIFO_PopFlags,
input [3:0] CM_FIFO_PushFlags,
input CM_FIFO_Overflow,
output CM_RingBufferMode,
input CM_AutoDrain_Busy,
// test points
output TP1,
output TP2,
// LEDs ON/OFF Control
output reg [2:0] leds_off_o,
// FFE CLock ENable
output reg FFE_CLK_Enable_o,
output reg ClockEnable_o,
output reg clock_32KHz_Enable_o,
output reg [2:0] FFE_Clock_Control_o,
output reg [2:0] SM_Clock_Control_o,
output reg ClkSourceSelect_o
);
parameter CYCLES_PER_MSEC = 33; // number of 32.768KHz clock cycles per millisecond
reg [7:0] CommandReg;
reg [7:0] msecs_per_sample_reg;
reg [7:0] MemSelect_reg;
reg [7:0] MemAddrLow;
reg [7:0] MemAddrHigh;
reg [7:0] MemDataByte0;
reg [7:0] MemDataByte1;
reg [7:0] MemDataByte2;
reg [7:0] MemDataByte3;
reg [3:0] MemDataByte4;
reg [7:0] CM_Control_reg;
reg WaitForMemRead;
reg WaitForMemWrite;
reg IncrementMemAddr;
reg StartFFE_32K, StartFFE_Clkin;
// reg InitSM_Clkin; // Removed for Rel 0 on 6/18
reg StartSM_Clkin;
reg [7:0] clock32K_count; // this needs to be wide enough to accomodate the CYCLES_PER_MSEC constant
reg [7:0] count_msecs;
wire pulse_1ms;
wire pulse_sample_period;
reg pulse_sample_period_reg;
wire FFE_Holdoff; // Used to ensure a full count on the First FFE run
reg FFE_Holdoff_reset;
reg FFE_Holdoff_preset;
wire RunFFEContinuously;
//wire RunFFEOnce;
//wire RunSMOnce;
//wire RunSensorInit;
wire CM_FIFO_Overflow_reg;
reg [3:0] CM_FIFO_PopFlags_r1;
reg [3:0] CM_FIFO_PopFlags_r2;
reg [3:0] CM_FIFO_PopFlags_sync;
wire I2C_Master_Error_reg;
reg [7:0] InterruptCtrl_reg;
reg [7:0] InterruptFFEMsg_clear;
wire Interrupt_En_0;
wire [7:0] InterruptFFEMsg_latched;
wire InterruptFFEMsg_ORed;
reg SW_Reset_Start;
reg SW_Reset_r1;
reg SW_Reset_r2;
reg RunFFEContinuously_r1;
reg RunFFEContinuously_r2;
reg FFEOverrun;
reg [31:0] FFE_Mailbox_reg;
wire i_StartFFEOut;
reg s1_StartFFEOut, s2_StartFFEOut;
reg s3_FFEBusyIn, s2_FFEBusyIn, s1_FFEBusyIn;
reg d_FFE_CLK_Enable;
reg s1_SMBusyIn, s2_SMBusyIn, s3_SMBusyIn;
wire d_ClockEnable;
wire smInit_enable;
// reg s1_InitSM_Clkin, s2_InitSM_Clkin, s3_InitSM_Clkin, s4_InitSM_Clkin, s5_InitSM_Clkin, s6_InitSM_Clkin; // Removed for Rel 0 on 6/18
reg s1_StartSM_Clkin, s2_StartSM_Clkin, s3_StartSM_Clkin, s4_StartSM_Clkin, s5_StartSM_Clkin, s6_StartSM_Clkin;
wire [2:0] FFE_SET, SM_SET;
wire clkSourceSelect;
reg SleepMode, IntInputLevel;
reg sensorInterrupt_s1, sensorInterrupt_s2, sensorInterrupt_s3;
wire sleepModeSet, sleepReset;
assign FFE_Mailbox_Out = {FFE_Mailbox_reg[15:0], FFE_Mailbox_reg[31:16]};
assign MemoryClockOut = SPI_SCLK;
assign RunFFEContinuously = CommandReg[0];
//assign RunFFEOnce = CommandReg[1];
//assign RunSMOnce = CommandReg[2];
//assign RunSensorInit = CommandReg[3];
//assign SW_Reset = CommandReg[6];
assign UseFastClockOut = CommandReg[7];
assign Interrupt_En_0 = InterruptCtrl_reg[0];
assign Interrupt_En_1 = InterruptCtrl_reg[1];
assign TLCDrivingFFEControlMem = MemSelect_reg[7] ? (MemSelect_reg[2:0] == 3'b000) : 1'b0;
assign TLCDrivingFFEDataMem1 = MemSelect_reg[7] ? (MemSelect_reg[2:0] == 3'b001) : 1'b0;
assign TLCDrivingFFEDataMem2 = MemSelect_reg[7] ? (MemSelect_reg[2:0] == 3'b010) : 1'b0;
assign TLCDrivingSMMem = MemSelect_reg[7] ? (MemSelect_reg[2:0] == 3'b011) : 1'b0;
assign TLCDrivingCMMem = 1'b0; // should be removed, since the CMMem is now the CM FIFO
assign MemorySelect_en = MemSelect_reg[7];
assign MemorySelect = MemSelect_reg[2:0];
assign MemoryAddressOut = {MemAddrHigh[3:0],MemAddrLow};
assign MemoryDataOut = {MemDataByte4[3:0],MemDataByte3,MemDataByte2,MemDataByte1,MemDataByte0};
assign CM_RingBufferMode = CM_Control_reg[0];
// requests to run FFE and Sensor Manager
assign pulse_1ms = (clock32K_count == (CYCLES_PER_MSEC - 1)); // 1-clock pulse each time 1ms has elapsed
assign pulse_sample_period = (pulse_1ms && (count_msecs == 1)); // 1-clock pulse @ each sample period
assign StartFFEOut = s2_StartFFEOut;
// Delay starting FFE
always @(posedge Clock32KIn or posedge ResetIn)
begin
if (ResetIn)
begin
s1_StartFFEOut <= 1'b0;
s2_StartFFEOut <= 1'b0;
end
else
begin
s1_StartFFEOut <= i_StartFFEOut;
s2_StartFFEOut <= s1_StartFFEOut;
end
end
// Synchronized FFE Busy input
// & logic to generate FFE_CLK_Enable (active when timer starts and off when busy end)
always @(posedge Clock32KIn or posedge ResetIn)
begin
if (ResetIn)
begin
s1_FFEBusyIn <= 0;
s2_FFEBusyIn <= 0;
s3_FFEBusyIn <= 0;
end
else
begin
s1_FFEBusyIn <= FFEBusyIn;
s2_FFEBusyIn <= s1_FFEBusyIn;
s3_FFEBusyIn <= s2_FFEBusyIn;
end
end
always @*
begin
if (!FFE_CLK_Enable_o)
d_FFE_CLK_Enable = s1_StartFFEOut ^ i_StartFFEOut;
else
if (s3_FFEBusyIn && !s2_FFEBusyIn)
d_FFE_CLK_Enable = 1'b0;
else
d_FFE_CLK_Enable = FFE_CLK_Enable_o;
end
always @(posedge Clock32KIn or posedge ResetIn)
begin
if (ResetIn)
begin
FFE_CLK_Enable_o <= 0;
end
else
begin
FFE_CLK_Enable_o <= d_FFE_CLK_Enable;
end
end
always @(posedge Clock32KIn or posedge ResetIn) begin
if (ResetIn) begin
clock32K_count <= 0;
count_msecs <= 1; // reset to 1 (sample period = 0 does not make sense, and should be invalid)
pulse_sample_period_reg <= 0;
TimeStampOut <= 0;
TimeStampOut_Tog <= 0;
StartFFE_32K <= 0;
FFEOverrun <= 0;
end else begin
pulse_sample_period_reg <= pulse_sample_period; // de-glitch the pulse_sample_period signal, since it's used to asynchronously reset FFE_Holdoff
if (pulse_1ms) begin
clock32K_count <= 0;
TimeStampOut <= TimeStampOut + 1; // the timestamp increments @ 1ms
TimeStampOut_Tog <= ~TimeStampOut_Tog; // the timestamp increments @ 1ms
end else begin
clock32K_count <= clock32K_count + 1;
TimeStampOut <= TimeStampOut;
TimeStampOut_Tog <= TimeStampOut_Tog;
end
if (pulse_sample_period) // sample period boundary
count_msecs <= msecs_per_sample_reg; // reset the msec counter back to the register value
else
if (pulse_1ms)
count_msecs <= count_msecs - 1; // decrement by 1 @ the 1ms boundary
else
count_msecs <= count_msecs;
//if ((clock32K_count == (CYCLES_PER_MSEC - 1)) && (count_msecs == 1)) begin // msec counter about to be reset back to the register value
if (pulse_sample_period && !SleepMode) begin // msec counter about to be reset back to the register value
if (RunFFEContinuously && !FFE_Holdoff) begin // trigger a run only if FFE_Holdoff has been deactivated
if (FFEBusyIn) begin
FFEOverrun <= 1'b1;
end else begin
StartFFE_32K <= ~StartFFE_32K;
//CMBufferBeingWrittenOut <= CMBufferBeingWrittenOut + 1;
//if (!AlternateI2CIsActiveIn) begin // If Alternate I2C is active, then we are reading the buffer
// CMBufferBeingRead <= CMBufferBeingWrittenOut;
//end
end
end
end
end
end
// software-controlled reset, 1-2 clock pulses wide @ the 32K clock
// generate a one-clock pulse @ the SPI_SCLK, to be used to preset a flop running in the 32K clock domain
always @(posedge SPI_SCLK)
if (RegWriteEnableIn && (RegAddrIn == `CommandReg) && RegDataIn[6]) // SW Reset control bit is being written
SW_Reset_Start <= 1;
else
SW_Reset_Start <= 0;
// 32K clock domain, the r1 flop gets preset by the SPI clock pulse above, and only gets deactivated after another 32K clock period (using the r2 flop)
always @(posedge Clock32KIn or posedge SW_Reset_Start)
if (SW_Reset_Start)
SW_Reset_r1 <= 1;
else
if (SW_Reset_r1 && !SW_Reset_r2)
SW_Reset_r1 <= 1;
else
SW_Reset_r1 <= 0;
// r2 flop, used to stretch the generated reset pulse
always @(posedge Clock32KIn)
SW_Reset_r2 <= SW_Reset_r1;
assign SW_Reset = SW_Reset_r2;
// When running the FFE continuously, this logic prevents the FFE from running until the start of a sample period
always @(posedge SPI_SCLK or posedge ResetIn)
if (ResetIn)
FFE_Holdoff_preset <= 0;
else
if (RegWriteEnableIn && (RegAddrIn == `CommandReg) && RegDataIn[0]) // Run FFE Continuously control bit is being written...
FFE_Holdoff_preset <= 1; // ... assert FFE_Holdoff
else
FFE_Holdoff_preset <= 0;
always @(posedge Clock32KIn or posedge ResetIn)
if (ResetIn)
FFE_Holdoff_reset <= 0;
else
if (pulse_sample_period_reg && RunFFEContinuously && FFE_Holdoff) // reset FFE_Holdoff when the first timer expiration occurs, to ensure a full first run
FFE_Holdoff_reset <= 1;
else
FFE_Holdoff_reset <= 0;
dff_pre_clr dff_pre_clr_FFE_Holdoff ( .CLK(1'b0) , .CLR(FFE_Holdoff_reset), .D(1'b0), .PRE(FFE_Holdoff_preset), .Q(FFE_Holdoff) );
// latch the I2C Master Error signal
dff_pre_clr dff_pre_clr_I2C_Master_Error ( .CLK(1'b0) , .CLR(ResetIn), .D(1'b0), .PRE(I2C_Master_Error), .Q(I2C_Master_Error_reg) );
// interrupt logic
// note: InterruptMsgFromFFEIn should be de-glitched externally (currently de-glitched in FFE_Control.v)
// logic to clear the FFE msg interrupts
always @(posedge SPI_SCLK)
if (RegWriteEnableIn && (RegAddrIn == `InterruptFFEMsg))
InterruptFFEMsg_clear <= RegDataIn[7:0];
else
InterruptFFEMsg_clear <= 8'b0;
// latch the interrupt msg from the FFE, clear when the InterruptFFEMsg register is being written
dff_pre_clr dff_pre_clr_InterruptFFEMsg_0 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[0]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[0]), .Q(InterruptFFEMsg_latched[0]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_1 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[1]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[1]), .Q(InterruptFFEMsg_latched[1]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_2 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[2]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[2]), .Q(InterruptFFEMsg_latched[2]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_3 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[3]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[3]), .Q(InterruptFFEMsg_latched[3]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_4 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[4]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[4]), .Q(InterruptFFEMsg_latched[4]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_5 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[5]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[5]), .Q(InterruptFFEMsg_latched[5]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_6 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[6]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[6]), .Q(InterruptFFEMsg_latched[6]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_7 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[7]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[7]), .Q(InterruptFFEMsg_latched[7]) );
assign InterruptFFEMsg_ORed = |InterruptFFEMsg_latched[7:0];
// drive the interrupt output pin: active-high, level sensitive
assign InterruptPinOut = (Interrupt_En_0 && InterruptFFEMsg_ORed) ||
(Interrupt_En_1 && (I2C_Master_Error_reg || SMOverrunIn || FFEOverrun));
// overflow detection bit
dff_pre_clr dff_pre_clr_overflow ( .CLK(1'b0) , .CLR(ResetIn), .D(1'b0), .PRE(CM_FIFO_Overflow), .Q(CM_FIFO_Overflow_reg) );
// sync the FIFO flags to the SPI clock domain
always @(posedge SPI_SCLK) begin
CM_FIFO_PopFlags_r1 <= CM_FIFO_PopFlags;
CM_FIFO_PopFlags_r2 <= CM_FIFO_PopFlags_r1;
if (CM_FIFO_PopFlags_r1 == CM_FIFO_PopFlags_r2)
CM_FIFO_PopFlags_sync <= CM_FIFO_PopFlags_r2;
else
CM_FIFO_PopFlags_sync <= CM_FIFO_PopFlags_sync;
end
//Registers for controlling the FFE and memories
always @(posedge SPI_SCLK or posedge ResetIn) begin
if (ResetIn) begin
RegDataOut <= 0;
MemoryReadEnableOut <= 0;
MemoryWriteEnableOut <= 0;
WaitForMemRead <= 0;
WaitForMemWrite <= 0;
IncrementMemAddr <= 0;
CommandReg <= 0;
msecs_per_sample_reg <= 1; // default value is 1 (sample period = 0 should be invalid)
InterruptCtrl_reg <= 0;
MemSelect_reg <= 0;
MemAddrLow <= 0;
MemAddrHigh <= 0;
MemDataByte0 <= 0;
MemDataByte1 <= 0;
MemDataByte2 <= 0;
MemDataByte3 <= 0;
MemDataByte4 <= 0;
StartFFE_Clkin <= 0;
// InitSM_Clkin <= 0; // Removed for Rel 0 on 6/18
StartSM_Clkin <= 0;
CM_FIFO_ReadEnable <= 0;
CM_Control_reg <= 0;
FFE_Mailbox_reg <= 0;
CtrlRunTimeAddressOut <= 0;
CtrlRunTimeAddressSM <= 0;
leds_off_o <= 3'b111;
ClkSourceSelect_o <= 1'b0;
clock_32KHz_Enable_o <= 1'b1;
FFE_Clock_Control_o <= FFE_SET;
SM_Clock_Control_o <= SM_SET;
RingOsc_cal_en <= 0;
RingOsc_select <= 3'h7;
end else begin
if (MemoryWriteEnableOut) begin
if(WaitForMemWrite == 0) begin
WaitForMemWrite <= 1;
end else begin
MemoryWriteEnableOut <= 0;
WaitForMemWrite <= 0;
IncrementMemAddr <= 1;
end
end // if (MemoryWriteEnableOut)
if (IncrementMemAddr) begin
IncrementMemAddr <= 0;
{MemAddrHigh[3:0],MemAddrLow} <= {MemAddrHigh[3:0],MemAddrLow} + 1;
end
if (MemoryReadEnableOut) begin
if (WaitForMemRead == 0) begin
WaitForMemRead <= 1;
end else begin
MemoryReadEnableOut <= 0;
WaitForMemRead <= 0;
MemDataByte4 <= MemoryDataIn[35:32];
MemDataByte3 <= MemoryDataIn[31:24];
MemDataByte2 <= MemoryDataIn[23:16];
MemDataByte1 <= MemoryDataIn[15:8];
MemDataByte0 <= MemoryDataIn[7:0];
end
end
// CM FIFO read control
///// Old Code
/*
if (CM_FIFO_ReadEnable)
CM_FIFO_ReadEnable <= 0;
else
if (RegAddrIn == `CM_FIFO_Data && RegReadDataAckIn)
CM_FIFO_ReadEnable <= 1;
else
CM_FIFO_ReadEnable <= 0;
*/
//// New Code
if (RegAddrIn == `CM_FIFO_Data && RegReadDataAckIn)
CM_FIFO_ReadEnable <= !CM_FIFO_ReadEnable;
else
CM_FIFO_ReadEnable <= CM_FIFO_ReadEnable;
if (RegWriteEnableIn) begin
case (RegAddrIn)
`CommandReg: begin
CommandReg <= RegDataIn;
//FFE_Holdoff <= 1;
end
`milSecSample: msecs_per_sample_reg <= RegDataIn;
`InterruptCtrl: InterruptCtrl_reg <= RegDataIn;
//`InterruptStat: // currently writes to this register does nothing, adding more interrupts may change this.
`MemSelect: MemSelect_reg <= RegDataIn;
`MemAddrLow: MemAddrLow <= RegDataIn;
`MemAddrHigh: begin
MemAddrHigh <= RegDataIn;
WaitForMemRead <= 0; // this is assigned in separate 'if' statements, the logic should be combined into 1.
MemoryReadEnableOut <= 1;
end
`MemDataByte0: MemDataByte0 <= RegDataIn;
`MemDataByte1: MemDataByte1 <= RegDataIn;
`MemDataByte2: MemDataByte2 <= RegDataIn;
`MemDataByte3: MemDataByte3 <= RegDataIn;
`MemDataByte4: begin
MemDataByte4 <= RegDataIn[3:0];
MemoryWriteEnableOut <= 1;
WaitForMemWrite <= 0; // this is assigned in separate 'if' statements, the logic should be combined into 1.
end
`CM_Control: CM_Control_reg <= RegDataIn;
`MailboxToFFE_0: FFE_Mailbox_reg[7:0] <= RegDataIn;
`MailboxToFFE_1: FFE_Mailbox_reg[15:8] <= RegDataIn;
`MailboxToFFE_2: FFE_Mailbox_reg[23:16] <= RegDataIn;
`MailboxToFFE_3: FFE_Mailbox_reg[31:24] <= RegDataIn;
`RunTimeAdrReg: begin
CtrlRunTimeAddressOut[7:0] <= RegDataIn; // Expanded for Rel 0 on 6/18
CtrlRunTimeAddressSM <= ~CtrlRunTimeAddressSM;
end
`DemoLedCtrlReg: begin
leds_off_o <= RegDataIn[2:0];
end
`ClocksControl: begin
FFE_Clock_Control_o <= RegDataIn[2:0];
SM_Clock_Control_o <= RegDataIn[5:3];
ClkSourceSelect_o <= RegDataIn[6];
clock_32KHz_Enable_o <= RegDataIn[7];
end
`RunTimeAdrReg_Upr: begin
CtrlRunTimeAddressOut[9:8] <= RegDataIn[1:0]; // New for Rel 0 on 6/18
end
`SleepControl: begin
RingOsc_cal_en <= RegDataIn[7];
RingOsc_select <= RegDataIn[6:4];
end
endcase
if ((RegAddrIn == `CommandReg) && RegDataIn[1]) // run FFE once
StartFFE_Clkin <= ~StartFFE_Clkin;
//the SM control signals come as a pair because only one should be toggled at a time if both bits are written to in CommandReg
//Initialization takes precedense over Start
// if ((RegAddrIn == `CommandReg) && RegDataIn[3]) // Removed for Rel 0 on 6/18
// InitSM_Clkin <= ~InitSM_Clkin; // Removed for Rel 0 on 6/18
// else if ((RegAddrIn == `CommandReg) && RegDataIn[2]) // Updated for Rel 0 on 6/18
if ((RegAddrIn == `CommandReg) && RegDataIn[2])
StartSM_Clkin <= ~StartSM_Clkin;
end else begin
case (RegAddrIn)
`CommandReg: RegDataOut <= { CommandReg[7], // UseFastClk
1'b0, // SW_Reset, self-clearing
1'b0, // reserved
1'b0, // reserved
1'b0, // RunSensorInit, self-clearing
1'b0, // RunSMOnce, self-clearing
1'b0, // RunFFEOnce, self-clearing
CommandReg[0] // RunFFEContinuously
};
`StatusReg: RegDataOut <= { 3'b0,
I2C_Master_Error_reg,
SMOverrunIn,
FFEOverrun,
SMBusyIn,
FFEBusyIn
}; // Status Reg
`milSecSample: RegDataOut <= msecs_per_sample_reg;
`InterruptCtrl: RegDataOut <= {6'b0, Interrupt_En_1, Interrupt_En_0};
`InterruptStat: RegDataOut <= {7'b0, InterruptFFEMsg_ORed};
`MemSelect: RegDataOut <= {MemSelect_reg[7], 4'b0, MemSelect_reg[2:0]};
`MemAddrLow: RegDataOut <= MemAddrLow;
`MemAddrHigh: RegDataOut <= MemAddrHigh;
`MemDataByte0: RegDataOut <= MemoryDataIn[7:0]; // MemDataByte0;
`MemDataByte1: RegDataOut <= MemoryDataIn[15:8]; // MemDataByte1;
`MemDataByte2: RegDataOut <= MemoryDataIn[23:16]; // MemDataByte2;
`MemDataByte3: RegDataOut <= MemoryDataIn[31:24]; // MemDataByte3;
`MemDataByte4: RegDataOut <= MemoryDataIn[35:32]; // MemDataByte4;
`CM_FIFO_Data: RegDataOut <= CM_FIFO_ReadData[7:0];
`CM_Control: RegDataOut <= {7'b0, CM_RingBufferMode};
`CM_Status: RegDataOut <= {6'b0, CM_FIFO_Overflow_reg, CM_AutoDrain_Busy};
`CM_FIFO_Flags_0: RegDataOut <= {4'b0, CM_FIFO_PopFlags_sync};
`MailboxToFFE_0: RegDataOut <= FFE_Mailbox_reg[7:0];
`MailboxToFFE_1: RegDataOut <= FFE_Mailbox_reg[15:8];
`MailboxToFFE_2: RegDataOut <= FFE_Mailbox_reg[23:16];
`MailboxToFFE_3: RegDataOut <= FFE_Mailbox_reg[31:24];
`InterruptFFEMsg: RegDataOut <= InterruptFFEMsg_latched;
`RunTimeAdrReg: RegDataOut <= CtrlRunTimeAddressReg[7:0]; // Expanded for Rel 0 on 6/18
`DemoLedCtrlReg: RegDataOut <= {5'b0, leds_off_o};
`ClocksControl: RegDataOut <= {clock_32KHz_Enable_o, ClkSourceSelect_o, SM_Clock_Control_o[2:0], FFE_Clock_Control_o[2:0]};
`SleepControl: RegDataOut <= {RingOsc_cal_en, RingOsc_select[2:0], 1'b0, sleepModeSet, IntInputLevel, SleepMode};
`RunTimeAdrReg_Upr: RegDataOut <= {6'h0, CtrlRunTimeAddressReg[9:8]}; // New for Rel 0 on 6/18
`CalValueLow: RegDataOut <= RingOsc_cal_value[7:0];
`CalValueHi: RegDataOut <= RingOsc_cal_value[15:8];
default: RegDataOut <= 8'h21;
endcase
end
end // if (ResetIn)
end // Always
assign i_StartFFEOut = StartFFE_32K ^ StartFFE_Clkin;
//assign InitSMOut = s6_InitSM_Clkin; // Removed for Rel 0 on 6/18
assign StartSMOut = s6_StartSM_Clkin;
// test points
assign TP1 = FFE_Mailbox_reg[0];
assign TP2 = RegWriteEnableIn;
// Logic to drive RIng Osc Clock Enable / Disable
//assign smInit_enable = (s2_InitSM_Clkin ^ s3_InitSM_Clkin) || (s2_StartSM_Clkin ^ s3_StartSM_Clkin); // Removed for Rel 0 on 6/18
assign smInit_enable = (s2_StartSM_Clkin ^ s3_StartSM_Clkin); // Updated for Rel 0 on 6/18
assign d_ClockEnable = ClockEnable_o ? ((!s2_SMBusyIn && s3_SMBusyIn) ? 1'b0 : 1'b1) : (( d_FFE_CLK_Enable || smInit_enable ) ? 1'b1 : 1'b0);
always @(posedge Clock32KIn or posedge ResetIn)
begin
if (ResetIn)
begin
s1_SMBusyIn <= 0;
s2_SMBusyIn <= 0;
s3_SMBusyIn <= 0;
ClockEnable_o <= 0;
// s1_InitSM_Clkin <= 0;
// s2_InitSM_Clkin <= 0;
// s3_InitSM_Clkin <= 0;
// s4_InitSM_Clkin <= 0;
// s5_InitSM_Clkin <= 0;
// s6_InitSM_Clkin <= 0;
s1_StartSM_Clkin <= 0;
s2_StartSM_Clkin <= 0;
s3_StartSM_Clkin <= 0;
s4_StartSM_Clkin <= 0;
s5_StartSM_Clkin <= 0;
s6_StartSM_Clkin <= 0;
end
else
begin
s1_SMBusyIn <= (SMBusyIn || FFEBusyIn);
s2_SMBusyIn <= s1_SMBusyIn;
s3_SMBusyIn <= s2_SMBusyIn;
ClockEnable_o <= d_ClockEnable;
// s1_InitSM_Clkin <= InitSM_Clkin;
// s2_InitSM_Clkin <= s1_InitSM_Clkin;
// s3_InitSM_Clkin <= s2_InitSM_Clkin;
// s4_InitSM_Clkin <= s3_InitSM_Clkin;
// s5_InitSM_Clkin <= s4_InitSM_Clkin;
// s6_InitSM_Clkin <= s5_InitSM_Clkin;
s1_StartSM_Clkin <= StartSM_Clkin;
s2_StartSM_Clkin <= s1_StartSM_Clkin;
s3_StartSM_Clkin <= s2_StartSM_Clkin;
s4_StartSM_Clkin <= s3_StartSM_Clkin;
s5_StartSM_Clkin <= s4_StartSM_Clkin;
s6_StartSM_Clkin <= s5_StartSM_Clkin;
end
end
// Logic to select default reset values for the SM and FFE CLK selection
assign FFE_SET[0] = (`FFE1CLK_FREQ_SLT == 8'b00000001) || (`FFE1CLK_FREQ_SLT == 8'b00000010) || (`FFE1CLK_FREQ_SLT == 8'b00000100) || (`FFE1CLK_FREQ_SLT == 8'b00001000) ||
(`FFE1CLK_FREQ_SLT == 8'b00010000) || (`FFE1CLK_FREQ_SLT == 8'b01000000);
assign FFE_SET[1] = (`FFE1CLK_FREQ_SLT == 8'b00000001) || (`FFE1CLK_FREQ_SLT == 8'b00000010) || (`FFE1CLK_FREQ_SLT == 8'b00000100) || (`FFE1CLK_FREQ_SLT == 8'b00001000) ||
(`FFE1CLK_FREQ_SLT == 8'b00100000) || (`FFE1CLK_FREQ_SLT == 8'b01000000);
assign FFE_SET[2] = (`FFE1CLK_FREQ_SLT == 8'b10000000);
assign SM_SET[0] = (`SM1CLK_FREQ_SLT == 8'b00000010) || (`SM1CLK_FREQ_SLT == 8'b00001000) || (`SM1CLK_FREQ_SLT == 8'b00100000) || (`SM1CLK_FREQ_SLT == 8'b10000000);
assign SM_SET[1] = (`SM1CLK_FREQ_SLT == 8'b00000100) || (`SM1CLK_FREQ_SLT == 8'b00001000) || (`SM1CLK_FREQ_SLT == 8'b01000000) || (`SM1CLK_FREQ_SLT == 8'b10000000);
assign SM_SET[2] = (`SM1CLK_FREQ_SLT == 8'b00010000) || (`SM1CLK_FREQ_SLT == 8'b00100000) || (`SM1CLK_FREQ_SLT == 8'b01000000) || (`SM1CLK_FREQ_SLT == 8'b10000000);
// Logic for Sleep Mode
// Sensor interrupt input is double ring to check for transtion from low to high
// Once detected, the design will enable the sampling period
assign sleepModeSet = sensorInterrupt_s2 && !sensorInterrupt_s3;
always @(posedge Clock32KIn or posedge ResetIn)
begin
if (ResetIn)
begin
sensorInterrupt_s1 <= 0;
sensorInterrupt_s2 <= 0;
sensorInterrupt_s3 <= 0;
end
else
begin
sensorInterrupt_s1 <= (SensorInterruptIn ~^ IntInputLevel) && SleepMode;
sensorInterrupt_s2 <= sensorInterrupt_s1;
sensorInterrupt_s3 <= sensorInterrupt_s2;
end
end
assign sleepReset = ResetIn || sleepModeSet;
always @(posedge SPI_SCLK or posedge sleepReset) begin
if (sleepReset)
begin
SleepMode <= 1'b0;
end
else if ((RegAddrIn == `SleepControl) && RegWriteEnableIn)
begin
SleepMode <= RegDataIn[0];
end
end
always @(posedge SPI_SCLK or posedge ResetIn) begin
if (ResetIn)
begin
IntInputLevel <= 1'b1;
end
else if ((RegAddrIn == `SleepControl) && RegWriteEnableIn)
begin
IntInputLevel <= RegDataIn[1];
end
end
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,126 @@
/***************************************************
Vendor : QuickLogic Corp.
Aurora Version : AU 1.0.0
File Name : primtive_macros.v
Author : Kishor Kumar
Description : Verilog Netlist File (For Synthesis/Pre-Layout Simulation)
*****************************************************/
/*-------------------------------------------------------------------------------
MODULE NAME : ck_buff
DESCRIPTION : Clock tree buffer
--------------------------------------------------------------------------------*/
`ifdef ck_buff
`else
`define ck_buff
module ck_buff ( A , Q )/* synthesis black_box black_box_pad_pin = "A" */;
input A/* synthesis syn_isclock=1 */;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* ck buff */
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : gclkbuff
DESCRIPTION : Global clock buffer
--------------------------------------------------------------------------------*/
`ifdef GCLKBUFF
`else
`define GCLKBUFF
module GCLKBUFF ( A , Z )/* synthesis black_box */;
input A;
output Z;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* gclk buff */
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : in_buff
DESCRIPTION : Input buffer
--------------------------------------------------------------------------------*/
`ifdef in_buff
`else
`define in_buff
module in_buff ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* in buff */
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : out_buff
DESCRIPTION : Output buffer
--------------------------------------------------------------------------------*/
`ifdef out_buff
`else
`define out_buff
module out_buff ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* out buff */
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : inv
DESCRIPTION : Inverter
--------------------------------------------------------------------------------*/
`ifdef inv
`else
`define inv
module inv ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*inverter*/
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : buff
DESCRIPTION : Buffer
--------------------------------------------------------------------------------*/
`ifdef buff
`else
`define buff
module buff ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*buffer*/
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : mux2x0
DESCRIPTION : Basic Mux 2:1
--------------------------------------------------------------------------------*/
`ifdef mux2x0
`else
`define mux2x0
module mux2x0 ( A , B, S, Q )/* synthesis black_box */;
input A, B, S;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*mux2x0*/
`endif
`ifdef LOGIC_Cell
`else
`define LOGIC_Cell
module LOGIC_Cell (T0I0, T0I1, T0I2, T0I3, B0I0, B0I1, B0I2, B0I3,
TB0S, Q0DI, CD0S, Q0EN, QST, QRT, QCK, QCKS, C0Z, Q0Z, B0Z)/* synthesis black_box */;
input T0I0, T0I1, T0I2, T0I3, B0I0, B0I1, B0I2, B0I3;
input TB0S, Q0DI, CD0S, Q0EN;
input QST, QRT, QCK, QCKS;
output C0Z, B0Z, Q0Z;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*LOGIC_Cell*/
`endif

View File

@ -0,0 +1,17 @@
`timescale 1ns / 1ns
module clock_buffer (
input A,
output Z
);
GCLKBUFF gclkbuff_0 (.A(A), .Z(Z));
//pragma attribute gclkbuff_0 ql_pack 1
//pragma attribute gclkbuff_0 hierarchy preserve
endmodule

View File

@ -0,0 +1,18 @@
`timescale 1ns / 1ns
module dff_pre_clr (
input CLK,
input CLR,
input D,
input PRE,
output Q
);
dffpc dffpc_0 ( .CLK(CLK) , .CLR(CLR), .D(D), .PRE(PRE), .Q(Q) )/* synthesis black_box */;
//pragma attribute dffpc_0 dont_touch true
endmodule

View File

@ -0,0 +1,301 @@
/* ------------------------------------------------------------------
ring_osc_adjust.v
Control logic to keep the ring oscillator's frequency within the
desired range.
divider values from ClockDivider_rev2.pdf:
SEL sysclk_x2 sysclk
--------------------------------
000 ? ?
001 2 4
010 3 6
011 4 8
100 5 10
101 6 12
110 7 14
111 8 16
------------------------------------------------------------------ */
`timescale 1ps/1ps
/*
module ring_osc_adjust (
input reset_i, // async reset
input clk_ringosc_i, // the ring oscillator output divided by 2 (this is not clk_main)
input clk_32khz_i, // 32.768KHz reference clock
input enable_i, // enable, can be tied off externally or driven occasionally to force re-calibration
output [2:0] div_sel_o // divider selection control for the ring oscillator divider circuit (in ASSP)
);
reg clk32k_r1, clk32k_r2;
reg clk32k_cycle_start;
reg enable_32k_sync, enable_32k_sync_r1;
reg enable_main_sync, enable_main_sync_r1, enable_main;
reg [10:0] clk_ringosc_div2_cnt;
reg [2:0] ring_osc_div, ring_osc_div_reg;
// divider SEL values
localparam [2:0] DIV2_SEL = 3'b001;
localparam [2:0] DIV3_SEL = 3'b010;
localparam [2:0] DIV4_SEL = 3'b011;
localparam [2:0] DIV5_SEL = 3'b100;
localparam [2:0] DIV6_SEL = 3'b101;
localparam [2:0] DIV7_SEL = 3'b110;
localparam [2:0] DIV8_SEL = 3'b111;
// threshold values for each divider value.
// These are the count values where each divider value will be applied.
// Example: if there are 395 counts on clk_ringosc_div2 within a 32KHz clock period, the ring osc is divided by 5.
// A divider of 5 means that sysclk_x2 = ring_osc/5, and sysclk = ring_osc/10.
// Nomenclature:
// ring_osc = ring oscillator raw clock (not accessible outside of ASSP)
// ring_osc_div2 = ring oscillator divided by 2 (used for calibration)
// sysclk_x2 = ring oscillator divided by SEL
// sysclk = ring oscillator divided by SEL*2 (used as system clock A.K.A. FFE clock)
// Assumptions:
// Ring osc range: 25.2MHz - 53.2MHz (39.7ns to 18.8ns period)
// I2C master will divide clk_main by 9 to produce SCL.
// SCL freq cannot exceed 400KHz.
// Guardband of 10% is added to allow for temperature/voltage variation, in case calibration is only done once at startup.
// A smaller guardband can be used if calibration is performed periodically.
localparam [10:0] DIV4_THRESHOLD = 11'd32; // (the threshold of 32 is arbitrary... just needs to be somewhat larger than 0)
localparam [10:0] DIV5_THRESHOLD = 11'd395;
localparam [10:0] DIV6_THRESHOLD = 11'd494;
localparam [10:0] DIV7_THRESHOLD = 11'd595;
localparam [10:0] DIV8_THRESHOLD = 11'd693;
// synchronize the enable to clk32k (set this FF on the rising edge of enable_i,
// clear it after one full 32KHz period has elapsed)
always @(posedge enable_i or posedge clk_32khz_i)
if (enable_i)
enable_32k_sync <= 1'b1;
else
if (enable_32k_sync_r1)
enable_32k_sync <= 1'b0;
else
enable_32k_sync <= enable_32k_sync;
always @(posedge clk_32khz_i)
enable_32k_sync_r1 <= enable_32k_sync;
assign enable_32k = enable_32k_sync_r1;
// detect rising edge on clk32khz
always @(posedge clk_ringosc_i) begin
if (!enable_i) begin
clk32k_r1 <= 1'b0;
clk32k_r2 <= 1'b0;
clk32k_cycle_start <= 1'b0;
end
else begin
clk32k_r1 <= clk_32khz_i;
clk32k_r2 <= clk32k_r1;
clk32k_cycle_start <= clk32k_r1 && !clk32k_r2;
end
end
// synchronize the stretched enable to the main clk domain,
// turn this enable off when clk32k_cycle_start is active
always @(posedge clk_ringosc_i or posedge reset_i) begin
if (reset_i) begin
enable_main_sync <= 1'b0;
enable_main_sync_r1 <= 1'b0;
enable_main <= 1'b0;
end
else begin
enable_main_sync <= enable_32k;
enable_main_sync_r1 <= enable_main_sync;
case (enable_main)
1'b0: if (clk32k_cycle_start && enable_main_sync_r1)
enable_main <= 1'b1;
else
enable_main <= 1'b0;
1'b1: if (clk32k_cycle_start && !enable_32k)
enable_main <= 1'b0;
else
enable_main <= 1'b1;
endcase
end
end
// count # of clk_ringosc_div2 cycles per 32khz clock period
always @(posedge clk_ringosc_i or posedge reset_i)
if (reset_i)
clk_ringosc_div2_cnt <= 0;
else
if (enable_main)
if (clk32k_cycle_start)
clk_ringosc_div2_cnt <= 0;
else
clk_ringosc_div2_cnt <= clk_ringosc_div2_cnt + 1;
else
clk_ringosc_div2_cnt <= 0;
// set the ring_osc clock divider value
// _div holds the temporary divider SEL valud
// _div_reg gets assigned after a full 32KHz clock period
always @(posedge clk_ringosc_i or posedge reset_i)
if (reset_i) begin
ring_osc_div <= 3'b111; // use the largest divide value by default
ring_osc_div_reg <= 3'b111;
end
else begin
if (enable_main)
case (clk_ringosc_div2_cnt)
DIV4_THRESHOLD: ring_osc_div <= DIV4_SEL;
DIV5_THRESHOLD: ring_osc_div <= DIV5_SEL;
DIV6_THRESHOLD: ring_osc_div <= DIV6_SEL;
DIV7_THRESHOLD: ring_osc_div <= DIV7_SEL;
DIV8_THRESHOLD: ring_osc_div <= DIV8_SEL;
default: ring_osc_div <= ring_osc_div; // hold for all other values
endcase
else
ring_osc_div <= ring_osc_div; // need to retain the old value when enable is off
if (clk32k_cycle_start)
ring_osc_div_reg <= ring_osc_div;
else
ring_osc_div_reg <= ring_osc_div_reg;
end
assign div_sel_o = ring_osc_div_reg;
//// New Logic to produce CNT to system
//// Detect transition of Calibration aneble from Low to Hi
always @(posedge clk_32khz_i or posedge reset_i)
begin
if (reset_i) begin
enable_r1 <= 1'b0;
enable_r2 <= 1'b0;
enable_r3 <= 1'b0;
end
else begin
enable_r1 <= enable_i;
enable_r2 <= enable_r1;
enable_r3 <= enable_r2;
end
end
// Generating enable for Clock Cnt circuit
// Default is is 2 32KHz CLK period
always @(posedge clk_32khz_i or posedge reset_i)
begin
if (reset_i)
downCnt <= 2'b0;
else
if (enable_r2 && !enable_r3)
downCnt <= 2'b11;
else if (downCnt[1] || downCnt[0])
downCnt <= downCnt - 1'b1;
else
downCnt <= downCnt;
end
// Sync to ring osc clk
always @(posedge clk_ringosc_i or posedge reset_i)
if (reset_i)
downCnt1_r1 <= 1'b0;
downCnt1_r2 <= 1'b0;
else
downCnt1_r1 <= downCnt[1];
downCnt1_r2 <= downCnt1_r1;
assign ringosccnt_reset = reset_i && !enable_i;
// Counting # of ringosc cyces in two 32KHz clock
always @(posedge clk_ringosc_i or posedge ringosccnt_reset)
begin
if (ringosccnt_reset)
ringosc_2_cnt <= 16'b0;
else if (downCnt1_r2)
ringosc_2_cnt <= ringosc_2_cnt + 1'b0;
else
ringosc_2_cnt <= ringosc_2_cnt;
end
endmodule
*/
module ring_osc_adjust (
input reset_i, // async reset
input clk_ringosc_i, // the ring oscillator output divided by 2 (this is not clk_main)
input clk_32khz_i, // 32.768KHz reference clock
input enable_i, // enable, can be tied off externally or driven occasionally to force re-calibration
output [15:0] cal_val_o // divider selection control for the ring oscillator divider circuit (in ASSP)
);
reg enable_r1, enable_r2, enable_r3;
reg [2:0] downCnt;
reg downCnt1_r1, downCnt1_r2;
reg [15:0] ringosc_2_cnt;
wire ringosccnt_reset;
//// New Logic to produce CNT to system
//// Detect transition of Calibration aneble from Low to Hi
always @(posedge clk_32khz_i or posedge reset_i)
begin
if (reset_i) begin
enable_r1 <= 1'b0;
enable_r2 <= 1'b0;
enable_r3 <= 1'b0;
end
else begin
enable_r1 <= enable_i;
enable_r2 <= enable_r1;
enable_r3 <= enable_r2;
end
end
// Generating enable for Clock Cnt circuit
// Default is is 2 32KHz CLK period
always @(posedge clk_32khz_i or posedge reset_i)
begin
if (reset_i)
downCnt <= 3'b0;
else
if (enable_r2 && !enable_r3)
downCnt <= 3'b111;
else if (downCnt != 3'b000)
downCnt <= downCnt - 1'b1;
else
downCnt <= downCnt;
end
// Sync to ring osc clk
always @(posedge clk_ringosc_i or posedge reset_i)
if (reset_i)
begin
downCnt1_r1 <= 1'b0;
downCnt1_r2 <= 1'b0;
end
else
begin
downCnt1_r1 <= downCnt[2];
downCnt1_r2 <= downCnt1_r1;
end
assign ringosccnt_reset = reset_i || !enable_i;
// Counting # of ringosc cyces in two 32KHz clock
always @(posedge clk_ringosc_i or posedge ringosccnt_reset)
begin
if (ringosccnt_reset)
ringosc_2_cnt <= 16'b0;
else if (downCnt1_r2)
ringosc_2_cnt <= ringosc_2_cnt + 1'b1;
else
ringosc_2_cnt <= ringosc_2_cnt;
end
assign cal_val_o = ringosc_2_cnt;
endmodule

View File

@ -0,0 +1,26 @@
// -----------------------------------------------------------------------------
// title : ulpsh_rtl_defines.v
// project : ULP Sensor Hub
// description : RTL defines
// -----------------------------------------------------------------------------
// copyright (c) 2014, QuickLogic Corporation
// -----------------------------------------------------------------------------
// Clock Circuit control defines
`define OP_CLK_DIV 8'b01000000
`define FFE1CLK_FREQ_SLT 8'b01000000
`define SM1CLK_FREQ_SLT 8'b00100000
`ifdef SIMULATION
`define OSC_SELECTION 1'b0
`else
`define OSC_SELECTION 1'b1
`endif
`define ENABLE_FFE_F0_SINGLE_DM
`define ENABLE_FFE_F0_EXTENDED_DM
`define FFE_F0_SEG0_OFFSET 9'h095
`define ENABLE_FFE_F0_CM_SIZE_4K

View File

@ -0,0 +1,38 @@
//-------------------------------------------------------------------
// Function: Binary to Decimal converter
// Source:
// https://verilogcodes.blogspot.com/2015/10/verilog-code-for-8-bit-binary-to-bcd.html
//-------------------------------------------------------------------
module bin2bcd(
bin,
bcd
);
//input ports and their sizes
input [7:0] bin;
//output ports and, their size
output [11:0] bcd;
//Internal variables
reg [11 : 0] bcd;
reg [3:0] i;
//Always block - implement the Double Dabble algorithm
always @(bin)
begin
bcd = 0; //initialize bcd to zero.
for (i = 0; i < 8; i = i+1) //run for 8 iterations
begin
bcd = {bcd[10:0],bin[7-i]}; //concatenation
//if a hex digit of 'bcd' is more than 4, add 3 to it.
if(i < 7 && bcd[3:0] > 4)
bcd[3:0] = bcd[3:0] + 3;
if(i < 7 && bcd[7:4] > 4)
bcd[7:4] = bcd[7:4] + 3;
if(i < 7 && bcd[11:8] > 4)
bcd[11:8] = bcd[11:8] + 3;
end
end
endmodule

View File

@ -0,0 +1,31 @@
//-------------------------------------------------------------------
// Function: Testbench for the Binary to Decimal converter
// Source:
// https://verilogcodes.blogspot.com/2015/10/verilog-code-for-8-bit-binary-to-bcd.html
module tb_bin2bcd;
// Input
reg [7:0] bin;
// Output
wire [11:0] bcd;
// Extra variables
reg [8:0] i;
// Instantiate the Unit Under Test (UUT)
bin2bcd uut (
.bin(bin),
.bcd(bcd)
);
//Simulation - Apply inputs
initial begin
//A for loop for checking all the input combinations.
for(i=0;i<256;i=i+1)
begin
bin = i;
#10; //wait for 10 ns.
end
$finish; //system function for stoping the simulation.
end
endmodule

View File

@ -0,0 +1,162 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_fsm ////
//// ////
//// Description ////
//// controls the cavlc parsing process ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-7 18:57 initial revision
`include "defines.v"
module cavlc_fsm
(
clk,
rst_n,
ena,
start,
max_coeff_num,
TotalCoeff,
TotalCoeff_comb,
TrailingOnes,
TrailingOnes_comb,
ZeroLeft,
state,
i,
idle,
valid
);
//------------------------
//ports
//------------------------
input clk;
input rst_n;
input ena;
input start;
input [4:0] max_coeff_num;
input [4:0] TotalCoeff;
input [4:0] TotalCoeff_comb;
input [1:0] TrailingOnes;
input [1:0] TrailingOnes_comb;
input [3:0] ZeroLeft;
output [7:0] state;
output [3:0] i;
output idle;
output valid;
//------------------------
//FFs
//------------------------
reg [7:0] state;
reg [3:0] i;
reg valid;
//------------------------
//state & i & valid
//------------------------
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
state <= `cavlc_idle_s;
i <= 0;
valid <= 0;
end
else if (ena)
case(state)
`cavlc_idle_s : begin
if (start) begin
state <= `cavlc_read_total_coeffs_s;
valid <= 0;
end
else begin
state <= `cavlc_idle_s;
end
end
`cavlc_read_total_coeffs_s : begin
i <= TotalCoeff_comb -1;
if (TrailingOnes_comb > 0 && TotalCoeff_comb > 0)
state <= `cavlc_read_t1s_flags_s;
else if (TotalCoeff_comb > 0)
state <= `cavlc_read_level_prefix_s;
else begin
state <= `cavlc_idle_s;
valid <= 1;
end
end
`cavlc_read_t1s_flags_s : begin
if (TrailingOnes == TotalCoeff)
state <= `cavlc_read_total_zeros_s;
else begin
state <= `cavlc_read_level_prefix_s;
i <= i - TrailingOnes;
end
end
`cavlc_read_level_prefix_s : begin
state <= `cavlc_read_level_suffix_s;
end
`cavlc_read_level_suffix_s : begin
state <= `cavlc_calc_level_s;
end
`cavlc_calc_level_s : begin
if ( i == 0 && TotalCoeff < max_coeff_num)
state <= `cavlc_read_total_zeros_s;
else if (i == 0) begin
state <= `cavlc_read_run_befores_s;
i <= TotalCoeff - 1;
end
else begin
state <= `cavlc_read_level_prefix_s;
i <= i - 1;
end
end
`cavlc_read_total_zeros_s : begin
state <= `cavlc_read_run_befores_s;
i <= TotalCoeff - 1;
end
`cavlc_read_run_befores_s : begin
if (i == 0 || ZeroLeft == 0) begin
state <= `cavlc_idle_s;
valid <= 1;
end
else begin
state <= `cavlc_read_run_befores_s;
i <= i - 1;
end
end
endcase
assign idle = state[`cavlc_idle_bit];
endmodule

View File

@ -0,0 +1,84 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_len_gen ////
//// ////
//// Description ////
//// generate the number of bits to forward ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-7 20:19 initial revision
`include "defines.v"
module cavlc_len_gen
(
cavlc_state,
len_read_total_coeffs_comb,
len_read_levels_comb,
len_read_total_zeros_comb,
len_read_run_befores_comb,
len_comb
);
//------------------------
// ports
//------------------------
input [7:0] cavlc_state;
input [4:0] len_read_total_coeffs_comb;
input [4:0] len_read_levels_comb;
input [3:0] len_read_total_zeros_comb;
input [3:0] len_read_run_befores_comb;
output [4:0] len_comb;
//------------------------
// regs
//------------------------
reg [4:0] len_comb; //number of bits comsumed by cavlc in a cycle
//------------------------
// len_comb
//------------------------
always @ (*)
case (1'b1) //synthesis parallel_case
cavlc_state[`cavlc_read_total_coeffs_bit] : len_comb <= len_read_total_coeffs_comb;
cavlc_state[`cavlc_read_t1s_flags_bit],
cavlc_state[`cavlc_read_level_prefix_bit],
cavlc_state[`cavlc_read_level_suffix_bit] : len_comb <= len_read_levels_comb;
cavlc_state[`cavlc_read_total_zeros_bit] : len_comb <= len_read_total_zeros_comb;
cavlc_state[`cavlc_read_run_befores_bit] : len_comb <= len_read_run_befores_comb;
cavlc_state[`cavlc_calc_level_bit],
cavlc_state[`cavlc_idle_bit] : len_comb <= 0;
default : len_comb <= 'bx;
endcase
endmodule

View File

@ -0,0 +1,400 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_read_levels ////
//// ////
//// Description ////
//// decode levels for coeffs ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-6 initiial revision
//2011-8-19 reverse the order of level
// include TrailingOnes
`include "defines.v"
module cavlc_read_levels (
clk,
rst_n,
ena,
t1s_sel,
prefix_sel,
suffix_sel,
calc_sel,
TrailingOnes,
TotalCoeff,
rbsp,
i,
level_0,
level_1,
level_2,
level_3,
level_4,
level_5,
level_6,
level_7,
level_8,
level_9,
level_10,
level_11,
level_12,
level_13,
level_14,
level_15,
len_comb
);
//------------------------
// ports
//------------------------
input clk;
input rst_n;
input ena;
input t1s_sel;
input prefix_sel;
input suffix_sel;
input calc_sel;
input [1:0] TrailingOnes;
input [4:0] TotalCoeff;
input [0:15] rbsp;
input [3:0] i;
output [8:0] level_0;
output [8:0] level_1;
output [8:0] level_2;
output [8:0] level_3;
output [8:0] level_4;
output [8:0] level_5;
output [8:0] level_6;
output [8:0] level_7;
output [8:0] level_8;
output [8:0] level_9;
output [8:0] level_10;
output [8:0] level_11;
output [8:0] level_12;
output [8:0] level_13;
output [8:0] level_14;
output [8:0] level_15;
output [4:0] len_comb;
//------------------------
// regs
//------------------------
reg [0:15] rbsp_internal; // reduce toggle rate
reg [3:0] level_prefix_comb;
reg [8:0] level_suffix;
reg [4:0] len_comb;
//------------------------
// FFs
//------------------------
reg [3:0] level_prefix;
reg [2:0] suffixLength; // range from 0 to 6
reg [8:0] level;
reg [8:0] level_abs;
reg [8:0] level_code_tmp;
reg [8:0] level_0, level_1, level_2, level_3, level_4, level_5, level_6, level_7;
reg [8:0] level_8, level_9, level_10, level_11, level_12, level_13, level_14, level_15;
//------------------------
// level_prefix_comb
//------------------------
always @(*)
if ((t1s_sel || prefix_sel || suffix_sel)&& ena)
rbsp_internal <= rbsp;
else
rbsp_internal <= 'hffff;
always @(*)
if (rbsp_internal[0]) level_prefix_comb <= 0;
else if (rbsp_internal[1]) level_prefix_comb <= 1;
else if (rbsp_internal[2]) level_prefix_comb <= 2;
else if (rbsp_internal[3]) level_prefix_comb <= 3;
else if (rbsp_internal[4]) level_prefix_comb <= 4;
else if (rbsp_internal[5]) level_prefix_comb <= 5;
else if (rbsp_internal[6]) level_prefix_comb <= 6;
else if (rbsp_internal[7]) level_prefix_comb <= 7;
else if (rbsp_internal[8]) level_prefix_comb <= 8;
else if (rbsp_internal[9]) level_prefix_comb <= 9;
else if (rbsp_internal[10]) level_prefix_comb <= 10;
else if (rbsp_internal[11]) level_prefix_comb <= 11;
else if (rbsp_internal[12]) level_prefix_comb <= 12;
else if (rbsp_internal[13]) level_prefix_comb <= 13;
else if (rbsp_internal[14]) level_prefix_comb <= 14;
else if (rbsp_internal[15]) level_prefix_comb <= 15;
else level_prefix_comb <= 'bx;
//------------------------
// level_prefix
//------------------------
always @(posedge clk or negedge rst_n)
if (!rst_n)
level_prefix <= 0;
else if (prefix_sel && ena)
level_prefix <= level_prefix_comb;
//------------------------
// suffixLength
//------------------------
wire first_level;
assign first_level = (i == TotalCoeff - TrailingOnes - 1);
always @(posedge clk or negedge rst_n)
if (!rst_n)
suffixLength <= 0;
else if (prefix_sel && ena) begin
if (TotalCoeff > 10 && TrailingOnes < 3 && first_level ) //initialize suffixLength before proceeding first level_suffix
suffixLength <= 1;
else if (first_level)
suffixLength <= 0;
else if (suffixLength == 0 && level_abs > 2'd3)
suffixLength <= 2;
else if (suffixLength == 0)
suffixLength <= 1;
else if ( level_abs > (2'd3 << (suffixLength - 1'b1) ) && suffixLength < 6)
suffixLength <= suffixLength + 1'b1;
end
//------------------------
// level_suffix
//------------------------
always @(*)
if (suffixLength > 0 && level_prefix <= 14)
level_suffix <= {3'b0, rbsp_internal[0:5] >> (3'd6 - suffixLength)};
else if (level_prefix == 14) //level_prefix == 14 && suffixLength == 0
level_suffix <= {3'b0, rbsp_internal[0:3] };
else if (level_prefix == 15)
level_suffix <= rbsp_internal[3:11];
else
level_suffix <= 0;
//------------------------
// level_code_tmp
//------------------------
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
level_code_tmp <= 0;
end
else if (suffix_sel && ena) begin
level_code_tmp <= (level_prefix << suffixLength) + level_suffix +
((suffixLength == 0 && level_prefix == 15) ? 4'd15 : 0);
end
//------------------------
// level
//------------------------
wire [2:0] tmp1;
assign tmp1 = (first_level && TrailingOnes < 3)? 2'd2 : 2'd0;
always @(*)
begin
if (level_code_tmp % 2 == 0) begin
level <= ( level_code_tmp + tmp1 + 2 ) >> 1;
end
else begin
level <= (-level_code_tmp - tmp1 - 1 ) >> 1;
end
end
//------------------------
// level_abs
//------------------------
wire level_abs_refresh;
assign level_abs_refresh = calc_sel && ena;
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
level_abs <= 0;
end
else if (level_abs_refresh) begin
level_abs <= level[8] ? -level : level;
end
//------------------------
// level regfile
//------------------------
always @ (posedge clk or negedge rst_n)
if (!rst_n) begin
level_0 <= 0; level_1 <= 0; level_2 <= 0; level_3 <= 0;
level_4 <= 0; level_5 <= 0; level_6 <= 0; level_7 <= 0;
level_8 <= 0; level_9 <= 0; level_10<= 0; level_11<= 0;
level_12<= 0; level_13<= 0; level_14<= 0; level_15<= 0;
end
else if (t1s_sel && ena)
case (i)
0 : level_0 <= rbsp_internal[0]? -1 : 1;
1 : begin
level_1 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_0 <= rbsp_internal[1]? -1 : 1;
end
2 : begin
level_2 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_1 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_0 <= rbsp_internal[2]? -1 : 1;
end
3 : begin
level_3 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_2 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_1 <= rbsp_internal[2]? -1 : 1;
end
4 : begin
level_4 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_3 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_2 <= rbsp_internal[2]? -1 : 1;
end
5 : begin
level_5 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_4 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_3 <= rbsp_internal[2]? -1 : 1;
end
6 : begin
level_6 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_5 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_4 <= rbsp_internal[2]? -1 : 1;
end
7 : begin
level_7 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_6 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_5 <= rbsp_internal[2]? -1 : 1;
end
8 : begin
level_8 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_7 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_6 <= rbsp_internal[2]? -1 : 1;
end
9 : begin
level_9 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_8 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_7 <= rbsp_internal[2]? -1 : 1;
end
10: begin
level_10 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_9 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_8 <= rbsp_internal[2]? -1 : 1;
end
11: begin
level_11 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_10 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_9 <= rbsp_internal[2]? -1 : 1;
end
12: begin
level_12 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_11 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_10 <= rbsp_internal[2]? -1 : 1;
end
13: begin
level_13 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_12 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_11 <= rbsp_internal[2]? -1 : 1;
end
14: begin
level_14 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_13 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_12 <= rbsp_internal[2]? -1 : 1;
end
15: begin
level_15 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_14 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_13 <= rbsp_internal[2]? -1 : 1;
end
endcase
else if (calc_sel && ena)
case (i)
0 :level_0 <= level;
1 :level_1 <= level;
2 :level_2 <= level;
3 :level_3 <= level;
4 :level_4 <= level;
5 :level_5 <= level;
6 :level_6 <= level;
7 :level_7 <= level;
8 :level_8 <= level;
9 :level_9 <= level;
10:level_10<= level;
11:level_11<= level;
12:level_12<= level;
13:level_13<= level;
14:level_14<= level;
15:level_15<= level;
endcase
always @(*)
if(t1s_sel)
len_comb <= TrailingOnes;
else if(prefix_sel)
len_comb <= level_prefix_comb + 1;
else if(suffix_sel && suffixLength > 0 && level_prefix <= 14)
len_comb <= suffixLength;
else if(suffix_sel && level_prefix == 14)
len_comb <= 4;
else if(suffix_sel && level_prefix == 15)
len_comb <= 12;
else
len_comb <= 0;
endmodule

View File

@ -0,0 +1,368 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_read_run_befores ////
//// ////
//// Description ////
//// decode runs and combine them with levels ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-16 initiial revision
`include "defines.v"
module cavlc_read_run_befores
(
clk,
rst_n,
ena,
sel,
clr,
ZeroLeft_init,
rbsp,
i,
TotalZeros_comb,
level_0,
level_1,
level_2,
level_3,
level_4,
level_5,
level_6,
level_7,
level_8,
level_9,
level_10,
level_11,
level_12,
level_13,
level_14,
level_15,
coeff_0,
coeff_1,
coeff_2,
coeff_3,
coeff_4,
coeff_5,
coeff_6,
coeff_7,
coeff_8,
coeff_9,
coeff_10,
coeff_11,
coeff_12,
coeff_13,
coeff_14,
coeff_15,
ZeroLeft,
len_comb
);
//----------------------
//ports
//----------------------
input clk;
input rst_n;
input ena;
input sel;
input clr;
input ZeroLeft_init;
input [0:10] rbsp;
input [3:0] i; //range from TotalCoeff-1 to 0
input [3:0] TotalZeros_comb;
input [8:0] level_0;
input [8:0] level_1;
input [8:0] level_2;
input [8:0] level_3;
input [8:0] level_4;
input [8:0] level_5;
input [8:0] level_6;
input [8:0] level_7;
input [8:0] level_8;
input [8:0] level_9;
input [8:0] level_10;
input [8:0] level_11;
input [8:0] level_12;
input [8:0] level_13;
input [8:0] level_14;
input [8:0] level_15;
output [8:0] coeff_0;
output [8:0] coeff_1;
output [8:0] coeff_2;
output [8:0] coeff_3;
output [8:0] coeff_4;
output [8:0] coeff_5;
output [8:0] coeff_6;
output [8:0] coeff_7;
output [8:0] coeff_8;
output [8:0] coeff_9;
output [8:0] coeff_10;
output [8:0] coeff_11;
output [8:0] coeff_12;
output [8:0] coeff_13;
output [8:0] coeff_14;
output [8:0] coeff_15;
output [3:0] ZeroLeft;
output [3:0] len_comb;
//----------------------
//regs
//----------------------
reg [3:0] run;
reg [3:0] len;
reg [8:0] coeff;
reg [3:0] len_comb;
//----------------------
//FFs
//----------------------
reg [3:0] ZeroLeft;
reg [8:0] coeff_0;
reg [8:0] coeff_1;
reg [8:0] coeff_2;
reg [8:0] coeff_3;
reg [8:0] coeff_4;
reg [8:0] coeff_5;
reg [8:0] coeff_6;
reg [8:0] coeff_7;
reg [8:0] coeff_8;
reg [8:0] coeff_9;
reg [8:0] coeff_10;
reg [8:0] coeff_11;
reg [8:0] coeff_12;
reg [8:0] coeff_13;
reg [8:0] coeff_14;
reg [8:0] coeff_15;
//----------------------
//run & len
//----------------------
always @(rbsp or ZeroLeft or ena or sel)
if (ena && sel)
case(ZeroLeft)
0 : begin len <= 0; run <= 0; end
1 : begin len <= 1; run <= rbsp[0]? 0:1; end
2 : begin if (rbsp[0]) begin
run <= 0;
len <= 1;
end
else if (rbsp[1]) begin
run <= 1;
len <= 2;
end
else begin
run <= 2;
len <= 2;
end
end
3 : begin
run <= 3 - rbsp[0:1];
len <= 2;
end
4 : begin
if (rbsp[0:1] != 0) begin
run <= 3 - rbsp[0:1];
len <= 2;
end
else begin
run <= rbsp[2]? 3:4;
len <= 3;
end
end
5 : begin
if (rbsp[0]) begin
run <= rbsp[1]? 0:1;
len <= 2;
end
else if (rbsp[1]) begin
run <= rbsp[2]? 2:3;
len <= 3;
end
else begin
run <= rbsp[2]? 4:5;
len <= 3;
end
end
6 : begin
if (rbsp[0:1] == 2'b11) begin
run <= 0;
len <= 2;
end
else begin
len <= 3;
case(rbsp[0:2])
3'b000 : run <= 1;
3'b001 : run <= 2;
3'b011 : run <= 3;
3'b010 : run <= 4;
3'b101 : run <= 5;
default: run <= 6;
endcase
end
end
default : begin
if (rbsp[0:2] != 0) begin
run <= 7 - rbsp[0:2];
len <= 3;
end
else begin
case (1'b1)
rbsp[3] : begin run <= 7; len <= 4; end
rbsp[4] : begin run <= 8; len <= 5; end
rbsp[5] : begin run <= 9; len <= 6; end
rbsp[6] : begin run <= 10; len <= 7; end
rbsp[7] : begin run <= 11; len <= 8; end
rbsp[8] : begin run <= 12; len <= 9; end
rbsp[9] : begin run <= 13; len <= 10;end
rbsp[10]: begin run <= 14; len <= 11;end
default : begin run <= 'bx; len <='bx;end
endcase
end
end
endcase
else begin
len <= 0;
run <= 0;
end
//----------------------
//len_comb
//----------------------
always @(*)
if (i > 0)
len_comb <= len;
else
len_comb <= 0;
//----------------------
//ZeroLeft
//----------------------
always @(posedge clk or negedge rst_n)
if (!rst_n)
ZeroLeft <= 0;
else if (ena && clr) //in case TotalCoeff >= max_coeff_num
ZeroLeft <= 0;
else if (ena && ZeroLeft_init)
ZeroLeft <= TotalZeros_comb;
else if (ena && sel )//if ZeroLeft == 0, run will be 0
ZeroLeft <= ZeroLeft - run;
//----------------------
//coeff
//----------------------
always @(*)
if (ena && sel)
case (i)
0 :coeff <= level_0;
1 :coeff <= level_1;
2 :coeff <= level_2;
3 :coeff <= level_3;
4 :coeff <= level_4;
5 :coeff <= level_5;
6 :coeff <= level_6;
7 :coeff <= level_7;
8 :coeff <= level_8;
9 :coeff <= level_9;
10:coeff <= level_10;
11:coeff <= level_11;
12:coeff <= level_12;
13:coeff <= level_13;
14:coeff <= level_14;
15:coeff <= level_15;
endcase
else
coeff <= 0;
//----------------------
//coeff_0 to coeff_15
//----------------------
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
coeff_0 <= 0; coeff_1 <= 0; coeff_2 <= 0; coeff_3 <= 0;
coeff_4 <= 0; coeff_5 <= 0; coeff_6 <= 0; coeff_7 <= 0;
coeff_8 <= 0; coeff_9 <= 0; coeff_10<= 0; coeff_11<= 0;
coeff_12<= 0; coeff_13<= 0; coeff_14<= 0; coeff_15<= 0;
end
else if (ena && clr) begin
coeff_0 <= 0; coeff_1 <= 0; coeff_2 <= 0; coeff_3 <= 0;
coeff_4 <= 0; coeff_5 <= 0; coeff_6 <= 0; coeff_7 <= 0;
coeff_8 <= 0; coeff_9 <= 0; coeff_10<= 0; coeff_11<= 0;
coeff_12<= 0; coeff_13<= 0; coeff_14<= 0; coeff_15<= 0;
end
else if (ena && sel && ZeroLeft > 0)
case (ZeroLeft+i)
1 :coeff_1 <= coeff;
2 :coeff_2 <= coeff;
3 :coeff_3 <= coeff;
4 :coeff_4 <= coeff;
5 :coeff_5 <= coeff;
6 :coeff_6 <= coeff;
7 :coeff_7 <= coeff;
8 :coeff_8 <= coeff;
9 :coeff_9 <= coeff;
10:coeff_10 <= coeff;
11:coeff_11 <= coeff;
12:coeff_12 <= coeff;
13:coeff_13 <= coeff;
14:coeff_14 <= coeff;
default:
coeff_15 <= coeff;
endcase
else if (ena && sel) begin
if (i >= 0) coeff_0 <= level_0;
if (i >= 1) coeff_1 <= level_1;
if (i >= 2) coeff_2 <= level_2;
if (i >= 3) coeff_3 <= level_3;
if (i >= 4) coeff_4 <= level_4;
if (i >= 5) coeff_5 <= level_5;
if (i >= 6) coeff_6 <= level_6;
if (i >= 7) coeff_7 <= level_7;
if (i >= 8) coeff_8 <= level_8;
if (i >= 9) coeff_9 <= level_9;
if (i >= 10)coeff_10 <= level_10;
if (i >= 11)coeff_11 <= level_11;
if (i >= 12)coeff_12 <= level_12;
if (i >= 13)coeff_13 <= level_13;
if (i >= 14)coeff_14 <= level_14;
if (i == 15)coeff_15 <= level_15;
end
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,716 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_read_total_zeros ////
//// ////
//// Description ////
//// decode total_zeros ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-14 initial version
`include "defines.v"
module cavlc_read_total_zeros
(
ena,
sel,
chroma_DC_sel,
rbsp,
TotalCoeff,
TotalZeros_comb,
len_comb
);
//------------------------
//ports
//------------------------
input ena;
input sel;
input chroma_DC_sel;
input [0:8] rbsp;
input [3:0] TotalCoeff;
output [3:0] TotalZeros_comb;
output [3:0] len_comb;
//-------------------------
//rregs
//-------------------------
reg [3:0] TotalZeros_comb; //TotalZeros will be saved as ZeroLeft in module cavlc_read_run_befores
reg [3:0] len_comb;
//for chroma_DC
reg [0:2] rbsp_chroma_DC;
reg [1:0] TotalZeros_chroma_DC;
reg [1:0] len_chroma_DC;
//for TotalCoeff <= 3
reg [0:8] rbsp_LE3;
reg [3:0] TotalZeros_LE3;
reg [3:0] len_LE3;
//for TotalCoeff > 3
reg [0:5] rbsp_G3;
reg [3:0] TotalZeros_G3;
reg [2:0] len_G3;
//----------------------------------------
//input mux
//----------------------------------------
always @(*)
if (ena && sel && chroma_DC_sel) begin
rbsp_chroma_DC <= rbsp[0:2];
rbsp_LE3 <= 'hffff;
rbsp_G3 <= 'hffff;
end
else if (ena && sel && TotalCoeff[3:2] == 2'b00) begin
rbsp_chroma_DC <= 'hffff;
rbsp_LE3 <= rbsp[0:8];
rbsp_G3 <= 'hffff;
end
else if (ena && sel)begin
rbsp_chroma_DC <= 'hffff;
rbsp_LE3 <= 'hffff;
rbsp_G3 <= rbsp[0:5];
end
else begin
rbsp_chroma_DC <= 'hffff;
rbsp_LE3 <= 'hffff;
rbsp_G3 <= 'hffff;
end
//----------------------------------------
//TotalZeros_chroma_DC & len_chroma_DC
//----------------------------------------
always @(*)
if ( TotalCoeff == 1 && rbsp_chroma_DC[0] ) begin
TotalZeros_chroma_DC <= 0;
len_chroma_DC <= 1;
end
else if ( TotalCoeff == 1 && rbsp_chroma_DC[1] ) begin
TotalZeros_chroma_DC <= 1;
len_chroma_DC <= 2;
end
else if ( TotalCoeff == 1 && rbsp_chroma_DC[2] ) begin
TotalZeros_chroma_DC <= 2;
len_chroma_DC <= 3;
end
else if ( TotalCoeff == 1 ) begin
TotalZeros_chroma_DC <= 3;
len_chroma_DC <= 3;
end
else if ( TotalCoeff == 2 && rbsp_chroma_DC[0] ) begin
TotalZeros_chroma_DC <= 0;
len_chroma_DC <= 1;
end
else if ( TotalCoeff == 2 && rbsp_chroma_DC[1] ) begin
TotalZeros_chroma_DC <= 1;
len_chroma_DC <= 2;
end
else if ( TotalCoeff == 2 ) begin
TotalZeros_chroma_DC <= 2;
len_chroma_DC <= 2;
end
else if ( rbsp_chroma_DC[0] ) begin
TotalZeros_chroma_DC <= 0;
len_chroma_DC <= 1;
end
else begin
TotalZeros_chroma_DC <= 1;
len_chroma_DC <= 1;
end
//---------------------------------
//TotalZeros_LE3 & len_LE3
//---------------------------------
always @(rbsp_LE3 or TotalCoeff)
case (TotalCoeff[1:0])
1 :begin
case(1'b1)
rbsp_LE3[0] : begin
TotalZeros_LE3 <= 0;
len_LE3 <= 1;
end
rbsp_LE3[1] : begin
len_LE3 <= 3;
if (rbsp_LE3[2])
TotalZeros_LE3 <= 1;
else
TotalZeros_LE3 <= 2;
end
rbsp_LE3[2] : begin
len_LE3 <= 4;
if (rbsp_LE3[3])
TotalZeros_LE3 <= 3;
else
TotalZeros_LE3 <= 4;
end
rbsp_LE3[3] : begin
len_LE3 <= 5;
if (rbsp_LE3[4])
TotalZeros_LE3 <= 5;
else
TotalZeros_LE3 <= 6;
end
rbsp_LE3[4] : begin
len_LE3 <= 6;
if (rbsp_LE3[5])
TotalZeros_LE3 <= 7;
else
TotalZeros_LE3 <= 8;
end
rbsp_LE3[5] : begin
len_LE3 <= 7;
if (rbsp_LE3[6])
TotalZeros_LE3 <= 9;
else
TotalZeros_LE3 <= 10;
end
rbsp_LE3[6] : begin
len_LE3 <= 8;
if (rbsp_LE3[7])
TotalZeros_LE3 <= 11;
else
TotalZeros_LE3 <= 12;
end
rbsp_LE3[7] : begin
len_LE3 <= 9;
if (rbsp_LE3[8])
TotalZeros_LE3 <= 13;
else
TotalZeros_LE3 <= 14;
end
default : begin
len_LE3 <= 9;
TotalZeros_LE3 <= 15;
end
endcase
end
2 : begin
case(1'b1)
rbsp_LE3[0] : begin
len_LE3 <= 3;
case(rbsp_LE3[1:2])
'b11 : TotalZeros_LE3 <= 0;
'b10 : TotalZeros_LE3 <= 1;
'b01 : TotalZeros_LE3 <= 2;
'b00 : TotalZeros_LE3 <= 3;
endcase
end
rbsp_LE3[1] : begin
if (rbsp_LE3[2]) begin
TotalZeros_LE3 <= 4;
len_LE3 <= 3;
end
else begin
len_LE3 <= 4;
if (rbsp_LE3[3])
TotalZeros_LE3 <= 5;
else
TotalZeros_LE3 <= 6;
end
end
rbsp_LE3[2] : begin
len_LE3 <= 4;
if (rbsp_LE3[3])
TotalZeros_LE3 <= 7;
else
TotalZeros_LE3 <= 8;
end
rbsp_LE3[3] : begin
len_LE3 <= 5;
if (rbsp_LE3[4])
TotalZeros_LE3 <= 9;
else
TotalZeros_LE3 <= 10;
end
default : begin
len_LE3 <= 6;
case(rbsp_LE3[4:5])
'b11 : TotalZeros_LE3 <= 11;
'b10 : TotalZeros_LE3 <= 12;
'b01 : TotalZeros_LE3 <= 13;
'b00 : TotalZeros_LE3 <= 14;
endcase
end
endcase
end
3 : begin
case(1'b1)
rbsp_LE3[0] : begin
len_LE3 <= 3;
case(rbsp_LE3[1:2])
'b11 : TotalZeros_LE3 <= 1;
'b10 : TotalZeros_LE3 <= 2;
'b01 : TotalZeros_LE3 <= 3;
'b00 : TotalZeros_LE3 <= 6;
endcase
end
rbsp_LE3[1] : begin
if (rbsp_LE3[2]) begin
TotalZeros_LE3 <= 7;
len_LE3 <= 3;
end
else begin
len_LE3 <= 4;
if (rbsp_LE3[3])
TotalZeros_LE3 <= 0;
else
TotalZeros_LE3 <= 4;
end
end
rbsp_LE3[2] : begin
len_LE3 <= 4;
if (rbsp_LE3[3])
TotalZeros_LE3 <= 5;
else
TotalZeros_LE3 <= 8;
end
rbsp_LE3[3] : begin
len_LE3 <= 5;
if (rbsp_LE3[4])
TotalZeros_LE3 <= 9;
else
TotalZeros_LE3 <= 10;
end
rbsp_LE3[4] : begin
len_LE3 <= 5;
TotalZeros_LE3 <= 12;
end
default : begin
len_LE3 <= 6;
if(rbsp_LE3[5])
TotalZeros_LE3 <= 11;
else
TotalZeros_LE3 <= 13;
end
endcase
end
default : begin
len_LE3 <= 'bx;
TotalZeros_LE3 <= 'bx;
end
endcase
//---------------------------------
//TotalZeros_G3 & len_G3
//---------------------------------
always @(rbsp_G3 or TotalCoeff)
case (TotalCoeff)
4 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 3;
case(rbsp_G3[1:2])
'b11 : TotalZeros_G3 <= 1;
'b10 : TotalZeros_G3 <= 4;
'b01 : TotalZeros_G3 <= 5;
'b00 : TotalZeros_G3 <= 6;
endcase
end
rbsp_G3[1] : begin
if (rbsp_G3[2]) begin
TotalZeros_G3 <= 8;
len_G3 <= 3;
end
else begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 2;
else
TotalZeros_G3 <= 3;
end
end
rbsp_G3[2] : begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 7;
else
TotalZeros_G3 <= 9;
end
default : begin
len_G3 <= 5;
case(rbsp_G3[3:4])
'b11 : TotalZeros_G3 <= 0;
'b10 : TotalZeros_G3 <= 10;
'b01 : TotalZeros_G3 <= 11;
'b00 : TotalZeros_G3 <= 12;
endcase
end
endcase
end
5 :begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 3;
case(rbsp_G3[1:2])
'b11 : TotalZeros_G3 <= 3;
'b10 : TotalZeros_G3 <= 4;
'b01 : TotalZeros_G3 <= 5;
'b00 : TotalZeros_G3 <= 6;
endcase
end
rbsp_G3[1] : begin
if (rbsp_G3[2]) begin
TotalZeros_G3 <= 7;
len_G3 <= 3;
end
else begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 1;
end
end
rbsp_G3[2] : begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 2;
else
TotalZeros_G3 <= 8;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 10;
end
default : begin
len_G3 <= 5;
if (rbsp_G3[4])
TotalZeros_G3 <= 9;
else
TotalZeros_G3 <= 11;
end
endcase
end
6 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 3;
case(rbsp_G3[1:2])
'b11 : TotalZeros_G3 <= 2;
'b10 : TotalZeros_G3 <= 3;
'b01 : TotalZeros_G3 <= 4;
'b00 : TotalZeros_G3 <= 5;
endcase
end
rbsp_G3[1] : begin
len_G3 <= 3;
if (rbsp_G3[2])
TotalZeros_G3 <= 6;
else
TotalZeros_G3 <= 7;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 9;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 8;
end
rbsp_G3[4] : begin
len_G3 <= 5;
TotalZeros_G3 <= 1;
end
default : begin
len_G3 <= 6;
if (rbsp_G3[5])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 10;
end
endcase
end
7 :begin
case(1'b1)
rbsp_G3[0] : begin
if (rbsp_G3[1]) begin
TotalZeros_G3 <= 5;
len_G3 <= 2;
end
else begin
len_G3 <= 3;
if (rbsp_G3[2])
TotalZeros_G3 <= 2;
else
TotalZeros_G3 <= 3;
end
end
rbsp_G3[1] : begin
len_G3 <= 3;
if (rbsp_G3[2])
TotalZeros_G3 <= 4;
else
TotalZeros_G3 <= 6;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 8;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 7;
end
rbsp_G3[4] : begin
len_G3 <= 5;
TotalZeros_G3 <= 1;
end
default : begin
len_G3 <= 6;
if (rbsp_G3[5])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 9;
end
endcase
end
8 :begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 2;
if (rbsp_G3[1])
TotalZeros_G3 <= 4;
else
TotalZeros_G3 <= 5;
end
rbsp_G3[1] : begin
len_G3 <= 3;
if (rbsp_G3[2])
TotalZeros_G3 <= 3;
else
TotalZeros_G3 <= 6;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 7;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 1;
end
rbsp_G3[4] : begin
len_G3 <= 5;
TotalZeros_G3 <= 2;
end
default : begin
len_G3 <= 6;
if (rbsp_G3[5])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 8;
end
endcase
end
9 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 2;
if (rbsp_G3[1])
TotalZeros_G3 <= 3;
else
TotalZeros_G3 <= 4;
end
rbsp_G3[1] : begin
len_G3 <= 2;
TotalZeros_G3 <= 6;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 5;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 2;
end
rbsp_G3[4] : begin
len_G3 <= 5;
TotalZeros_G3 <= 7;
end
default : begin
len_G3 <= 6;
if (rbsp_G3[5])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 1;
end
endcase
end
10 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 2;
if (rbsp_G3[1])
TotalZeros_G3 <= 3;
else
TotalZeros_G3 <= 4;
end
rbsp_G3[1] : begin
len_G3 <= 2;
TotalZeros_G3 <= 5;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 2;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 6;
end
default : begin
len_G3 <= 5;
if (rbsp_G3[4])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 1;
end
endcase
end
11 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 1;
TotalZeros_G3 <= 4;
end
rbsp_G3[1] : begin
len_G3 <= 3;
if (rbsp_G3[2])
TotalZeros_G3 <= 5;
else
TotalZeros_G3 <= 3;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 2;
end
default : begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 1;
else
TotalZeros_G3 <= 0;
end
endcase
end
12 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 1;
TotalZeros_G3 <= 3;
end
rbsp_G3[1] : begin
len_G3 <= 2;
TotalZeros_G3 <= 2;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 4;
end
default : begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 1;
else
TotalZeros_G3 <= 0;
end
endcase
end
13 :begin
if (rbsp_G3[0]) begin
TotalZeros_G3 <= 2;
len_G3 <= 1;
end
else if (rbsp_G3[1]) begin
TotalZeros_G3 <= 3;
len_G3 <= 2;
end
else if (rbsp_G3[2]) begin
TotalZeros_G3 <= 1;
len_G3 <= 3;
end
else begin
TotalZeros_G3 <= 0;
len_G3 <= 3;
end
end
14 : begin
if (rbsp_G3[0]) begin
TotalZeros_G3 <= 2;
len_G3 <= 1;
end
else if (rbsp_G3[1]) begin
TotalZeros_G3 <= 1;
len_G3 <= 2;
end
else begin
TotalZeros_G3 <= 0;
len_G3 <= 2;
end
end
15 : begin
len_G3 <= 1;
if (rbsp_G3[0])
TotalZeros_G3 <= 1;
else
TotalZeros_G3 <= 0;
end
default : begin
len_G3 <= 'bx;
TotalZeros_G3 <= 'bx;
end
endcase
//---------------------------------
//TotalZeros_comb & len_comb
//---------------------------------
always @(*)
if (ena && sel && chroma_DC_sel) begin
TotalZeros_comb <= TotalZeros_chroma_DC;
len_comb <= len_chroma_DC;
end
else if (ena && sel && TotalCoeff[3:2] == 2'b00) begin
TotalZeros_comb <= TotalZeros_LE3;
len_comb <= len_LE3;
end
else if (ena && sel)begin
TotalZeros_comb <= TotalZeros_G3;
len_comb <= len_G3;
end
else begin
TotalZeros_comb <= 0;
len_comb <= 0;
end
endmodule

View File

@ -0,0 +1,294 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_top ////
//// ////
//// Description ////
//// top module of cavlc decoder ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-7 initial version
`include "defines.v"
module cavlc_top
(
clk,
rst_n,
ena,
start,
rbsp,
nC,
max_coeff_num,
coeff_0,
coeff_1,
coeff_2,
coeff_3,
coeff_4,
coeff_5,
coeff_6,
coeff_7,
coeff_8,
coeff_9,
coeff_10,
coeff_11,
coeff_12,
coeff_13,
coeff_14,
coeff_15,
TotalCoeff,
len_comb,
idle,
valid
);
//------------------------
// ports
//------------------------
input clk, rst_n;
input ena;
input start;
input [0:15] rbsp;
input signed [5:0] nC;
input [4:0] max_coeff_num;
output signed [8:0] coeff_0;
output signed [8:0] coeff_1;
output signed [8:0] coeff_2;
output signed [8:0] coeff_3;
output signed [8:0] coeff_4;
output signed [8:0] coeff_5;
output signed [8:0] coeff_6;
output signed [8:0] coeff_7;
output signed [8:0] coeff_8;
output signed [8:0] coeff_9;
output signed [8:0] coeff_10;
output signed [8:0] coeff_11;
output signed [8:0] coeff_12;
output signed [8:0] coeff_13;
output signed [8:0] coeff_14;
output signed [8:0] coeff_15;
output [4:0] TotalCoeff;
output [4:0] len_comb;
output idle;
output valid;
//------------------------
// cavlc_read_total_coeffs
//------------------------
wire [1:0] TrailingOnes;
wire [4:0] TotalCoeff;
wire [1:0] TrailingOnes_comb;
wire [4:0] TotalCoeff_comb;
wire [4:0] len_read_total_coeffs_comb;
wire [7:0] cavlc_state;
cavlc_read_total_coeffs cavlc_read_total_coeffs(
.clk(clk),
.rst_n(rst_n),
.ena(ena),
.start(start),
.sel(cavlc_state[`cavlc_read_total_coeffs_bit]),
.rbsp(rbsp),
.nC(nC),
.TrailingOnes(TrailingOnes),
.TotalCoeff(TotalCoeff),
.TrailingOnes_comb(TrailingOnes_comb),
.TotalCoeff_comb(TotalCoeff_comb),
.len_comb(len_read_total_coeffs_comb)
);
//------------------------
// cavlc_read_levels
//------------------------
wire [4:0] len_read_levels_comb;
wire [3:0] i;
wire [8:0] level_0;
wire [8:0] level_1;
wire [8:0] level_2;
wire [8:0] level_3;
wire [8:0] level_4;
wire [8:0] level_5;
wire [8:0] level_6;
wire [8:0] level_7;
wire [8:0] level_8;
wire [8:0] level_9;
wire [8:0] level_10;
wire [8:0] level_11;
wire [8:0] level_12;
wire [8:0] level_13;
wire [8:0] level_14;
wire [8:0] level_15;
cavlc_read_levels cavlc_read_levels(
.clk(clk),
.rst_n(rst_n),
.ena(ena),
.t1s_sel(cavlc_state[`cavlc_read_t1s_flags_bit]),
.prefix_sel(cavlc_state[`cavlc_read_level_prefix_bit]),
.suffix_sel(cavlc_state[`cavlc_read_level_suffix_bit]),
.calc_sel(cavlc_state[`cavlc_calc_level_bit]),
.TrailingOnes(TrailingOnes),
.TotalCoeff(TotalCoeff),
.i(i),
.rbsp(rbsp),
.level_0(level_0),
.level_1(level_1),
.level_2(level_2),
.level_3(level_3),
.level_4(level_4),
.level_5(level_5),
.level_6(level_6),
.level_7(level_7),
.level_8(level_8),
.level_9(level_9),
.level_10(level_10),
.level_11(level_11),
.level_12(level_12),
.level_13(level_13),
.level_14(level_14),
.level_15(level_15),
.len_comb(len_read_levels_comb)
);
//------------------------
// cavlc_read_total_zeros
//------------------------
wire [3:0] TotalZeros_comb;
wire [3:0] len_read_total_zeros_comb;
cavlc_read_total_zeros cavlc_read_total_zeros(
.ena(ena),
.sel(cavlc_state[`cavlc_read_total_zeros_bit]),
.chroma_DC_sel(nC[5]),
.rbsp(rbsp[0:8]),
.TotalCoeff(TotalCoeff[3:0]),
.TotalZeros_comb(TotalZeros_comb),
.len_comb(len_read_total_zeros_comb)
);
//------------------------
// read_run_before
//------------------------
wire [3:0] ZeroLeft;
wire [3:0] len_read_run_befores_comb;
cavlc_read_run_befores cavlc_read_run_befores(
.clk(clk),
.rst_n(rst_n),
.ena(ena),
.clr(cavlc_state[`cavlc_read_total_coeffs_bit]),
.sel(cavlc_state[`cavlc_read_run_befores_bit]),
.ZeroLeft_init(cavlc_state[`cavlc_read_total_zeros_bit]),
.rbsp(rbsp[0:10]),
.i(i),
.TotalZeros_comb(TotalZeros_comb),
.level_0(level_0),
.level_1(level_1),
.level_2(level_2),
.level_3(level_3),
.level_4(level_4),
.level_5(level_5),
.level_6(level_6),
.level_7(level_7),
.level_8(level_8),
.level_9(level_9),
.level_10(level_10),
.level_11(level_11),
.level_12(level_12),
.level_13(level_13),
.level_14(level_14),
.level_15(level_15),
.coeff_0(coeff_0),
.coeff_1(coeff_1),
.coeff_2(coeff_2),
.coeff_3(coeff_3),
.coeff_4(coeff_4),
.coeff_5(coeff_5),
.coeff_6(coeff_6),
.coeff_7(coeff_7),
.coeff_8(coeff_8),
.coeff_9(coeff_9),
.coeff_10(coeff_10),
.coeff_11(coeff_11),
.coeff_12(coeff_12),
.coeff_13(coeff_13),
.coeff_14(coeff_14),
.coeff_15(coeff_15),
.ZeroLeft(ZeroLeft),
.len_comb(len_read_run_befores_comb)
);
//------------------------
// cavlc_len_gen
//------------------------
wire [4:0] len_comb;
cavlc_len_gen cavlc_len_gen(
.cavlc_state(cavlc_state),
.len_read_total_coeffs_comb(len_read_total_coeffs_comb),
.len_read_levels_comb(len_read_levels_comb),
.len_read_total_zeros_comb(len_read_total_zeros_comb),
.len_read_run_befores_comb(len_read_run_befores_comb),
.len_comb(len_comb)
);
//------------------------
// fsm
//------------------------
cavlc_fsm cavlc_fsm(
.clk(clk),
.rst_n(rst_n),
.ena(ena),
.start(start),
.max_coeff_num(max_coeff_num),
.TotalCoeff(TotalCoeff),
.TotalCoeff_comb(TotalCoeff_comb),
.TrailingOnes(TrailingOnes),
.TrailingOnes_comb(TrailingOnes_comb),
.ZeroLeft(ZeroLeft),
.state(cavlc_state),
.i(i),
.idle(idle),
.valid(valid)
);
endmodule

View File

@ -0,0 +1,22 @@
`timescale 1ns / 1ns // timescale time_unit/time_presicion
`define cavlc_idle_bit 0
`define cavlc_read_total_coeffs_bit 1
`define cavlc_read_t1s_flags_bit 2
`define cavlc_read_level_prefix_bit 3
`define cavlc_read_level_suffix_bit 4
`define cavlc_calc_level_bit 5
`define cavlc_read_total_zeros_bit 6
`define cavlc_read_run_befores_bit 7
`define cavlc_idle_s 8'b00000001
`define cavlc_read_total_coeffs_s 8'b00000010
`define cavlc_read_t1s_flags_s 8'b00000100
`define cavlc_read_level_prefix_s 8'b00001000
`define cavlc_read_level_suffix_s 8'b00010000
`define cavlc_calc_level_s 8'b00100000
`define cavlc_read_total_zeros_s 8'b01000000
`define cavlc_read_run_befores_s 8'b10000000

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
module counter(clk, q, rst);
input clk;
input rst;
output [7:0] q;
reg [7:0] q;
always @ (posedge clk)
begin
if(rst)
q <= 8'b00000000;
else
q <= q + 1;
end
endmodule

View File

@ -0,0 +1,24 @@
module counter_tb;
reg clk_counter, rst_counter;
wire [7:0] q_counter;
counter_original C_1(
clk_counter,
q_counter,
rst_counter);
initial begin
#0 rst_counter = 1'b1; clk_counter = 1'b0;
#100 rst_counter = 1'b0;
end
always begin
#10 clk_counter = ~clk_counter;
end
initial begin
#5000 $stop;
end
endmodule

View File

@ -0,0 +1,102 @@
// 5 counter with 5 clock domain
// each counter has 130 bits
// each counter has 21 output
// test: placement , routing and performace for each clock domain
module counter120bitx5(clk1,clk2,clk3,clk4,clk5,out1x,out2x,out3x,out4x,out5x,reset);
input clk1,clk2,clk3,clk4,clk5,reset;
output [13:0] out1x;
output [13:0] out2x;
output [13:0] out3x;
output [13:0] out4x;
output [13:0] out5x;
reg [120:0] cnt1;
reg [120:0] cnt2;
reg [120:0] cnt3;
reg [120:0] cnt4;
reg [120:0] cnt5;
assign out1x = {cnt1[120:115],cnt1[7:0]};
assign out2x = {cnt2[120:115],cnt2[7:0]};
assign out3x = {cnt3[120:115],cnt3[7:0]};
assign out4x = {cnt4[120:115],cnt4[7:0]};
assign out5x = {cnt5[120:115],cnt5[7:0]};
always @(posedge clk1)
begin
if (reset)
cnt1 <=1'b0;
else
cnt1 <= cnt1+1;
end
always @(posedge clk2)
begin
if (reset)
cnt2 <=1'b0;
else
cnt2 <= cnt2 +1;
end
always @(posedge clk3)
begin
if (reset)
cnt3 <=1'b0;
else
cnt3 <= cnt3 +1;
end
always @(posedge clk4)
begin
if (reset)
cnt4 <=1'b0;
else
cnt4 <= cnt4 +1;
end
always @(posedge clk5)
begin
if (reset)
cnt5 <=1'b0;
else
cnt5 <= cnt5 +1;
end
endmodule

View File

@ -0,0 +1,21 @@
//
// Copyright (c) 2020 QuickLogic Corporation. All Rights Reserved.
//
// Description :
// Example of asimple 16 bit up counter in Verilog HDL
//
// Version 1.0 : Initial Creation
//
module top (clk, reset, enable, count);
input clk, reset, enable;
output [15:0] count;
reg [15:0] count;
always @ (posedge clk)
if (reset == 1'b1) begin
count <= 0;
end else if ( enable == 1'b1) begin
count <= count + 1;
end
endmodule

View File

@ -0,0 +1,311 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Discrete Cosine Transform, Parallel implementation ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: dct.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module dct(
clk,
ena,
rst,
dstrb,
din,
dout_00, dout_01, dout_02, dout_03, dout_04, dout_05, dout_06, dout_07,
dout_10, dout_11, dout_12, dout_13, dout_14, dout_15, dout_16, dout_17,
dout_20, dout_21, dout_22, dout_23, dout_24, dout_25, dout_26, dout_27,
dout_30, dout_31, dout_32, dout_33, dout_34, dout_35, dout_36, dout_37,
dout_40, dout_41, dout_42, dout_43, dout_44, dout_45, dout_46, dout_47,
dout_50, dout_51, dout_52, dout_53, dout_54, dout_55, dout_56, dout_57,
dout_60, dout_61, dout_62, dout_63, dout_64, dout_65, dout_66, dout_67,
dout_70, dout_71, dout_72, dout_73, dout_74, dout_75, dout_76, dout_77,
douten
);
//
// parameters
//
// Worst case errors (Din = 64* -128) remain in decimal bit
// when using 13bit coefficients
//
// For ultra-high
parameter coef_width = 11;
parameter di_width = 8;
parameter do_width = 12;
//
// inputs & outputs
//
input clk;
input ena;
input rst; // active low asynchronous reset
input dstrb; // data-strobe. Present dstrb 1clk-cycle before data block
input [di_width:1] din;
output [do_width:1]
dout_00, dout_01, dout_02, dout_03, dout_04, dout_05, dout_06, dout_07,
dout_10, dout_11, dout_12, dout_13, dout_14, dout_15, dout_16, dout_17,
dout_20, dout_21, dout_22, dout_23, dout_24, dout_25, dout_26, dout_27,
dout_30, dout_31, dout_32, dout_33, dout_34, dout_35, dout_36, dout_37,
dout_40, dout_41, dout_42, dout_43, dout_44, dout_45, dout_46, dout_47,
dout_50, dout_51, dout_52, dout_53, dout_54, dout_55, dout_56, dout_57,
dout_60, dout_61, dout_62, dout_63, dout_64, dout_65, dout_66, dout_67,
dout_70, dout_71, dout_72, dout_73, dout_74, dout_75, dout_76, dout_77;
output douten; // data-out enable
reg douten;
//
// variables
//
reg go, dgo, ddgo, ddcnt, dddcnt;
reg [di_width:1] ddin;
//
// module body
//
// generate sample counter
reg [5:0] sample_cnt;
wire dcnt = &sample_cnt;
always @(posedge clk or negedge rst)
if (~rst)
sample_cnt <= #1 6'h0;
else if (ena)
if(dstrb)
sample_cnt <= #1 6'h0;
else if(~dcnt)
sample_cnt <= #1 sample_cnt + 6'h1;
// internal signals
always @(posedge clk or negedge rst)
if (~rst)
begin
go <= #1 1'b0;
dgo <= #1 1'b0;
ddgo <= #1 1'b0;
ddin <= #1 0;
douten <= #1 1'b0;
ddcnt <= #1 1'b1;
dddcnt <= #1 1'b1;
end
else if (ena)
begin
go <= #1 dstrb;
dgo <= #1 go;
ddgo <= #1 dgo;
ddin <= #1 din;
ddcnt <= #1 dcnt;
dddcnt <= #1 ddcnt;
douten <= #1 ddcnt & ~dddcnt;
end
// Hookup DCT units
// V = 0
dctub #(coef_width, di_width, 3'h0)
dct_block_0 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_00), // (U,V) = (0,0)
.dout1(dout_01), // (U,V) = (0,1)
.dout2(dout_02), // (U,V) = (0,2)
.dout3(dout_03), // (U,V) = (0,3)
.dout4(dout_04), // (U,V) = (0,4)
.dout5(dout_05), // (U,V) = (0,5)
.dout6(dout_06), // (U,V) = (0,6)
.dout7(dout_07) // (U,V) = (0,7)
);
// V = 1
dctub #(coef_width, di_width, 3'h1)
dct_block_1 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_10), // (U,V) = (1,0)
.dout1(dout_11), // (U,V) = (1,1)
.dout2(dout_12), // (U,V) = (1,2)
.dout3(dout_13), // (U,V) = (1,3)
.dout4(dout_14), // (U,V) = (1,4)
.dout5(dout_15), // (U,V) = (1,5)
.dout6(dout_16), // (U,V) = (1,6)
.dout7(dout_17) // (U,V) = (1,7)
);
// V = 2
dctub #(coef_width, di_width, 3'h2)
dct_block_2 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_20), // (U,V) = (2,0)
.dout1(dout_21), // (U,V) = (2,1)
.dout2(dout_22), // (U,V) = (2,2)
.dout3(dout_23), // (U,V) = (2,3)
.dout4(dout_24), // (U,V) = (2,4)
.dout5(dout_25), // (U,V) = (2,5)
.dout6(dout_26), // (U,V) = (2,6)
.dout7(dout_27) // (U,V) = (2,7)
);
// V = 3
dctub #(coef_width, di_width, 3'h3)
dct_block_3 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_30), // (U,V) = (3,0)
.dout1(dout_31), // (U,V) = (3,1)
.dout2(dout_32), // (U,V) = (3,2)
.dout3(dout_33), // (U,V) = (3,3)
.dout4(dout_34), // (U,V) = (3,4)
.dout5(dout_35), // (U,V) = (3,5)
.dout6(dout_36), // (U,V) = (3,6)
.dout7(dout_37) // (U,V) = (3,7)
);
// V = 4
dctub #(coef_width, di_width, 3'h4)
dct_block_4 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_40), // (U,V) = (4,0)
.dout1(dout_41), // (U,V) = (4,1)
.dout2(dout_42), // (U,V) = (4,2)
.dout3(dout_43), // (U,V) = (4,3)
.dout4(dout_44), // (U,V) = (4,4)
.dout5(dout_45), // (U,V) = (4,5)
.dout6(dout_46), // (U,V) = (4,6)
.dout7(dout_47) // (U,V) = (4,7)
);
// V = 5
dctub #(coef_width, di_width, 3'h5)
dct_block_5 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_50), // (U,V) = (5,0)
.dout1(dout_51), // (U,V) = (5,1)
.dout2(dout_52), // (U,V) = (5,2)
.dout3(dout_53), // (U,V) = (5,3)
.dout4(dout_54), // (U,V) = (5,4)
.dout5(dout_55), // (U,V) = (5,5)
.dout6(dout_56), // (U,V) = (5,6)
.dout7(dout_57) // (U,V) = (5,7)
);
// V = 6
dctub #(coef_width, di_width, 3'h6)
dct_block_6 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_60), // (U,V) = (6,0)
.dout1(dout_61), // (U,V) = (6,1)
.dout2(dout_62), // (U,V) = (6,2)
.dout3(dout_63), // (U,V) = (6,3)
.dout4(dout_64), // (U,V) = (6,4)
.dout5(dout_65), // (U,V) = (6,5)
.dout6(dout_66), // (U,V) = (6,6)
.dout7(dout_67) // (U,V) = (6,7)
);
// V = 7
dctub #(coef_width, di_width, 3'h7)
dct_block_7 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_70), // (U,V) = (7,0)
.dout1(dout_71), // (U,V) = (7,1)
.dout2(dout_72), // (U,V) = (7,2)
.dout3(dout_73), // (U,V) = (7,3)
.dout4(dout_74), // (U,V) = (7,4)
.dout5(dout_75), // (U,V) = (7,5)
.dout6(dout_76), // (U,V) = (7,6)
.dout7(dout_77) // (U,V) = (7,7)
);
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,123 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Discrete Cosine Transform, MAC unit ////
//// ////
//// Virtex-II: Block-Multiplier is used ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: dct_mac.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module dct_mac(clk, ena, dclr, din, coef, result);
//
// parameters
//
parameter dwidth = 8;
parameter cwidth = 16;
parameter mwidth = dwidth + cwidth; // multiplier result
parameter rwidth = mwidth +3; // add 3 bits for growth
//
// inputs & outputs
//
input clk; // clock input
input ena; // clock enable
input dclr; // start new mac (delayed 1 cycle)
input [dwidth-1:0] din; // data input
input [cwidth-1:0] coef; // coefficient input
output [rwidth-1:0] result; // mac-result
reg [rwidth -1:0] result;
//
// variables
//
wire [mwidth-1:0] idin;
wire [mwidth-1:0] icoef;
reg [mwidth -1:0] mult_res /* synthesis syn_multstyle="block_mult" syn_pipeline=1*/ ;
wire [rwidth -1:0] ext_mult_res;
//
// module body
//
assign icoef = { {(mwidth-cwidth){coef[cwidth-1]}}, coef};
assign idin = { {(mwidth-dwidth){din[dwidth-1]}}, din};
// generate multiplier structure
always @(posedge clk)
if(ena)
mult_res <= #1 icoef * idin;
assign ext_mult_res = { {3{mult_res[mwidth-1]}}, mult_res};
// generate adder structure
always @(posedge clk)
if(ena)
if(dclr)
result <= #1 ext_mult_res;
else
result <= #1 ext_mult_res + result;
endmodule

View File

@ -0,0 +1,95 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Discrete Cosine Transform Synthesis Test ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
//// Synthesis results: ////
//// ////
//// ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: dct_syn.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
module dct_syn(clk, ena, rst, dstrb, din, dout, den);
input clk;
input ena;
input rst;
input dstrb;
input [7:0] din;
output [11:0] dout;
output den;
//
// DCT unit
//
// As little as 11bits coefficients can be used while
// all errors remain in the decimal bit range (dout[0])
// total errors = 5(14bit resolution)
// = 12(13bit resolution)
// = 26(12bit resolution)
// = 54(11bit resolution)
fdct #(13) dut (
.clk(clk),
.ena(1'b1),
.rst(rst),
.dstrb(dstrb),
.din(din),
.dout(dout),
.douten(den)
);
endmodule

View File

@ -0,0 +1,106 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Discrete Cosine Transform Unit ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: dctu.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module dctu(clk, ena, ddgo, x, y, ddin, dout);
parameter coef_width = 16;
parameter di_width = 8;
parameter [2:0] v = 0;
parameter [2:0] u = 0;
//
// inputs & outputs
//
input clk;
input ena;
input ddgo; // double delayed go signal
input [2:0] x, y;
input [di_width:1] ddin; // delayed data input
output [11:0] dout;
//
// variables
//
reg [ 31:0] coef;
wire [coef_width +10:0] result;
`include "dct_cos_table.v"
//
// module body
//
// hookup cosine-table
always @(posedge clk)
if(ena)
coef <= #1 dct_cos_table(x, y, u, v);
// hookup dct-mac unit
dct_mac #(8, coef_width)
macu (
.clk(clk),
.ena(ena),
.dclr(ddgo),
.din(ddin),
.coef( coef[31:31 -coef_width +1] ),
.result(result)
);
assign dout = result[coef_width +10: coef_width -1];
endmodule

View File

@ -0,0 +1,169 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Discrete Cosine Transform, DCT unit block ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: dctub.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module dctub(clk, ena, ddgo, x, y, ddin,
dout0, dout1, dout2, dout3, dout4, dout5, dout6, dout7);
parameter coef_width = 16;
parameter di_width = 8;
parameter [2:0] v = 3'h0;
//
// inputs & outputs
//
input clk;
input ena;
input ddgo; // double delayed go strobe
input [2:0] x, y;
input [di_width:1] ddin; // delayed data input
output [11:0] dout0, dout1, dout2, dout3, dout4, dout5, dout6, dout7;
//
// module body
//
// Hookup DCT units
dctu #(coef_width, di_width, v, 3'h0)
dct_unit_0 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout0)
);
dctu #(coef_width, di_width, v, 3'h1)
dct_unit_1 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout1)
);
dctu #(coef_width, di_width, v, 3'h2)
dct_unit_2 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout2)
);
dctu #(coef_width, di_width, v, 3'h3)
dct_unit_3 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout3)
);
dctu #(coef_width, di_width, v, 3'h4)
dct_unit_4 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout4)
);
dctu #(coef_width, di_width, v, 3'h5)
dct_unit_5 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout5)
);
dctu #(coef_width, di_width, v, 3'h6)
dct_unit_6 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout6)
);
dctu #(coef_width, di_width, v, 3'h7)
dct_unit_7 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout7)
);
endmodule

View File

@ -0,0 +1,292 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Forward Discrete Cosine Transform and ZigZag unit ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: fdct.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module fdct(clk, ena, rst, dstrb, din, dout, douten);
//
// parameters
//
////////////////////////////////////////////////////////////////////
// //
// ITU-T.81, ITU-T.83 & Coefficient resolution notes //
// //
////////////////////////////////////////////////////////////////////
// //
// Worst case error (all input values -128) is //
// zero (i.e. no errors) when using 15bit coefficients //
// //
// Using less bits for the coefficients produces a biterror //
// approx. equal to (15 - used_coefficient-bits). //
// i.e. 14bit coefficients, errors in dout-bit[0] only //
// 13bit coefficients, errors in dout-bits[1:0] //
// 12bit coefficients, errors in dout-bits[2:0] etc. //
// Tests with real non-continous tone image data have shown that //
// even when using 13bit coefficients errors remain in the lsb //
// only (i.e. dout-bit[0] //
// //
// The amount of coefficient-bits needed is dependent on the //
// desired quality. //
// The JPEG-standard compliance specs.(ITU-T.83) prescribe //
// that the output of the combined DCT AND Quantization unit //
// shall not exceed 1 for the desired quality. //
// //
// This means for high quantization levels, lesser bits //
// for the DCT unit can be used. //
// //
// Looking at the recommended "quantization tables for generic //
// compliance testing of DCT-based processes" (ITU-T.83 annex B) //
// it can be noticed that relatively large quantization values //
// are being used. Errors in the lower-order bits should //
// therefore not be visible. //
// For certain applications some of the lower-order bits could //
// actually be discarded. When looking at the luminance and //
// chrominance example quantization tables (ITU-T.81 annex K) //
// it can be seen that the smallest quantization value is ten //
// (qnt_val_min = 10). This means that the lowest 2bits can be //
// discarded (set to zero '0') without having any effect on the //
// final result. In this example 11 bit or 12 bit coefficients //
// would be sufficient. //
// //
////////////////////////////////////////////////////////////////////
parameter coef_width = 11;
parameter di_width = 8;
parameter do_width = 12;
//
// inputs & outputs
//
input clk; // system clock
input ena; // clock enable
input rst; // active low asynchronous reset
input dstrb; // data-strobe. Present dstrb 1clk-cycle before data block
input [di_width-1:0] din;
output [do_width-1:0] dout;
output douten; // data-out enable
//
// variables
//
wire doe;
wire [do_width -1:0] // results from DCT module
res00, res01, res02, res03, res04, res05, res06, res07,
res10, res11, res12, res13, res14, res15, res16, res17,
res20, res21, res22, res23, res24, res25, res26, res27,
res30, res31, res32, res33, res34, res35, res36, res37,
res40, res41, res42, res43, res44, res45, res46, res47,
res50, res51, res52, res53, res54, res55, res56, res57,
res60, res61, res62, res63, res64, res65, res66, res67,
res70, res71, res72, res73, res74, res75, res76, res77;
//
// module body
//
// Hookup DCT module
dct #(coef_width, di_width, do_width)
dct_mod(
.clk(clk),
.ena(ena),
.rst(rst),
.dstrb(dstrb),
.din(din),
.dout_00(res00),
.dout_01(res01),
.dout_02(res02),
.dout_03(res03),
.dout_04(res04),
.dout_05(res05),
.dout_06(res06),
.dout_07(res07),
.dout_10(res10),
.dout_11(res11),
.dout_12(res12),
.dout_13(res13),
.dout_14(res14),
.dout_15(res15),
.dout_16(res16),
.dout_17(res17),
.dout_20(res20),
.dout_21(res21),
.dout_22(res22),
.dout_23(res23),
.dout_24(res24),
.dout_25(res25),
.dout_26(res26),
.dout_27(res27),
.dout_30(res30),
.dout_31(res31),
.dout_32(res32),
.dout_33(res33),
.dout_34(res34),
.dout_35(res35),
.dout_36(res36),
.dout_37(res37),
.dout_40(res40),
.dout_41(res41),
.dout_42(res42),
.dout_43(res43),
.dout_44(res44),
.dout_45(res45),
.dout_46(res46),
.dout_47(res47),
.dout_50(res50),
.dout_51(res51),
.dout_52(res52),
.dout_53(res53),
.dout_54(res54),
.dout_55(res55),
.dout_56(res56),
.dout_57(res57),
.dout_60(res60),
.dout_61(res61),
.dout_62(res62),
.dout_63(res63),
.dout_64(res64),
.dout_65(res65),
.dout_66(res66),
.dout_67(res67),
.dout_70(res70),
.dout_71(res71),
.dout_72(res72),
.dout_73(res73),
.dout_74(res74),
.dout_75(res75),
.dout_76(res76),
.dout_77(res77),
.douten(doe)
);
// Hookup ZigZag unit
zigzag zigzag_mod(
.clk(clk),
.ena(ena),
.dstrb(doe),
.din_00(res00),
.din_01(res01),
.din_02(res02),
.din_03(res03),
.din_04(res04),
.din_05(res05),
.din_06(res06),
.din_07(res07),
.din_10(res10),
.din_11(res11),
.din_12(res12),
.din_13(res13),
.din_14(res14),
.din_15(res15),
.din_16(res16),
.din_17(res17),
.din_20(res20),
.din_21(res21),
.din_22(res22),
.din_23(res23),
.din_24(res24),
.din_25(res25),
.din_26(res26),
.din_27(res27),
.din_30(res30),
.din_31(res31),
.din_32(res32),
.din_33(res33),
.din_34(res34),
.din_35(res35),
.din_36(res36),
.din_37(res37),
.din_40(res40),
.din_41(res41),
.din_42(res42),
.din_43(res43),
.din_44(res44),
.din_45(res45),
.din_46(res46),
.din_47(res47),
.din_50(res50),
.din_51(res51),
.din_52(res52),
.din_53(res53),
.din_54(res54),
.din_55(res55),
.din_56(res56),
.din_57(res57),
.din_60(res60),
.din_61(res61),
.din_62(res62),
.din_63(res63),
.din_64(res64),
.din_65(res65),
.din_66(res66),
.din_67(res67),
.din_70(res70),
.din_71(res71),
.din_72(res72),
.din_73(res73),
.din_74(res74),
.din_75(res75),
.din_76(res76),
.din_77(res77),
.dout(dout),
.douten(douten)
);
endmodule

View File

@ -0,0 +1,201 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Zig-Zag Unit ////
//// Performs zigzag-ing, as used by many DCT based encoders ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: zigzag.v,v 1.2 2002-10-23 09:06:59 rherveille Exp $
//
// $Date: 2002-10-23 09:06:59 $
// $Revision: 1.2 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
module zigzag(
clk,
ena,
dstrb,
din_00, din_01, din_02, din_03, din_04, din_05, din_06, din_07,
din_10, din_11, din_12, din_13, din_14, din_15, din_16, din_17,
din_20, din_21, din_22, din_23, din_24, din_25, din_26, din_27,
din_30, din_31, din_32, din_33, din_34, din_35, din_36, din_37,
din_40, din_41, din_42, din_43, din_44, din_45, din_46, din_47,
din_50, din_51, din_52, din_53, din_54, din_55, din_56, din_57,
din_60, din_61, din_62, din_63, din_64, din_65, din_66, din_67,
din_70, din_71, din_72, din_73, din_74, din_75, din_76, din_77,
dout,
douten
);
//
// inputs & outputs
//
input clk; // system clock
input ena; // clock enable
input dstrb; // data-strobe. Present dstrb 1clk-cycle before data block
input [11:0]
din_00, din_01, din_02, din_03, din_04, din_05, din_06, din_07,
din_10, din_11, din_12, din_13, din_14, din_15, din_16, din_17,
din_20, din_21, din_22, din_23, din_24, din_25, din_26, din_27,
din_30, din_31, din_32, din_33, din_34, din_35, din_36, din_37,
din_40, din_41, din_42, din_43, din_44, din_45, din_46, din_47,
din_50, din_51, din_52, din_53, din_54, din_55, din_56, din_57,
din_60, din_61, din_62, din_63, din_64, din_65, din_66, din_67,
din_70, din_71, din_72, din_73, din_74, din_75, din_76, din_77;
output [11:0] dout;
output douten; // data-out enable
//
// variables
//
reg ld_zigzag;
reg [11:0] sresult [63:0]; // store results for zig-zagging
//
// module body
//
always @(posedge clk)
if(ena)
ld_zigzag <= #1 dstrb;
assign douten = ld_zigzag;
//
// Generate zig-zag structure
//
// This implicates that the quantization step be performed after
// the zig-zagging.
//
// 0: 1: 2: 3: 4: 5: 6: 7: 0: 1: 2: 3: 4: 5: 6: 7:
// 0: 63 62 58 57 49 48 36 35 3f 3e 3a 39 31 30 24 23
// 1: 61 59 56 50 47 37 34 21 3d 3b 38 32 2f 25 22 15
// 2: 60 55 51 46 38 33 22 20 3c 37 33 2e 26 21 16 14
// 3: 54 52 45 39 32 23 19 10 36 34 2d 27 20 17 13 0a
// 4: 53 44 40 31 24 18 11 09 35 2c 28 1f 18 12 0b 09
// 5: 43 41 30 25 17 12 08 03 2b 29 1e 19 11 0c 08 03
// 6: 42 29 26 16 13 07 04 02 2a 1d 1a 10 0d 07 04 02
// 7: 28 27 15 14 06 05 01 00 1c 1b 0f 0e 06 05 01 00
//
// zig-zag the DCT results
integer n;
always @(posedge clk)
if(ena)
if(ld_zigzag) // reload results-register file
begin
sresult[63] <= #1 din_00;
sresult[62] <= #1 din_01;
sresult[61] <= #1 din_10;
sresult[60] <= #1 din_20;
sresult[59] <= #1 din_11;
sresult[58] <= #1 din_02;
sresult[57] <= #1 din_03;
sresult[56] <= #1 din_12;
sresult[55] <= #1 din_21;
sresult[54] <= #1 din_30;
sresult[53] <= #1 din_40;
sresult[52] <= #1 din_31;
sresult[51] <= #1 din_22;
sresult[50] <= #1 din_13;
sresult[49] <= #1 din_04;
sresult[48] <= #1 din_05;
sresult[47] <= #1 din_14;
sresult[46] <= #1 din_23;
sresult[45] <= #1 din_32;
sresult[44] <= #1 din_41;
sresult[43] <= #1 din_50;
sresult[42] <= #1 din_60;
sresult[41] <= #1 din_51;
sresult[40] <= #1 din_42;
sresult[39] <= #1 din_33;
sresult[38] <= #1 din_24;
sresult[37] <= #1 din_15;
sresult[36] <= #1 din_06;
sresult[35] <= #1 din_07;
sresult[34] <= #1 din_16;
sresult[33] <= #1 din_25;
sresult[32] <= #1 din_34;
sresult[31] <= #1 din_43;
sresult[30] <= #1 din_52;
sresult[29] <= #1 din_61;
sresult[28] <= #1 din_70;
sresult[27] <= #1 din_71;
sresult[26] <= #1 din_62;
sresult[25] <= #1 din_53;
sresult[24] <= #1 din_44;
sresult[23] <= #1 din_35;
sresult[22] <= #1 din_26;
sresult[21] <= #1 din_17;
sresult[20] <= #1 din_27;
sresult[19] <= #1 din_36;
sresult[18] <= #1 din_45;
sresult[17] <= #1 din_54;
sresult[16] <= #1 din_63;
sresult[15] <= #1 din_72;
sresult[14] <= #1 din_73;
sresult[13] <= #1 din_64;
sresult[12] <= #1 din_55;
sresult[11] <= #1 din_46;
sresult[10] <= #1 din_37;
sresult[09] <= #1 din_47;
sresult[08] <= #1 din_56;
sresult[07] <= #1 din_65;
sresult[06] <= #1 din_74;
sresult[05] <= #1 din_75;
sresult[04] <= #1 din_66;
sresult[03] <= #1 din_57;
sresult[02] <= #1 din_67;
sresult[01] <= #1 din_76;
sresult[00] <= #1 din_77;
end
else // shift results out
for (n=1; n<=63; n=n+1) // do not change sresult[0]
sresult[n] <= #1 sresult[n -1];
assign dout = sresult[63];
endmodule

Some files were not shown because too many files have changed in this diff Show More