zoukankan      html  css  js  c++  java
  • 乘法器之五(混和式乘法器(Hybrid multiplication))

    4)    混和式乘法器(Hybrid multiplication

    混合乘法器模式结合了半并行和乘加两种乘法器模式,它有不同的两个输入位流,并且乘以不同的系数。

    这种模式在象FFTs这样的有复数乘法应用中非常有用,复数信号通常包含实部和虚部两部份,所以乘法

    实现的时候可以分开乘以不同的系数值。每个部份产生的部份积被累加产生最终的结果。

    混合乘法器模式中,每个时钟周期里从两组输入数据中依次选取相同的位数拼接起来,送到到RAM块的

    地址端口,低位先送。比如RAM块的地址端口只有四位时,那么从每个输入数据中依次选取2位来计算,

    直到输入数据的所有位都被送入RAM块地址端口。这样,一个16位输入总线共需要八个时钟周期送入到

    存储器。RAM块每个时钟周期的输出为特定一组输入位和系数的乘积之和。

    图19显示了一个用RAM LUT实现两个16位输入,以及最高到15位的常系数的例子,两个输入分别标记为

    “Input I”和“Input Q”。根据权位每个时钟周期移位累加从RAM块得到的部份积,一共要11个时钟

    (其中八个时钟周期用于将输入数据移入到RAM块,外加三个时钟周期的流水延时)来完成乘法操作。

    每次部份积的移位累加会增加两位。最后一次(也就是第八次)部份积累加后,乘法器产生一个32位输出。

    输入数据的宽度决定了乘法器的输出位宽以及乘法器的延时。

     

    图19中的例子是两个16位输入数据。虽然M512 RAM块可以配置成32X18位,能有5位地址(2^5=32),

    但每次每个输入要同时送入相同的位数,故最多一次接收两位(总共是四位)。这个例子中,如果使用相同

    的存储器块,输入的位宽决定着乘法器的输出位宽以及乘法器的延时。增加M512块的使用数目或者换成使

    用更大的存储器块比如M4K RAM,就可以有效减小乘法器的延时,并且支持更大的系数位宽。

    图20显示的是基于图19种例子的仿真结果。例子中有可选的流水级,两个乘数Iuput_I和Input_Q的值分

    别是300和55,系数Ci和Cq的值分别是10和25。这样,乘法的结果是:

    (Input_I X Ci)+ (Input_Q X Cq) = (300 X 10) + (55 X 25) = 4375

    提醒:设计者可以选择减少流水的级数,不过如此会减小设计结果的Fmax

     表28和表29显示了分别用StratixII和Stratix器件实现两个16位输入、15位常系数混合乘法器例子的结果。

     

    表29 用Stratix器件实现双输入、15位常系数混合乘法器的结果

     

    表30和表31显示了分别用StratixII和Stratix器件实现15位变系数混合乘法器例子的结果。

    自己写的程序,希望大家多多指教:

    module mul_test
      #(parameter WIDTH = 18,
       WIDTHAD = 4)
        (input clk,
      input sclr,
      input sload_data,
      input[15:0] input_i,/*输入信号I*/
      input[15:0] input_q,/*输入信号Q*/
      output[31:0] result,
      output result_valid);
    reg [31:0] result_r;
    reg[17:0] rom_out;
    reg[3:0] rom_add;
    reg [15:0] input_i_r, input_q_r;
    reg result_valid_r;
    reg[5:1] i;

    always@(posedge clk or negedge sclr)
    begin
    if(sclr == 0)
     begin
      result_r <= 32'd0;
      i <= 5'd0;
      input_i_r <= 16'd0;
      input_q_r <= 16'd0;
      rom_add <= 4'd0;
     end
    else
     begin
      if(sload_data == 1)/*用来启动乘法器,先把输入数据固定起来*/
      begin
       i <= 5'd0;
       input_i_r <= input_i;
       input_q_r<= input_q;
       result_r <= 32'd0;
       rom_add <= 4'd0;
      end
     else
      begin
       
          rom_add <= {input_i_r[i+1],input_i_r[i],input_q_r[i+1],input_q_r[i]};
          
       i <= i + 5'd2;
         if(i == 5'd20)
         i <= 5'd0;
         if(i >= 6)/*此时才真正把ROM中的数据读出来*/
       result_r <= result_r + ({14'd0,rom_out} << i-6);/*累加过程*/
      end
     end
    end
    always@(posedge clk )
    begin
     if(i == 5'd20)
     begin
       result_valid_r <= 1'b1;/*当最终结果输出时为1*/
      
      end
       
     else
      result_valid_r <= 1'b0;
    end
    lpm_rom rom1
    (.address(rom_add), .inclock(clk), .outclock(clk), .q(rom_out));
    defparam rom1.lpm_width = WIDTH;
    defparam rom1.lpm_widthad = WIDTHAD;
    defparam rom1.lpm_file = "mul_rom.mif";
    assign result = result_r;
    assign result_valid = result_valid_r;
    endmodule

    从上面仿真可以看出当i为6时rom_out才有输出所以会有 result_r <= result_r + ({14'd0,rom_out} << i-6);

    本例中,input_i和input_q分别乘的系数为10和25,有65535X10+1X25 = 655375;

  • 相关阅读:
    pyspider 在ubuntu上安装失败怎么搞?
    怎么在项目中使用前端包管理器bower和构建工具gulp
    Asp.net mvc 实时生成缩率图到硬盘
    如果转载优酷、土豆视频等,怎么让视频自适应宽度?
    C语言II博客作业04
    C语言I博客作业03
    C语言II博客作业02
    C语言II博客作业01
    学期总结
    The first essay
  • 原文地址:https://www.cnblogs.com/zhongguo135/p/2640363.html
Copyright © 2011-2022 走看看