Skip to content

Instantly share code, notes, and snippets.

@cfelton
Last active July 5, 2016 16:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cfelton/0f258c309877e13cfcd914b7d1d8d983 to your computer and use it in GitHub Desktop.
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
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