SystemVerilog proporciona una serie de tipos de datos nuevos.
logic es un tipo de dato que unifica y simplifica lo que en Verilog clásico se hacía con wire y reg.
La variable logic tomar cuatro valores (0, 1, X ,Z) y se puede declarar como un bit o un vector. La principal ventaja de la variable logic vs reg es que se puede utilizar tanto con asignaciones continuas como dentro de bloques de procedimiento always (recuerda que las variables tipo reg quedaban limitadas a los bloques always).
logic no permite múltiples drivers (como wire). En caso de necesitar múltiples drivers (por ejemplo en buses tri-state), se debe usar wire.
Nota: logic no se puede declarar como inout.
bit, es un tipo de dato de dos estados cuyos valores se limitan únicamente a 0 y 1. Las variables tipo bit se pueden sintetizar, pero depende del contexto de la asignación, de ahí que su uso principal sea en simulación cuando no se necesitan valores lógicos adicionales X o Z. Por defecto las variables tipo bit se inicializan a 0 en simulación, a menos que se indique lo contrario.
Otro tipo de datos biestado son:
byte // 8 bits con signo
int // 32 bits con signo
shortint // 16 bits con signo
longint // 64 bits con signo
Este tipo de variables no pueden tomar X ni Z ya que son son enteros de 2 estados (0 y 1) y por defecto con signo (signed), es decir que por ejemplo la variable byte no va de 0 a 255 si no que el rango de valores es de -128 a 127.
El hecho de que sean variables con solo dos estados, supone una ventaja en términos de rendimiento, mejorando además el uso de memoria.
Los datos tipo struct son tipos compuestos que permiten agrupar varias señales o variables relacionadas bajo un único nombre, formando una estructura organizada. Esto permite reutilizar el tipo en otros módulos.
Se utilizan para agrupar señales de un bus, modelar transacciones (AXI, UART, SPI…), pasar información entre módulos, organizar testbench, y mejorar le legibilidad del código.
Se declaran usando typedef
typedef struct {
logic [7:0] addr;
logic [31:0] data;
logic valid;
} packet_t;
packet_t pkt;
Para acceder a los campos se usa el operador punto:
pkt.addr = 8'h12;
pkt.data = 32'hAABBCCDD;
pkt.valid = 1'b1;
Se pueden inicializar por nombre o por posición:
pkt = '{addr:8'h10, data:32'h12345678, valid:1'b1}; // inicialización por nombre
pkt = '{8'h10, 32'h12345678, 1'b1}; // inicialización por posición
Los datos user-defined (definidos por el usuario) son tipos de datos creados por el diseñador para adaptar el lenguaje a las necesidades del proyecto. En lugar de usar solo tipos básicos (logic, int, byte…), se pueden definir tipos personalizados para mejorar claridad, reutilización y robustez del código.
Por ejemplo, permite crear alias o nuevos tipos basados en otros. Aquí byte_t es un tipo definido por el usuario.:
typedef logic [7:0] byte_t;
byte_t dato;
O definir un tipo enumerado (muy usado en FSM):
typedef enum logic [1:0] {
IDLE,
START,
STOP
} state_t;
state_t estado;
Los Enumerated Data Types (enum) son tipos de datos definidos por el usuario que permiten representar un conjunto finito de valores con nombre. En lugar de usar números “mágicos”, se usa identificadores simbólicos más claros y seguros donde enum es un tipo que puede tomar solo uno de varios valores predefinidos.
Ejemplos:
typedef enum {IDLE, START, STOP} state_t;
typedef enum {RED, GREEN, BLUE} led_light;
El tipo string es un tipo de dato dinámico que almacena cadenas de caracteres (texto). A diferencia de Verilog clásico -que usaba vectores de bits para texto- string es un tipo nativo, más flexible y potente.
Sus características principales son: es un tipo dinámico (su tamaño cambia automáticamente), biestado (no almacena X ni Z), se usa principalmente en testbench y verificación por lo que no es sintetizable.
Ejemplo de declaración y asignación:
string s;
initial begin
s = "Hola mundo";
end
También se puede hacer de manera directa:
string mensaje = "SystemVerilog";
Se puede concatenar:
string a = "Hola";
string b = "Mundo";
string c;
c = {a, " ", b}; // "Hola Mundo"
Permite operaciones de comparación:
if (a == b)
if (a != b)
if (a > b) // comparación lexicográfica