/* * VHDL code generation for processes. * * Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "vhdl_target.h" #include "vhdl_element.hh" #include #include #include /* * Convert a Verilog process to VHDL and add it to the architecture * of the given entity. */ static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc) { set_active_entity(ent); // Create a new process and store it in the entity's // architecture. This needs to be done first or the // parent link won't be valid (and draw_stmt needs this // to add information to the architecture) vhdl_process *vhdl_proc = new vhdl_process(); ent->get_arch()->add_stmt(vhdl_proc); // If this is an initial process, push signal initialisation // into the declarations vhdl_proc->get_scope()->set_initializing (ivl_process_type(proc) == IVL_PR_INITIAL); ivl_statement_t stmt = ivl_process_stmt(proc); int rc = draw_stmt(vhdl_proc, vhdl_proc->get_container(), stmt); if (rc != 0) return rc; // Initial processes are translated to VHDL processes with // no sensitivity list and and indefinite wait statement at // the end // However, if no statements were added to the container // by draw_stmt, don't bother adding a wait as `emit' // will optimise the process out of the output if (ivl_process_type(proc) == IVL_PR_INITIAL) { // Get rid of any useless `wait for 0 ns's at the end of the process prune_wait_for_0(vhdl_proc->get_container()); // The above pruning might have removed all logic from the process if (!vhdl_proc->get_container()->empty()) { vhdl_wait_stmt *wait = new vhdl_wait_stmt(); vhdl_proc->get_container()->add_stmt(wait); } } // Add a comment indicating where it came from ivl_scope_t scope = ivl_process_scope(proc); const char *type = ivl_process_type(proc) == IVL_PR_INITIAL ? "initial" : "always"; std::ostringstream ss; ss << "Generated from " << type << " process in " << ivl_scope_tname(scope) << " (" << ivl_process_file(proc) << ":" << ivl_process_lineno(proc) << ")"; vhdl_proc->set_comment(ss.str()); set_active_entity(NULL); return 0; } int draw_process(ivl_process_t proc, void *cd) { ivl_scope_t scope = ivl_process_scope(proc); debug_msg("Translating process in %s (%s:%d)", ivl_scope_name(scope), ivl_process_file(proc), ivl_process_lineno(proc)); // A process should occur in a module scope, therefore it // should have already been assigned a VHDL entity assert(ivl_scope_type(scope) == IVL_SCT_MODULE); vhdl_entity *ent = find_entity(ivl_scope_name(scope)); assert(ent != NULL); return generate_vhdl_process(ent, proc); }