MEP107
AuthorChristopher Felton
StatusDraft
Created19-Jan-2012
MyHDL-version0.9

Introduction

An interface is an object passed as a port to a MyHDL module and has one or more Signal objects as attributes.

The following is a proposal to add conversion support for attributes that are a Signal type. In this MEP a collection of attributes that are a type Signal will be referred to as an interface. Attributes are anything to the right of the "dot" in an expression.

This proposal is to add unique name creation for attributes in the converted code (when the attribute is a convertible type). It is important to state that using attributes is fully support in MyHDL 0.7 for modeling and simulation except when used in the sensitivity list as discussed in the mailing-list.

For more information on Python classes and attributes see the following 1

The rest of this enhancement proposal will outline the addition of attributes to the MyHDL convertible subset of the Python programming language. Through the rest of this document the term "interface(s)" will be used to refer to attributes of a convertible type.

Name Expansion

The desired approach is to generate a unique name for a Signal that is part of an interface. If an expression includes an interface a unique net name will be generated for the Signal, example:

myobj.x.next = yourobj.y + silly.samsobj.z

The conversion utilities would determine if the type referenced is a Signal and then create a unique name for the Signal. The following is an example of the name expansion:

myobj_x = yourobj_y + silly_samsobj_z

The converter will simply use the interface's reference name as part of the net name. The same rules that apply to the hierarchy naming will be included. The above might be convert to something like the following to avoid name collision:

mod1i_mod2i_myobj_x = mod1i_mod2i_yourobj_y + mod1i_mod2i_silly_samsobj_z

In other cases a data structure might not contain a Signal but a constant (literal). In this case the conversion method will dig down to find the constant and use the constant value.

Required support:

  • Expansion of Signal interface names
  • Interfaces as ports, including top-level ports
  • Interfaces as sensitivity lists
  • Resolution of data in data structures

In general, interfaces can be used, as long as the final referenced object is a convertible type (Signal, int, long, bool, intbv). All of the above is supported for MyHDL modeling in MyHDL 0.7, except for the "interfaces as sensitivity lists" as discussed on the mailing-list.

This feature is similar to the VHDL record and SystemVerilog interfaces. The idea is that signals can be logically grouped. Logically grouping signals is extremely useful in large complex designs.

Conversion Guidelines

  1. The attribute referenced is a convertible type

    1. Left hand side : Signal of type intbv or bool

    2. Right hand side : int, long, bool, intbv or a Signal of type int, long, bool, intbv

  2. The object being referenced will be represented in the converted code as a long-net-name. Long-net-names are derived by object.attribute path

  3. Class path name extension, the name will simply replace the "." in the Python source with an "_" in the target conversion HDL

  4. Hierarchy name rules. The same rules that avoid name conflict for local Signals will be used in name extension

Examples

Example 1

from myhdl import *

class MyObj(object):
   def __init__(self):
      self.x = Signal(intbv(0)[8:])
      self.y = Signal(intbv(0)[4:])
      self.z = Signal(intbv(0)[9:])

def m_ex1(clk, xyz):

   @always(clk.posedge)
   def hdl():
      xyz.z.next = xyz.x + xyz.y

   return hdl

clk = Signal(False)
xyz = MyObj()
toVerilog(m_ex1, clk, xyz)
toVHDL(m_ex1, clk, xyz)

Verilog conversion for example 1

// File: m_ex1.v
// Generated by MyHDL 0.9dev
// Date: Mon Jan 20 20:12:41 2014

`timescale 1ns/10ps

module m_ex1 (
    clk,
    xyz_y,
    xyz_x,
    xyz_z
);


input clk;
input [3:0] xyz_y;
input [7:0] xyz_x;
output [8:0] xyz_z;
reg [8:0] xyz_z;

always @(posedge clk) begin: M_EX1_HDL
    xyz_z <= (xyz_x + xyz_y);
end

endmodule

VHDL conversion for the example 1

-- File: m_ex1.vhd
-- Generated by MyHDL 0.9dev
-- Date: Mon Jan 20 20:12:41 2014


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_09.all;

entity m_ex1 is
    port (
        clk: in std_logic;
        xyz_y: in unsigned(3 downto 0);
        xyz_x: in unsigned(7 downto 0);
        xyz_z: out unsigned(8 downto 0)
    );
end entity m_ex1;


architecture MyHDL of m_ex1 is

begin

M_EX1_HDL: process (clk) is
begin
    if rising_edge(clk) then
        xyz_z <= (resize(xyz_x, 9) + xyz_y);
    end if;
end process M_EX1_HDL;

end architecture MyHDL;

Example 2

Embedded memory-mapped buses are common in designs. The following is a simple memory-mapped bus definition and an example of a conversion using the bus. The conversion code is only a snippet of the full converted code, relevant code with the name extension.

class BareBoneBus:
    def __init__(self):
        self.wr = Signal(False)
        self.rd = Signal(False)
        self.ack = Signal(False)
        self.rdat = Signal(intbv(0)[8:])
        self.wdat = Signal(intbv(0)[8:])
        self.addr = Signal(intbv(0)[16:])

Verilog conversion for example 2

always @(posedge clock) begin: M_SIMPLE_GL_RTL
    if (reset == 1) begin
        gl_bb_rdat <= 0;
        leds <= 0;
        gl_lled <= 0;
        gl_bb_ack <= 0;
    end
    else begin
        if ((gl_bb_rd && (gl_bb_addr == 0))) begin
            gl_bb_rdat <= gl_lled;
            gl_bb_ack <= 1'b1;
        end
        else if ((gl_bb_wr && (gl_bb_addr == 0))) begin
            gl_lled <= gl_bb_wdat;
            gl_bb_ack <= 1'b1;
        end
        else begin
            gl_bb_ack <= 1'b0;
        end
        leds <= gl_lled;
    end
end

VHDL conversion for the example 2

M_SIMPLE_GL_RTL: process (clock) is
begin
    if rising_edge(clock) then
        if (reset = '1') then
            gl_bb_rdat <= to_unsigned(0, 8);
            leds <= to_unsigned(0, 8);
            gl_lled <= to_unsigned(0, 8);
            gl_bb_ack <= '0';
        else
            if (bool(gl_bb_rd) and (gl_bb_addr = 0)) then
                gl_bb_rdat <= gl_lled;
                gl_bb_ack <= '1';
            elsif (bool(gl_bb_wr) and (gl_bb_addr = 0)) then
                gl_lled <= gl_bb_wdat;
                gl_bb_ack <= '1';
            else
                gl_bb_ack <= '0';
            end if;
            leds <= gl_lled;
        end if;
    end if;
end process M_SIMPLE_GL_RTL;

Conclusion

Interfaces provide a powerful method to encapsulate signals and to group signals that are associated. The straight-forward net-name extraction creates a unique net in the lower-level HDLs that can be mapped back to the Signal in a data structure.

Acknowledgments

Keerthan Jaic implemented this MEP (interface conversion) in 0.9, this was no small task! Jan Decaluwe provided feedback that provided clarity and focus.