Я новичок в использовании 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