进行Vivado综合"每个时钟周期触发一个进程,每个时钟周期都没有功能。

时间:2017-06-14 08:43:23

标签: verilog hdl synthesis vivado

这是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的想法是这样的:&#34;如果乘法发生在每个时钟周期,r_mul在被发送到输出之前会被覆盖。因此,它是一个写入但未读取的寄存器,请将其删除!&#34;由于我在测试台中插入3个时钟周期等待,因此仿真结果始终准确。我想知道什么是&#34;正确&#34;这样做的方式,所以我不必使用keep属性。这是一个很好的解决方案,但我认为应该学习有用的技术,所以不必使用黑客。任何想法或讨论欢迎。

1 个答案:

答案 0 :(得分:1)

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

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