FPGA Verilog 并行全比较算法(大点数)

FPGA Verilog 并行全比较算法(大点数)

排序算法的意义:

排序是一种重要的数据运算,传统的排序方法主要靠软件串行方式实现,包括冒泡法、选择法、计数法等,这些算法大多采用循环比较,运算费时,实时性差。不能满足工程上越来越高的实时性要求。FPGA由于其优秀的并行运算能力,充分利用这种能力可在短短数个周期内完成大点数(如256点)的排序任务。

算法介绍:

并行全比较算法时一种以FPGA的资源换取排序时间的算法。一组数据,先进行两两之间的比较,每两个数比较都会得到一个比较结果。可以根据两数的大小定义输出排序结果0或1。对这些比较结果进行求和计算得到积分通过积分可以进行排序。由于所有数的两两之间的比较都在硬件内同时进行,只需一个时钟的时间,即可得到比较结果,再加上比较结果的和加等计算时间,几个时钟周期,就实现了数字序列的排序。

算法优势:

在网上能找到的并行全比较算法,大多数时小点数的并行全比较算法。通过多个if-else判断,来进行对比和积分。但面对大点数的全比较并行算法,这种方式并不可行(笔者最初写了一个256点全比较算法,用这种方式写出来比较部分有6W多行,最终是通过写脚本输出文本来完成的)。本文采用了for循环的方法,同时采用二维数组作为积分表,来进行运算。通过三个周期可以完成排序。

算法流程

在缓存存满了之后,先进行数据的一一对比和计分。

   case (mst_exec_state)  
   ranking: 
    if(cacu_flag)
    begin   
     for(temp_j=0;temp_j<255;temp_j=temp_j+1)   //对比
     begin
      for(temp_i=temp_j+1;temp_i<256;temp_i=temp_i+1)    
      begin 
       //#5;
       if(save_data[temp_j]>save_data[temp_i])     
       begin      
        state[temp_j][temp_i]<=1;     
       end     
       else     
       begin      
        state[temp_i][temp_j]<=1;     
       end
      end
     end
     mst_exec_state <= adding;
    end

state[temp_j][temp_i]是一个二维数组。
如果data[temp_j]大于data[temp_i],state[temp_j][temp_i]置一。最后求和的时候data[1]的积分就是对state[1][i]求和。
这里写图片描述
图示为data2>data1>data0
求和部分:

   adding: 
    if(cacu_flag)
    begin
     for(temp_j=0;temp_j<256;temp_j=temp_j+1)   //求和
     begin
      for(temp_i=0;temp_i<256;temp_i=temp_i+1)    
      begin 
       sum[temp_j] = state[temp_j][temp_i] + sum[temp_j];
      end
     end 
     mst_exec_state <= saving;
    end

按照积分排序。

   saving: 
    if(cacu_flag)
    begin
     for(temp_j=0;temp_j<256;temp_j=temp_j+1)   //输入对应位置
     begin    
      output_data[sum[temp_j]] <= save_data[temp_j];    
     end
     out_data_i <=0;
     output_flag <=1;
     cacu_flag <=0;   
     dat_num <=0;
     mst_exec_state <= ranking;
     clear_state<=1;
    end

sum所有的积分最终就是对应数字应该在的位置 output_data[sum[temp_j]] ,同时这种写法已经考虑到了一组数据中有几个相等的数字的情况,两个数字相等,会给后面的数字计分加1.

所有代码和TB

代码

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2018/08/21 15:40:50
// Design Name: 
// Module Name: rank
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module rank(
 input wire aclk,   //模块输入时钟
 input wire aken,   //模块中断信号
 input wire [7:0]   in_data,    //输入信号数据
 input  wire ready,     
 output reg valid,
 output reg [7:0]   out_data    //输出信号数据
    );

 reg [7:0]  state   [255:0][255:0]; //比较大小记录寄存器
 reg [7:0]  sum [255:0];    //比较大小记录求和
 reg [7:0]  save_data   [255:0];    //输入数据存储
 reg    [7:0]   output_data [255:0];    //输出数据缓存
 reg    cacu_flag = 0;  //计算比较标志位
 reg    output_flag = 0;    //输出信号标志位
 reg clear_state = 0;   //清除内存标志位

 //一些计数变量
 integer out_data_i = 0;
 integer dat_num = 0;
 integer    temp_i = 0;
 integer    temp_j = 0;
 integer clear_i = 0;
 integer clear_j = 0; 

 parameter [1:0] ranking = 2'b00, // This is the initial/idle state               

    adding = 2'b01, // This state initializes the counter, ones   
        // the counter reaches C_M_START_COUNT count,        
        // the state machine changes state to INIT_WRITE     
    saving = 2'b10;
 reg    [1:0]   mst_exec_state;  

 initial $readmemh("C:/Users/74339/Desktop/vivado_code/ranking/int.txt",sum);

 always@(posedge aclk)  //清理内存逻辑控制
 begin
  if(clear_state)
  begin
   for(clear_i=0;clear_i<256;clear_i=clear_i+1)
   begin
    for(clear_j=0;clear_j<256;clear_j=clear_j+1)
    begin
     state[clear_i][clear_j]<=0;
    end
    sum[clear_i] <=0;
   end
   clear_state <= 0;
  end
 end

 always@(posedge aclk)  //计算开始逻辑控制
 begin
  if(dat_num>255)
  begin
   cacu_flag <= 1;
   valid <= 0;
  end
  else
  begin
   valid <= 1;
  end
 end

 always@(posedge aclk)  //输入控制信号逻辑
 begin
  if(valid&ready)
  begin
   save_data[dat_num] <= in_data;
   dat_num <= dat_num + 1;
  end
 end

 always@(posedge aclk)
 begin
  if(!aken)
  begin
   clear_state <= 1;
   dat_num <= 0;
   valid <= 0;
   cacu_flag <= 0;
   out_data <= 8'h00;
   mst_exec_state <= ranking;
  end
  else
  begin

   case (mst_exec_state)  
   ranking: 
    if(cacu_flag)
    begin   
     for(temp_j=0;temp_j<255;temp_j=temp_j+1)   //对比
     begin
      for(temp_i=temp_j+1;temp_i<256;temp_i=temp_i+1)    
      begin 
       //#5;
       if(save_data[temp_j]>save_data[temp_i])     
       begin      
        state[temp_j][temp_i]<=1;     
       end     
       else     
       begin      
        state[temp_i][temp_j]<=1;     
       end
      end
     end
     mst_exec_state <= adding;
    end
   adding: 
    if(cacu_flag)
    begin
     for(temp_j=0;temp_j<256;temp_j=temp_j+1)   //求和
     begin
      for(temp_i=0;temp_i<256;temp_i=temp_i+1)    
      begin 
       sum[temp_j] = state[temp_j][temp_i] + sum[temp_j];
      end
     end 
     mst_exec_state <= saving;
    end
   saving: 
    if(cacu_flag)
    begin
     for(temp_j=0;temp_j<256;temp_j=temp_j+1)   //输入对应位置
     begin    
      output_data[sum[temp_j]] <= save_data[temp_j];    
     end
     out_data_i <=0;
     output_flag <=1;
     cacu_flag <=0;   
     dat_num <=0;
     mst_exec_state <= ranking;
     clear_state<=1;
    end
   endcase
  end
 end  


 always@(posedge aclk)
 begin
  if(output_flag)
  begin
   out_data <= output_data[out_data_i];
   out_data_i <= out_data_i + 1;
  end
 end

 always@(posedge aclk)
 begin
  if(out_data_i>=256)
  begin
   out_data_i <= 0;
   output_flag <= 0;
  end
 end 
endmodule

TB

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2018/08/21 17:14:18
// Design Name: 
// Module Name: rank_TB
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module rank_TB;
 reg    aken;
 reg aclk = 0;
 reg    [7:0]   in_data = 0;
 reg    ready;
 wire   valid;
 wire [7:0] out_data;

 rank uut(
 .aclk(aclk),
 .aken(aken),
 .in_data(in_data),
 .ready(ready),
 .valid(valid),
 .out_data(out_data)
 );

 reg[11:0] mem0_re[700:0];
 integer    temp_i = 0;

 initial $readmemh("C:/Users/74339/Desktop/vivado_code/ranking/data.txt",mem0_re);


 always #5 aclk <= !aclk;

 always @(posedge aclk)
 begin

  ready <= 1;

  if(ready&&ready)
  begin
  in_data <= mem0_re[temp_i];
   temp_i <= temp_i+1;
  end

 end

 initial
 begin
  aken <=0 ;

  #30;

  aken <= 1;


 end
endmodule

仿真结果:

这里写图片描述
可以看到,在缓存存满了之后,一个周期开始进行计分,一个周期求和,之后就可以输出啦。
这里写图片描述
各个数对应的积分。
这里写图片描述
排序之后的数。可以看到已经考虑过了数字相等的情况。

  • 9
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 多路并行FFT算法是一种将多个FFT算法并行进行计算的方法,可以大幅提高FFT的计算速度。FPGA是一种灵活可编程的硬件平台,因其高度并行化的特点,非常适合用于实现多路并行FFT算法。 在FPGA中实现多路并行FFT算法的关键技术包括并行输入数据的处理、并行FFT计算模块的设计和数据的重组。首先,需要对输入数据进行并行处理,将其分成多个子序列,以实现并行计算的目的。接下来,需要设计并实现多个并行FFT计算模块,以对不同子序列进行FFT计算。由于FPGA中的硬件资源有限,需要合理地分配和利用这些资源,以实现高效的多路并行计算。 在并行FFT计算过程中,为了保证并行计算模块之间的数据一致性,需要采用合适的时钟同步和数据通信机制。同时,由于并行计算模块的结果是独立计算的,需要对这些结果进行合并和重组,以得到最终的FFT计算结果。在数据重组过程中,可以使用合并排序等算法来保证数据的正确顺序。 此外,为了充分利用FPGA并行计算能力,还可以采用流水线技术和片上存储器等方式进行优化。流水线技术可以将FFT计算过程划分为多个阶段,并使每个阶段的计算结果能够连续地进行下一阶段的计算,以提高整体的计算效率。而片上存储器则可以用来缓存中间结果和输入数据,减少外部存储器的访问延迟,进一步提高计算效率。 总而言之,多路并行FFT算法FPGA上的实现涉及到并行输入数据的处理、并行FFT计算模块的设计和数据的重组等关键技术。通过合理地设计和优化,可以实现高效的FFT计算,并提高计算速度。 ### 回答2: 多路并行FFT算法FPGA的实现涉及到以下几个关键技术。 首先,多路并行FFT算法需要对输入数据进行分组,并分配给不同的FFT模块进行处理。在FPGA中,可以使用分布式RAM或者BRAM来存储输入数据,并设计合适的数据引导逻辑,将输入数据均匀地分配给不同的FFT模块。 其次,每个FFT模块需要进行FFT变换的计算。对于每个模块,需要实现FFT的核心计算部分,包括蝶形运算和旋转因子乘法。这些计算可以通过组合逻辑和乘法器实现,并且可以使用并行计算技术来提高计算速度。 另外,在多路并行FFT算法中,多个FFT模块的输出需要进行重新组合,得到最终的FFT结果。在FPGA中,可以使用分布式RAM或者BRAM来存储每个FFT模块的输出,并设计合适的数据引导逻辑,将各个模块的结果按照正确的顺序重新组合。 此外,为了进一步提高多路并行FFT算法的性能,还可以使用流水线技术对FFT模块进行优化。通过将FFT计算划分为多个阶段,并将不同阶段的计算并行化,可以进一步提高FFT的计算速度。 总之,多路并行FFT算法FPGA的实现涉及到分组分配、FFT计算、结果重组等关键技术,并可以通过并行计算和流水线优化来进一步提高计算性能。 ### 回答3: 多路并行FFT (Fast Fourier Transform) 算法是一种在FPGA上实现FFT加速的方法。在传统的FFT算法中,数据是串行输入并依次计算,而多路并行FFT算法通过将输入数据分为多个子序列并行计算,极大提高了计算效率。 FPGA作为一种可编程逻辑器件,具有高度的并行性和灵活性,非常适合实现多路并行FFT算法。在FPGA上实现多路并行FFT算法需要考虑以下几个关键技术。 首先是数据的划分和分配。将输入数据划分为多个子序列,使得每个子序列都可以被并行处理。这需要设计有效的数据分配方案,确保每个子序列被分配到合适的处理单元中。 其次是设计并行计算单元。每个处理单元需要实现FFT运算的基本功能,包括蝶形运算、FFT kernel计算、数据交换等。这些并行计算单元可以使用硬件描述语言(如VHDL或Verilog)实现,并通过FPGA的配置器进行逻辑资源的分配。 另外,需要设计合适的数据通路和存储器结构。数据通路用于连接并行计算单元,传输输入和输出数据。存储器结构则用于存储中间结果和FFT kernel。这些结构的设计需要考虑到数据传输带宽、存储器容量以及时序等因素。 最后,需要对多路并行FFT算法进行优化。这包括算法并行度设计、蝶形运算的并行性、数据重用等方面。通过合理的算法优化,可以提高FFT计算的性能和吞吐量。 总而言之,多路并行FFT算法FPGA实现技术涉及数据的划分和分配、并行计算单元的设计、数据通路和存储器结构的设计,以及算法的优化等方面。通过合理的设计和优化,可以实现高效的FFT计算,并提升FPGA系统的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值