Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

A placeholder for my viciv.vhdl notesMuch of the impetus behind my studying of “viciv.vhdl” came from an issue I observed while using 640x400 4-bitplanes (16 colour) mode.

The discord thread itself is probably a good read in relation to these studies, so will provide a link to it also:

State Machines

There are two main state machines residing within viciv.vhdl, they are:

  • raster_fetch_state

    • The larger of the two

    • Encompasses all the various drawing modes, such as:

      • character modes (multi-colour, monochrome, extended colour)

      • bitmap modes (monochrome, multi-colour)

      • sprites (0 to 7)

      • bitplane mode

        • note that the 8 bitplanes make use of the same sprite mechanics and are internally considered to be sprites 8 to 15

  • paint_fsm_state

    • The smaller of the two

    • Starts off sitting in ‘Idle’ state, until some activity within the raster_fetch_state machine pushes it to a different paint-state.

I’ll provide graphviz/dot diagrams for the two state machines below. My hope is that they will be of good use to newcomers to this file that want an overview of the behaviour (rather than trying to have a read through the over 5000 lines of source code within the “viciv.vhdl” file). Once you get your bearings via a nice overview diagram like this, I hope you’ll be navigate to the areas you are interested in easier and hone your focus on the specific areas you want to investigate deeper into.

“raster_fetch_state” state machine

Graphviz
digraph raster_fetch_state {
  rankdir=TB;
  node [shape = rectangle];
  graph [splines = ortho];
  nodesep = 2;
  ranksep = 0.5;

  Idle -> FetchScreenRamLine [xlabel="if first_card_of_row !=\n prev_first_card_of_row"];
  Idle -> FetchFirstCharacter [xlabel="else"];
  FetchScreenRamLine -> FetchScreenRamLine2 [xlabel="if paint_ready='1'"];
  FetchScreenRamLine2 -> FetchFirstCharacter [xlabel="if (sixteenbit_charset='1' and end_of_row_16='1')\n   or (sixteenbit_charset='0' and end_of_row='1')"];
  FetchFirstCharacter -> FetchNextCharacter [xlabel="if bitplane_mode='0' or viciv_bitplane_chargen_on='1'"];
  FetchFirstCharacter -> EndOfChargen [xlabel="else"];
  FetchNextCharacter -> FetchCharHighByte [xlabel="if sixteenbit_charset='1'"];
  FetchNextCharacter -> dot [xlabel="else"];
  dot -> FetchTextCell [xlabel="yes"];
  dot -> FetchBitmapCell [xlabel="no"];
  FetchCharHighByte -> FetchTextCell [xlabel="if text_mode='1'"];
  FetchCharHighByte -> FetchBitmapCell [xlabel="else"];
  FetchTextCell -> FetchTextCellColourAndSource;
  FetchTextCellColourAndSource -> PaintMemWait;
  FetchBitmapCell -> FetchBitmapData;
  FetchBitmapData -> PaintMemWait;
  PaintMemWait -> PaintMemWait2;
  PaintMemWait2 -> dot2;
  dot2 -> dot3 [xlabel="yes"];
  dot2 -> PaintMemWait3 [xlabel="no"];
  dot3 -> PaintFullColourFetch [xlabel="yes"];
  dot3 -> PaintFullColourHyperRAMFetch [xlabel="no"];
  PaintFullColourHyperRAMFetch -> PaintMemWait3 [xlabel="if hyper_data_strobe='1'\n and full_colour_fetch_count>=8"];
  PaintFullColourFetch -> PaintMemWait3 [xlabel="if full_colour_fetch_count>=8"];
  PaintMemWait3 -> EndOfChargen [xlabel="if (end_of_row = '1')\n or (short_line='1')"];
  PaintMemWait3 -> PaintDispatch [xlabel="else"];
  PaintDispatch -> FetchNextCharacter [xlabel="if paint_ready='1'"];
  EndOfChargen -> SpritePointerFetch [xlabel="if paint_fsm_state = Idle"];
  SpritePointerFetch -> Idle [xlabel="if sprite_fetch_sprite_number = 16\n or (sprite_fetch_sprite_number = 8\n   and bitplane_mode = '0')"];
  SpritePointerFetch -> SpritePointerFetch2 [xlabel="elsif sprite_fetch_sprite_number < 8"]
  SpritePointerFetch -> dot4
  dot4 -> SpritePointerFetch [xlabel="yes"]
  dot4 -> SpritePointerCompute [xlabel="no"]
  SpritePointerFetch2 -> SpritePointerCompute1;
  SpritePointerCompute1 -> SpritePointerCompute;
  SpritePointerCompute -> SpritePointerComputeMSB [xlabel="vicii_sprite_pointer_address(23)='1'"];
  SpritePointerCompute -> SpriteDataFetch [xlabel="else"];
  SpritePointerComputeMSB -> SpriteDataFetch;
  SpriteDataFetch -> SpriteDataFetch2;
  SpriteDataFetch2 -> SpritePointerFetch [xlabel="if (sprite_fetch_byte_number = max_sprite_fetch_byte_number)"];

  Idle;
  FetchScreenRamLine;
  FetchScreenRamLine2;
  FetchFirstCharacter;
  FetchNextCharacter;
  EndOfChargen;
  FetchCharHighByte;
  dot [shape = diamond, label="if text_mode='1'"];
  dot2 [shape = diamond, label="if glyph_full_color = '1'"];
  dot3 [shape = diamond, label="if glyphs_from_hyperram='0'\n or (not hyper_installed)"];
  dot4 [shape = diamond, label="if bitplane_enables(\n sprite_fetch_sprite_number mod 8)='0'"]
  
  FetchTextCell;
  FetchTextCellColourAndSource;
  FetchBitmapCell;
  FetchBitmapData;
  PaintFullColourFetch;
  PaintFullColourHyperRAMFetch;
  PaintMemWait;
  PaintMemWait2;
  PaintDispatch;
  SpritePointerFetch;
  SpritePointerFetch2;
  SpritePointerCompute1;
  SpritePointerCompute;
  SpritePointerComputeMSB;
  SpriteDataFetch;
  SpriteDataFetch2;
}

“paint_fsm_state” state machine

Graphviz
digraph paint_fsm {
    rankdir=TB;
  node [shape = rectangle];
  graph [splines = ortho];
  nodesep = 2;
  ranksep = 0.5;

    // Define custom colors
    lightblue = "#ADD8E6";

    // Define legend box
    subgraph cluster_legend {
        label = "Legend";
        shape = "none";
        color = "gray";
        
        // Define HTML label for legend table
        legend_table [label=<
            <table border="0" cellborder="1" cellspacing="0">
                <tr>
                    <td bgcolor="lightblue">raster_fetch_state</td>
                </tr>
                <tr>
                    <td bgcolor="palegreen">paint_fsm_state</td>
                </tr>
            </table>
        >];
    }
    
  Idle [label="Idle", style=filled, fillcolor=palegreen];
  PaintFullColour [label="PaintFullColour", style=filled, fillcolor=palegreen];
  PaintMultiColour [label="PaintMultiColour", style=filled, fillcolor=palegreen];
  PaintMono [label="PaintMono", style=filled, fillcolor=palegreen];
  PaintMonoDrive [label="PaintMonoDrive", style=filled, fillcolor=palegreen];
  PaintMonoBits [label="PaintMonoBits", style=filled, fillcolor=palegreen];
  PaintMultiColourDrive [label="PaintMultiColourDrive", style=filled, fillcolor=palegreen];
  PaintMultiColourBits [label="PaintMultiColourBits", style=filled, fillcolor=palegreen];
  PaintMultiColourHold [label="PaintMultiColourHold", style=filled, fillcolor=palegreen];
  PaintFullColourPixels [label="PaintFullColourPixels", style=filled, fillcolor=palegreen];
  Paint4bitColourPixels [label="Paint4bitColourPixels", style=filled, fillcolor=palegreen];
  # NOTE: This 'PaintFullColourDone' state wasn't really used by the system, so let's ignore it
  # PaintFullColourDone [label="PaintFullColourDone", style=filled, fillcolor=palegreen];
  cond1 [shape = diamond, label="[raster_fetch_state:PaintDispatch]\nif paint_ready='1'", style=filled, fillcolor=lightblue];
  cond2 [shape = diamond, label="if glyph_goto='1'", style=filled, fillcolor=lightblue];
  cond3 [shape = diamond, label="elsif glyph_full_colour='1'", style=filled, fillcolor=lightblue];
  cond4 [shape = diamond, label="else", style=filled, fillcolor=lightblue];
    cond5 [shape = diamond, label="if multicolour_mode='0'\nand extended_background_mode='0'", style=filled, fillcolor=lightblue];
    cond6 [shape = diamond, label="elsif multicolour_mode='1'", style=filled, fillcolor=lightblue]
      cond7 [shape = diamond, label="text_mode='1' and glyph_colour(3)='0'", style=filled, fillcolor=lightblue]
    cond8 [shape = diamond, label="elsif extended_background_mode='1'", style=filled, fillcolor=lightblue]
  cond9 [shape = diamond, label="[raster_fetch_state:EndOfChargen]\nif paint_ready='1'", style=filled, fillcolor=lightblue];

  Idle -> cond1;
  cond1 -> Idle [xlabel="no"];
  cond1 -> cond2 [xlabel="yes"];
  cond2 -> Idle [xlabel="yes"];
  cond2 -> cond3 [xlabel="no"];
  cond3 -> PaintFullColour [xlabel="yes"];
  cond3 -> cond4 [xlabel="no"];
  cond4 -> cond5;
  cond5 -> PaintMono [xlabel="yes"];
  cond5 -> cond6 [xlabel="no"];
  cond6 -> cond7 [xlabel="yes"];
  cond7 -> PaintMono [xlabel="yes"];
  cond7 -> PaintMultiColour [xlabel="no"];
  cond6 -> cond8 [xlabel="no"]
  cond8 -> PaintMono [xlabel="yes"]
  
  cond9 -> Idle [xlabel="yes"]
  
  PaintFullColour -> Paint4bitColourPixels [xlabel="if paint_glyph_4bit='1'"];
  PaintFullColour -> PaintFullColourPixels [xlabel="else"];
  
  # Paint4bitColourPixels -> PaintFullColourDone [xlabel = "if not paint_bits_remaining > 0"]
  Paint4bitColourPixels -> Idle [xlabel = "if paint_bits_remaining = 0"];
  
  #PaintFullColourPixels -> PaintFullColourDone [xlabel = "if not paint_bits_remaining > 0"]
  PaintFullColourPixels -> Idle [xlabel = "if paint_bits_remaining = 0"];
  
  PaintMono -> PaintMonoDrive;
  PaintMonoDrive -> PaintMonoBits;
  PaintMonoBits -> Idle [xlabel="if paint_bits_remaining = 1\n or paint_bits_remaining = 0"];
  
  PaintMultiColour -> PaintMultiColourDrive;
  PaintMultiColourDrive -> PaintMultiColourBits;
  PaintMultiColourBits -> PaintMultiColourHold;
  
  PaintMultiColourHold -> Idle [xlabel="if paint_bits_remaining = 0"]
  PaintMultiColourHold -> PaintMultiColourBits [xlabel="else"]
}