Если переменная имеет ограниченное число возможных значений, то иногда удобно присвоить этим значениям символьные имена. Распространенный пример - имена состояний автомата (IDLE, REQ, RESP и т.д.), которые в символьном виде делают код более читабельным. Если в Verilog присвоить символьные имена можно было с помощью параметров или дефайнов, то в SystemVerilog для этого был введен специальный тип данных enum. Состояния автомата с помощью этого типа можно описать следующим образом:
enum {IDLE,REQ,RESP} states;
В этом примере создается тип данных states. Переменные этого типа могут принимать только значения, указанные в фигурных скобках (IDLE, REQ и RESP). Если попытаться присвоить переменной типа states значение, которое не было указано в фигурных скобках, то возникнет ошибка. Тип данных enum является жестко типизированным.
По умолчанию значения в фигурных скобках будут типа int. В предыдущем примере IDLE=0, REQ=1, RESP=2. Эти значения можно выводить на печать как в числовом, так и в символьном формате.
Можно явно присваивать значения символьным именам. Если значение не задано явно, то будет присвоено увеличенное на 1 предыдущее значение. Значение первого символьного имени по умолчанию равно 0.
// символьному имени 'c' автоматически присвоится значение 6 enum {a=3, b=5, c} operands; // Синтаксическая ошибка: 'c' и 'd' имеют значение 8 enum {a=0, b=7, c, d=8} operands; // a=0, b=7, c=8 enum {a, b=7, c} operands;
Методы для работы с переменными типа enum
В SV есть несколько методов, которые упрощают обращение к значениям переменной типа enum:
- first() - возвращает первое значение переменной типа enum
- last() - возвращает последнее значение переменной типа enum
- next() - возвращает i-e следующее по счету значение переменной, отсчитанное от текущего значения (по умолчанию возвращает просто следующее значение)
- prev() - возвращает i-e предыдущее по счету значение переменной, отсчитанное от текущего значения (по умолчанию возвращает просто предыдущее значение)
- name() - возвращает символьное отображение значения переменной типа enum. Если значение не определено для данного типа, то метод name() вернет пустую строку
Примеры:
module enum_methods; typedef enum {red,blue,green} e_color; e_color color; initial begin color = color.first(); $display(" %s ",color.name); color = color.next(); $display(" %s ",color.name); color = color.last(); $display(" %s ",color.name); color = color.prev(); $display(" %s ",color.name); end endmodule
Результаты:
red blue green blue
Переменные типа enum в численных выражениях
Элементы переменных типа enum могут использоваться в численных выражениях. В выражениях действия выполняются над числовыми значениями соответствующих символьных отображений.
Используемая в выражении переменная типа enum или идентификатор автоматически приводятся к базовому типу (заданному или типу по умолчанию int). Если тип выражения отличается от типа участвующих в нем переменных, может потребоваться приведение типов.
Примеры:
module enum_methods; typedef enum {red,blue,green} e_color; e_color c,d; int i; initial begin $display("%s",c.name()); d = c; $display("%s",d.name()); d = e_color'(c + 1); // приведение к типу e_color $display("%s",d.name()); i = d; // автоматическое приведение $display("%0d",i); c = e_color'(i); $display("%s",c.name()); end endmodule
Результаты:
red red blue 1 blueЕсли требуется определить в типе enum значения X и Z, то необходимо явно указать тип данных с 4-мя состояниями:
enum integer {IDLE, XX='x, S1='b01, S2='b10} state, next;