输入的Verilog波形相同,但输出不同

Verilog waveform of inputs is identical, however, output is different

我目前正在尝试使用数据流建模在 Verilog 中实现一个 up/down 计数器。在尝试为计数器添加限制时(以便在达到限制时计数器将重置为适当的值)我偶然发现了一个错误。即使clear_q、清除和clear_s的波形相同,同样preset_q、预设和preset_s的波形相同,Q的行为, R、S不同,特别是Q与R、S不同。

Picture of Waveforms

值得注意的是,三个清除信号的上升沿与时钟的下降沿不对齐,但是,Q从0到F与三个清除信号的上升沿对齐。

从代码中可以清楚地看出,clear_q 和 clear_s 以及 preset_q 和 preset_s 之间的唯一区别是简单地包含了 "& 1 'b1”。 Q 从 0 到 F 的唯一方法是 preset_q 变低并且 clear_q 暂时变高,但是从波形来看 preset_q 保持高电平。

“&1'b1”的作用是临时模拟被注释掉的相等检查器

“& 1'b1”究竟有什么问题,或者还有其他问题?

limited_ud_counter.v

module limited_ud_counter(input clk, preset, clear, up, input[3:0] limit, output[3:0] Q);
  //wire[3:0] n;
  wire[3:0] Q, R, S;
  wire e, preset_p, clear_p;

  // assign n[0] = Q[0] ^ limit[0];
  // assign n[1] = Q[1] ^ limit[1];
  // assign n[2] = Q[2] ^ limit[2];
  // assign n[3] = Q[3] ^ limit[3];
  // assign e = !(n[0] | n[1] | n[2] | n[3]);

  assign e = 0;

  //(preset & clear & (!(e & up))) | (preset & !clear);
  //(preset & clear & !(e & (!up))) | (clear & !preset);

  assign preset_q = ((preset & clear) & 1'b1) | (preset & !clear);
  assign clear_q = ((preset & clear) & 1'b1) | (clear & !preset);

  assign preset_s = ((preset & clear)) | (preset & !clear);
  assign clear_s = ((preset & clear)) | (clear & !preset);

  //Q not showing expected behavior
  up_down_counter udc0(clk, preset_q, clear_q, up, Q);
  //R showing expected behavior
  up_down_counter udc1(clk, preset, clear, up, R);
  //S also showing expected behavior
  up_down_counter udc2(clk, preset_s, clear_s, up, S);

endmodule;

up_down_counter.v

module up_down_counter(input clk, preset, clear, up, output[3:0] Q);
  wire[2:0] jk_up, jk_down, jk;
  wire[3:0] Q_bar;

  assign jk_up[0] = Q[0] & up;
  assign jk_down[0] = Q_bar[0] & (!up);
  assign jk[0] = jk_up[0] | jk_down[0];

  assign jk_up[1] = Q[1] & jk_up[0];
  assign jk_down[1] = Q_bar[1] & jk_down[0];
  assign jk[1] = jk_up[1] | jk_down[1];

  assign jk_up[2] = Q[2] & jk_up[1];
  assign jk_down[2] = Q_bar[2] & jk_down[1];
  assign jk[2] = jk_up[2] | jk_down[2];

  jkff jkff0(clk, 1'b1, 1'b1, preset, clear, Q[0], Q_bar[0]);
  jkff jkff1(clk, jk[0], jk[0], preset, clear, Q[1], Q_bar[1]);
  jkff jkff2(clk, jk[1], jk[1], preset, clear, Q[2], Q_bar[2]);
  jkff jkff3(clk, jk[2], jk[2], preset, clear, Q[3], Q_bar[3]);
endmodule

jkff.v

module jkff(input clk, j, k, preset, clear, output q, q_bar);
  wire j_p, k_p, q_m, q_bar_m;

  assign j_p = !(j & q_bar & clk);
  assign k_p = !(k & q & clk);

  sr sr0(j_p, k_p, preset, clear, q_m, q_bar_m);
  gated_sr gsr0(!clk, q_m, q_bar_m, preset, clear, q, q_bar);
endmodule;

sr.v

//set, reset, preset, clear are active low
module sr(input set, reset, preset, clear, output q, q_bar);
  assign q = !(set & preset & q_bar);
  assign q_bar = !(reset & clear & q);
endmodule

gated_sr.v

//enable, set, and reset are active high; preset and clear are active low
module gated_sr(input enable, set, reset, preset, clear, output q, q_bar);
  wire set_p, reset_p;
  assign set_p = !(set & enable);
  assign reset_p = !(reset & enable);
  sr sr0 (
    .set (set_p),
    .reset (reset_p),
    .preset (preset),
    .clear (clear),
    .q (q),
    .q_bar (q_bar)
    );
endmodule

测试台代码

`include "limited_ud_counter.v"
`include "../UpDownCounter/up_down_counter.v"
`include "../JKFF/jkff.v"
`include "../GatedSR/gated_sr.v"
`include "../SR/sr.v"

module limited_ud_counter_tb;
  reg clk, preset, clear, up;
  reg[3:0] limit;
  wire[3:0] Q;

  always begin
    #5 clk = !clk;
  end

  initial begin
    $dumpfile("limited_ud_counter_tb.vcd");
    $dumpvars;
  
    clk = 1'b0;
    up = 1'b1;
    preset = 1'b1;
    clear = 1'b0;
    limit = 4'b1100;
    #12 clear = 1'b1;
 
    #200 $finish;
  end

  limited_ud_counter ludc0(clk, preset, clear, up, limit, Q);

endmodule

如果有帮助,这是使用 Icarus Verilog。

我已经解决了这个问题。发生的事情是在计算 preset_q 和 clear_q 的值时,有一段时间 preset_q 和 clear_q 都变低了。由于这些被送入 SR 锁存器,因此会发生错误。

同时 (t=12),preset_q 和 clear_q 是这样的:

  • preset_q = 1, clear_q = 0
  • preset_q = 0, clear_q = 0 <- 这就是问题所在
  • preset_q = 1, clear_q = 1

由于这些都是同时发生的,所以只有最终值在波形上可见。为了解决这个问题,我选择让预设和清除信号都变高,如果它们在 SR 锁存器级别都是低的话。