Last active
May 11, 2017 06:38
-
-
Save cfelton/4de2b1e93dd7418f56e4 to your computer and use it in GitHub Desktop.
Code snips for http://www.fpgarelated.com/showarticle/25.php, see the link for description
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from myhdl import Signal, intbv, always_seq | |
def shift_reg(clock, reset, y): | |
shift = Signal(intbv(0)[len(y):]) | |
mask = shift.max - 1 | |
@always_seq(clock.posedge, reset=reset) | |
def beh_shift(): | |
if y == 0: | |
y.next = 1 | |
else: | |
y.next = (y << 1) & mask | |
return beh_shift |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def verify(clock, led, clock_frequency, led_rate, numled, numdumb): | |
cnt, numclk = 0, int(clock_frequency*led_rate) | |
nloops, direction = 30000, 'wait' | |
ledlsb, ledmsb = 1, 1 << len(led) | |
led_last = led.val | |
for ii in range(nloops): | |
yield clock.posedge | |
cnt += 1 | |
if direction == 'wait': | |
if (led & ledmsb) == ledmsb: | |
direction = 'right' | |
led_last = led.val | |
elif (led & ledlsb) == ledlsb: | |
direction = 'left' | |
led_last = led.val | |
elif led == 0: | |
direction = 'wait' | |
if led != led_last: | |
if direction == 'right': | |
assert led_last>>1 == led.val, \ | |
"{:x} != {:x}".format(led, led_last) | |
elif direction == 'left': | |
assert led_last<<1 == led.val, \ | |
"{:x} != {:x}".format(led, led_last) | |
assert cnt == numclk | |
cnt = 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from myhdl import always_seq | |
def led_stroby( | |
# ~~~[Ports]~~~ | |
clock, # input: system sync clock | |
led, # output: to IO ports drive LEDs | |
reset=None, # input: reset, many boards don't have reset | |
# ~~~[Parameters]~~~ | |
clock_frequency=48e6, # clock frequency | |
led_rate=333e-3, # strobe change rate of 333ms | |
num_dumb=4, # The number of dummy LEDS on each side | |
): | |
# empty module, it is good practice to create the test first | |
# and use the empty module to verify the test fails, this | |
# stub contains the myhdl generator but doesn't implement | |
# any of the logic. | |
@always_seq(clock.posedge, reset=reset) | |
def beh_stroby(): | |
led.next = 0 | |
return beh_stroby |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from myhdl import Signal, intbv, always_seq, always_comb | |
def led_stroby( | |
# ~~~[Ports]~~~ | |
clock, # input : system sync clock | |
led, # output : to IO ports drive LEDs | |
reset=None, # input : reset | |
# ~~~[Parameters]~~~ | |
clock_frequency=48e6, # clock frequency | |
led_rate=333e-3, # strobe change rate of 333ms | |
num_dumb=4, # The number of dummy LEDS on each side | |
): | |
# Number of LEDs | |
led_bank = len(led) | |
# Need to calculate some constants. Want the value to | |
# be an integer (non-fractional value only whole number) | |
cnt_max = int(clock_frequency * led_rate) | |
# Some useful definitions | |
mb = led_bank + 2*num_dumb | |
lsb, msb = 0, mb-1 | |
msb_reverse_val = (1 << mb-2) | |
lsb_reverse_val = 2 | |
# Declare the internal Signals in our design | |
led_bit_mem = Signal(intbv(1)[mb:]) | |
left_not_right = Signal(True) | |
clk_cnt = Signal(intbv(0, min=0, max=cnt_max)) | |
strobe = Signal(False) | |
@always_seq(clock.posedge, reset=reset) | |
def beh_strobe(): | |
# Generate the strobe event, use the "greater | |
# than" for initial condition cases. Count the | |
# number of clock ticks that equals the LED strobe rate | |
if clk_cnt >= cnt_max-1: | |
clk_cnt.next = 0 | |
strobe.next = True | |
else: | |
clk_cnt.next = clk_cnt + 1 | |
strobe.next = False | |
# Describe the strobing, note the following always | |
# changes direction and "resets" when either the lsb | |
# or msb is set. This handles our initial condition | |
# as well. | |
if strobe: | |
if led_bit_mem[msb]: | |
led_bit_mem.next = msb_reverse_val | |
left_not_right.next = False | |
elif led_bit_mem[lsb]: | |
led_bit_mem.next = lsb_reverse_val | |
left_not_right.next = True | |
else: | |
if left_not_right: | |
led_bit_mem.next = led_bit_mem << 1 | |
else: | |
led_bit_mem.next = led_bit_mem >> 1 | |
@always_comb | |
def beh_map_output(): | |
led.next = led_bit_mem[led_bank+num_dumb:num_dumb] | |
return beh_strobe, beh_map_output |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
import argparse | |
import myhdl | |
from myhdl import * | |
try: | |
from rhea.build import get_board | |
build_package_available = True | |
except: | |
build_package_available = False | |
from fpga25_snip4 import led_stroby | |
from test_stroby import verify, test_random | |
def convert(args): | |
myhdl.toVerilog(led_stroby, clock, leds, reset, | |
clock_frequency, led_rate, num_dumb) | |
myhdl.toVHDL(led_stroby, clock, leds, reset, | |
clock_frequency, led_rate, num_dumb) | |
def build(args): | |
if build_package_available: | |
brd = get_board(args.board) | |
flow = brd.get_flow(top=led_stroby) | |
flow.run() | |
def cliargs(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument('-N', type=int, default=1, | |
help="number of loops to test") | |
parser.add_argument('--trace', action='store_true', default=False, | |
help="enable tracing in the testbench") | |
parser.add_argument('--convert', action='store_true', default=False, | |
help="convert the design under test") | |
parser.add_argument('--build', action='store_true', default=False, | |
help="attempt to invoke FPGA tools") | |
parser.add_argument('--board', | |
choices=('sx1', 'ufo400', 'de0nano', 'zybo', | |
'atlys', 'xula', 'xula2', 'cat'), | |
help="FPGA development board selection") | |
args = parser.parse_args() | |
return args | |
def main(): | |
args = cliargs() | |
# tests are always run before conversion / build | |
for ii in range(args.N): | |
test_random() | |
if args.convert: | |
convert(args) | |
if args.build: | |
build(args) | |
if __name__ == '__main__': | |
main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import print_function | |
import myhdl | |
from myhdl import (Signal, ResetSignal, intbv, always, instance, | |
delay, StopSimulation) | |
from fpga25_snip1 import shift_reg | |
def test(): | |
clock = Signal(bool(0)) | |
reset = ResetSignal(0, active=1, async=False) | |
y = Signal(intbv(1)[4:]) | |
def bench(): | |
tbdut = myhdl.traceSignals(shift_reg, clock, reset, y) | |
@always(delay(1)) | |
def tbclk(): | |
clock.next = not clock | |
@instance | |
def tbstim(): | |
reset.next = True | |
yield delay(2) | |
reset.next = False | |
for ii in range(4): | |
yield clock.negedge | |
print("{:3d} {}".format(myhdl.now(), myhdl.bin(y, 4))) | |
raise StopSimulation | |
return tbdut, tbclk, tbstim | |
myhdl.Simulation(bench()).run() | |
if __name__ == '__main__': | |
test() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import print_function, division | |
import random | |
import myhdl | |
from myhdl import (Signal, ResetSignal, intbv, always, | |
instance, delay, StopSimulation) | |
# replace the following with from stroby import led_stroby | |
from fpga25_snip4 import led_stroby | |
def verify(clock, led, clock_frequency, led_rate): | |
cnt, numclk = 0, int(clock_frequency*led_rate) | |
nloops, direction = 30000, 'wait' | |
ledlsb, ledmsb = 1, 1 << len(led) | |
led_last = led.val | |
for ii in range(nloops): | |
yield clock.posedge | |
cnt += 1 | |
if direction == 'wait': | |
if (led & ledmsb) == ledmsb: | |
direction = 'right' | |
led_last = led.val | |
elif (led & ledlsb) == ledlsb: | |
direction = 'left' | |
led_last = led.val | |
elif led == 0: | |
direction = 'wait' | |
if led != led_last: | |
if direction == 'right': | |
assert led_last >> 1 == led.val, \ | |
"{:x} != {:x}".format(led, led_last) | |
elif direction == 'left': | |
assert led_last << 1 == led.val, \ | |
"{:x} != {:x}".format(led, led_last) | |
assert cnt == numclk | |
cnt = 0 | |
def test_random(): | |
clock_frequency = random.randint(20, 5000) | |
led_rate = random.randrange(2, 10)/10 | |
num_led = random.randint(2, 64) | |
num_dumb = random.randint(1, 16) | |
clock = Signal(False) | |
reset = ResetSignal(0, active=0, async=True) | |
leds = Signal(intbv(0)[num_led:]) | |
print("Testing: clock frequency {}, # leds {}, # dumb (pad) {}".format( | |
clock_frequency, num_led, num_dumb)) | |
def bench(): | |
tbdut = led_stroby(clock, leds, reset, clock_frequency, | |
led_rate, num_dumb) | |
# note the following delay is generic, it is simply the number | |
# of simulation ticks. In this simulation the sim ticks are | |
# not defined to an absolute physical time unit. | |
@always(delay(5)) | |
def tbclk(): | |
clock.next = not clock | |
@instance | |
def tbstim(): | |
reset.next = reset.active | |
yield delay(100) | |
reset.next = not reset.active | |
yield verify(clock, leds, clock_frequency, led_rate) | |
print("Test passed") | |
raise StopSimulation | |
return tbdut, tbclk, tbstim | |
# run the simulaiton and create a waveform dumpy file | |
myhdl.Simulation(myhdl.traceSignals(bench)).run() | |
myhdl.toVerilog(led_stroby, clock, leds, reset, | |
clock_frequency, led_rate, num_dumb) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment