diff --git a/tgt-vlog95/event.c b/tgt-vlog95/event.c index f4b3d370d..0a1c0b881 100644 --- a/tgt-vlog95/event.c +++ b/tgt-vlog95/event.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com) * * 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 @@ -21,6 +21,24 @@ # include "config.h" # include "vlog95_priv.h" +static unsigned need_ivl_top_module = 0; + +void emit_icarus_generated_top_module() +{ + if (need_ivl_top_module) { + fprintf(vlog_out, +"\n" +"/*\n" +" * This module is used to trigger any always_comb or always_latch processes\n" +" * at time zero to make sure all the outputs have the correct values.\n" +"*/\n" +"module IVL_top_priv_module;\n" +" event IVL_T0_trigger_event;\n" +" initial #0 -> IVL_T0_trigger_event;\n" +"endmodule /* IVL_top_priv_module */\n"); + } +} + void emit_event(ivl_scope_t scope, ivl_statement_t stmt) { unsigned eidx, nevents, first = 1; @@ -68,4 +86,12 @@ void emit_event(ivl_scope_t scope, ivl_statement_t stmt) emit_id(ivl_event_basename(event)); } } + + /* If this is an always_comb/latch then we need to add a trigger to + * get the correct functionality. */ + if (ivl_stmt_needs_t0_trigger(stmt)) { + assert(first == 0); + fprintf(vlog_out, " or IVL_top_priv_module.IVL_T0_trigger_event"); + need_ivl_top_module = 1; + }; } diff --git a/tgt-vlog95/vlog95.c b/tgt-vlog95/vlog95.c index 1890d76b6..8fe45fb10 100644 --- a/tgt-vlog95/vlog95.c +++ b/tgt-vlog95/vlog95.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2010-2017 Cary R. (cygcary@yahoo.com) * * 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 @@ -30,7 +30,7 @@ static const char*version_string = "Icarus Verilog VLOG95 Code Generator " VERSION " (" VERSION_TAG ")\n\n" -"Copyright (C) 2010-2015 Cary R. (cygcary@yahoo.com)\n\n" +"Copyright (C) 2010-2017 Cary R. (cygcary@yahoo.com)\n\n" " This program is free software; you can redistribute it and/or modify\n" " it under the terms of the GNU General Public License as published by\n" " the Free Software Foundation; either version 2 of the License, or\n" @@ -219,9 +219,12 @@ int target_design(ivl_design_t des) /* Emit any UDP definitions that the design used. */ emit_udp_list(); - /* Emit any UDPs that are Icarus generated (D-FF). */ + /* Emit any UDPs that are Icarus generated (D-FF or latch). */ emit_icarus_generated_udps(); + /* Emit the Icarus top module used to trigger translated always_comb/latch processes at T0. */ + emit_icarus_generated_top_module(); + /* If there were errors then add this information to the output. */ if (vlog_errors) { fprintf(vlog_out, "\n"); diff --git a/tgt-vlog95/vlog95_priv.h b/tgt-vlog95/vlog95_priv.h index 913fd0424..36e3cf543 100644 --- a/tgt-vlog95/vlog95_priv.h +++ b/tgt-vlog95/vlog95_priv.h @@ -1,7 +1,7 @@ #ifndef IVL_vlog95_priv_H #define IVL_vlog95_priv_H /* - * Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2010-2017 Cary R. (cygcary@yahoo.com) * * 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 @@ -106,7 +106,6 @@ extern void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex, extern void emit_nexus_port_driver_as_ca(ivl_scope_t scope, ivl_nexus_t nex); extern void emit_const_nexus(ivl_scope_t scope, ivl_net_const_t const_net); extern void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig); -extern void emit_icarus_generated_udps(void); extern void add_udp_to_list(ivl_udp_t udp); extern void emit_udp_list(void); @@ -118,6 +117,9 @@ extern void emit_number(const char *bits, unsigned nbits, unsigned is_signed, const char *file, unsigned lineno); extern void emit_string(const char *string); +extern void emit_icarus_generated_udps(void); +extern void emit_icarus_generated_top_module(void); + /* * Find the enclosing module scope. */