Source code for hwtLib.logic.bcdToBin
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from hwt.code import Switch, If, Concat
from hwt.code_utils import rename_signal
from hwt.hdl.types.bits import Bits
from hwt.hdl.types.enum import HEnum
from hwt.interfaces.std import Handshaked
from hwt.interfaces.utils import addClkRstn
from hwt.math import log2ceil
from hwt.synthesizer.param import Param
from hwt.synthesizer.unit import Unit
[docs]class BcdToBin(Unit):
"""
Convert a BCD number to binary encoding
This uses the double-dabble algorithm in reverse. The conversion of a BCD
number to an n-bit binary number will take n+3 cycles to complete.
based on: https://github.com/kevinpt/vhdl-extras/blob/master/rtl/extras/bcd_conversion.vhdl
.. hwt-autodoc::
"""
def _config(self):
self.BCD_DIGITS = Param(3)
def _declr(self):
addClkRstn(self)
BCD_DIGITS = self.BCD_DIGITS
bcd = self.din = Handshaked() # BCD data to convert
bcd.DATA_WIDTH = 4 * BCD_DIGITS
bin_ = self.dout = Handshaked()._m()
bin_.DATA_WIDTH = log2ceil(10 ** BCD_DIGITS - 1) # Converted output. Retained until next conversion
def _impl(self):
st_t = HEnum("state_t", ["IDLE", "LOAD_SR", "CONVERTING", "DONE"])
st = self._reg("st", st_t, def_val=st_t.IDLE)
sr_shift = st.next._eq(st_t.CONVERTING)
bcd = self.din
bin_ = self.dout
bcd_sr = self._reg("bcd_sr", bcd.data._dtype, def_val=0)
binary_sr = self._reg("binary_sr", bin_.data._dtype, def_val=0)
next_bcd = rename_signal(self, bcd_sr >> 1, "next_bcd")
MAX_COUNT = binary_sr._dtype.bit_length()
bit_count = self._reg("bit_count", Bits(log2ceil(MAX_COUNT), signed=False), def_val=MAX_COUNT)
If(sr_shift,
bit_count(bit_count - 1),
).Else(
bit_count(MAX_COUNT),
)
# dabble the digits
digits = []
for i in range(self.BCD_DIGITS):
d = next_bcd[(i + 1) * 4:i * 4]._unsigned()
d_sig = (d < 7)._ternary(d, d - 3)
digits.append(d_sig)
If(st.next._eq(st_t.LOAD_SR),
bcd_sr(bcd.data),
binary_sr(0),
).Elif(sr_shift,
# shift right
binary_sr(Concat(bcd_sr[0], binary_sr[:1])),
bcd_sr(Concat(*reversed(digits))),
)
bin_.data(binary_sr)
Switch(st)\
.Case(st_t.IDLE,
If(bcd.vld,
st(st_t.LOAD_SR), # load the shift registers
))\
.Case(st_t.LOAD_SR,
# shift right each cycle
st(st_t.CONVERTING),
)\
.Case(st_t.CONVERTING,
If(bit_count._eq(0),
# indicate completion
st(st_t.DONE),
)
)\
.Case(st_t.DONE,
If(bcd.vld & bin_.rd,
st(st_t.LOAD_SR),
).Elif(bin_.rd,
st(st_t.IDLE),
)
)
bcd.rd(st._eq(st_t.IDLE) | (st._eq(st_t.DONE) & bin_.rd))
bin_.vld(st._eq(st_t.DONE))
if __name__ == "__main__":
from hwt.synthesizer.utils import to_rtl_str
u = BcdToBin()
print(to_rtl_str(u))