Assignment 01
Logic Gates in MyHDL

Assignment

Starting with only Nand, 0, and 1, create MyHDL code for the following 16 functions (see also Figure 1.2 in Ch1). Submissions are due 1 week after A01 appears in the autograder.

  x 0 0 1 1  
Function y 0 1 0 1 submission filename
constant 0 0 0 0 0 0 Constant0.py
And x and y 0 0 0 1 And.py
x And Not y x and (not y) 0 0 1 0 Xandnoty.py
x x 0 0 1 1 X.py
Not x And y (not x) and y 0 1 0 0 Notxandy.py
y y 0 1 0 1 Y.py
Xor (x and (not y)) or (not (x and y)) 0 1 1 0 Xor.py
Or x or y 0 1 1 1 (none)
Nor not (x or y) 1 0 0 0 Nor.py
Equivalence x is y 1 0 0 1 Equivalence.py
Not y not y 1 0 1 0 Not.py
If y then x x or (not y) 1 0 1 1 Ifythenx.py
Not x not x 1 1 0 0 Not.py
If x then y (not x) or y 1 1 0 1 Ifxtheny.py
Nand not (x and y) 1 1 1 0 (none)
constant 1 1 1 1 1 1 Constant1.py
Note
Do not submit files for Or.py or Nand.py. These are available in the Autograder environment for your modules to import. Your files can use from Nand import Nand to use the provided implementation.
Hint1
Once you have a working implementation for And, you can use it in subsequent designs.
Hint2
When you are working on this assignment (either on your personal machine or silo), keep all these files in the same directory for simpler importing.

MyHDL boilerplate

For each primitive gate, you can start with the following "boilerplate" code and add your implementation:

from myhdl import block, always_comb, Signal  # bare minimum, possibly sufficient
from Nand import Nand  # import any gates you've already built, if you need them
from test import test  # import the test harness

# implement the gate
# replace "Name_of_gate_to_implement" with Nor, Xor, and the rest.
@block
def Name_of_gate_to_implement(a, b, z):
    # your code here
    # create instances of Nand or other blocks
    # connect them using Signal

    @always_comb
    def f():
        # your code here
        # z.next = one_of_your_signals_here

    return f

# run the test function, using the name of the gate you implemented above
if __name__ == "__main__":
    test = test_gate(Name_of_gate_to_implement)
    test.run_sim()

Provided gate: Nand

Below is the implementation of Nand. Remember that this one is allowed to use Python's and and not keywords.

# filename: Nand.py
from myhdl import block, always_comb

@block
def Nand(a, b, out):
    @always_comb
    def f():
        out.next = not (a and b)
    return f

Provided gate: Not

Below is an implementation of Not, using Nand as its building block.

# filename: Not.py
from myhdl import block, always_comb, Signal
from Nand import Nand

@block
def Not(a, z):
    out = Signal(0)
    n1 = Nand(a, 1, out)

    @always_comb
    def f():
        z.next = out

    return f, n1

Provided gate: Or

As a final example, the Or gate can be implmented using any of the gates already described (Nand and Not).

# filename: Or.py
from myhdl import block, always_comb, Signal, intbv

from Nand import Nand
from Not import Not

@block
def Or(a, b, z):
    nota = Signal(0)
    notb = Signal(0)
    out = Signal(0)

    n1 = Not(a, nota)
    n2 = Not(b, notb)
    n3 = Nand(nota, notb, out)

    @always_comb
    def f():
        z.next = out

    return f, n1, n2, n3

Test harness

You can use the following test harness for all of the 2-input gates.

from myhdl import block, instance, delay, Signal

# two-input gate test harness
@block
def test_two(func):
    a, b, z = [Signal(0) for _ in range(3)]
    fun1 = func(a, b, z)

    @instance
    def tester():
        print("a b z")
        for i in [0, 1]:
            for j in [0, 1]:
                a.next, b.next = i, j
                yield delay(1)
                print(a, b, int(z))

    return fun1, tester


# one-input gate test harness
@block
def test_one(func):
    a, z = [Signal(0) for _ in range(2)]
    fun1 = func(a, z)

    @instance
    def tester():
        print("a z")
        for i in [0, 1]:
            a.next = i
            yield delay(1)
            print(a, int(z))

    return fun1, tester

Comlete example: Or

A complete example like you would turn in for Or is shown below:

# save this file as Or.py
from myhdl import block, always_comb, Signal
from Nand import Nand  # provided by Autograder
from Not import Not    # assume we also uploaded a working Not.py
from Test import test_two

@block
def Or(a, b, z):
    nota = Signal(0)
    notb = Signal(0)
    out = Signal(0)

    n1 = Not(a, nota)
    n2 = Not(b, notb)
    n3 = Nand(nota, notb, out)

    @always_comb
    def f():
        z.next = out

    return f, n1, n2, n3


if __name__ == "__main__":
    test = test_two(Or)
    test.run_sim()

Supplemental: implementations

You can find implementations of Test.py, Nand.py, Or.py, and Not.py here:

https://github.com/ENGR110/ENGR110.github.io/tree/master/assignments/supplemental/A01