一、 实验过程中发现的问题
使用ISE进行项目的实现时出现以下错误。
意思很简单,就是使用DSP48E1的数量超出限制,因为没有接触过DSP48E1,所以尝试了很多错误的方法后,我找到项目下的.mrp文件,里面有一行显示 Number of DSP48E1s: 496 out of 480 103%,也就是说我使用的 XC6V1x130t 型号FPGA只有480个DSP48E1,但是我使用了496个。
我的项目中用到了4个fir滤波器,都是160阶的,而且其中两个系数对称,另外两个系数不对称,我在代码中尝试添加其中的某个滤波器,发现系数对称的滤波器会占用80个DSP48E1,系数不对称的fir滤波器会占用160个DSP48E1,并且结合查阅到的资料,DSP48E1主要是用来做乘法器使用的,这就非常合理了,对称的系数可以使用如下结构实现,确实节省一半的乘法器。实际上,fir滤波器的底层实现就是通过多个DSP48E1级联实现的。可以参考。
于是,我适当减少了fir滤波器的系数个数,最终可以成功实现。
二、学习DSP48E1
图中带*号的信号是级联专用信号,只在级联时使用,用户逻辑访问不了。我们只需要关注A、B、C、D、P、INMODE、OPMODE、ALUMODE这几个信号的使用即可。
INMODE
上图主要反映了INMODE与打拍寄存器的关系,可以用下面两个表概括,INMODE一般配置为7’b0000101,做乘法器使用。
OPMODE
X、Y、Z输出与OPMODE的关系如下表所示。
ALUMODE
最终P端口输出与ALUMODE的关系如下所示,其中的CIN就是48位输入信号C。
例程
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/06/19 16:58:05
// Design Name:
// Module Name: tb_DSP48E1
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_DSP48E1();
reg R_clk;
reg R_reset;
reg[29:0] R_A;
reg[24:0] R_D;
reg[47:0] R_C;
reg[17:0] R_B;
wire[47:0] W_P;
wire[47:0] W_PCIN;
reg[4:0] INMODE;
reg[6:0] OPMODE;
reg[3:0] ALUMODE;
reg[3:0] R_num;
initial begin
R_clk = 1'b0;
R_reset = 1'b1;
R_A = 30'd100;
R_B = 18'd2;
R_C = 48'd2000;
R_D = 25'd200;
R_num = 4'd0;
OPMODE = 7'b0000101; // X-M Y-M Z-0
INMODE = 5'b00101; // (D+A1) * B2 这三个输出刚好对齐,第三拍得到运算结果
ALUMODE = 4'b0000; // X+Y+Z+C
#100 R_reset = 1'b0;
end
always#5 R_clk = ~R_clk;
always @(posedge R_clk) begin
if(R_reset)begin
R_A <= 30'd100;
R_B <= 18'd2;
R_C <= 48'd2000;
R_D <= 25'd200;
R_num <= 4'd0;
end
else if(R_num < 9)begin
R_num <= R_num + 1'b1;
R_A <= R_A + 1'b1;
R_B <= R_B + 1'b1;
R_C <= R_C + 1'b1;
R_D <= R_D + 1'b1;
end
else begin
OPMODE <= 7'b0110101; // X-M Y-M Z-C
R_A <= R_A + 1'b1;
R_B <= R_B + 1'b1;
R_C <= R_C + 1'b1;
R_D <= R_D + 1'b1;
end
end
DSP48E1 #(
// Feature Control Attributes: Data Path Selection
.A_INPUT("DIRECT"), // Selects A input source, "DIRECT" (A port) or "CASCADE" (ACIN port)
.B_INPUT("DIRECT"), // Selects B input source, "DIRECT" (B port) or "CASCADE" (BCIN port)
.USE_DPORT("TRUE"), // Select D port usage (TRUE or FALSE)
.USE_MULT("MULTIPLY"), // Select multiplier usage ("MULTIPLY", "DYNAMIC", or "NONE")
.USE_SIMD("ONE48"), // SIMD selection ("ONE48", "TWO24", "FOUR12")
// Pattern Detector Attributes: Pattern Detection Configuration
.AUTORESET_PATDET("NO_RESET"), // "NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH"
.MASK(48'h3fffffffffff), // 48-bit mask value for pattern detect (1=ignore)
.PATTERN(48'h000000000000), // 48-bit pattern match for pattern detect
.SEL_MASK("MASK"), // "C", "MASK", "ROUNDING_MODE1", "ROUNDING_MODE2"
.SEL_PATTERN("PATTERN"), // Select pattern value ("PATTERN" or "C")
.USE_PATTERN_DETECT("NO_PATDET"), // Enable pattern detect ("PATDET" or "NO_PATDET")
// Register Control Attributes: Pipeline Register Configuration
.ACASCREG(1), // Number of pipeline stages between A/ACIN and ACOUT (0, 1 or 2)
.ADREG(1), // Number of pipeline stages for pre-adder (0 or 1)
.ALUMODEREG(1), // Number of pipeline stages for ALUMODE (0 or 1)
.AREG(1), // Number of p