diff --git a/litex/gen/fhdl/memory.py b/litex/gen/fhdl/memory.py index 19fd6793f..19602db17 100644 --- a/litex/gen/fhdl/memory.py +++ b/litex/gen/fhdl/memory.py @@ -44,9 +44,9 @@ def memory_emit_verilog(memory, ns, add_data_file): # Memory Description. # ------------------- - r += "//" + "-"*80 + "\n" + r += "//" + "-"*78 + "\n" r += f"// Memory {gn(memory)}: {memory.depth}-words x {memory.width}-bit\n" - r += "//" + "-"*80 + "\n" + r += "//" + "-"*78 + "\n" for n, port in enumerate(memory.ports): r += f"// Port {n} | " if port.async_read: @@ -110,7 +110,8 @@ def memory_emit_verilog(memory, ns, add_data_file): r += f"\tif ({gn(port.we)}{wbit})\n" lbit = i*port.we_granularity hbit = (i+1)*port.we_granularity-1 - r += f"\t\t{gn(memory)}[{gn(port.adr)}][{hbit}:{lbit}] <= {gn(port.dat_w)}[{hbit}:{lbit}];\n" + dslc = f"[{hbit}:{lbit}]" if (memory.width != port.we_granularity) else "" + r += f"\t\t{gn(memory)}[{gn(port.adr)}]{dslc} <= {gn(port.dat_w)}{dslc};\n" # Read Logic. if not port.async_read: @@ -150,6 +151,6 @@ def memory_emit_verilog(memory, ns, add_data_file): # Read-First/No-Change mode: Data already Read on Data Register. if port.mode in [READ_FIRST, NO_CHANGE]: r += f"assign {gn(port.dat_r)} = {gn(data_regs[n])};\n" - r += "//" + "-"*80 + "\n\n" + r += "\n\n" return r diff --git a/litex/gen/fhdl/verilog.py b/litex/gen/fhdl/verilog.py index 33020394c..5973ba372 100644 --- a/litex/gen/fhdl/verilog.py +++ b/litex/gen/fhdl/verilog.py @@ -13,6 +13,9 @@ # This file is Copyright (c) 2018 Robin Ole Heinemann # SPDX-License-Identifier: BSD-2-Clause +import time +import datetime + from functools import partial from operator import itemgetter import collections @@ -24,7 +27,50 @@ from migen.fhdl.namer import build_namespace from migen.fhdl.conv_output import ConvOutput from migen.fhdl.specials import Memory -from litex.build.tools import generated_banner +from litex.build.tools import get_litex_git_revision + +# ------------------------------------------------------------------------------------------------ # +# BANNER/TRAILER/SEPARATORS # +# ------------------------------------------------------------------------------------------------ # + +def _print_banner(filename, device): + return """\ +// ----------------------------------------------------------------------------- +// Auto-Generated by: __ _ __ _ __ +// / / (_) /____ | |/_/ +// / /__/ / __/ -_)> < +// /____/_/\\__/\\__/_/|_| +// Build your hardware, easily! +// https://github.com/enjoy-digital/litex +// +// Filename : {filename}.v +// Device : {device} +// LiteX sha1 : {revision} +// Date : {date} +//------------------------------------------------------------------------------\n +""".format( + device = device, + filename = filename, + revision = get_litex_git_revision(), + date = datetime.datetime.fromtimestamp(time.time()).strftime("%Y-%m-%d %H:%M:%S") +) + +def _print_trailer(): + return """ +// ----------------------------------------------------------------------------- +// Auto-Generated by LiteX on {date}. +//------------------------------------------------------------------------------ +""".format( + date=datetime.datetime.fromtimestamp(time.time()).strftime("%Y-%m-%d %H:%M:%S") +) + +def _print_separator(msg=""): + r = "\n" + r += "//" + "-"*78 + "\n" + r += f"// {msg}\n" + r += "//" + "-"*78 + "\n" + r += "\n" + return r # ------------------------------------------------------------------------------------------------ # # RESERVED KEYWORDS # @@ -333,7 +379,8 @@ def _print_module(f, ios, name, ns, attr_translate): inouts = list_special_ios(f, ins=False, outs=False, inouts=True) targets = list_targets(f) | special_outs wires = _list_comb_wires(f) | special_outs - r = "module " + name + "(\n" + + r = f"module {name} (\n" firstp = True for sig in sorted(ios, key=lambda x: x.duid): if not firstp: @@ -346,18 +393,29 @@ def _print_module(f, ios, name, ns, attr_translate): sig.name = ns.get_name(sig) if sig in inouts: sig.direction = "inout" - r += "\tinout wire " + _print_signal(ns, sig) + r += "\tinout wire " + _print_signal(ns, sig) elif sig in targets: - sig.direction = "output" + sig.direction = "output " if sig in wires: r += "\toutput wire " + _print_signal(ns, sig) else: sig.type = "reg" - r += "\toutput reg " + _print_signal(ns, sig) + r += "\toutput reg " + _print_signal(ns, sig) else: sig.direction = "input" - r += "\tinput wire " + _print_signal(ns, sig) + r += "\tinput wire " + _print_signal(ns, sig) r += "\n);\n\n" + + return r + +def _print_signals(f, ios, name, ns, attr_translate): + sigs = list_signals(f) | list_special_ios(f, ins=True, outs=True, inouts=True) + special_outs = list_special_ios(f, ins=False, outs=True, inouts=True) + inouts = list_special_ios(f, ins=False, outs=False, inouts=True) + targets = list_targets(f) | special_outs + wires = _list_comb_wires(f) | special_outs + + r = "" for sig in sorted(sigs - ios, key=lambda x: x.duid): attr = _print_attribute(sig.attr, attr_translate) if attr: @@ -365,8 +423,7 @@ def _print_module(f, ios, name, ns, attr_translate): if sig in wires: r += "wire " + _print_signal(ns, sig) + ";\n" else: - r += "reg " + _print_signal(ns, sig) + " = " + _print_expression(ns, sig.reset)[0] + ";\n" - r += "\n" + r += "reg " + _print_signal(ns, sig) + " = " + _print_expression(ns, sig.reset)[0] + ";\n" return r # ------------------------------------------------------------------------------------------------ # @@ -525,27 +582,40 @@ def convert(f, ios=set(), name="top", platform=None, # Build Verilog. # -------------- - verilog = generated_banner("//") + verilog = "" + verilog += _print_banner( + filename = name, + device = getattr(platform, "device", "Unknown") + ) - # Module Top. + # Module Definition. + verilog += _print_separator("Module") verilog += _print_module(f, ios, name, ns, attr_translate) + # Module Signals. + verilog += _print_separator("Signals") + verilog += _print_signals(f, ios, name, ns, attr_translate) + # Combinatorial Logic. + verilog += _print_separator("Combinatorial Logic") if regular_comb: verilog += _print_combinatorial_logic_synth(f, ns) else: verilog += _print_combinatorial_logic_sim(f, ns) # Synchronous Logic. + verilog += _print_separator("Synchronous Logic") verilog += _print_synchronous_logic(f, ns) # Specials + verilog += _print_separator("Specialized Logic") verilog += _print_specials(special_overrides, f.specials - lowered_specials, ns, r.add_data_file, attr_translate) # Module End. verilog += "endmodule\n" + verilog += _print_trailer() r.set_main_source(verilog) r.ns = ns