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 HBits
from hwt.hdl.types.enum import HEnum
from hwt.hwIOs.std import HwIODataRdVld
from hwt.hwIOs.utils import addClkRstn
from hwt.math import log2ceil
from hwt.hwModule import HwModule
from hwt.hwParam import HwParam
from hwt.pyUtils.typingFuture import override


[docs] class BcdToBin(HwModule): """ 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:: """ @override def hwConfig(self): self.BCD_DIGITS = HwParam(3) @override def hwDeclr(self): addClkRstn(self) BCD_DIGITS = self.BCD_DIGITS bcd = self.din = HwIODataRdVld() # BCD data to convert bcd.DATA_WIDTH = 4 * BCD_DIGITS bin_ = self.dout = HwIODataRdVld()._m() bin_.DATA_WIDTH = log2ceil(10 ** BCD_DIGITS - 1) # Converted output. Retained until next conversion @override def hwImpl(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._rtlNextSig._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", HBits(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._rtlNextSig._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.synth import to_rtl_str m = BcdToBin() print(to_rtl_str(m))