#!/bin/csh -f

alias BEGIN 'cat <<END'


@ sram = 0
foreach varg ($*)
  if ($varg =~ "sram") then
    @ sram = 1
    break
  endif
end


BEGIN

/* cammod.v */

\`timescale 1 ns / 10 ps

module cammod (fly_out,
	disp, status_in, status_out,
	lsout, rsout,
	n_dl, n_dr,
	glue_xp, glue_xm,
	glue_yp, glue_ym,
	glue_zp, glue_zm,
	n_lsin, n_rsin, n_iosel, fly_in,
	pb_rst_n, pb_clk,
	sync, ioout,
	scan_in, scan_out
	) ;

	parameter n = $1 ;

	inout [n - 1:0]
		fly_out,
		glue_xp,
		glue_xm,
		glue_yp,
		glue_ym,
		glue_zp,
		glue_zm;
	tri [n - 1:0]
		glue_xp,
		glue_xm,
		glue_yp,
		glue_ym,
		glue_zp,
		glue_zm;

	output
		status_out,
		scan_out,
		lsout,
		rsout,
		ioout;

	inout [n - 1:0]
		disp,
		n_dl,
		n_dr;

	tri [n - 1:0]
		disp,
		n_dl,
		n_dr,
		n_dl_c,
		p52,
		p53;

	tri
		int_n;

	input [n - 1:0]
		fly_in;

	input
		status_in,
		scan_in,
		n_iosel,
		n_lsin,
		n_rsin,
		pb_rst_n,
		pb_clk,
		sync;

	// Internal signals
	wire [n - 1:0]
		dras_n,
		dcas_n,
		dwe_n,
		doe_n,
		saa,
		sba;

END


@ i = 0
while ( $i < $1 )

BEGIN
	wire [10:0] da$i;
	tri [3:0] dd$i;
END

@ i = $i + 1
end


# if there are not enough cam chips to control
#   sram and the sram option is not specified,
#   tie the data to the address
if ( ($1 < 4) && ($sram == 0) ) then

BEGIN

	tri [n - 1:0]
		sad = saa,
		sbd = sba;
END

# if 3 or more chips, just define address and data
else

BEGIN

	tri [3:0]
		sad,
		sbd;
END
endif


BEGIN

	tri [n - 1:0]
		mpa,
		mpb;

	tri
		mod_sel;

	// status in need pulldown
	pulldown_slow PU309 (status_in) ;

	// left status out signal
	pulldown_slow PU300 (lsout) ;

	// io out
	pulldown_slow PU302 (ioout) ;

	// right status out signal
	pullup_slow PU301 (rsout) ;
END



if ($1 == 1) then

BEGIN

        // right status out signal
        assign rsout = U00.u1.u14.n_rsout;

	initial
		begin
		force rsout = 1;

		// release rsout after multipurpose
		//   reg is loaded
		wait ( (U00.u1.u13.u35.u341.z === 1'b0) &&
			(U00.clk === 1'b0) );
//		\$display (\$stime, "  mpb load is low");
		wait ( (U00.u1.u13.u35.u341.z === 1'b1) &&
			(U00.clk === 1'b0) );
//		\$display (\$stime, "  mpb load is high");
		wait ( (U00.u1.u13.u35.u341.z === 1'b0) &&
			(U00.clk === 1'b0) );
//		\$display (\$stime, "  releasing rsout");
		release rsout;
		end
END
 

endif


if ($1 > 3) then
BEGIN

	pullup_slow PU303 (mpb [2]) ;
	pullup_slow PU304 (mpb [3]) ;

	pullup_slow PU305 (mpa [2]) ;
	pullup_slow PU306 (mpa [3]) ;
END
endif


BEGIN

	pullup_slow PU307 (mod_sel) ;
	pullup_slow PU308 (int_n) ;
END


# external buffer for interface bus
BEGIN

        parameter
                BUFFER_TYPE = "CD74AC245";

        // mpb [4] is data direction (0 = read)
        // mpa [4] is data enable (0 = enable)
        TTL245 #(BUFFER_TYPE) U500 (
END

@ i = 0
while ( $i < $1 )

  @ k = $i + 1

BEGIN
                .A${k}(n_dl [$i]),
                .B${k}(n_dl_c [$i]),
END

  @ i = $i + 1
end

BEGIN
                .DIR(U00.u1.n_dlen_n),
                .G(U00.u1.u82.z)
                ) ;
END


@ i = 0

while ( $i < $1 )

if ( $i == 0) then
  set mpa = "status_out"
  set mpb = "status_in"
else if ( $i == 1 ) then
  set mpa = "scan_in"
  set mpb = "scan_out"
else
  set mpa = "mpa [$i]"
  set mpb = "mpb [$i]"
endif

if ( $i == 0 ) then
  set p53 = ".p53(lsout),"
  set p52 = ".p52(ioout),"
else if ( $i == 1 ) then
  set p53 = ".p53(rsout),"
  set p52 = ".p52(p52 [$i]),"

BEGIN

	pullup_slow PU40${i} (p52 [$i]);
END

else
  set p53 = ".p53(p53 [$i]),"
  set p52 = ".p52(p52 [$i]),"

BEGIN

	pullup_slow PU41${i} (p53 [$i]);
	pullup_slow PU42${i} (p52 [$i]);
END

endif

# determine whether to use full chip model
set chip = "chip1"
foreach arg ($*)
  if ( $arg =~ fullcam ) then
    set chip = "chip"
    break
  endif
end

BEGIN

        $chip U0$i (.p2(sad [$i]), .p1(int_n), .p3(sbd [$i]),
                .p4(disp [$i]), .p5($mpb), .p6($mpa),
			.p7(glue_zm [$i]), .p8(glue_zp [$i]),
			.p9(glue_ym [$i]), .p10(glue_yp [$i]),
                        .p11(glue_xm [$i]), .p12(glue_xp [$i]),
			.p21(sync), .p14(mod_sel),
			.p15(dd${i} [3]), .p16(dd${i} [2]),
			.p17(dd${i} [1]), .p18(dd${i} [0]),
			.p19(n_rsin), .p20(n_iosel),
			.p13(fly_in [$i]), .p22(n_lsin),
                        .p23(n_dl_c [$i]), .p24(n_dr [$i]),
			.p25(pb_clk), .p26(pb_rst_n), .p27(fly_out [$i]),
                        .p28(sba [$i]), .p29(saa [$i]), .p30(doe_n [$i]),
			.p31(dcas_n [$i]), .p32(dwe_n [$i]), .p33(dras_n [$i]),
			.p34(da${i} [10]), .p35(da${i} [9]), .p36(da${i} [8]),
			.p37(da${i} [7]), .p38(da${i} [6]), .p39(da${i} [5]),
                        .p40(da${i} [4]), .p41(da${i} [3]), .p42(da${i} [2]),
			.p43(da${i} [1]), .p44(da${i} [0]),
			.p45(glue_zm [$i]), .p46(glue_zp [$i]),
                        .p47(glue_ym [$i]), .p48(glue_yp [$i]),
			.p49(glue_xm [$i]), .p50(glue_xp [$i]),
//                      .p51(1'b0),
			$p52
			$p53
                        .p54(1'b0), .p55(1'b0) ) ;

//TMS44400
TMS44400
     u30$i (da${i}[0] ,da${i}[1] ,da${i}[2] ,da${i}[3] ,da${i}[4] ,da${i}[5] ,
         da${i}[6] ,da${i}[7] ,da${i}[8] ,da${i}[9] ,
         dcas_n[0] ,dd${i}[0] ,dd${i}[1] ,dd${i}[2] ,dd${i}[3] ,
         doe_n[0] , dras_n[0] , dwe_n[0] );

always @(negedge doe_n[${i}] )
  begin
    #25;
    if (dd${i}[0] === 1'bx) force dd${i}[0] = 0;
    if (dd${i}[1] === 1'bx) force dd${i}[1] = 0;
    if (dd${i}[2] === 1'bx) force dd${i}[2] = 0;
    if (dd${i}[3] === 1'bx) force dd${i}[3] = 0;
  end

always @(posedge doe_n[$i] ) 
  begin
    #16;
     release dd${i}[0] ;
     release dd${i}[1] ;
     release dd${i}[2] ;
     release dd${i}[3] ;
  end

END

@ i = $i + 1

end


if ($1 < 3) then

  @ i = 3 - $1
  set csa = "U00.u1.u33.sa_ce_n"
  set csb = "U00.u1.u33.sb_ce_n"
  set wea = "U00.u1.u33.sa_we_n"
  set web = "U00.u1.u33.sb_we_n"
#  set adata = "{sad, ${i}'hz}"
#  set bdata = "{sbd, ${i}'hz}"
  set adata = "sad"
  set bdata = "sbd"


else
  set csa = "mpa [1]"
  set csb = "mpa [2]"
  set wea = "mpb [1]"
  set web = "mpb [2]"
  set adata = "sad"
  set bdata = "sbd"

endif


if ( ($1 > 3) || ($sram == 1) ) then

BEGIN

// module sram (data, address, cs_n, oe_n, we_n);
	sram #(4, n) U100 (.data($adata), .address(saa),
	.cs_n($csa), .oe_n(1'b0), .we_n($wea)
	) ;

	sram #(4, n) U101 (.data($bdata), .address(sba),
	.cs_n($csb), .oe_n(1'b0), .we_n($web)
	) ;
END

endif


if ($1 < 3) then

BEGIN

	initial
		begin
		force $csa = 1; force $csb = 1;
		force $wea = 1; force $web = 1;

		// release cs and we after multipurpose
		//   reg is loaded
		wait ( (U00.u1.u13.u35.u341.z === 1'b0) &&
			(U00.clk === 1'b0) );
		wait ( (U00.u1.u13.u35.u341.z === 1'b1) &&
			(U00.clk === 1'b0) );
		wait ( (U00.u1.u13.u35.u341.z === 1'b0) &&
			(U00.clk === 1'b0) );
		release $csa; release $csb;
		release $wea; release $web;
		end
END

endif

 
if ($1 > 1) then

BEGIN

/* -------------------------------------------------------
The following code provides a means for the Forth program
to exercise the multipurpose pins of chips U00 and U01,
to force conflicts on the glue and interface pins of U00,
and to generate an invalid sync signal.
  The following table shows the action taken depending on
what is written to control register 0:
  pin selection (bits 19-16):
    0 - chip 1 glue 0
    1 - chip 1 glue 1
    2 - chip 1 glue 2
    3 - chip 1 glue 3
    4 - chip 1 glue 4
    5 - chip 1 glue 5
    6 - chip 1 mpa
    7 - chip 1 mpb
    8 - chip 1 interface data
    9 - chip 1 sync
 control (bits 21-20):
    0 - disable
    1 - force to 1
    2 - force to 0
    3 - force pattern (010), done
        only when cam clock is running!)

 ------------------------------------------------------- */


	reg [3:0]
		pin_sel;
	reg [1:0]
		pin_action;

	// delay from rising edge of clock before force
	//   becomes effective
	parameter force_delay = 5;

	// latch the bits written to control reg 0
	always @(posedge system.U1.U1.U1.u2.u1.u45.zn)
		begin
		@(posedge system.sb_clk);
		pin_sel = system.sb_d[19:16];
		pin_action = system.sb_d[21:20];
		case (pin_action)
			2'h0:
				begin
				@(posedge system.U00.U00.u1.clk)
				#(force_delay);
				release_pins;
				end
			2'h1:
				begin
				@(posedge system.U00.U00.u1.clk)
				#(force_delay);
				force_pin (1'b1);
				end
			2'h2:
				begin
				@(posedge system.U00.U00.u1.clk)
				#(force_delay);
				force_pin (1'b0);
				end
			2'h3:
				begin
				@(posedge system.U00.U00.u1.clk)
				#(force_delay);
				force_pin (1'b0);
				@(posedge system.U00.U00.u1.clk)
				#(force_delay);
				force_pin (1'b1);
				@(posedge system.U00.U00.u1.clk)
				#(force_delay);
				force_pin (1'b0);

				// don't wait for local clock to
				//   release pin
				@(posedge system.pb_clk)
				#(force_delay);
				release_pins;
				end
		endcase
		end

	initial
		release_pins;


	task	release_pins;
		begin
		release system.U00.U01.p12;	// glue 0
		release system.U00.U01.p11;	// glue 1
		release system.U00.U01.p10;	// glue 2
		release system.U00.U01.p9;	// glue 3
		release system.U00.U01.p8;	// glue 4
		release system.U00.U01.p7;	// glue 5
		release system.U00.U01.p6;	// multipurpose a
		release system.U00.U01.p5;	// multipurpose b
		release system.pb_dl [1];	// interface data
		release system.pb_sync;		// sync
		end
	endtask


	task	force_pin;
		input
			value;

		begin
		\$write (\$stime, "  Forcing pin ");
		case (pin_sel)
			4'h0: force system.U00.U01.p12 = value;	// glue 0
			4'h1: force system.U00.U01.p11 = value;	// glue 1
			4'h2: force system.U00.U01.p10 = value;	// glue 2
			4'h3: force system.U00.U01.p9 = value;	// glue 3
			4'h4: force system.U00.U01.p8 = value;	// glue 4
			4'h5: force system.U00.U01.p7 = value;	// glue 5
			4'h6: force system.U00.U01.p6 = value;	// multipurpose a
			4'h7: force system.U00.U01.p5 = value;	// multipurpose b
			4'h8: force system.pb_dl [1] = value;	// interface data
			4'h9: force system.pb_sync = value;	// sync
		endcase

		case (pin_sel)
			4'h0: \$write ("p12");
			4'h1: \$write ("p11");
			4'h2: \$write ("p10");
			4'h3: \$write ("p9");
			4'h4: \$write ("p8");
			4'h5: \$write ("p7");
			4'h6: \$write ("p6");
			4'h7: \$write ("p5");
			4'h8: \$write ("pb_dl [1]");
			4'h9: \$write ("pb_sync");
		endcase

		\$write (" to %b\n", value);

		end
	endtask

END

endif


BEGIN

endmodule

END

