6 votos

Problemas con el controlador VGA en el CPLD

Lo que estoy intentando hacer es crear un controlador VGA a partir de un Lattice MachXO CPLD en Verilog.

El problema

Estoy intentando mostrar el color rojo con una resolución de 640x480 @ 60Hz usando un reloj de 25.175 MHz interno al CPLD; sin embargo, cuando conecto el CPLD a un monitor obtengo un mensaje "Out of Range"; ningún monitor que pruebe puede entender la resolución que quiero.

Lo que he probado

He simulado el código en ModelSim (imágenes incluidas), y todo parece estar bien excepto por un problema. Cuando cuento la cantidad de pasos de tiempo que han ocurrido desde el durante la zona de visualización de V-Sync (cuando H-Sync está dibujando) y lo divido por la frecuencia de H-Sync, obtengo 479 pulsos - uno menos de las 480 líneas que debería estar dibujando. No entiendo de dónde puede venir esto, ya que he comprobado mis tiempos muchas veces, y sospecho que esto puede ser un síntoma del problema, pero no estoy seguro.

Los números que estoy utilizando para generar mis números para los tiempos es de Tiny VGA: tinyvga.com/vga-timing/640x480@60Hz En lugar de contar líneas para V_SYNC estoy contando pulsos de reloj, sin embargo, los números deberían ser equivalentes (es decir, 2 800 líneas de conteo = 1600 pulsos). Es posible que más adelante cambie este comportamiento a conteo de líneas.

Abajo está mi código, y las imágenes de los tiempos de ModelSim.

module Top(RESET, H_SYNC, V_SYNC, RED);
    input  wire RESET;
    output wire H_SYNC;
    output wire V_SYNC;
    output wire RED;

    wire rgb_en;

    /*** Test Bench Code ***/
     //reg osc_clk, reset;
     //initial begin
         //#0 reset     = 0;
         //#0 osc_clk = 0;
         //#2 reset     = 1;
     //end

     //always #1 osc_clk = ~osc_clk;

    OSCC        OSCC_1 (.OSC(osc_clk)); /*< IP clock module for Lattice CPLD    >*/
    Controller  CNTRL(.NRST(RESET), .CLK(osc_clk), .H_SYNC(H_SYNC), .V_SYNC(V_SYNC), .RGB_EN(rgb_en));

    assign RED = (rgb_en ? 1:1'bz); 

endmodule

module Controller(CLK, NRST, H_SYNC, V_SYNC, RGB_EN);
    input  wire CLK;        /*< CLK input from Top module   >*/
    input  wire NRST;       /*< Reset input from Top module >*/
    output reg  H_SYNC;     /*< Goes to VGA Horizontal Sync >*/
    output reg  V_SYNC;     /*< Goes to VGA Verical Sync    >*/
    output reg  RGB_EN  ;   /*< Enables RGB values durning display time on H_SYNC >*/

    reg [9:0] h_counter;   /*< Tracks amount of pulses from CLK                 >*/
    reg [18:0] v_counter;  /*< Tracks amount of pulses from H_SYNC              >*/

    `define H_SYNC_PULSE        10'd96      /*< Length of Sync Pulse            >*/
    `define H_BACK_PORCH_END    10'd144     /*< Pulse len + Porch Len           >*/
    `define H_FRONT_PORCH_STRT  10'd784     /*< Front Porch Len - Max           >*/
    `define H_COUNT_MAX         10'd799     /*< Max line pulses for resolution  >*/

    `define V_SYNC_PULSE        19'd1600    /*< 2 H_SYNC lines       >*/
    `define V_BACK_PORCH_END    19'd28000   /*< 33+2 H_SYNC lines    >*/
    `define V_FRONT_PORCH_STRT  19'd412000  /*< 525-10 H_SYNC lines  >*/
    `define V_COUNT_MAX         19'd419999  /*< 525 H_SYNC lines     >*/

    /*** Logic for H_SYNC ***/
    always @(*) begin
        if (h_counter < `H_SYNC_PULSE) begin
            H_SYNC = 0;
            RGB_EN = 0;
        end
        /* If H_Sync is in the display zone, enable RGB */
        else if (h_counter > `H_BACK_PORCH_END && h_counter < `H_FRONT_PORCH_STRT) begin
            H_SYNC = 1;
            RGB_EN = 1;
        end
        /* During the Front Porch period, disable RGB */
        else begin
            H_SYNC = 1;
            RGB_EN = 0;
        end
    end

    /*** Logic for V_SYNC ***/
    always @(*) begin
        if (v_counter < `V_SYNC_PULSE) begin
            V_SYNC = 0;
        end
        else begin
            V_SYNC = 1;
        end
    end

    /*** Counter logic ***/
    always @(posedge CLK) begin
        if (h_counter >= `H_COUNT_MAX || !NRST) begin
            h_counter <= 11'b00;
        end
        else begin
            h_counter <= h_counter + 1;
        end
    end

    always @(posedge CLK) begin
        if (v_counter >= `V_COUNT_MAX || !NRST) begin
            v_counter <= 11'b00;
        end
        else begin
            v_counter <= v_counter + 1;
        end
    end

endmodule

H/V_SYNC and their respective counters w.r.t each other

1 votos

Deberías incluir en tu pregunta las formas de onda reales medidas con un osciloscopio. He encontrado pocas razones para confiar en las simulaciones lógicas programables.

0 votos

Un comentario general: en tu código, dices que estás haciendo "máquinas de estado" para V_SYNC y H_SYNC, pero me parece que esos bloques de siempre sólo harán lógica combinacional. La única cosa parecida a una máquina de estado que tienes actualmente es el contador.

0 votos

Estoy de acuerdo. El comentario ha sido editado.

5voto

GSerg Puntos 33571

Es necesario mantener la salida H_SYNC en funcionamiento incluso cuando V_SYNC está activo.

0 votos

Gracias Dave, he encontrado material que también confirma tu respuesta. Desde entonces he ajustado el código para que la salida H_SYNC esté siempre en marcha, y actualizaré las imágenes tan pronto como pueda hoy mismo. Desafortunadamente, el problema aún persiste; todavía estoy recibiendo errores de "Fuera de Rango".

2voto

Will Read Puntos 39

Por fin he dado con mi problema. En la documentación del CPLD y por sugerencias de mis profesores, pensé que el reloj interno del CPLD era configurable. Resulta que lo que estaba leyendo era el margen de error del reloj, no la programabilidad. Mi problema es que el oscilador interno no ha estado funcionando a 25,175 MHz como yo pensaba.

En caso de que algún otro alma venga a buscar esto en Google, que se sepa que el Lattice MachXO 2280 no puede ser usado para la salida VGA debido al valor aleatorio y la falta de programación del reloj sin usar un oscilador externo.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X