User Tools

Site Tools


migen:migen_seven

Testbench Example

Seven Segment Display

In this part, we are going to see another interesting feature of Migen, which consist of developing advanced testbench in python. The example we are taking here is the one of a simple seven segment controller.

As its name stipulate, a seven segment display is made of 7 segments/led which are denoted ABCDEFG (we don't considerate the dot here). If we wanted to control such a display, we would need then either 7 Signals() in migen, or a single one with 7 bits. This is what we will be doing. considering that the LSB is the “A” and the MSB is the “G”.

By combining the led of the display, one can display all the hexadecimal values.

def display_seven(val):
    line0 = ["   ", " _ "]
    line1 = ["   ", "  |", " _ ", " _|", "|  ", "| |" , "|_ ", "|_|"]
    a = val&1;
    fgb = ((val >> 1) & 1) | ((val >> 5) & 2) | ((val >> 3) & 4)
    edc = ((val >> 2) & 1) | ((val >> 2) & 2) | ((val >> 2) & 4)
    print(line0[a])
    print(line1[fgb])
    print(line1[edc])
 
def test_display():
    for in in range(128):
        display_seven(i)

This code will display all the possibilities that could be displayed with a 7segment.

Now let's just filter the ones that are in the hexa set.

def test_display():
    val = [0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71]
    for v in val:
        display_seven(v)

And here is the result. Of course those 16 values were represented previously. But they are highlighted here.

The HDL code for seven segment display controller

Here we are going to use a simple case that takes “hexa” as a 4 bits signal (from 0 to 15) and “abcdefg” our 7 wires that will power on the leds of our display. The code is straight forward.

class sevenseg_ctrl(Module):
    def __init__(self):
        self.abcdefg = abcdefg = Signal(7)
        self.hexa = hexa = Signal(4)
        table = [
            0x3f, 0x06, 0x5b, 0x4f, 
            0x66, 0x6d, 0x7d, 0x07, 
            0x7f, 0x6f, 0x77, 0x7c, 
            0x39, 0x5e, 0x79, 0x71
            ]
 
        cases = {}
        for i in range(16):
            cases[i] = abcdefg.eq(table[i])
 
        self.comb += Case(hexa, cases)

What is interesting here, is to integrate in our testbench, the display that we made previously.

def sevseg_tb(dut):
    for i in range(16):
        yield dut.hexa.eq(i)
        yield
        display_seven((yield dut.abcdefg))

The file would look like this:

seven.py
from migen import *
 
class sevenseg_ctrl(Module):
    def __init__(self):
        self.abcdefg = abcdefg = Signal(7)
        self.hexa = hexa = Signal(4)
        table = [
            0x3f, 0x06, 0x5b, 0x4f, 
            0x66, 0x6d, 0x7d, 0x07, 
            0x7f, 0x6f, 0x77, 0x7c, 
            0x39, 0x5e, 0x79, 0x71
            ]
 
        cases = {}
        for i in range(16):
            cases[i] = abcdefg.eq(table[i])
 
        self.comb += Case(hexa, cases)
 
def display_seven(val):
    line0 = ["   ", " _ "]
    line1 = ["   ", "  |", " _ ", " _|", "|  ", "| |" , "|_ ", "|_|"]
    a = val&1;
    fgb = ((val >> 1) & 1) | ((val >> 5) & 2) | ((val >> 3) & 4)
    edc = ((val >> 2) & 1) | ((val >> 2) & 2) | ((val >> 2) & 4)
    print(line0[a])
    print(line1[fgb])
    print(line1[edc])
 
def sevseg_tb(dut):
    for i in range(16):
        yield dut.hexa.eq(i)
        yield
        display_seven((yield dut.abcdefg))
 
 
dut = sevenseg_ctrl()
run_simulation(dut, sevseg_tb(dut))

As we can see in sevseg_tb, we set the 16 values to dut.hexa. and run a cycle with “yield”, then get the value in “abcdefg” of our module, and send it to our display function previously written. We will see that our core works and have a display, rather than just use a waveform and deduce. That makes us save a lot of precious time.

migen/migen_seven.txt · Last modified: 2018/01/10 18:42 by po