- 若该文为原创文章,未经允许不得转载
- 风释雪
- QQ:627833006
- E-mail:hn.cy@foxmail.com
- CSDN博客地址:https://blog.csdn.net/weixin_46718879
1.版本说明
2.概述
本文主要实现在INT8模式下,使用一个DSP,同时计算两个乘法。
3.原理
Z
Y
N
Q
:
P
=
(
A
×
2
17
+
D
)
×
B
ZYNQ :P = ( A \times 2 ^ {17} + D ) \times B
ZYNQ:P=(A×217+D)×B
U
l
t
r
a
s
c
a
l
e
:
P
=
(
A
×
2
18
+
D
)
×
B
Ultrascale:P = ( A \times 2 ^ {18} + D ) \times B
Ultrascale:P=(A×218+D)×B
ZYNQ的DSP位宽为:18x25(有符号)
ZYNQ Ultrascale的DSP位宽为:18x27(有符号)
在INT8模式下,A、D、B分别为8bit数据,AB结果共16bit,DB结果共16bit,如图所示结果过程:(公式A = 图a, 公式D = 图b, 公式B = 图c)
在zynq器件中
,由于DSP的最大位宽少了2bit,因此在 公式中,移位就少了一位(只有17,ultrascale是18),所以低位8bit相乘后,会有一个bit的结果误差影响高位的结果输出!!通过仿真发现:
- 当 bc 相乘为正数, 高位直接输出,低位直接输出;
- 当 bc 相乘为负数(bc本身不能为0),高位直接输出+1,低位直接输出;
总结:低位的8bit相乘,无论正负不影响结果,但是高位的输出需要根据低位运算结果的正负,选择是否+1操作。
在ultrascaler器件中
,同ZYNQ。
4.验证
- 例化DSP IP核
- 输入ADB三个数,同时计算AD、DB
- 直接用乘号计算AD、DB并延时与DSP结果一起输出,对比两者输出数据是否相同。
- ADB各位8bit,因此输入组合公用:256x256x256,因此输入模块进行结果比对,全部相同则模块正确!!
`timescale 1ns/1ps
/******************************************************************************
* Auther : abner
* Email : hn.cy@foxmail.com
* Description :
* @Create : 2020.04.20
* @Modify :
******************************************************************************/
module dsp_mux
(
input clk,
input din_en,
input [7 : 0] din_a,
input [7 : 0] din_b,
input [7 : 0] din_d,
output reg dout_en = 1'd0,
output reg [15 : 0] dout_ab,
output reg [15 : 0] dout_db
);
/*******************************************************************************
*
* Define localparam
*
********************************************************************************/
/*******************************************************************************
*
* Define reg / wire
*
********************************************************************************/
reg [1 : 0] dly = 1'd0;
wire [32 : 0] p;
wire signed [15 : 0] p_ab;
wire signed [15 : 0] p_db;
/*******************************************************************************
*
* RTL verilog
*
*******************************************************************************/
// DSP48 INT8 Mux: p = (a*2^17 + d) * b
// D_BITWIDTH = 25
// A_BITWIDTH = 25
// B_BITWIDTH = 8
// Tier_A4 = EN
// Tier_B4 = EN
// Tier_C6 = EN
// OUT_BITWIDTH = 33
// Delay = 2
ip_scaler_dsp_v ip_scaler_dsp_v (
.CLK( clk ), // input wire CLK
.CE ( din_en ),
.A ( {din_a, 17'd0} ), // input wire [24 : 0] A
.B ( din_b ), // input wire [ 7 : 0] B
.D ( {{17{din_d[7]}}, din_d} ), // input wire [24 : 0] D
.P ( p ) // output wire [32 : 0] P
);
assign p_ab = p[32:17];
assign p_db = p[15: 0];
always @ (posedge clk) begin
{dout_en, dly} <= {dly, din_en};
if(dly[1]) begin
dout_ab <= p_ab + p_db[15];
dout_db <= p_db;
end
end
/*
// sim
// * (a + d) * b
// * a+ d+ b+ : ab+0 db+0
// * a+ d- b- : ab+0 db+0
// * a- d+ b+ : ab+0 db+0
// * a- d- b- : ab+0 db+0
// * a+ d+ b- : ab+1 db+0 (& d!=0)
// * a+ d- b+ : ab+1 db+0 (& d!=0)
// * a- d+ b- : ab+1 db+0 (& d!=0)
// * a- d- b+ : ab+1 db+0 (& d!=0)
reg signed [7 : 0] din_a_d1;
reg signed [7 : 0] din_b_d1;
reg signed [7 : 0] din_d_d1;
reg signed [7 : 0] din_a_d2;
reg signed [7 : 0] din_b_d2;
reg signed [7 : 0] din_d_d2;
reg signed [15 : 0] rlt_ab;
reg signed [15 : 0] rlt_db;
reg err_ab;
reg err_db;
always @ (posedge clk) begin
din_a_d1 <= din_a;
din_b_d1 <= din_b;
din_d_d1 <= din_d;
din_a_d2 <= din_a_d1;
din_b_d2 <= din_b_d1;
din_d_d2 <= din_d_d1;
rlt_ab <= din_a_d2 * din_b_d2;
rlt_db <= din_d_d2 * din_b_d2;
err_ab <= (rlt_ab != dout_ab);
err_db <= (rlt_db != dout_db);
end
*/
endmodule
5.后序
DSP虽然可以复用,但是由于上一级DSP输出的结果经过处理能才给下一级的DSP,导致实际在布线是,DSP的最大时钟速度已经被消弱,所以速度和面积在这里存在取舍!
后续会继续研究ultrascale的DSP复位,是否能够直接级联,减少布线对最大时钟的影响。