首页 > 手撕代码:“排序、比较”专题1
头像
数字IC剑指offer
编辑于 2021-04-21 17:37
+ 关注

手撕代码:“排序、比较”专题1

注:以下题目均为各大公司面试真题,要求为用verilog语言实现。

1、 给出4个数据,从中选择出最小的数据,同时将该最小数据的地址输出。

  • 思路:分组两两比较,得到的结果再次两两比较,直到比出最终的最小值和地址,推荐的写法是写编写两两比较得出较小数数据和地址的task或function,然后编写组合逻辑调用或者用于DFF触发器D端输入。

2、对输入的16个数据进行排序,找出最大值和次大值(很经典的题目,同理在8个、16个、32个数中找最大、次大值)。

  • 思路:这里都认为16个数一次性全部输入,如果是按照clk一次进一个,可以进来一个数比较一次。

  1. 最直接的算法就是遍历,将这16个数存入数组,采用循环语句,将当前最大值、次大值和新数据对比,从而更新最大值、次大值,16个周期之后就可以得到结果。这种方法一方面需要的时钟周期多,另一方面对硬件电路不友好。

  2. 从硬件电路的角度出发,这其实是一个16个数据比大小的电路,那么很容易想到比较器,最基本的比较器是2to1比较器。假如只要求最大值,那么将16个数两两分组通过2to1比较器找到各组的最大值,然后再次两两分组比较,以此类推,就可以找到最大值了,只求最大值的情况设计是非常简单的。但是当牵涉到次大值,问题难度瞬间就变大了,上面求最大值的方法中,每次两两比较得到两者中的较大值,较小值被丢弃,对于求次大值来说这是有问题的,因为次大值是可能出现在这些较小值当中的,因此在求次大值的电路中基本的比较单元不能是2to1比较器,而是4to2比较器(输出4个数中的最大值和次大值,当然也是由基本的2to1比较器构成的)。基本思路是,将16个数4个一组分成4组,每组通过4to2比较器找出当前组中的最大值和次大值,然后将4组的最大值和次大值再次分组找各组的最大值和次大值,以此类推可以得到最终的最大值和次大值。下面是一个8个数据中找最大值、次大值的电路,16个数据的原理一样:


    那问题来了,这里4to2比较器是关键,需要找到4个数中的最大值和次大值,也是由2to1比较器构成的,一种实现方式如下:

    这里的cmp_in_2也需要由两个比较器构成,一个输出max,一个输出min。整个模块实际上完成了对4个数的排序,当然在找最大值、次大值的应用中只需要max和max2两个输出即可。以这个模块为基础,就可以以级联的形式设计出找最大值和次大值的电路了,如果时钟周期受限,可以采用流水线的形式。

3、八个数比大小排序,只能用二输入比较器。

  • 思路:主要是先设计4个数排序的模块,每次先找出当前所有数中的最大最小值,然后找剩下数的最大最小值,以此类推,电路图如下:

4、一个模块,input有clk,rstn,10bit随机数,output为曾经出现过的次大值以及次大值出现的次数。

  • 思路:代码思路不难,需要注意的是,不仅需要记录次大值max2的计数器,还需要记录最大值max的计数器,因为当max成为max2的时候,需要把这个计数值cnt传递下来。

5、求三个数的中位数。

  • 思路:理清逻辑即可,采用always块组合逻辑写法更为简单

6、64个数用最快的速度找出最大的值。

  • 思路:64个数两两比较再比较的方式理论上是并行度最高的设计方法,考虑到64个数比较需要6级组合逻辑,路径会较长,可能会限制时钟频率,为了提高速度,可以采用流水线的设计方法,对中间结果打拍,这样可以提高频率,提高吞吐率。

全部评论

(0) 回帖
加载中...
话题 回帖

推荐话题

相关热帖

近期热帖

近期精华帖

热门推荐