2.2 Signals, ports, and concurrency

In the previous section, we simulated a design with a single generator and no concurrency. On the other hand, real hardware descriptions are typically massively concurrent. MyHDL supports this by allowing an arbitrary number of concurrently running generators.

With concurrency comes the problem of deterministic communication. Hardware languages use special objects to support deterministic communication between concurrent code. In particular, MyHDL has a Signal object which is roughly modeled after VHDL signals.

We will demonstrate signals and concurrency by extending and modifying our first example. We define two hardware modules, one that drives a clock signal, and one that is sensitive to a positive edge on a clock signal:

from myhdl import Signal, delay, always, now, Simulation


def ClkDriver(clk):

    halfPeriod = delay(10)

    @always(halfPeriod)
    def driveClk():
        clk.next = not clk

    return driveClk


def HelloWorld(clk):
    
    @always(clk.posedge)
    def sayHello():
        print "%s Hello World!" % now()

    return sayHello


clk = Signal(0)
clkdriver_inst = ClkDriver(clk)
hello_inst = HelloWorld(clk)
sim = Simulation(clkdriver_inst, hello_inst)
sim.run(50)

The clock driver function ClkDriver has a clock signal as its parameter. This is how a port is modeled in MyHDL. The function defines a generator that continuously toggles a clock signal after a certain delay. A new value of a signal is specified by assigning to its next attribute. This is the MyHDL equivalent of the VHDL signal assignment and the Verilog non-blocking assignment.

The HelloWorld function is modified from the first example. It now also takes a clock signal as parameter. Its generator is made sensitive to a rising edge of the clock signal. This is specified by the posedge attribute of a signal. The edge specifier is the argument of the always decorator. As a result, the decorated function will be executed on every rising clock edge.

The clk signal is constructed with an initial value 0. When creating an instance of each hardware module, the same clock signal is passed as the argument. The result is that the instances are now connected through the clock signal. The Simulation object is constructed with the two instances.

When we run the simulation, we get:

% python hello2.py
10 Hello World!
30 Hello World!
50 Hello World!
_SuspendSimulation: Simulated 50 timesteps

About this document