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.         */ 
/*                                                                            */ 
/******************************************************************************/ 
/***************************************************************************
****************************************************************************
***
***  Program File:  @(#)afx_slave_sm.v
***
***
***  Description:
***    Implements the afx slave / pci master state machine.
*** 
****************************************************************************
****************************************************************************/

[Up: f_afx_slave afx_slave_sm]
module afx_slave_sm(
	reset,			// reset
	fast_gclk,		// gclk early in clock tree for s_reply
	clock,			// afx g clock
	pci_clk,		// pci clock
	pci_clk_sync,		// pci clock for sync cells		
	pci_clk_sync_,		// pci clock for sync cells		
	gclk_sync,		// gclk for sync cells
	gclk_sync_,		// gclk for sync cells

	cmd_out,		// afx fifo command
	next_cmd_out,		// afx fifo next command
	addr_out,		// afx fifo address
	next_addr_out,		// afx fifo next address
	bm_out_lo_l,		// afx fifo bm out for bm, address 2:0, wc
	bm_out_hi_l,		// afx fifo bm out for bm, address 2:0, wc
	cmd_fifo_full_count,	// afx command fifo full count
	data_fifo_full_count,	// afx data fifo full count
	burst_enable,		// burst enable from configuration
	prefetch_enable,	// enable memory read prefetch

	config_add_pci,		// configuration address

	read_cmd_fifo,		// read the afx command fifo
	read_addr_fifo,		// read the afx address fifo
	read_bm_fifo,		// read the afx byte mark fifo
	read_data_fifo,		// read the afx data fifo

	afx_slave_idle,		// output to idle generator which is synced to gclk
	pci_req,		// start the pci core, must be synched to pci
	pci_complete,		// pci core complete must be synched back
				// to clock
	mas_start_dma,		// handshake from core to indicate that the
				// request can be dropped.
	pci_error,		// pci core error, must be synched back 
				// to clock
	pci_perror,		// pci core parity error, must be synched back 
				// to clock
	pci_async_perror,	// pci core parity error, must be synched back 
				// to clock
	pci_address,		// pci core starting address latched at pci_req
	pci_wcount,		// pci word count latched at pci_req
	pci_command,		// pci command

	pci_last,		// last xfer flag to pci core data fifo
	pci_mast_fifo_write_lo,	// write into pci master fifo lo word
	pci_mast_fifo_write_hi,	// write into pci master fifo hi word
	pci_mast_xmit_fifo_flush,// flush pci core master xmit fifo (ERRORS)
	pci_mast_rcv_fifo_flush,// flush pci core master fifo (ERRORS
				// and NO prefetch cases)
	pci_mast_rcv_fifo_empty_lo, // pci_receive fifo empty, gclk
	pci_mast_rcv_fifo_empty_hi, // pci_receive fifo empty, gclk
	pci_mast_rcv_fifo_read_lo,// read mas rcv lo word
	pci_mast_rcv_fifo_read_hi,// read mas rcv lo word
	
	load_afx_read_data_lo,     //
	load_afx_read_data_hi,     //
        select_config_add,      // selects config address for
                                // afx reads
	select_error,		// select all f's for read data on error
	load_config_add,	// load the configuration address
	select_falcon_data,	// selects falcon config_data
	pci_config_we,		// write configuration data

// add to support pci configuration writes
	pci_config_access_busy,
	host_config_access_busy,
	config_write,

	afx_slave_preply, 	// afx slave generated p reply
	afx_mast_error_address, // error address for configuration
	afx_mast_error_cmd, 	// error address for configuration
	afx_mast_error		// load error

);

// AFX slave state machine and interface to PCI core (master).
// This module controls the AFX slave fifos, and PCI core master
// fifos as well as the command / address / count interface
// to the PCI master.
// All transactions except for memory writes are a maximum of
// 1 doubleword, (could be less depending on byte marks)
// memory writes are "bursted" to a maximum of 4 double words
// if fewer than 4 double words are available, then the "last" 
// flag is sent with the last double word of data.

input 		reset;
input		fast_gclk;
input		clock;
input		pci_clk;
input		pci_clk_sync;
input		pci_clk_sync_;
input		gclk_sync;
input		gclk_sync_;

input	[3:0]	cmd_out;
input	[3:0]	next_cmd_out;
input	[28:0]	addr_out;
input	[28:0]	next_addr_out;
input	[3:0]	bm_out_lo_l;
input	[3:0]	bm_out_hi_l;
input	[2:0]	cmd_fifo_full_count;
input	[2:0]	data_fifo_full_count;
input		burst_enable;
input		prefetch_enable;

input	[31:0]	config_add_pci;

output		read_cmd_fifo;
output		read_addr_fifo;
output		read_bm_fifo;
output		read_data_fifo;

output		afx_slave_idle;
wire		afx_slave_idle;
output		pci_req;
input		pci_complete;
input		mas_start_dma;
input		pci_error;
input		pci_perror;
input		pci_async_perror;  // this error occurs after a transaction
				   // is complete and must be handled
				   //uniquely
output	[31:0]	pci_address;
output  [7:0]	pci_wcount;
output	[3:0]	pci_command;
output		pci_last;
output		pci_mast_fifo_write_lo;
output		pci_mast_fifo_write_hi;
output		pci_mast_xmit_fifo_flush;
output		pci_mast_rcv_fifo_flush;
output		pci_mast_rcv_fifo_read_lo;// read pci master receive fifo lo wd
output		pci_mast_rcv_fifo_read_hi;// read pci master receive fifo hi wd
input		pci_mast_rcv_fifo_empty_lo;
input		pci_mast_rcv_fifo_empty_hi;



output  	load_afx_read_data_lo; 
output  	load_afx_read_data_hi; 
output          select_config_add;
output          select_error;
output          load_config_add;

wire	[28:0]	addr_out_inc1 = addr_out + 1'b1;

wire		single_word;
wire		any_lo_bm;
wire		any_hi_bm;

wire		read_ready;
wire		pci_mast_rcv_fifo_read_lo;// read pci master receive fifo lo wd
wire		pci_mast_rcv_fifo_read_hi;// read pci master receive fifo hi wd

wire		load_config_add;

wire  		load_afx_read_data; 
wire  		load_afx_read_data_lo; 
wire  		load_afx_read_data_hi; 
wire            select_config_add;
wire		mas_start_dma_sync;

wire	[28:0]	last_address;
reg		last_cmd_3;
wire	[2:0]	last_cmd_reg;

wire	[31:0]	pci_address;
wire	[7:0]	pci_wcount;
wire	[3:0]	pci_command;

reg		pci_busy_reg;
reg		slave_idle;
reg		sm_idle;
reg		sm_config_add;
reg		sm_config_data;
reg		sm_config_data_rd;
reg		sm_io;
reg		sm_io_rd;
reg		sm_special_cycle;
reg		sm_mem_rd;
reg		sm_mem_rd1;
reg		sm_mem_rd4_1;
reg		sm_mem_rd4_2;
reg		sm_mem_pf_rd;
reg		sm_mem_wr;
reg		sm_mem_wr_wait2;
reg		sm_mem_wr_wait3;
reg		sm_mem_wr_wait4;
reg		sm_mem_wr_send1;
reg		sm_mem_wr_send2;
reg		sm_mem_wr_send3;
reg		sm_error;
reg		sm_falcon;
reg		sm_falcon1;

reg 		pci_start_reg;
wire		pci_start_reg_in;

reg		read_wait_pci;
wire		read_wait_pci_in;

reg		pci_complete_hold;
reg		pci_complete_d1;  // pci complete delayed by 1 pci_clk
wire		pci_complete_reg;
wire		sm_idle_in;
wire		sm_config_add_in;
wire		sm_config_data_in;
wire		sm_config_data_rd_in;
wire		sm_io_in;
wire		sm_io_rd_in;
wire		sm_special_cycle_in;
wire		sm_mem_rd_in;
wire		sm_mem_rd1_in;
wire		sm_mem_rd4_1_in;
wire		sm_mem_rd4_2_in;
wire		sm_mem_pf_rd_in;
wire		sm_mem_wr_in;
wire		sm_mem_wr_wait2_in;
wire		sm_mem_wr_wait3_in;
wire		sm_mem_wr_wait4_in;
wire		sm_mem_wr_send1_in;
wire		sm_mem_wr_send2_in;
wire		sm_mem_wr_send3_in;
wire		sm_error_in;
wire		sm_falcon_in;
wire		sm_falcon1_in;

wire 		pci_start;		// start pci, must convert to pci clock
//wire 		cmd_start;		// start command
wire 		pci_last;		// last data xfer, flows with data
wire		read_afx_fifo;		// read the afx fifos
wire		pci_mast_fifo_write;	// write into pci fifo
wire		pci_mast_fifo_write_lo;	// write into pci fifo
wire		pci_mast_fifo_write_hi;	// write into pci fifo
wire		pci_mast_xmit_fifo_flush_in;// flush remaining pci fifo data (ERR)
reg		pci_mast_xmit_fifo_flush;// flush remaining pci fifo data (ERR)
wire		pci_mast_rcv_fifo_flush_in;// flush remaining pci data in (ERR)
reg		pci_mast_rcv_fifo_flush;// flush "registered"
wire		pci_read_mas_rcv_fifo;	// read pci master receive fifo


wire		pci_complete_sync;	// pci_complete through synchronizer
wire		pci_error_sync;		// pci_error through synchronizer
wire		pci_perror_sync;	// pci_perror through synchronizer
wire		pci_async_perror_sync;	// pci_perror through synchronizer
reg		pci_error_reg;		// at next rising pci_clk
reg		pci_perror_reg;		// parity error
reg		pci_async_perror_reg;		// parity error

wire 	pci_complete_error = pci_complete_sync & 
		(pci_error_sync | pci_perror_sync);
wire 	pci_complete_no_error = pci_complete_sync & 
		~(pci_error_sync | pci_perror_sync);

wire	pci_async_err_detect = pci_async_perror_sync & ~ pci_async_perror_reg;

wire	[2:0]	fifo_full_count = cmd_out[0] ? data_fifo_full_count : cmd_fifo_full_count;

wire mem_wr_cmd_decode = (cmd_out == 4'h7);
wire mem_rd_cmd_decode = (cmd_out == 4'h6);

// interrupt acknowledge cycles are handled as io reads.  Address bus doesn't
// matter during intack cycles.
wire io_cmd_decode = (cmd_out == 4'h2) | (cmd_out == 4'h3) | (cmd_out == 4'h0);
wire io_rd_cmd_decode = (cmd_out == 4'h2) | (cmd_out == 4'h0);

wire config_add_cmd_decode = (cmd_out == 4'h8) | (cmd_out == 4'h9);

// Don't start config access if config_address reg decodes
// to special cycle
wire config_data_cmd_decode = (cmd_out == 4'ha) | (cmd_out == 4'hb);

wire config_data_rd_cmd_decode = (cmd_out == 4'ha);

// special cycle via address decode or config_address reg decode
wire special_cycle_cmd_decode = (cmd_out == 4'h1);

wire falcon_reg_cmd_decode = (cmd_out == 4'h4) | (cmd_out == 4'h5);

wire burst_on = (cmd_out == 4'h7) & (next_cmd_out == 4'h7) & 
	(fifo_full_count >= 3'h2) & burst_enable & ~single_word;

wire address_cmp = (next_addr_out == addr_out_inc1 );

wire burst = burst_on & address_cmp;

assign read_ready = single_word & (any_lo_bm & ~pci_mast_rcv_fifo_empty_lo |
	any_hi_bm & ~pci_mast_rcv_fifo_empty_hi) | ~single_word & 
	~pci_mast_rcv_fifo_empty_lo & ~pci_mast_rcv_fifo_empty_hi;

assign any_lo_bm = |(~bm_out_lo_l);
assign any_hi_bm = |(~bm_out_hi_l);

output 		select_falcon_data;
output		pci_config_we;

input		pci_config_access_busy;
output		host_config_access_busy;
wire		host_config_access_busy;
input		config_write;

output	[1:0]	afx_slave_preply;			
reg	[1:0]	afx_slave_preply;
wire	[1:0]	afx_slave_preply_in;

output 	[31:0]	afx_mast_error_address;
wire 	[31:0]	afx_mast_error_address;
output	[3:0]	afx_mast_error_cmd;
wire	[3:0]	afx_mast_error_cmd;
output		afx_mast_error;
wire		afx_mast_error;


// io addresses must have starting byte number, others must have
// 1:0 set to 00 (linear address) bit 2 should have appropriate word

wire [2:0]  addr_lsbs = io_cmd_decode ? decode8to3({bm_out_hi_l,bm_out_lo_l}) : 
		any_lo_bm ? 3'b000 : any_hi_bm ? 3'b100 : 3'b000;


assign single_word = any_hi_bm ^ any_lo_bm; 

// pci word count is set to:
//	8 words for memory write, if shorter, pci_last will be set with
//				last data
//	8 words for memory read, if prefetch enable is set.  Each read
//		will read 1 doubleword, so PCI need not be started for
//		reads with data still in the receive fifo
//	2 words if both word byte marks are set,
//	1 word if only 1 words byte marks are set.

wire [7:0] pci_wcount_in = single_word ? 8'h01 :
	(mem_wr_cmd_decode & burst_enable | mem_rd_cmd_decode & prefetch_enable)
	? 8'h08 : 8'h02;


// use the configuration address for configuration data read or writes,
// otherwise use the 29 bits from addr_out and the adjusted ls 3 bits
wire [31:0] pci_address_in = config_data_cmd_decode ? config_add_pci : 
	{addr_out,addr_lsbs};



// pci word count and address latched at start of pci core request
// the reserved commands which have decode of 4,5 (falcon regs)
// or 8,9 (configuration address) never start pci so we can't send
// an invalid command to the pci_core

// IT IS ASSUMED FROM PCI SPEC THAT THE ADDRESS, WCOUNT, COMMAND,
// ETC. WON'T BE USED UNTIL THE PCI CYCLE AFTER THE PCI_REQ.  IF
// NOT THESE SIGNALS MAY NOT HAVE ENOUGH SETUP TIME.

REG44 reg44_0({pci_command,pci_wcount,pci_address},clock,pci_start,
		{cmd_out,pci_wcount_in,pci_address_in});
// hold the last address and last command to be used in determining if
// the next read command is prefetchable.

// Do the increment while waiting for capture instead of after
// this was a close timing path
REG32 reg32_0({last_cmd_reg[2:0],last_address},clock,read_afx_fifo,
		{cmd_out[2:0],addr_out_inc1});

always @(posedge clock)
begin
  if( read_afx_fifo)
    last_cmd_3 <= #1 cmd_out[3];
end

wire [3:0] last_cmd = {last_cmd_3,last_cmd_reg};

wire prefetchable = prefetch_enable & (last_cmd == 4'h6) & mem_rd_cmd_decode &
	(addr_out == last_address) & ~pci_mast_rcv_fifo_empty_lo &
	~pci_mast_rcv_fifo_empty_hi & ~single_word;

// flush the pci receive fifos for any pci read EXCEPT prefetch reads
// at the start of each pci transaction

wire prefetch_flush = sm_config_data | sm_io | sm_mem_rd | sm_mem_rd4_1;

assign pci_mast_rcv_fifo_flush_in = sm_error |  prefetch_flush;

wire fifo_full_eq0 = (fifo_full_count == 3'b000);
wire fifo_full_ge1 = (fifo_full_count >= 3'b001);
wire fifo_full_ge2 = (fifo_full_count >= 3'b010);

wire pci_busy = ~reset & ~pci_complete_sync & pci_busy_reg;

always @(posedge clock)
begin

pci_async_perror_reg <= #1 pci_async_perror_sync;
pci_busy_reg <= #1 (~reset & (pci_start | ~pci_complete_sync & pci_busy_reg));
sm_idle <= #1 (sm_idle_in);
slave_idle <= #1 (sm_idle_in & ~pci_busy);
sm_config_add <= #1 (sm_config_add_in);
sm_config_data <= #1 (sm_config_data_in);
sm_config_data_rd <= #1 (sm_config_data_rd_in);
sm_io <= #1 (sm_io_in);
sm_io_rd <= #1 (sm_io_rd_in);
sm_special_cycle <= #1 (sm_special_cycle_in);
sm_mem_rd <= #1 (sm_mem_rd_in);
sm_mem_rd1 <= #1 (sm_mem_rd1_in);
sm_mem_pf_rd <= #1 (sm_mem_pf_rd_in);
sm_mem_rd4_1 <= #1 (sm_mem_rd4_1_in);
sm_mem_rd4_2 <= #1 (sm_mem_rd4_2_in);
sm_mem_wr <= #1 (sm_mem_wr_in);
sm_mem_wr_wait2 <= #1 (sm_mem_wr_wait2_in);
sm_mem_wr_wait3 <= #1 (sm_mem_wr_wait3_in);
sm_mem_wr_wait4 <= #1 (sm_mem_wr_wait4_in);
sm_mem_wr_send1 <= #1 (sm_mem_wr_send1_in);
sm_mem_wr_send2 <= #1 (sm_mem_wr_send2_in);
sm_mem_wr_send3 <= #1 (sm_mem_wr_send3_in);
sm_error <= #1 (sm_error_in);
sm_falcon <= #1 sm_falcon_in;
sm_falcon1 <= #1 sm_falcon1_in;

pci_start_reg <= #1 pci_start_reg_in;

pci_complete_hold <= #1 pci_complete_reg;

pci_mast_rcv_fifo_flush <= #1 pci_mast_rcv_fifo_flush_in;
pci_mast_xmit_fifo_flush <= #1 pci_mast_xmit_fifo_flush_in;

read_wait_pci <= #1 read_wait_pci_in;
end

// use an earlier gclk to get this out sooner!!
always @(posedge fast_gclk)
  afx_slave_preply <= #1 afx_slave_preply_in;


// Had to change this so that special cycles held until complete sync so
// that we could flush the fifos on completion and not collide with a
// write.

assign  sm_idle_in = reset |  ~pci_complete_error  &
	(sm_config_add | sm_io & cmd_out[0] | sm_io_rd &
	pci_complete_sync | sm_config_data & cmd_out[0] | 
	sm_config_data_rd & pci_complete_sync | 
	sm_special_cycle & pci_complete_sync | 
	sm_mem_rd1 & pci_complete_sync |
	sm_mem_pf_rd |
 	sm_mem_rd4_1 & pci_complete_sync  |
	sm_mem_rd4_2 & (pci_complete_sync | read_ready) |
	sm_mem_wr_wait2 & ~burst | sm_mem_wr_wait3 & ~burst |
	sm_mem_wr_wait4 & ~burst | sm_mem_wr_send3 |
	sm_idle & (pci_busy & (~mem_wr_cmd_decode & 
	~(mem_rd_cmd_decode & prefetchable)) | fifo_full_eq0)
	| sm_idle & falcon_reg_cmd_decode & pci_config_access_busy
	| sm_error | sm_falcon1);

assign  sm_error_in = ~reset & pci_complete_error;

assign  sm_mem_wr_in = ~reset & ~pci_complete_error &
	(sm_idle & mem_wr_cmd_decode & fifo_full_ge1 |
	sm_mem_wr & pci_busy);

assign  sm_mem_wr_send1_in = ~reset & ~pci_complete_error & 
	(sm_mem_wr & burst & ~pci_busy | sm_mem_wr_wait2 & burst);

assign  sm_mem_wr_wait2_in = ~reset & ~pci_complete_error & 
	(sm_mem_wr & ~burst & ~pci_busy);

assign  sm_mem_wr_send2_in = ~reset & ~pci_complete_error & 
	(sm_mem_wr_send1 & burst | sm_mem_wr_wait3 & burst);

assign  sm_mem_wr_wait3_in = ~reset & ~pci_complete_error & 
	(sm_mem_wr_send1 & ~burst);

assign  sm_mem_wr_send3_in = ~reset & ~pci_complete_error & 
	(sm_mem_wr_send2 & burst | sm_mem_wr_wait4 & burst);

assign  sm_mem_wr_wait4_in = ~reset &  ~pci_complete_error &
	(sm_mem_wr_send2 & ~burst);

assign  sm_config_add_in = ~reset & ~pci_complete_error &
	(sm_idle & config_add_cmd_decode & ~pci_busy & fifo_full_ge1);

// have to stay in special cycle until the end so that we can flush the
// fifos since this no longer gets a master abort.
assign  sm_special_cycle_in = ~reset & ~pci_complete_error &
	(sm_idle & special_cycle_cmd_decode & ~pci_busy & fifo_full_ge1
	| sm_special_cycle & ~pci_complete_sync);

assign  sm_io_in = ~reset & ~pci_complete_error &
	(sm_idle & io_cmd_decode & ~pci_busy & fifo_full_ge1);

assign  sm_io_rd_in = ~reset & ~pci_complete_error &
	(sm_io & io_rd_cmd_decode | sm_io_rd & ~pci_complete_sync);

assign  sm_config_data_in = ~reset & ~pci_complete_error &
	(sm_idle & config_data_cmd_decode & ~pci_busy & fifo_full_ge1);

assign  sm_config_data_rd_in = ~reset & ~pci_complete_error &
	(sm_config_data & config_data_rd_cmd_decode |
	sm_config_data_rd & ~pci_complete_sync);

assign  sm_mem_rd_in = ~reset & ~pci_complete_error &
	(sm_idle & mem_rd_cmd_decode & ~pci_busy & fifo_full_ge1 
	& (single_word | ~prefetch_enable));

assign  sm_mem_rd1_in = ~reset & ~pci_complete_error &
	(sm_mem_rd | sm_mem_rd1 & ~pci_complete_sync);

assign  sm_mem_rd4_1_in = ~reset & ~pci_complete_error &
	((sm_idle & mem_rd_cmd_decode & ~pci_busy & fifo_full_ge1 
	& ~single_word & prefetch_enable & ~prefetchable) | (sm_mem_rd4_1 &
	read_ready & ~ pci_complete_sync));

// must wait for the rcv fifos to be flushed before waiting for data so
// that cases of initial read followed by different address don't
// send a premature preply. Wait for read_ready to go off then on
assign  sm_mem_rd4_2_in = ~reset & ~pci_complete_error &
	(sm_mem_rd4_1 & ~read_ready 
	| sm_mem_rd4_2 & ~(pci_complete_sync | read_ready));

assign  sm_mem_pf_rd_in = ~reset & ~pci_complete_error &
	(sm_idle & mem_rd_cmd_decode & fifo_full_ge1 
	& prefetchable);

assign  sm_falcon_in = ~reset & ~pci_complete_error &
	(sm_idle & falcon_reg_cmd_decode & ~pci_busy & fifo_full_ge1 &
	~pci_config_access_busy); 
	 

assign  sm_falcon1_in = ~reset & ~pci_complete_error & sm_falcon;

// start pci from idle except for:
// config_address operations (don't need pci)
// falcon configuration reads / writes (don't need pci) 
// memory write (has special flow in state machine)

assign #1 pci_start =  ~pci_complete_error & 
	(sm_idle & ~pci_busy & fifo_full_ge1 & 
	(io_cmd_decode | config_data_cmd_decode
	| special_cycle_cmd_decode | mem_rd_cmd_decode & ~prefetchable) 
	| sm_mem_wr & ~pci_busy & burst | sm_mem_wr_wait2);

assign  pci_last = sm_mem_wr_wait2 & ~burst 
	| sm_mem_wr_wait3 & ~burst
	| sm_mem_wr_wait4 & ~burst
	| sm_mem_wr_send3;

// Since the pci clock is slower than clock, the possibility
// exists that a simple synchronizer with pci clock would not
// catch the pci_start signal,  So it must be held until the
// PCI core acknowledges it. Can't use the input to the register
// because it might be "glitching" during the the time that the
// PCI clock is switching. (if truly asynchronous.)  Use the output
// of the flop to make sure it's clean, but add's latency.

assign  pci_start_reg_in = ~reset & (pci_start | pci_start_reg 
	& ~mas_start_dma_sync);

sync sync1(	.out		(pci_req), 
		.in_clk		(pci_clk_sync), 
		.out_clk	(pci_clk_sync_),
		.in		(pci_start_reg)
);

// Since the pci clock is slower than clock, the possibility
// exists that these signals could be active for more than
// 1 clock. The synchronizer will cut off the possible second
// occurance, assuming they cannot happen back to back 
// the error signal is always qualified by the complete signal
// so it doesn't need anything extra.

// CAREFULL, these two signals are starting at clock falling
// and don't have much time to meet the rising edge of
// the same clock with the complex equations in some of them.
// An alternative would be to switch to the opposite edge
// to sync on, but this may cause additional latency for the 
// case of both clocks generated by the cpu. DID THIS!

assign  pci_complete_sync = ~pci_complete_hold & pci_complete_reg;

sync sync2(	.out	(pci_complete_reg), 
		.in_clk	(gclk_sync_), 
		.out_clk(gclk_sync),
		.in	(pci_complete)
);

sync sync3(	.out	(pci_error_sync), 
		.in_clk	(gclk_sync_), 
		.out_clk(gclk_sync),
		.in	(pci_error_reg)
);


sync sync9(	.out	(pci_async_perror_sync), 
		.in_clk	(gclk_sync_), 
		.out_clk(gclk_sync),
		.in	(pci_async_perror)
);
sync sync7(	.out	(pci_perror_sync), 
		.in_clk	(gclk_sync_), 
		.out_clk(gclk_sync),
		.in	(pci_perror_reg)
);

sync sync8(	.out	(afx_slave_idle), 
		.in_clk	(pci_clk_sync_), 
		.out_clk(pci_clk_sync),
		.in	(slave_idle)
);

sync sync4(	.out	(mas_start_dma_sync), 
		.in_clk	(gclk_sync_), 
		.out_clk(gclk_sync),
		.in	(mas_start_dma)
);

// The pci error signal is appearing before pci_complete
// catch and hold till complete.  Hopefully this is in time
// to flush any badness that happened 
// must make sure that pci_error reg is on for 2 cycles so that in 3:3 mode
// the error stays on 

always @(posedge pci_clk)
  begin
  pci_error_reg <= #1 (~reset & (pci_error | pci_error_reg & ~pci_complete_d1));
  pci_perror_reg <= #1 (~reset & (pci_perror | pci_perror_reg & ~pci_complete_d1));
  pci_complete_d1 <= #1 pci_complete;
  end

assign read_wait_pci_in = sm_io_rd | sm_config_data_rd |
	sm_mem_rd1 | sm_mem_rd4_1 | sm_mem_rd4_2;


// read the afx fifos if completing an operation OR a read was waiting
// for the pci to complete and it had an error.
assign  read_afx_fifo = sm_error & read_wait_pci | ~pci_complete_error & 
	(sm_mem_wr & burst & ~pci_busy | sm_mem_wr_send1 & burst
	| sm_mem_wr_send2 & burst | sm_mem_wr_send3
	| sm_mem_wr_wait2 | sm_mem_wr_wait3 | sm_mem_wr_wait4 
	| sm_config_add | sm_io & cmd_out[0] | sm_io_rd & pci_complete_sync
	| sm_config_data & cmd_out[0] | sm_config_data_rd & pci_complete_sync
	| sm_special_cycle & pci_complete_sync | sm_mem_rd1 & pci_complete_sync
	| sm_falcon1 | sm_mem_pf_rd  
// prefetch reads must read from pci, not fifo, so use pci_busy
	| sm_mem_rd4_1 & pci_complete_sync
	| sm_mem_rd4_2 & (pci_complete_sync | read_ready));


// break the above into two pieces for getting the address compare as
// the last level of logic before leaving this module

wire  read_afx_fifo1 = sm_error & read_wait_pci | ~pci_complete_error &
        ( sm_mem_wr_send3
        | sm_mem_wr_wait2 | sm_mem_wr_wait3 | sm_mem_wr_wait4
        | sm_config_add | sm_io & cmd_out[0] | sm_io_rd & pci_complete_sync
        | sm_config_data & cmd_out[0] | sm_config_data_rd & pci_complete_sync
        | sm_special_cycle  & pci_complete_sync | sm_mem_rd1 & pci_complete_sync
        | sm_falcon1 | sm_mem_pf_rd
// prefetch reads must read from pci, not fifo, so use pci_busy
        | sm_mem_rd4_1 & pci_complete_sync
        | sm_mem_rd4_2 & (pci_complete_sync | read_ready));

wire  read_afx_fifo2 = ~pci_complete_error &
	(sm_mem_wr & ~pci_busy | sm_mem_wr_send1 | sm_mem_wr_send2 );


// Early p-reply for the cases in which we are starting a prefetable
// read from the pci.  It will take 6 more pci clocks if we wait for
// the pci operation to complete before sending the data and reply

assign  afx_slave_preply_in = (cmd_out[0] & read_afx_fifo) ? 2'b10 :
	(~cmd_out[0] & read_afx_fifo ) ? 2'b11 : 2'b00;

// load the pci fifo only on writes, the same time as the pci fifo
// read pointer is being updated
assign  pci_mast_fifo_write = sm_mem_wr & burst & ~pci_busy  
	| sm_mem_wr_send1 & burst
	| sm_mem_wr_send2 & burst | sm_mem_wr_send3
	| sm_mem_wr_wait2 | sm_mem_wr_wait3 | sm_mem_wr_wait4 
	| sm_io & cmd_out[0] 
	| sm_config_data & cmd_out[0] 
	| sm_special_cycle;

// both sides of the fifo must be loaded if we started on a burst
// regardless of length of burst. (must load both sides even if the
// last write is only a single word!)
// Both sides of the fifo must be loaded even for single words.  The
// pci fifos are both "primed" and these primings cannot be ignored
// by the read pointers, SO there must be data in both sides at
// the start of any write xfer

assign pci_mast_fifo_write_lo = pci_mast_fifo_write ;

assign pci_mast_fifo_write_hi = pci_mast_fifo_write ;


// Now that special cycles don't generate a master abort, we must clear the
// fifos. 8-13-96
assign  pci_mast_xmit_fifo_flush_in = sm_error | (pci_command == 4'h1) 
	& pci_complete_sync;

assign  pci_read_mas_rcv_fifo = sm_io_rd & pci_complete_sync
	| sm_config_data_rd & pci_complete_sync 
	| sm_mem_rd1 & pci_complete_sync
	| sm_mem_rd4_2 & read_ready
	| sm_mem_pf_rd;

assign #1 pci_mast_rcv_fifo_read_lo = pci_read_mas_rcv_fifo & 
	(~single_word | single_word & any_lo_bm);

assign #1 pci_mast_rcv_fifo_read_hi = pci_read_mas_rcv_fifo & 
	( ~single_word | single_word & any_hi_bm);

assign  load_afx_read_data = sm_io_rd & pci_complete_sync 
	| sm_config_data_rd & pci_complete_sync 
	| sm_mem_rd1 & pci_complete_sync 
	| sm_mem_pf_rd
	| sm_mem_rd4_2 & (pci_complete_sync | read_ready)
	| sm_config_add & ~cmd_out[0]
	| sm_special_cycle &pci_complete_sync & ~cmd_out[0]
	| sm_falcon & ~cmd_out[0];

wire	select_error = pci_complete_error ;
 
assign  load_afx_read_data_lo = load_afx_read_data &
 	(~single_word | single_word & any_lo_bm);

assign  load_afx_read_data_hi = load_afx_read_data &
 	(~single_word | single_word & any_hi_bm);


assign  select_config_add = sm_config_add;

assign  read_cmd_fifo = read_afx_fifo1 
	| read_afx_fifo2 & burst_on & address_cmp;

assign  read_addr_fifo = read_afx_fifo1 
	| read_afx_fifo2 & burst_on & address_cmp;

assign  read_bm_fifo = read_afx_fifo1 
	| read_afx_fifo2 & burst_on & address_cmp; 

// data fifo is only loaded on writes, so must only be unloaded on writes
assign  read_data_fifo = (read_afx_fifo1 
	| read_afx_fifo2 & burst_on & address_cmp) & cmd_out[0];

assign  pci_config_we = pci_config_access_busy ? config_write : 
	sm_falcon & cmd_out[0];

assign  select_falcon_data = sm_falcon;

assign  load_config_add = sm_config_add & cmd_out[0];


// host is busy using configuration registers etc 
assign  host_config_access_busy = sm_falcon_in | sm_falcon | sm_falcon1;

// if we have an async parity error always, signal the last command.  This
// error occurs if we have a target detected parity error on short commands
// and the command will have been completed before the error can be determined.
// therefore identifying the last command will be correct. (as possible)

assign  afx_mast_error_address = (afx_mast_error_cmd[3:1] == 3'h5) ?
	config_add_pci : (read_wait_pci & ~pci_async_err_detect |
	pci_async_err_detect & read_afx_fifo) ? {addr_out,3'b0} : 
	{(last_address - 1'b1), 3'b0};

assign  afx_mast_error_cmd = (read_wait_pci & ~pci_async_err_detect |
	pci_async_err_detect & read_afx_fifo) ? cmd_out : last_cmd;

assign	afx_mast_error = sm_error | pci_async_err_detect;

function [2:0] decode8to3;
input	[7:0]	bm_l;
begin

  casex(bm_l)
	
	8'bxxxxxxx0:	decode8to3 = 3'b000;
	8'bxxxxxx01:	decode8to3 = 3'b001;
	8'bxxxxx011:	decode8to3 = 3'b010;
	8'bxxxx0111:	decode8to3 = 3'b011;
	8'bxxx01111:	decode8to3 = 3'b100;
	8'bxx011111:	decode8to3 = 3'b101;
	8'bx0111111:	decode8to3 = 3'b110;
	8'b01111111:	decode8to3 = 3'b111;
	default:	decode8to3 = 3'b000;
  endcase
end
endfunction

endmodule
HierarchyFilesModulesSignalsTasksFunctionsHelp

This page: Created:Thu Aug 19 12:02:38 1999
From: ../../../sparc_v8/ssparc/pcic/afx_slave/rtl/afx_slave_sm.v

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