输入的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 锁存器级别都是低的话。
我目前正在尝试使用数据流建模在 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 锁存器级别都是低的话。