Generate synthesisable code for sequential processes

Whilst adding `wait until ...' at the end of every
process is a valid translation of the input, it is not
actually synthesisable in at least one commercial
synthesiser (XST). According to the XST manual the
correct template is to use `wait until ...' at the
start of sequential processes and `wait on ...'
(equivalent to `wait until ...' with 'Event on all
the signals) at the end of combinatorial processes.
This patch implements that.
This commit is contained in:
Nick Gasson 2008-07-17 17:36:42 +01:00
parent 1f9ed2c5ec
commit e9637f6d11
3 changed files with 69 additions and 35 deletions

View File

@ -387,7 +387,10 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container,
/* /*
* A wait statement waits for a level change on a @(..) list of * A wait statement waits for a level change on a @(..) list of
* signals. * signals. Purely combinatorial processes (i.e. no posedge/negedge
* events) produce a `wait on' statement at the end of the process.
* Sequential processes produce a `wait until' statement at the
* start of the process.
*/ */
static int draw_wait(vhdl_procedural *_proc, stmt_container *container, static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
ivl_statement_t stmt) ivl_statement_t stmt)
@ -400,6 +403,34 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
new vhdl_binop_expr(VHDL_BINOP_OR, vhdl_type::boolean()); new vhdl_binop_expr(VHDL_BINOP_OR, vhdl_type::boolean());
int nevents = ivl_stmt_nevent(stmt); int nevents = ivl_stmt_nevent(stmt);
bool combinatorial = true; // True if no negedge/posedge events
for (int i = 0; i < nevents; i++) {
ivl_event_t event = ivl_stmt_events(stmt, i);
if (ivl_event_npos(event) > 0 || ivl_event_nneg(event) > 0)
combinatorial = false;
}
if (combinatorial) {
vhdl_wait_stmt *wait = new vhdl_wait_stmt(VHDL_WAIT_ON);
for (int i = 0; i < nevents; i++) {
ivl_event_t event = ivl_stmt_events(stmt, i);
int nany = ivl_event_nany(event);
for (int i = 0; i < nany; i++) {
ivl_nexus_t nexus = ivl_event_any(event, i);
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
wait->add_sensitivity(ref->get_name());
delete ref;
}
}
draw_stmt(proc, container, ivl_stmt_sub_stmt(stmt));
container->add_stmt(wait);
}
else {
for (int i = 0; i < nevents; i++) { for (int i = 0; i < nevents; i++) {
ivl_event_t event = ivl_stmt_events(stmt, i); ivl_event_t event = ivl_stmt_events(stmt, i);
@ -437,6 +468,7 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
container->add_stmt(new vhdl_wait_stmt(VHDL_WAIT_UNTIL, test)); container->add_stmt(new vhdl_wait_stmt(VHDL_WAIT_UNTIL, test));
draw_stmt(proc, container, ivl_stmt_sub_stmt(stmt)); draw_stmt(proc, container, ivl_stmt_sub_stmt(stmt));
}
return 0; return 0;
} }

View File

@ -307,6 +307,7 @@ void vhdl_wait_stmt::emit(std::ostream &of, int level) const
break; break;
case VHDL_WAIT_ON: case VHDL_WAIT_ON:
{ {
of << " on ";
string_list_t::const_iterator it = sensitivity_.begin(); string_list_t::const_iterator it = sensitivity_.begin();
while (it != sensitivity_.end()) { while (it != sensitivity_.end()) {
of << *it; of << *it;

View File

@ -323,6 +323,7 @@ public:
~vhdl_wait_stmt(); ~vhdl_wait_stmt();
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
void add_sensitivity(const std::string &s) { sensitivity_.push_back(s); }
private: private:
vhdl_wait_type_t type_; vhdl_wait_type_t type_;
vhdl_expr *expr_; vhdl_expr *expr_;