Verilog:在always块中等待模块逻辑评估

时间:2017-01-16 14:25:06

标签: verilog hdl hardware-design

我想在always块中使用另一个模块的输出。 目前使此代码工作的唯一方法是在 pi_in 分配后添加#1 ,以便有足够的时间让Pi完成。

模块pLayer.v的相关部分:

jQuery("#tableWithId").on("click", ".single_add_to_cart_button", function(e) {
    e.preventDefault();
    var url = jQuery(this).data('href');
    window.open(url, '_blank');
    return false;
});

Modllue Pi.v

Pi pi(pi_in,pi_out);

always @(*)
begin

    for(i=0; i<constants.nSBox; i++) begin
        for(j=0; j<8; j++) begin
            x               = (state_value[(constants.nSBox-1)-i]>>j) & 1'b1;
            pi_in           = 8*i+j;#1; /* wait for pi to finish */
            PermutedBitNo   = pi_out;
            y               = PermutedBitNo>>3;

            tmp[(constants.nSBox-1)-y] ^= x<<(PermutedBitNo-8*y);
        end
    end
    state_out = tmp;
end

在最终实施中不应使用延迟,那么有没有使用#1 的另一种方式?

本质上我希望只有在Pi模块以pi_in(= 8 * i + j)作为输入完成其作业后才能评估 PermutedBitNo = pi_out 。 我怎么能阻止这条线直到Pi完成?

我必须使用时钟吗?如果是这样的话,请给我一个提示。

更新

根据Krouitch的建议我修改了我的模块。这是更新版本:

来自pLayer.v:

`include "constants.v" 

module Pi(in, out);
input  [31:0]   in;
output [31:0]   out;
reg [31:0] out;

always @* begin
    if (in != constants.nBits-1) begin
        out = (in*constants.nBits/4)%(constants.nBits-1);
    end else begin
        out = constants.nBits-1;
    end
end
endmodule

来自Pi.v:

    Pi pi(.clk (clk),
      .rst (rst),
      .in  (pi_in),
      .out (pi_out));

counter c_i (clk, rst, stp_i, lmt_i, i);
counter c_j (clk, rst, stp_j, lmt_j, j);

always @(posedge clk)
begin
    if (rst) begin
        state_out = 0;
    end else begin
        if (c_j.count == lmt_j) begin
            stp_i = 1;
        end else begin
            stp_i = 0;
        end

        // here, the logic starts
        x               = (state_value[(constants.nSBox-1)-i]>>j) & 1'b1;
        pi_in           = 8*i+j;
        PermutedBitNo   = pi_out;
        y               = PermutedBitNo>>3;
        tmp[(constants.nSBox-1)-y] ^= x<<(PermutedBitNo-8*y);

        // at end
        if (i == lmt_i-1)
            if (j == lmt_j) begin
                state_out = tmp;
            end
    end
end
endmodule

module counter(
  input  wire clk,
  input  wire rst,
  input  wire stp,
  input  wire [32:0] lmt,
  output reg  [32:0] count
);

always@(posedge clk or posedge rst)
    if(rst)
        count <= 0;
    else if (count >= lmt)
        count <= 0;
    else if (stp)
        count <= count + 1;
endmodule

1 个答案:

答案 0 :(得分:3)

这是你在这里的一个很好的软件......

这种语言描述硬件的事实并没有帮助。

在verilog中,你写的东西会在零时间内模拟。这意味着ij上的循环也将在零时间内完成。这就是为什么当你强制循环使用#1等待1个时间单位时你看到的东西。

是的,你必须使用时钟

为了让您的系统正常工作,我必须实现ij的计数器。

带复位的计数器同步计数器可以这样写:

`define SIZE 10
module counter(
  input  wire clk,
  input  wire rst_n,
  output reg [`SIZE-1:0] count
);

always@(posedge clk or negedge rst_n)
  if(~rst_n)
    count <= `SIZE'd0;
  else
    count <= count + `SIZE'd1;
endmodule

您指定仅在处理pi_out时才对pi_in进行采样。 在数字设计中,这意味着您要在发送pi_in的那一刻与您正在阅读pi_out的那一刻之间等待一个时钟周期。

在我看来,最好的解决方案是让您的pi模块顺序,然后将pi_out视为注册。

要做到这一点,我会做以下事情:

module Pi(in, out);
input           clk;
input  [31:0]   in;
output [31:0]   out;
reg [31:0]  out;
wire        clk;
wire [31:0] out_comb;
always @* begin
  if (in != constants.nBits-1) begin
    out_comb = (in*constants.nBits/4)%(constants.nBits-1);
  end else begin
    out_comb = constants.nBits-1;
  end
end

always@(posedge clk)
  out <= out_comb;

endmodule

如果您使用ij以及最后pi模块的计数器,很快就会发生这种情况:

  1. 在新的时钟周期,ij会发生变化 - &gt; pi_in会在同一时间(模拟中)相应更改
  2. 在下一个时钟周期out_comb将存储在out中,然后您将pi_out的新值比pi_in晚一个时钟周期
  3. 修改

    首先,在编写(同步)进程时,我建议您只按进程处理1个寄存器。它将使您的代码更清晰,更易于理解/调试。

    另一个提示是将组合电路与顺序分开。它还可以使您的代码更清晰,更易理解。

    如果我以前面写过的计数器为例,它看起来像是:

    `define SIZE 10
    module counter(
      input  wire clk,
      input  wire rst_n,
      output reg [`SIZE-1:0] count
    );
    
    //Two way to do the combinatorial function
    //First one
    wire [`SIZE-1:0] count_next;
    assign count_next = count + `SIZE'd1; 
    
    //Second one  
    reg [`SIZE-1:0] count_next;
    always@*
      count_next = count + `SIZE'1d1;
    
    
    always@(posedge clk or negedge rst_n)
      if(~rst_n)
        count <= `SIZE'd0;
      else
        count <= count_next;
    
    
    endmodule
    

    在这里,我看到为什么你还有一个比预期更多的周期,这是因为你在同步过程中放置​​了控制pi模块的组合电路。这意味着将发生以下情况:

    1. 首先评估clk正边ij
    2. 下一个周期,评估pi_in
    3. 下一个周期,pi_out被捕获
    4. 所以它需要2个周期才有意义。

      要纠正你应该从同步过程中取出'逻辑'部分。正如您在评论中所述,这是逻辑,所以它不应该在同步过程中。

      希望有所帮助