进行综合 Vivado "A process triggered every clock cycle will not have functionality every clock cycle"

Making Vivado Synthesis "A process triggered every clock cycle will not have functionality every clock cycle"

这是仅进行加法和乘法运算的 ALU 代码。加法在同一个时钟周期内处理,但乘法结果必须延迟 3 个时钟周期。

module my_addmul(
    //control signals
    input i_clk,
    input i_rst,
    input i_en,

    //add=01, mul=10
    input [1:0] i_op,

    //input and output registers
    input [31:0] i_A,
    input [31:0] i_B,
    output [31:0] o_D,

    //to signal if output is valid
    output o_done
    );


 //registers to save output
       reg [31:0] r_D;
       reg [63:0] r_mul;//(*keep="true"*)
       reg r_mul_done;
       reg r_mul_done2;
       reg r_done;

       //updating outputs
       assign o_D = r_D;
       assign o_done = r_done;


   always @ (posedge i_clk)    
   begin
       r_done <= 0;
       r_mul_done <= 0;

       if (i_rst) begin

           r_D <= 0;
           r_mul <= 0;
           r_mul_done <= 0;
           r_mul_done2 <= 0;

       end else if (i_clk == 1) begin

           if (i_en == 1) begin

               //addition - assignment directly to OP registers
               if (i_op == 01) begin
                   r_done <= 1;
                   r_D <= i_A + i_B;

               //multiplication - indirect assignment to OP registers
               end else if (i_op == 2'b10) begin
                   r_mul <= i_A * i_B;
                   r_mul_done <= 1;
               end
           end

           //1-clock cycle delay
           r_mul_done2 <= (r_mul_done == 1) ? 1 : 0;

           //updating outputs in the 3rd cycle
           if (r_mul_done2 == 1) begin
               r_D <= r_mul[31:0];
               r_done <= 1;
           end
       end
   end   
endmodule

问题是,如果不使用keep属性,存储乘法输出直到第3个时钟周期的r_mul寄存器被优化掉。我阅读了这个问题并意识到 Vivado 是这样想的: "If the multiplication happens every clock cycle, the r_mul is over-written before it is sent to output. Therefore, it is a register being written but not read, Lets remove it!" 由于我在测试台中插入了 3 个时钟周期等待,因此仿真结果始终是准确的。我想知道执行此操作的 "Proper" 方法是什么,这样我就不必使用 keep 属性。这是一个不错的解决方案,但我认为应该学习有用的技术,这样就不必使用 hack 了。欢迎任何想法或讨论。

如果我想延迟信号,我可能会为此插入触发器。您可能会像处理 mul_done 信号一样翻牌 mul_output。此外,最好有不同的 always 块来做同样的事情。您可以查看下面的代码,但它可能有问题,因为我没有 simulated/synthesized -

module my_addmul(
    //control signals
    input i_clk,
    input i_rst,
    input i_en,

    //add=01, mul=10
    input [1:0] i_op,

    //input and output registers
    input [31:0] i_A,
    input [31:0] i_B,
    output [31:0] o_D,

    //to signal if output is valid
    output o_done
    );


 //registers to save output
       reg [31:0] r_D;
       reg [63:0] r_mul;//(*keep="true"*)
       reg r_mul_1;
       reg r_mul_2;
       reg r_mul_done;
       reg r_mul_done2;
       reg r_done;

       //updating outputs
       assign o_D = r_D;
       assign o_done = r_done;


   always @ (posedge i_clk)    
   begin
       r_done <= 0;
       r_mul_done <= 0;

       if (i_rst) begin

           r_D <= 0;
           r_mul <= 0;
           r_mul_done <= 0;
           r_mul_done2 <= 0;

       end else if (i_clk == 1) begin

           if (i_en == 1) begin

               //addition - assignment directly to OP registers
               if (i_op == 01) begin
                   r_done <= 1;
                   r_D <= i_A + i_B;

               //multiplication - indirect assignment to OP registers
               end else if (i_op == 2'b10) begin
                   r_mul <= i_A * i_B;
                   r_mul_done <= 1;
               end
           end
       end
   end

     always @ (posedge i_clk)
       begin
         if (i_rst)
           begin
             r_mul_1 <= 0;
             r_mul_done2 <= 0;
           end
         else
           begin
             r_mul_1 <= r_mul;
             r_mul_done2 <= r_mul_done;
           end
       end

     always @ (posedge i_clk)
       begin
         if (i_rst)
           begin
             r_D <= 0;
             r_done <= 0;
           end
         else
           begin
             r_D <= r_mul_1;
             r_done <= r_mul_done2;
           end
       end

endmodule