2

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

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

例如,在 state 中done,我需要取消shiftRight设置register R. 为此,我可以执行以下按位运算:

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftRight;

这完美地工作。下面,您可以看到我为寄存器控制总线定义的所有信号和按位操作。但是,由于我不需要修改每个状态中两个寄存器的所有寄存器控制总线,所以我最终得到了锁存器。例如,在下面的状态done中,我只需要修改寄存器控制总线register R。结果,为register 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
4

2 回答 2

3

这是verilog - 你可以直接得到。也许将您的参数更改为位索引:


module case_statements #( parameter REGISTER_CTRL_WIDTH = 5 ) ( input [3:0] currentState, output reg [REGISTER_CTRL_WIDTH-1:0] xRegisterControlBus, output reg [REGISTER_CTRL_WIDTH-1:0] rRegisterControlBus );

localparam REGISTER_CTRL_RESET = 0;
localparam REGISTER_CTRL_LOAD = 1;
localparam REGISTER_CTRL_SHIFTLEFT = 2;
localparam REGISTER_CTRL_SHIFTRIGHT = 3;
localparam REGISTER_CTRL_AUXILARY = 4;

localparam STATE_SHIFTLEFT = 0;  // or enum, maybe?
localparam STATE_SHIFTRIGHT = 1;
localparam STATE_DONE = 2;

always@(*)
  begin
      // Defaults:
      rRegisterControlBus = 5'd0; // or whatever
      xRegisterControlBus = 5'd0;

      // Special cases:
      case(currentState)
        STATE_SHIFTRIGHT:
          begin
              rRegisterControlBus[REGISTER_CTRL_SHIFTRIGHT] = 1'b1;
          end
        STATE_SHIFTLEFT:
          begin
              rRegisterControlBus[REGISTER_CTRL_SHIFTLEFT] = 1'b1;
          end
        STATE_DONE:
          begin
              rRegisterControlBus[REGISTER_CTRL_SHIFTRIGHT] = 1'b0;
              rRegisterControlBus[REGISTER_CTRL_SHIFTLEFT] = 1'b0;
          end
      endcase
  end

endmodule

为了避免闩锁,并避免编写大量的 verilog 以确保每个逻辑分支设置所有变量,我正在使用一种我不知道其名称的技术!

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

于 2011-12-05T15:02:29.947 回答
0

这种类型的线不适合组合语句。

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftLeft;

输入组合地影响该行中的输出。该工具会看到这一点,并让您知道这是一个问题。为了使问题更清楚并显示该工具担心的是什么,想象一下如果我写了:

always (*)
begin  
my_sig = ~my_sig;
end

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

于 2016-08-18T03:21:45.300 回答