Проблемы с контроллером VGA на CPLD

Я пытаюсь создать контроллер VGA из Lattice MachXO CPLD в Verilog.

Проблема

Я пытаюсь отобразить красный цвет с разрешением 640x480 при 60 Гц, используя тактовую частоту 25,175 МГц, внутреннюю для CPLD; однако, когда я подключаю CPLD к монитору, я получаю сообщение «Out of Range»; нет монитора, я пытаюсь понять, какое разрешение я бы хотел.

Что я пробовал

Я смоделировал код в ModelSim (включая изображения), и все выглядит хорошо, за исключением одной проблемы. Когда я подсчитываю количество временных шагов, которые произошли в зоне отображения V-Sync (когда рисует H-Sync), и делю его на частоту H-Sync, я получаю 479 импульсов - один меньше 480 линии, которые я должен рисовать. Я не понимаю, откуда это могло произойти, поскольку я много раз проверял свои тайминги и подозреваю, что это может быть признаком проблемы, но я не уверен.

Числа, которые я использую для генерации чисел для таймингов, взяты из Tiny VGA: tinyvga.com/vga -timing / 640x480 @ 60 Гц

Ниже мой код и изображения таймингов от 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 [10:0] h_counter;   /*< Tracks amount of pulses from CLK                    >*/
    reg [19:0] v_counter;   /*< Tracks amount of pulses from H_SYNC                 >*/

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

    `define V_SYNC_PULSE        19'd1600
    `define V_BACK_PORCH_END    19'd28000
    `define V_FRONT_PORCH_STRT  19'd412000
    `define V_COUNT_MAX         19'd419999

    /*** State Machine for H_SYNC ***/
    always @(*) begin
        /* If the vertical sync line is not in the display zone, keep H_Sync low */
        if(!(v_counter > `V_BACK_PORCH_END && v_counter < `V_FRONT_PORCH_STRT)) begin
            H_SYNC = 0;
            RGB_EN = 0;
        end
        /* If the vertical sync line is in display zone, allow H_Sync to go through its procedure */
        else 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
    end

    /*** State Machine 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_counter на заднем крыльце> /

/ ‹Счетчик опрокидывания и V_SYNC> /


person Jon.H    schedule 09.04.2013    source источник
comment
Как вы пришли к подсчету тиков для определения? Я не говорю, что они ошибаются, но, возможно, добавление математики к вашему сообщению может помочь. Например, если я посмотрю на V_COUNT_MAX * ваша частота, я получу 16,55 мс (60,4 Гц), в то время как в ссылке VGA, которую вы указали, время кадра должно быть 16,68 мс (60 Гц). Также время между передним и задним крыльцом (408800 - 28000) / 800, я думаю, всего 476 строк, а не 480.   -  person Tim    schedule 09.04.2013
comment
Спасибо, Тим. Я, должно быть, забыл отправить свой код в репо, когда вернулся домой и сделал это сообщение, так как это старые числа. Значение V_COUNT_MAX должно быть 419999, а V_FRONT_PORCH_STRT должно равняться 412000, что дает мне значение 59,94 Гц. Я отредактировал сообщение, чтобы отразить правильные числа, и это были единственные различия между моей копией в лаборатории и дома. К сожалению, проблема не устранена.   -  person Jon.H    schedule 10.04.2013


Ответы (2)


Каждый монитор VGA, с которым я работал, требует, чтобы красный, зеленый и синий сигналы были равны нулю в периоды гашения (HSYNC | VSYNC). Вместо назначения z (высокий импеданс) попробуйте assign RED = (rgb_en ? 1'b1 : 1'b0);. Вам также нужно будет сделать это с ЗЕЛЕНЫМ и СИНЕМ (или просто присвоить им 0 навсегда).

Если это не так, скорее всего, проблема в сроках. Попробуйте использовать осциллограф для измерения частоты ваших сигналов VSYNC - она ​​должна точно соответствовать 60 Гц.

person exhausted_engy    schedule 01.06.2013
comment
Это действительно вопрос времени. Проблема заключалась в CPLD, возглавляемом моим профессором, и плохой документации, я думал, что внутренние часы были программируемыми, хотя на самом деле то, что я читал, была погрешностью. Если кто-то еще наткнется на это, Lattice MachXO 2280C CPLD не может использоваться для управления дисплеем VGA без внешних часов. Спасибо за ответ, утомился. - person Jon.H; 06.06.2013

Относится к ответу @exhausted_engy (пытался сделать это комментарием, но не могу понять, где это сделать): многие видео ЦАП имеют контакты для dac_blank и dac_sync именно для этой цели.

person Doov    schedule 03.06.2013