Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents

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

...

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 able to 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
outputpng
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
outputpng
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"]
}