tc_lod.v 7.41 KB
/**************************************************************************
 *                                                                        *
 *               Copyright (C) 1994, Silicon Graphics, Inc.               *
 *                                                                        *
 *  These coded instructions, statements, and computer programs  contain  *
 *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
 *  are protected by Federal copyright  law.  They  may not be disclosed  *
 *  to  third  parties  or copied or duplicated in any form, in whole or  *
 *  in part, without the prior written consent of Silicon Graphics, Inc.  *
 *                                                                        *
 *************************************************************************/

// $Id: tc_lod.v,v 1.1.1.1 2002/05/17 06:07:49 blythe Exp $

////////////////////////////////////////////////////////////////////////
//
// Project Reality
//
// module:	tc_lod
// description:	Level of detail module. Transforms LOD into tile memory
//		addresses and into LOD fraction for 3rd-axis mip-map
//		interpolation.
//
// designer:	Tony DeLaurier
// date:	6/21/94
//
////////////////////////////////////////////////////////////////////////

module tc_lod (gclk, st_span, ncyc, lod, min_level, max_level, detail_en, 
	       sharp_en, lod_en, prim_tile, load, tlut_en, l_frac_out, l_tile, 
	       lod_ge_one_out, load_3d, load_4d);

  input gclk;			// RDP gated clock
  input st_span;                // start span
  input ncyc;                   // 0: 1-cycle mode, 1: 2-cycle mode
  input [15:0] lod;		// level of detail 
  input [4:0] min_level;	// minimum lod fraction clamp
  input [2:0] max_level;	// number of mipmaps -1 or -2
  input detail_en;		// enable detailed texture
  input sharp_en;		// enable sharpened texture
  input lod_en;			// use lod in tile indices determination
  input [2:0] prim_tile;	// base tile index of primitive
  input load;			// load_tile, load_block or load_tlut
  input tlut_en;                // enable texture lookup table

  output [8:0] l_frac_out;	// l_frac out
  reg [8:0] l_frac_out;		// l_frac out
  output [2:0] l_tile;		// tile index into tile memory
  reg [2:0] l_tile;		// tile index into tile memory
  output lod_ge_one_out;	// lod >= 1
  reg lod_ge_one_out;		// lod >= 1
  output load_3d;		// load delayed 3 cycles
  reg load_3d;			// load delayed 3 cycles
  output load_4d;		// load delayed 4 cycles
  reg load_4d;			// load delayed 4 cycles

  reg [14:0] lod_clamp;		// clamped lod
  reg min;			// below finest level of detail
  reg max;			// equal or above coarsest level of detail
  reg [2:0] lod_index;		// encoded lod
  reg [2:0] index_clamp;	// clamped encoded lod
  reg [7:0] fraction;		// lod fraction
  reg [7:0] fract_clamp;	// clamped lod fraction
  reg inc;			// increment tile address by one
  reg inc2;			// increment tile address by two
  reg load_1d;			// load delayed 1 cycle
  reg load_2d;			// load delayed 2 cycles
  reg force_cycle;		// force cycle 
  reg cycle;			// cycle 0 or cycle 1

  reg [8:0] l_frac;		// lod fraction for 3rd-axis interpolation
  reg [8:0] l_frac_1d;		// l_frac delayed 1
  reg [8:0] l_frac_2d;		// l_frac delayed 2
  reg [8:0] l_frac_3d;		// l_frac delayed 3
  reg [8:0] l_frac_4d;		// l_frac delayed 4
  reg [8:0] l_frac_5d;		// l_frac delayed 5
  reg [8:0] l_frac_6d;		// l_frac delayed 6
  reg [8:0] l_frac_7d;		// l_frac delayed 7
  reg [8:0] l_frac_8d;		// l_frac delayed 8

  reg lod_ge_one;		// lod >= 1
  reg lod_ge_one_1d;		// lod_ge_one delayed 1
  reg lod_ge_one_2d;		// lod_ge_one delayed 2
  reg lod_ge_one_3d;		// lod_ge_one delayed 3
  reg lod_ge_one_4d;		// lod_ge_one delayed 4
  reg lod_ge_one_5d;		// lod_ge_one delayed 5
  reg lod_ge_one_6d;		// lod_ge_one delayed 6
  reg lod_ge_one_7d;		// lod_ge_one delayed 7
  reg lod_ge_one_8d;		// lod_ge_one delayed 8

  reg tlut_en_1d;		// tlut_en delayed 1
  reg tlut_en_2d;		// tlut_en delayed 2

  always @(posedge gclk)
  begin

    // clamp lod

    if (lod[15] && lod[14])
    begin
      lod_clamp[14:5] = 0;
      lod_clamp[4:0] = min_level[4:0];
    end 
    else if (lod[15] && !lod[14])
    begin
      lod_clamp[14:0] = 15'h7fff;
    end 
    else if ((lod[14:5] == 0) && (lod[4:0] < min_level[4:0]))
    begin
      lod_clamp[14:5] = 0;
      lod_clamp[4:0] = min_level[4:0];
    end 
    else
      lod_clamp[14:0] = lod[14:0];

    // delay tlut_en by 2 cycles

    tlut_en_1d <= tlut_en;
    tlut_en_2d <= tlut_en_1d;

    // determine if below finest lod
    
    min = (lod_clamp[14:5] == 0);

    lod_ge_one <= !min;
    lod_ge_one_1d <= lod_ge_one;
    lod_ge_one_2d <= lod_ge_one_1d;
    lod_ge_one_3d <= lod_ge_one_2d;
    lod_ge_one_4d <= lod_ge_one_3d;
    lod_ge_one_5d <= lod_ge_one_4d;
    lod_ge_one_6d <= lod_ge_one_5d;
    lod_ge_one_7d <= lod_ge_one_6d;
    lod_ge_one_8d <= lod_ge_one_7d;

    lod_ge_one_out <= tlut_en_2d ? lod_ge_one_8d : lod_ge_one_6d;

    // determine lod_index

    casez (lod_clamp[12:5])
      8'b1???????: lod_index[2:0] = 3'h7;
      8'b01??????: lod_index[2:0] = 3'h6;
      8'b001?????: lod_index[2:0] = 3'h5;
      8'b0001????: lod_index[2:0] = 3'h4;
      8'b00001???: lod_index[2:0] = 3'h3;
      8'b000001??: lod_index[2:0] = 3'h2;
      8'b0000001?: lod_index[2:0] = 3'h1;
      8'b00000001: lod_index[2:0] = 3'h0;
      8'b00000000: lod_index[2:0] = 3'h0;
      default: lod_index[2:0] = 3'bx;
    endcase

    // determine if greater than or equal to coarsest lod

    max = ((lod_clamp[14:13] != 0) || (lod_index[2:0] >= max_level[2:0]));

    // clamp lod_index

    index_clamp[2:0] = max ? max_level[2:0] : lod_index[2:0];

    // determine lod fraction
    
    case (lod_index[2:0])
      3'h0: fraction[7:0] = {lod_clamp[4:0], 3'b0};
      3'h1: fraction[7:0] = {lod_clamp[5:0], 2'b0};
      3'h2: fraction[7:0] = {lod_clamp[6:0], 1'b0};
      3'h3: fraction[7:0] = {lod_clamp[7:0]};
      3'h4: fraction[7:0] = {lod_clamp[8:1]};
      3'h5: fraction[7:0] = {lod_clamp[9:2]};
      3'h6: fraction[7:0] = {lod_clamp[10:3]};
      3'h7: fraction[7:0] = {lod_clamp[11:4]};
      default: fraction[7:0] = 8'hx;
    endcase

    // clamp fraction

    fract_clamp[7:0] = fraction[7:0];
    if (~sharp_en && ~detail_en)
    begin
      if (max) 
        fract_clamp[7:0] = 8'hff;
      else if (min)
	fract_clamp[7:0] = 8'h00;
    end
    
    // for now leave out detail texture tlu

    // negate based on sharpen (register)
    
    l_frac[8:0] <= {(min && sharp_en), fract_clamp[7:0]};
    l_frac_1d <= l_frac;
    l_frac_2d <= l_frac_1d;
    l_frac_3d <= l_frac_2d;
    l_frac_4d <= l_frac_3d;
    l_frac_5d <= l_frac_4d;
    l_frac_6d <= l_frac_5d;
    l_frac_7d <= l_frac_6d;
    l_frac_8d <= l_frac_7d;

    l_frac_out <= tlut_en_2d ? l_frac_8d : l_frac_6d;

    // determine which cycle

    force_cycle = st_span || cycle;
    cycle <= !force_cycle && ncyc;

    // determine inc and inc2

    inc = (detail_en && ~cycle && ~min) ||
          (detail_en && cycle && (min || max)) ||
          (~detail_en && cycle && (~min || sharp_en) && ~max);

    // delay load 

    load_1d <= load;
    load_2d <= load_1d;
    load_3d <= load_2d;
    load_4d <= load_3d;

    if (load_1d)
      inc = 0;
    else if (~lod_en)
      inc = cycle;

    inc2 = detail_en && cycle && ~(min || max);

    if (load_1d || ~lod_en)
      inc2 = 0;

    // add (register)

    l_tile[2:0] <= (index_clamp[2:0] & {3{lod_en}} & {3{~load_1d}}) + 
		   prim_tile[2:0] + inc + (inc2 << 1);

  end // always

endmodule // tc_lod