Merge branch 'master' into gg_ci_cd_dev
This commit is contained in:
commit
f0294d1339
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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...");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 -----"));
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 += "}";
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue