BSchlinker
BSchlinker

Reputation: 3481

Preventing latches within Verilog case statement

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

Upvotes: 2

Views: 4888

Answers (2)

Rich Maes
Rich Maes

Reputation: 1222

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.

Upvotes: 0

Marty
Marty

Reputation: 6644

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.

Upvotes: 3

Related Questions