我试图实现一个简单的多周期处理器,但我遇到了一些我似乎无法解决的问题。代码如下。我现在正在尝试实现这一目标。当我完成后,我将开始实施指令和ALU。但是,我在这一点上陷入困境。在下面的代码中,我意识到永远不会使用data_memory
(如果我能解决这个问题,我会到那里),现在还没有使用某些输入和输出,{{1 }和x1
只是我创建的变量,用于查看真正发生的事情。 x2
文件中的内容是不言而喻的。
我使用Altera Quartus 15.1和Verilog2001。由于未使用的东西,这段代码会编译好一些警告,但是当我尝试用20ns的时钟周期模拟它时会出现错误,说明"错误(可抑制):( vsim-3601)时间达到迭代限制5000 100 ns"。它还说这是可以抑制的,但我不知道如何压制它们。
我查找了这个错误,并且我了解到这种情况正在发生,因为在某些时候代码会进入无限循环。我试图通过创建另一个变量definitions.v
来解决这个问题。通过将ok
设置为ok
开始循环,在完成该周期的微操作后,我将0
设置为ok
。因此,循环不会在不正确的时间发生变化(就像锁定循环一样)。不幸的是,这导致了同样的错误。
我也尝试了另一种流程。我创建了一个循环变量,而不是1
和cycle
。在时钟的每个上升沿,我检查当前状态并做相应的事情,然后设置下一步的周期。示例:
next_cycle
这也很好编译,可以毫无错误地模拟!但是,功能不正确,会产生奇怪的(或意外的)结果。我发现其他方法更直观。所以我会努力让它发挥作用。
我该如何解决/实施?
always @ (posedge clk) begin
case (cycle)
3'b000: begin
MAR <= PC;
cycle <= 3'b001;
ire <= 1'b1;
x2 <= 2'b00;
3'b001: begin
...
...
答案 0 :(得分:1)
当我们在verilog中写入always @(signal)
时,指定的灵敏度列表,在该信号的变化时触发逻辑。这可能导致对硬件实际工作方式的误解。我们在边缘上改变的唯一硬件是触发器,你需要指定posedge或negedge关键字。
合成always @(signal)
时,实际上会得到一个组合块,其效果类似于always @(*)
。这是一个自动敏感列表。
因此,从评论中我们将看到这一小段代码:
always @ (*) begin
case (cycle)
3'b011: begin
ok = 0;
if (OPC==5'b01011) x1 = 2'b11;
PC = PC + 1;
next_cycle = 3'b000;
x2 = 2'b11;
ok = 1;
这是一个组合块,在模拟器中触发任何可以影响输出变化的东西。大多数信号被分配给静态信号,或其他已知的带有输出循环的值。
PC = PC +1;
上述行虽然更新了PC的值,但是PC的这个新值应该触发组合块重新评估,再次点击PC增量等等。这一切都发生在delta内部模拟器的循环。
使用像Verilog这样的硬件描述语言(HDL),我们必须记住我们正在描述并行语句,而不是连续执行的代码行。