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;