Generate rising/falling edge detectors

This commit is contained in:
Nick Gasson 2008-06-12 10:36:38 +01:00
parent 19e60b698f
commit 7eb41304e6
4 changed files with 75 additions and 9 deletions

View File

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

View File

@ -163,7 +163,6 @@ private:
vhdl_expr_list exprs_;
};
/*
* A concurrent statement appears in architecture bodies but not
* processes.

View File

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

View File

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