Asignación continua durante la simulación de SystemVerilog

2

Estoy proporcionando entrada a una interfaz SPI. La señal de entrada es una concatenación de varias señales diferentes. Lo que me gustaría hacer en la simulación es tener una concatenación continua de las diferentes señales en una cadena final que se enviará al SPI:

logic [7:0] foo;      // Signal 1
logic [7:0] bar;      // Signal 2
logic [15:0] combine; // Final signal
assign combine = {foo, bar};

task SendSPI;
begin
     foo = 8'hFF;
     bar = 8'h00;
     SendToSpi(combine); // Want it to send 16'hFF00;
endtask;

El código anterior se compila y se ejecuta en el simulador (simulación de Cadence NC), pero el valor de la combinación es indefinido (xxxx). Sé que puedo solucionar esto teniendo una tarea de concatenación:

task CombineSignal;
begin
     combine = {foo, bar};
endtask;

y llamaría a esa tarea cada vez que quisiera concatenar, ¡pero tener un trabajo continuo de asignación sería muy bueno! ¿Alguien sabe si la asignación continua es posible en una situación como esta?

    
pregunta Unreasonable Sin

2 respuestas

3

Me di cuenta de lo que estaba pasando. La declaración asignar combinación necesita tiempo para pasar antes de que tome un nuevo valor.

logic [7:0] foo;      // Signal 1
logic [7:0] bar;      // Signal 2
logic [15:0] combine; // Final signal
assign combine = {foo, bar};

task SendSPI;
    begin
         foo = 8'hFF;
         bar = 8'h00;

         SendToSpi(combine); // combine is undefined.

         @(negedge clk);     // let some simulator time pass.

         SendToSpi(combine); // combine now equals 16'hFF00
    endtask;
    
respondido por el Unreasonable Sin
1

Debe comprender cómo los simuladores de Verilog programan los eventos.

Si las declaraciones de procedimiento aparecen en diferentes bloques de procedimiento, no hay garantía para el orden de su ejecución. Por ejemplo:

initial
  begin
    a = 0;
    b = 1;
  end

always a = b;

always b = a;

El código anterior puede dar como resultado que tanto a como b sean 1, así como 0's.

Sin embargo, se garantiza que las declaraciones de procedimiento que aparecen en el mismo bloque de procedimiento se ejecutan secuencialmente:

initial
  begin
    a = 0;
    b = 1;
  end

always 
  begin
    a = b;
    b = a;
  end

El código anterior dará como resultado que tanto a como b sean 1.

El problema con su código inicial es que la operación de concatenación está fuera del cuerpo de la tarea, por lo tanto, no hay forma de que el programador pueda ejecutarlo entre las declaraciones en el cuerpo de la tarea (porque se ejecutan secuencialmente, sin interrupción externa).

Sin embargo, una vez que agrega una construcción secuencial ( @(negedge clk) ), el simulador avanza a la siguiente franja horaria que permite la ejecución de la asignación de concatenación.

Aunque el código que proporcionó le funciona, es una mala práctica escribir Verilog de esta manera. ¿Por qué no hacer esto:

logic [7:0] foo;      // Signal 1
logic [7:0] bar;      // Signal 2

task SendSPI;
begin
     foo = 8'hFF;
     bar = 8'h00;
     SendToSpi({foo, bar}); // Will send 16'hFF00;
endtask;
    
respondido por el Vasiliy

Lea otras preguntas en las etiquetas