*********************** What's new in MyHDL 0.6 *********************** Conversion to VHDL ================== Rationale --------- Since the MyHDL to Verilog conversion has been developed, a path to implementation from MyHDL is available. Given the widespread support for Verilog, it could thus be argued that there was no real need for a convertor to VHDL. However, it turns out that VHDL is still very much alive and will remain so for the forseeable future. This is especially true for the FPGA market, which is especially interesting for MyHDL. It seems much more dynamic and poised for growth than the ASIC market. Moreover, because of the nature of FPGA's, FPGA designers may be more willing to try out new ideas, such as open-source solutions in general and Python and MyHDL in particular. To convince designers to use a new tool, it should integrate with their current design flow. That is why the MyHDL to VHDL convertor is needed. It should lower the threshold for VHDL designers to start using MyHDL. Advantages ---------- MyHDL to VHDL conversion offers the following advantages: * **MyHDL integration in a VHDL-based design flow** Designers can start using MyHDL and benefit from its power and flexibility, within the context of their proven design flow. * **The convertor to VHDL automates certain hard tasks** Like its Verilog counterpart, the convertor automates certain tasks that are hard in VHDL directly. For example, getting the desired behavior right when using ``unsigned`` and ``signed`` types is often not easy. In contrast, a MyHDL designer can use the high-level ``intbv`` type instead, and let the convertor deal with type conversions and resizings. * **MyHDL as an IP development platform** The possibility to convert the same MyHDL source to equivalent Verilog and VHDL creates a novel application: using MyHDL as an IP development platform. IP developers can serve customers for both target languages from a single MyHDL source base. Morever, MyHDL's flexibility and outstanding parametrizability are ideally suited to this application. Solution description -------------------- Approach ^^^^^^^^ The approach followed to convert MyHDL code to VHDL is identical to the one followed for conversion to Verilog. For a detailed description, see `the chapter about conversion to Verilog `_ in the manual. In particular, the MyHDL code analyzer in the convertor is identical for both target languages. The goal is that all MyHDL code that can be converted to Verilog conversion can be converted to VHDL also, and vice versa. This has been achieved except for a few minor issues due to limitations of the target languages. User interface ^^^^^^^^^^^^^^ Conversion to VHDL is implemented by the following function in the ``myhdl`` package: .. function:: toVHDL(func[, *args][, **kwargs]) Converts a MyHDL design instance to equivalent VHDL code. *func* is a function that returns an instance. :func:`toVHDL` calls *func* under its control and passes *\*args* and *\*\*kwargs* to the call. The return value is the same as would be returned by the call ``func(*args, **kwargs)``. It can be assigned to an instance name. The top-level instance name and the basename of the Verilog output filename is ``func.func_name`` by default. The :func:`toVHDL` callable has the following attribute: .. attribute:: toVHDL.name This attribute is used to overwrite the default top-level instance name and the basename of the VHDL output. Type handling ^^^^^^^^^^^^^ In contrast to Verilog, VHDL is a strongly typed language. The convertor has to carefully perform type inferencing, and handle type conversions and resizings appropriately. To do this right, a well-chosen mapping from MyHDL types to VHDL types is crucial. MyHDL types are mapped to VHDL types according to the following table: +--------------------------------------------------+-----------------------------------+ | MyHDL type | VHDL type | +==================================================+===================================+ | ``bool`` | ``std_logic`` | +--------------------------------------------------+-----------------------------------+ | ``intbv``, attribute ``min >= 0`` | ``signed`` | +--------------------------------------------------+-----------------------------------+ | ``intbv``, attribute ``min < 0`` | ``unsigned`` | +--------------------------------------------------+-----------------------------------+ | ``enum`` | dedicated enumeration type | +--------------------------------------------------+-----------------------------------+ | ``tuple``of ``int`` | mapped to case statement | +--------------------------------------------------+-----------------------------------+ | ``list`` of ``bool`` | ``array`` of ``std_logic`` | +--------------------------------------------------+-----------------------------------+ | ``list`` of ``intbv``, attribute ``min >= 0`` | ``array of unsigned`` | +--------------------------------------------------+-----------------------------------+ | ``list`` of ``intbv``, attribute ``min < 0`` | ``array of signed`` | +--------------------------------------------------+-----------------------------------+ Additional remarks and constraints: * The VHDL ``std_logic`` type is defined in the standard VHDL package ``IEEE.std_logic_1164`` * The VHDL ``unsigned`` and ``signed`` types used are those from the standard VHDL packages ``IEEE.numeric_std`` * The convertor only supports MyHDL signals that use ``bool``, ``intbv`` or ``enum`` objects as their underlying type. * a MyHDL signal is mapped to a VHDL signal with the appropriate type as above * a MyHDL list of signals is not always directly mapped to a VHDL type. If the list is used purely for structure, list syntax is not used within generator code. In that case, the signals are mapped to VHDL individually. * a MyHDL tuple of ints is used for ROM inference, and can only be used in a very specific way: an indexing operation into the tuple should be the rhs of an assignment. Template transformation ^^^^^^^^^^^^^^^^^^^^^^^ There is a difference between VHDL and Verilog in the way in which sensitivity to signal edges is specified. In Verilog, edge specifiers can be used directly in the sensitvity list. In VHDL, this is not possible: only signals can be used in the sensitivity list. To check for an edge, one uses the ``rising_edge()`` or ``falling_edge()`` functions in the code. MyHDL follows the Verilog scheme to specify edges in the sensitivity list. Consequently, when mapping such code to VHDL, it needs to be transformed to equivalent VHDL. This is an important issue because it affects all synthesizable templates that infer sequential logic. We will illustrate this feature with some examples. This is the MyHDL code for a D flip-flop:: @always(clk.posedge) def logic(): q.next = d It is converted to VHDL as follows:: DFF_LOGIC: process (clk) is begin if rising_edge(clk) then q <= d; end if; end process DFF_LOGIC; The convertor can handle the more general case. For example, this is MyHDL code for a D flip-flop with asynchronous set, asynchronous reset, and preference of set over reset:: @always(clk.posedge, set.negedge, rst.negedge) def logic(): if set == 0: q.next = 1 elif rst == 0: q.next = 0 else: q.next = d This is converted to VHDL as follows:: DFFSR_LOGIC: process (clk, set, rst) is begin if (set = '0') then q <= '1'; elsif (rst = '0') then q <= '0'; elsif rising_edge(clk) then q <= d; end if; end process DFFSR_LOGIC; All cases with practical utility can be handled in this way. However, there are other cases that cannot be transformed to equivalent VHDL. The convertor will detect those cases and give an error. Conversion of lists of signals ============================== Conversion of test benches ========================== Background ---------- After conversion, we obviously want to verify that the VHDL or Verilog code works correctly. In previous MyHDL versions, the proposed verification technique was co-simulation: use the same MyHDL test bench to simulate the converted Verilog code and the original MyHDL code. While co-simulation works well, there are a number of issues with it: * Co-simulation requires that the HDL simulator has an interface to its internal workings, such as ``vpi`` for Verilog and ``vhpi`` for VHDL. * vpi`` for Verilog is well-established and available for open-source simulators such as Icarus and cver). However, ``vhpi`` for VHDL is much less established; it is unclear whether there is an open source solution that is powerful enough for MyHDL's purposes. * Even though ``vpi`` is a "standard", there are differences between various simulators. Therefore, some customization is likely required per Verilog simulator. * MyHDL co-simulation uses unix-style interprocess communication that doesn't work on Windows natively. This is an exception to the rest of MyHDL that should run on any Python platform. The conclusion is that co-simulation is probably not a viable solution for the VHDL case, and it has some disadvantages for Verilog as well. The proposed alternative is to convert the test bench itself, so that both test bench and design can be run in the HDL simulator. Of course, this is not a fully general solution either, as there are important constraints on the kind of code that can be converted. However, with the additional features that have been developed, it should be a useful solution for the purpose of verifying converted code. Print statement --------------- In previous MyHDL versions, print statement conversion to Verilog was supported in a quick (and dirty) way, by merely copying the format string without checks. With the advent of VHDL conversion, this has now been done more rigourously. This was necessary because VHDL doesn't work with format strings. Rather, the format string specification has to be converted to a sequence of VHDL ``write`` and ``writeline`` calls. A print statement with multiple arguments:: print arg1, arg2, ... is supported. However, there are restrictions on the arguments. First, they should be of one of the following forms:: arg formatstring % arg formatstring % (arg1, arg2, ...) where ``arg`` is a ``bool``, ``int``, ``intbv``, ``enum``, or a ``Signal`` of these types. The ``formatstring`` contains ordinary characters and conversion specifiers as in Python. However, the only supported conversion specifiers are ``%s`` and ``%d``. Things like justification and width specification are thus not supported. Printing without a newline:: print arg1 , is not supported. This is because the solution is based on ``std.textio``. In VHDL ``std.textio``, subsequent ``write`` calls to a line are only flushed (printed) upon a ``writeline`` call. As a normal ``print`` implies a newline, the correct behavior can be guaranteed, but for a ``print`` without newline this is not possible. In the future, other techniques may be used and this restricion may be lifted. Assert statement ---------------- An assert statement in Python looks as follow:: assert test_expression It can be converted provided ``test_expression`` is convertible. Delay objects ------------- Delay objects are constructed as follows:: delay(t) with ``t`` an integer. They are used in ``yield`` statements and as the argument of ``always`` decorators, to specify delays. They can now be converted. Methodology notes ----------------- The following techniques can be used to create complex test benches that can still be converted: * A complex functional top-level test bench with a good coverage can be used to generate a simplified test bench with the same coverage, but that can always be converted. One can simply sample inputs and outputs and store them in some table format. This is similar to what is commonly done to generate some of the production test vectors for ASICs. * Coding techniques can move some of the required complexity out of the convertor. For example, arbitrary complex test vectors sequences can be set up on beforehand instead of being generated on the fly. They are then converted in the same way as a ROM table. Conversion output verification ============================== .. note:: This functionality is not needed in a typical design flow. It is only relevant to debug the MyHDL convertor functionality itself. Approach -------- To verify the VHDL output, a methodology has been developed and implemented that doesn't rely on co-simulation. The solution works for Verilog as well. The idea is basically to convert the test bench as well as the functional code. In particular, ``print`` statements in MyHDL are converted to equivalent statements in the HDL. The verification process consists of running both the MyHDL and the HDL simulation, comparing the simulation output, and reporting any differences. The goal is to make the verfication process as easy as possible. The use of ``print`` statements to debug a design is a very common and simple technique. The verification process itself is implemented in a single function with an interface that is identical to ``toVHDL`` and ``toVerilog``. As this is a native Python solution, it runs on any platform on which the HDL simulator runs. Moreover, any HDL simulator can be used as no ``vpi`` or ``vhpi`` capabilities are needed. Of course, per HDL simulator some customization is required to define the details on how it is used. This needs to be done once per HDL simulator and is fully under user control. Verification interface ---------------------- All functions related to conversion verification are implemented in the ``myhdl.conversion`` package. (To keep the ``myhdl`` namespace clean, they are not available from the ``myhdl`` namespace directly.) .. function:: verify(func[, *args][, **kwargs]) Used like ``toVHDL()``. It converts MyHDL code, simulates both the MyHDL code and the HDL code and reports any differences. The default HDL simulator is GHDL. .. function:: analyze(func[, *args][, **kwargs]) Used like ``toVHDL()``. It converts MyHDL code, and analyzes the resulting HDL. Used to verify whether the HDL output is syntactically correct. The two previous functions have the following attribute: .. attribute:: analyze.simulator Used to set the name of the HDL analyzer. GHDL is the default. .. attribute:: verify.simulator Used to set the name of the HDL simulator. GHDL simulator is the default. HDL simulator registration -------------------------- To be able to use a HDL simulator to verify conversions, it needs to be registered first. This is needed once per simulator (or rather, per set of analysis and simulation commands). Registering is done with the following function: .. function:: registerSimulator(name=None, analyze=None, elaborate=None, simulate=None) Registers a particular HDL simulator to be used by :func:`verify()` and :func:`analyze()`. *name* is the name of the simulator. *analyze* is a command string to analyze the HDL source code. *elaborate* is a command string to elaborate the HDL code. This command is optional. *simulate* is a command string to simulate the HDL code. The command strings should be string templates that refer to the ``topname`` variable that specifies the design name. The command strings can assume that a subdirectory called ``work`` is available in the current working directory. Analysis and elaboration results can be put there if desired. The :func:`analyze()` function uses the *analyze* command. The :func:`verify()` function uses the *analyze* command, then the *elaborate* command if any, and then the *simulate* command. The GHDL simulator is registered by default, but its registration can be overwritten if required. Example ^^^^^^^ As an example of registering a HDL simulator, we will show how the GHDL simulator is registered in the MyHDL distribution. The command is the following:: registerSimulator(name="GHDL", analyze="ghdl -a --workdir=work %(topname)s.vhd", elaborate="ghdl -e --workdir=work %(topname)s", simulate="ghdl -r %(topname)s") This assumes that the GHDL simulator is properly set up. Backwards incompatible changes ============================== Decorator usage --------------- Conversion of printing without a newline ---------------------------------------- Printing without a newline (a print statement followed by a comma) is no longer supported by the convertor to Verilog. This is done to be compatible with the convertor to VHDL. Currently, the VHDL solution relies on ``std.textio`` and this implies that printing without a newline cannot be reliably converted.