HDL Implementation of Video Generator Test for 16-bit PVB's

Topics relating to PALs, CPLDs, FPGAs, and other PLDs used for the support or creation of 65-family processors, both hardware and HDL.
Post Reply
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by Arlet »

ElEctric_EyE wrote:
@Arlet. I'm trying to 'up' the resolution to 1024x768x60Hz by using the settings shown in the tinyvga site. Can your vga module go up to this 1024 horizontal resolution? I've changed all the parameters to match the tinyvga site, I also made the odd parameters even, by adding 1, since your counters seem to subtract by 2...
My counters do not subtract by two:

Code: Select all

// adjust down counter. Reload when it's done.
always @(posedge clk50)
        if( pclk ) begin
             if( hcount_done )
                  hcount <= { 1'b0, hload };
             else
                  hcount <= hcount - 1;
        end
I do subtract two when loading the initial counter value, because my counter counts all the way down to -1 before stopping, but that works just as well with odd values (they just need to be bigger than 1). You do need to make sure you have enough bits. The hload en vload registers should be wide enough to hold the counter values, but hcount en vcount should be 1 bit bigger. Also the hcount_done and vcount_done signal should look at the new highest bit.

By the way, the current code divides the main clock into a pixel clock, but at higher pixel clocks, it would be easier to use the main clock directly as the pixel clock, without dividing. You should be able to reach 1280x1024x60 Hz that way.
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by ElEctric_EyE »

Arlet wrote:
...You should be able to reach 1280x1024x60 Hz that way.
I think you have just helped me to finalize v1.0h, for a most expensive option, if one were to win the lottery! That leftover gclk pin might be used for A21 on a 4MB SyncRAM (now @$155US). That would allow for a framebuffer at 1280x1024. EDIT: no, no, no. I must have a mental block or something. At 108MHz, that would assume an FPGA delay of about 3ns. Might work for a simple read only design we are now working on, but not for a full-fledged design...

Thanks for the suggestions, I'll try them out tonight, and aim for that resolution tomorrow on my day off.
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by Arlet »

ElEctric_EyE wrote:
I think you have just helped me to finalize v1.0h, for a most expensive option, if one were to win the lottery! That leftover gclk pin might be used for A21 on a 4MB SyncRAM (now @$155US). That would allow for a framebuffer at 1280x1024. EDIT: no, no, no. I must have a mental block or something. At 108MHz, that would assume an FPGA delay of about 3ns. Might work for a simple read only design we are now working on, but not for a full-fledged design...
The delay is not a problem. There's 15 ns delay in a 10-foot VGA cable, and you don't notice that, do you ?

Assuming you can push your RAM to 133 MHz, it will take 9.62 usecs to read 1280 pixels @ 16 bits. A line takes 15.63 usecs, so you have 6 usecs left for writing, plus another 656 usecs during vertical blank. It's not much compared to what a modern PC can do, but still perfectly usable.
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by ElEctric_EyE »

Arlet wrote:
...The delay is not a problem. There's 15 ns delay in a 10-foot VGA cable, and you don't notice that, do you ?...
That is not a problem since the delay is after the output. But I am thinking ahead to when there's a cpu writing and reading from the RAM. Surely the delay is a concern here, which is why I add an estimated delay of the FPGA to the RAM delay to get an idea of the overall top speed.
Arlet wrote:
...it would be easier to use the main clock directly as the pixel clock...
I am having a problem trying to do this. It is giving me a nasty little message "This design may not be routable!..." I am using a DCM to get the 108MHz from 100MHz. It has 4 108MHz outputs. 1 goes to your HVSYNC(vga.v) module, 1 goes to the SDRAMif module, 1 goes offchip to the SyncRAM clk, and 1 goes to the videoDAC clk. The 108MHz has been verified by 'scope. Here are the 2 modules:

Code: Select all

/*
 * vga.v 
 *
 * VGA timing generator
 *
 * This module only generates the VGA sync signals and control signals
 * for the actual video generator. Add a suitable video generator to 
 * create real outputs.
 *
 * +-------+       +-----------------+
 * | vga.v | ----> | video generator | ----> RGB outputs
 * +---+---+	   +-----------------+
 *     | 
 *     `-----------------------------------> Hsync/Vsync ouputs 
 *
 * The hstart/vstart and blank signals are short enable pulses with a 
 * width equal to the pixel clock (pclk). They are intended to drive 
 * a state machine in the video generator. All outputs are fully
 * registered. The 'hstart' pulse signals that next pclk will shift out
 * the leftmost pixel of each line. The 'hblank' pulse signals that the
 * next pclk must be blanked. Likewise, the 'vstart' and 'vblank' enables
 * do the same thing for vertical blanking, but with less precise timing. 
 *
 * So, use the vstart/vblank to update state machine, and use hstart/hblank
 * for pixel timing. 
 *
 * The hsync/vsync signals are delayed by 1 pclk period with 
 * respect to the vstart/hstart/blank signals. It is intended that 
 * the video generator will introduce a 1 pclk pipeline delay so that
 * the signals will align again. If the video generator requires a 
 * larger delay, the hsync and vsync signals need to be delayed as well.
 *
 * The design has been optimised for speed (>200 MHz on Spartan-3
 * with ISE 9.2 and one-hot FSM encoding selected).
 *
 * (C) Arlet Ottens, <arlet@c-scape.nl>
 */
module vga( input pclk,			
			   //output reg pclk = 0,	// pixel clock
			   output reg hsync,		// horizontal sync
			   output reg vsync,		// vertical sync
			   output reg hstart,		// line start on next clock
			   output reg vstart,		// field starts on next clock
			   output reg hblank = 1,	// hblank on next clock
			   output reg vblank = 0	// vblank on next clock
			   );
// timing parameters
parameter 
    HFRONT  = 10'd48,		// front porch (+right border)
    HVIDEO  = 10'd1280,		// active video area 
    HSYNC   = 10'd112,		// hsync 
    HBACK   = 10'd248;		// back porch  (+left border)

parameter
    VFRONT  = 10'd3,		// front porch (+bottom border)
    VVIDEO  = 10'd1024,		// active vide area
    VSYNC   = 10'd3,		// vsync
    VBACK   = 10'd38;  // back porch  (+top border)

// states (used for both H and V state machines)
parameter
    VIDEO  = 2'd0,
    FRONT  = 2'd1,
    SYNC   = 2'd2,
    BACK   = 2'd3;

// horizontal counters and state
reg [11:0] hcount = 0;		// down counter for horizontal state 
reg [10:0] hload;		// next load value
reg [1:0] hstate = FRONT;	// horizontal state
wire hcount_done = hcount[11];	// done when count < 0

// vertical counters and state
reg [11:0] vcount = 0;		// down counter for vertical state
reg [10:0] vload;		// next load value
reg [1:0] vstate = FRONT;	// horizontal state
wire vcount_done = vcount[11];	// done when count < 0

// enable signal for V state machine
wire venable = (hstate == FRONT) & hcount_done & pclk;

// make 25 MHz pixel clock from 50MHz input clock
//always @(posedge clk50)
	//pclk <= ~pclk;

// preload next timer value depending on state
// subtract 2 from timing value to compensate for pipeline delays
// This should be synthesized as a small LUT ROM, so it's quite
// efficient.
always @(posedge pclk)
	hload <= (hstate == BACK)  ? HVIDEO - 2:
	         (hstate == VIDEO) ? HFRONT - 2:
		 (hstate == FRONT) ? HSYNC  - 2:
		  		     HBACK  - 2;

// do the same for vertical 
always @(posedge pclk)
	vload <= (vstate == BACK)  ? VVIDEO - 2:
	         (vstate == VIDEO) ? VFRONT - 2:
		 (vstate == FRONT) ? VSYNC  - 2:
		  		     VBACK  - 2;

// adjust down counter. Reload when it's done.
always @(posedge pclk) 
	//if( pclk ) begin
	     if( hcount_done )
		  hcount <= { 1'b0, hload };
	     else
		  hcount <= hcount - 1;
	//end

// when down counter is done, go to next state
always @(posedge pclk)
	if( hcount_done ) 
	    case( hstate )
		    VIDEO : hstate <= FRONT;
		    FRONT : hstate <= SYNC;
		    SYNC  : hstate <= BACK;
		    BACK  : hstate <= VIDEO;
	    endcase

// start of active line
always @(posedge pclk)
	//if( pclk )
	    hstart <= (hstate == BACK) & hcount_done & ~vblank;

// vstart pulse to signal end of vertical blanking
always @(posedge pclk)
	//if( pclk )
	    vstart <= (vstate == BACK) & venable & vcount_done;

// adjust down counter. Reload when it's done.
always @(posedge pclk) 
	if( venable ) begin
	     if( vcount_done )
		  vcount <= { 1'b0, vload };
	     else
		  vcount <= vcount - 1;
	end

// when down counter is done, go to next state
always @(posedge pclk)
	if( venable & vcount_done ) 
	    case( vstate )
		    VIDEO : vstate <= FRONT;
		    FRONT : vstate <= SYNC;
		    SYNC  : vstate <= BACK;
		    BACK  : vstate <= VIDEO;
	    endcase

// update registered outputs
always @(posedge pclk) begin
	//if( pclk ) begin
	    hsync  <= hstate == SYNC;
	    vsync  <= vstate == SYNC;
	    hblank <= (vstate == VIDEO) & (hstate == VIDEO) & hcount_done;
	    vblank <= vstate != VIDEO;
	//end
end

endmodule

Code: Select all

module SRAMif( output reg [20:0] SRAddr = 0,
					output reg WEn = 1,
					output reg SRCS = 1,
					input [15:0] SRD,
					output reg [4:0] Red_data,
					output reg [5:0] Green_data,
					output reg [4:0] Blue_data,
					output reg DACBLANKn = 1,
					//input clk50,
					input pclk,
					input hstart,
					input vstart,
					input hblank
					);

reg [15:0] SRDtemp;
reg countflag;

always @(posedge pclk)
   //if ( pclk )
      if ( hstart )
         countflag <= 1;	//countflag active in display area
      else if ( hblank )
         countflag <= 0;
		
always @(posedge pclk)
	if ( vstart )	//reset address counter at top left of screen
		SRAddr <= 0;
	else if ( countflag )
		SRAddr <= SRAddr + 1;			//increment RAM address counter
		
always @(posedge pclk)
	if ( countflag )
		begin
			SRDtemp <= SRD;	//latch incoming data
			Red_data <= hblank ? 0 : SRDtemp [15:11];		//outgoing data to videoDAC
			Green_data <= hblank ? 0 : SRDtemp [10:5];
			Blue_data <= hblank ? 0 : SRDtemp [4:0];
		end
			
endmodule

Last edited by ElEctric_EyE on Sat Oct 06, 2012 12:06 am, edited 1 time in total.
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by Arlet »

ElEctric_EyE wrote:
That is not a problem since the delay is after the output. But I am thinking ahead to when there's a cpu writing and reading from the RAM. Surely the delay is a concern here, which is why I add an estimated delay of the FPGA to the RAM delay to get an idea of the overall top speed.
There would only be potential problem when switching between read and write. When doing a burst of reads or a burst of writes, the delay is not an issue. Switching between read/write can be minimized by buffering data, so you switch between bursts of reads and bursts of writes as much as possible.
Quote:
I am having a problem trying to do this. It is giving me a nasty little message "This design may not be routable!..." I am using a DCM to get the 108MHz from 100MHz. It has 4 108MHz outputs. 1 goes to your HVSYNC(vga.v) module, 1 goes to the SDRAMif module, 1 goes offchip to the SyncRAM clk, and 1 goes to the videoDAC clk. The 108MHz has been verified by 'scope. Here are the 2 modules:
Try using only one DCM output, and feed that in the input of a global clock buffer, and use the output as a main clock (clk108) for everything (assign pclk = clk108 should work)
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by ElEctric_EyE »

Arlet wrote:
Try using only one DCM output, and feed that in the input of a global clock buffer, and use the output as a main clock (clk108) for everything (assign pclk = clk108 should work)
Ok, I did this in both modules. Going back to your original code in your module, I substituted clk108 for clk50, commented out the pclk <= ~pclk portion, and added assign pclk = clk108 after parameter definitions. Also had to change

Code: Select all

output reg pclk
to

Code: Select all

output pclk
because of an error "target <pclk> should be of net type".
In my module I used the same pclk= clk108 assignment.

It still doesn't like something. Message is "Global clock driving non-clock load pins", then goes on to list 30 pins and message too long >1K. Any ideas? Sorry about this.
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by Arlet »

ElEctric_EyE wrote:
It still doesn't like something. Message is "Global clock driving non-clock load pins", then goes on to list 30 pins and message too long >1K. Any ideas? Sorry about this.
Maybe this

Code: Select all

wire venable = (hstate == FRONT) & hcount_done & pclk;
Take out the "& pclk" at the end.
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by ElEctric_EyE »

That got it to pass, but still nothing. (Got rid of the pclk=clk108 assignment in my module as this was an error)

I made a new project file to start fresh, in case I confused ISE. I set the parameters back down to 640x480 and made the clk108 input 25MHz, which I can see on the 'scope. My address counter is not working as I am not seeing activity on the RAM's address bus. No activity on HSYNC or VSYNC either. I think the assignment is somehow messing things up.

I think I will try to go one more step back and get the original working again, then move towards a single clock without the assignment statement.
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by Arlet »

To get the 108 MHz off-chip, you'll need to use a DDR flip-flop, too.
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by ElEctric_EyE »

Arlet wrote:
To get the 108 MHz off-chip, you'll need to use a DDR flip-flop, too.
Right, got that squared away. Little experience from last 2 projects goes a long way.

Not too difficult to make the board run @640x480x60Hz using 1 clk. I just had to remove all references to pclk.

When trying to step up to 1024x768, I increased the clk to 65MHz changed the H&V counters to:

Code: Select all

// horizontal counters and state
reg [11:0] hcount = 0;		// down counter for horizontal state 
reg [10:0] hload;		// next load value
...
wire hcount_done = hcount[11];	// done when count < 0

// vertical counters and state
reg [10:0] vcount = 0;		// down counter for vertical state
reg [9:0] vload;		// next load value
...
wire vcount_done = vcount[10];	// done when count < 0
and used these settings from tinyvga:

Code: Select all

// timing parameters
parameter 
    HFRONT  = 10'd24,		// front porch (+right border)
    HVIDEO  = 10'd1024,		// active video area 
    HSYNC   = 10'd136,		// hsync 
    HBACK   = 10'd160;		// back porch  (+left border)

parameter
    VFRONT  = 10'd3,		// front porch (+bottom border)
    VVIDEO  = 10'd768,		// active vide area
    VSYNC   = 10'd6,		// vsync
    VBACK   = 10'd29;  // back porch  (+top border)
These settings do not appear correct. The monitor blinks for a second then goes black, and I can hear the crt gun frequency as it is within hearing range. Horizontal back porch seems awfully high doesn't it? The back porch in 640x480x60Hz was 48 clocks.
EDIT: The monitor does not like the 75MHz/70Hz settings either.
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by Arlet »

Code: Select all

// timing parameters
parameter 
    HFRONT  = 10'd24,	    // front porch (+right border)
    HVIDEO  = 10'd1024,	  // active video area 
    HSYNC   = 10'd136,		// hsync 
    HBACK   = 10'd160;		// back porch  (+left border)
The notation "10'd" means a 10 bit decimal. In this case, the HVIDEO requires 11 bits. To make things easier, you can drop the width indicator.

Code: Select all

parameter 
    HFRONT  = 24,	    // front porch (+right border)
    HVIDEO  = 1024,	  // active video area 
    HSYNC   = 136,		// hsync 
    HBACK   = 160;		// back porch  (+left border)
At higher pixel clock rate, the back porch gets bigger to keep the time delay in the same range. Old CRT monitors need that time to sweep back the electron beam.
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by ElEctric_EyE »

Ok, one more question and I will go on to more testing: To make the HSYNC & VSYNC pulses positive is this all that is needed in your code?

Code: Select all

// update registered outputs
always @(posedge clk108) begin
	    hsync  <= hstate != SYNC;
	    vsync  <= vstate != SYNC;
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by Arlet »

Correct
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by ElEctric_EyE »

Observations: According to the parameters I am setting, I am seeing 1000x700 @75MHz pixel clock. The monitor 'status' button is telling me it is seeing a 1024x768x78Hz signal.

Also, I can make 1023(max)x700 @70MHz work, but 1024 does not display. I have not tried to max the vertical yet.

These are with 1024x768x70Hz timings.

Found this neat site, that can calculate timings for odd resolutions

EDIT: Another observation: The SyncRAM is getting abit warm :lol:, probably approaching its 305mA max current draw. The FPGA is getting warm too. Screen is still free from noise. ReEDIT: I am starting to see noise, hard to see in the random colored pixels. Fixed the link above.
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: HDL Implementation of Video Generator Test for 16-bit PV

Post by Arlet »

Can you post your latest code ? I'm running a sim here with my original code, but modified for 1024 wide, and I don't see a problem here.

EDIT: The noise you're seeing could be from setup/hold time violations at the data inputs of the FPGA. You may be able to fix this by using an IODELAY2 primitive at the input pins (I've never done this myself). By delaying the input a little bit, the clock can be lined up with the middle of the eye.
Post Reply