防止 Verilog case 语句中出现锁存

发布于 2024-12-19 13:21:43 字数 1862 浏览 2 评论 0原文

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

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

例如,在状态done 下,我需要取消设置register RshiftRight 位。为了做到这一点,我可以执行以下按位运算:

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

I'm having trouble understanding how I can prevent latches from being created within a Verilog project. I understand that latches are being created because I am not specifying what occurs to all signals within each case statement. However, I do not know if there is any way to avoid this (other then the draconian method which I have used at the moment).

I currently have two shifter registers, register X and register R. Each of these shifter registers has a 5-bit wide control bus, controlled from a finite state machine. In order to make management of these shifter registers easier, I was hoping to utilize bitwise operations to set and unset control bus bits.

For instance, in state done, I need to unset the shiftRight bit for register R. In order to do this, I can perform the following bitwise operation:

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftRight;

This works perfectly. Below, you can see all of the signals and bitwise operations which I have defined for the register control bus. However, since I do not need to modify all of the register control buses for both registers within each state, I end up with latches. For instance, within state done below, I only need to modify the register control bus for register R. As a result, a latch is created for register X control bus.

At the moment, I've resolved this by simply setting all of the bits for both of the register control buses within each state of the state machine, throwing away my idea to perform bitwise operations on the signals.

However, I believe the bitwise operation method is cleaner -- I would like to know if there is anyway for me to continue to use this method without dealing with latches. It makes the code much easier to read and modify.

As always, thanks for any assistance.

// 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;

Previous solution:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陪你到最终 2024-12-26 13:21:43

这是 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

结束模块

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

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

This is verilog - you can get at the bits directly. Maybe change your parameters to bit indices:


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

To avoid latches, and to avoid having to write loads of verilog to make sure each logic branch sets all variables, I'm using a technique for which I don't know the name of!

The idea is to set any variables you're assigning to within an always procedure to some set of reasonable 'defaults' at the beginning. Then you can treat any deviations from these defaults as special cases and not have to worry about making sure all your variables are set in all branches of your code - they will get the 'default' value.

残龙傲雪 2024-12-26 13:21:43

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

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftLeft;

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

always (*)
begin  
my_sig = ~my_sig;
end

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

This type of line is not good for a combinatorial statement.

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftLeft;

The input effects the output in this line combinatorially. The tool sees this and lets you know it's a problem. To make the problem more clear and to show what it is that the tool is worried about, imagine if I wrote:

always (*)
begin  
my_sig = ~my_sig;
end

Combinatorially, the signal always wants to invert and it will do so at the speed of the logic propagation. I have just made an oscillator because it will never come to a resting state. The tools knows this probably isn't what is desired and lets me know.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文