Allow ouput to be read if connected to child output
If output P of A is connected to output Q of B (and A is instantiated inside B) then VHDL does not allow B to read the value of Q (also P), but Verilog does. To get around this the output Q is mapped to P_Sig which is then connected to P, this allows B to read the value of P/Q via P_Sig.
This commit is contained in:
parent
aa951af2b7
commit
3bd480a375
|
|
@ -389,7 +389,49 @@ static void map_signal(ivl_signal_t to, vhdl_entity *parent,
|
|||
std::string name = make_safe_name(to);
|
||||
vhdl_var_ref *to_ref;
|
||||
if ((to_ref = dynamic_cast<vhdl_var_ref*>(to_e))) {
|
||||
inst->map_port(name.c_str(), to_ref);
|
||||
// If we're mapping an output of this entity to an output of
|
||||
// the child entity, then VHDL will not let us read the value
|
||||
// of the signal (i.e. it must pass straight through).
|
||||
// However, Verilog allows the signal to be read in the parent.
|
||||
// To get around this we create an internal signal name_Sig
|
||||
// that takes the value of the output and can be read.
|
||||
vhdl_decl *decl =
|
||||
parent->get_arch()->get_scope()->get_decl(to_ref->get_name());
|
||||
vhdl_port_decl *pdecl;
|
||||
if ((pdecl = dynamic_cast<vhdl_port_decl*>(decl))
|
||||
&& pdecl->get_mode() == VHDL_PORT_OUT) {
|
||||
|
||||
// We need to create a readable signal to shadow this output
|
||||
std::string shadow_name(to_ref->get_name());
|
||||
shadow_name += "_Sig";
|
||||
|
||||
vhdl_signal_decl *shadow =
|
||||
new vhdl_signal_decl(shadow_name.c_str(),
|
||||
new vhdl_type(*decl->get_type()));
|
||||
shadow->set_comment("Needed to make output readable");
|
||||
|
||||
parent->get_arch()->get_scope()->add_decl(shadow);
|
||||
|
||||
// Make a continuous assignment of the shadow to the output
|
||||
parent->get_arch()->add_stmt
|
||||
(new vhdl_cassign_stmt
|
||||
(to_ref, new vhdl_var_ref(shadow_name.c_str(), NULL)));
|
||||
|
||||
// Make sure any future references to this signal read the
|
||||
// shadow not the output
|
||||
ivl_signal_t sig = find_signal_named(to_ref->get_name(),
|
||||
parent->get_arch()->get_scope());
|
||||
rename_signal(sig, shadow_name);
|
||||
|
||||
// Finally map the child port to the shadow signal
|
||||
inst->map_port(name.c_str(),
|
||||
new vhdl_var_ref(shadow_name.c_str(), NULL));
|
||||
}
|
||||
else {
|
||||
// Not an output port declaration therefore we can
|
||||
// definitely read it
|
||||
inst->map_port(name.c_str(), to_ref);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Not a static expression
|
||||
|
|
|
|||
|
|
@ -130,6 +130,16 @@ const std::string &get_renamed_signal(ivl_signal_t sig)
|
|||
return g_known_signals[sig].renamed;
|
||||
}
|
||||
|
||||
ivl_signal_t find_signal_named(const std::string &name, const vhdl_scope *scope)
|
||||
{
|
||||
signal_defn_map_t::const_iterator it;
|
||||
for (it = g_known_signals.begin(); it != g_known_signals.end(); ++it) {
|
||||
if ((*it).second.scope == scope && (*it).second.renamed == name)
|
||||
return (*it).first;
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
ivl_design_t get_vhdl_design()
|
||||
{
|
||||
return g_design;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ void vhdl_entity::emit(std::ostream &of, int level) const
|
|||
of << "use ieee.std_logic_1164.all;" << std::endl;
|
||||
of << "use ieee.numeric_std.all;" << std::endl;
|
||||
of << "use std.textio.all;" << std::endl;
|
||||
//of << "use work.verilog_support.all;" << std::endl;
|
||||
of << std::endl;
|
||||
|
||||
emit_comment(of, level);
|
||||
|
|
|
|||
|
|
@ -501,6 +501,7 @@ public:
|
|||
: vhdl_decl(name, type), mode_(mode) {}
|
||||
|
||||
void emit(std::ostream &of, int level) const;
|
||||
vhdl_port_mode_t get_mode() const { return mode_; }
|
||||
private:
|
||||
vhdl_port_mode_t mode_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ void remember_signal(ivl_signal_t sig, const vhdl_scope *scope);
|
|||
void rename_signal(ivl_signal_t sig, const std::string &renamed);
|
||||
const vhdl_scope *find_scope_for_signal(ivl_signal_t sig);
|
||||
const std::string &get_renamed_signal(ivl_signal_t sig);
|
||||
ivl_signal_t find_signal_named(const std::string &name, const vhdl_scope *scope);
|
||||
|
||||
void blocking_assign_to(vhdl_procedural *proc, ivl_signal_t sig);
|
||||
std::string strip_var(const std::string &str);
|
||||
|
|
|
|||
Loading…
Reference in New Issue