2017-01-16 14 views
2

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

Соответствующая часть из модуля 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) в качестве входных данных. Как я могу заблокировать эту строку до завершения 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 то, что вы пишете, будет имитировать в нулевое время. это означает, что ваш цикл на i и j будет полностью выполнен в нулевое время. Вот почему вы видите что-то, когда вы вынуждаете цикл ждать 1 раз с #1.

Итак, да, вы должны использовать часы.

Чтобы ваша система работала, вам нужно будет использовать счетчики для i и j, поскольку я вижу вещи.

Счетчик синхронного счетчика со сбросом может быть записана следующим образом:

`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 в качестве регистра.

Чтобы сделать это, я хотел бы сделать следующее:

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 

быстро, если использовать счетчики для i и j и последнего pi модуля это то, что будет происходить:

  1. на новом часы цикла, i и j изменится ->pi_in изменится соответственно в то же время (в моделировании)
  2. на следующей странице Ock цикл out_comb будут храниться в out, и тогда вы будете иметь новое значение pi_out один такт позже, чем pi_in

EDIT

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

Так имеет смысл, что он занимает 2 цикла.

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

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

+0

Спасибо, ваши советы дали мне еще один шаг. Однако теперь у меня есть проблема, что out_comb всегда не один, но (по какой-то причине) два цикла позже. поэтому, когда я хочу использовать PermuteBitNo в tmp, он возвращает неверные результаты. – cie

+0

Можете ли вы добавить свой пост с тем, что вы сделали? – Krouitch

+0

Обратите внимание, что out_comb должен быть регистром, потому что он назначается в всегда блоке. Также я не уверен, почему вы использовали сбрасываемые сбрасывания. Есть ли конкретная причина? – cie