我正在使用以下原型实现一个简单的程序计数器加法器:
module program_counter(input enable_count,
input enable_overwrite,
input[31:0] overwrite_value,
output[31:0] out);
当使用Icarus Verilog进行模拟时,我在第一个时钟周期内获得无限循环,其中禁止重写并启用计数,因此内部寄存器由PC加法器(PC + 4)的输出提供。
我将问题简化为基本的代码片段,其中D触发器用作1位寄存器:
module register(input in, input set, output out);
wire not_in;
wire q0;
wire not_q0;
wire not_q;
nand (q0, in, set);
not (not_in, in);
nand (not_q0, not_in, set);
nand (out, q0, not_q);
nand (not_q, not_q0, out);
endmodule
module test;
reg clock;
reg in;
wire out;
wire not_out;
xor (x_out, out, 1); // add
or (muxed_out, x_out, in); // mux
register r(muxed_out, clock, out);
initial
begin
$dumpfile("test.vcd");
$dumpvars(0, test);
$display("\tclock,\tin,\tout");
$monitor("\t%b,\t%x,\t%b",
clock, in, out);
#0 assign in = 1; // erase register
#0 assign clock = 1;
#1 assign in = 0;
#1 assign clock = 0;
#2 assign clock = 1;
#3 assign clock = 0;
#4 assign clock = 1;
end
endmodule
模拟卡住后,VCD输出不会显示任何状态变化。
我的猜测是,在特定的时间点,加法器不断地输入不同的值(连续添加),因此它不稳定,模拟器正在等待值被修复并卡住。
这种设计是否正确(即可以合成并且应该起作用)?
答案 0 :(得分:0)
有一个组合循环:'注册'的输出。在测试中通过xor /或gate反馈回其输入。您基本上创建了ring oscillator。
如果在寄存器中添加以下代码,您可以看到这种情况:
always @(in) $display("@%d: in = %d", $time, in);
当您运行解释器时,您会看到一堆这些:
@ 1: in = 1
@ 1: in = 0
@ 1: in = 1
@ 1: in = 0
您似乎正试图在“注册”中设置启用的锁定功能。这是你的意图吗?边沿触发触发器是同步设计中的常规做法。您需要两个背对背的锁存器才能做到这一点,但在Verilog中执行此操作的标准(并且更容易)是这样的:
reg my_flop;
always @(posedge clk)
my_flop <= input;
如果你真的想要一个闩锁,可以这样推断(但这些往往容易出错并且通常不鼓励):
always @(clk, input)
begin
if (clk)
my_flop = input;
end
您是否有理由尝试使用门手动创建这些内容?