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
```
asked Jan 3, 2023 at 22:42
\$\endgroup\$
1
  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. \$\endgroup\$ 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

answered Jan 4, 2023 at 22:43
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.