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:
Nick Gasson 2008-07-13 12:41:02 +01:00
parent aa951af2b7
commit 3bd480a375
5 changed files with 56 additions and 1 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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_;
};

View File

@ -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);