tc_adj.v 8.11 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_adj.v,v 1.2 2002/11/22 00:34:20 rws Exp $

//////////////////////////////////////////////////////////////////////// 
//
// Project Reality
//
// module:	tc_adj
// description:	Texture coordinate adjust module. Conversion
//		of S or T from image coordinates to tile
//		coordinates. Clamp, wrap, and mirror S or T tile
//		coordinate. Also determine tile coordinate fraction.
//
// designer:	Tony DeLaurier
// date:	6/24/94
//
////////////////////////////////////////////////////////////////////////

module tc_adj (clk, start_gclk, c_w, load_8d, load_9d, shift_c, cl, ch, mask_c, mir_c, 
	       shift_coord, clamp_c, copy, c_adrs, c_frac_1d, mask_en_1d, 
	       c_all_zero, c_all_one, wrap_bit_1d);

  input clk, start_gclk;			// RDP gated clock
  input [15:0] c_w;             // perspective corrected text. coord.
  input load_8d;		// load delayed 8 cycles
  input load_9d;		// load delayed 9 cycles
  input [3:0] shift_c;		// tile attribute: right shift
  input [11:0] cl;		// tile attribute: tile offset in image space
  input [11:0] ch;		// tile attribute: tile end in image space
  input [3:0] mask_c;           // tile attribute: coord. mask
  input mir_c;                  // tile attribute: enable mirror
  input shift_coord;            // treat coord. as 12.3
  input clamp_c;                // tile attribute: coord. clamp enabled
  input copy;                   // copy mode enabled

  output [12:0] c_adrs;         // c passed to address block
  reg [12:0] c_adrs;            // c passed to address block
  output [4:0] c_frac_1d;       // c fraction delayed
  reg [4:0] c_frac_1d;          // c fraction delayed
  output mask_en_1d;      	// registered mask enable
  reg mask_en_1d;      		// registered mask enable
  output [3:0] c_all_zero;      // c all zeros +0, +1, +2, +3
  reg [3:0] c_all_zero;      	// c all zeros +0, +1, +2, +3
  output [3:0] c_all_one;       // c all ones -0, -1 , -2, -3
  reg [3:0] c_all_one;      	// c all ones -0, -1 , -2, -3
  output wrap_bit_1d;           // next coord. bit above mask
  reg wrap_bit_1d;              // next coord. bit above mask

  reg [15:0] c_shifted;		// coord shifted right
  reg [16:0] c_tile;		// text. coord. in tile space
  reg mask_en;                  // mask enabled
  reg clamp_dis;                // clamp disabled
  reg max;                      // c_shifted >= ch
  reg [9:0] tile_diff;          // tile difference
  reg c_over;                   // >= to last texel of tile
  reg c_under;                  // < first texel of tile
  reg [12:0] c_tile_shifted;    // c_tile shifted
  reg [12:0] c_clamped;         // c clamped
  reg [9:0] msk_dec;            // decoded mask
  reg wrap_bit;                 // next coord. bit above mask
  reg [9:0] c_masked;           // c wrapped or mirrored
  reg [4:0] c_frac;             // c fraction

  always @(posedge clk)
    if (start_gclk) begin

    // shift texture coordinate
    
    case (shift_c[3:0] & {4{~load_8d}})
      4'h0: c_shifted[15:0] = {c_w[15:0]};
      4'h1: c_shifted[15:0] = {{2{c_w[15]}}, c_w[14:1]};
      4'h2: c_shifted[15:0] = {{3{c_w[15]}}, c_w[14:2]};
      4'h3: c_shifted[15:0] = {{4{c_w[15]}}, c_w[14:3]};
      4'h4: c_shifted[15:0] = {{5{c_w[15]}}, c_w[14:4]};
      4'h5: c_shifted[15:0] = {{6{c_w[15]}}, c_w[14:5]};
      4'h6: c_shifted[15:0] = {{7{c_w[15]}}, c_w[14:6]};
      4'h7: c_shifted[15:0] = {{8{c_w[15]}}, c_w[14:7]};
      4'h8: c_shifted[15:0] = {{9{c_w[15]}}, c_w[14:8]};
      4'h9: c_shifted[15:0] = {{10{c_w[15]}}, c_w[14:9]};
      4'ha: c_shifted[15:0] = {{11{c_w[15]}}, c_w[14:10]};
      4'hb: c_shifted[15:0] = {c_w[10:0], 5'b0};
      4'hc: c_shifted[15:0] = {c_w[11:0], 4'b0};
      4'hd: c_shifted[15:0] = {c_w[12:0], 3'b0};
      4'he: c_shifted[15:0] = {c_w[13:0], 2'b0};
      4'hf: c_shifted[15:0] = {c_w[14:0], 1'b0};
      default: c_shifted[15:0] = 16'bx;
    endcase

    // convert from image to tile coordinate
    
    c_tile[16:3] <= {c_shifted[15], c_shifted[15:3]} - cl[11:0]; //compass adder_arch carry_select_add
   
    c_tile[2:0] <= c_shifted[2:0];
 
    // compare c image coordinate with ch of tile

    max <= (c_shifted[14:3] >= ch[11:0]) && (!c_shifted[15]);

    // determine tile_diff

    tile_diff[9:0] <= ch[11:2] - cl[11:2];

  end // always

  always @(posedge clk)
    if (start_gclk) begin

    // determine mask enable

    mask_en = !(mask_c[3:0] == 0) && !load_9d;

    mask_en_1d <= mask_en;

    // determine clamp disable

    clamp_dis = (mask_en && !clamp_c) || load_9d || copy;

    // determine c_over

    c_over = max && !clamp_dis;

    // determine c_under

    c_under = c_tile[16] && !clamp_dis;

    // determine c_tile_shifted

    c_tile_shifted[12:0] = shift_coord ? {1'b0, c_tile[14:3]} :
                                        {c_tile[16], c_tile[16:5]};
    // determine c_clamped

    if (c_over)
      c_clamped[12:0] = {3'b0, tile_diff[9:0]};
    else
      c_clamped[12:0] = c_tile_shifted[12:0] & {13{~c_under}};

    // wrap and mirror

    // decode mask and extract wrap bit

    case (mask_c[3:0])
      4'h0: 
        begin
          msk_dec[9:0] = 10'h001;
          wrap_bit = c_clamped[0];
        end
      4'h1: 
        begin
          msk_dec[9:0] = 10'h001;
          wrap_bit = c_clamped[1];
        end
      4'h2: 
        begin
          msk_dec[9:0] = 10'h003;
          wrap_bit = c_clamped[2];
        end
      4'h3: 
        begin 
          msk_dec[9:0] = 10'h007;
          wrap_bit = c_clamped[3];
        end
      4'h4: 
        begin 
          msk_dec[9:0] = 10'h00f;
          wrap_bit = c_clamped[4];
        end
      4'h5: 
        begin 
          msk_dec[9:0] = 10'h01f;
          wrap_bit = c_clamped[5];
        end
      4'h6: 
        begin 
          msk_dec[9:0] = 10'h03f;
          wrap_bit = c_clamped[6];
        end
      4'h7: 
        begin 
          msk_dec[9:0] = 10'h07f;
          wrap_bit = c_clamped[7];
        end
      4'h8: 
        begin 
          msk_dec[9:0] = 10'h0ff;
          wrap_bit = c_clamped[8];
        end
      4'h9: 
        begin 
          msk_dec[9:0] = 10'h1ff;
          wrap_bit = c_clamped[9];
        end
      4'ha: 
        begin 
          msk_dec[9:0] = 10'h3ff;
          wrap_bit = c_clamped[10];
        end
      default: 
        begin 
          msk_dec[9:0] = 10'h3ff;
          wrap_bit = c_clamped[10];
        end
    endcase

    // delay the wrap bit for output
    wrap_bit_1d <= wrap_bit;

    // wrap or mirror the tile coordinate

    c_masked[9:0] = msk_dec[9:0] & (c_clamped[9:0] ^ {10{(mir_c & wrap_bit)}});

    // determine all_one and all_zero flags for c_masked

    c_all_zero[0] <= (c_masked[9:0] == 10'h000);
    c_all_zero[1] <= (c_masked[9:0] == 10'h001);
    c_all_zero[2] <= (c_masked[9:0] == 10'h002);
    c_all_zero[3] <= (c_masked[9:0] == 10'h003);

    c_all_one[0] <= ((c_masked[9:0] | ~msk_dec[9:0]) == 10'h3ff);
    c_all_one[1] <= ((c_masked[9:0] | ~msk_dec[9:0]) == 10'h3fe);
    c_all_one[2] <= ((c_masked[9:0] | ~msk_dec[9:0]) == 10'h3fd);
    c_all_one[3] <= ((c_masked[9:0] | ~msk_dec[9:0]) == 10'h3fc);

    // select between clamping and masking

    c_adrs[12:0] <= mask_en ? {3'b0, c_masked[9:0]} : c_clamped[12:0];

    // determine tile coordinate fraction and delay

    c_frac[4:0] <= c_tile[4:0] &
               {5{!((!mask_en || (mask_en && !clamp_dis)) && (c_over || c_under))}};
    
    c_frac_1d[4:0] <= c_frac[4:0];

  end // always

endmodule // tc_adj