/******************************************************************************/
/* */
/* Copyright (c) 1999 Sun Microsystems, Inc. All rights reserved. */
/* */
/* The contents of this file are subject to the current version of the Sun */
/* Community Source License, microSPARCII ("the License"). You may not use */
/* this file except in compliance with the License. You may obtain a copy */
/* of the License by searching for "Sun Community Source License" on the */
/* World Wide Web at http://www.sun.com. See the License for the rights, */
/* obligations, and limitations governing use of the contents of this file. */
/* */
/* Sun Microsystems, Inc. has intellectual property rights relating to the */
/* technology embodied in these files. In particular, and without limitation, */
/* these intellectual property rights may include one or more U.S. patents, */
/* foreign patents, or pending applications. */
/* */
/* Sun, Sun Microsystems, the Sun logo, all Sun-based trademarks and logos, */
/* Solaris, Java and all Java-based trademarks and logos are trademarks or */
/* registered trademarks of Sun Microsystems, Inc. in the United States and */
/* other countries. microSPARC is a trademark or registered trademark of */
/* SPARC International, Inc. All SPARC trademarks are used under license and */
/* are trademarks or registered trademarks of SPARC International, Inc. in */
/* the United States and other countries. Products bearing SPARC trademarks */
/* are based upon an architecture developed by Sun Microsystems, Inc. */
/* */
/******************************************************************************/
/***************************************************************************
****************************************************************************
***
*** Program File: @(#)misc_tasks.v
***
****************************************************************************
****************************************************************************/
// Code for testing clock and scan logic
module misc_tasks
;
// Use this in calls to the tap_op tasks
reg [31:0] tdo_bits
;
// Reset JTAG, clk_cntl, and internal logic
task jtag_clk_rst ;
input lofreq_clk_rst ;
fork
// Run clocks forever - we'll turn them off below.
Mclocks.cycles('h7fffffff,20,1,2,0) ;
begin
do_jtag_clk_rst(lofreq_clk_rst) ;
// The next ext_clk will be gated through. input_reset_l is
// still asserted. Turn off Mclocks.clock .
Mclocks.cycles.n = 0 ;
end
join
endtask
// This does all the work, but doesn't $stop. It can be invoked from
// other tasks.
task do_jtag_clk_rst ;
input lofreq_clk_rst ;
begin
`BOARD.input_reset_l = 0 ;
`BOARD.jtag_trst_l = 0 ;
// Wait for jtag state machine to reset, then de-assert trst
@(posedge `BOARD.jtag_ck) ;
@(posedge `BOARD.jtag_ck) ;
#1 `BOARD.jtag_trst_l = 1 ;
fork
// shift in '11' into the MSBs of the JTAG instruction
// register, so that it contains '110000', the
// clk_rst opcode. Then continue on to
// Test-Logic-Reset. clk_cntl will reset several times
// during this; the last reset is the input_clock posedge
// which comes just before the negedge of jtag_ck in the
// Update-DR cycle. clk_rst_l will be asserted for
// four jtag_ck cycles.
do_tap_op(4'hf, 4'hf, 11, 11'b11111000110, 11'b11111111111,
11'b11111111111, 11'bx, tdo_bits) ;
// If we want this to work at 'high speed', we have to disable
// the ext_clk input around transitions of the clk_rst_l
// signal, because the timing of this signal has not
// been analyzed. Wait for clk_rst to be asserted,
// wait a couple of clock cycles, then enable ext_clk
// for one clock cycle (this give2 two ext_clk1
// pulses, since ext_clk1 is twice the frequency of
// Mclocks.clock).
if (~lofreq_clk_rst) begin
@(posedge Mclocks.clock) #1 `BOARD.dsbl_ext_clk = 1 ;
@(negedge `rl_clk_cntl.clk_rst_l) ;
@(posedge Mclocks.clock) #1 ;
@(posedge Mclocks.clock) #1 ;
@(posedge Mclocks.clock) #1 `BOARD.dsbl_ext_clk = 0 ;
@(posedge Mclocks.clock) #1 `BOARD.dsbl_ext_clk = 1 ;
end
join
// Clock controller has been reset - we're in the second half of
// the first phase. Turn clocks on if we turned them off.
if (~lofreq_clk_rst) begin
@(posedge `BOARD.jtag_ck) #1 ; // Sync up with jtag_ck
// Start ext_clk so that the first 0->1 on free_clk
// coincides with a 0->1 on Mclocks.clock .
@(negedge Mclocks.clock) #1 `BOARD.dsbl_ext_clk = 0 ;
end
// The next ext_clk will be gated through. input_reset_l is
// still asserted.
end
endtask
`ifdef CLK_MISC_GATE_LEVEL
// .Lv names - .sv has escaped-ID instance names
wire [3:0] jtag_state = ~{
`rl_jtag_cntl.tapsm_fsm_Mflipflop_ar_3_3_dff.Q,
`rl_jtag_cntl.tapsm_fsm_Mflipflop_ar_3_2_dff.Q,
`rl_jtag_cntl.tapsm_fsm_Mflipflop_ar_3_1_dff.Q,
`rl_jtag_cntl.tapsm_fsm_Mflipflop_ar_3_0_dff.Q
} ;
`else
wire [3:0] jtag_state
= `rl_jtag_cntl.tapsm.tapc_state ;
`endif
// These keep the same names in .Lv . Escaped IDs in .sv, though . . .
wire [5:0] jtag_instr
= `rl_jtag_cntl.inst ;
wire [2:0] free_phase
= `rl_clk_cntl.free_phase ;
// When set, print a comment on every jtag state change
reg jtag_state_comments
; initial jtag_state_comments
= 0 ;
always @(jtag_state) if (jtag_state_comments)
$fdisplay(Mccdisp.allvec_tto_mcd,
"---------- %0d: jtag_state<-%h, instr=%b ----------",
Mclocks.cycle_count_s, jtag_state, jtag_instr) ;
task tap_op ;
input [3:0] from_state ;
input [3:0] to_state ;
input [31:0] n ;
input [31:0] tms_bits ;
input [31:0] tdi_bits ;
input [31:0] td_mask ; // for each '1', scan in the corresponding bit
input [31:0] scanout ;
output [31:0] tdo_bits ;
fork
// Run clocks forever - we'll turn them off below.
Mclocks.cycles('h7fffffff,20,1,2,0) ;
// While the clock generator is running, run the jtag state
// machine. Turn off clocks when we're done.
begin
// Do the tap sequence
do_tap_op(from_state, to_state, n, tms_bits, tdi_bits,
td_mask, scanout, tdo_bits) ;
// Now turn off clocks - since jtag_ck period is at least
// twice the cycletime, clocks are guaranteed to
// stop before the next jtag_ck posedge.
Mclocks.cycles.n = 0 ;
end
join
endtask
// Issue up to 32 clocks worth of TAP operation
task do_tap_op ;
input [3:0] from_state ;
input [3:0] to_state ;
input [31:0] n ;
input [31:0] tms_bits ;
input [31:0] tdi_bits ;
input [31:0] td_mask ; // for each '1', scan in the corresponding bit
input [31:0] scanout ;
output [31:0] tdo_bits ;
reg [31:0] tdo_bits ;
integer i ;
if (n>32) Mclocks.print_error("Too many bits to shift") ;
else begin
$fdisplay(Mccdisp.allvec_tto_mcd,
"---------- %0d: %0d-bit tap_op %h->%h ----------",
Mclocks.cycle_count_s, n, from_state, to_state);
if (((^from_state)!==1'bx) && (jtag_state!==from_state)) begin
$display("\n*** %0d: Expected jtag state %b, found %b, at start of %0d-bit tap_op", Mclocks.cycle_count_s, from_state, jtag_state, n) ;
Mclocks.error_count = Mclocks.error_count + 1 ;
end
tdo_bits = 0 ;
for (i=0 ; i<n ; i=i+1) begin
// Allow changes to propagate to jtag_tdo (it's on a
// negative-edge-triggered FF).
if (`BOARD.jtag_ck) @(negedge `BOARD.jtag_ck) #2 ;
`BOARD.jtag_ms = tms_bits[i] ;
`BOARD.jtag_tdi =
td_mask[i] ? tdi_bits[i] : `BOARD.jtag_tdo ;
@(posedge `BOARD.jtag_ck) begin
tdo_bits[i] = `BOARD.jtag_tdo ;
end
#2 ;
end
// We are now #2 after the last posedge jtag_ck, so
// all state machine outputs have reached their
// ending states.
// Check for proper ending state
if (((^to_state)!==1'bx) && (jtag_state!==to_state)) begin
$display("\n*** %0d: Expected jtag state %b, found %b, at end of %0d-bit tap_op", Mclocks.cycle_count_s, to_state, jtag_state, n) ;
Mclocks.error_count = Mclocks.error_count + 1 ;
end
// Check for expected scanout value - all this XORing is to
// ignore match on 'x' bits in the scanout parameter.
scanout = scanout & ((1<<n)-1) ; // Clear unused MSBs
if ( (tdo_bits^(scanout^scanout))!==scanout) begin
$write("\n**** ") ;
Mclocks.print_bits(n, tdo_bits) ;
$write(" scanned out (cycle %0d)\n *** ",
Mclocks.cycle_count_s) ;
Mclocks.print_bits(n, scanout) ;
$display(" expected\n") ;
Mclocks.error_count = Mclocks.error_count + 1 ;
end
end
endtask
// Jtag clock
reg [31:0] tck_hi
, tck_lo
;
reg [31:0] tck_period
;
// Use the $GetEnv pli option to pass the variable for tck_period
initial begin
$GetEnv("tck_period", tck_period);
tck_hi = (tck_period>>1);
tck_lo = (tck_period-(tck_period>>1)) ;
end
initial begin
`BOARD.jtag_ck = 0 ;
// Sync up with free clocks at startup . This is useful only when
// the jtag_ck period is a multiple of the Mclocks.clock period.
#(`TCK_START) `BOARD.jtag_ck = 1 ;
forever begin
#(tck_hi) `BOARD.jtag_ck = 0 ;
#(tck_lo) `BOARD.jtag_ck = 1 ;
end
end
task tap_clk ;
input [31:0] n ;
fork
// Clock forever (we'll terminate the loop when we've seen
// enough tclk's.
Mclocks.cycles('h7fffffff,20,1,2,0) ;
begin
// Count down tclk pulses, then terminate the clock loop
repeat(n) @(posedge `BOARD.jtag_ck) ;
Mclocks.cycles.n = 0 ;
end
join
endtask
// Print a character after the Mclocks.cycle '.' to indicate special cycles
wire #1 ref_clk_dly
= `rl_clk_cntl.ss_clock_unbuf ;
wire #1 free_clk_dly
= `rl_clk_cntl.free_clock ;
reg [7:0] clk_type
, last_clk_type
; initial clk_type
= 0 ;
always @(posedge Mclocks.clock)
// Print nothing in first half of free cycle
if (free_clk_dly) last_clk_type = " " ;
else begin
clk_type =
// Unknown state
((`rl_clk_cntl.stopped
^ ref_clk_dly
^ free_clk_dly
^`rl_jtag_cntl.sys_sen
^`misc.reset_nonwd)===1'bx) ? "X" : (
// Clocks stopped
(ref_clk_dly & `rl_clk_cntl.stopped) ? "_" : (
// Clock pause (rcc_clk but no ss_clock)
(ref_clk_dly & ~`rl_clk_cntl.stopped) ? "p" : (
// Scan shift
`rl_jtag_cntl.sys_sen ? "s" : (
// Reset
`misc.reset_nonwd ? "r" : (
0 ))))) ;
// Mclocks.cycle has already printed the '.', etc, for the cycle
// which ends at this posedge; now print the character (if any)
// which describes the cycle we just finished. Also, if this was
// the first normal cycle after some abnormal ones, print a '+'
// (this makes it easier to see a single-step, for example).
if (clk_type) $write("%c%0s", clk_type, Mclocks.vsh_nl) ;
else if (last_clk_type) $write("+%0s", Mclocks.vsh_nl) ;
// For next time . . .
last_clk_type = clk_type ;
end
// Serial data shift to or from the given buffer
// On entry, you must be Exit1-DR state
// On exit, we are in Run-Test-Idle state
`ifdef VCS
`else
task data_shift ;
input [31:0] n ; // Total number of bits to scan
input [31:0] pause_interval ; // Number of bits to scan between pauses
input write ; // 1->write_chain, 0->read_chain
inout [8191:0] buffer ;
reg [31:0] scanin_bits, scanin_mask, maxbits ;
reg [8191:0] scanout_bits ;
reg [4:0] dummy5 ;
integer lsb, next_lsb, this_n ;
fork
// Run clocks forever - we'll turn them off below
Mclocks.cycles('h7fffffff,20,1,2,0) ;
// While clocks are running, do the scan shift. Turn off clocks
// when we're done.
begin
// If no pause is specified, shift 32 bits at a time
maxbits = pause_interval ? pause_interval : 32 ;
if (write) begin
// Scan in every bit
scanin_mask = -1 ;
end
else begin
// Recirculate the scanout data for read_chain
scanin_mask = 0 ;
scanin_bits = 'bx ;
buffer = 0 ;
end
if (pause_interval==0) begin
// No pause - transition to Shift-DR before entering the loop.
do_tap_op(4'h1, 4'h2, 5, 5'b01000, 5'bx, 5'bx, 5'bx, dummy5) ;
end
lsb = 0 ;
while (lsb<n) begin
next_lsb = lsb + maxbits ;
if (next_lsb>n) next_lsb = n ;
this_n = next_lsb - lsb ;
$display("---- %0d: shifting bits %0d:%0d ----",
Mclocks.cycle_count_s, (next_lsb-1), lsb) ;
if (write) scanin_bits = buffer >> lsb ;
if (pause_interval) begin
// Go to Shift-DR (5 clocks), then do the data shift (this_n
// clocks), ending up in Exit1-DR.
do_tap_op(4'h1, 4'h1,
(this_n+5),
{(1<<(this_n-1)), 5'b01000},
{scanin_bits,5'bx}, {scanin_mask,5'bx},
32'bx, {scanout_bits,dummy5}) ;
end
else begin
// No pause - just do the data shift.
// Stay in Shift-DR unless this is the last shift - then
// go to Exit1-DR.
do_tap_op(4'h2, ((next_lsb==n) ? 4'h1 : 4'h2),
this_n,
((next_lsb==n) ? (1<<(this_n-1)) : 0),
scanin_bits, scanin_mask,
32'bx, scanout_bits) ;
end
if (~write) buffer = buffer | (scanout_bits<<lsb) ;
lsb = next_lsb ;
end
// In case we monitor these in a vcd file, signal that we're done
// with the data shift.
lsb = 'bx ;
next_lsb = 'bx ;
// Stop in Run-Test-Idle
do_tap_op(4'h1, 4'hc, 8, 8'b00011000,
'bx, 'bx, 'bx, scanout_bits) ;
// Turn off vsh clock generator
Mclocks.cycles.n = 0 ;
end
join
endtask
`endif
endmodule
This page: |
Created: | Thu Aug 19 12:02:12 1999 |
| From: |
../../../sparc_v8/env/rtl/misc_tasks.v
|