Múltiples salidas LED en FPGA usando Verilog

Hice un simple contador ascendente de 0 a 9 usando Verilog. La salida son 4 LED que se encienden cuando su bit correspondiente es 1. El código se sintetiza bien, pero en la FPGA, solo un LED se enciende y se apaga repetidamente. Los otros tres LED no se encienden en absoluto. Aquí está mi código:

module counter(
   input wire clock,
   input wire reset,

   output wire [3:0] o_number
);

reg [3:0] cur_state;
reg [3:0] next_state;

always @(posedge clock or posedge reset) begin
   if (reset) cur_state <= 4'b0;
   else 
    cur_state <= next_state;
end

// Next state function
always @(*) begin
   if (cur_state == 4'b1001) next_state = 4'b0000;
   else next_state = cur_state + 4'b0001;
end

 // Output function
assign o_number = cur_state;

endmodule

module display(
   input wire [3:0] inumber,

   output wire [3:0] LEDs
);

assign LEDs = inumber;

endmodule

Ninguno de los LED está roto, ya que todos se iluminan cuando se prueban individualmente. El reloj se ha ajustado para que su período sea de alrededor de 2 segundos.

Por favor, ayúdame. Gracias.

Revisé el módulo contador. Aquí están todos los archivos que usé:

arriba.v

module top ( input wire clock, input wire reset, output wire [3:0] LEDs);
counter c1 (.clock(clock), .reset(reset), .o_number(number));
display d1 (.inumber(number), .LEDs(LEDs));
endmodule

contador.v

module counter ( input wire clock, input wire reset, output wire [3:0] o_number);
reg [3:0] cur_state;
always @ (posedge clock or posedge reset) begin
    if (reset) cur_state[3:0] <= 4'b0000;
    else begin
        if (cur_state[3:0]==4'b1001) cur_state[3:0] <= 4'b0000;
        else cur_state[3:0] <= cur_state[3:0] + 4'b0001;
    end
end
assign o_number[3:0]=cur_state[3:0];
endmodule

mostrar.v

module display( input wire[3:0] inumber, output wire [3:0] LEDs);
assign LEDs[3:0] = inumber[3:0];
endmodule

superior.ucf

NET "LEDs[0]" LOC = K12;
NET "LEDs[1]" LOC = P14;
NET "LEDs[2]" LOC = L12;
NET "LEDs[3]" LOC = N14;

NET "clock" LOC = T9;
NET "reset" LOC = L14;
¿No le gustaría que el siguiente estado cambiara en la señal del reloj en lugar de *?
Está cambiando en el borde positivo del reloj.
Cambia al siguiente estado en el reloj pero cambia el estado de nextState en *
¿Sería eso un gran problema?
Tal vez no, pero no me parece bien
De hecho, estoy siguiendo una guía que me dice que separe un FSM en lógica secuencial, función de siguiente estado y función de salida.
No hay nada malo desde la perspectiva de Verilog. Supongo que solo el LED asignado LEDs[3]es el único que se enciende. Si ese es el caso, intente reducir la velocidad de su reloj a 1/4 de su frecuencia actual. Si eso no funciona, vuelva a verificar el mapeo en su top.ucf
Ah, otra cosa. La mayoría de los FPGA tienen un número limitado de flops con reinicio/preajuste asíncrono. Dado que su código se sintetiza correctamente, no debería tener ningún problema, pero es posible que desee considerar cambiar al reinicio síncrono. Eliminar or posedge resetpara que sea un reinicio síncrono. Dudo que la asincronía sea el problema, creo que la frecuencia del reloj es probablemente el problema.

Respuestas (2)

Hubo un problema con el módulo superior. No declaré el cable que se usa para conectar el módulo de visualización y contador.

Aquí está el top.v revisado:

module top ( input wire clock, input wire reset, output wire [3:0] LEDs);
wire [3:0] number;
counter c1 (.clock(clock), .reset(reset), .o_number(number));
display d1 (.inumber(number), .LEDs(LEDs));
endmodule

Los LED se encienden correctamente según cada estado ahora.

Debería haber advertencias o errores al respecto. ¿Puede compilar con esta declaración y sin ella y ver la diferencia en los mensajes del compilador/sintetizador?
En realidad, no hubo advertencias ni mensajes que indicaran este problema. La documentación dice que cuando no se especifica ningún cable en el módulo superior, se asume automáticamente un cable de un bit. Por lo tanto, obtuve el resultado en el que solo funcionaba un LED.

Supongo que el problema puede estar en el uso cur_statey next_statesin índices. Intentar

always @(posedge clock or posedge reset) begin
    if (reset) cur_state[3:0] <= 4'b0;
    else begin
        cur_state[3:0] <= next_state[3:0];
end

always @(*) begin
    if (cur_state[3:0] == 4'b1001) next_state[3:0] <= 4'b0000;
    else next_state[3:0] <= cur_state[3:0] + 4'b0001;
end

y

assign o_number[3:0] = cur_state[3:0];

y

assign LEDs[3:0] = inumber[3:0];

Tenga en cuenta que agrego [3:0]en todas partes y cambio =a <=en la segunda alwaysconstrucción.

El objetivo se puede lograr mediante una configuración mucho más simple:

module counter(
input wire clock,
input wire reset,
output wire [3:0] LEDs
);

reg [3:0] cur_state;
wire reset_n=~reset;
assign LEDs[3:0] = cur_state[3:0];

always @(posedge clock or negedge reset_n) begin
    if (!reset_n) cur_state[3:0] <= {4{1'b0}};
    else begin
        if (cur_state[3:0] == 4'b1001) cur_state[3:0] <= {4{1'b0}};
        else cur_state[3:0] <= cur_state[3:0] + 4'b1;
    end
end

Actualización: no ayudó; lo primero que debe hacer es asignar LEDs[3:0]y 4'b1111ver si todos los LED están encendidos.

La siguiente posible causa del problema es always @(*) beginque se activa con el cambio de cualquier cable de entrada para la alwaysconstrucción de contenido. El único evento que ocurre cuando emite reinicio y cur_statecambia a 0, y por lo tanto cur_statese convierte en 4'b0001 y mantiene este valor.

Actualización 1: Entonces tienes LSB funcionando, otros 3 bits no funcionan. Probó que todos los LED están encendidos cuando escribe 4'b1111 en los cables de los LED. Creo que el código es correcto, hay algo más que está mal. Considera lo siguiente:

  • simplificar el cambio de decimal a hexadecimal. En este caso, solo tendrá cur_state[3:0] <= cur_state[3:0] + 4'b1;sin ninguna condición verificar el estado # 10

    always @ (posedge clock or posedge reset) begin if (reset) cur_state[3:0] <= 4'b0000; else cur_state[3:0] <= cur_state[3:0] + 4'b0001; end

  • considerar lo que sucede resetdurante la prueba. ¿Estás seguro de que es constante bajo? Alternativamente, elimínelo de la configuración:

    always @ (posedge clock) begin cur_state[3:0] <= cur_state[3:0] + 4'b0001; end

  • sintetice mi código anterior con solo un módulo y reset_nvea si no funciona también.

  • intente usar otros LED:

    always @ (posedge clock) begin cur_state[3:1] <= cur_state[3:1] + 3'b001; end

Gracias por tu respuesta, pero no resolvió el problema. También quiero implementarlo usando dos módulos, por lo que no es necesaria la simplificación. Por cierto, estoy usando la placa Spartan 3 FPGA.
Actualicé la respuesta. Creo que la causa del problema es always @(*). Puede conservar dos módulos, pero no debería haber necesidad de complicar el primer módulo con dos construcciones always. La implementación debe ser lo más concisa y legible posible: este es un objetivo de cualquier lenguaje de programación, incluido Verilog.
No entiendo muy bien el último párrafo de tu respuesta. ¿Puedes explicarlo de nuevo?
Intenté todas sus sugerencias, pero aún nada funcionó.
Agregue su nuevo código a la pregunta (pero no elimine el antiguo). No puedo adivinar lo que intentaste. ¿Probó que todos los LED funcionan escribiendo todos los 1 en el registro de salida? Mi último párrafo dice que always @(*)parece que no realiza lo que quiere de él. RTFM sobre lo que hace y, lo más importante, cuándo.
Probé que todos los LED funcionan tal como lo pediste. Publiqué todos los códigos que usé, por lo que sería genial si pudieras echarles un vistazo.
Bien, si miras mi código, puedes ver que uso negedge de reinicio invertido. Por favor, intente de esta manera. alwaysEn mi opinión, su condición actual debería causar que no se puedan hacer coincidir los operandos en la condición con los bordes correspondientes en el control de evento adjunto del error de construcción siempre. También explique cómo no funciona ahora.
Lo intenté, pero no recibo ningún error y el código se sintetiza bien. Sin embargo, en la placa FPGA, el LED LSB se enciende después del primer reloj, luego, en el siguiente reloj, se apaga sin que se enciendan otros LED. Entonces, solo el LED LSB (LED [0]) se enciende y apaga repetidamente.
Actualicé la respuesta con la actualización # 1. Su último código me parece bien, por lo que debe excluir declaración por declaración para ver cuándo comienza a funcionar como se esperaba.
Gracias por toda tu ayuda. El problema fue que no declaré cable extra en el módulo superior. Gracias.