原创 Altera vs Xilinx之二 DSP速度(转)

2008-7-1 13:13 4384 6 6 分类: 测试测量

转自:http://www.21ic.com/news/html/257/show27813.htm


 


 


大家知道,高端的FPGA中都有为数不少的DSP块,里边主要包括一些18X18的乘法器,以及加法器等单元,相邻的DSP往往可以通过专用的连线互连,从而实现滤波器的级联设计,提高滤波器的运行速度。XilinxAlteraDSP块有所差别,XilinxDSP模块可以做18X18乘法,18X18乘累加运算,18X18乘加运算等,其中累加器可以到48位宽,厂家标称的最高速度位500MHzAlteraDSP块可以分解成为8X8, 16X16, 32X32块,可以完成乘法,乘累加,乘加等运算,厂家标称的最高速度为450MHz

 

下面的表格给出了一些综合结果。

 

1  转置形式的FIR滤波器综合结果


FPGA PlatformFPGA TypeSpeed (MHz)Speed (MHz)FPGA TypeFPGA Platform
Stratix IIEP2S90F1020C3313 165 xc4vsx35-ff668-12Virtex 4
EP2S90F1020C4282 154 xc4vsx35-ff668-11
EP2S90F1020C5240 124 xc4vsx35-ff668-10
 

2  直接形式的FIR滤波器综合结果


FPGA PlatformFPGA TypeSpeed (MHz)Speed (MHz)FPGA TypeFPGA Platform
Stratix IIEP2S90F1020C3195109 xc4vsx35-ff668-12Virtex 4
EP2S90F1020C4169101 xc4vsx35-ff668-11
EP2S90F1020C514188 xc4vsx35-ff668-10
 

一些简单的分析:


1.  Xilinx之所以速度比Altera慢一个原因可能是ISE综合时可能需要加一些约束才可以达到最佳状态,就这件事情我曾经咨询过Xilinx的应用工程师,她给了我一个使用Synplify综合的结果,速度明显比我使用ISE的好不少。


2.  有关XilinxDSP Block,我还试了不少其他的模块,包括简单的乘法器等,但是都不能达到器标称的500MHz,另外,ISE不能支持随意的写法,对代码的风格有一定的要求,比如,需要写成同步reset,这样才能被综合到DSP Block当中。

 

附件是相应的VHDL代码,欢迎大家讨论。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity NoiseFilterD is
  port(
    aReset : in std_logic;
    Clk    : in std_logic;
   
    cDin   : in std_logic_vector(7 downto 0);
    cDout  : out std_logic_vector(7 downto 0));
end NoiseFilterD;


architecture rtl of NoiseFilterD is


  constant kNumCoes : positive := 57;
 
  type IntegerArray is array (natural range <>) of integer;
  constant kCoe : IntegerArray(kNumCoes-1 downto 0) := (
                                     -5,   6,    10,   0,    -16,  -11,  16,   31,
                                     -1,   -48,  -34,  45,   84,   -2,   -120, -84,
                                     105,  193,  -4,   -272, -194, 241,  463,  -5,
                                     -742, -618, 952,  3092, 4095, 3092, 952,  -618,
                                     -742, -5,   463,  241,  -194, -272, -4,   193,
                                     105,  -84,  -120, -2,   84,   45,   -34,  -48,
                                     -1,   31,   16,   -11,  -16,  0,    10,   6,
                                     -5);
                                               
  type SignedArray is array (natural range <>) of signed(7 downto 0);
  signal cDelayData : SignedArray(kNumCoes-1 downto 0);  
 
  type ProdArray is array (natural range <>) of signed(20 downto 0);
  signal cProd : ProdArray(kNumCoes-1 downto 0);
 
  type SumArray is array (natural range <>) of signed(22 downto 0);
  signal cSumL1 : SumArray(13 downto 0);
  signal cSumL2 : SumArray(3 downto 0);
  signal cSumL3 : SumArray(0 downto 0);
                                               
begin                                          
 
  cDout <= std_logic_vector(cSumL3(0)(20 downto 13));
                                               
  -- Input data delay chain
  process(aReset, Clk)                         
  begin                                        
    if aReset='1' then                         
      for i in 0 to kNumCoes-1 loop                     
        cDelayData(i) <= (others => '0');      
      end loop;                                
    elsif rising_edge(Clk) then                
      cDelayData(0) <= signed(cDin);                
      for i in 1 to kNumCoes-1 loop                     
        cDelayData(i) <= cDelayData(i-1);      
      end loop;                                
    end if;                                    
  end process;                                 
                                               
  -- Calculate product of each tap
  process(aReset, Clk)                         
  begin                                        
    if aReset='1' then   
      for i in 0 to kNumCoes-1 loop                     
        cProd(i) <= (others => '0');      
      end loop;                                
    elsif rising_edge(Clk) then                
      for i in 0 to kNumCoes-1 loop                     
        cProd(i) <= cDelayData(i) * to_signed(kCoe(i), 13);      
      end loop;                                
    end if;                                    
  end process;       
 
  -- calculate the first level sum
  process(aReset, Clk)
  begin
    if aReset='1' then
      for i in 0 to 13 loop
        cSumL1(i) <= (others => '0');
      end loop;
    elsif rising_edge(Clk) then
      for i in 0 to 13 loop
        cSumL1(i) <= resize(cProd(i*4), 23) + resize(cProd(i*4+1), 23) +
                     resize(cProd(i*4+2), 23) + resize(cProd(i*4+3), 23);
      end loop;
    end if;
  end process;                         
 
  -- calculate the second level sum
  process(aReset, Clk)
  begin
    if aReset='1' then
      for i in 0 to 3 loop
        cSumL2(i) <= (others => '0');
      end loop;
    elsif rising_edge(Clk) then
      for i in 0 to 2 loop
        cSumL2(i) <= cSumL1(i*4) + cSumL1(i*4+1) + cSumL1(i*4+2) + cSumL1(i*4+3);
      end loop;
      cSumL2(3) <= cSumL1(12) + cSumL1(13);
    end if;
  end process;                         
 
  -- calculate the third level sum
  process(aReset, Clk)
  begin
    if aReset='1' then
      cSumL3(0) <= (others => '0');
    elsif rising_edge(Clk) then
      cSumL3(0) <= cSumL2(0) + cSumL2(1) + cSumL2(2) + cSumL2(3);
    end if;
  end process;                         
                                               
end rtl;


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity NoiseFilterT is
  port
  (aReset : in std_logic;
   Clk    : in std_logic;
  
   cDin   : in std_logic_vector(7 downto 0);
   cDout  : out std_logic_vector(7 downto 0));
end NoiseFilterT;


architecture rtl of NoiseFilterT is


  constant kNumCoes : positive := 57;
 
  type IntegerArray is array (natural range <>) of integer;
  constant kCoe : IntegerArray(kNumCoes-1 downto 0) := (
                                     -5,   6,    10,   0,    -16,  -11,  16,   31,
                                     -1,   -48,  -34,  45,   84,   -2,   -120, -84,
                                     105,  193,  -4,   -272, -194, 241,  463,  -5,
                                     -742, -618, 952,  3092, 4095, 3092, 952,  -618,
                                     -742, -5,   463,  241,  -194, -272, -4,   193,
                                     105,  -84,  -120, -2,   84,   45,   -34,  -48,
                                     -1,   31,   16,   -11,  -16,  0,    10,   6,
                                     -5);


  type ProdArray is array (natural range <>) of signed(20 downto 0);
  signal cProd : ProdArray(kNumCoes-1 downto 0);
 
  type SumArray is array (natural range <>) of signed(22 downto 0);
  signal cSum : SumArray(kNumCoes-1 downto 0);
 
  signal cDin_ms, cDinDbSync : signed(7 downto 0);
 
begin
 
  cDout <= std_logic_vector(cSum(kNumCoes-1)(20 downto 13));
 
  process(aReset, Clk)
  begin
    if aReset='1' then
      cDin_ms    <= (others => '0');
      cDinDbSync <= (others => '0');
    elsif rising_edge(Clk) then
      cDin_ms    <= signed(cDin);
      cDinDbSync <= cDin_ms;
    end if;
  end process;
 
  -- multiply the input data and
  process(aReset, Clk)
  begin
    if aReset='1' then
      for i in 0 to 56 loop
        cProd(i) <= (others => '0');
      end loop;
    elsif rising_edge(Clk) then
      for i in 0 to 56 loop
        cProd(i) <= cDinDbSync * to_signed(kCoe(56-i), 13);
      end loop;
    end if;
  end process;
 
  -- Add the products
  process(aReset, Clk)
  begin
    if aReset='1' then
      for i in 0 to kNumCoes-1 loop
        cSum(i) <= (others => '0');
      end loop;
    elsif rising_edge(Clk) then
      cSum(0) <= resize(cProd(0), 23);
      for i in 1 to kNumCoes-1 loop
        cSum(i) <= cSum(i-1) + resize(cProd(i), 23);
      end loop;
    end if;
  end process;
   
end rtl;


随着FPGA在信号处理领域应用越来越广泛, 其内部的DSP资源越来越受到了开发者的重视. 本文对XilinxAltera FPGA的固定乘法器(DSP)做一个比较深入的分析, 以对今后的设计提供参考.


 首先, XilinxAlteraFPGA DSP功能基本相同, 两者基本上可以实现相近的功能. 比较小的差别是,XilinxDSP模块可以在模块内做乘累加运算, Altera的必须借助逻辑资源实现. 另外, 两者的速度有所区别, Xilinx V4标称最高速度为500MHz, Altera S2标称最高速率为450MHz.  在实际使用过程当中, 厂商的参数固然重要, 然而用户的使用对性能的影响也是非常大的. 我在AlteraS2C3上用综合工具自动识别 *, 以及调用 IP core, 发现两者的结果一致, 对于16X16的乘法器速度是367.65MHz, 对于8X8乘法器的速度是375.94MHz. AlteraIP core对流水线的支持相对较少, 只有2. Xilinx综合工具似乎并没有那么智能, 只能把 * 识别出来, IP core0级流水线替代, 而不能将乘法后跟随的一级流水线自己吸收到IP core. 不过Xilinx的乘法器提供了18级流水线选择, 因而采用IP core例化实现的乘法器速度大大的提升. 我做的一个结果(V4-12), 采用综合工具infer出乘法器的速度是189MHz, 而采用IP core例化的方法实现的为260MHz611MHz, 分别对应一级流水线和两级流水线结构 

从以上实验结果以及笔者的使用经验来看, 似乎Altera的软件的智能程度稍高一些, 然而Xilinx的硬件功能更强. 在本例子当中, 通过例化IP core, 可以大大提高乘法器的速度. 如果采用XilinxFPGA, 在项目前期时可以采用综合工具infer, 留两级流水线待将来例化IP core使用, 这样一方面可以达到原型平台的快速开发, 用可以保证以后性能的改进和提高. 而采用alteraFPGA, 似乎软件已经解决了以上问题, 利用IP core例化的效果并不明显.

下面是代码
module SyncMult (areset, clk, a, b, prod);


  parameter kinsize="16";
 
  input clk, areset;
  input [kinsize-1:0] a, b;
  output [kinsize*2-1:0] prod;
 
  reg [kinsize-1:0] a_ms, a_db_sync;
  reg [kinsize-1:0] b_ms, b_db_sync;
  reg [kinsize*2-1:0] pi, pj;
 
  assign prod = pj;
 
  always @(posedge clk or posedge areset)
  begin
    if (areset)
      begin
        a_ms <= 0;
        b_ms <= 0;
        a_db_sync <= 0;
        b_db_sync <= 0;
        pi <= 0;
        pj   <= 0;
      end
    else
      begin
        a_ms <= a;
        b_ms <= b;
        a_db_sync <= a_ms;
        b_db_sync <= b_ms;
        pi <= a_db_sync * b_db_sync;
        pj <= pi;
      end
  end


endmodule

module SyncMultWrapX (areset, clk, a, b, prod);
 
  parameter kinsize="16";
  input clk, areset;
  input [kinsize-1:0] a, b;
  output [kinsize*2-1:0] prod;
 
  reg [kinsize-1:0] a_ms, a_db_sync;
  reg [kinsize-1:0] b_ms, b_db_sync;
  //reg [15:0] pi, pj;
 
  //assign prod = pj;
 
  always @(posedge clk or posedge areset)
  begin
    if (areset)
      begin
        a_ms <= 0;
        b_ms <= 0;
        a_db_sync <= 0;
        b_db_sync <= 0;
      end
    else
      begin
        a_ms <= a;
        b_ms <= b;
        a_db_sync <= a_ms;
        b_db_sync <= b_ms;
      end
  end
 
  MultCoreX MultIPCoreX(
    .a (a_db_sync),
    .b (b_db_sync),
    .sclr (areset),
    .clk (clk),
    .p (prod));


endmodule

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条