Pantalla de siete segmentos de Altera DE1

0

Lo que estoy tratando de hacer es usar la Clave 0 como contador ascendente y la clave 1 como contador descendente en el mismo programa. Puedo hacer eso por separado. Por lo tanto, cuando se activa la habilitación, al presionar la tecla 0 aumentará el valor mostrado en una pantalla de siete segmentos y al presionar la tecla 1 disminuirá el valor. El siguiente es mi código.

/*
This program uses SW0 as the enable swithch.
And Key 0 as a upcounter, Key 1 as a downcounter
*/

module seven_seg_single_up_down ( en, in_up, in_down, a, b, c, d, e, f, g );
input en;
input in_up, in_down;

output a, b, c, d, e, f, g;

reg a, b, c, d, e, f, g;
reg [3:0]i;

always @( posedge in_up, posedge in_down, negedge en ) begin
    if ( ~en )
        begin
            {a, b, c, d, e, f, g} = 7'b1111111;
            i = 0;
        end
    //else if (in_up) 
    //  i = i + 1;
    //else if (in_down and i > 0 )
    //  i = i - 1;
    //else begin

    else begin
        if ( in_up )
            i = i + 1;
        if ( in_down ) begin
            i = i - 1;
        end

        case(i)
            1:{a, b, c, d, e, f, g} = 7'b1001111;
            2:{a, b, c, d, e, f, g} = 7'b0010010;
            3:{a, b, c, d, e, f, g} = 7'b0000110;
            4:{a, b, c, d, e, f, g} = 7'b1001100;
            5:{a, b, c, d, e, f, g} = 7'b0100100;
            6:{a, b, c, d, e, f, g} = 7'b0100000;
            7:{a, b, c, d, e, f, g} = 7'b0001111;
            8:{a, b, c, d, e, f, g} = 7'b0000000;
            9: begin
                {a, b, c, d, e, f, g} = 7'b0000100;
                i = -1;
                end
            default: {a, b, c, d, e, f, g} = 7'b0000001;
        endcase
    end
end
endmodule

No entiendo qué es lo que está mal con el código anterior.

    
pregunta user20263

2 respuestas

1

Tu código no parece, en general, sintetizable para mí, ya que realmente no estás siguiendo ninguna convención de diseño síncrono. Espero que si inspeccionas tus registros de síntesis encontrarás varias advertencias y / o errores.

  1. Un bloque de borde activado siempre debe modelar un flip-flop, lo que significa que tiene un reloj de borde activado y un valor predeterminado activado y / o reinicio. No debe activarse en el borde de múltiples señales arbitrarias. @(posedge clk or negedge en) sería más apropiado, asumiendo que su fpga cuenta con una señal de reloj adecuada.

  2. Dentro de un bloque activado por flanco, generalmente debe usar asignaciones no bloqueantes: <= , en lugar de bloquear asignaciones: = , ya que esto modela más correctamente el comportamiento de un flip flop. Si no sabe lo que esto significa, haga una investigación entre la diferencia entre las tareas de bloqueo y las de no bloqueo.

Si desea usar elementos de memoria como un contador, entonces necesita usar la lógica sincronizada. En cada flanco de reloj puede verificar si in_up o in_down ha cambiado con respecto al valor anterior, y luego usarlo para decidir si desea aumentar o disminuir su valor de contador. Es posible que deba rebotar las señales de entrada si provienen de un botón o puede tener múltiples alternancias falsas cuando se presiona.

    
respondido por el Tim
0

Como señala Tim, las herramientas de síntesis se basan mucho en los patrones convencionales de su código.

Una forma convencional de codificar la lógica para i sería algo como esto

always @(posedge clk or posedge reset) begin
   if (reset) begin
      i <= 4'b0000;
   end
   else begin
      if (in_up) begin
         if (i == 4'b1001) begin
              i <= 4'b0000;
         end
         else begin
            i <= i + 1;
         end
      end
      else if (in_down) begin
         // example of trinary operator 
         i <= (i == 4'b0000) ? 4'b1001 : i - 1;
      end
   end  // if ~reset
end // always @(posedge clk or posedge reset)

Esto coloca toda la lógica que define las transiciones de estado de i en un solo lugar. También se asegura de que para cualquier conjunto de entradas, i se actualice exactamente una vez. Si bien algunas herramientas de síntesis pueden dar sentido a un código más complejo, en general es una buena práctica suponer que su herramienta es bastante estúpida y le dice explícitamente qué hacer.

También, date cuenta de que intenté escribir este código sin introducir muchas nuevas variables. Otros estilos podrían introducir, por ejemplo, un cable tc (para el recuento de terminales) para detectar la condición cuando i llega a 9 y utiliza eso simplifica la lógica de conteo ascendente. El uso del operador trinary ?: , como mostré en la lógica de conteo descendente, también es muy común en Verilog para reducir el número de líneas necesarias para expresar una lógica como esta.

    
respondido por el The Photon

Lea otras preguntas en las etiquetas