unique Archives - Verilog Pro https://www.verilogpro.com/tag/unique/ Verilog and Systemverilog Resources for Design and Verification Mon, 27 Jun 2022 07:42:50 +0000 en-US hourly 1 https://wordpress.org/?v=6.4.4 98068679 One-hot State Machine in SystemVerilog – Reverse Case Statement https://www.verilogpro.com/systemverilog-one-hot-state-machine/ https://www.verilogpro.com/systemverilog-one-hot-state-machine/#comments Wed, 14 Oct 2015 16:55:07 +0000 http://www.verilogpro.com/?p=167 Finite state machine (FSM) is one of the first topics taught in any digital design course, yet coding one is not as easy as first meets the eye. There are Moore and Mealy state machines, encoded and one-hot state encoding, one or two or three always block coding styles. Recently I was reviewing a coworker’s ... Read more

The post One-hot State Machine in SystemVerilog – Reverse Case Statement appeared first on Verilog Pro.

]]>
Finite state machine (FSM) is one of the first topics taught in any digital design course, yet coding one is not as easy as first meets the eye. There are Moore and Mealy state machines, encoded and one-hot state encoding, one or two or three always block coding styles. Recently I was reviewing a coworker’s RTL code and came across a SystemVerilog one-hot state machine coding style that I was not familiar with. Needless to say, it became a mini research topic resulting in this blog post.

When coding state machines in Verilog or SystemVerilog, there are a few general guidelines that can apply to any state machine:

  1. If coding in Verilog, use parameters to define state encodings instead of ‘define macro definition. Verilog ‘define macros have global scope; a macro defined in one module can easily be redefined by a macro with the same name in a different module compiled later, leading to macro redefinition warnings and unexpected bugs.
  2. If coding in SystemVerilog, use enumerated types to define state encodings.
  3. Always define a parameter or enumerated type value for each state so you don’t leave it to the synthesis tool to choose a value for you. Otherwise it can make for a very difficult ECO when it comes time to reverse engineer the gate level netlist.
  4. Make curr_state and next_state declarations right after the parameter or enumerated type assignments. This is simply clean coding style.
  5. Code all sequential always block using nonblocking assignments (<=). This helps guard against simulation race conditions.
  6. Code all combinational always block using blocking assignments (=). This helps guard against simulation race conditions.

SystemVerilog enumerated types are especially useful for coding state machines. An example of using an enumerated type as the state variable is shown below.

typedef enum {
  IDLE   = 2'b00,
  ACTIVE = 2'b01,
  DONE   = 2'b10,
  XX     = 'x
} state_t;
state_t curr_state, next_state;

Notice that enumerated types allow X assignments. Enumerated types can be displayed as names in simulator waveforms, which eliminates the need of a Verilog trick to display the state name in waveform as a variable in ASCII encoding.

One-hot refers to how each of the states is encoded in the state vector. In a one-hot state machine, the state vector has as many bits as number of states. Each bit represents a single state, and only one bit can be set at a time—one-hot. A one-hot state machine is generally faster than a state machine with encoded states because of the lack of state decoding logic.

SystemVerilog and Verilog has a unique (pun intended) and efficient coding style for coding one-hot state machines. This coding style uses what is called a reverse case statement to test if a case item is true by using a case header of the form case (1’b1). Example code is shown below:

enum {
  IDLE = 0,
  READ = 1,
  DLY  = 2,
  DONE = 3
//} state, next; // Original not completely correct code
} state_index_t;
logic [3:0] state, next; // Corrected. Thanks John!

// Sequential state transition
always_ff @(posedge clk or negedge rst_n)
  if (!rst_n) begin
    state       <= '0; // default assignment
    state[IDLE] <= 1'b1;
  end
  else
    state       <= next;

// Combinational next state logic
always_comb begin
  next = '0;
  unique case (1'b1)
    state[IDLE] : begin
      if (go)
        next[READ] = 1'b1;
      else
        next[IDLE] = 1'b1;
    end
    state[READ] : next[ DLY] = 1'b1;
    state[ DLY] : begin
      if (!ws)
        next[DONE] = 1'b1;
      else
        next[READ] = 1'b1;
    end
    state[DONE] : next[IDLE] = 1'b1;
  endcase
end

// Make output assignments
always_ff @(posedge clk or negedge rst_n)
...

In this one-hot state machine coding style, the state parameters or enumerated type values represent indices into the state and next vectors. Synthesis tools interpret this coding style efficiently and generates output assignment and next state logic that does only 1-bit comparison against the state vectors. Notice also the use of always_comb and always_ff SystemVerilog always statements, and unique case to add some run-time checking.

An alternate one-hot state machine coding style to the “index-parameter” style is to completely specify the one-hot encoding for the state vectors, as shown below:

enum {
  IDLE = 4'b0001,
  READ = 4'b0010,
  DLY  = 4'b0100,
  DONE = 4'b1000
} state, next;

According to Cliff Cummings’ 2003 paper, this coding style yields poor performance because the Design Compiler infers a full 4-bit comparison against the state vector, in effect defeating the speed advantage of a one-hot state machine. However, the experiments conducted in this paper were done in 2003, and I suspect synthesis tools have become smarter since then.

State machines may look easy on paper, but are often not so easy in practice. Given how frequently state machines appear in designs, it is important for every RTL designer to develop a consistent and efficient style for coding them. One-hot state machines are generally preferred in applications that can trade-off area for a speed advantage. This article demonstrated how they can be coded in Verilog and SystemVerilog using a unique and very efficient “reverse case statement” coding style. It is a technique that should be in every RTL designer’s arsenal.

What are your experiences with coding one-hot state machines? Do you have another coding style or synthesis results to share? Leave a comment below!

References

The post One-hot State Machine in SystemVerilog – Reverse Case Statement appeared first on Verilog Pro.

]]>
https://www.verilogpro.com/systemverilog-one-hot-state-machine/feed/ 14 167
SystemVerilog Unique And Priority – How Do I Use Them? https://www.verilogpro.com/systemverilog-unique-priority/ https://www.verilogpro.com/systemverilog-unique-priority/#comments Sat, 19 Sep 2015 15:07:02 +0000 http://www.verilogpro.com/?p=126 Improperly coded Verilog case statements can frequently cause unintended synthesis optimizations or unintended latches. These problems, if not caught in pre-silicon simulations or gate level simulations, can easily lead to a non-functional chip. The new SystemVerilog unique and priority keywords are designed to address these coding traps. In this article, we will take a closer ... Read more

The post SystemVerilog Unique And Priority – How Do I Use Them? appeared first on Verilog Pro.

]]>
Improperly coded Verilog case statements can frequently cause unintended synthesis optimizations or unintended latches. These problems, if not caught in pre-silicon simulations or gate level simulations, can easily lead to a non-functional chip. The new SystemVerilog unique and priority keywords are designed to address these coding traps. In this article, we will take a closer look at how to use these new SystemVerilog keywords in RTL coding. The reader is assumed to have knowledge of how Verilog case statements work. Those who are not familiar can refer to my previous post “Verilog twins: case, casez, casex. Which Should I Use?

The SystemVerilog unique and priority modifiers are placed before an if, case, casez, casex statement, like this:

unique if (expression)
  statements
else
  statements

priority case (case_expression)
  case_item_1: case_expression_1
  case_item_2: case_expression_2
endcase

With the if…else statement, the SystemVerilog unique or priority keyword is placed only before the first if, but affects all subsequent else if and else statements.

SystemVerilog Unique Keyword

The unique keyword tells all software tools that support SystemVerilog, including those for simulation, synthesis, lint-checking, formal verification, that each selection item in a series of decisions is unique from any other selection item in that series, and that all legal cases have been listed. In other words, each item is mutually exclusive, and the if…else or case statement specifies all valid selection items.

It is easier to illustrate the effects of SystemVerilog unique using a case statement. unique case causes a simulator to add run-time checks that will report a warning if any of the following conditions are true:

  1. More than one case item matches the case expression
  2. No case item matches the case expression, and there is no default case

To illustrate how SystemVerilog unique affects simulation of case statements, let’s look at a wildcard casez statement:

always @(irq) begin
  {int2, int1, int0} = 3'b000;
  unique casez (irq)
    3'b1?? : int2 = 1'b1;
    3'b?1? : int1 = 1'b1;
    3'b??1 : int0 = 1'b1;
  endcase
end

You may recognize that this code resembles the priority decoder example from my previous post “Verilog twins: case, casez, casex. Which Should I Use?” However, by adding the SystemVerilog unique keyword, the behaviour is now completely different.

Firstly, by adding the SystemVerilog unique keyword, the designer asserts that only one case item can match at a time. If more than one bit of irq is set in simulation, the simulator will generate a warning, flagging that the assumption of irq being one-hot has been violated. Secondly, to synthesis tools, the unique keyword tells the tool that all valid case items have been specified, and can be evaluated in parallel. Synthesis is free to optimize the case items that are not listed.

Read the second point again, it is paramount! In a unique case statement (without a default case), outputs after synthesis from any unlisted case item is indeterminate. In simulation you may see a deterministic behaviour, maybe even an output that looks correct (along with an easy-to-miss warning), but that may not match what you see in silicon. I have personally seen a chip that did not work because of this coding error.

Back to the example, because of the unique keyword, synthesis will remove the priority logic. Thus, this code example is actually a decoder with no priority logic. Eliminating unnecessary priority logic typically results in smaller and faster logic, but only if it is indeed the designer’s intention.

The SystemVerilog unique keyword can be applied similarly to an if…else statement to convey the same uniqueness properties. For a unique if statement, a simulator will generate a run-time warning if any of the following is false:

  1. If two or more of the if conditions are true at the same time
  2. If all of the if conditions (including else if) are false, and there is no final else branch

SystemVerilog 2012 adds the keyword unique0 which, when used with a case or if statement, generates a warning only for the first condition above.

SystemVerilog Priority Keyword

The priority keyword instructs all tools that support SystemVerilog that each selection item in a series of decisions must be evaluated in the order in which they are listed, and all legal cases have been listed. A synthesis tool is free to optimize the logic assuming that all other unlisted conditions are don’t cares. If the priority case statement includes a case default statement, however, then the effect of the priority keyword is disabled because the case statement has then listed all possible conditions. In other words, the case statement is full.

Since the designer asserts that all conditions have been listed, a priority case will cause simulators to add run-time checks that will report a warning for the following condition:

  1. If the case expression does not match any of the case item expressions, and there is no default case

A priority if will cause simulators to report a warning if all of the if…if else conditions are false, and there is no final else branch. An else branch will disable the effect of the priority if.

When to Use Them

SystemVerilog unique and priority should be used especially in case statements that infer priority or non-priority logic. Using these keywords help convey design intent, guide synthesis tools to the correct result, and adds simulation and formal verification assertions that check for violation of design assumptions. One suggestion from “full_case parallel_case”, the Evil Twins of Verilog Synthesis is to code intentional priority encoders using if…else if statements rather than case statements, as it is easier for the typical engineer to recognize a priority encoder coded that way.

SystemVerilog unique and priority do not guarantee the removal of unwanted latches. Any case statement that makes assignments to more than one output in each case item statement can still generate latches if one or more output assignments are missing from other case item statements. One of the easiest ways to avoid these unwanted latches is by making a default assignment to the outputs before the case statement.

The unique and priority keywords should not be blindly added to any case and if statements either. Below is an example where the priority keyword will cause a design to break. The hardware that is intended is a decoder with enable en. When en=0, the decoder should output 4’b0000 on y.

logic [3:0] y;
logic [1:0] a;
logic       en;

always_comb begin
  y = '0;
  priority case ({en,a})
    3'b100: y[a] = 1'b1;
    3'b101: y[a] = 1'b1;
    3'b110: y[a] = 1'b1;
    3'b111: y[a] = 1'b1;
  endcase
end
SystemVerilog priority case incorrect usage

The logic will synthesize to something like this:

Here the priority keyword indicates that all unlisted case items are don’t cares, and can be optimized. As a result, the synthesis tool will simply optimize away en, which results in a different hardware than what was intended. A simulator will report a warning whenever en=0, which should raise an alarm warning that something is wrong. The unique keyword will have the same result here.

Conclusion

SystemVerilog unique and priority help avoid bugs from incorrectly coded case and if…else statements. They are part of the SystemVerilog language which means all tools that support SystemVerilog, including those for simulation, lint-checking, formal verification, synthesis, all have to implement the same specification of these keywords. Using these keywords help convey design intent, guide synthesis tools to the correct result, and adds simulation and formal verification checks for violation of design assumption.

In this post I have purposely tried to avoid discussing the Verilog pragmas full_case and parallel_case to write a more stand-alone discussion of the SystemVerilog unique and priority keywords. Those who are interested in the historical development of these keywords from Verilog full_case and parallel_case can refer to “full_case parallel_case”, the Evil Twins of Verilog Synthesis.

Do you have other experiences or examples of when to use or not use unique and priority? Leave a comment below!

References

Quiz and Sample Source Code

Now it’s time for a quiz! How will each of the following variations of case statement behave when the case expression

  1. matches one of the non-default case items
  2. does not match any non-default case item
  3. contains all X’s (e.g. if the signal comes from an uninitialized memory)
  4. contains all Z’s (e.g. if the signal is unconnected)
  5. contains a single bit X
  6. contains a single bit Z?

Case statement variations:

  1. Plain case statement
  2. Plain case with default case
  3. Casez
  4. Casez with default case
  5. Casex
  6. Casex with default case
  7. Unique case
  8. Unique case with default case
  9. Unique casez
  10. Unique casex

Stumped? Download the executable source code to find out the answer!

[lab_subscriber_download_form download_id=7]

The post SystemVerilog Unique And Priority – How Do I Use Them? appeared first on Verilog Pro.

]]>
https://www.verilogpro.com/systemverilog-unique-priority/feed/ 7 126