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

0 Members and 1 Guest are viewing this topic.

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1650 on: September 16, 2020, 11:59:32 am »
Ok, I removed a heap of a mess in both the linegen and geometry_xy_plotter.
Get the attached files below.

My added comments arent too detailed, so read up and add comments and ask me questions why while I still have a bit of time left.

Run and test a simulation.
If it looks good, then try it on the Z80.

Hmm.. not sure what's going on, but it seems that (in the simulation at least), linegen#1 is repeating when I include the PAGET in the simulation.  :-//

I did this after I tried the HDL on the Z80 - the initial simulation (without PAGET) seemed to work just fine - but when I try to draw the two lines on the Z80, I'm only getting the second line (from x/y[0] to x/y[1]) drawn - there's no sign of the first line.  Just to cover myself, here's how I'm entering the coordinates:
Code: [Select]
    LD      HL,8001H        ; set X[0] to 1
    CALL    send_gpu
    LD      HL,0C001H       ; set Y[0] to 1
    CALL    send_gpu
    LD      HL,9004H        ; set X[1] to 4
    CALL    send_gpu
    LD      HL,0D004H       ; set Y[1] to 4
    CALL    send_gpu
    LD      HL,0A001H       ; set X[2] to 1
    CALL    send_gpu
    LD      HL,0E00AH       ; set Y[2] to 10
    CALL    send_gpu
    LD      A,15            ; Colour white
    CALL    GET_MASK
    CALL    drawLine

All I'm seeing is a line from 1,1 to 4,4.  So I went back to the simulation, included the PAGET and got the output I've attached below.  I'm not sure why the 1st line isn't drawn, unless I'm missing something in the simulation output.

The only changes I made to geo_xy_plotter.sv when I added it to the live project was to remove the two DEBUG pins and declare them in the code as LOGIC and removed the 'extended_cmd' on the geo_mask assignment (line 426 in attached module) as it was throwing errors (it should be command_in[5] if anything) and previously was just grounded.  I've done code tidying as well and changed the REG and WIRE declarations to LOGIC.

So - either my test code is wrong, I've messed up copy-pasting the geo_xy_plotter and line_generator modules from the test bench to the live project, or there's an issue with the HDL.  It's probably something I've done.  :-//
« Last Edit: September 16, 2020, 12:02:14 pm by nockieboy »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1651 on: September 16, 2020, 12:47:19 pm »
First issue - time to bang you hear again:



Try scrolling the sim waveform in the direction of the arrow...
Run the sim again without the pixel-write and just scroll to the right to 900ns and see what was always there.
« Last Edit: September 16, 2020, 12:50:18 pm by BrianHG »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1652 on: September 16, 2020, 12:58:00 pm »
Haha  ;D  I have to laugh otherwise I'd go mad. :palm:

Okay, so that sorts the simulation out.  Still have the problem with the Z80 not drawing the first line.  :-// 
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1653 on: September 16, 2020, 01:18:02 pm »
Ok, zooming into the simulation with the pixel writer enabled, looking at the bottom at the 'wr_ena' as a reference, you can see the 'ram_addr' just above writing that vertical line and 45 degree line, back and forth 1 pixel after another.  So, this looks good.

IE, 2 writes into 6010, then 6020, 6022, 6030, 6032, 6040, 6044, 6050, 6060,...60A0.
(6050 through 60A0 finishes the vertical white line)

Not only that, but you can count the 'wr_ena' clocks and it comes to 14, so, 14 pixels were written.

Are you sure you have the right source code in your Z80 build?
Seems you are drawing 1 single line from xy[0] to xy[1] like the old line program.
« Last Edit: September 16, 2020, 01:22:17 pm by BrianHG »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1654 on: September 16, 2020, 01:51:05 pm »
Are you sure you have the right source code in your Z80 build?
Seems you are drawing 1 single line from xy[0] to xy[1] like the old line program.

Hmm, well I don't know what that was about, but it's working now.  I suspect the Windows CP/M emulator I'm using to compile the source into a .COM file (CP/M executable file) wasn't overwriting the original source, or something. :palm:  I've cleared out the cobwebs on the simulated drive and it's compiled the latest version now, as I'm getting two lines drawn on the Z80.  Onwards and upwards... :-+

That, or... well, when it wasn't working I'd programmed the FPGA directly via JTAG.  This time I've programmed the configuration ROM via AAS.  Wonder if that might have had something to do with it..
« Last Edit: September 16, 2020, 01:52:47 pm by nockieboy »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1655 on: September 16, 2020, 01:59:18 pm »
Okay, all is still not quite well..  On the FIRST run of the program since the uCOM is powered on, I get two lines drawn.  If I re-run the program, I only get one drawing from x/y[0] to x/y[2].  I suppose there's still work to be done around the state of the linegens after the two lines are drawn, as the function isn't yet complete?
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1656 on: September 16, 2020, 04:03:30 pm »
Okay, so getting linegen 2 restarted isn't proving easy.  I figured that using a register to track which set of coordinates linegen#2 is using would make sense, but I may be wrong there - so line_stage is a single-bit register.  In the combinational logic section, I'm setting the coordinate sets in current use as follows:
Code: [Select]
    // Starting and ending coordinate selection for Linegen#1
    lgen_1a              = 0 ; // default to starting at X[0],Y[0]
    lgen_1b              = 2 ; // default to   ending at X[2],Y[2]
   
    // Linegen#2's coordinate selection is a little more involved - needs to switch from 0-1 to 1-2 at first completion
    lgen_2a              = line_stage     ;
    lgen_2b              = line_stage + 1 ;
So linegen#2 uses set [ 0] to set [1] if line_stage is 0, or set [1] to set [2] if line_stage is 1.  That's the idea, anyway.

Line_stage is set in the asynchronous section:
Code: [Select]
        // If linegen#2 completes the first line, set its coordinates to the second line and restart it
        if ( line_2_done && !line_stage ) begin
       
            line_stage  <= 1'b1 ;
           
        end
The only issue is that it takes a clock for line_stage to update linegen#2 to the next set of coordinates - I'm sure there's a way I can do this instantly, I just don't know what it is currently.   I figure I need to do something with the y_stop_en_# assignments to restart linegen#2?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1657 on: September 17, 2020, 12:28:26 am »
Arrrrggg, damn FMAX... Changes coming...

 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1658 on: September 17, 2020, 02:50:55 am »
Ok, here we go, get the attached project.
It is your responsibility to document and update the revision numbers....

First big change, the drawing functions have been updated to these new ones:
Once the triangle fills, you will need to edit the command numbers. We will want these commands:
0 = do nothing.
1 = place a pixel.  (Currently a line, or the triangle we are debugging.)
2 = draw a line.
3 = draw a triangle.
4 = draw a box
5 = draw a quadrilateral
6 = draw an ellipse
7 = draw a Bezier Curve    (spare, may be used for something else).

Fills have yet to be done.

Changes in line_generator.sv:
1. 'line_complete' is now a single 1-shot after the line is finished.
    Enabling line 58 in the code and disabling the other instances in the code changes 'line_complete' into a 1-shot which is send during the final pixel output, meaning you shave 1 clock off when stringing one line command to the next in a sequence.  However, the FMAX will drop below 125MHz in the current setup.
2. 'ypos_stopped' now switches off immediately as the 'ena_stop_y' input goes low, IE it's now combinational logic saving a clock cycle.
3. Numerous other logic start and stop bugs cleaned up.


Changes in geometry_xy_plotter.sv:
1. New line setup Look Up Tables.  (LUT seem to slow down simulation by a big factor since I use large ones...Sorry)

A) This lookup table counts the number of sequences each linegen needs to run: 167-183
Code: [Select]
// This lookup table specifies the number of sequence cycles each linegen needs to run before completing the final shape
logic [2:0] LUT_LG_CMD_SEQ_SIZE[0:31] = '{ // Linegen 1, Linegen 2 sequence size
 0,0,   // Shape  0 = NOTHING
 1,0,   // Shape  1 = Pixel
 1,0,   // Shape  2 = Line
 1,2,   // Shape  3 = Triangle
 4,0,   // Shape  4 = Box
 4,0,   // Shape  5 = Quadrilateral
 0,0,   // Shape  6 = Ellipse
 0,0,   // Shape  7 = Bezier Curve
 0,0,   // Shape f0 = NOTHING
 0,0,   // Shape f1 = Pixel
 0,0,   // Shape f2 = Line
 0,0,   // Shape f3 = Triangle Filled
 0,0,   // Shape f4 = Box Filled
 0,0,   // Shape f5 = Quadrilateral Filled
 0,0,   // Shape f6 = Ellipse Filled
 0,0 }; // Shape f7 = Bezier Curve Filled

B) These 2 lookup tables tells which XY coordinates to use during each linegen sequence: 185-220
Code: [Select]
// These are the lookup tables to select which X/Y source for A,B
// The order is stage 0A,0B, 1A,1B,  2A,2B, 3A,3B, 4A,4B, 5A,5B, 6A,6B, 7A,7B
 logic [1:0] LUT_LG1_SEL_XY[0:511] = '{
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  0 = NOTHING
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  1 = Pixel
 0,0,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  2 = Line
 0,0,2,2, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  3 = Triangle
 0,0,1,0, 1,0,1,1, 1,1,0,1, 0,1,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  4 = Box
 0,0,1,1, 1,1,2,2, 2,2,3,3, 3,3,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  5 = Quadrilateral
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  6 = Ellipse
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  7 = Bezier Curve
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f0 = NOTHING
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f1 = Pixel
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f2 = Line
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f3 = Triangle Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f4 = Box Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f5 = Quadrilateral Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f6 = Ellipse Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; // Shape f7 = Bezier Curve Filled
 logic [1:0] LUT_LG2_SEL_XY[0:511] = '{
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  0 = NOTHING
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  1 = Pixel
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  2 = Line
 0,0,1,1, 1,1,2,2, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  3 = Triangle
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  4 = Box
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  5 = Quadrilateral
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  6 = Ellipse
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  7 = Bezier Curve
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f0 = NOTHING
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f1 = Pixel
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f2 = Line
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f3 = Triangle Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f4 = Box Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f5 = Quadrilateral Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f6 = Ellipse Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; // Shape f7 = Bezier Curve Filled

These variables hold each linegen sequence position: 159-164
Code: [Select]
logic [2:0] lg1_seq       ; // Sequence counter for geometric shapes with multiple lines
logic [2:0] lg2_seq       ; // Sequence counter for geometric shapes with multiple lines
logic [2:0] lg1_seq_end   ; // Sequence counter for geometric shapes with multiple lines
logic [2:0] lg2_seq_end   ; // Sequence counter for geometric shapes with multiple lines
logic [2:0] lg1_nseq      ; // Sequence counter for geometric shapes with multiple lines
logic [2:0] lg2_nseq      ; // Sequence counter for geometric shapes with multiple lines

C) When a geometric shape is called, these lines initialize the linegen params: 538-551
Code: [Select]
                    // Depending on the selected draw command+fill bit, this sets the number of sequences to count down from for each linegen once each linegen finishes.
lg1_seq_end <= LUT_LG_CMD_SEQ_SIZE[{command_in[3:0],1'b0}];
lg2_seq_end <= LUT_LG_CMD_SEQ_SIZE[{command_in[3:0],1'b1}];
lg1_seq     <= 0;
lg2_seq     <= 0;

                    lgen_1ax <= LUT_LG1_SEL_XY[{command_in[3:0],5'b00000}] ;
                    lgen_1ay <= LUT_LG1_SEL_XY[{command_in[3:0],5'b00001}] ;
                    lgen_1bx <= LUT_LG1_SEL_XY[{command_in[3:0],5'b00010}] ;
                    lgen_1by <= LUT_LG1_SEL_XY[{command_in[3:0],5'b00011}] ;
                    lgen_2ax <= LUT_LG2_SEL_XY[{command_in[3:0],5'b00000}] ;
                    lgen_2ay <= LUT_LG2_SEL_XY[{command_in[3:0],5'b00001}] ;
                    lgen_2bx <= LUT_LG2_SEL_XY[{command_in[3:0],5'b00010}] ;
                    lgen_2by <= LUT_LG2_SEL_XY[{command_in[3:0],5'b00011}] ;

D) When the new one-shot 'line_complete' fires, it increments updates the following linegen settings here: 375-390
Code: [Select]
if ( geo_run ) begin // Decrement each line sequence counter once their line has completed.
if (line_1_done && (lg1_seq!=lg1_seq_end)) begin
                                             lg1_seq  <= lg1_nseq;
                                                         lgen_1ax <= LUT_LG1_SEL_XY[{geo_shape[3:0],lg1_nseq,2'b00}] ;
                                                         lgen_1ay <= LUT_LG1_SEL_XY[{geo_shape[3:0],lg1_nseq,2'b01}] ;
                                                         lgen_1bx <= LUT_LG1_SEL_XY[{geo_shape[3:0],lg1_nseq,2'b10}] ;
                                                         lgen_1by <= LUT_LG1_SEL_XY[{geo_shape[3:0],lg1_nseq,2'b11}] ;
                                             end
if (line_2_done && (lg2_seq!=lg2_seq_end)) begin
                                 lg2_seq  <= lg2_nseq;
                                                         lgen_2ax <= LUT_LG2_SEL_XY[{geo_shape[3:0],lg2_nseq,2'b00}] ;
                                                         lgen_2ay <= LUT_LG2_SEL_XY[{geo_shape[3:0],lg2_nseq,2'b01}] ;
                                                         lgen_2bx <= LUT_LG2_SEL_XY[{geo_shape[3:0],lg2_nseq,2'b10}] ;
                                                         lgen_2by <= LUT_LG2_SEL_XY[{geo_shape[3:0],lg2_nseq,2'b11}] ;
                                 end
end

E) This is the current sequence combinational logic for the linegens: 306-323
Code: [Select]
    // If any of the linegens or blitter are working, geo_run needs to go immediately HIGH to stop loading new commands
    geo_run              = (lg1_seq!=lg1_seq_end) || (lg2_seq!=lg2_seq_end) || line_gen_3_running ;

    // Line generator running logic
    line_gen_starter     = !reset && ( !fifo_cmd_rdy_n && !geo_run ) && ( command_in[7:5] == 3'd0 && command_in[2:0] != 3'd0 )    ; // for now, only the draw line command

    linegen_1_run        = line_gen_1_running  || (lg1_seq!=lg1_seq_end && !line_1_done)  ; // initiate linegen1 when linegen2 is not running
    linegen_2_run        = (line_gen_2_running || ( y_stopped_1 )) && !(line_2_done && (lg2_seq!=lg2_seq_end))       ; // initiate linegen2 after linegen1 has its first stop
    linegen_3_run        = 1'b0                                                                                      ; // not used at the moment
   
    // Starting and ending coordinate selection

    // Only release a stop once the opposite linegen goes from a non-y-stopped state to a y-stopped-state, or that linegen has completed a line
    y_stop_en_1          = ( !(y_stopped_2 && !last_y_stopped_2) ) && (lg2_seq!=lg2_seq_end) ;
    y_stop_en_2          = ( !(y_stopped_1 && !last_y_stopped_1) ) && (lg1_seq!=lg1_seq_end) ;

    lg1_nseq  = lg1_seq + 1; // prepare an array with the next sequence number
    lg2_nseq  = lg2_seq + 1; // prepare an array with the next sequence number

You now need to test the first 1..5 functioning commands.  Make sure they work on the Z80.  Make sure the simulation look good.  Update your comments.  Check that the Y position from linegen 1&2 stay synchronized with odd angle lines.  Make sure multiple lines works right.

Next you need to activate the 'Fill' commands.
« Last Edit: September 17, 2020, 02:56:34 am by BrianHG »
 
The following users thanked this post: nockieboy

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1659 on: September 17, 2020, 05:18:07 am »
Your idea to not use the external Y-STOP counter to stop the linegens is making issues with a filled box and filled quadrilateral.  No problems with a filled triangle as the first pixel is a point and it doesn't need a a filled line between the 2 points.

Ohhh boy, you got a challenge now.

The problem is when a y_increment is ready to take place, y_stopped happens, but, the output coordinates for the next line also come out.  It's like the y_stopped skids 1 extra clock.

With my original idea where we externally mandate a Y-position which will prevent the linegen from doing anything at all if the core Y coordinates equal the externally supplied Y-position, your current code waits for a Y-inc to happen, then stops everything, but let's out the next y_position.

Still, we can start the module in a Y-stopped state, except when switching linegen2 in the middle creates an additional stop we do not want since the beginning and ending xy coordinates happen to match and we want to flush through that first set of numbers until the next Y coordinates only during that mid time, otherwise the Y position of linegen 1&2 loose sync.

This created a little mess.
« Last Edit: September 17, 2020, 05:54:46 am by BrianHG »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1660 on: September 17, 2020, 08:42:15 am »
:wtf:  That's going to take some time to get my head around. :o  Thank you though.

So the first question that springs up when looking at the LUTs is this:

Code: [Select]
logic [1:0] LUT_LG1_SEL_XY[0:511] = '{
You've got one table for each of the first two linegens (LUT_LG1 and LUT_LG2), but I'm a little confused why they're declared as [1:0] LUT_name[0:511]?  There's 512 entries in the table, but what's the first index (1:0) for?

Also, for the box function, wouldn't it make sense to use both the linegens to draw the parallel lines simultaneously? ???  The second linegen looks seriously underused.  ;)

Your idea to not use the external Y-STOP counter to stop the linegens is making issues with a filled box and filled quadrilateral.  No problems with a filled triangle as the first pixel is a point and it doesn't need a a filled line between the 2 points.

Ohhh boy, you got a challenge now.

I hate it when you say that.  I'm not up to the non-challenging stuff, let alone the challenges.  :-[

The problem is when a y_increment is ready to take place, y_stopped happens, but, the output coordinates for the next line also come out.  It's like the y_stopped skids 1 extra clock.

Yeah, I'd noticed that previously.  I guess the only way to stop that would be to calculate the X & Y-coordinates internally and delay them by a clock before outputting them, so y_stopped can get out before the next Y-coordinate?

With my original idea where we externally mandate a Y-position which will prevent the linegen from doing anything at all if the core Y coordinates equal the externally supplied Y-position, your current code waits for a Y-inc to happen, then stops everything, but let's out the next y_position.

Still, we can start the module in a Y-stopped state, except when switching linegen2 in the middle creates an additional stop we do not want since the beginning and ending xy coordinates happen to match and we want to flush through that first set of numbers until the next Y coordinates only during that mid time, otherwise the Y position of linegen 1&2 loose sync.

This created a little mess.

Hmm.. did you see this coming a mile away when I first suggested stopping on every Y-coordinate? ;)

I guess we could add back the 'stop_y_coordinate' register and add a flag/signal to specify whether the linegen is to stop on every y-increment or at the specified y-coordinate?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1661 on: September 17, 2020, 08:55:17 am »
Ok, the fills are working, however, I haven't solved the above problem.
This means when rasterizing a triangle, the Y position from linegen1 to linegen 2 will slip at the halfway point.
This doesn't seem to be a serious problem as linegen3 will connect the uneven line between lingen 1&2 anyways.

Though I tried a few simple addon patches to fix the problem, non of them were really kosher.  I'll leave it up to you to fix.

Like the previous version, make sure you can simulate, and understand what the simulations are saying and why.
Make sure the FMAX can be reached as we are right on the line.  I had to remove a few optimization which shaved off occasional clock cycles between command transitions, but, your Z80 could never keep up and the pixel writer is the bigger bottleneck anyways.

In the line generator, line 149 reads:

                    ypos_stopped_int   <= 1'b1    ; // PREset ypos_stopped_int flag

The makes the linegen perform a y_stop after the first pixel output.  Disabling this corrects the Y-alignment error on the filled triangles.  However, the box fill and quadrilateral fill will be missing the first line between the first 2 coordinates.

I leave it up to you on if you want to re-engineer the way the y-stop works, or engineer a method to fix the triangle mid-point reset of lingen2 which adds an additional delay in y-coordinates generating that alignment error.

Test/simulate & Z80 test everything out, because I only did the basics.
Remember, we are not yet sorting the 3 coordinates withing the code, but, all the geometry shapes should now be working with and without fill.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1662 on: September 17, 2020, 09:03:05 am »
:wtf:  That's going to take some time to get my head around. :o  Thank you though.

So the first question that springs up when looking at the LUTs is this:

Code: [Select]
logic [1:0] LUT_LG1_SEL_XY[0:511] = '{
You've got one table for each of the first two linegens (LUT_LG1 and LUT_LG2), but I'm a little confused why they're declared as [1:0] LUT_name[0:511]?  There's 512 entries in the table, but what's the first index (1:0) for?
The first [1:0] means each table entry is a number between 0 and 3, IE: 2 bits wide, it's not an index...
Unlike parameter int's, this tells the compiler the size of the results so I may use the results inside indexed arrays and the compiler will simplify any values in the array down to a logic truth table.
Quote
Also, for the box function, wouldn't it make sense to use both the linegens to draw the parallel lines simultaneously? ???  The second linegen looks seriously underused.  ;)
Take a look at my new upload which supports box fills.
The box function is the same, but, the box_fill does use both linegens in parallel while the third linegen fills the space inbetween.

Same with the quadrilateral and quadrilateral fill.
(You can do freaky double triangles here if you cross up your a,b,c,d coordinates.  I would like to see what happens on the screen when you do so...)
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1663 on: September 17, 2020, 10:06:27 am »
Got to head out, but will continue testing when I get back.  Rects, lines and pixels are all working great though.  ;D :-+
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1664 on: September 17, 2020, 01:03:29 pm »
Okay, here's some test images.  The code that draws them does so in this sequence:
  • Draw a red filled rectangle from 32,1 to 64,32
  • Draws a pair of yellow diagonal lines, from 33,2 to 63,31 and 33,31 to 63,2
  • Draws four blue pixels in the corners at 32,1 - 64,1 - 32,32 - 64,32
  • Draws a white rectangle from 32,1 to 64,32
  • Draws a filled mauve triangle, 1,1 - 24,24 - 3,100
  • Draws a white triangle, 1,1 - 24,24 - 3,100

I have 6 images attached, showing the graphics output from each of the above steps.

At the moment, the only error I can see is the missing pixel in the filled rectangle?  Otherwise, the box fill seems to be okay?
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1665 on: September 17, 2020, 01:35:25 pm »
Quadrilateral checks out fine as well.  :-+
« Last Edit: September 17, 2020, 01:38:22 pm by nockieboy »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1666 on: September 17, 2020, 02:41:26 pm »
What's that missing dot in the purple triangle?
Also, try a weird quadrilateral where it is forced to make one side more pointed and stretched.
« Last Edit: September 17, 2020, 02:43:13 pm by BrianHG »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1667 on: September 17, 2020, 02:42:37 pm »
What's that missing dot in the purple triangle?

At the moment, the only error I can see is the missing pixel in the filled rectangle?  Otherwise, the box fill seems to be okay?

I'm not sure.  As soon as I get time, I'll try a few more triangles and see if it repeats, but it appears every time in that particular test.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1668 on: September 17, 2020, 02:45:05 pm »
In line generator, try this:
In the line generator, line 149 reads:

                    ypos_stopped_int   <= 1'b1    ; // PREset ypos_stopped_int flag

Change that to a 1'b0.
Should fix the triangle, but give you the reverse buf where the filled box and filled quad will be missing the first line.


« Last Edit: September 17, 2020, 02:46:43 pm by BrianHG »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1669 on: September 17, 2020, 03:00:46 pm »
That's interesting - yes, it gets rid of the missing pixel and also the top line of the rectangle and quad.  What I don't understand is how that would affect a single pixel in the middle of the triangle fill?

Shame though, it seemed like a good fix for the missing top-line issue.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1670 on: September 17, 2020, 03:09:07 pm »
Extreme quad attached...  Same coordinates as before, except for X/Y[2] which I extended out around 250,250-ish.  As you can see, there's a fill error there - or I've got the coordinate order mixed up?

Here's the coordinates I used:

X/Y[0]: 32,40
X/Y[1]: 64,40
X/Y[2]: 236,246
X/Y[3]: 28,70
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1671 on: September 17, 2020, 07:24:10 pm »
That's interesting - yes, it gets rid of the missing pixel and also the top line of the rectangle and quad.  What I don't understand is how that would affect a single pixel in the middle of the triangle fill?

Shame though, it seemed like a good fix for the missing top-line issue.
RUN The simulation!!!
Watch what linegen 1,2, then 3 is doing in each case.
Predict what would happen in a large area fill.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1672 on: September 17, 2020, 07:36:49 pm »
For now, stuff the quads.
Show me what a triangle with a flat & near flat top and flat & near flat bottom looks like.

Extra:
If you go enough ram, go into 480x320x4 color so you can test the pixel writer's 4 color mode and larger filled surfaces.

I think we will switch over to a sequencer and just live with an extra clock cycle as new line parameters change.

Maybe we can get rid of the Y wait and just do a pixel wait and make a line fill every pixel advance from the first 2 linegens.  This would multiple repaint over many lines but the fills can be at any angle between both linegen outputs.  No clue if you would get pixel voids.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7747
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #1673 on: September 17, 2020, 07:57:03 pm »
Just so we are clear, stopping your linegen on a chosen Y position was easier and faster and fewer lines of code in the linegen than what you did which became a little isolated monsters which needs a taming...
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #1674 on: September 18, 2020, 09:51:18 pm »
For now, stuff the quads.
Show me what a triangle with a flat & near flat top and flat & near flat bottom looks like.

Okay, image attachments as below:

image_1.jpg - Flat top
image_2.jpg - Near-flat top
image_3.jpg - Flat bottom
image_4.jpg - Near-flat bottom

« Last Edit: September 18, 2020, 09:54:46 pm by nockieboy »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf