Verilog: дождаться оценки логики модуля в блоке всегда

Я хочу использовать вывод другого модуля внутри всегда блока. В настоящее время единственный способ заставить этот код работать - это добавить #1 после присвоения pi_in, чтобы прошло достаточно времени, чтобы Pi завершил работу.

Соответствующая часть из модуля 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 завершил свою работу с pi_in (=8*i+j) в качестве ввода. Как я могу заблокировать эту строку, пока Пи не закончил?

Должен ли я использовать часы? Если это так, пожалуйста, дайте мне подсказку.

Обновить:

Основываясь на предложениях 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
);

always@(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

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

1 ответ

Это хорошая часть программного обеспечения у вас здесь...

Тот факт, что этот язык описывает аппаратные средства, тогда не помогает.

В verilog, то, что вы пишете, будет симулировать в нулевое время. это означает, что ваш цикл включен i а также j будет полностью сделано в нулевое время тоже. Вот почему вы видите что-то, когда вы заставляете цикл ждать 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 а также j и это последнее 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 положительный край i а также j будет оцениваться
  2. следующий цикл pi_in оценивается
  3. следующий цикл, pi_out захвачен

Так что имеет смысл, что требуется 2 цикла.

Чтобы исправить это, вы должны вынуть из синхронного процесса "логическую" часть. Как вы заявили в своих комментариях, это логика, поэтому она не должна быть в синхронном процессе.

Надеюсь, поможет

Другие вопросы по тегам