Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Verilog case语句中防止锁存_Verilog_Xilinx - Fatal编程技术网

在Verilog case语句中防止锁存

在Verilog case语句中防止锁存,verilog,xilinx,Verilog,Xilinx,我很难理解如何防止在Verilog项目中创建锁存。我理解正在创建锁存,因为我没有指定每个case语句中的所有信号发生了什么。然而,我不知道是否有任何方法可以避免这种情况(除了我目前使用的严厉方法) 我目前有两个移位寄存器,寄存器X和寄存器R。每个移位寄存器都有一个5位宽的控制总线,由有限状态机控制。为了使这些移位寄存器的管理更容易,我希望利用逐位操作来设置和取消设置控制总线位 例如,在状态done下,我需要为寄存器R取消设置shiftRight位。为此,我可以执行以下逐位操作: rRegiste

我很难理解如何防止在Verilog项目中创建锁存。我理解正在创建锁存,因为我没有指定每个case语句中的所有信号发生了什么。然而,我不知道是否有任何方法可以避免这种情况(除了我目前使用的严厉方法)

我目前有两个移位寄存器,
寄存器X
寄存器R
。每个移位寄存器都有一个5位宽的控制总线,由有限状态机控制。为了使这些移位寄存器的管理更容易,我希望利用逐位操作来设置和取消设置控制总线位

例如,在状态
done
下,我需要为
寄存器R
取消设置
shiftRight
位。为此,我可以执行以下逐位操作:

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftRight;
这很好用。下面,您可以看到我为寄存器控制总线定义的所有信号和按位操作。但是,由于我不需要修改每个状态中两个寄存器的所有寄存器控制总线,因此我最终得到了锁存。例如,在下面的状态
done
中,我只需要修改
寄存器R
的寄存器控制总线。因此,为
寄存器X
控制总线创建锁存器

目前,我已经解决了这个问题,只需在状态机的每个状态中设置两个寄存器控制总线的所有位,就可以对信号执行逐位操作

然而,我相信按位操作方法更干净——我想知道是否有任何方法可以让我继续使用这种方法而不处理锁存。它使代码更易于阅读和修改

一如既往,感谢您的帮助

// Register Control Bus Signals
// bit # - purpose
// 0 - reset (rst)
// 1 - load (ld)
// 2 - shift left (sl)
// 3 - shift right (sr)
// 4 - auxilary 1 (mux select)
parameter register_ctrl_reset = 5'b00001;
parameter register_ctrl_load = 5'b00010;
parameter register_ctrl_shiftLeft = 5'b00100;
parameter register_ctrl_shiftRight = 5'b01000;
parameter register_ctrl_auxilary = 5'b10000;
parameter register_ctrl_width = 5;
output reg [register_ctrl_width-1:0] xRegisterControlBus;
output reg [register_ctrl_width-1:0] rRegisterControlBus;
以前的解决方案:

always@(currentState, ryCompareOut)
begin
  case(currentState)
   shiftRight:
   begin
     rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftLeft;
     xRegisterControlBus = xRegisterControlBus & ~register_ctrl_shiftLeft;
     rRegisterControlBus = rRegisterControlBus | register_ctrl_shiftRight;
   end

   done:
   begin
    rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftRight; 
   end

  endcase
end

这是verilog-您可以直接获取位。可能会将参数更改为位索引:

端模

为了避免锁存,为了避免必须写入verilog以确保每个逻辑分支设置所有变量,我使用了一种我不知道名称的技术


其思想是在
始终
过程中,将您分配给的任何变量设置为一组合理的“默认值”。然后,您可以将与这些默认值的任何偏差视为特殊情况,而不必担心确保在代码的所有分支中都设置了所有变量-它们将获得“默认”值。

这种类型的行不适合组合语句

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftLeft;
输入以组合方式影响该行中的输出。该工具会看到这一点,并让您知道这是一个问题。为了使问题更清楚,并说明该工具所担心的是什么,想象一下,如果我写道:

always (*)
begin  
my_sig = ~my_sig;
end

从组合的角度来看,信号总是想反转,它会以逻辑传播的速度反转。我刚刚制作了一个振荡器,因为它永远不会进入静止状态。这些工具知道这可能不是我们想要的,并让我知道。

我称之为“默认分配”。基本上,如果代码中有一条路径(if或case的分支)没有定义信号的值(wire、reg、logic等等),您将得到一个锁存器。有了默认分配,就不可能有这样的路径。@Paul S--我唯一关心的是,在整个循环中的每个迭代中,我都没有任何“默认分配”。我可以在控制总线上添加一条导线,以便在每次通过循环时指定它,但这似乎也很草率。(我想我可以在这里更改我的模型——从技术上讲,我可以在每次迭代中将所有寄存器的加载位设置为零,因为我无法预测我要加载超过一个时钟周期的情况——不过,这似乎有点草率)。
rRegisterControlBus
等都是寄存器,对吗?如你所知,egisters可以被认为有一个当前状态和一个下一个状态。如果示例中的combo
always
块正在计算下一个状态,那么默认值可能只是当前状态,否?如果它们是寄存器,则需要在时钟进程中分配它们。上面所有的块都没有时钟,所以我假设它们不是寄存器(reg type在这方面没有任何意义,并且具有误导性)。这很简单。如果一个项目在时钟上更新,它就是一个寄存器。如果它在某些情况下通过代码更新,但没有计时,则它是一个闩锁。如果它总是被更新,那就是一个有线/信号。马蒂的方法是“正确”的。不过,您可能希望对rRegisterControlBus进行计时,否则您将得到一些小的更改(取决于状态机设计的其余部分)。我喜欢用一个小巧的FSM做任何事情。您可能需要创建一个重复的“rRegisterControlBus_next”寄存器,该寄存器在条件always块中更新,然后将该rRegisterControlBus_next寄存器复制到always@(clk)块中的rRegisterControlBus。请参阅Ciletti的“Verilog HDL中的高级数字设计”以获取示例。您可以发布您的整个状态机吗?很难说您是否打算将xRegisterControlBus作为存储元素。
always (*)
begin  
my_sig = ~my_sig;
end