Example #1
0
def make_example_graph():
    in1, in2 = pyrtl.Input(8, 'in1'), pyrtl.Input(8, 'in2')
    out = pyrtl.Output(9, 'output')
    out <<= adders.kogge_stone(in1, in2)

    pyrtl.synthesize()
    pyrtl.optimize()
Example #2
0
# tracking down bugs.  However, PyRTL introduces some new complexities because
# the place where  functionality is defined (when you construct and operate
# on PyRTL classes) is separate in time from where that functionality is executed
# (i.e. during simulation).  Thus, sometimes it hard to track down where a wire
# might have come from, or what exactly it is doing.

# In this example specifically, we will be building a circuit that adds up three values.
# However, instead of building an add function ourselves or using the
# built-in "+" function in PyRTL, we will instead use the Kogge-Stone adders
# in RtlLib, the standard library for PyRTL.

# building three inputs
in1, in2, in3 = (pyrtl.Input(8, "in" + str(x)) for x in range(1, 4))
out = pyrtl.Output(10, "out")

add1_out = adders.kogge_stone(in1, in2)
add2_out = adders.kogge_stone(add1_out, in2)
out <<= add2_out

# The most basic way of debugging PyRTL is to connect a value to an output wire
# and use the simulation to trace the output. A simple "print" statement doesn't work
# because the values in the wires are not populated during *creation* time

# If we want to check the result of the first addition, we can connect an output wire
# to the result wire of the first adder

debug_out = pyrtl.Output(9, "debug_out")
debug_out <<= add1_out

# now simulate the circuit.  Let's create some random inputs to feed our adder.
Example #3
0
def prng_xoroshiro128(bitwidth, load, req, seed=None):
    """ Builds a PRNG using the Xoroshiro128+ algorithm in hardware.

    :param bitwidth: the desired bitwidth of the random number
    :param load: one bit signal to load the seed into the prng
    :param req: one bit signal to request a random number
    :param seed: 128 bits WireVector, defaults to None (self-seeding),
      refrain from self-seeding if reseeding at run time is required
    :return ready, rand: ready is a one bit signal showing the random number has been
      produced, rand is a register containing the random number with the given bitwidth

    An efficient noncryptographic PRNG, has much smaller area than Trivium.
    But it does require a 64-bit adder to compute the output, so it is a bit slower.
    Has a period of 2**128 - 1. Passes most statistical tests. Outputs a 64-bit random
    word each cycle, takes multiple cycles if more than 64 bits are requested, and MSBs
    of the random words are returned if the bitwidth is not a multiple of 64.

    See also http://xoroshiro.di.unimi.it/
    """
    from math import ceil, log
    from pyrtl.rtllib import adders
    from pyrtl.rtllib.libutils import _shifted_reg_next as shift  # for readability
    if seed is None:
        import random
        cryptogen = random.SystemRandom()
        seed = cryptogen.randrange(
            1, 2**128)  # seed itself if no seed signal is given
    seed = pyrtl.as_wires(seed, 128)

    s0, s1 = (pyrtl.Register(64) for i in range(2))
    output = pyrtl.WireVector(64)
    # update internal states by xoring, rotating, and shifting
    _s1 = s0 ^ s1
    s0_next = (shift(s0, 'l', 55) | shift(s0, 'r', 9)) ^ shift(_s1, 'l',
                                                               14) ^ _s1
    s1_next = shift(_s1, 'l', 36) | shift(_s1, 'r', 28)
    output <<= adders.kogge_stone(s0, s1)

    gen_cycles = int(ceil(bitwidth / 64))
    counter_bitwidth = int(ceil(log(gen_cycles, 2))) if gen_cycles > 1 else 1
    rand = pyrtl.Register(gen_cycles * 64)
    counter = pyrtl.Register(counter_bitwidth, 'counter')
    gen_done = counter == gen_cycles - 1
    state = pyrtl.Register(1)
    WAIT, GEN = (pyrtl.Const(x) for x in range(2))
    with pyrtl.conditional_assignment:
        with load:
            s0.next |= seed[:64]
            s1.next |= seed[64:]
            state.next |= WAIT
        with req:
            counter.next |= 0
            s0.next |= s0_next
            s1.next |= s1_next
            rand.next |= pyrtl.concat(rand, output)
            state.next |= GEN
        with state == GEN:
            with ~gen_done:
                counter.next |= counter + 1
                s0.next |= s0_next
                s1.next |= s1_next
                rand.next |= pyrtl.concat(rand, output)

    ready = ~load & ~req & (state == GEN) & gen_done
    return ready, rand[-bitwidth:]  # return MSBs because LSBs are less random
# tracking down bugs.  However, PyRTL introduces some new complexities because
# the place where  functionality is defdined (when you construct and operate
# on PyRTL classes) is seperate in time from where that functionalty is executed
# (i.e. during siumation).  Thus, sometimes it hard to track down where a wire
# might have come from, or what exactly it is doing.

# In this example specifically, we will be building a circuit that adds up three values.
# However, instead of building an add function ourselves or using the
# built-in "+" function in PyRTL, we will instead use the Kogge-Stone adders
# in RtlLib, the standard library for PyRTL.

# building three inputs
in1, in2, in3 = (pyrtl.Input(8, "in" + str(x)) for x in range(1, 4))
out = pyrtl.Output(10, "out")

add1_out = adders.kogge_stone(in1, in2)
add2_out = adders.kogge_stone(add1_out, in2)
out <<= add2_out

# The most basic way of debugging PyRTL is to connect a value to an output wire
# and use the simulation to trace the output. A simple "print" statement doesn't work
# because the values in the wires are not populated during *creation* time

# If we want to check the result of the first addition, we can connect an output wire
# to the result wire of the first adder

debug_out = pyrtl.Output(9, "debug_out")
debug_out <<= add1_out

# now simulate the circuit.  Let's create some random inputs to feed our adder.