Verilog 为什么添加一个操作会导致我的逻辑元素数量猛增?

Verilog 为什么添加一个操作会导致我的逻辑元素数量猛增?,verilog,fpga,hdl,Verilog,Fpga,Hdl,我正在用Verilog设计一个464阶FIR滤波器,用于Altera DE0 FPGA。我有(我相信是)一个有效的实现;然而,有一个小问题确实让我很头疼。基本操作如下:从微控制器发送一个10位数字,并存储在数据存储中。然后,FPGA过滤数据,如果数据接近100,则点亮LED1,如果数据接近50,则熄灭LED1。当数据既不是100也不是50,或者过滤器尚未填充缓冲区时,LED2打开 在本规范中,系数(已预先提供)已乘以2^15,以便将其表示为整数。因此,我需要将最终输出Y除以2^15。我使用了一个

我正在用Verilog设计一个464阶FIR滤波器,用于Altera DE0 FPGA。我有(我相信是)一个有效的实现;然而,有一个小问题确实让我很头疼。基本操作如下:从微控制器发送一个10位数字,并存储在数据存储中。然后,FPGA过滤数据,如果数据接近100,则点亮LED1,如果数据接近50,则熄灭LED1。当数据既不是100也不是50,或者过滤器尚未填充缓冲区时,LED2打开

在本规范中,系数(已预先提供)已乘以2^15,以便将其表示为整数。因此,我需要将最终输出Y除以2^15。我使用了一个shift来实现这一点,因为它应该是(?)最有效的方法。然而,这条单行导致我的逻辑元素数量从没有它的11000个跃增到35000多个。Altera DE0使用Cyclone III FPGA,该FPGA仅可容纳约15k逻辑元件。我试过在组合逻辑块和顺序逻辑块中进行,两者都有相同的问题

为什么这一看似简单的单一操作会导致如此严重的通货膨胀?我将包括我的代码,我确信它不是最有效的,也不是最干净的。我根本不关心优化此设计的性能或面积/密度。我只是想把它安装到FPGA上,这样它就可以运行了。我在HDL设计方面不是很有经验,这是迄今为止我需要处理的最复杂的项目。值得注意的是,我没有完全删除y,而是用
assign YY=y替换了“bad”行

请注意:为了理智起见,我没有包括所有的系数。我知道可能有一种比使用case语句更好的方法,但它就是这样来的,我真的不想将464个元素重新定位到参数声明中,等等

module lab5 (LED1, LED2, handshake, reset, data_clock, datastore, bit_out, clk); 

    // NUMBER OF COEFFICIENTS (465)
    //  (Change this to a small value for initial testing and debugging, 
    //  otherwise it will take ~4 minutes to load your program on the FPGA.)
    parameter NUMCOEFFICIENTS = 465;

    // DEFINE ALL REGISTERS AND WIRES HERE
    reg         [11:0]  coeffIndex;     // Coefficient index of FIR filter
    reg signed  [16:0]  coefficient;    // Coefficient of FIR filter for index coeffIndex
    reg signed  [16:0]  out;            // Register used for coefficient calculation
    reg signed [31:0] y;
    wire signed [7:0] YY;
    reg [9:0] xn [0:464];               // Integer array for holding x
    integer i;
    output reg LED1, LED2;
    // Added values from part 1
    input reset, handshake, clk, data_clock, bit_out;
    output reg [9:0] datastore;
    integer k; 
    reg sent;

    initial
    begin
        sent = 0;
        i=0;
        datastore = 10'b0000000000;
        y=0;
        LED1 = 0;
        LED2 = 0;
        for (i=0; i<NUMCOEFFICIENTS; i=i+1)
        begin
            xn[i] = 0;
        end
    end


always@(posedge data_clock)
begin
    if(handshake)
    begin
        if(bit_out)
        begin
            datastore = datastore >> 1; 
            datastore [9] = 1;
        end
        else
        begin
            datastore = datastore >> 1;
            datastore [9] = 0;
        end
    end
end


always@(negedge clk)
begin
    if (!handshake )
    begin
        if(!sent)
        begin
            y=0;

            for (i=NUMCOEFFICIENTS-1; i > 0; i=i-1) //shifts coeffecients
            begin
                xn[i] = xn[i-1];
            end

            xn[0] = datastore;      

            for (i=0; i<NUMCOEFFICIENTS; i=i+1)
            begin   
            // Calculate coefficient based on the coeffIndex value. Note that coeffIndex is a signed value!
            // (Note: These don't necessarily have to be blocking statements.)
            case ( 464-i )

                12'd0: out = 17'd442;   // This coefficient should be multiplied with the oldest input value
                12'd1: out = -17'd373;
                12'd2: out = -17'd169;
                ...
                12'd463: out = -17'd373; //-17'd373
                12'd464: out = 17'd442;  //17'd442
                // This coefficient should be multiplied with the most recent data input

                // This should never occur.
                default: out = 17'h0000;        
        endcase

            y = y + (out * xn[i]);

            end

            sent = 1;

        end
    end
    else if (handshake)
    begin
        sent = 0;
    end
end     

assign YY = (y>>>15); //THIS IS THE LINE THAT IS CAUSING THE ISSUE!

always @(YY)
begin

            LED1 = 0;
            LED2 = 1;

            if ((YY >= 40) && (YY <= 60))
            begin
                LED1 <= 0;
                LED2 <= 0;
            end
            if ((YY >= 90) && (YY <= 110))
            begin
                LED1 <= 1;
                LED2 <= 0;
            end
end 
endmodule
模块lab5(LED1、LED2、握手、复位、数据时钟、数据存储、位输出、时钟);
//系数数(465)
//(对于初始测试和调试,将其更改为较小的值,
//否则,在FPGA上加载程序需要约4分钟。)
参数NUMCOEFFICIENTS=465;
//在此处定义所有寄存器和导线
reg[11:0]系数指数;//FIR滤波器的系数指标
reg符号[16:0]系数;//指数系数指数的FIR滤波器系数
reg已签出[16:0];//用于系数计算的寄存器
注册签名[31:0]y;
签署于[7:0]YY的电报;
注册号[9:0]xn[0:464];//用于保存x的整数数组
整数i;
输出调节器LED1、LED2;
//第1部分的附加值
输入复位、握手、时钟、数据时钟、位输出;
输出reg[9:0]数据存储;
整数k;
注册发送;
最初的
开始
发送=0;
i=0;
数据存储=10'b0000000000;
y=0;
LED1=0;
LED2=0;
对于(i=0;i>1;
数据存储[9]=1;
结束
其他的
开始
数据存储=数据存储>>1;
数据存储[9]=0;
结束
结束
结束
始终@(negedge clk)
开始
如果(!握手)
开始
如果(!已发送)
开始
y=0;
对于(i=NUMCOEFFICIENTS-1;i>0;i=i-1)//移位系数
开始
xn[i]=xn[i-1];
结束
xn[0]=数据存储;
for(i=0;i>>15);//这是导致问题的行!
始终@(YY)
开始
LED1=0;
LED2=1;

如果((YY>=40)&(YY你几乎可以肯定地看到综合优化的效果

下一行是唯一使用
y
的地方:

assign YY = (y>>>15); //THIS IS THE LINE THAT IS CAUSING THE ISSUE!
如果删除这一行,所有输入到
y
(包括
out
xn
)的逻辑都将被删除。在Altera上,您需要仔细查看地图报告,该报告将包含Quartus删除的所有逻辑及其原因的信息(隐藏在一百万其他内容中)

从端口连接性检查开始,它将告诉您是否有任何输入或输出处于高电平或低电平或悬空状态。查看在合成期间删除的寄存器部分和删除的寄存器触发进一步的寄存器优化

您可以尝试在QSF中使用以下命令,强制Quartus不删除冗余逻辑:

set_instance_assignment -name preserve_fanout_free_node on -to reg
set_instance_assignment -name preserve_register on -to foo

然而,在您的情况下,正确的解决方案似乎是重新考虑代码,而不是试图保留冗余逻辑。我怀疑您希望研究使用存储系数。

您几乎肯定看到了合成优化的效果

下一行是唯一使用
y
的地方:

assign YY = (y>>>15); //THIS IS THE LINE THAT IS CAUSING THE ISSUE!
如果删除这一行,所有输入到
y
(包括
out
xn
)的逻辑都将被删除。在Altera上,您需要仔细查看地图报告,该报告将包含Quartus删除的所有逻辑及其原因的信息(隐藏在一百万其他内容中)

从端口连接性检查开始,它将告诉您是否有任何输入或输出处于高电平或低电平或悬空状态。查看在合成期间删除的寄存器部分和删除的寄存器触发进一步的寄存器优化

您可以尝试在QSF中使用以下命令,强制Quartus不删除冗余逻辑:

set_instance_assignment -name preserve_fanout_free_node on -to reg
set_instance_assignment -name preserve_register on -to foo

然而,在您的情况下,正确的解决方案似乎是重新考虑代码,而不是试图保留冗余逻辑。我怀疑您希望研究使用存储系数。

您几乎肯定看到了合成的效果