Mecanismos de Paso de Parámetros en SystemVerilog

En SystemVerilog, la transmisión de parámetros a funciones y procedimientos se basa en dos reglas fundamentales: transmisión por valor y transmisión por referencia. A continuación, se analizan los tipos de parámetros ref, input, output e inout, con ejemplos para tipos básicos y clases.

1. Parámetros de tipo input

Para tipos de datos básicos como int, el parámetro input actúa como transmisión por valor. La función trabaja con una copia del valor original, por lo que cualquier modificación interna no afecta a la variable externa.


module modulo_ejemplo;
int contador_global = 1;

function void prueba_input(input int valor);
  $display("Dentro de prueba_input:");
  valor += 1;
  $display("valor = %0d", valor);
endfunction

function void mostrar_global();
  $display("Valor global: %0d", contador_global);
endfunction

initial begin
  mostrar_global();
  prueba_input(contador_global);
  mostrar_global();
end
endmodule

Salida esperada:


Valor global: 1
Dentro de prueba_input:
valor = 2
Valor global: 1

Para clases, el parámetro input pasa el identificador del objeto. La función modifica el objeto a través del mismo identificador, afectando los datos en el espacio compartido.


module modulo_clase;

class datos;
  int valor_interno;
  function void imprimir();
    $display("Valor interno en datos: %0d", valor_interno);
  endfunction
endclass

function void usar_input(input datos ref_obj);
  $display("Modificando objeto:");
  ref_obj.valor_interno = 5;
  $display("valor_interno = %0d", ref_obj.valor_interno);
endfunction

initial begin
  datos obj = new();
  obj.valor_interno = 0;
  obj.imprimir();
  usar_input(obj);
  obj.imprimir();
end
endmodule

Salida:


Valor interno en datos: 0
Modificando objeto:
valor_interno = 5
Valor interno en datos: 5

2. Parámetros de tipo output

Para tipos básicos, output transmite la dirección de una nueva variable interna al exterior. Al finalizar la función, la variable externa apunta a la dirección de la variable interna, actualizando su valor.


module modulo_output;
int dato_externo = 1;

function void prueba_output(output int param);
  $display("Asignando nuevo valor:");
  param = 10;
  $display("param = %0d", param);
endfunction

function void mostrar_externo();
  $display("dato_externo = %0d", dato_externo);
endfunction

initial begin
  mostrar_externo();
  prueba_output(dato_externo);
  mostrar_externo();
end
endmodule

Salida:


dato_externo = 1
Asignando nuevo valor:
param = 10
dato_externo = 10

Para clases, output pasa el identtificador del objeto al inicio de la función, similar a input. Las modificaciones afectan directamente al objeto.


module modulo_output_clase;

class configuracion;
  int ajuste;
  function void mostrar();
    $display("Ajuste: %0d", ajuste);
  endfunction
endclass

function void configurar_objeto(output configuracion cfg);
  cfg.ajuste = 100;
  $display("Ajuste configurado: %0d", cfg.ajuste);
endfunction

initial begin
  configuracion mi_cfg = new();
  mi_cfg.ajuste = 50;
  mi_cfg.mostrar();
  configurar_objeto(mi_cfg);
  mi_cfg.mostrar();
end
endmodule

Salida:


Ajuste: 50
Ajuste configurado: 100
Ajuste: 100

3. Parámetros de tipo ref

Para tipos básicos, ref trasnmite la dirección de la variable original. La función trabaja directamente con la misma dirección, modificando el valor externo.


module modulo_ref;
int variable_compartida = 1;

function void modificar_ref(ref int puntero);
  $display("Modificando vía ref:");
  puntero += 5;
  $display("puntero = %0d", puntero);
endfunction

function void ver_variable();
  $display("variable_compartida = %0d", variable_compartida);
endfunction

initial begin
  ver_variable();
  modificar_ref(variable_compartida);
  ver_variable();
end
endmodule

Salida:


variable_compartida = 1
Modificando vía ref:
puntero = 6
variable_compartida = 6

Para clases, ref pasa el identificador del objeto, permitiendo modificaciones directsa en el objeto compartido.


module modulo_ref_clase;

class registro;
  int dato;
  function void leer();
    $display("Dato en registro: %0d", dato);
  endfunction
endclass

function void actualizar_ref(ref registro reg);
  reg.dato = 999;
  $display("Dato actualizado: %0d", reg.dato);
endfunction

initial begin
  registro mi_reg = new();
  mi_reg.dato = 100;
  mi_reg.leer();
  actualizar_ref(mi_reg);
  mi_reg.leer();
end
endmodule

Salida:


Dato en registro: 100
Dato actualizado: 999
Dato en registro: 999

4. Parámetros de tipo inout

Para tipos básicos, inout realiza dos transmisiones por valor: al inicio de la función copia el valor externo a una variable interna, y al finalizar copia el valor interno de vuelta al externo.


module modulo_inout;
int acumulador = 1;

function void ajustar_inout(inout int numero);
  $display("Ajustando:");
  numero += 3;
  $display("numero = %0d", numero);
endfunction

function void ver_acumulador();
  $display("acumulador = %0d", acumulador);
endfunction

initial begin
  ver_acumulador();
  ajustar_inout(acumulador);
  ver_acumulador();
end
endmodule

Salida:


acumulador = 1
Ajustando:
numero = 4
acumulador = 4

Para clases, inout pasa el identificador del objeto al inicio, similar a los otros mecanismos.


module modulo_inout_clase;

class contador;
  int cuenta;
  function void incrementar();
    cuenta++;
    $display("Cuenta: %0d", cuenta);
  endfunction
endclass

function void modificar_inout(inout contador cnt);
  cnt.cuenta = 10;
  $display("Cuenta modificada: %0d", cnt.cuenta);
endfunction

initial begin
  contador mio = new();
  mio.cuenta = 0;
  mio.incrementar();
  modificar_inout(mio);
  mio.incrementar();
end
endmodule

Salida:


Cuenta: 1
Cuenta modificada: 10
Cuenta: 11

En resumen, para tipos de datos básicos, input es transmisión por valor, output y ref son transmisión por referencia, e inout es transmisión por valor doble. Para clases, todos los tipos transmiten el identificador del objeto al inicio de la función, lo que permite modificaciones directas en el objeto compartido.

Etiquetas: SystemVerilog Parámetros Transmisión de Valor Transmisión de Referencia Input

Publicado el 5-29 11:11