ms_rand.v 6.4 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: ms_rand.v,v 1.1 2002/03/28 00:26:13 berndt Exp $

////////////////////////////////////////////////////////////////////////
//
// Project Reality
//
// module:      ms_rand
// description: Pseudo_random number generator for mem span unit.
//		Generates 3 sets of 3 bits of random numbers for
//		dithering the 8 bit RGB values to 5 bits in 5/5/5/3
//		color mode. Made of long period recirculating shift
//		registers, with relatively prime periods within
//		each color, and different periods for each of the
//		nine bits. Should be run off the ungated clock, so
//		will not correlate with noise in color combine unit
//		which runs off the rdp's gated clock. Alpha dither
//		is hashed from these random numbers and the noise
//		bits for the color combine unit, which are from the
//		gated clock. Therefore, alpha dither should be only
//		used in the gated clock domain. Since they are
//		correlated, alpha dither should not be used with
//		noise.
//
// designer:    Phil Gossett
// date:        6/2/95
//
////////////////////////////////////////////////////////////////////////

module ms_rand (clk, reset_l, dither_sel, rgb_dither,
	noise, rand_r, rand_g, rand_b, alpha_dither);

input clk;
input reset_l;
input [1:0] dither_sel;		// select type of rgb dither
input [2:0] rgb_dither;		// ordered dither pattern
input [2:0] noise;		// top 3 (random) bits of cc noise[8:6]

output [2:0] rand_r;
output [2:0] rand_g;
output [2:0] rand_b;
output [7:0] alpha_dither;	// hash of noise and rands

reg [29:1] rand30b;		// recirculating shift register
reg [28:1] rand29b;		// recirculating shift register
reg [27:1] rand28b;		// recirculating shift register
reg [26:1] rand27b;		// recirculating shift register
reg [25:1] rand26b;		// recirculating shift register
reg [24:1] rand25b;		// recirculating shift register
reg [22:1] rand23b;		// recirculating shift register
reg [20:1] rand21b;		// recirculating shift register
reg [18:1] rand19b;		// recirculating shift register
reg rand30q;			// recirculating shift register (ls bit)
reg rand29q;			// recirculating shift register (ls bit)
reg rand28q;			// recirculating shift register (ls bit)
reg rand27q;			// recirculating shift register (ls bit)
reg rand26q;			// recirculating shift register (ls bit)
reg rand25q;			// recirculating shift register (ls bit)
reg rand23q;			// recirculating shift register (ls bit)
reg rand21q;			// recirculating shift register (ls bit)
reg rand19q;			// recirculating shift register (ls bit)
reg [7:0] alpha_dither;

wire reset;

// invert reset (this week)
assign reset = ~reset_l;

// 9 bits worth of pseudo-random number generators
always @(posedge clk)
begin
	// 2^30 - 1 = 1,073,741,823 = 3*3*7*11*31*151*331 =  16 s
	rand30b[29:1] <= {rand30b[28:1],rand30q};
	// 2^29 - 1 =   536,870,911 = 233*1103*2089       =   8 s
	rand29b[28:1] <= {rand29b[27:1],rand29q};
	// 2^28 - 1 =   268,435,455 = 3*5*29*43*113*127   =   4 s
	rand28b[27:1] <= {rand28b[26:1],rand28q};
	// 2^27 - 1 =   134,217,727 = 7*73*262657         =   2 s
	rand27b[26:1] <= {rand27b[25:1],rand27q};
	// 2^26 - 1 =    67,108,863 = 3*2731*8191         =   1 s
	rand26b[25:1] <= {rand26b[24:1],rand26q};
	// 2^25 - 1 =    33,554,431 = 31*601*1801	  = 500 ms
	rand25b[24:1] <= {rand25b[23:1],rand25q};
	// 2^23 - 1 =     8,388,607 = 47*178481		  = 125 ms
	rand23b[22:1] <= {rand23b[21:1],rand23q};
	// 2^21 - 1 =     2,097,151 = 7*7*127*337	  =  32 ms
	rand21b[20:1] <= {rand21b[19:1],rand21q};
	// 2^19 - 1 =       524,287 = 524287		  =   8 ms
	rand19b[18:1] <= {rand19b[17:1],rand19q};
end

// 9 bits worth of pseudo-random number generators (ls bit)
always @(posedge clk or posedge reset)
begin
	if (reset == 1'b1)
		begin
		rand30q <= 1'b1;
		rand29q <= 1'b1;
		rand28q <= 1'b1;
		rand27q <= 1'b1;
		rand26q <= 1'b1;
		rand25q <= 1'b1;
		rand23q <= 1'b1;
		rand21q <= 1'b1;
		rand19q <= 1'b1;
		end
	else
		begin
		// 2^30 - 1 = 1,073,741,823 = 3*3*7*11*31*151*331 =  16 s
		rand30q <= rand30b[29]^rand30b[5]^rand30b[3]^rand30q;
		// 2^29 - 1 =   536,870,911 = 233*1103*2089       =   8 s:
		rand29q <= rand29b[28]^rand29b[1];
		// 2^28 - 1 =   268,435,455 = 3*5*29*43*113*127   =   4 s:
		rand28q <= rand28b[27]^rand28b[2];
		// 2^27 - 1 =   134,217,727 = 7*73*262657         =   2 s:
		rand27q <= rand27b[26]^rand27b[4]^rand27b[1]^rand27q;
		// 2^26 - 1 =    67,108,863 = 3*2731*8191         =   1 s
		rand26q <= rand26b[25]^rand26b[5]^rand26b[1]^rand26q;
		// 2^25 - 1 =    33,554,431 = 31*601*1801	  = 500 ms
		rand25q <= rand25b[24]^rand25b[2];
		// 2^23 - 1 =     8,388,607 = 47*178481		  = 125 ms
		rand23q <= rand23b[22]^rand23b[4];
		// 2^21 - 1 =     2,097,151 = 7*7*127*337	  =  32 ms
		rand21q <= rand21b[20]^rand21b[1];
		// 2^19 - 1 =       524,287 = 524287		  =   8 ms
		rand19q <= rand19b[18]^rand19b[4]^rand19b[1]^rand19q;
		end
end

// concatenate to form dither values
assign rand_r = dither_sel[1] ?			// intermediate period
			(({3{dither_sel[0]}})|{rand28q,rand27q,rand25q}) :
			rgb_dither;
assign rand_g = dither_sel[1] ?			// longest period
			(({3{dither_sel[0]}})|{rand30q,rand29q,rand23q}) :
			rgb_dither;
assign rand_b = dither_sel[1] ?			// shortest period
			(({3{dither_sel[0]}})|{rand26q,rand21q,rand19q}) :
			rgb_dither;

// hash noise (gclk: q29,28,27) and rands (clk: q26,25,23,21,19)
always @(posedge clk)
begin
	alpha_dither[7] <= noise[1]^noise[0];
	alpha_dither[6] <= noise[0]^noise[2];
	alpha_dither[5] <= noise[2]^noise[1];
	alpha_dither[4] <= noise[2]^rand26q;	// rand_b[2]
	alpha_dither[3] <= noise[1]^rand25q;	// rand_r[0]
	alpha_dither[2] <= noise[0]^rand23q;	// rand_g[0]
	alpha_dither[1] <= noise[2]^rand21q;	// rand_b[1]
	alpha_dither[0] <= noise[1]^rand19q;	// rand_b[0]
end

endmodule // ms_rand