Last active
July 5, 2016 16:17
-
-
Save cfelton/0f258c309877e13cfcd914b7d1d8d983 to your computer and use it in GitHub Desktop.
Generic module that determines the number of bits for a value (limited to 32), uses 5 LUTs on an Artix7
This file contains 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 random import randint | |
import myhdl | |
from myhdl import Signal, intbv, always, delay, instance, StopSimulation | |
def bit_length(num): | |
"""Determine the number of bits required to represent a value | |
This functions provides the same functionality as the Python | |
int.bit_length() function but is convertible. This function | |
generates the combinatorial logic to determine the maximum | |
number of bits required to represent an unsigned value. | |
Currently the function computes a maximum of 32 bits for values | |
larger than 2**32 this function will fail. | |
myhdl convertible | |
""" | |
maxlen = 32 | |
assert num >= 0 and num < 2**maxlen | |
val = int(num) | |
nbits = 0 | |
for ii in range(maxlen): | |
if val == 0: | |
nbits = ii | |
break | |
val = val >> 1 | |
return nbits | |
def bit_length_lim(num, maxlen): | |
""" | |
This version limits the max number of bits to search. | |
Arguments: | |
num: the value to be analyzed | |
max_width: set the upper bound | |
This version is intended to be an experiment to check if | |
limiting the upper bound significantly reduces the number | |
of resources (synthesis experiment). | |
""" | |
assert num >= 0 and num < 2**maxlen | |
val = int(num) | |
nbits = 0 | |
for ii in range(maxlen): | |
if val == 0: | |
nbits = ii | |
break | |
val = val >> 1 | |
return nbits | |
@myhdl.block | |
def bit_length_block(clock, sig, numbits): | |
"""Get the number of bits needed to represent the value of `sig` | |
Arguments: | |
clock (SignalType): system clock. | |
sig (SignalType): input signal. | |
numbits (SignalType): the number of bits to represent `sig`. | |
myhdl convertible | |
""" | |
inum = Signal(sig.val) | |
oval = Signal(numbits.val) | |
@always(clock.posedge) | |
def beh(): | |
inum.next = sig | |
oval.next = bit_length(inum) | |
numbits.next = oval | |
return beh | |
def test_bit_length(): | |
clock = Signal(bool(0)) | |
sig = Signal(intbv(0)[10:]) | |
nbits = Signal(intbv(0, min=0, max=10+1)) | |
@myhdl.block | |
def bench(): | |
tbdut = bit_length_block(clock, sig, nbits) | |
@always(delay(5)) | |
def tbclk(): | |
clock.next = not clock | |
@instance | |
def tbstim(): | |
for ii in range(len(sig)): | |
x = 1 << ii | |
sig.next = x | |
# the block registers the inputs and outupts for synthesis tests | |
for ii in range(4): | |
yield clock.posedge | |
print("{:<5d} {:4d} {:4d}".format(x, int(nbits), x.bit_length())) | |
assert nbits == x.bit_length() | |
for _ in range(27): | |
x = randint(0, 2**len(sig)-1) | |
sig.next = x | |
# the block registers the inputs and outupts for synthesis tests | |
for ii in range(4): | |
yield clock.posedge | |
print("{:<5d} {:4d} {:4d}".format(x, int(nbits), x.bit_length())) | |
assert nbits == x.bit_length() | |
raise StopSimulation | |
return tbdut, tbclk, tbstim | |
inst = bench() | |
inst.config_sim(trace=True) | |
inst.run_sim() | |
inst = bit_length_block(clock, sig, nbits) | |
inst.convert(hdl='Verilog') | |
if __name__ == '__main__': | |
test_bit_length() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment