设计思路
所有的数字均以二进制的形式进行存储。在计算机中均是二进制,对于对数的求取具有天然的优势。对于任意一个数字,均可以表示成一系列2的n次幂的和。以6为例:
在进行以2为底的求对数运算中,当其拆解为2的n次幂的和那么最高次幂的次数决定了结果的整数部分。像上面的6最高次幂为2,故其结果整数部分即为2。而这正和数字以二进制存储时的结构相对应:
读到这里, 想必你心中已经有了一个大概的思路了!
对于向向下取整,只需找出数据的为1的最高bit的位置即可。
对于向上取整,在找到数据的为1的bit位置之外,还需考虑是否有其他bit存在为1的情况。若存在,则需再加1,否则,即输出。
无论是求对数向上取整还是向下取整,整个逻辑设计关键为找到数据中为1的最高bit的位置。而再进一步拆分,可以分为两步:
将数据转换为独热码,独热码中1出现的位置即为原数据中为1的最高bit的位置。
将读热码中1出现的位置转换成普通的二进制表示形式。
二进制转独热码
对于上面的第一步,想要实现独热码中1出现的位置即为原数据中为1的最高bit的位置,不知小伙伴是否有合适的Idea?千万可别是一堆if else 或者casez……
如果暂且没有思路,不妨换个想法。如何找到一个数据中最低位为 1的位置并转换成独热码。只需要做一次减法和按位与:
oneHotCode=symbol& ~(symbol-1)
原理并不复杂。对于任何一个数据:
其减一之后将会变成:
取反:
做按位与后即可得到对应的独热码:
有了找到一个数据中最低位为 1的位置并转换成独热码的方式,那么实现独热码中1出现的位置即为原数据中为1的最高bit的位置也就不难了。
独热码的二进制表示
而针对独热码转换成为二进制,一开始或许也要思索一番。其实也不难,只要发现了其中的规律,实现起来也就没有那么难了。以8位数为例,其转换为二进制则需要3个比特(0~7)。先看下其规律:
其中可以认为:
其中假定OneHot的编码序号为index,则有
以此类推,可得到OneHot转UInt的方式为:
最终实现
有了上面的总结,想必你就知道怎么实现了。其实上面的两个小的方法在SpinalHDL lib中均有提供。这里给出完整的实现(不考虑输入为0):
SpinalHDL这种丰富的组件对于日常的开发工作来讲无疑是十分好用的,深入之后你会发现,自己曾经是多么无聊的一遍遍造轮子~
原作者:玉骐
|