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

Това, което се опитвам да направя, е да създам VGA контролер от Lattice MachXO CPLD във Verilog.

Проблемът

Опитвам се да покажа червения цвят с разделителна способност 640x480 @ 60Hz, използвайки 25,175 MHz часовник, вътрешен в CPLD; обаче, когато включа CPLD в монитор, получавам съобщение "Извън обхват"; никой монитор, който пробвам, не може да разбере каква резолюция бих искал.

Какво опитах

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

Числата, които използвам, за да генерирам числата си за времена, са от Tiny VGA: tinyvga.com/vga -време/640x480@60Hz

По-долу е моят код и снимки на времената от 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 на задната веранда >/

/‹ Counter rollover и V_SYNC >/


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


Отговори (2)


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

Ако не е това, най-вероятно е проблем с времето. Опитайте да използвате осцилоскоп, за да измерите честотата на вашите VSYNC сигнали - тя трябва добре да се подреди до 60Hz.

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

Свързано с отговора на @exhausted_engy (опитах се да направя това коментар, но не мога да разбера къде да го направя): много видео DAC имат щифтове за dac_blank и dac_sync точно за тази цел.

person Doov    schedule 03.06.2013