Generación y Gestión de Señales de Reloj y Reset en Plataformas de Verificación con SystemVerilog

La generación y sincronización precisa de las señales de reloj (clk) y reset (rstn) es fundamental en el diseño de una plataforma de verificación. Este artículo explora prácticas comunes para su implementación, el control de aserciones durante los dominios de reset y la gestión de escenarios específicos.

1. Módulo de Generación de Estímulos Básicos

Un punto de partida es crrear un módulo que proporcione los estímulos iniciales. El siguiente código ejemplifica la creación de un reloj con un período configurable y una secuencia de reset controlada, donde los tiempos de activación se aleatorizan para cubrir diferentes condiciones de inicio.

module signal_generator;
  timeunit 1ps;
  timeprecision 1ps;

  real period_ns = 500.0; // Ejemplo: genera un reloj de 2 GHz
  logic sys_clk;
  logic async_rstn;

  // Generación del reloj
  initial begin
    int unsigned clk_startup_delay;
    sys_clk = 1'b0;
    clk_startup_delay = $urandom_range(12, 25);
    #clk_startup_delay;
    forever #(period_ns / 2.0) sys_clk = ~sys_clk;
  end

  // Generación del reset
  initial begin
    int unsigned rst_assert_time, rst_deassert_delay;
    async_rstn = 1'bx;
    rst_assert_time = $urandom_range(1, 3);
    #rst_assert_time;
    async_rstn = 1'b1;
    #rst_assert_time;
    async_rstn = 1'b0; // Reset activado
    rst_deassert_delay = $urandom_range(1, 30); // Desalineado con el reloj
    #rst_deassert_delay;
    async_rstn = 1'b1; // Reset desactivado
  end
endmodule

2. Sincronización de Aserciones con el Reset

Las aserciones basadas en reloj a menudo deben inhabilitarse durante el reset. Una práctica estándar es utilizar la señal rstn en una cláusula disable iff.

property register_overflow_check(input logic [7:0] counter, input logic enable, input logic [7:0] limit);
  @(posedge sys_clk) disable iff (!async_rstn)
    enable |-> (counter <= limit);
endproperty

Sin embargo, en sistemas complejos donde diferentes IP tienen dominios de reset independientes, utilizar el reset global del testbench puede causar falsas fallas. Es necesario introducir una señal de habilitación (enable) específica para las aserciones de ese bloque.

module assertions_with_enable (
  input logic sva_clk,
  input logic sva_rstn,
  input logic specific_ip_rstn,
  input logic assertion_enable
);
  property reset_sequence_check;
    @(posedge sva_clk) disable iff (!specific_ip_rstn || !assertion_enable)
      $fell(request) |-> ##[1:100] $fell(grant);
  endproperty

  assert property(reset_sequence_check)
    else $error("La secuencia de reset del IP fallo.");
endmodule

3. Propagación de Estados 'X' en Simulación

Para verificar el comportamiento del diseño frente a condiciones no inicializadas, se puede habliitar la propagación de valores 'X' durante la simulación. Esto se configura típicamente en el comando del simulador.

// Ejemplo de directiva de simulador para habilitar xprop en el DUT
// instance {testbench.dut} {xpropOn};

Con xprop activado, una señal no conducida por un driver de reloj mantendrá el estado 'X', propagándose a través de la lógica combinacional y secuencial, lo que ayuda a detectar diseños no robustos.

4. Consideraciones para Resets Parciales

Los resets parciales, donde solo una porción del diseño se reinicia, presentan desafíos únicos.

  • Acceso a Registros: Durante un reset parcial, el acceso a registros en el dominio que se está reiniciando debe ser bloqueado por el firmware o software de control. Intentar leer o escribir puede dar lugar a datos inválidos o comportamientos inesperados en el bus.
  • Control de Hilos en Estímulos: Es necesario gestionar los hilos de generación de estímulos que interactúan con una región bajo reset parcial. Un enfoque común es terminar explícitamente los hilos afectados antes de activar el reset.
fork
  begin : stimulus_thread
    automatic process::job_t job_handle;
    job_handle = process::self();
    vseq.start(env.bus_vsqr);
  end
  begin : reset_monitor
    repeat(5) begin
      int unsigned reset_gap = $urandom_range(500, 1500);
      #(reset_gap * 1ns);
      trigger_partial_reset();
      // Forzar la terminación del hilo de estímulos asociado
      stimulus_thread.job_handle.kill();
    end
  end
join

5. Sentencias de Espera y Sincronziación

Existen múltiples formas de sincronizar el flujo de la verificación con señales de reloj y reset.

Espera directa en señales de interfaz:

// Espera en cualquier flanco del reloj
@(system_bus.clk);
// Espera solo en el flanco ascendente
@(posedge system_bus.clk);

Uso de bloques de sincronización (clocking blocks): Estos proporcionan una capa de abstracción y permiten definir tiempos de setup y hold.

interface bus_interface(input logic clk, input logic rst_n);
  parameter setup_time = 2ns;
  parameter hold_time = 1ns;

  clocking driver_cb @(posedge clk);
    default input #setup_time output #hold_time;
    output data;
    output address;
    input acknowledge;
  endclocking
endinterface
// Espera al siguiente evento del bloque de sincronización del driver
@(bus_vif.driver_cb);

Etiquetas: SystemVerilog SVA Testbench Clock Reset Generation Assertion Management

Publicado el 6-11 22:45