tf.v 6.69 KB
////////////////////////////////////////////////////////////////////////
//
// Project Reality
//
// module:	tf
// description:	Top level for texture filter unit. 2 pipe stages.
//
// designer:	Phil Gossett
// date:	6/15/95
//
////////////////////////////////////////////////////////////////////////

module tf (clk, start_gclk, st_span, ncyc, bilerp0m, bilerp1m, convert_one, mid_texel,
	k0_coeff, k1_coeff, k2_coeff, k3_coeff,
	lod_frac, sfrac_rg, tfrac_rg, sfrac_ba, tfrac_ba,
	tm_ra, tm_ga, tm_ba, tm_aa,
	tm_rb, tm_gb, tm_bb, tm_ab,
	tm_rc, tm_gc, tm_bc, tm_ac,
	tm_rd, tm_gd, tm_bd, tm_ad,
	tf_r, tf_g, tf_b, tf_a, tf_lod_frac);

input clk;
input start_gclk;
input st_span;		// start of span (to sync cycle count)
input ncyc;		// number of cycles per pixel (- 1)
input bilerp0m;		// cycle 0 mode bit
input bilerp1m;		// cycle 1 mode bit
input convert_one;	// loopback mode
input mid_texel;	// mid mode (for 4 texel average)
input [8:0] k0_coeff;	// color convert coefficients
input [8:0] k1_coeff;
input [8:0] k2_coeff;
input [8:0] k3_coeff;
input [8:0] lod_frac;	// pipe thru to CCU
input [7:0] sfrac_rg;	// bilerp alphas
input [7:0] tfrac_rg;
input [7:0] sfrac_ba;
input [7:0] tfrac_ba;
input [8:0] tm_ra;	// this texel
input [8:0] tm_ga;
input [8:0] tm_ba;
input [8:0] tm_aa;
input [8:0] tm_rb;	// horizontal texel
input [8:0] tm_gb;
input [8:0] tm_bb;
input [8:0] tm_ab;
input [8:0] tm_rc;	// vertical texel
input [8:0] tm_gc;
input [8:0] tm_bc;
input [8:0] tm_ac;
input [8:0] tm_rd;	// other (opposite) texel
input [8:0] tm_gd;
input [8:0] tm_bd;
input [8:0] tm_ad;

output [8:0] tf_r;	// texture filter unit outputs
output [8:0] tf_g;
output [8:0] tf_b;
output [8:0] tf_a;
output [8:0] tf_lod_frac; // pipe thru to CCU

reg force_cycle;	// temp

reg cycle;		// cycle counter (0 if 1 cycle pixel)

reg bilerp;		// control for 1st stage muxes
reg mid_rg;		// mid mode active
reg mid_ba;
reg [7:0] sfrac_sh_rg;	// bilerp alphas (shifted for mid mode)
reg [7:0] tfrac_sh_rg;
reg [7:0] sfrac_sh_ba;
reg [7:0] tfrac_sh_ba;

reg loopback;		// mux control for second stage
reg [8:0] rg_reg_a;	// 1st multiply input (pre mux)
reg [8:0] ba_reg_a;
reg [8:0] rg_reg_b;	// 2nd multiply input (pre mux)
reg [8:0] ba_reg_b;
reg [8:0] r_reg_c;	// final lerp add (pre mux)
reg [8:0] g_reg_c;
reg [8:0] b_reg_c;
reg [8:0] a_reg_c;
reg [8:0] r_reg_xa;	// 1st positive subtract input
reg [8:0] g_reg_xa;
reg [8:0] b_reg_xa;
reg [8:0] a_reg_xa;
reg [8:0] r_reg_ya;	// 1st negative subtract input
reg [8:0] g_reg_ya;
reg [8:0] b_reg_ya;
reg [8:0] a_reg_ya;
reg [8:0] r_reg_xb;	// 2nd positive subtract input
reg [8:0] g_reg_xb;
reg [8:0] b_reg_xb;
reg [8:0] a_reg_xb;
reg [8:0] r_reg_yb;	// 2nd negative subtract input
reg [8:0] g_reg_yb;
reg [8:0] b_reg_yb;
reg [8:0] a_reg_yb;
reg [8:0] r_reg_t;	// for mid mode average (1's comp)
reg [8:0] g_reg_t;
reg [8:0] b_reg_t;
reg [8:0] a_reg_t;
reg [8:0] r_reg_o;	// for mid mode average
reg [8:0] g_reg_o;
reg [8:0] b_reg_o;
reg [8:0] a_reg_o;
reg [8:0] reg_lod_frac; // pipe thru to CCU

wire [8:0] rg_a;	// 1st multiply input
wire [8:0] ba_a;
wire [8:0] rg_b;	// 2nd multiply input
wire [8:0] ba_b;
wire [8:0] r_c;		// final lerp add
wire [8:0] g_c;
wire [8:0] b_c;
wire [8:0] a_c;
wire [8:0] r_mp;	// final carry-propagated sum
wire [8:0] g_mp;
wire [8:0] b_mp;
wire [8:0] a_mp;

reg [8:0] tf_r;		// texture filter unit outputs
reg [8:0] tf_g;
reg [8:0] tf_b;
reg [8:0] tf_a;
reg [8:0] tf_lod_frac;	// pipe thru to CCU

always @(posedge clk)
  if (start_gclk) begin
	force_cycle = st_span || cycle;
	cycle <= !(force_cycle || !ncyc);
  end

always @(posedge clk)
  if (start_gclk) begin
	bilerp = cycle ? bilerp1m : bilerp0m;
	mid_rg = bilerp && mid_texel &&
		(sfrac_rg[7:3] == 5'b10000) &&
		(tfrac_rg[7:3] == 5'b10000);
	mid_ba = bilerp && mid_texel &&
		(sfrac_ba[7:3] == 5'b10000) &&
		(tfrac_ba[7:3] == 5'b10000);
	sfrac_sh_rg = mid_rg ? {1'b0,sfrac_rg[7:1]} : sfrac_rg;
	tfrac_sh_rg = mid_rg ? {1'b0,tfrac_rg[7:1]} : tfrac_rg;
	sfrac_sh_ba = mid_ba ? {1'b0,sfrac_ba[7:1]} : sfrac_ba;
	tfrac_sh_ba = mid_ba ? {1'b0,tfrac_ba[7:1]} : tfrac_ba;
	loopback <= convert_one && cycle;
	rg_reg_a <= bilerp ? {1'b0,sfrac_sh_rg} : tm_ra; // u
	ba_reg_a <= bilerp ? {1'b0,sfrac_sh_ba} : tm_ra;
	rg_reg_b  <= bilerp ? {1'b0,tfrac_sh_rg} : tm_ga; // v
	ba_reg_b  <= bilerp ? {1'b0,tfrac_sh_ba} : tm_ga;
	r_reg_c  <= bilerp ? tm_ra : tm_ba; // y
	g_reg_c  <= bilerp ? tm_ga : tm_ba;
	b_reg_c  <= bilerp ? tm_ba : tm_ba;
	a_reg_c  <= bilerp ? tm_aa : tm_ba;
	r_reg_xa <= bilerp ? tm_rb : 9'b000000000;
	g_reg_xa <= bilerp ? tm_gb : k1_coeff;
	b_reg_xa <= bilerp ? tm_bb : k3_coeff;
	a_reg_xa <= bilerp ? tm_ab : 9'b000000000;
	r_reg_ya <= bilerp ? tm_ra : 9'b000000000;
	g_reg_ya <= bilerp ? tm_ga : ~k1_coeff;
	b_reg_ya <= bilerp ? tm_ba : ~k3_coeff;
	a_reg_ya <= bilerp ? tm_aa : 9'b000000000;
	r_reg_xb <= bilerp ? tm_rc : k0_coeff;
	g_reg_xb <= bilerp ? tm_gc : k2_coeff;
	b_reg_xb <= bilerp ? tm_bc : 9'b000000000;
	a_reg_xb <= bilerp ? tm_ac : 9'b000000000;
	r_reg_yb <= bilerp ? tm_ra : ~k0_coeff;
	g_reg_yb <= bilerp ? tm_ga : ~k2_coeff;
	b_reg_yb <= bilerp ? tm_ba : 9'b000000000;
	a_reg_yb <= bilerp ? tm_aa : 9'b000000000;
	r_reg_t  <= ~({9{mid_rg}} & tm_ra);
	g_reg_t  <= ~({9{mid_rg}} & tm_ga);
	b_reg_t  <= ~({9{mid_ba}} & tm_ba);
	a_reg_t  <= ~({9{mid_ba}} & tm_aa);
	r_reg_o  <=   {9{mid_rg}} & tm_rd;
	g_reg_o  <=   {9{mid_rg}} & tm_gd;
	b_reg_o  <=   {9{mid_ba}} & tm_bd;
	a_reg_o  <=   {9{mid_ba}} & tm_ad;
	reg_lod_frac <= lod_frac;
end

// don't optimize the following instanced stuff:
tf_mux9	tfmuxra	(.s(loopback), .i0i(rg_reg_a), .i1i(tf_r), .z(rg_a));
tf_mux9	tfmuxga	(.s(loopback), .i0i(ba_reg_a), .i1i(tf_r), .z(ba_a));
tf_mux9	tfmuxrb	(.s(loopback), .i0i(rg_reg_b), .i1i(tf_g), .z(rg_b));
tf_mux9	tfmuxgb	(.s(loopback), .i0i(ba_reg_b), .i1i(tf_g), .z(ba_b));
tf_mux9	tfmuxrc	(.s(loopback), .i0i(r_reg_c), .i1i(tf_b), .z(r_c));
tf_mux9	tfmuxbc	(.s(loopback), .i0i(g_reg_c), .i1i(tf_b), .z(g_c));
tf_mux9	tfmuxgc	(.s(loopback), .i0i(b_reg_c), .i1i(tf_b), .z(b_c));
tf_mux9	tfmuxac	(.s(loopback), .i0i(a_reg_c), .i1i(tf_b), .z(a_c));
tf_lerp	tflerpr	(.xa(r_reg_xa), .ya(r_reg_ya), .a(rg_a),
		 .xb(r_reg_xb), .yb(r_reg_yb), .b(rg_b),
		 .c(r_c), .t(r_reg_t), .o(r_reg_o), .mp(r_mp));
tf_lerp	tflerpg	(.xa(g_reg_xa), .ya(g_reg_ya), .a(rg_a),
		 .xb(g_reg_xb), .yb(g_reg_yb), .b(rg_b),
		 .c(g_c), .t(g_reg_t), .o(g_reg_o), .mp(g_mp));
tf_lerp	tflerpb	(.xa(b_reg_xa), .ya(b_reg_ya), .a(ba_a),
		 .xb(b_reg_xb), .yb(b_reg_yb), .b(ba_b),
		 .c(b_c), .t(b_reg_t), .o(b_reg_o), .mp(b_mp));
tf_lerp	tflerpa	(.xa(a_reg_xa), .ya(a_reg_ya), .a(ba_a),
		 .xb(a_reg_xb), .yb(a_reg_yb), .b(ba_b),
		 .c(a_c), .t(a_reg_t), .o(a_reg_o), .mp(a_mp));

always @(posedge clk)
  if (start_gclk) begin
	tf_r <= r_mp;
	tf_g <= g_mp;
	tf_b <= b_mp;
	tf_a <= a_mp;
	tf_lod_frac <= reg_lod_frac;
end

endmodule // tf