генерировать внутри генерировать verilog + ошибка рядом с генерировать (veri - 1137)

Написание кода Verilog в течение нескольких дней, и у меня есть один вопрос: «Можем ли мы написать блок генерации внутри блока генерации»? Я пишу RTL примерно так:

Where 'n' is a parameter.
reg [DATA_WIDTH:0] flops [n-1:0];

generate
  if (n > 0) begin
    always @(posedge clk) begin
      if (en) begin
        flops[0] <= mem[addr];
      end
     end
     generate
       genvar i;
       for (i = 1; i <= n ; i = i + 1) begin
         always @(posedge clk) begin
           flops[i] <= flops[i-1];
         end
       end
     endgenerate
     always @(flops[n - 1])
       douta = flops[n - 1];
   else
     always @(posedge clk) begin
       if (en) begin
         primary_output = mem[addr];
       end
     end
   end
endgenerate

При компиляции приведенного выше кода я получаю:

ERROR: syntax error near generate (VERI-1137)

Не уверен, почему. Целью этого RTL является создание конвейера из n отказов на выходе проекта.

Допустим, n равно 2, тогда схема должна стать:

flop1-> flop2-> primary output of design

flop1 и flop2 — вновь созданные флопы.


person Hemant Bhargava    schedule 02.08.2016    source источник


Ответы (1)


Вы очень далеко от того места, где должны быть.

Verilog — это не язык программирования; это язык описания оборудования. Вы моделируете оборудование как сеть одновременных процессов. Каждый процесс моделирует небольшой аппаратный элемент, такой как счетчик, конечный автомат, регистр сдвига, некоторая комбинационная логика... В Verilog каждый процесс закодирован как блок always. Таким образом, одно выражение always никогда не может появляться внутри другого; это бессмысленно.

Во-вторых, generate — довольно специализированный оператор. Вы используете его, когда вам нужно большое или переменное количество одновременных процессов. Это не часто требуется, поэтому generate не является обычным явлением, но полезно, когда это необходимо. Вам не нужен оператор генерации для реализации параметризуемого сдвигового регистра. А поскольку блок always является параллельным оператором, он находится внутри оператора generate, а а не наоборот.

Я не знаю, каково именно ваше намерение, потому что я подозреваю, что этот код не делает именно то, что вы хотите. Однако он реализует параметризуемый сдвиговый регистр длины n и ширины DATA_WIDTH+1 (вы действительно это имели в виду?), активируемый вводом en:

module N_FLOPS #(n = 2, DATA_WIDTH = 8) (input [DATA_WIDTH:0] dina, input clk, en, output [DATA_WIDTH:0] douta);

  reg [DATA_WIDTH:0] flops [n-1:0];

  always @(posedge clk)
    if (en)
      begin : SR
        integer i;
        flops[0] <= dina;
        for (i = 1; i <= n ; i = i + 1) 
          flops[i] <= flops[i-1];
      end

  assign douta = flops[n-1];

endmodule

http://www.edaplayground.com/x/3kuY

Как видите, никаких generate утверждений не требуется. Этот код соответствует этому шаблону, которого достаточно для любой последовательной логики без асинхронного сброса:

always @(posedge CLOCK)  // or negedge
  begin
    // do things that occur on the rising (or falling) edge of CLOCK
    // stuff here gets synthesised to combinational logic on the D input
    // of the resulting flip-flops
  end
person Matthew Taylor    schedule 02.08.2016
comment
К вашему сведению: SystemVerilog позволяет присваивать многомерные массивы в одном операторе. Поэтому вы можете пропустить цикл for с always @(posedge clk) begin flop[0] <= dina; if (n>1) flops[n-1:1] <= flops[n-2:0]; end - person Greg; 02.08.2016