0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FPGA上如何求32个输入的最大值和次大值:分治

Hx 作者:工程师陈翠 2018-06-28 09:18 次阅读

题目

FPGA上实现一个模块,求32个输入中的最大值和次大值,32个输入由一个时钟周期给出。

从我个人的观点来看,这是一道很好的面试题目:

其一是这大概是某些机器学习算法实现过程中遇到的问题的简化,是很有意义的一道题目;

其二是这道题目不仅要求FPGA代码能力,还有很多可以在算法上优化的可能;

当然,输入的位宽可能会影响最终的解题思路和最终的实现可能性。但位宽在一定范围内,譬如8或者32,解题的方案应该都是一致的,只是会影响最终的频率。后文针对这一题目做具体分析。(题目没有说明重复元素如何处理,这里认为最大值和次大值可以是一样的,即计算重复元素)

解法

从算法本身来看,找最大值和次大值的过程很简单;通过两次遍历:第一次求最大值,第二次求次大值; 算法复杂度是O(2n)。FPGA显然不可能在一个周期内完成如此复杂的操作,一般需要流水设计。这一方法下,整个结构是这样的

1. 通过比较,求最大值,通过流水线实现两两之间的比较,32-16-8-4-2-1通过5个clk的延迟可以求得最大值;

2. 由于需要求取次大值,因此需要确定最大值的位置,在求最大值的过程中需要维持最大值的坐标;

3. 最大值坐标处取值清零(置为最小)

4. 通过流水线实现两两之间的比较,32-16-8-4-2-1,再经过5个clk的延迟可以求得次大值;

这种解法有若干个缺点,包括:延迟求最大值和次大值分别需要5clk延时,总延迟会超过10个cycles;资源占用较高,维持最大值坐标和清零操作耗费了较多资源,同时为了计算次大值,需要将输入寄存若干个周期,寄存器消耗较多。

另一个种思路考虑同时求最大值和次大值,由于这一逻辑较为复杂,可以将其流水化,如下图。(以8输入为例,32输入需要增加两级)

FPGA上如何求32个输入的最大值和次大值:分治

其中sort模块完成对4输入进行排序,得到最大值和次大值输出的功能。4个数的排序较为复杂,这一过程大概需要2-3个cycles完成。对于32输入而言,输入数据经过32-16-8-4-2输出得到结果,延迟大概也有10个周期。

分治

如果需要在FPGA上实现一个特定的算法,那么去找一个合适的方法去实现就好了;但如果是要实现一个特定的功能,那么需要找一个优秀的且适合FPGA实现的方法。

求最大值和次大值是一个很不完全的排序,通过简单的查找复杂度为O(2n),且不利于硬件实现。对于排序而言,无论快速排序或者归并排序都用了分治的思想,如果我们试图用分治的思想来解决这一问题。考虑当只有2个输入时,通过一个比较就可以得到输出,此时得到的是一个长度为2的有序数组。如果两个有序数组,那么通过两次比较就可以得到最大值和次大值。采用归并排序的思想,查找最大值和次大值的复杂度为O(1.5n)(即为n/2+n/2+n/4… ,不知道有没有算错)。采用归并排序的思想,从算法时间复杂度上看更为高效了。

那么这一方案是否适合FPGA实现呢,答案是肯定的。分治的局部性适合FPGA的流水实现,框图如下。(以8输入为例,32输入需要增加两级)

FPGA上如何求32个输入的最大值和次大值:分治

其中meg模块内部有两级的比较器,一般而言1clk就可以完成,输入数据经过32-32-16-8-4-2得到结果,延迟为5个时钟周期。实现代码如下

module test#(

parameter DW = 8

input clk,

input [32*DW-1 :0] din,

output [DW-1:0] max1,

output [DW-1:0] max2

);

wire[DW-1:0] d[31:0];

generate

genvar i;

for(i=0;i《32;i=i+1)

begin:loop_assign

assign d[i] = din[DW*i+DW-1:DW*i];

end

endgenerate

// stage 1,comp

reg[DW-1:0] s1_max[15:0];

reg[DW-1:0] s1_min[15:0];

generate

for(i=0;i《16;i=i+1)

begin:loop_comp

always@(posedge clk)

if(d[2*i]》d[2*i+1])begin

s1_max[i] 《= d[2*i];

s1_min[i] 《= d[2*i+1];

end

else begin

s1_max[i] 《= d[2*i+1];

s1_min[i] 《= d[2*i];

end

end

endgenerate

// stage 2,

wire[DW-1:0] s2_max[7:0];

wire[DW-1:0] s2_min[7:0];

generate

for(i=0;i《8;i=i+1)

begin:loop_megs2

meg u_s2meg(

.clk(clk),

.g1_max(s1_max[2*i]),

.g1_min(s1_min[2*i]),

.g2_max(s1_max[2*i+1]),

.g2_min(s1_min[2*i+1]),

.max1(s2_max[i]),

.max2(s2_min[i])

);

end

endgenerate

// stage 3,

wire[DW-1:0] s3_max[3:0];

wire[DW-1:0] s3_min[3:0];

generate

for(i=0;i《4;i=i+1)

begin:loop_megs3

meg u_s3meg(

.clk(clk),

.g1_max(s2_max[2*i]),

.g1_min(s2_min[2*i]),

.g2_max(s2_max[2*i+1]),

.g2_min(s2_min[2*i+1]),

.max1(s3_max[i]),

.max2(s3_min[i])

);

end

endgenerate

// stage 4,

wire[DW-1:0] s4_max[1:0];

wire[DW-1:0] s4_min[1:0];

generate

for(i=0;i《2;i=i+1)

begin:loop_megs4

meg u_s4meg(

.clk(clk),

.g1_max(s3_max[2*i]),

.g1_min(s3_min[2*i]),

.g2_max(s3_max[2*i+1]),

.g2_min(s3_min[2*i+1]),

.max1(s4_max[i]),

.max2(s4_min[i])

);

end

endgenerate

// stage 5,

meg u_s5meg(

.clk(clk),

.g1_max(s4_max[0]),

.g1_min(s4_min[0]),

.g2_max(s4_max[1]),

.g2_min(s4_min[1]),

.max1(max1),

.max2(max2)

);

endmodule

module meg#(

parameter DW = 8

input clk,

input [DW-1 :0] g1_max,

input [DW-1 :0] g1_min,

input [DW-1 :0] g2_max,

input [DW-1 :0] g2_min,

output reg [DW-1:0] max1,

output reg [DW-1:0] max2

);

always@(posedge clk)

begin

if(g1_max》g2_max) begin

max1 《= g1_max;

if(g2_max》g1_min)

max2 《= g2_max;

else

max2 《= g1_min;

end

else begin

max1 《= g2_max;

if(g1_max》g2_min)

max2 《= g1_max;

else

max2 《= g2_min;

end

end

endmodule

3. 其他

简单测试了上面的代码,在上一代器件上(20nm FPGA),8bit数据输入模块能综合到很高的频率,逻辑级数大概是5级左右,对于整个工程而言瓶颈基本不会出现在这一部分。32bit数据输入由于数据位宽太大,频率不会太高,但是通过将meg模块做一级流水,也几乎不会成为整个系统的瓶颈。

32bit32输入情况下,数据输入位宽为1024(不是IO输入,是内部信号)。之前在通信/数字信号处理方面可能不会用到这么大位宽的数据,但对于AI领域FPGA的应用,数千比特的输入应该是很平常的,这的确会影响最终FPGA上实现的效果。要想让机器学习算法在FPGA上跑得更好,还需要算法和FPGA共同努力才是。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1625

    文章

    21663

    浏览量

    601673
收藏 人收藏

    评论

    相关推荐

    分治法找出最大值和最小的问题

    我用分治法写了一程序,找出一数组中最大值和最小,可是运行时总是报错段错误,我把源代码贴出来,还请高手赐教指点。#include"std
    发表于 03-21 11:00

    DAQmx中的最大值最小的设定

    如何将与最大值和最小相连的输入控件控制旋钮的最大最小,即DAQmx中最大最小
    发表于 08-08 10:45

    新人求助Labview区域最大值

    各位大神帮帮小女子吧,泪流满面了 T T有一函数有四变量X1,X2,X3,X4,这四变量都在1~10且为整数。这四
    发表于 11-20 02:56

    怎么查找一数组里面与最大值最近的极大啊?

    本帖最后由 唐少华 于 2017-2-20 11:32 编辑 labview怎么查找一数组里面与最大值靠得最近的极大啊?次大好找
    发表于 02-20 10:54

    请问C6713找最大值次大的可行方法?

    我目前要用C6713处理上万数据,其中有一步是要找出这些数据中的最大值次大。在matlab我是用函数先找出
    发表于 07-25 06:08

    AD9235的使用稳定性未作出找到最大值的操作

    向各位大师请教几个问题,我使用ad9235与fpga电路进行一简单的最大值判断电路。一类似正玄信号(周期性的)模拟输入,通过ad9235
    发表于 10-09 17:43

    交流电的最大值与有效

    交流电的最大值与有效    我们知道,交流信号是时间的函数,它的幅度是随时间
    发表于 04-16 23:35 1.8w次阅读
    交流电的<b class='flag-5'>最大值</b>与有效<b class='flag-5'>值</b>

    输入最小 最大值选择电路

    输入最小 最大值选择电路
    发表于 09-25 10:37 2708次阅读
    四<b class='flag-5'>输入</b>最小 <b class='flag-5'>最大值</b>选择电路

    排除最大最小平均值

    输入数据中排除最大最小平均值的算法,测试通过。
    发表于 08-18 18:24 11次下载

    FPGA实现一模块,32输入中的最大值次大

    从算法本身来看,找最大值次大的过程很简单;通过两次遍历:第一次最大值,第二次
    的头像 发表于 03-31 11:18 1012次阅读

    交流电的有效最大值和平均值

    瞬时值的绝对,用I m 、U m 、E m 分别表示电流、电压和电动势的最大值。 3、交流电的有效 1)交流电的瞬时值是一随时间变化的量,难以表征其作功本领的大小,如果采用
    的头像 发表于 10-30 09:11 8524次阅读

    jvm配置metaspace最大值的参数

    JVM(Java虚拟机)是Java程序的运行环境,而Metaspace是Java 8及其更高版本中引入的一种新的内存区域,用于存储类的元数据。Metaspace的最大值可以通过在JVM启动时设置
    的头像 发表于 12-05 14:21 1991次阅读

    BUCK电路占空比最小最大值的限制因素分别是什么?

    BUCK电路占空比最小最大值的限制因素  BUCK电路是一种常用于降压调节的电力转换器,广泛应用于电源管理、马达控制和电动车辆等领域。在设计和实施BUCK电路时,占空比是一非常重要的参数,它
    的头像 发表于 01-31 18:14 3516次阅读

    二极管击穿电压是最大值还是有效

    二极管击穿电压是指二极管在反向偏置下,电流突然增大,导致二极管损坏的电压最大值(Peak Value):最大值是指在一周期内,电压或电流的
    的头像 发表于 08-08 10:05 671次阅读

    三相电流有效最大值关系

    为: 有效 = 最大值 / √2 这个关系是基于正弦波交流电的特性得出的。在正弦波交流电中,电流(或电压)随时间变化,其波形呈现为正弦曲线。有效是通过电流(或电压)的热效应来定义的,即让一
    的头像 发表于 08-08 10:11 2208次阅读