Remove some redundant code from draw_synthesisable_wait

The default draw_wait now produces code for FFs with sync
waits that should synthesise OK.
This commit is contained in:
Nick Gasson 2009-01-06 19:25:46 +00:00 committed by Stephen Williams
parent 6047eab005
commit 02b58f6ae8
1 changed files with 21 additions and 41 deletions

View File

@ -529,30 +529,12 @@ static void get_nexuses_from_expr(ivl_expr_t expr, set<ivl_nexus_t> &out)
* ... * ...
* end if; * end if;
* end process; * end process;
*
* ----
*
* always @(posedge A)
* if (...)
* ...
* else
* ...
*
* This is assumed to be a template for a FF with synchronous reset,
* if A does not appear in the `if' test expression. This should produce
* the following VHDL:
*
* process (A) is
* begin
* if rising_edge(A) then
* ...
* end if;
* end process;
*/ */
static bool draw_synthesisable_wait(vhdl_process *proc, stmt_container *container, static bool draw_synthesisable_wait(vhdl_process *proc, stmt_container *container,
ivl_statement_t stmt) ivl_statement_t stmt)
{ {
enum ff_type_t { SYNC_RESET, ASYNC_RESET }; // At the moment this only detects FFs with an asynchronous reset
// All other code will fall back on the default draw_wait
// Store a set of the edge triggered signals // Store a set of the edge triggered signals
// The second item is true if this is positive-edge // The second item is true if this is positive-edge
@ -575,15 +557,9 @@ static bool draw_synthesisable_wait(vhdl_process *proc, stmt_container *containe
edge_triggered.insert(ivl_event_neg(event, j)); edge_triggered.insert(ivl_event_neg(event, j));
} }
// If we're sensitive to a single signal edge that should be a clock // If we're edge-sensitive to less than two signals this doesn't
// (but we try to make sure), if there are two signals one might be // match the expected template, so use the default draw_wait
// an asynchronous reset if (edge_triggered.size() < 2)
ff_type_t ff_type;
if (edge_triggered.size() == 2)
ff_type = ASYNC_RESET;
else if (edge_triggered.size() == 1)
ff_type = SYNC_RESET;
else
return false; return false;
// Now check to see if the immediately embedded statement is an `if' // Now check to see if the immediately embedded statement is an `if'
@ -591,6 +567,11 @@ static bool draw_synthesisable_wait(vhdl_process *proc, stmt_container *containe
if (ivl_statement_type(sub_stmt) != IVL_ST_CONDIT) if (ivl_statement_type(sub_stmt) != IVL_ST_CONDIT)
return false; return false;
// The if should have two branches: one is the reset branch and
// one is the clocked branch
if (ivl_stmt_cond_false(sub_stmt) == NULL)
return false;
// Check the first branch of the if statement // Check the first branch of the if statement
// If it matches exactly one of the edge-triggered signals then assume // If it matches exactly one of the edge-triggered signals then assume
// this is the (dominant) reset branch // this is the (dominant) reset branch
@ -638,21 +619,20 @@ static bool draw_synthesisable_wait(vhdl_process *proc, stmt_container *containe
// Draw the clocked branch // Draw the clocked branch
// For an asynchronous reset we just want this around the else branch, // For an asynchronous reset we just want this around the else branch,
// for a synchronous reset we want this to contain both branches stmt_container *else_container = body->add_elsif(edge);
stmt_container *else_container = NULL;
if (ff_type == SYNC_RESET) {
vhdl_if_stmt *clocked = new vhdl_if_stmt(edge);
clocked->get_then_container()->add_stmt(body);
container->add_stmt(clocked);
else_container = body->get_else_container();
}
else {
else_container = body->add_elsif(edge);
container->add_stmt(body);
}
draw_stmt(proc, else_container, ivl_stmt_cond_false(sub_stmt)); draw_stmt(proc, else_container, ivl_stmt_cond_false(sub_stmt));
if (proc->contains_wait_stmt()) {
// Expanding the body produced a `wait' statement which can't
// be included in a sensitised process so undo all this work
// and fall back on the default draw_wait
delete body;
return false;
}
else
container->add_stmt(body);
// Add all the edge triggered signals to the sensitivity list // Add all the edge triggered signals to the sensitivity list
for (set<ivl_nexus_t>::const_iterator it = edge_triggered.begin(); for (set<ivl_nexus_t>::const_iterator it = edge_triggered.begin();
it != edge_triggered.end(); ++it) { it != edge_triggered.end(); ++it) {