diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 2c0393df3..e1e09eb1e 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -238,8 +238,6 @@ static int draw_delay(vhdl_process *proc, stmt_container *container, /* * A wait statement waits for a level change on a @(..) list of * signals. - * TODO: This won't yet handle the posedge to rising_edge, etc. - * mapping. */ static int draw_wait(vhdl_process *proc, stmt_container *container, ivl_statement_t stmt) @@ -248,10 +246,9 @@ static int draw_wait(vhdl_process *proc, stmt_container *container, for (int i = 0; i < nevents; i++) { ivl_event_t event = ivl_stmt_events(stmt, i); - if (ivl_event_nneg(event) != 0) - error("Negative edge events not supported yet"); - if (ivl_event_npos(event) != 0) - error("Positive edge events not supported yet"); + // A list of the non-edge triggered signals to they can + // be added to the edge-detecting `if' statement later + string_list_t non_edges; int nany = ivl_event_nany(event); for (int i = 0; i < nany; i++) { @@ -268,14 +265,77 @@ static int draw_wait(vhdl_process *proc, stmt_container *container, // Only add this signal to the sensitivity if it's part // of the containing architecture (i.e. it has already // been declared) - if (proc->get_parent()->have_declared(signame)) + if (proc->get_parent()->have_declared(signame)) { proc->add_sensitivity(signame); + non_edges.push_back(signame); + } } else { // Ignore all other types of nexus pointer } } - } + } + + int nneg = ivl_event_nneg(event); + int npos = ivl_event_npos(event); + if (nneg + npos > 0) { + vhdl_binop_expr *test = + new vhdl_binop_expr(VHDL_BINOP_OR, vhdl_type::boolean()); + + // Generate falling_edge(..) calls for each negedge event + for (int i = 0; i < nneg; i++) { + ivl_nexus_t nexus = ivl_event_neg(event, i); + + int nptrs = ivl_nexus_ptrs(nexus); + for (int j = 0; j < nptrs; j++) { + ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, j); + + ivl_signal_t sig; + if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) { + vhdl_fcall *detect + = new vhdl_fcall("falling_edge", vhdl_type::boolean()); + detect->add_expr + (new vhdl_var_ref(ivl_signal_basename(sig), + vhdl_type::std_logic())); + test->add_expr(detect); + } + } + } + + // Generate rising_edge(..) calls for each posedge event + for (int i = 0; i < npos; i++) { + ivl_nexus_t nexus = ivl_event_pos(event, i); + + int nptrs = ivl_nexus_ptrs(nexus); + for (int j = 0; j < nptrs; j++) { + ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, j); + + ivl_signal_t sig; + if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) { + vhdl_fcall *detect + = new vhdl_fcall("rising_edge", vhdl_type::boolean()); + detect->add_expr + (new vhdl_var_ref(ivl_signal_basename(sig), + vhdl_type::std_logic())); + test->add_expr(detect); + } + } + } + + // Add Name'Event terms for each non-edge-triggered signal + string_list_t::iterator it; + for (it = non_edges.begin(); it != non_edges.end(); ++it) { + test->add_expr + (new vhdl_var_ref((*it + "'Event").c_str(), + vhdl_type::boolean())); + } + + container->add_stmt(new vhdl_if_stmt(test)); + } + else { + // Don't bother generating an edge detector if there + // are no edge-triggered events + } } ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt); diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 294fe3268..191eb56bb 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -163,7 +163,6 @@ private: vhdl_expr_list exprs_; }; - /* * A concurrent statement appears in architecture bodies but not * processes. diff --git a/tgt-vhdl/vhdl_type.cc b/tgt-vhdl/vhdl_type.cc index 060961178..374fef0ac 100644 --- a/tgt-vhdl/vhdl_type.cc +++ b/tgt-vhdl/vhdl_type.cc @@ -38,6 +38,11 @@ vhdl_type *vhdl_type::line() return new vhdl_type(VHDL_TYPE_LINE); } +vhdl_type *vhdl_type::boolean() +{ + return new vhdl_type(VHDL_TYPE_BOOLEAN); +} + vhdl_type *vhdl_type::integer() { return new vhdl_type(VHDL_TYPE_INTEGER); diff --git a/tgt-vhdl/vhdl_type.hh b/tgt-vhdl/vhdl_type.hh index 574de501b..f597690a5 100644 --- a/tgt-vhdl/vhdl_type.hh +++ b/tgt-vhdl/vhdl_type.hh @@ -30,6 +30,7 @@ enum vhdl_type_name_t { VHDL_TYPE_LINE, VHDL_TYPE_FILE, VHDL_TYPE_INTEGER, + VHDL_TYPE_BOOLEAN, }; /* @@ -54,6 +55,7 @@ public: static vhdl_type *line(); static vhdl_type *std_logic_vector(int msb, int lsb); static vhdl_type *integer(); + static vhdl_type *boolean(); protected: vhdl_type_name_t name_; int msb_, lsb_;