最近想做一个通用二分法,所谓通用,就是对不同的位宽的数据都能做二分法,比如输入4bit。能够按照8->12->14->13的顺序开始做二分法。输入2bit,能够按照2->3的顺序做二分法。
假设输入N,那么就会从N/2开始做二分法。
我这个二分法是作用于反馈系统的,此二分法的当前输出,是与比较结果(比较结果决定二分法的下一次分区)相关的。
使用verilog语言实现的话,我这里暂时想出了一种思路。
以下面这个二分法流程为引。
进程cnt_id=0 : 比较结果为0表示二分法向下 32->16 100000-> 010000
进程cnt_id=1 : 比较结果为1表示二分法向上 16->24 010000-> 011000
进程cnt_id=2 : 比较结果为0表示二分法向下 24->20 011000-> 010100
进程cnt_id=3 : 比较结果为0表示二分法向下 20->18 010100-> 010010
进程cnt_id=4 : 比较结果为1表示二分法向上 18->19 010010-> 010011
根据以上这个流程可以总结出几点规律:
1 每次做二分法的数据位宽只有2bit,其他bit都不变。
2 做二分法的数据位置,根据进程变化。比如进程是0时,数据只有最高位和次高位变化。数据操作依次右移。
3 做二分法的2bit数据中,高位会与比较结果相等,低位的结果都是从0变成1。
那么,我的思路是做一个数据刷子,这个刷子把原数据刷一下,就变成了二分之后的数据。
这个刷子是这么做的。
首先根据异或xor的运算规则。
根据0 ^ 0 = 0,0 ^ 1 = 1 可得0 ^ n = n
根据1 ^ 0 = 1,1 ^ 1 = 0 可得1 ^ n = !n
那么以此运算规则为基础,根据上面总结的二分法的规律,数据bit不变的地方,我让它异或0,bit变为比较结果的地方,我让他异或(比较结果的取反),从0变成1的地方,我让它异或1就可以了。
所以我构造的刷子就出来了。
[!cmp_in,1’b1]根据cnt_id右移位,其他位补0
用这个刷子,去异或原数据,比如
进程cnt_id=0 : 比较结果为0表示二分法向下 32->16 100000(->010000)
我的刷子是110000,那么110000异或100000是010000。
进程cnt_id=1 : 比较结果为1表示二分法向上 16->24 010000 (->011000)
我的刷子是001000,那么001000异或010000是011000。
依次类推。
写成代码我是这么写的
result <= result ^ ({!cmp_in,1’b1}<<(REG_WIDTH-2-cnt_id))
空位的话verilog会自动补0的。
我这个思路其实我自己感觉还有些奇怪的地方,比如这句话是不是逻辑过多的。
先记录一下,以后有问题再回来总结。