赞
踩
① 使用官方提供的IP核 Multipler
优点:使用最少的DSP资源,可以进行有符号,无符号数计算;位宽2-64bit可调。
缺点:最大位宽只有64bit,数据再大不支持(eg:s数据放大2^50后计算,数据位宽大于64)。
② 使用乘法号 * 计算
优点:数据位宽可以任意调整,使用多个DSP资源。
缺点:DSP资源使用浪费,同样位宽计算,使用DSP数可能大于使用IP核;有符号计算时需要使用signed标识寄存器内数据是有符号数,不然会被当作无符号数计算。
计算数据 32bit * 64bit;使用IP核Multipler计算,编译过后报时序警告,打开Implemented Design可以看到
在Device窗口点击Routing Resources 可以看到这为实现这个乘法计算所经过的路径
在右边的窗口中也可以看到,此时路径延时为13.244ns.系统时钟100M。
路径延时过大,可能会使得数据在时钟沿到来后无法处于稳定状态,从而数据无法被所存,出现亚稳态,在资源使用紧张,时序要求严苛的时候会导致系统无法正确运行。
为处理数据路径延时过大导致亚稳态的问题,我们可以将大位宽数据拆分成多个位宽的数据放到多个寄存器中分开计算,并将结果移位相加。
方案原理:求 data_A[63:0] * data_B[31:0] 。
①:取两个数据最高位作为符号位flag。
②:取两个数据的绝对值data_A_Abs = |data_A| ; data_B_Abs = |data_B| 。
③:将大位宽拆成多个小位宽数据:data_A_H = data_A_Abs [63:32] ; data_A_L = data_B_Abs [31:0]。
④:将拆分的数据相乘data_buff1 = data_A_H * data_B_Abs ; data_buff2 = data_A_L * data_B_Abs 。
⑤:移位相加 data_o = data_buff1 <<32 + data_buff2 ;
Verilog代码设计:
`timescale 1ns / 1ps
module Calculate(
input clk ,
input rst_n ,
input Calculate_en ,
input signed [63:0] data_A ,
input signed [31:0] data_B ,
output reg signed [95:0] data_o
);
reg Calculate_en1 ;
always@(posedge clk or negedge rst_n)
begin
if(rst_n==0)
Calculate_en1 <= 'b0 ;
else
Calculate_en1 <= Calculate_en ;
end
assign Calculate_en_raising = ~ Calculate_en1 & Calculate_en;
localparam idle = 0 ,
st1 = 1 ,
st2 = 2 ,
st3 = 3 ;
reg [3:0] cur_st ;
reg [31:0] data_A_H ;
reg [31:0] data_A_L ;
reg [63:0] data_buff1 ;
reg [63:0] data_buff2 ;
reg [63:0] data_A_Abs ;
reg [31:0] data_B_Abs ;
reg flag1 ;
always@(posedge clk or negedge rst_n)
begin
if(rst_n==0)
begin
data_A_Abs <= 'b0 ;
data_B_Abs <= 'b0 ;
data_A_H <= 'b0 ;
data_A_L <= 'b0 ;
data_buff1 <= 'b0 ;
data_buff2 <= 'b0 ;
data_o <= 'b0 ;
flag1 <= 'b0 ;
cur_st <= idle ;
end
else
begin
case(cur_st)
idle :begin
if(PR_en_raising)
begin
PR_out_en <= 'b0 ;
case({data_B[31],data_A[63]})
2'b00: //++
begin
flag1 <= 'b0 ;
data_B_Abs <= data_B ;
data_A_Abs <= data_A ;
end
2'b01: //+-
begin
flag1 <= 'b1 ;
data_B_Abs <= data_B ;
data_A_Abs <= - data_A ;
end
2'b10: //-+
begin
flag1 <= 'b1 ;
data_B_Abs <= - data_B ;
data_A_Abs <= data_A ;
end
2'b11: //--
begin
flag1 <= 'b0 ;
data_B_Abs <= - data_B ;
data_A_Abs <= - data_A ;
end
endcase
cur_st <= st1 ;
end
else
cur_st <= idle ;
end
st1 :begin
data_A_H <= data_A_Abs[63:32] ;
data_A_L <= data_A_Abs[31:0] ;
cur_st <= st2 ;
end
st2 :begin
data_buff1 <= data_B_Abs * data_A_H ;
data_buff2 <= data_B_Abs * data_A_L ;
cur_st <= st3 ;
end
st3 :begin
if(flag1)
data_o <= -({{32{data_buff2[63]}},data_buff2} + {data_buff1,32'b0}) ;
else
data_o <= {{32{data_buff2[63]}},data_buff2} + {data_buff1,32'b0} ;
cur_st <= idle ;
end
default :begin
end
endcase
end
end
endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。