The // synopsys enum directive is designed to use with the Verilog parameter definition statement to specify state machine encodings. When a variable is marked as a state_vector (see the state_vector Directive section of this chapter) and it is declared as an enum, Foundation Express uses the enum values and names for the states of an extracted state machine.
The syntax of the enum directive is either one of the following.
// synopsys enum enum_name
/* synopsys enum enum_name */
The following example shows the declaration of an enumeration of type colors that is 3 bits wide and has the enumeration literals red, green, blue, and cyan with the values shown.
parameter [2:0] // synopsys enum colors
red = 3'b000, green = 3'b001, blue = 3'b010, cyan = 3'b011;
The enumeration must include a size (bit-width) specification. The following example shows an invalid enum declaration.
parameter /* synopsys enum colors */
red = 3'b000, green = 1;
// [2:0] required
The following example shows a register, a wire, and an input port with the declared type of colors. In each of the following declarations, the array bounds must match those of the enumeration declaration. If you use different bounds, synthesis might not agree with simulation behavior.
reg [2:0] /* synopsys enum colors */ counter;
wire [2:0] /* synopsys enum colors */ peri_bus;
input [2:0] /* synopsys enum colors */ input_port;
Even though you declare a variable to be of type enum, it can still be assigned a bit value that is not one of the enumeration values in the definition. The following example relates to the previous example and shows an invalid encoding for colors.
counter = 3'b111;
Because 111 is not in the definition for colors, it is not a valid encoding. Foundation Express accepts this encoding, because it is valid Verilog code, but Foundation Express recognizes this assignment as an invalid encoding and ignores it.
You can use enumeration literals just like constants, as shown in the following example.
if (input_port == blue)
counter = red;
You can also use enumeration with the state_vector directive. The following example shows how the state_vector variable is tagged by using enumeration.
// This finite-state machine (Mealy type) reads 1 bit
// per cycle and detects 3 or more consecutive ones.
module enum2_V(signal, clock, detect);
input signal, clock;
output detect;
reg detect;
//Declare the symbolic names for states
parameter [1:0 //synopsys enum state_info
NO_ONES = 2'h0,
ONE_ONE = 2'h1,
TWO_ONES = 2'h2,
AT_LEAST_THREE_ONES = 2'h3;
//Declare current state and next state variables
reg [1:0] /* synopsys enum state_info */ cs;
reg [1:0] /* synopsys enum state_info */ ns;
// synopsys state_vector c
always @ (cs or signal)
begin
detect = 0; //default values
if (signal == 0)
ns = NO_ONES;
else
case (cs) //synopsys full_case
NO_ONES: ns = ONE_ONE;
ONE_ONE: ns = TWO_ONES;
TWO_ONES, ns = AT_LEAST_THREE_ONES;
AT_LEAST_THREE_ONES:
begin
ns = AT_LEAST_THREE_ONES;
detect = 1;
end
endcase
end
always @ (posedge clock) begin
cs = ns;
end
endmodule
Enumerated types are designed to be used as whole entities. This design allows Foundation Express to rebind the encodings of an enumerated type more easily. You cannot select a bit or a part from a variable that has been given an enumerated type. If you do, the overall behavior of your design changes when Foundation Express changes the original encoding. The following example shows an unsupported bit-select.
parameter [2:0] /* synopsys enum states */
s0 = 3'd0, s1 = 3'd1, s2 = 3'd2, s3 = 3'd3,
s4 = 3'd4, s5 = 3'd5, s6 = 3'd6, s7 = 3'd7;
reg [2:0] /* synopsys enum states */ state, next_state;
assign high_bit = state[2];// not supported
Because you cannot access individual bits of an enumerated type, you cannot use component instantiation to hook up single-bit flip-flops or three-states. The following example shows an example of this type of unsupported bit-select.
DFF ff0 ( next_state[0], clk, state[0] );
DFF ff1 ( next_state[1], clk, state[1] );
DFF ff2 ( next_state[2], clk, state[2] );
To create flip-flops and three-states for enum values, you must imply them with the posedge construct or the literal z, as shown in the following example.
parameter [2:0] /* synopsys enum states */
s0 = 3'd0, s1 = 3'd1, s2 = 3'd2, s3 = 3'd3,
s4 = 3'd4, s5 = 3'd5, s6 = 3'd6, s7 = 3'd7;
reg [2:0] /* synopsys enum states */ state, next_state;
parameter [1:0] /* synopsys enum outputs */
DONE = 2'd0, PROCESSING = 2'd1, IDLE = 2'd2;
reg [1:0] /* synopsys enum outputs */ out, triout;
always @ (posedge clk) state = next_state;
assign triout = trienable ? out : 'bz;
If you use the constructs shown in the example above, you can change the enumeration encodings by changing the parameter and reg declarations, as shown in the following example. You can also allow Foundation Express to change the encodings.
parameter [3:0] /* synopsys enum states */
s0 = 4'd0, s1 = 4'd10, s2 = 4'd15, s3 = 4'd5,
s4= 4'd2, s5 = 4'd4, s6 = 4'd6, s7 = 4'd8;
reg [3:0] /* synopsys enum states */ state, next_state;
parameter [1:0] /* synopsys enum outputs */
DONE = 2'd3, PROCESSING = 2'd1, IDLE = 2'd0;
reg [1:0] /* synopsys enum outputs */ out, triout;
always @ (posedge clk) state = next_state;
assign triout = trienable ? out : 'bz;
If you must select individual bits of an enumerated type, you can declare a temporary variable of the same size as the enumerated type. Assign the enumerated type to the variable, then select individual bits of the temporary variable. The following example shows how this is done.
parameter [2:0] /* synopsys enum states */
s0 = 3'd0, s1 = 3'd1, s2 = 3'd2, s3 = 3'd3,
s4 = 3'd4, s5 = 3'd5, s6 = 3'd6, s7 = 3'd7;
reg [2:0] /* synopsys enum states */ state, next_state;
wire [2:0] temporary;
assign temporary = state;
assign high_bit = temporary[2]; //supported
Note: Selecting individual bits from an enumerated type is not recommended.
If you declare a port as a reg and as an enumerated type, you must declare the enumeration when you declare the port. The following example shows the declaration of the enumeration.
module good_example (a,b);
parameter [1:0] /* synopsys enum colors */
green = 2'b00, white = 2'b11;
input a;
output [1:0] /* synopsys enum colors */ b;
reg [1:0] b;
.
.
endmodule
The following example shows the wrong way to declare a port as an enumerated type, because the enumerated type declaration appears with the reg declaration instead of with the output port declaration. This code does not export enumeration information to Foundation Express.
module bad_example (a,b);
parameter [1:0] /* synopsys enum colors */
green = 2'b00, white = 2'b11;
input a;
output [1:0] b;
reg [1:0] /* synopsys enum colors */ b;
.
.
endmodule