2017-01-16 200 views
2

我想使用always块中另一个模块的输出。 目前,以使此代码工作的唯一途径是通过增加#1 pi_in分配后,使有足够的时间已经过去了,让曹丕完成。Verilog:在always块中等待模块逻辑评估

有关部分从模块pLayer.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 

Modllue Pi.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 

延误的,应当不会在最终实现中使用,所以有不使用#1另一种方式

在本质上我想PermutedBitNo = pi_out后才裨模块完成其与pi_in(= 8 * I + J)作为输入作业进行评估。 如何在Pi完成之前阻止此行?

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

更新:

基于Krouitch建议我修改的模块。以下是更新版本:

从pLayer.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 
); 

[email protected](posedge clk or posedge rst) 
    if(rst) 
     count <= 0; 
    else if (count >= lmt) 
     count <= 0; 
    else if (stp) 
     count <= count + 1; 
endmodule 

从Pi.v:

always @* begin 
    if (rst == 1'b1) begin 
     out_comb = 0; 
    end 
    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 

[email protected](posedge clk) begin 
    if (rst) 
     out <= 0; 
    else 
     out <= out_comb; 
end 

回答

3

这是一个不错的一块你在这里软件...

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

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

所以,是的,你必须使用一个时钟

为您的系统工作,你将必须实现计数器ij,因为我看到的东西。通过复位

计数器同步计数器可以写成这样:

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

[email protected](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作为注册。

这样做,我会做到以下几点:如果您使用计数器ij这最后pi模块

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 

[email protected](posedge clk) 
    out <= out_comb; 

endmodule 

很快,这是会发生什么:

  1. 在一个新的时钟周期,ij将会改变 - >pi_in会相应改变(模拟中)
  2. 在下一个cl玉珠周期out_comb将被存储在out,然后你将有pi_out新值一个时钟周期晚于pi_in

编辑

首先,写作时(同步)的过程,我会建议你只处理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; 
[email protected]* 
    count_next = count + `SIZE'1d1; 


[email protected](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被捕获

所以它是有道理的,它需要2个周期。

要纠正您应该从同步过程中除去“逻辑”部分。正如你在评论中所说的那样,它是逻辑的,所以它不应该在同步过程中。

希望它有帮助

+0

谢谢你,你的提示让我更进一步。 但是,现在我有问题,out_comb总是不是一个,但(出于某种原因)两个周期后。 所以当我想在tmp中使用PermuteBitNo时,它会返回不正确的结果。 – cie

+0

你可以附加你的文章吗? – Krouitch

+0

请注意,out_comb必须是一个reg,因为它被分配在always块中。另外我不知道你为什么使用否定重置。有没有特定的原因? – cie