2
\$\begingroup\$

I am trying to generate images on a Samsung S22C300H monitor using the Diligent Nexys 7 board running the Xilinx Artix 7 FPGA. Even though the datasheet says the display supports 640x480, I was only able to get it to stop complaining about unsupported signals when stepping up the resolution to 1280x1024. This is the same resolution that the monitor runs at when displaying the OOB program as well. However, I cannot get the display to show anything. The red status light is constant on which means the display is getting valid sync signals. I cannot access the menu while in VGA mode only while my program is running. The menu works when running the OOB program.

I am trying to target VESA 1280x1024 @ 60Hz.

Below is my module, a testbench for it, the constraint file, and the datasheet for my monitor.

I am completely stumped here. The OOB program is written in VHDL which I don't understand and is way more complex than I am able to unravel.

I've read the other suggested threads to this one, and it seems like their issues are all different than mine. If you can get it to work on your monitor please let me know as well.

module GraphicsCard
#(
    parameter HSYNC_BITS = 11,
    parameter VSYNC_BITS = 11,
    
    parameter HD = 1280,                    // Display area
    parameter HF = 48,                      // Front porch
    parameter HR = 112,                     // Retrace/Sync
    parameter HB = 248,                     // Back Porch
    parameter HMAX = HD + HF + HR + HB - 1, // MAX counter value
    
    parameter VD = 1024,
    parameter VF = 1,
    parameter VR = 3,
    parameter VB = 38,
    parameter VMAX = VD + VF + VR + VB - 1
) (
    input Clk, Reset,
    
    input [11:0] SW,
    
    output VGA_HS, VGA_VS,
    output [11:0] RGB,
    output [11:0] LED
);

    // System Clock Buffer
    reg clkbuff;
    wire clkout;
    
    // Display timing counters
    reg [HSYNC_BITS-1:0] hcount = 0;
    reg [VSYNC_BITS-1:0] vcount = 0;
    
    // Sync signal registers, vertical counter enable register, and pixel enable register
    reg hsync = 0, vsync = 0, venable = 0, pixel_enable = 0;
    
    // Switch state buffer registers
    reg [11:0] switches;
    
    // Buffering the Clock
    always @ (Clk) begin
        clkbuff <= Clk;
    end
    
    assign clkout = clkbuff;
    
    // Horizontal counter
    always @ (posedge clkout or posedge Reset) begin
        if (Reset == 1'b1) begin
            hcount <= 0;
            venable <= 0;
        end
        else if (hcount < HMAX) begin
            hcount <= hcount + 1;
            venable <= 0;
        end
        else begin
            hcount <= 0;
            venable <= 1; // Allows the vertical counter to increment
        end
    end
    
    // Vertical counter
    always @ (posedge clkout or posedge Reset) begin
        if (Reset == 1'b1) vcount <= 0;
        else begin
            if (venable == 1'b1) begin
                if (vcount < VMAX) vcount <= vcount + 1;
                else vcount <= 0;
            end
        end
    end
    
    // Horizontal and Vertical sync signal generator
    always @ (posedge clkout or posedge Reset) begin
        if (Reset) begin
            hsync <= 1'b0;
            vsync <= 1'b0;
        end
        else begin
            hsync <= (hcount < HR) ? 1'b1 : 1'b0;
            vsync <= (vcount < VR) ? 1'b1 : 1'b0;
        end
    end
    
    // Assigning register values to outputs
    assign VGA_HS = hsync;
    assign VGA_VS = vsync;
    
    always @ (posedge clkout or posedge Reset) begin
        if (Reset) pixel_enable <= 1'b0;
        else
            if (hcount >= (HR+HB) && hcount < (HMAX-HF) && vcount >= (VR+VB) && vcount < (VMAX-VF)) pixel_enable <= 1'b1;
            else pixel_enable <= 1'b0;
    end
    
    
    // Buffering switch inputs
    always @ (SW) switches <= SW;
    
    // Assigning the current switch state to both view which switches are on and output to VGA RGB DAC
    assign LED = switches;
    assign RGB = (pixel_enable) ? switches : 12'b0;
endmodule
module GraphicsCard_tb ();

    reg Clk, Reset;
    
    reg [11:0] SW;
    
    wire VGA_HS, VGA_VS;
    wire [11:0] RGB, LED;
    
    GraphicsCard
    #(
        .HSYNC_BITS(11),
        .VSYNC_BITS(11)
    ) GraphicsCard (
        .Clk(Clk), .Reset(Reset), .SW(SW), .VGA_HS(VGA_HS), 
        .VGA_VS(VGA_VS), .RGB(RGB), .LED(LED)
    );
    
    initial begin
        Clk = 1'b0;
        forever #4.630 Clk <= ~Clk;
    end
    
    initial begin
        Reset = 1'b1;
        SW = 12'h000;
        #9.260
        Reset = 1'b0;
        #9.260 SW = 12'hFFF;
    end
endmodule
## Clock signal
set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33 } [get_ports { Clk }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
create_clock -add -name sys_clk_pin -period 9.260 -waveform {0 4.630} [get_ports {Clk}];

##Switches
set_property -dict { PACKAGE_PIN J15   IOSTANDARD LVCMOS33 } [get_ports { SW[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
set_property -dict { PACKAGE_PIN L16   IOSTANDARD LVCMOS33 } [get_ports { SW[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
set_property -dict { PACKAGE_PIN M13   IOSTANDARD LVCMOS33 } [get_ports { SW[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
set_property -dict { PACKAGE_PIN R15   IOSTANDARD LVCMOS33 } [get_ports { SW[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
set_property -dict { PACKAGE_PIN R17   IOSTANDARD LVCMOS33 } [get_ports { SW[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4]
set_property -dict { PACKAGE_PIN T18   IOSTANDARD LVCMOS33 } [get_ports { SW[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5]
set_property -dict { PACKAGE_PIN U18   IOSTANDARD LVCMOS33 } [get_ports { SW[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6]
set_property -dict { PACKAGE_PIN R13   IOSTANDARD LVCMOS33 } [get_ports { SW[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7]
set_property -dict { PACKAGE_PIN T8    IOSTANDARD LVCMOS18 } [get_ports { SW[8] }]; #IO_L24N_T3_34 Sch=sw[8]
set_property -dict { PACKAGE_PIN U8    IOSTANDARD LVCMOS18 } [get_ports { SW[9] }]; #IO_25_34 Sch=sw[9]
set_property -dict { PACKAGE_PIN R16   IOSTANDARD LVCMOS33 } [get_ports { SW[10] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10]
set_property -dict { PACKAGE_PIN T13   IOSTANDARD LVCMOS33 } [get_ports { SW[11] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11]

## LEDs
set_property -dict { PACKAGE_PIN H17   IOSTANDARD LVCMOS33 } [get_ports { LED[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
set_property -dict { PACKAGE_PIN K15   IOSTANDARD LVCMOS33 } [get_ports { LED[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
set_property -dict { PACKAGE_PIN J13   IOSTANDARD LVCMOS33 } [get_ports { LED[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
set_property -dict { PACKAGE_PIN N14   IOSTANDARD LVCMOS33 } [get_ports { LED[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]
set_property -dict { PACKAGE_PIN R18   IOSTANDARD LVCMOS33 } [get_ports { LED[4] }]; #IO_L7P_T1_D09_14 Sch=led[4]
set_property -dict { PACKAGE_PIN V17   IOSTANDARD LVCMOS33 } [get_ports { LED[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5]
set_property -dict { PACKAGE_PIN U17   IOSTANDARD LVCMOS33 } [get_ports { LED[6] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6]
set_property -dict { PACKAGE_PIN U16   IOSTANDARD LVCMOS33 } [get_ports { LED[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7]
set_property -dict { PACKAGE_PIN V16   IOSTANDARD LVCMOS33 } [get_ports { LED[8] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8]
set_property -dict { PACKAGE_PIN T15   IOSTANDARD LVCMOS33 } [get_ports { LED[9] }]; #IO_L14N_T2_SRCC_14 Sch=led[9]
set_property -dict { PACKAGE_PIN U14   IOSTANDARD LVCMOS33 } [get_ports { LED[10] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10]
set_property -dict { PACKAGE_PIN T16   IOSTANDARD LVCMOS33 } [get_ports { LED[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11]

##VGA Connector
set_property -dict { PACKAGE_PIN A3    IOSTANDARD LVCMOS33 } [get_ports { RGB[0] }]; #IO_L8N_T1_AD14N_35 Sch=vga_r[0]
set_property -dict { PACKAGE_PIN B4    IOSTANDARD LVCMOS33 } [get_ports { RGB[1] }]; #IO_L7N_T1_AD6N_35 Sch=vga_r[1]
set_property -dict { PACKAGE_PIN C5    IOSTANDARD LVCMOS33 } [get_ports { RGB[2] }]; #IO_L1N_T0_AD4N_35 Sch=vga_r[2]
set_property -dict { PACKAGE_PIN A4    IOSTANDARD LVCMOS33 } [get_ports { RGB[3] }]; #IO_L8P_T1_AD14P_35 Sch=vga_r[3]
set_property -dict { PACKAGE_PIN C6    IOSTANDARD LVCMOS33 } [get_ports { RGB[4] }]; #IO_L1P_T0_AD4P_35 Sch=vga_g[0]
set_property -dict { PACKAGE_PIN A5    IOSTANDARD LVCMOS33 } [get_ports { RGB[5] }]; #IO_L3N_T0_DQS_AD5N_35 Sch=vga_g[1]
set_property -dict { PACKAGE_PIN B6    IOSTANDARD LVCMOS33 } [get_ports { RGB[6] }]; #IO_L2N_T0_AD12N_35 Sch=vga_g[2]
set_property -dict { PACKAGE_PIN A6    IOSTANDARD LVCMOS33 } [get_ports { RGB[7] }]; #IO_L3P_T0_DQS_AD5P_35 Sch=vga_g[3]
set_property -dict { PACKAGE_PIN B7    IOSTANDARD LVCMOS33 } [get_ports { RGB[8] }]; #IO_L2P_T0_AD12P_35 Sch=vga_b[0]
set_property -dict { PACKAGE_PIN C7    IOSTANDARD LVCMOS33 } [get_ports { RGB[9] }]; #IO_L4N_T0_35 Sch=vga_b[1]
set_property -dict { PACKAGE_PIN D7    IOSTANDARD LVCMOS33 } [get_ports { RGB[10] }]; #IO_L6N_T0_VREF_35 Sch=vga_b[2]
set_property -dict { PACKAGE_PIN D8    IOSTANDARD LVCMOS33 } [get_ports { RGB[11] }]; #IO_L4P_T0_35 Sch=vga_b[3]
set_property -dict { PACKAGE_PIN B11   IOSTANDARD LVCMOS33 } [get_ports { VGA_HS }]; #IO_L4P_T0_15 Sch=vga_hs
set_property -dict { PACKAGE_PIN B12   IOSTANDARD LVCMOS33 } [get_ports { VGA_VS }]; #IO_L3N_T0_DQS_AD1N_15 Sch=vga_vs

[Samsung S22C300H Datasheet Link to Samsung.com][1] [1]: https://www.samsung.com/hk_en/support/model/LS22C300HS/XK/#downloads

UPDATE NEW CODE FROM COMMENTS

module GraphicsCard
#(
    parameter HSYNC_BITS = 11,
    parameter VSYNC_BITS = 11,
    
    parameter HD = 1280,                    // Display area
    parameter HF = 48,                      // Front porch
    parameter HR = 112,                     // Retrace/Sync
    parameter HB = 248,                     // Back Porch
    parameter HMAX = HD + HF + HR + HB - 1, // MAX counter value
    
    parameter VD = 1024,
    parameter VF = 1,
    parameter VR = 3,
    parameter VB = 38,
    parameter VMAX = VD + VF + VR + VB - 1
) (
    input Clk, Reset,
    
    input [11:0] SW,
    
    output VGA_HS, VGA_VS,
    output [11:0] RGB,
    output [11:0] LED
);
    
    // Display timing counters
    reg [HSYNC_BITS-1:0] hcount = 0;
    reg [VSYNC_BITS-1:0] vcount = 0;
    
    // Sync signal registers, vertical counter enable register, and pixel enable register
    reg hsync = 0, vsync = 0, pixel_enable = 0;
    
    // Switch state buffer registers
    reg [11:0] switches;
    
    // Horizontal counter
    always @ (posedge Clk or posedge Reset) begin
        if (Reset == 1'b1) begin
            hcount <= 0;
        end
        else if (hcount < HMAX) begin
            hcount <= hcount + 1;
        end
        else begin
            hcount <= 0;
        end
    end
    
    // Vertical counter
    always @ (posedge Clk or posedge Reset) begin
        if (Reset == 1'b1) vcount <= 0;
        else begin
            if (hcount == HMAX) begin
                if (vcount < VMAX) vcount <= vcount + 1;
                else vcount <= 0;
            end
        end
    end
    
    // Horizontal and Vertical sync signal generator
    always @ (posedge Clk or posedge Reset) begin
        if (Reset) begin
            hsync <= 1'b0;
            vsync <= 1'b0;
        end
        else begin
            hsync <= (hcount < HR) ? 1'b1 : 1'b0;
            vsync <= (vcount < VR) ? 1'b1 : 1'b0;
        end
    end
    
    // Assigning register values to outputs
    assign VGA_HS = hsync;
    assign VGA_VS = vsync;
    
    always @ (posedge Clk or posedge Reset) begin
        if (Reset) pixel_enable <= 1'b0;
        else
            if (hcount >= (HR+HB) && hcount < (HR+HB+HD) && vcount >= (VR+VB) && vcount < (VR+VB+VD)) pixel_enable <= 1'b1;
            else pixel_enable <= 1'b0;
    end
    
    
    // Buffering switch inputs
    always @ (SW) switches <= SW;
    
    // Assigning the current switch state to both view which switches are on and output to VGA RGB DAC
    assign LED = switches;
    assign RGB = (pixel_enable) ? switches : 12'b0;
endmodule
```
\$\endgroup\$
1
  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. \$\endgroup\$
    – Voltage Spike
    Commented Jan 4, 2023 at 21:44

1 Answer 1

2
\$\begingroup\$

For anyone reading, this is essential copying and reiterating the extended discussion.

The original code had a couple "off by one" errors. A PLL IP also needed to be instantiated to generate a 108 MHz pixel clock from the 100 MHz clock onboard the Nexys A7.

In order to correct the errors in the code, here were the changes:

  • Change hcount < (HMAX-HF) to hcount < (HR+HB+HD). That change fixes the horizontal timing issue.
  • Remove venable signal completely and change if (venable == 1'b1) begin to if (hcount == HMAX) begin. That fixes the one clock period delay issue between vertical sync and horizontal sync.
  • Change vcount < (VMAX-VF) to vcount < (VR+VB+VD). That change fixes the vertical timing issue.
  • Add PLL to generate 108 MHz clock from the 100 MHz system clock for the new resolution.

Hope this helps!

Some additional discussion:

The "off by one" issue was caused by the original developer incorrectly using HMAX and VMAX for counter comparisons. Remember that 1 is subtracted from the totals when both parameters are defined. The original developer did not account for this in the other areas of code. The subtraction throws off the if statement comparisons.

The venable signal causes a one flop delay between vertical sync and horizontal sync. The vertical sync counter vcount is enabled by venable. venable is essentially a set/reset flip-flop based off of hcount. The extra flop causes a one clock period delay between the sync signals.

Here are some instructions for instantiating a PLL: Digital Clock Manager FPGA

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.