Неожиданное поведение симуляции в иверилоге на триггерном реплицирующем тактовом сигнале - PullRequest
0 голосов
/ 25 октября 2019

Я новичок в использовании icarus verilog, и я наткнулся на следующую проблему. У меня есть модуль, который просто воспроизводит свой тактовый сигнал в триггере. Это кажется довольно простым.

Последовательная логика реализует триггер (_q_clock_copy <= _d_clock_copy), а комбинационная логика выполняет копирование (_d_clock_copy = clock). </p>

Однако после моделирования _d_clock_copyдействительно дублирует часы, но _q_clock_copy плоский.

Кроме того, модуль содержит счетчик, и оба регистра триггера ведут себя, как и ожидалось (_q_counter отслеживает _d_counter со смещением в один такт). Почему _q_clock_copy / _d_clock_copy ведут себя по-разному?

Чего мне не хватает?

Ниже приведен весь код, который я моделирую с помощью iverilog последней версии (собранный из исходного кода с использованием github master на сегодняшний день, также пробовал ветку v10, тот же результат). Я генерирую FST-файл, который я смотрю на него с помощью gtkwave. _d_clock_copy - это то, что я ожидаю, но _q_clock_copy плоская.

Спасибо! PS: определенный шаблон q / d, используемый здесь, важен для меня, так как я пишу инструмент, который генерирует эти файлы verilog. Я не пытаюсь исправить это поведение, а хочу понять, почему это происходит.

////////////////////////////// module with potential error
//
// I would expect that _q_sdram_clock replicates
// what is in _d_sdram_clock (the input clock signal)
// instead it remains flat. 
// There is no such problem with _d_counter/_q_counter

module M_pll(
input clock,
input reset,
output [0:0] out_clock_copy
);

reg  [2:0] _d_counter,_q_counter;
reg  [0:0] _d_clock_copy,_q_clock_copy;
assign out_clock_copy = _q_clock_copy;

always @(posedge clock) begin
  if (reset) begin
    _q_counter <= 0;
    _q_clock_copy <= 0;
  end else begin
    _q_counter <= _d_counter;
    _q_clock_copy <= _d_clock_copy;
  end
end

always @* begin
  _d_counter = _q_counter+1;
  _d_clock_copy = clock;
end

endmodule

////////////////////////////// main
// 
// Counts and stops by signaling to testbench

module M_main(
output out_done,
input clock,
input reset
);

wire  [0:0] _w_clockgen_clock_copy;

reg  [7:0] _d_iter,_q_iter;
assign out_done = (_d_iter == 32);

always @(posedge clock) begin
  if (reset) begin
    _q_iter <= 0;
  end else begin
    _q_iter <= _d_iter;
  end
end

M_pll clockgen(
.clock(clock),
.reset(reset),
.out_clock_copy(_w_clockgen_clock_copy)
);

always @* begin
  _d_iter = _q_iter+1;
end
endmodule

////////////////////////////// testbench

module top;

reg clk;
reg rst_n;

initial begin
  clk = 1'b0;
  rst_n = 1'b0;
  $display("icarus framework started");
  $dumpfile("icarus.fst");
  $dumpvars(0,top);
  repeat(4) #5 clk = ~clk;
  rst_n = 1'b1;
  forever #5 clk = ~clk; // generate a clock
end

reg ready = 0;
reg [3:0] RST_d;
reg [3:0] RST_q;

always @* begin
  RST_d = RST_q >> 1;
end

always @(posedge clk) begin
  if (ready) begin
    RST_q <= RST_d;
  end else begin
    ready <= 1;
    RST_q <= 4'b1111;
  end
end

wire done_main;

M_main __main(
  .clock(clk),
  .reset(RST_d[0]),
  .out_done(done_main)
);

always @* begin
  if (done_main && !RST_d[0]) $finish;
end

endmodule
...