tc_adrs.v 10 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_adrs.v,v 1.1.1.1 2002/05/17 06:07:49 blythe Exp $

////////////////////////////////////////////////////////////////////////
//
// Project Reality
//
// module:	tc_adrs
// description:	Texture coordinate address module. Transforms tile 
//              coordinates S and T into TMEM address.
//
// designer:	Tony DeLaurier
// date:	6/28/94
//
////////////////////////////////////////////////////////////////////////

module tc_adrs (gclk, tex_type, tex_size, s_adrs, t_adrs, line, tmem_adrs, 
 		load_4d, copy, samp_type, mask_en_s, mask_en_t, mir_s, 
		mir_t, s_all_one, wrap_bit_s, s_all_zero, t_all_one, 
		wrap_bit_t, t_all_zero, a, b_adder, c_adder, d_adder, shift, 
		flip, odd_t, yuv_tex_1d, load_5d, copy_1d, tex_type_1d, 
		tex_size_1d, a_three); 

  `include "tex.vh"

  input gclk;			// RDP gated clock
  input [2:0] tex_type;	      	// tile attribute: texel type
  input [1:0] tex_size;		// tile attribute: texel size
  input [12:0] s_adrs;          // adjusted s
  input [12:0] t_adrs;          // adjusted t
  input [8:0] line;		// tile attribute: line width
  input [8:0] tmem_adrs;	// tile attribute: tmem start address
  input load_4d;                // load_tile, load_block or load_tlut
  input copy;                   // copy mode enabled
  input samp_type;              // filter enabled
  input mask_en_s;              // mask enabled s
  input mask_en_t;              // mask enabled t
  input mir_s;                  // mirror enabled s
  input mir_t;                  // mirror enabled t
  input [3:0] s_all_one;        // s all ones -0, -1 , -2, -3
  input wrap_bit_s;             // s wrap bit
  input [3:0] s_all_zero;       // s all zeros +0, +1, +2, +3
  input t_all_one;              // t all ones
  input wrap_bit_t;             // t wrap bit
  input t_all_zero;             // t all zeros

  output [12:0] a;              // address a before interleave
  reg [12:0] a;			// address a before interleave
  output [12:0] b_adder;	// address b adder input
  reg [12:0] b_adder;		// address b adder input
  output [12:0] c_adder;	// address c adder input
  reg [12:0] c_adder;		// address c adder input
  output [12:0] d_adder;	// address d adder input
  reg [12:0] d_adder;		// address d adder input
  output shift;			// shift b_rg address delta
  reg shift;			// shift b_rg address delta
  output flip;			// flip c and d interleave bit
  reg flip;			// flip c and d interleave bit
  output odd_t;			// registered t lsb
  reg odd_t;			// registered t lsb
  output yuv_tex_1d;		// yuv_tex delayed 1 cycle
  reg yuv_tex_1d;		// yuv_tex delayed 1 cycle
  output load_5d;		// load delayed 5 cycles
  reg load_5d;			// load delayed 5 cycles
  output copy_1d;		// copy delayed 1 cycle
  reg copy_1d;			// copy delayed 1 cycle
  output [2:0] tex_type_1d;     // texel type delayed 1 cycle
  reg [2:0] tex_type_1d;     	// texel type delayed 1 cycle
  output [1:0] tex_size_1d;     // texel size delayed 1 cycle
  reg [1:0] tex_size_1d;     	// texel size delayed 1 cycle
  output a_three;     		// base_address[3]
  reg a_three;     		// base_address[3]

  reg [1:0] tex_size_adj;	// adjusted texel size
  reg [12:0] s_nib;		// s in nibbles
  reg [12:0] tex_nib;		// texel size in nibbles 
  reg [8:0] t_prod;		// t * line 
  reg [12:0] base_adrs;		// base tmem address 
  reg yuv_tex;			// tile texel type is yuv
  reg mir_s_1d;			// mirror enable delayed 1 cycle
  reg mir_t_1d;			// mirror enable delayed 1 cycle


  always @(posedge gclk)
  begin

    // delay copy by a clock
   
    copy_1d <= copy;

    // delay mir enables by a clock

    mir_s_1d <= mir_s;
    mir_t_1d <= mir_t;

    // check for yuv texel type

    yuv_tex = (tex_type == TYPE_YUV);
    yuv_tex_1d <= yuv_tex;
    tex_size_adj[1:0] = (yuv_tex) ? SIZE_8BIT : tex_size[1:0]; 
    
    // determine s and the texel size in nibbles

    case (tex_size_adj[1:0])

      2'b00: 
        begin
          s_nib[12:0] = s_adrs[12:0];
          tex_nib[12:0] = 13'h1;
        end

      2'b01: 
        begin
          s_nib[12:0] = {s_adrs[11:0], 1'b0};
          tex_nib[12:0] = 13'h2;
        end

      2'b10: 
        begin
          s_nib[12:0] = {s_adrs[10:0], 2'b0};
          tex_nib[12:0] = 13'h4;
        end

      2'b11:
        begin 
          s_nib[12:0] = {s_adrs[10:0], 2'b0};
          tex_nib[12:0] = 13'h4;
        end

      default: 
        begin 
          s_nib[12:0] = 13'bx;
          tex_nib[12:0] = 13'bx;
        end

    endcase

    // determine t * line

    t_prod[8:0] = t_adrs[7:0] * line[8:0];

    // determine base address

    base_adrs[12:4] = t_prod[8:0] + tmem_adrs[8:0] + s_nib[12:4];

    base_adrs[3:0] = s_nib[3:0];

    // output the base_adrs[3]

    a_three <= base_adrs[3];

    // kill the long bit <3> if loading

    load_5d <= load_4d;

    a[12:4] <= base_adrs[12:4];
    a[3] <= base_adrs[3] && !load_5d;
    a[2:0] <= base_adrs[2:0];

    // delay t lsb by a clock

    odd_t <= t_adrs[0];

    // determine address B for different modes and conditions

    if (load_5d)
      b_adder[12:0] <= 13'h4;
    else if (copy_1d || samp_type)
    begin
      if (!mask_en_s)
        b_adder[12:0] <= tex_nib[12:0];
      else if (!mir_s_1d)	// wrap_s
      begin
        if (s_all_one[0])
          b_adder[12:0] <= -s_nib[12:0];
        else
          b_adder[12:0] <= tex_nib[12:0];
      end
      else // mirror_s
      begin
        if ((!wrap_bit_s && s_all_one[0]) || (wrap_bit_s && s_all_zero[0]))
          b_adder[12:0] <= 13'h0;
        else if (!wrap_bit_s) 
          b_adder[12:0] <= tex_nib[12:0];
        else
          b_adder[12:0] <= -tex_nib[12:0];
      end
    end
    else // point sample
      b_adder[12:0] <= 13'h0;
  
    // determine address C for different modes and conditions

    if (load_5d)
      c_adder[12:0] <= 13'h8;
    else if (copy_1d)
    begin
      if (!mask_en_s)
	c_adder[12:0] <= {tex_nib[11:0], 1'b0};
      else if (!mir_s_1d) // wrap_s
      begin
        if (s_all_one[0])
	  c_adder[12:0] <= tex_nib[12:0] - s_nib[12:0];
        else if (s_all_one[1])
	  c_adder[12:0] <= -s_nib[12:0];
	else
	  c_adder[12:0] <= {tex_nib[11:0], 1'b0};
      end
      else // mirror_s
      begin
        if ((!wrap_bit_s && s_all_one[1]) || (wrap_bit_s && s_all_zero[0]))
	  c_adder[12:0] <= tex_nib[12:0];
	else if ((!wrap_bit_s && s_all_one[0]) || (wrap_bit_s && s_all_zero[1]))
	  c_adder[12:0] <= -tex_nib[12:0];
        else if (!wrap_bit_s) 
	  c_adder[12:0] <= {tex_nib[11:0], 1'b0};
        else
	  c_adder[12:0] <= -{tex_nib[11:0], 1'b0};
      end
    end
    else if (!samp_type)
      c_adder[12:0] <= 13'h0;
    else
    begin
      if (!mask_en_t)
	c_adder[12:0] <= {line[8:0], 4'h0};
      else if (!mir_t_1d) // wrap_t
      begin
        if (t_all_one)
	  c_adder[12:0] <= -{t_prod[8:0], 4'h0};
        else
	  c_adder[12:0] <= {line[8:0], 4'h0};
      end
      else //mirror_t
      begin
        if ((!wrap_bit_t && t_all_one) || (wrap_bit_t && t_all_zero))
	  c_adder[12:0] <= 13'h0;
        else if (!wrap_bit_t) 
	  c_adder[12:0] <= {line[8:0], 4'h0};
        else
	  c_adder[12:0] <= -{line[8:0], 4'h0};
      end
    end

    // determine address D for different modes and conditions

    if (load_5d)
      d_adder[12:0] <= 13'h8;
    else if (copy_1d)
    begin
      if (!mask_en_s)
        d_adder[12:0] <= {tex_nib[11:0], 1'b0};
      else if (!mir_s_1d) // wrap_s
      begin
        if (s_all_one[1])
          d_adder[12:0] <= -s_nib[12:0];
        else if (s_all_one[2])
          d_adder[12:0] <= -(tex_nib[12:0] + s_nib[12:0]);
        else    
          d_adder[12:0] <= {tex_nib[11:0], 1'b0};
      end
      else // mirror_s
      begin
        if ((!wrap_bit_s && s_all_one[2]) || (wrap_bit_s && s_all_zero[1]))
          d_adder[12:0] <= tex_nib[12:0];
        else if ((!wrap_bit_s && s_all_one[1]) || (wrap_bit_s && s_all_zero[2]))
          d_adder[12:0] <= -tex_nib[12:0];
	else if ((!wrap_bit_s && s_all_one[3]) || (wrap_bit_s && s_all_zero[0]))
	  d_adder[12:0] <= {tex_nib[11:0], 1'b0};
	else if ((!wrap_bit_s && s_all_one[0]) || (wrap_bit_s && s_all_zero[3]))
	  d_adder[12:0] <= -{tex_nib[11:0], 1'b0};
        else if (!wrap_bit_s) 
          d_adder[12:0] <= {tex_nib[11:0], 1'b0};
        else
          d_adder[12:0] <= -{tex_nib[11:0], 1'b0};
      end
    end
    else if (!samp_type)
      d_adder[12:0] <= 13'h0;
    else
    begin
      if (!mask_en_t)
        d_adder[12:0] <= {line[8:0], 4'h0};
      else if (!mir_t_1d) // wrap_t
      begin
        if (t_all_one)
          d_adder[12:0] <= -{t_prod[8:0], 4'h0};
        else
          d_adder[12:0] <= {line[8:0], 4'h0};
      end
      else //mirror_t
      begin
        if ((!wrap_bit_t && t_all_one) || (wrap_bit_t && t_all_zero))
          d_adder[12:0] <= 13'h0;
        else if (!wrap_bit_t)
          d_adder[12:0] <= {line[8:0], 4'h0};
        else
          d_adder[12:0] <= -{line[8:0], 4'h0};
      end
    end

    // determine whether to shift b_rg and d_rg address deltas

    shift <= yuv_tex && !load_5d;

    // determine whether to flip c and d interleave bit

    flip <= (!load_5d && !copy_1d && samp_type) && !(mask_en_t && mir_t_1d && 
                                                 ((!wrap_bit_t && t_all_one) || 
				           	 (wrap_bit_t && t_all_zero)));

    // delay tile texel type and size by 3 cycles

    tex_type_1d <= tex_type;
    tex_size_1d <= tex_size;

  end // always

endmodule // tc_adrs