HierarchyFilesModulesSignalsTasksFunctionsHelp

/******************************************************************************/ 
/*                                                                            */ 
/* 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.         */ 
/*                                                                            */ 
/******************************************************************************/ 
// @(#)afx_mon.v	1.15 1/5/94

/* This is the basic AFX monitor module
   which is used to monitor the AFX transactions
*/

//	updates:
//
//		1 dec 1992	
//		fixed checking addr/size for illegal transfers, display of
//		sized transfers, counting address transactions
//	2.0	8 dec 1992
//		change over to AFX rev 2
//	2.1	1 mar 1993
//		changes to match the latest spec (rev. 2.1);
//		timeout and latency checks, new signal names

module afx_mon;

// parameters & defines	/////////////////////////////////////////////////
parameter TRACE = 1;		// if set, will print transactions
parameter FIFOSIZE = 4;
parameter READ_LAT = 1;		// value to check for, read latency
				// should be set to 1 or 0
parameter [31:0]
		TIMEOUT	= 32'd2047,	// afx timeout value measured in gclks
		REPEAT	= 32'd2047;	// repeats of timeout error message

// this is the afx space for for Physical address <30:29>
parameter AFXPA =2'b01; 

parameter [1:0]
		WR_REPLY	= 2'b10,	// reply r/w bits
		RD_REPLY	= 2'b11;

// wires & registers		/////////////////////////////////////////

	// Substitute the correct module for master_blob
	wire		falcon_exists = 1'b1;		// hardwired to 1, this is the lazy way John Petry
	wire		mon_clk = `SSPARC_CORE.w_gclk;
	wire	[1:0]	p_reply = `SSPARC_CORE.pcic_p_reply;

//	wire	[1:0]	s_reply = `SS_SCOPE.w_s_reply;
	wire	[1:0]	s_reply = {`SSPARC_CORE.w_s_reply, `SS_SCOPE.mc_mwe_l};
	wire		write_l = `SS_SCOPE.mc_mwe_l;

//	wire		lo_addr = `SS_SCOPE.lo_addr;
	wire		lo_addr = `SSPARC_CORE.w_s_reply;

//	wire	[14:0]	ab = `SS_SCOPE.ab[15:1];
	wire	[14:0]	ab = {`SSPARC_CORE.w_ab_out, `SS_SCOPE.mc_memaddr};
	wire		aen = `SSPARC_CORE.w_aen;
	reg	[1:0]	mon_p_rply;
	reg	[1:0]	mon_s_rply;

	// Fake output enables until we hook them up
	//reg		ram_oe, cpu_oe, afx_oe;
	//reg		ram_oe;
	wire		ram_oe = Msystem.TheRam.ram_output;
	wire		cpu_oe = `SS_SCOPE.b_mem_oen;

`ifdef A24_STUB
//	wire		afx_oe = Msystem.fstub.afxs.db_en;
`else
//	wire		afx_oe = Msystem.fstub.afxs.read_oe_l;
`endif
	wire		afx_oe = 1'b0 ;
	
	// State
	reg		read_flag, write_flag;
	reg		read_pend;
	reg	[7:0]	write_count, addr_count;
	reg	[14:0]	ab_hi, ab_low;
	
	reg	[31:0]	save_addr;
	reg	[3:0]	save_mask;
	reg 	[7:0] 	disp_byte;		// used for displaying data
	reg 	[15:0] 	disp_hword;
	reg 	[31:0] 	disp_word;
	
	reg	[31:0]	timer;			// afx bus timeout counter
	reg		timer_en;		// timer enable

	// Decoded address, data, size
	wire	[28:3]	address = {ab_hi[0], ab_hi[14:1], ab_low[10:0]};
// temporarily change this to allow a view of PCI data via 
// the separate read and write paths. - JP
	wire	[63:0]	data = `SS_SCOPE.b_memdata;
	wire	[63:0]	read_data = `SSPARC_CORE.b_memdata_in;
	wire	[63:0]	write_data = `SS_SCOPE.w_b_memdata_out;
	wire	[3:0]	mask = ab_low[14:11];

// initial blocks	/////////////////////////////////////////////////

	// Initialize variables
	initial
	    begin
		// The following three should go away
		
		// Init states
		read_flag = 0;
		write_flag = 0;
		read_pend = 0;
		write_count = 0;
		addr_count = 0;
		timer = 0;
		timer_en = 0;
		ab_hi = 'hX;
		ab_low = 'hX;

		mon_p_rply = 0;
		mon_s_rply = 0;
		
		save_addr[31:29] = AFXPA;
		
	    end

// always blocks	/////////////////////////////////////////////////

	// Check for driver fights
	wire	fight1 = (ram_oe & cpu_oe);
	wire	fight2 = (ram_oe & afx_oe);
	wire	fight3 = (cpu_oe & afx_oe);
	wire	driver_fight = (fight1 | fight2 | fight3);
//	always @ (posedge driver_fight) begin
//	    $display("*** Error: afx_monitor: driver fight, ram_oe = %d, cpu_oe = %d, afx_oe = %d",
//				ram_oe, cpu_oe, afx_oe);
//	    Mclocks.error_count = Mclocks.error_count + 1;
//	    // AT THIS POINT, WE SHOULD YANK A FLAG THAT STOPS THE SIM
//	end

	// Here's the fun part, check for correct operation of the AFX bus

	// It all starts on the leading edge of the clock...
	always @ (posedge mon_clk) begin
	    //
	    // Check address stuff
	    if (aen == 1) begin
		// High address
		if (lo_addr == 1'b0) begin
		    ab_hi = ab;
		end
		// Low address, launch command
		else if ((lo_addr == 1'b1) &&
			(~falcon_exists || (address[28] == 1'b1))) begin
		    timer = 0;
		    timer_en = 1;
		    ab_low = ab;
		    // check for illegal mask code
		    if (mask == 4'b1111) begin
		    	$display("*** Error: afx_monitor: illegal mask code = 1111");
		    	Mclocks.error_count = Mclocks.error_count + 1;
	    	    	// YANK THE HALT SIM LINE
		    end
		    // check fifo counts
		    if (write_l == 1'b0) begin	// write cmd
			addr_count = addr_count + 1;
			if (addr_count > FIFOSIZE) begin
		    	    $display("*** Error: afx_monitor: too many write commands on address bus");
		    	    Mclocks.error_count = Mclocks.error_count + 1;
	    	    	    // YANK THE HALT SIM LINE
			end
		    end
		    else begin			// read cmd
			if (read_pend == 1) begin
			    $display("*** Error: afx_monitor: too many read commands on address bus");
		    	    Mclocks.error_count = Mclocks.error_count + 1;
	    	    	    // YANK THE HALT SIM LINE
			end
			else begin
			    read_pend = 1;	// set the flag until read
			end
		    end
		end
		// if not 0 or 1, then bad data on lo_addr!
		else if ((lo_addr !== 1'b1) && (lo_addr !== 1'b0)) begin
		    $display("*** Error: afx_monitor: bad data on lo_addr = %b", lo_addr);
		end
	    end

	    // Check for command
	    // Write
	    if ((s_reply == WR_REPLY) &&
			(~falcon_exists || (address[28] == 1'b1))) begin
		write_flag = 1;
		write_count = write_count + 1;
		
		// Check for buffer overflow
		if (write_count > FIFOSIZE) begin
		    $display("*** Error: afx_monitor: too many writes");
		    Mclocks.error_count = Mclocks.error_count + 1;
	    	    // YANK THE HALT SIM LINE
		end

		if (read_flag == 1) begin
		    $display("*** Error: afx_monitor: write during read");
		    Mclocks.error_count = Mclocks.error_count + 1;
	    	    // YANK THE HALT SIM LINE
		end
	    end
	    // Read
	    else if ((s_reply == RD_REPLY) &&
			(~falcon_exists || (address[28] == 1'b1))) begin
	        read_flag = 1;
	    end

	    // Check for replies
	    // Write
	    if (p_reply == WR_REPLY) begin
		// Check for buffer underflow
		if (write_count == 0) begin
		    $display("*** Error: afx_monitor: too many write replies");
		    Mclocks.error_count = Mclocks.error_count + 1;
	    	    // YANK THE HALT SIM LINE
		end
		write_count = write_count - 1;
		if (write_count == 0)
			timer_en = 0;
		addr_count = addr_count - 1;
	    end
	    // Read
	    else if (p_reply == RD_REPLY) begin
		if (read_flag == 0) begin
		    $display("*** Error: afx_monitor: bogus read reply");
		    Mclocks.error_count = Mclocks.error_count + 1;
	    	    // YANK THE HALT SIM LINE
		end
		if (write_count != 0) begin
		    $display("*** Error: afx_monitor: write buf not flushed");
		    Mclocks.error_count = Mclocks.error_count + 1;
	    	    // YANK THE HALT SIM LINE
		end
		if (TRACE == 1) begin	// if set, write out transaction
		    save_addr[28:3] = address[28:3];
		    case (mask)
		        // byte reads /////////////////////////////////////////
		    	4'b0000: begin
			    save_addr[2:0] = 3'b000;
			    disp_byte = read_data[63:56];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_byte, save_addr, mask);
			end
			4'b0001: begin
			    save_addr[2:0] = 3'b001;
			    disp_byte = read_data[55:48];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_byte, save_addr, mask);
			end
			4'b0010: begin
			    save_addr[2:0] = 3'b010;
			    disp_byte = read_data[47:40];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_byte, save_addr, mask);
			end
			4'b0011: begin
			    save_addr[2:0] = 3'b011;
			    disp_byte = read_data[39:32];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_byte, save_addr, mask);
			end
			4'b0100: begin
			    save_addr[2:0] = 3'b100;
			    disp_byte = read_data[31:24];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_byte, save_addr, mask);
			end
			4'b0101: begin
			    save_addr[2:0] = 3'b101;
			    disp_byte = read_data[23:16];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_byte, save_addr, mask);
			end
			4'b0110: begin
			    save_addr[2:0] = 3'b110;
			    disp_byte = read_data[15:8];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_byte, save_addr, mask);
			end
			4'b0111: begin
			    save_addr[2:0] = 3'b111;
			    disp_byte = read_data[7:0];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_byte, save_addr, mask);
			end
			// halfword reads /////////////////////////////////////
		    	4'b1000: begin
			    save_addr[2:0] = 3'b000;
			    disp_hword = read_data[63:48];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_hword, save_addr, mask);
			end
			4'b1010: begin
			    save_addr[2:0] = 3'b010;
			    disp_hword = read_data[47:32];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_hword, save_addr, mask);
			end
			4'b1100: begin
			    save_addr[2:0] = 3'b100;
			    disp_hword = read_data[31:16];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_hword, save_addr, mask);
			end
			4'b1110: begin
			    save_addr[2:0] = 3'b110;
			    disp_hword = read_data[15:0];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_hword, save_addr, mask);
			end
			// word reads /////////////////////////////////////////
		    	4'b1001: begin
			    save_addr[2:0] = 3'b000;
			    disp_word = read_data[63:32];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_word, save_addr, mask);
			end
			4'b1101: begin
			    save_addr[2:0] = 3'b100;
			    disp_word = read_data[31:0];
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     disp_word, save_addr, mask);
			end
			// doubleword reads ///////////////////////////////////
		    	4'b1011: begin
			    save_addr[2:0] = 3'b000;
			    $display("\n\t%s: RD (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				     read_data, save_addr, mask);
			end
		    endcase	// mask
		end		// if (TRACE == 1)
		read_flag = 0;
		read_pend = 0;
		timer_en = 0;
	    end			// if (p_reply == RD_REPLY)
	    
	    // check for read latency violation
/*
	    if ((s_reply == RD_REPLY) && (write_count > READ_LAT)) begin
	    	$display("*** Error: afx_monitor: read latency violation, write fifo = %d deep.", 
			write_count);
		Mclocks.error_count = Mclocks.error_count + 1;
		// YANK THE HALT SIM LINE
	    end			// 
*/
		
	end			// always @ (posedge mon_clk)

	// Display write trace
	always @ (posedge write_flag) begin
	    // save info from 1st cycle of write
	    save_addr[28:3] = address[28:3];
	    save_mask = mask;
	    // Wait until data is asserted
	    @(posedge mon_clk)
	    if (TRACE == 1) begin
		case (mask)
		    // byte writes ////////////////////////////////////////////
		    4'b0000: begin
			save_addr[2:0] = 3'b000;
			disp_byte = write_data[63:56];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_byte, save_addr, save_mask);
		    end
		    4'b0001: begin
			save_addr[2:0] = 3'b001;
			disp_byte = write_data[55:48];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_byte, save_addr, save_mask);
		    end
		    4'b0010: begin
			save_addr[2:0] = 3'b010;
			disp_byte = write_data[47:40];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_byte, save_addr, save_mask);
		    end
		    4'b0011: begin
			save_addr[2:0] = 3'b011;
			disp_byte = write_data[39:32];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_byte, save_addr, save_mask);
		    end
		    4'b0100: begin
			save_addr[2:0] = 3'b100;
			disp_byte = write_data[31:24];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_byte, save_addr, save_mask);
		    end
		    4'b0101: begin
			save_addr[2:0] = 3'b101;
			disp_byte = write_data[23:16];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_byte, save_addr, save_mask);
		    end
		    4'b0110: begin
			save_addr[2:0] = 3'b110;
			disp_byte = write_data[15:8];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_byte, save_addr, save_mask);
		    end
		    4'b0111: begin
			save_addr[2:0] = 3'b111;
			disp_byte = write_data[7:0];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_byte, save_addr, save_mask);
		    end
		    // halfword writes ////////////////////////////////////////
		    4'b1000: begin
			save_addr[2:0] = 3'b000;
			disp_hword = write_data[63:48];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_hword, save_addr, save_mask);
		    end
		    4'b1010: begin
			save_addr[2:0] = 3'b010;
			disp_hword = write_data[47:32];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_hword, save_addr, save_mask);
		    end
		    4'b1100: begin
			save_addr[2:0] = 3'b100;
			disp_hword = write_data[31:16];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_hword, save_addr, save_mask);
		    end
		    4'b1110: begin
			save_addr[2:0] = 3'b110;
			disp_hword = write_data[15:0];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_hword, save_addr, save_mask);
		    end
		    // word writes ////////////////////////////////////////////
		    4'b1001: begin
			save_addr[2:0] = 3'b000;
			disp_word = write_data[63:32];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_word, save_addr, save_mask);
		    end
		    4'b1101: begin
			save_addr[2:0] = 3'b100;
			disp_word = write_data[31:0];
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 disp_word, save_addr, save_mask);
		    end
		    // doubleword writes //////////////////////////////////////
		    4'b1011: begin
			save_addr[2:0] = 3'b000;
			    $display("\n\t%s: WR (%x)@(%x) mask(%x)",
					save_addr[28] ? "PCI" : "AFX",
				 write_data, save_addr, save_mask);
		    end
		endcase
	    end		// if (TRACE == 1)
	    write_flag = 0;
	
	end		// always @ (posedge write_flag)
	
	always @(posedge mon_clk) begin
	#1  if (timer_en == 1) begin
		timer = timer + 1;
		// this actually counts in the same cycle as timer_en
		// gets set, so need to wait until count is greater than...
		if (timer >= TIMEOUT) begin
		    // only report timeout error every REPEAT clocks over
		    if (((timer - TIMEOUT) % REPEAT) == 0) begin
		    	$display("*** Warning: afx_monitor: access timed out, timer = %d gclk's.", timer);
		   	Mclocks.warning_count = Mclocks.warning_count + 1;
			reset_flags;
	    	    	// YANK THE HALT SIM LINE
		    end
		end	
	    end		
	    else timer = 0;
	end			// always @(posedge mon_clk)


// tasks        /////////////////////////////////////////////////////////
 
// resets flags, variables, pointers, etc. when an error occurs
task reset_flags;
begin
        read_flag = 0;
        write_flag = 0;
        read_pend = 0;
        write_count = 0;
        addr_count = 0;
        ab_hi = 'hX;
        ab_low = 'hX;
         
end
endtask         // reset_flags


endmodule		// module afx_mon

HierarchyFilesModulesSignalsTasksFunctionsHelp

This page: Created:Thu Aug 19 11:59:52 1999
From: ../../../sparc_v8/system/rtl/afx_mon.v

Verilog converted to html by v2html 5.0 (written by Costas Calamvokis).Help