verilog_backend: in non-SV mode, add a trigger for `always @*`.
authorwhitequark <whitequark@whitequark.org>
Thu, 16 Jul 2020 11:26:31 +0000 (11:26 +0000)
committerwhitequark <whitequark@whitequark.org>
Thu, 16 Jul 2020 11:30:14 +0000 (11:30 +0000)
This commit only affects translation of RTLIL processes (for which
there is limited support).

Due to the event-driven nature of Verilog, processes like

    reg x;
    always @*
        x <= 1;

may never execute. This can be fixed in SystemVerilog code by using
`always_comb` instead of `always @*`, but in Verilog-2001 the options
are limited. This commit implements the following workaround:

    reg init = 0;
    reg x;
    always @* begin
        if (init) begin end
        x <= 1;
    end

Fixes #2271.

backends/verilog/verilog_backend.cc

index e174a6ea4988bd4f760088d041cda67338c1d49d..71f71554b078f0269ed44f8837aff05e92345f7e 100644 (file)
@@ -1718,6 +1718,8 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
        }
 
        f << stringf("%s" "always%s begin\n", indent.c_str(), systemverilog ? "_comb" : " @*");
+       if (!systemverilog)
+               f << indent + "  " << "if (" << id("\\initial") << ") begin end\n";
        dump_case_body(f, indent, &proc->root_case, true);
 
        std::string backup_indent = indent;
@@ -1850,6 +1852,9 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
        }
        f << stringf(");\n");
 
+       if (!systemverilog && !module->processes.empty())
+               f << indent + "  " << "reg " << id("\\initial") << " = 0;\n";
+
        for (auto w : module->wires())
                dump_wire(f, indent + "  ", w);