$30 off During Our Annual Pro Sale. View Details »

MyHDL: Designing Digital Hardware with Python (PyConTW 2013)

MyHDL: Designing Digital Hardware with Python (PyConTW 2013)

Jan Decaluwe

May 26, 2013
Tweet

Other Decks in Programming

Transcript

  1. MyHDL: Designing Digital
    Hardware with Python
    Jan Decaluwe

    View Slide

  2. CMOS Image Sensor by CMOSIS (cmosis.com)
    Digital design by Easics (easics.com)

    View Slide

  3. Sensor Application Chip
    Designed by Easics (easics.com) and ICsense (icsense.com)

    View Slide

  4. One more thing ...
    The digital design of these two chips was
    completely done with Python!
    (using the MyHDL library)

    View Slide

  5. Mainstream digital design
    ● language based
    ● such a language is called a Hardware
    Description Language (HDL)
    ● industry standard HDLs: Verilog, VHDL
    Question: what makes an HDL special?

    View Slide

  6. What is the difference between an
    HDL and a programming language?
    Answer: 4317 lines of Python code :-)
    (That is the line count of the MyHDL library.)

    View Slide

  7. A digital hardware system model

    View Slide

  8. Digital hardware system
    characteristics
    ● massive amount of concurrent "threads"
    ● communication through "signals"
    ● actions triggered by "events" on signals
    ● deterministic "by construction"
    ● fine-grained control of data type bit widths
    Requirement: an HDL must natively support
    these characteristics

    View Slide

  9. What is an HDL?
    ● An HDL is an event-driven microthread
    programming language, with built-in
    determinism.
    ● An HDL must also implement a hardware-
    friendly type system.
    ● Warning: Many hardware designers don't
    want to hear that it's all just software
    programming!

    View Slide

  10. The design of MyHDL
    Our goal is to design a Python library that
    supports the following features
    ● Microthreads
    ● Events that trigger actions
    ● Deterministic communication
    ● Hardware friendly type system

    View Slide

  11. Determinism in an HDL
    ● separate phases for:
    value updates
    computations
    ● computation order does not matter!
    ● More info:
    www.sigasi.com/content/vhdls-crown-jewel

    View Slide

  12. The leaf object of determinism
    ● the Signal class
    ● Signals implement value buffering:
    s = Signal(0)
    s.next = 5
    ● value updates occur automatically by a
    scheduler (a.k.a. the "simulator")
    ● if all communication goes through Signals,
    the model is deterministic

    View Slide

  13. Events
    ● Events trigger computation actions
    ● Signals also define events:
    ■ value changes
    ■ 0->1 transition (a "posedge")
    ■ 1->0 transition (a "negedge")
    ● Commonly used global synchronizing event:
    the "clock edge"
    ● Other events exist, e.g. waiting for a delay

    View Slide

  14. Microthreads
    ● we need massive concurrency
    ● the threads should be super lightweight
    ● as lightweight as a function ...

    View Slide

  15. Microthread implementation
    ● Python generator functions to the rescue
    # z, a, b, sel are Signal objects (outer scope)
    def mux():
    while True: # loop forever
    yield a, b, sel # wait on a value change
    if sel: # of a, b, or sel
    z.next = a
    else:
    z.next = b

    View Slide

  16. Using decorators to create
    generators: @instance
    ● @instance decorator creates a generator
    from a generator function
    @instance # equivalent to mux = mux()
    def mux():
    while True:
    yield a, b, sel
    if sel:
    z.next = a
    else:
    z.next = b

    View Slide

  17. The @always decorator
    ● @always decorator abstracts an outer
    "while True" loop followed by a "yield"
    statement
    @always(a, b, sel)
    def mux():
    if sel:
    z.next = a
    else:
    z.next = b

    View Slide

  18. Combinatorial logic: @always_comb
    ● @always_comb decorator automatically
    infers the "sensitivity" to input value changes
    @always_comb
    def mux():
    if sel:
    z.next = a
    else:
    z.next = b

    View Slide

  19. Sequential logic: @always_seq
    ● @always_seq infers the reset functionality
    reset = ResetSignal(0, active=0, async=True)
    @always_seq(clock.posedge, reset=reset)
    def dff():
    q.next = d
    ● Equivalent code:
    @always(clock.posedge, reset.negedge)
    def dff():
    if reset == 0:
    q.next = 0 # initial value of q
    else:
    q.next = d

    View Slide

  20. Decorators are a great tool to create
    a domain-specific language
    ● @instance: most general, multiple yield
    statements.
    ● @always: single yield statement, abstracts
    "while True" loop.
    ● @always_comb: automatically infers
    combinatorial sensitivity.
    ● @always_seq: automatically infers the reset
    functionality for sequential logic. A unique
    feature of MyHDL!

    View Slide

  21. MyHDL is minimalistic
    ● only features that are strictly necessary are
    implemented
    ● use native Python features as much as
    possible, e.g.:
    ○ lists for random access memory (RAM)
    ○ tuples for read-only memory (ROM)
    ● a hardware module is modeled by a function
    that returns generators
    ● hierarchy is modeled by a submodule "call"

    View Slide

  22. Modeling hierarchy
    def module(out1,..., in2,..., clock, reset):
    sig1 = Signal(...)
    ...
    inst1 = submodule(...)
    ...
    @always_seq(clock.posedge, reset=reset)
    def gen1():
    ...
    @always_comb():
    def gen2():
    ...
    return inst1,..., gen1, gen2,...

    View Slide

  23. Hardware-friendly type system
    ● based on integer arithmetic
    ● fine-grained control of bit width for efficiency
    A Puzzle:
    ● given: a in range(0, 8) and b in range(-8, 8)
    ● calculate c = a + b
    ● For example: 7 + -2 = ?

    View Slide

  24. 7 + -2: The Verilog answer
    reg [2:0] a;
    reg signed [3:0] b;
    reg signed [4:0] c;
    ...
    c <= a + b;
    Answer:
    7 + -2 = -11

    View Slide

  25. 7 + -2: The VHDL answer
    signal a: unsigned(2 downto 0);
    signal b: signed(3 downto 0);
    signal c: signed(4 downto 0);
    ...
    c <= a + b;
    Answer:
    test.vhd:24:10: no function declarations for
    operator "+": compilation error.

    View Slide

  26. What's wrong with integer arithmetic
    in Verilog/VHDL
    ● based on low-level, non-abstract types:
    signed/unsigned
    ● mixed expressions are problematic
    ● Verilog casts everything to unsigned!
    ● VHDL's strong typing doesn't work well with
    low-level types

    View Slide

  27. Integer arithmetic in MyHDL
    ● the Python way: based on good old integers
    ● the intbv class: "integer with bit vector
    capabilities"
    ● specify range for implementation efficiency
    a = intbv(0, min=0, max=8)
    b = intbv(0, min=-8, max=8)
    ● range boundaries reused in value assertions
    ● slicing & indexing interface to access the bits
    z.next = a[2:0]

    View Slide

  28. Sidenote: Synthesis
    ● a "synthesis tool" is a compiler
    ● it compiles an HDL hardware model into a
    gate-level implementation
    ● the entry point of a fully automated back-end
    ● only a restricted HDL subset is synthesizable:
    the Register Transfer Level (RTL)
    ● available from multiple vendors in all price
    categories (free to $$$)
    ● Verilog and VHDL only!

    View Slide

  29. Conversion: connecting to standard
    design flows
    ● a subset of MyHDL can be automatically
    converted to Verilog/VHDL
    ● the convertor maintains the abstraction level
    ● however, it supports some unique MyHDL
    features and automates some tedious tasks
    ● creates readable VHDL/Verilog that
    integrates seamlessly in the design flow
    ● the convertible subset is much broader than
    the synthesizable subset

    View Slide

  30. Conversion example
    ● MyHDL code:
    a = Signal(intbv(0, min=0, max=8))
    b = Signal(intbv(0, min=-8, max=8))
    c = Signal(intbv(0, min=-8, max=15))
    c.next = a + b
    ● Conversion to Verilog:
    c <= $signed({1'b0, a}) + b;
    ● Conversion to VHDL:
    c <= signed(resize(a, 5)) + b;
    ● The convertor does the casts and resizings,
    so you don't have to!

    View Slide

  31. The MyHDL-based Design Flow
    Modeling
    Verification
    Synthesis
    Place & Route
    ASIC
    FPGA
    Conversion
    MyHDL
    Back-
    end

    View Slide

  32. MyHDL's strongest point:
    Verification
    ● Verification is by far the hardest task in
    hardware design
    ● With MyHDL, hardware verification
    engineers benefit from Python's expressive
    power and ecosystem
    ● Test-driven design (TTD) for hardware (with
    unittest, py.test...)
    ● The foundation is an event-driven simulator
    provided by MyHDL

    View Slide

  33. The MyHDL simulator
    ● input is a (hierarchical) list of generators,
    that communicate through signals
    update signal values
    check which generators
    become active
    run active generators in
    any order

    View Slide

  34. Simulation debugging
    ● classical Python debugging
    ● waveform viewer output

    View Slide

  35. pypy and MyHDL: a dream team
    ● pypy is an alternative, Python 2.7 compliant
    Python interpreter
    ● JIT technology for speed-up
    ● benchmark simulations run 8 - 20 faster
    ● within speed range of commercial
    VHDL/Verilog simulators
    ● overnight game changer for "free" :-)

    View Slide

  36. Future
    ● fixed point support in conversion
    ● attribute name lookup support in convertor
    (interfaces)
    ● Python 3.0 (gradual process)

    View Slide

  37. MyHDL resources
    ● myhdl.org has all the info on:
    ○ Manual & examples
    ○ Download & installation instructions
    ○ Newsgroup & mailing list
    ○ Users, projects & success stories
    ○ Development
    ● @MyHDL on twitter
    ● Development with mercurial on Bitbucket

    View Slide

  38. Thank you!
    Questions, anyone?

    View Slide