Author Topic: FPGA VGA Controller for 8-bit computer  (Read 48163 times)

0 Members and 1 Guest are viewing this topic.

Offline nockieboy

  • Frequent Contributor
  • **
  • Posts: 972
  • Country: gb
Re: FPGA VGA Controller for 8-bit computer
« Reply #1250 on: July 06, 2020, 09:54:56 pm »
Z80_bridge now good  :) .

 ;D ;D ;D

This isn't where your error is.  This is the way the PS2 VHDL is written and that its working at 50MHz, not 125MHz. 

Your lines:
Code: [Select]
   if (PS2_RDY) begin           // valid data on PS2_DAT
      PS2_CHAR   <= PS2_DAT;    // Latch the character into Ps2_char register
   end

Is where the problem lies.

Ah! Of course!  :palm:  PS2_RDY is a one-shot, but it's running at 50 MHz, not 125 MHz.  So it's more of a long-shot.   ;D  I need an edge-detect on it...

try this instead:
Code: [Select]
reg [7:0] PS2_RDY_r;
.......
PS2_RDY_r[7:0] <= {PS2_RDY_r[7:1],PS2_RDY};
   if (PS2_RDY_r[7:0] == 8'b00001111 ) begin           // valid data on PS2_DAT
      PS2_CHAR   <= PS2_DAT;    // Latch the character into Ps2_char register
   end

Yeah, that's the thing.  :-+

Oh, shouldn't that be:
Code: [Select]
PS2_RDY_r[7:0] <= {PS2_RDY_r[6:0],PS2_RDY};
???

This means that the PS2_RDY needs to come in for 4 clocks low, then 4 clocks high in a row for the PS2_CHAR to latch the data on that 1 single clock shot, however, this will not solve reading the keyboard port & hitting a key simultaneously.

To fix that problem, you need to:
Code: [Select]
   if ( z80_read_port_1s && Z80_addr_r[7:0]==IO_DATA[7:0] ) begin  // Z80 is reading PS/2 port
      Z80_rData  <= PS2_CHAR;
      if (PS2_RDY_r[7:0] != 8'b00001111 )  PS2_CHAR   <= 8'b0;
end

That if will prevent the clearing of the PS2_CHAR if a new key is pressed at the same time you are reading the current character.

I'll test this tomorrow, it's getting late and I'm up early tomorrow (actually I might just hang on and try a build!), thanks for pinning the problem down.  :-+
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1251 on: July 06, 2020, 09:58:42 pm »
try this instead:
Code: [Select]
reg [7:0] PS2_RDY_r;
.......
PS2_RDY_r[7:0] <= {PS2_RDY_r[7:1],PS2_RDY};
   if (PS2_RDY_r[7:0] == 8'b00001111 ) begin           // valid data on PS2_DAT
      PS2_CHAR   <= PS2_DAT;    // Latch the character into Ps2_char register
   end

Yeah, that's the thing.  :-+

Oh, shouldn't that be:
Code: [Select]
PS2_RDY_r[7:0] <= {PS2_RDY_r[6:0],PS2_RDY};
???
Doh...  |O  My dyslexia.
Lucky you caught that one.

Depending on the VHDL, if the:
if (PS2_RDY_r[7:0] == 8'b00001111 )
is too fat to respond to any key press, then change it to:
if (PS2_RDY_r[5:0] == 6'b000111 )

Don't forget to match the if ( != ) as well.
« Last Edit: July 06, 2020, 10:02:47 pm by BrianHG »
__________
BrianHG.
 

Offline nockieboy

  • Frequent Contributor
  • **
  • Posts: 972
  • Country: gb
Re: FPGA VGA Controller for 8-bit computer
« Reply #1252 on: July 06, 2020, 10:10:20 pm »
The keyboard now works perfectly.  As in no errors whatsoever.   ;D ;D ;D ;D

What you will need to eventually do is make an 8 byte port where if you have multiple keys pressed, each byte will retain one of the 8 keys while they are still pressed.  As they keys are released the keyboard HDL will clear the correct one of the 8 bytes to 0.  The read port will not clear each key's set byte, but HDL will react to you releasing each key on the keyboard by clearing to 0 of the correct one of the 8 bytes.

Your Z80 can scan the 8 bytes and decide what to do, like key repeats, or in game mode, have raw access to those 8 bytes for game controls.

If you want the Z80 to clear any one of the 8 keyboard bytes, you would just write to that port byte.

Or, just 'F' it and do it in software.  Use the current setup and use the bit 8 in the character to send to the Z80 normal key bottom 7 bit code plus the same code again with bit 8 signifying that the key was released.

This way it is backwards compatible with what you have now as long as you ignore any incoming characters with a value above 127.

I like that last suggestion.  Makes it easy to ignore the break codes, but at the same time gives the software (i.e. a game) the ability to read and monitor multiple key presses at the same time.  I'll just need to modify the ps2_to_ascii (or whatever it's called - I haven't got Quartus open right now) module to send break codes in the format you've suggested - should be easy enough.

So the gate is open for progress on the hardware graphics engine again now the Z80_bridge is behaving itself?  :)
 
The following users thanked this post: BrianHG

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1253 on: July 06, 2020, 10:24:32 pm »
Yes.
      Now the Z80_bridge works synchronously to the Z80_CLKn input.  Other than other functions I don't know you want to add, just adding read and write ports should now be easy peasy.  This includes adding the GPU 'ID' onto the Z80 data lines if the address is within a specific range.

      It should also be easier to introduce interrupt requests in the future, make sure you understand why I made the code the way I did and you shouldn't have a problem now that you can assert the interrupt at the right time and hold for the right amount of true Z80 clock cycles.

     Also, the bus_mux now responds to memory requests on a sequenced priority basis, with 3 word deep FIFOs at each command port inputs.  The bus_mux also now has 16 bit access to the GPU core memory allowing the pixel writer to work with 16 bit words.

     Now that everything is AOK, I'll add a third command input port to the bus_mux for the geometry pixel writer.

     You should begin on making the single line engine into a channel 4-line engine.  Then you will make the drawn triangle filled triangle commands.
« Last Edit: July 06, 2020, 10:44:28 pm by BrianHG »
__________
BrianHG.
 

Offline nockieboy

  • Frequent Contributor
  • **
  • Posts: 972
  • Country: gb
Re: FPGA VGA Controller for 8-bit computer
« Reply #1254 on: July 07, 2020, 06:42:07 am »
Other than other functions I don't know you want to add, just adding read and write ports should now be easy peasy.  This includes adding the GPU 'ID' onto the Z80 data lines if the address is within a specific range.

I just need to get the Z80_bridge to return 0xFF if a read is attempted on any address above MEM_SIZE_BYTES, except for the last 16 bytes at the very top of MEMORY_RANGE, where it should return BANK_ID.

As these two conditions are part of the memory read cycle, I'm thinking I should modify the following bits of code to do this (lines 225-230 in Z80_bridge_v2.sv):
Code: [Select]
   if ( z80_read_memory_1s && mem_in_range ) begin                   // pass read request to GPU ram
      gpu_addr   <= Z80_addr_r[19:0];
      gpu_rd_req <= 1'b1;       // Flag HIGH for 1 clock when reading from GPU RAM
   end else begin
      gpu_rd_req <= 1'b0;       // Flag HIGH for 1 clock when reading from GPU RAM
   end

I'll need to add an 'else if' above to trigger a dummy gpu_rd_req for reads in MEMORY_RANGE, but above MEM_SIZE_BYTES.  Then in lines 254-261:
Code: [Select]
   if ( ~Z80_RDn_r ) begin  // this section sets the output enable and sends the correct data back to the Z80
      //if (z80_read_opcode) // unused
      if (z80_read_memory && mem_in_range && gpu_rd_rdy ) begin    // if a valid read memory range and the GPU returns a gpu_rd_rdy, send out data
         Z80_rData       <= gpu_rData ;
         Z80_245data_dir <= data_out;
         Z80_rData_ena   <= 1'b1 ;
         Z80_245_oe      <= 1'b0 ;
      end else if (z80_read_memory && <RD ADDR above MEM_SIZE_BYTES but below MEMORY_RANGE> && gpu_rd_rdy) begin
         <return 0xFF if below BANK_ID address> or <return BANK_ID byte if in BANK_ID range>
      end

I'll need to add an else if to return either 0xFF or a byte from BANK_ID according to the address read above MEM_SIZE_BYTES.

Does that sound right?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1255 on: July 07, 2020, 11:28:57 am »
Are you talking about this?

Code: [Select]
wire   mem_in_bank;
assign mem_in_bank         = (Z80_addr_r[21:19]==MEMORY_RANGE[2:0]) ; // Define the memory access window
wire   mem_in_range;
assign mem_in_range        = (Z80_addr_r[18:0] < MEM_SIZE_BYTES[19:0]) ; // The size of GPU ram + GPU palette ram

and then

Code: [Select]
   if ( z80_read_memory_1s && mem_in_bank ) begin                   // pass read request to GPU ram
      gpu_addr   <= Z80_addr_r[19:0];
      gpu_rd_req <= 1'b1;       // Flag HIGH for 1 clock when reading from GPU RAM
   end else begin
      gpu_rd_req <= 1'b0;       // Flag HIGH for 1 clock when reading from GPU RAM
   end

and then

Code: [Select]
if ( ~Z80_RDn_r ) begin  // this section sets the output enable sends the correct data back to the Z80
            //if (z80_read_opcode) // unused
            if (z80_read_memory && mem_in_bank && gpu_rd_rdy ) begin    // if a valid read memory range and the GUP returns a gpu_rd_rdy, send out data

                                                                if (mem_in_range) Z80_rData       <= gpu_rData ;
                                                                else              Z80_rData       <= BANK_ID[Z80_addr_r[3:0]];

                                                                Z80_245data_dir <= data_out;
                                                                Z80_rData_ena   <= 1'b1 ;
                                                                Z80_245_oe      <= 1'b0 ;
                                                                end

This would make best sense.  You can simulate the reads on the simulation test bench by changing the read address to what you like.
__________
BrianHG.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1256 on: July 07, 2020, 11:39:53 am »
Also, protect your writes to GPU ram:

Code: [Select]
   if ( z80_write_memory_1s && mem_in_bank && mem_in_range ) begin                  // pass write request to GPU ram
And for the 'SUPER' stingy version (this one removes the 'gpu_rd_req' flag and it's reliance to return a pulse from the GPU ram section to return a 'BANK_ID') :

Code: [Select]
   if ( z80_read_memory_1s && mem_in_bank && mem_in_range ) begin                   // pass read request to GPU ram
      gpu_addr   <= Z80_addr_r[19:0];
      gpu_rd_req <= 1'b1;       // Flag HIGH for 1 clock when reading from GPU RAM
   end else begin
      gpu_rd_req <= 1'b0;       // Flag HIGH for 1 clock when reading from GPU RAM
   end

and

Code: [Select]
           if (z80_read_memory && mem_in_bank && ~mem_in_range ) begin    // memory read outside memory range, but inside the bank.  Return BANK_ID
                                                                Z80_rData       <= BANK_ID[Z80_addr_r[3:0]];
                                                                Z80_245data_dir <= data_out;
                                                                Z80_rData_ena   <= 1'b1 ;
                                                                Z80_245_oe      <= 1'b0 ;
                                                                end
          if (z80_read_memory && mem_in_bank && mem_in_range && gpu_rd_rdy ) begin    // if a valid read memory range and the GUP returns a gpu_rd_rdy, send out data
                                                                Z80_rData       <= gpu_rData ;
                                                                Z80_245data_dir <= data_out;
                                                                Z80_rData_ena   <= 1'b1 ;
                                                                Z80_245_oe      <= 1'b0 ;
                                                                end

Remember to simulate test this code...
« Last Edit: July 07, 2020, 12:44:46 pm by BrianHG »
__________
BrianHG.
 

Offline nockieboy

  • Frequent Contributor
  • **
  • Posts: 972
  • Country: gb
Re: FPGA VGA Controller for 8-bit computer
« Reply #1257 on: July 07, 2020, 02:36:12 pm »
Simulations are running perfectly - getting 0xFF and BANK_ID values back from appropriate read addresses, just waiting for a project compile to complete to test on the board.   :-+

Wanted to ask a question re: BGA soldering to anyone reading this, really.  Bearing in mind I'm looking to fabricate a PCB for the EP4CE22F17 (256-fBGA with 1mm pitch), is it necessary to have a pre-heater or some form of board heater to use in addition with the hot air gun to solder the BGA effectively?  I don't have an expensive hot air gun - it's a pretty cheap one to be honest, but has served me well so far soldering the EQFP-144 packages.

Is pre-heating (is that the right term?) necessary?  Could I just get away with hot-air soldering the BGA onto the PCB in a skillet over the cooker, if necessary?

EDIT:  Z80_bridge is working 100% now, returning correct values for non-RAM areas and the ID at the top of its memory space.  :-+
« Last Edit: July 07, 2020, 02:41:22 pm by nockieboy »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1258 on: July 07, 2020, 02:48:49 pm »
You can get away with just hot air.  Also you should get a re-balling stencil and paste like in the video I showed you as you might fail your first mounting.

When placing the BGA, having the PCB on a hot place to kick the PCB up to around 125 degree C just helps when using the hot air as it will easily melt with minimal air.  (I would use an old pan and portable stove on minimum warm only if I can assure the pan's surface temperature.)  Professionals use all the proper pre-heating rules and mounting to ensure no PCB or IC goes to waste, they also don't want to remount an IC and ensure the mounted IC will not fail for over the 20 or so year lifetime of the PCB.

You are building 2 to 5 PCBs.  A bad solder means remove - reball - remount like in the provided video, but you are not a production assembly house where every point of failure is = to time and money loss on an industrial scale.  This is why they need to own and use all the right tools.
« Last Edit: July 07, 2020, 02:51:00 pm by BrianHG »
__________
BrianHG.
 
The following users thanked this post: nockieboy

Offline nockieboy

  • Frequent Contributor
  • **
  • Posts: 972
  • Country: gb
Re: FPGA VGA Controller for 8-bit computer
« Reply #1259 on: July 07, 2020, 03:06:16 pm »
You should begin on making the single line engine into a channel 4-line engine.  Then you will make the drawn triangle filled triangle commands.

Errr... where do I start with that?  It should take in four sets of parameters and draw the lines simultaneously, or....?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1260 on: July 07, 2020, 03:11:43 pm »
Try making all the line's registers [3:0] / 4 slot arrays.
This also means when running a line, you draw a single pixel of a single line, 1 at a time, or select a few in sequence.

Also think of the sub-routine steps to run and stop each line or part of a line.
__________
BrianHG.
 

Offline nockieboy

  • Frequent Contributor
  • **
  • Posts: 972
  • Country: gb
Re: FPGA VGA Controller for 8-bit computer
« Reply #1261 on: July 07, 2020, 03:22:20 pm »
Try making all the line's registers [3:0] / 4 slot arrays.
This also means when running a line, you draw a single pixel of a single line, 1 at a time, or select a few in sequence.

Also think of the sub-routine steps to run and stop each line or part of a line.

So the function would iterate through the 4 slots, drawing a pixel from each?  Or would it be quicker to just draw an entire shape first before moving on to the next one in the array?

On a side note, I've just thought of something for the graphics mode that would be an important addition (you've probably already thought of it) - the ability to write text to the graphics memory?  So the existing character tilemaps could be used to display text in the graphics RAM?  I suppose that would just be a blitter function (with some decoding of the character tile into a bitmap)?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1262 on: July 07, 2020, 04:18:20 pm »
Think about what you need to do to fill in a non-right angle triangle...
__________
BrianHG.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1263 on: July 08, 2020, 05:43:29 am »
Please test the attached updated 'FIFO_3word_0_latency.sv'.  If it works, please update all your project folders with the new version.
__________
BrianHG.
 

Offline nockieboy

  • Frequent Contributor
  • **
  • Posts: 972
  • Country: gb
Re: FPGA VGA Controller for 8-bit computer
« Reply #1264 on: July 08, 2020, 08:48:32 am »
Please test the attached updated 'FIFO_3word_0_latency.sv'.  If it works, please update all your project folders with the new version.

Yes, that works fine.  :)
 
The following users thanked this post: BrianHG

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1265 on: July 08, 2020, 12:33:54 pm »
Have you tried to figure out how to draw a filled triangle, why it needs 3 running lines.
Try to make a working one in the FreeBasic geo.bas and show it to me.
__________
BrianHG.
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 1186
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1266 on: July 08, 2020, 01:27:18 pm »
Wanted to ask a question re: BGA soldering to anyone reading this, really.  Bearing in mind I'm looking to fabricate a PCB for the EP4CE22F17 (256-fBGA with 1mm pitch), is it necessary to have a pre-heater or some form of board heater to use in addition with the hot air gun to solder the BGA effectively?  I don't have an expensive hot air gun - it's a pretty cheap one to be honest, but has served me well so far soldering the EQFP-144 packages.

Is pre-heating (is that the right term?) necessary?  Could I just get away with hot-air soldering the BGA onto the PCB in a skillet over the cooker, if necessary?
Don't worry about preheating. It's a nice thing to have, and makes process easier and faster, but it's not a necessity. In case you're wondering, I don't have a preheater either, but I recently upgraded my hot air gun from cheap-ass $99 affair (that served me for over 3 years) to this one, and it sped things up quite a bit because it's more powerful.

Offline nockieboy

  • Frequent Contributor
  • **
  • Posts: 972
  • Country: gb
Re: FPGA VGA Controller for 8-bit computer
« Reply #1267 on: July 08, 2020, 02:00:15 pm »
Have you tried to figure out how to draw a filled triangle, why it needs 3 running lines.
Try to make a working one in the FreeBasic geo.bas and show it to me.

Haven't had much time to think about, really.  I've given some thought to how to draw a non-filled rectangle - the easiest method seems to be just to draw three lines, but that's no good for a filled triangle - looks like the lines will need to be drawn simultaneously, which could be a headache as it'll involve three sets of variables in the same line function...   :-//
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1268 on: July 08, 2020, 04:45:30 pm »
When I said 3 lines for triangle, a hint would be that 1 line is always re-drawing with a new start and stop coordinates every time it finishes.  Now, what are the other 2 line drawing engines doing?

Can this still work for fill 4 coordinate geometric shapes as well?
« Last Edit: July 08, 2020, 04:47:08 pm by BrianHG »
__________
BrianHG.
 

Offline nockieboy

  • Frequent Contributor
  • **
  • Posts: 972
  • Country: gb
Re: FPGA VGA Controller for 8-bit computer
« Reply #1269 on: July 08, 2020, 06:29:53 pm »
When I said 3 lines for triangle, a hint would be that 1 line is always re-drawing with a new start and stop coordinates every time it finishes.

So one line draws the perimeter of the triangle?  It would draw a line from x0,y0 to x1,y1, then from x1,y1 to x2,y2, then from x2,y2 to x0,y0?

Now, what are the other 2 line drawing engines doing?

Supervising the work of the first one?  ;)

Erm... a random guess would be filling the shape - one engine to each half (top/bottom) of the shape??  :-//

Can this still work for fill 4 coordinate geometric shapes as well?

I suppose so.  A 4-coordinate geometric shape is just a compound shape made of two triangles.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1270 on: July 08, 2020, 06:53:18 pm »
When I said 3 lines for triangle, a hint would be that 1 line is always re-drawing with a new start and stop coordinates every time it finishes.

So one line draws the perimeter of the triangle?  It would draw a line from x0,y0 to x1,y1, then from x1,y1 to x2,y2, then from x2,y2 to x0,y0?

Now, what are the other 2 line drawing engines doing?

Supervising the work of the first one?  ;)

Erm... a random guess would be filling the shape - one engine to each half (top/bottom) of the shape??  :-//

Can this still work for fill 4 coordinate geometric shapes as well?

I suppose so.  A 4-coordinate geometric shape is just a compound shape made of two triangles.
|O  Nope...

Method #1, using 2 line generators.  (Eats less gates)

Make line generator #1 = to points A&B on a triangle.
Loop until line #1 is finished:
{
Step Line #1
run line generator #2 with the current coordinates of line#1 for it's beginning and the triangle's point C for it's ending and draw a complete line line.
}
To complete an unfilled triangle, the running of line generator #2 should only take place on the first and last pixel of line generator #1.

Method 2:

Load the first 2 line generators with the coordinates of 2 edges of the triangle.  EG: Line 1 points =A&B, Line #2 points =B&C.
Loop until line #1 and line #2 are finished:
{
Step Line #1 & #2 by 1 pixel
load line generator #3 with the current coordinates of line#1 for it's beginning and current coordinates of line #2 for it's ending and draw a complete line.
}

The difference between filled and non filled is that line generator #3 is only run once at the beginning and when line generators #1&#2 are finished.  Or, you can just draw 3 lines in sequence.

The advantage of #2 is that you have 4 coordinates, (Loading line 1 with points A&B, loading line #2 with points C&D)  a start and stop position for 2 line generators meaning you can draw a filled 4 sided polygon.  Drawing a triangle with this engine means that 2 points on the 4 sided polygon share the same coordinates.

« Last Edit: July 08, 2020, 08:23:39 pm by BrianHG »
__________
BrianHG.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1271 on: July 08, 2020, 07:13:14 pm »
Come to think of it, you can use my method #1 and draw 2 back-back triangles.

Still need to consider giving the line engines an ARC parameter, ie look at how the ellipse draws a curve in the existing geo.bas software as it is nothing but a fancy line drawing algorithm generating 2 halves of each quadrant of the ellipse.

I'm thinking that the line begins in the center with a delta X/Y offset, then proceeded drawing to the end-points in each direction curving it's path as it goes.  With this not only are the circles easy as the delta X&Y are easy to compute, but manually entering these coordinates on an angle will allow ellipses to be generated at odd angles.

Using method #1, maybe you will just create 2 completely separate line generator modules as the gate count wont be terrible compared to 3 or 4 line generators.
« Last Edit: July 08, 2020, 10:58:45 pm by BrianHG »
__________
BrianHG.
 

Offline gcewing

  • Regular Contributor
  • *
  • Posts: 69
  • Country: nz
Re: FPGA VGA Controller for 8-bit computer
« Reply #1272 on: July 09, 2020, 12:54:22 am »
None of the suggested methods for filling a triangle sounds like the way I would do it, which is this:

Let A, B, C be the vertices in order from top to bottom. Initialise two line generators, L1 from A to B and L2 from A to C. Step them both together vertically and fill horizontal rows between L1 and L2 at each step. When L1 reaches B, reset it to go from B to C and continue.

This method only requires two line generators, and has the advantage that it writes consecutive pixels horizontally, which could be important if your graphics memory benefits from burst accesses. It also doesn't rely on adjacent non-axis-aligned lines fitting together perfectly without leaving gaps.

Polygons with more than three vertices can be handled by dividing them into triangles. This is probably best done in software rather than trying to make the hardware do it.
 
The following users thanked this post: BrianHG, nockieboy

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 4283
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1273 on: July 09, 2020, 02:48:42 am »
None of the suggested methods for filling a triangle sounds like the way I would do it, which is this:

Let A, B, C be the vertices in order from top to bottom. Initialise two line generators, L1 from A to B and L2 from A to C. Step them both together vertically and fill horizontal rows between L1 and L2 at each step. When L1 reaches B, reset it to go from B to C and continue.

This method only requires two line generators, and has the advantage that it writes consecutive pixels horizontally, which could be important if your graphics memory benefits from burst accesses. It also doesn't rely on adjacent non-axis-aligned lines fitting together perfectly without leaving gaps.

Polygons with more than three vertices can be handled by dividing them into triangles. This is probably best done in software rather than trying to make the hardware do it.
This works great and works so long as you draw lines A&B vertically downward, you step each until they increment on the Y axis, then fill.  This way the filling of pixels on a line are drawn once.  My 2 line method is cheaper and easier to do, however it's shortcoming is that pixels are filled over multiple times.  My only question is when we increment an angled line, the line itself may fill another adjacent pixel or 2 on the X axis.  The horizontal line generator would need to take the maximum X width unless we use a different line generator optimized for this task.  One that jumps an X&Y position on each clock and rely on the horizontal line filler to fill in the gaps.

Remember, our current line generator is optimized for fill in all the gaps as it generates a line and is not intended/optimized to be part of a fill generator.

Yes, our memory is our bottle neck and we will have up to a horizontal 16 pixel cache since we do need read-modify-write to support the bitplane modes, translucency & collision detection when drawing.  Your horizontal line filling, though a little trickier to implement for best results, would accelerate filled triangles by a larger and larger degree as the triangle grows in size compared to my dumb engine which makes use of what we already have.  Let's see if nockieboy would like to tackle this type of triangle engine.
« Last Edit: July 09, 2020, 03:18:40 am by BrianHG »
__________
BrianHG.
 

Offline nockieboy

  • Frequent Contributor
  • **
  • Posts: 972
  • Country: gb
Re: FPGA VGA Controller for 8-bit computer
« Reply #1274 on: July 09, 2020, 09:13:40 am »
Okay, I feel like I'm waaay out of my depth here trying to come up with even just the BASIC interpretation of a routine to draw these triangles.  Now you're presenting me with options?! :scared:  ;)

Right, just so I'm (and the average reader is) clear, these are the three different methods available to draw a filled triangle so far (thanks for chipping in, @gcewing!):

[attach=1]

[attach=2]

[attach=3]

Order of drawing is (mostly) in alphabetical order in those diagrams.

I had an instant reservation pop up as soon as I read about method #1 - and that's the concern that some pixels might be missed when starting a line from a point on line #1 and a lot of pixels will be overwritten as the 2nd line converges on C.  This was a technique used in the 80's and early 90's on 8-bit computers (and even on 16-bit systems in the demo scene) to produce random-ish pretty Moire patterns etc. by taking advantage of the limitations of the graphics systems.

Method #2 looks logical and with less wasted effort (less overwritten pixels - if any).   I like this one, but again the concern is how effective would the fill be?  For certain angles and triangle sizes, is there a chance pixels could be missed in the fill?

Method #3 looks to have the least pixel overwrites (none) due to rasterising the triangle in a way that is sympathetic to the system it's being drawn on, but as @BrianHG has pointed out, a diagonal line with an angle less than 45 degrees from horizontal will sometimes have more than one pixel on an edge with the same Y value, creating an overwritten line filling that segment of the triangle.  Diagram below shows darker pink lines where multiple horizontal fill lines would overwrite each other:

[attachimg=4]

I'm limited by my understanding of translating all this into BASIC, then HDL, unfortunately.  I'm going to have to go away and make a serious effort to understand how the routines are working in the FreeBASIC simulator, but I'm inclined to go with method #3.
« Last Edit: July 09, 2020, 09:19:47 am by nockieboy »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf