¿Cómo funcionan una declaración "if" y una declaración "always @" en Verilog?

0

Estoy intentando programar un registro de pila de 8 niveles para un contador de programa. Está funcionando lo suficientemente bien, pero por alguna razón, cuando lo pruebo, algunas combinaciones de entradas producen resultados inesperados. Esto me lleva a creer que realmente no entiendo la lógica subyacente detrás de la declaración "if (condition1 & & & & condition2)" o la instrucción always @ (Statement? No estoy realmente segura de cómo llamarlo). No me importa si es sintetizable. Simplemente siento que me estoy perdiendo algo.

Aquí está el código:

  module Stack(
  // Buses
  inout [12:0] BUS_Stack,             // Bus used to exchange data between Stack and PC
  // Inputs
  input logic WE_Stack,               // Write Enable. WE = 1 Stack sends data to PC
  input logic RE_Stack                // Read Enable. RE = 1 Receives data from PC
  );

  // Internal variables
  integer i;                          // Variable used for "for loops"
  reg [12:0] Stack [0:7];             // Stack matrix. A registry is used for it to have "memory"
  logic [12:0] Data_To_PC;            // Internal variable that manages the writing process to BUS_Stack
  parameter Height = 7;               // Constant for the number of layers that the stack has. Given in (N-1) bits

  // The bus between PC and Stack is set to Z when WE_Stack = 0;
  assign BUS_Stack = (WE_Stack && !RE_Stack) ? Data_To_PC : 13'bz;

  always @(BUS_Stack or WE_Stack == 1'b1 or RE_Stack)
    begin

      // Receive data from PC
      if (!WE_Stack && RE_Stack)
        begin
          // Downward PUSH to all elements in the Stack register
          for (i = Height; i > 0 ; i = i - 1) Stack [i][12:0] = Stack [i-1][12:0];
          // First Stack address <- Bus
          Stack [0][12:0] = BUS_Stack;
        end

      // Send data to PC
      else if (WE_Stack && !RE_Stack)
        begin
          // Stack's first row is asigned to the Bus
          Datos_A_PC = Stack [0][12:0];
          // Upwards PUSH to all elements inside the stack register
          for (i = 0; i < Height ; i = i + 1) Stack [i][12:0] = Stack [i+1][12:0];
          Stack[Height][12:0] = 13'bx;
        end

    end

endmodule

Aquí está el banco de pruebas que estoy usando:

//----------------------------TESTBENCH--------------------------------


module testbench();

  // Inputs and Outputs
  logic WE_Stack, RE_Stack;
  logic [12:0] PC;
  wire [12:0] BUS_Stack;

  // Connection to module
  Stack STK (.WE_Stack(WE_Stack), .BUS_Stack(BUS_Stack), .RE_Stack(RE_Stack));

  // Assign statement used to simulate the Stack bus receiving data
  assign BUS_Stack = (!WE_Stack && RE_Stack) ? PC : 13'bz;

  initial
    begin
      $monitor("WE_Stack: %b \t RE_Stack: %b", WE_Stack, RE_Stack);

      #1 WE_Stack = 0; RE_Stack = 1;
      #1 PC = 13'd7;
      #1 PC = 13'd21;
      #1 PC = 13'd1;
      #1 PC = 13'd144;
      #1 PC = 13'd5;
      #3 WE_Stack = 1; RE_Stack = 0;
      #1 WE_Stack = 1; RE_Stack = 1;
      #1 WE_Stack = 1; RE_Stack = 0;
      #1 WE_Stack = 0; RE_Stack = 0;
      #1 PC = 13'd4;
      #1 PC = 13'd68;
    end

  initial
    begin
      #120 $finish;
      $dumpfile("dump.vcd");
      $dumpvars(1);
    end

endmodule

El problema aparece después de la línea

#3 WE_Stack = 1; RE_Stack = 0;

Se supone que el programa debe escribir en la PC solo una vez, pero cuando se simula, produce aproximadamente 7 operaciones de escritura en la PC.

    
pregunta Eddysanoli

2 respuestas

1

No estás cronometrando la pila. Eso significa que cada instante de simulación que se desencadena el bloque siempre provocará una escritura. Siempre se está activando la escritura siempre que es alta, y eso ocurre durante 3 unidades de tiempo, por lo que espero que esa declaración cause 3 escrituras. No sé por qué ves 7, pero más de 1 tiene sentido.

Casi siempre es mejor usar siempre @ * en lugar de una lista de sensibilidad pasada de moda.

Intente poner un punto y coma después de los retrasos en libras. Me olvido de lo que hace una libra en las tareas de una tarea.

    
respondido por el Matt
0

Gracias por la ayuda a todos. Después de un poco de debbugging, descubrí que la parte del código que causaba todos los problemas era la "asignación". La instrucción de asignación se actualiza tan pronto como finaliza el bucle for. Por lo tanto, si se registra una escritura en el BUS, el programa sale del bucle for pero vuelve a ingresarlo rápidamente después de que el BUS se actualice con los datos. El programa se convierte en un ciclo sin fin en el que el bucle for cambia los datos en el BUS y, debido a que el BUS se modifica, se ejecuta de nuevo.

    
respondido por el Eddysanoli

Lea otras preguntas en las etiquetas