2

I want to use the output of another module inside an always block. Currently the only way to make this code work is by adding #1 after the pi_in assignment so that enough time has passed to allow Pi to finish.

Relevant part from module 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

Delays should not be used in the final implementation, so is there another way without using #1?

In essence i want PermutedBitNo = pi_out to be evaluated only after the Pi module has finished its job with pi_in (=8*i+j) as input. How can i block this line until Pi has finished?

Do i have to use a clock? If that's the case, please give me a hint.

update:

Based on Krouitch suggestions i modified my modules. Here is the updated version:

From 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
);

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

From 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

always@(posedge clk) begin
    if (rst)
        out <= 0;
    else
        out <= out_comb;
end
4

1 回答 1

3

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

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

在 Verilog 中,您编写的内容将在零时间内进行模拟。这意味着您的循环将在ij时间内完全完成。这就是为什么当你强制循环等待 1 个时间单位时你会看到一些东西#1

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

为了使您的系统正常工作,您必须为我看到的东西i实施计数器。j

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

`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

i如果你对andj和最后一个模块使用计数器,很快pi就会发生这种情况:

  1. 在一个新的时钟周期,i并且j会改变-->pi_in会同时改变(在模拟中)
  2. 在下一个时钟周期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;
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被捕获

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

要纠正这一点,您应该从同步过程中取出“逻辑”部分。正如您在评论中所说,这是逻辑,因此它不应该处于同步过程中。

希望能帮助到你

于 2017-01-16T15:11:20.737 回答