HierarchyFilesModulesSignalsTasksFunctionsHelp
12

/******************************************************************************/ 
/*                                                                            */ 
/* 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:  @(#)afxmaster.v
***
***  Description:
***   This is the afx master block for the Falcon pci bridge. 
***   It works with the PCI slave block to form the DMA path
***   between PCI devices and host memory.
*** 
****************************************************************************
****************************************************************************/
`timescale      1ns/1ns

[Up: pcic afxm]
module afxmaster ( 
// add for 2.0 stale data problem 
		tar_trdyout,
		pcis_big_endian,
		// PCI SLAVE SIGNALS
   		tar_rcv1_fifo_read,
   		tar_rcv_fifo_flush,
   		tar_rcv1_dataout,
	        tar_rcv1_fifo_be_out,
	        tar_rcv1_fifo_next_be_out,
	        tar_rcv1_fifo_empty,
	        tar_rcv1_fifo_full,
	        tar_rcv2_fifo_full,
	        tar_rcv1_half_full,
	        tar_rcv2_half_full,
	        tar_rcv1_almost_full,
	        tar_rcv2_almost_full,
	        tar_rcv2_fifo_read,
	        tar_rcv2_dataout,
	        tar_rcv2_fifo_be_out,
	        tar_rcv2_fifo_next_be_out,
	        tar_rcv2_fifo_empty,
	        rcv_fifo_inpempty,
		tar_xmit1_data_in,
		tar_xmit1_fifo_write,
		tar_xmit1_fifo_write_ptr,
		tar_xmt_fifo_flush,
		tar_xmt_fifo_empty,
		tar_xmt_fifo_outempty,
		tar_xmit1_fifo_full,
		tar_xmit2_data_in,
		tar_xmit2_fifo_write,
		tar_xmit2_fifo_write_ptr,
		tar_xmit2_fifo_full,
		txmt_stop_fifowr,
		cdec_address,
		cdec_curCmd,
		force_pci_retry,
		retry_condition,
		tar_valid_cmd,
		tar_valid_cmd_early,
		afxm_idle_cyc,
		afxm_dma_read,
		afxm_read_alert,
                pclk,       
                pci_clk_sync,
                pci_clk_sync_,
		// AFX SIGNALS
		am_cstb_l, 
		am_read, 
		cas_cyc,
		valid_l,
		am_gnt_l, 
		mm_oddpar, 
		gclk, 
        	gclk_sync,
         	gclk_sync_,
		about, 
		aboe, 
		dbin, 
		dbout, 
		dboe2_in, 
		am_wm, 
		mparin,
		dp_perr,
		mparout,
		reset_l,

		// MISC SIGNALS
		req_quiescence,
		ack_quiescence,
		req_q_retry,
		afx_m_idle,
		discard_timer,

		// IOTLB signals
	        standby_dsbl_tlb,       // iotlb power down mode input
                iotlb_cd_in_reg,        // iotlb cam input data register
                iotlb_rd_in_reg,        // iotlb ram input data register
                iotlb_cd_out_reg,       // iotlb cam output data register
                iotlb_rd_out_reg,       // iotlb ram output data register
                iotlb_cntl_reg,         // iotlb control input register
                iotlb_cntl_wrt,         // iotlb control write pulse
                dma_err,                // iotlb miss or parity error
                dma_err_address,        // iotlb miss or parity error address
		iotlb_enable		// iotlb bypass or enable
	);

// add for stale data flush fix for 2.0 
	input	tar_trdyout;

	input	pcis_big_endian;
	// PCI SLAVE SIGNALS
	output tar_rcv1_fifo_read;
	output tar_rcv_fifo_flush;
	input [31:0] tar_rcv1_dataout;
	input [3:0] tar_rcv1_fifo_be_out;
	input [3:0] tar_rcv1_fifo_next_be_out;
	input tar_rcv1_fifo_empty;
	input tar_rcv1_fifo_full;
	input tar_rcv1_half_full;
	input tar_rcv1_almost_full;
	output tar_rcv2_fifo_read;
	input [31:0] tar_rcv2_dataout;
	input [3:0] tar_rcv2_fifo_be_out;
	input [3:0] tar_rcv2_fifo_next_be_out;
	input tar_rcv2_fifo_empty;
	input tar_rcv2_fifo_full;
	input tar_rcv2_half_full;
	input tar_rcv2_almost_full;
	input rcv_fifo_inpempty;
	input [2:0] tar_xmit1_fifo_write_ptr;
	input [2:0] tar_xmit2_fifo_write_ptr;
	output [31:0] tar_xmit1_data_in;
	output tar_xmit1_fifo_write;
	output tar_xmt_fifo_flush;
	input tar_xmit1_fifo_full;
	input tar_xmt_fifo_empty;
	input tar_xmt_fifo_outempty;
	output [31:0] tar_xmit2_data_in;
	output tar_xmit2_fifo_write;
	input tar_xmit2_fifo_full;
	input txmt_stop_fifowr;
	input [31:0] cdec_address;
 	input [3:0] cdec_curCmd;
	output force_pci_retry;
	input retry_condition;
	input tar_valid_cmd;
	input tar_valid_cmd_early;
	output afxm_idle_cyc;
	output afxm_dma_read;
	output afxm_read_alert;

	input pclk;       
        input pci_clk_sync;             // for sync ckts
        input pci_clk_sync_;            // for sync ckts
	// AFX SIGNALS
	output  am_cstb_l;              // transfer request to afx master
        output  am_read;                // r/w indicator on Falcon transfers
        input   valid_l;                // read/write strobe for falcon afx master
        input   cas_cyc;                // low addr for falcon afx master
        input   am_gnt_l;               // afx grant for falcon
        input   mm_oddpar;              // from mmu PCR: odd/even parity

	input gclk;			// afx clock @ 1/3 cpu clock
        input gclk_sync;             	// for sync ckts
        input gclk_sync_;            	// for sync ckts
        output [14:0] about;		// muxed addr/byte mask row/col address
        output  aboe;			// address bus output enable, 4 copies
        input [63:0] dbin;		// input afx data bus
        output [63:0] dbout;		// afx DMA write data out
        output dboe2_in;		// afx DMA write data bus enable (to be or'ed and
					//  flopped with afx_slave dboe)
        output [1:0] am_wm;		// afx word mask
        input [1:0] mparin;       	// input afx data parity
        input [1:0] dp_perr;       	// parity error from memif
        output [1:0] mparout;       	// afx write data parity
        input reset_l;       		// system reset
	input req_quiescence;		// cpu request to flush write buffers
	output ack_quiescence;		// Falcon acknwledge to cpu that flush
					//  is done and Falcon afxm is quiescent
	output req_q_retry;		// quiescence req to retry
					//  pci slave
	output afx_m_idle;		// afx master idle AND fifo's are empty too.
    	input [14:0] discard_timer;     // discard timer timeout max (from config reg @0x68)

// IOTLB interface
output   [31:0]  iotlb_cd_out_reg;
output   [31:0]  iotlb_rd_out_reg;
output           dma_err;
output   [31:0]  dma_err_address;
input  [31:0]  iotlb_cd_in_reg;
input  [31:0]  iotlb_rd_in_reg;
input  [7:0]   iotlb_cntl_reg;
input          iotlb_cntl_wrt;
input          iotlb_enable;
input          standby_dsbl_tlb;

parameter MAX_XFER = 4'h7;            //max afx burst xfer memif allows

	wire [3:0] dma_bm;
	reg dma_burst;
	wire idle_cyc;
        wire idle_cyc_p;
        wire idle_cyc_p2;
        wire afx_m_idle;
	wire req_cyc;
	wire radr_cyc, radr_cyc1;
        reg radr_cyc2;			//2.0 addition
	wire cadr_cyc, cadr_cyc1;
	wire data_cyc,data_cyc1;
	wire hold_cyc,hold_cyc1;
	wire error;
        wire aboe;			// 
        wire aboe5;			//5th copy, used internally
        wire dboe2_in;			//to be or'ed an flopped with afx_slave dboe
        reg dboe_ff;			//internal copy

wire   tar_valid_cmd    ;
wire   tar_valid_cmd_early    ;
wire   [ 3:0]  tar_rcv1_fifo_be_out ;
wire   [ 3:0]  tar_rcv2_fifo_be_out ;

wire save_addr;
wire discard_timeout;
reg discard_timeout1;
wire discard_ok_g, discard_ok;



wire am_cstb_l;
wire am_gnt_l;

wire [3:0]   cdec_curCmd ;

// enabled mem read and write for IO commands below 
wire  pci_mem_rd_p  =   (cdec_curCmd == 4'h6) | 
                        (cdec_curCmd == 4'hc) |
                        (cdec_curCmd == 4'he) |
			(cdec_curCmd == 4'h2);      //pci_io_rd

//create gclk-synced version of pci_mem_rd
wire pci_mem_rd_g;
sync s24 (.out(pci_mem_rd_g),.in_clk(gclk_sync),.out_clk(gclk_sync_),.in(pci_mem_rd_p));

 
wire   pci_mem_wrt_p =   (cdec_curCmd == 4'h7) |
                         (cdec_curCmd == 4'hf) | 
			 (cdec_curCmd == 4'h3);	//pci_io_wrt


//create gclk-synced version of pci_mem_wrt
wire pci_mem_wrt_g;
sync s25 (.out(pci_mem_wrt_g),.in_clk(gclk_sync),.out_clk(gclk_sync_),.in(pci_mem_wrt_p));


reg tar_valid_cmd1;
reg pci_mem_wrt_p1;

always @(posedge pclk) begin
    tar_valid_cmd1 <= #1 tar_valid_cmd;
    pci_mem_wrt_p1 <= #1 pci_mem_wrt_p ;
end

wire tar_valid_cmd_p = tar_valid_cmd | tar_valid_cmd1;

//create gclk-synced version of tar_valid_cmd
wire tar_valid_cmd_g;
sync s1 (.out(tar_valid_cmd_g),.in_clk(gclk_sync),.out_clk(gclk_sync_),.in(tar_valid_cmd_p));

wire cmd_start_p = tar_valid_cmd_p & (pci_mem_rd_p | pci_mem_wrt_p) ;
wire cmd_start_g = tar_valid_cmd_g & (pci_mem_rd_g | pci_mem_wrt_g) ;

reg cmd_start_g1;
reg pci_mem_wrt_g1;
always @(posedge gclk) begin
    cmd_start_g1 <= #1 cmd_start_g;
    pci_mem_wrt_g1 <= #1 pci_mem_wrt_g ;
end

wire tar_rcv1_fifo_empty;
wire tar_rcv2_fifo_empty;
wire rcv_fifo_empty_g = (tar_rcv1_fifo_empty & tar_rcv2_fifo_empty) ||
		         tar_rcv_fifo_flush;

//wire trcv_full = tar_rcv1_fifo_full | tar_rcv2_fifo_full;
//wire trcv_half_full = tar_rcv1_half_full & tar_rcv2_half_full;
//wire trcv_qtr_full = ~(tar_rcv1_fifo_empty | tar_rcv2_fifo_empty);
wire trcv_qtr_full = ~(tar_rcv1_fifo_empty | tar_rcv2_fifo_empty);

wire oe_off;
wire start_xfer_g;
wire back2idle =  rcv_fifo_empty_g & idle_cyc;

wire am_gnt_l1;


reg [31:0] start_addr;
reg [31:0] dma_addr;
wire  delayed_read;
reg read_alert;
wire dma_read;


//2.0: added delayed_read_g for write_alert (used to use
// delayed_read
wire delayed_read_g;
sync s2 (.out(delayed_read_g),.in_clk(gclk_sync),.out_clk(gclk_sync_),.in(delayed_read));

wire write_alert = ~read_alert & ~delayed_read_g & 
		     ~rcv_fifo_empty_g & ~ack_quiescence;

wire write_alert_p;
sync s22 (.out(write_alert_p),.in_clk(pci_clk_sync),.out_clk(pci_clk_sync_),.in(write_alert));

wire [31:0] cdec_address ;
reg [31:0] retried_addr;
wire retry_addr_match;
reg unaligned;
reg [2:0] xfer_count;
reg [63:0] afx_rdata;
reg [1:0] afx_mpar;
wire read_start_p;
wire txmt_stop_fifo_wr0;
wire txmt_stop_fifo_wr;
reg rmw;
wire pend_abort_write;
wire delayed_abort_write;
wire rmw_write;

//2.0: fix to pn138: add ~delayed_read term
//wire afxm_idle_cyc = idle_cyc_p;
wire afxm_idle_cyc = idle_cyc_p & ~delayed_read;

//2.0: change idle_cyc_p to idle_cyc
//wire dma_read_to_pcis = (dma_read & ~rmw) | (pend_abort_write & idle_cyc_p);
wire dma_read_to_pcis = (dma_read & ~rmw) | (pend_abort_write & idle_cyc);

wire afxm_dma_read;
sync s13 (.out(afxm_dma_read),.in_clk(pci_clk_sync),.out_clk(pci_clk_sync_),.in(dma_read_to_pcis));

sync s14 (.out(idle_cyc_p),.in_clk(pci_clk_sync),.out_clk(pci_clk_sync_),.in(idle_cyc));
sync s17 (.out(idle_cyc_p2),.in_clk(pci_clk_sync_),.out_clk(pci_clk_sync),.in(idle_cyc));

reg tar_rcv_fifo_flush;
wire rcv_fifo_empty_p = rcv_fifo_inpempty | tar_rcv_fifo_flush;

wire force_pci_retry;
reg tar_xmt_fifo_flush;

wire tar_xmt_fifo_empty_g = tar_xmt_fifo_empty;
wire tar_xmt_fifo_empty_p = tar_xmt_fifo_outempty | tar_xmt_fifo_flush;

assign afx_m_idle = idle_cyc_p2 & tar_xmt_fifo_empty_p & rcv_fifo_empty_p ;

wire req_q_rd; 		//req_q_rd qualified for delayed read case

//wire req_q_retry = (req_quiescence | ack_quiescence) & ~read_alert |
//  	     req_q_rd & read_alert;
wire req_q_retry = req_quiescence | ack_quiescence ;


wire rmw_next; 

wire read_alert_p;
sync s31 (.out(read_alert_p),.in_clk(pci_clk_sync_),.out_clk(pci_clk_sync),.in(read_alert));

//2.0: new output to pci_slave
wire afxm_read_alert = read_alert_p;

//read_pack_done makes the retry_sm wait till at least 1 read word data
//has been written packed) into xmit fifos before accepting the 
//returning read master.

//2.0: redefined read_pack_done  
//wire read_pack_done = ((tar_xmit1_fifo_write_ptr > 3'h0) & (tar_xmit2_fifo_write_ptr > 3'h0)) |

wire read_pack_done =  ~tar_xmt_fifo_empty_p;

reg cmd_start_p1;
wire flush_stale_read;
retry_sm retry_sm1(force_pci_retry, save_addr, discard_timeout,
                pclk, reset_l, flush_stale_read, cmd_start_p, cmd_start_p1,
		pci_mem_rd_p, pci_mem_wrt_p, 
		delayed_read, idle_cyc_p, rcv_fifo_empty_p,
                tar_xmt_fifo_empty_p, retry_addr_match, read_pack_done, 
		ack_quiescence, discard_timer, discard_ok);

always @(posedge pclk) begin
     discard_timeout1 <= #1 discard_timeout;
end

assign discard_ok_g = ~tar_xmt_fifo_empty_g & ~read_alert &
		       ~data_cyc & ~hold_cyc;

sync s501 (.out(discard_ok),.in_clk(pci_clk_sync_),.out_clk(pci_clk_sync),.in(discard_ok_g));

always @(posedge pclk) begin
   if (~reset_l)
	retried_addr <= #1 32'b0;
   else if (save_addr)
        retried_addr <= #1 cdec_address;
end

// change this to be only the same number of bits as the
// the flush compare below to make a gate fix possible.
assign retry_addr_match = (retried_addr == cdec_address);
//assign retry_addr_match = (retried_addr[31:12] == cdec_address[31:12]);

wire retry_condition_p = retry_condition;

wire force_pci_retry_g;
sync s15 (.out(force_pci_retry_g),.in_clk(gclk_sync),.out_clk(gclk_sync_),.in(force_pci_retry));

wire retry_condition_g;
sync s29 (.out(retry_condition_g),.in_clk(gclk_sync),.out_clk(gclk_sync_),.in(retry_condition_p));


wire save_start_addr = cmd_start_p & ~cmd_start_p1 &
              //((pci_mem_wrt_p & ~retry_condition_p ) |
              ((pci_mem_wrt_p) |
//2.0: change read_alert to read_alert_p (1.0 bug? )
              //(pci_mem_rd_p & rcv_fifo_empty_p & ~read_alert));
               (pci_mem_rd_p & rcv_fifo_empty_p & ~read_alert_p));

start_xfer_sm start_xfer_sm1 (start_xfer_g,
                gclk, reset_l, cmd_start_g, cmd_start_g1,
                pci_mem_wrt_g1, pci_mem_rd_g, retry_condition_g,
                rcv_fifo_empty_g, tar_xmt_fifo_empty_g, idle_cyc, 
		force_pci_retry_g);
//2.0: substituted tar_xmt_fifo_empty_g with am_gnt_l 
                //rcv_fifo_empty_g, am_gnt_l, idle_cyc, force_pci_retry_g);

quiescent_sm q_sm(ack_quiescence, req_q_rd,
                 req_quiescence, pclk, reset_l ,tar_valid_cmd_early, 
		 read_alert, rcv_fifo_empty_p , tar_xmt_fifo_empty_p , 
		//2.0: replace idle_cyc_p with afxm_idle_cyc (see
		//     pn138)
		 //delayed_read, retry_addr_match,  idle_cyc_p);
		 delayed_read, retry_addr_match, afxm_idle_cyc);

reg nonaligned_start_addr_p;
always @(posedge pclk) begin
    if (~reset_l) begin
	start_addr <= #1 32'b0;
	nonaligned_start_addr_p <= #1 1'b0;
    end
    else if (save_start_addr) begin
        start_addr <= #1 {cdec_address[31:3],3'b0} ;
	nonaligned_start_addr_p <= #1 cdec_address[2];
    end
end

wire nonaligned_start_addr;
sync s26 (.out(nonaligned_start_addr),.in_clk(gclk_sync),.out_clk(gclk_sync_),.in(nonaligned_start_addr_p));

reg start_xfer_g1;

always @(posedge pclk) begin
    cmd_start_p1 <= #1 cmd_start_p;
end


//2.0 add read_pack_done 
start_sm start_sm1 (read_start_p, delayed_read,
                pclk, reset_l, cmd_start_p, cmd_start_p1, 
		pci_mem_rd_p, rcv_fifo_empty_p,
                tar_xmt_fifo_empty_p, force_pci_retry, idle_cyc_p,
		ack_quiescence);
		//ack_quiescence, read_pack_done);

wire read_start;
sync s28 (.out(read_start),.in_clk(gclk_sync),.out_clk(gclk_sync_),.in(read_start_p));

always @(posedge gclk) begin
    start_xfer_g1 <= #1 start_xfer_g;
end


wire preempted;
reg am_read;
always @(posedge gclk) begin
  	am_read <= #1  
		~((rmw & ~rmw_write & ((cadr_cyc&cas_cyc) | data_cyc | hold_cyc)) ||
		  (write_alert & rmw & rmw_write & ~rmw_next) ||
                  (write_alert & ~rmw_next & ~rmw) ||
                  (write_alert & rmw_next & ~rmw & ~am_cstb_l) ||
                  (~write_alert & ~read_alert & ~dma_read) 
		 );
end

wire afxm_idle = (~write_alert & ~read_alert) | error; 

wire [31:0] next_addr;
wire [2:0] xfercount;
wire  dma_addr12 = dma_addr[12];
wire  nxt_addr12 = next_addr[12];

//2.0: replace cross_page flop with wire (1.0/1.1 bug! see pn137) 
/*
reg cross_page;
always @(posedge gclk) begin
   if (~(data_cyc & valid_l))
        cross_page <= #1 ~(nxt_addr12 == dma_addr12) & ~am_gnt_l;
end
*/
wire cross_page = (nxt_addr12 != dma_addr12) & ~am_gnt_l;

wire dma_burst_in = ~afxm_idle & ~cross_page & ~rmw_write & (xfer_count < MAX_XFER);

always @(posedge gclk) begin
   if (idle_cyc | radr_cyc | cadr_cyc | hold_cyc)
       dma_burst <= #1 dma_burst_in;
end

wire txmt_stop_fifo_wr_g;
wire abort_write;


reg valid_l1;
wire write_aborted;			//used to sync up on next burst

wire incr_ok =  aboe5 & ~am_gnt_l & ~(rmw & ~rmw_write) & ~pend_abort_write & 
		~abort_write & ~write_aborted;

wire tar_xmit_fifo_full = tar_xmit1_fifo_full | tar_xmit2_fifo_full;

reg inhibit_xmit_write;
always @(posedge gclk ) begin

   // valid_l1 used to reduce valid_l loading
//2.0: adjust since initial rcv_fifo read strobe timing changed
   //if (~reset_l | ((write_alert & radr_cyc) | (read_alert & ~valid_l1)))
   //2.0: add ~inhibit_xmit_write (see PN134) 
   if (~reset_l | ((write_alert & radr_cyc1 & ~radr_cyc2) | (read_alert & ~valid_l1 & ~inhibit_xmit_write)))
   //turn off unaligned flag after first unaligned data has been
   //read out of tar_rcv2 on writes or written into tar_xmit2 on reads.
   //or initialize on system reset
       unaligned <= #1 1'b0;
   //initialize unaligned flag based on starting address alignment
   else if (start_xfer_g | start_xfer_g1) 
       unaligned <= #1 nonaligned_start_addr;

   //dma_addr 
   if (~reset_l)
      dma_addr <= #1 32'b0;
   //load starting address at start
   else if (start_xfer_g) 
      dma_addr <= #1 start_addr;
   //increment address
   else if (incr_ok & data_cyc & ~data_cyc1) 
           dma_addr[31:0] <= #1 next_addr[31:0];

   //data transfer count 
   //if (~reset_l | start_xfer_g)
   if (~reset_l | am_gnt_l)
      xfer_count <= #1 3'b0;
   //increment data transfer count
   else if (~valid_l) 
          xfer_count <= #1 xfercount;

   //reset read_alert
   if (~reset_l)
       read_alert <= #1 1'b0;
   else
   //initialize read_alert flag at beginning of read transaction
   if (~read_alert) 
       read_alert <= #1 read_start;
   else
   //turn off read_alert flag after 3rd valid_l so afxm stops
   //after 4th xfer--unless pci_slave asserts txmt_stop_fifo_wr
   //to indicate initiator has terminated the read 
//2.0: corollary fix to pn137
//if (read_alert &  ((~valid_l & (xfer_count==(MAX_XFER-1) | cross_page)) |
if (read_alert &  ((~valid_l & (xfer_count==(MAX_XFER-1)) | cross_page) |
//2.0: add read_start term (necessary?) 
		   (txmt_stop_fifo_wr_g & ~read_start) | 
		   ack_quiescence))
      read_alert <= #1 1'b0;

end


assign next_addr[31:3] = dma_addr[31:3] + 1'b1;
assign next_addr[2:0] = 3'b000;
assign xfercount = xfer_count + 1'b1;

always @(posedge gclk) begin
    valid_l1 <= #1 valid_l;
end

/* DMA READ STUFF */

//flushing read buffers

assign txmt_stop_fifo_wr0 = txmt_stop_fifowr;

reg txmt_stop_fifo_wr1;
always @(posedge pclk) begin
    txmt_stop_fifo_wr1 <= #1 txmt_stop_fifo_wr0;
end
assign txmt_stop_fifo_wr = txmt_stop_fifo_wr0 | txmt_stop_fifo_wr1;

//txmt_stop_fifo_wr_g needed?
sync s16 (.out(txmt_stop_fifo_wr_g),.in_clk(gclk_sync),.out_clk(gclk_sync_),.in(txmt_stop_fifo_wr));

//flushing stale read data (case where read data is sitting in
//read buffers and a write to same location comes in before
//read completes).

//assign flush_stale_read = save_start_addr & pci_mem_wrt_p & ~tar_xmt_fifo_empty_p &
assign flush_stale_read = ~tar_trdyout & pci_mem_wrt_p & ~tar_xmt_fifo_empty_p &
			//2.0: compare within 4K page to make sure 
			//     entire read fifo is compared against
			//     starting write address.
			//( {cdec_address[31:3],3'b0} == retried_addr);
			(cdec_address[31:12] == retried_addr[31:12]);

// note tar_xmt_fifo_flush is synced with pclk
always @(posedge pclk) begin
    tar_xmt_fifo_flush <= #1 read_start_p | txmt_stop_fifo_wr |  
			      flush_stale_read | discard_timeout |
			      ack_quiescence;
			     
end


reg unaligned1;
always @(posedge gclk) begin
   unaligned1 <= #1 unaligned;
end

//2.0: introduce inhibit on tar_xmit_fifo_writes to keep xmit fifo 
// from being written again after flush. 
always @(posedge gclk) begin
   if (txmt_stop_fifo_wr_g)
	inhibit_xmit_write <= #1 1'b1;
   else if (xfer_count == 3'h0)
	inhibit_xmit_write <= #1 1'b0;
end

//write enables for pci read buffers
reg tar_xmit1_fifo_write, tar_xmit2_fifo_write;
always @(posedge gclk) begin
	tar_xmit1_fifo_write <= #1 dma_read & ~rmw & ~valid_l & 
		~tar_xmit1_fifo_full & ~unaligned & ~inhibit_xmit_write;
	tar_xmit2_fifo_write <= #1 dma_read & ~rmw & ~valid_l & 
		~tar_xmit2_fifo_full & ~inhibit_xmit_write;
end


//read enables for pci read buffers


//latching in read data from afx db
always @(posedge gclk) begin
   if (~reset_l ) begin
      afx_rdata <= #1 64'b0;
      afx_mpar <= #1 2'b0;
   end
   else if (aboe5 & ~dboe_ff & dma_read & data_cyc) begin
      afx_rdata <= #1 dbin;
      afx_mpar <= #1 mparin;
   end
end

wire [1:0] memif_perr = ~am_gnt_l & dma_read ? dp_perr[1:0] : 2'b0;

wire afx_perr = memif_perr[1] | memif_perr[0];

wire [1:0] afx_rdata_par = {^(afx_rdata[63:32]),^(afx_rdata[31:0])};


//convert read data from big to little endian
wire [31:0] tar_xmit1_data_in = {afx_rdata[39:32],afx_rdata[47:40],
                     	    afx_rdata[55:48],afx_rdata[63:56]};

wire [31:0] tar_xmit2_data_in = {afx_rdata[7:0],afx_rdata[15:8],
                     	    afx_rdata[23:16],afx_rdata[31:24]};

reg trcv1_val, trcv2_val;
wire [3:0] rmw_data2_mask = trcv2_val ? tar_rcv2_fifo_be_out[3:0] : 4'b1111;
wire [3:0] rmw_data1_mask = trcv1_val ? tar_rcv1_fifo_be_out[3:0] : 4'b1111;

//rmw read data masking
wire [63:0] rmw_rdata;
assign rmw_rdata[63:32] = {tar_xmit2_data_in[31:24] & {8{rmw_data2_mask[3]}}, 
		      	   tar_xmit2_data_in[23:16] & {8{rmw_data2_mask[2]}},
		      	   tar_xmit2_data_in[15:8]  & {8{rmw_data2_mask[1]}},
		      	   tar_xmit2_data_in[7:0]   & {8{rmw_data2_mask[0]}}};
assign rmw_rdata[31:0]  = {tar_xmit1_data_in[31:24] & {8{rmw_data1_mask[3]}}, 
		      	   tar_xmit1_data_in[23:16] & {8{rmw_data1_mask[2]}},
		      	   tar_xmit1_data_in[15:8]  & {8{rmw_data1_mask[1]}},
		      	   tar_xmit1_data_in[7:0]   & {8{rmw_data1_mask[0]}}};



/* DMA WRITE STUFF */



reg am_gnt_ff;
always @(posedge gclk ) begin
    am_gnt_ff <= #1 am_gnt_l;
end
assign am_gnt_l1 = am_gnt_ff;

reg tar_rcv1_fifo_empty1;
reg tar_rcv2_fifo_empty1;
reg rcv_fifo_empty_g1;
always @(posedge gclk ) begin
	tar_rcv1_fifo_empty1 <= #1 tar_rcv1_fifo_empty;
	tar_rcv2_fifo_empty1 <= #1 tar_rcv2_fifo_empty;
	rcv_fifo_empty_g1 <= #1 rcv_fifo_empty_g;
end

//read enables for pci write buffers
reg tar_rcv1_fifo_read;
reg tar_rcv2_fifo_read;

//2.0: change first read strobe from req_cyc to radr_cyc1 
always @(posedge gclk) begin
    radr_cyc2 <= #1 radr_cyc1;
end
//wire read1 = req_cyc & ~preempted & (~am_read|rmw_next);
wire read1 = radr_cyc & ~radr_cyc1 & ~preempted & (~am_read|rmw_next);
wire read2 = cadr_cyc & cas_cyc & ~dma_read & ~rmw & 
	     ~cross_page & ~rmw_next & dboe_ff & ~abort_write;
wire read3 = hold_cyc & ~dma_read & ~am_gnt_l & ~rmw & dma_burst &  
	     ~cross_page & ~rmw_next & dboe_ff & ~abort_write &
	     (xfer_count < MAX_XFER);

always @(posedge gclk ) begin
    tar_rcv1_fifo_read <= #1 (read1 & ~tar_rcv1_fifo_empty & ~unaligned & ~abort_write & ~write_aborted) | 
		             (read2 & ~tar_rcv1_fifo_empty & ~write_aborted) |
		             (read3 & ~tar_rcv1_fifo_empty & ~write_aborted) ;

    tar_rcv2_fifo_read <= #1 (read1 & ~tar_rcv2_fifo_empty) |
		             (read2 & ~tar_rcv2_fifo_empty) | 
		             (read3 & ~tar_rcv2_fifo_empty) ; 
end

/*
wire tar_rcv1_fifo_read;
wire tar_rcv2_fifo_read;
wire tar_rcv1_fifo_read = (~tar_rcv1_fifo_empty & cadr_cyc & ~cadr_cyc1 &
		  ~preempted & ~unaligned & ~abort_write & ~write_aborted &
		 (~dma_read|rmw_next)) ||
		 (data_cyc & ~data_cyc1 & dma_burst & ~dma_read & ~rmw 
		  & ~rmw_next & dboe_ff & ~tar_rcv1_fifo_empty & ~abort_write & ~write_aborted);

wire tar_rcv2_fifo_read = (~tar_rcv2_fifo_empty & cadr_cyc & ~cadr_cyc1 & ~abort_write &
		  ~preempted & (~dma_read|rmw_next)) ||
		 (data_cyc & ~data_cyc1 & dma_burst & ~dma_read & ~rmw 
		  & ~rmw_next & dboe_ff & ~tar_rcv2_fifo_empty & ~abort_write);
*/

wire rcv_fifo_read = tar_rcv1_fifo_read | tar_rcv2_fifo_read;

//Detect case where last write data is single word but dw-aligned 
wire last_single = (radr_cyc | data_cyc) &
		    tar_rcv1_fifo_read & ~tar_rcv2_fifo_read;

//muxing of dma write data 
wire [31:0] tar_rcv1_dataout, tar_rcv2_dataout;
wire [63:0] rmw_wdata;
wire [63:0] rmw_dataout;

always @(posedge gclk) begin
  if (~reset_l | idle_cyc | (req_cyc & ~preempted)) begin
      trcv1_val <= #1 1'b0;
      trcv2_val <= #1 1'b0;
  end
  //2.0: adjust since initial rcv_fifo read strobe timing changed:
  //else if ((radr_cyc & ~radr_cyc1) | (data_cyc & ~data_cyc1 & ~rmw)) begin
  else if ((radr_cyc1 & ~radr_cyc2) | (data_cyc & ~data_cyc1 & ~rmw)) begin
      trcv1_val <= #1 tar_rcv1_fifo_read;
      trcv2_val <= #1 tar_rcv2_fifo_read;
  end
end

wire trcv_val = trcv1_val | trcv2_val;

wire [63:0] dma_data;
wire [63:0] trcv_datamux;
assign trcv_datamux[63:32] = trcv2_val ? tar_rcv2_dataout : 32'b0;
assign trcv_datamux[31:0] = trcv1_val ? tar_rcv1_dataout : 32'b0;


assign dma_data = rmw ? rmw_dataout : trcv_datamux;

//function to convert pci be's (8 bits) to 2-bit afx word mask

//detect if next xfer is rmw, based on next byte enables
wire [1:0] word_mask_next;


wire [3:0] trcv2_next_be_out = tar_rcv2_fifo_next_be_out;
wire [3:0] trcv1_next_be_out = tar_rcv1_fifo_next_be_out;


assign word_mask_next = ~tar_rcv2_fifo_empty & ~tar_rcv1_fifo_empty ?
				wm_encode({trcv2_next_be_out,trcv1_next_be_out}) :
			~tar_rcv2_fifo_empty & tar_rcv1_fifo_empty ?
				wm_encode({trcv2_next_be_out,4'b1111}) :
			 tar_rcv2_fifo_empty & ~tar_rcv1_fifo_empty ?
				wm_encode({4'b1111,trcv1_next_be_out}) :
		         2'b11;

assign rmw_next = (word_mask_next==2'b0);


always @(posedge gclk) begin
   if (~reset_l) 
       rmw <= #1 1'b0;
   else if (idle_cyc | 
	    (hold_cyc & rmw_write) | 
	    (data_cyc & am_gnt_l & (dma_burst|trcv_val))) 	//preempted
       rmw <= #1 rmw_next;
   else
       rmw <= #1 rmw;
end

wire trcv2_only =  ~tar_rcv2_fifo_empty;

//2.0: add new wire for abort_write_sm; signals when no valid
//     write data has been read out of rcv fifos due to temp
//     empty condition; causes a quick abort of the afx write cycle.
wire no_rcv_read = ((radr_cyc1 & ~radr_cyc2) | (data_cyc & ~data_cyc1 & ~rmw)) &
		   ~tar_rcv1_fifo_read & ~tar_rcv2_fifo_read &
		   ~dma_read;

reg no_rcv_read_ff;
always @(posedge gclk) begin
    if (data_cyc & ~data_cyc1)
        no_rcv_read_ff <= #1 no_rcv_read;
end

wire new_cmd_start = cmd_start_g & ~cmd_start_g1;

abort_write_sm aw_sm (pend_abort_write, abort_write, write_aborted, 
		 	delayed_abort_write, gclk, reset_l,
			last_single, no_rcv_read, valid_l, trcv2_only, data_cyc,
			cas_cyc, radr_cyc, cadr_cyc, hold_cyc, idle_cyc, 
			req_cyc, tar_rcv2_fifo_read, new_cmd_start);

reg [1:0] word_mask;
wire [1:0] word_maskin1 = tar_rcv2_fifo_read & tar_rcv1_fifo_read ? 
			   wm_encode({tar_rcv2_fifo_next_be_out,tar_rcv1_fifo_next_be_out}) :
		       tar_rcv2_fifo_read & ~tar_rcv1_fifo_read ?
			   wm_encode({tar_rcv2_fifo_next_be_out,4'b1111}) :
		       ~tar_rcv2_fifo_read & tar_rcv1_fifo_read ?
			   wm_encode({4'b1111,tar_rcv1_fifo_next_be_out}) :
		       word_mask;
wire [1:0] word_maskin2 = trcv2_val & trcv1_val ? 
			   wm_encode({tar_rcv2_fifo_be_out,tar_rcv1_fifo_be_out}) :
		       trcv2_val & ~trcv1_val ?
			   wm_encode({tar_rcv2_fifo_be_out,4'b1111}) :
		       ~trcv2_val & trcv1_val ?
			   wm_encode({4'b1111,tar_rcv1_fifo_be_out}) :
//2.0: change for quick_abort condition
		       ~trcv2_val & ~trcv1_val & ~delayed_abort_write & no_rcv_read_ff ?
		       //word_mask;
		       2'b0 :
		       word_mask;

always @(posedge gclk) begin
   if (~reset_l | dma_read | rmw)
       word_mask <= #1 2'b11;
   //2.0: adjust since init rcv_fifo read strobe changed timing
   //else if (radr_cyc & ~radr_cyc1) begin
   else if (radr_cyc1 & ~radr_cyc2) begin
       word_mask <= #1 word_maskin1;
   end    
   else if (hold_cyc) begin
       word_mask <= #1 word_maskin2;
   end    
end


wire [1:0] am_wm =  word_mask[1:0];

//rmw write data masking
assign rmw_wdata[63:32] = {trcv_datamux[63:56] & ~{8{rmw_data2_mask[3]}}, 
		           trcv_datamux[55:48] & ~{8{rmw_data2_mask[2]}},
		           trcv_datamux[47:40] & ~{8{rmw_data2_mask[1]}},
		           trcv_datamux[39:32] & ~{8{rmw_data2_mask[0]}}};
assign rmw_wdata[31:0]  = {trcv_datamux[31:24] & ~{8{rmw_data1_mask[3]}}, 
		           trcv_datamux[23:16] & ~{8{rmw_data1_mask[2]}},
		           trcv_datamux[15:8]  & ~{8{rmw_data1_mask[1]}},
		           trcv_datamux[7:0]   & ~{8{rmw_data1_mask[0]}}};

//merge masked rmw_rdata and rmw_wdata
assign rmw_dataout = rmw_rdata | rmw_wdata;

//flushing write buffers
// note tar_rcv_fifo_flush is synced with pclk
always @(posedge pclk) begin
      //tar_rcv_fifo_flush <= #1 cmd_start_p & ~cmd_start_p1 & 
      tar_rcv_fifo_flush <= #1 tar_valid_cmd_early & ~tar_valid_cmd & 
 		 	    pci_mem_wrt_p;
end

//
// adding iotlb between dma_addr register output, and about_ff register
//
reg  [31:0] iotlb_rd_out_reg;
reg  [31:0] iotlb_cd_out_reg;
reg	iotlb_cntl_wrt_d1;
reg	iotlb_cntl_wrt_d2;
reg	iotlb_cntl_wrt_d3;
wire iotlb_rdwrt = (iotlb_cntl_wrt_d1 | iotlb_cntl_wrt_d2 | iotlb_cntl_wrt_d3 );
wire xlate_start = ((idle_cyc | req_cyc | radr_cyc) & (start_xfer_g | start_xfer_g1));
wire xlate_incr  = incr_ok & (data_cyc & ~data_cyc1);
wire [41:0] iotlb_cd_in; 
wire [41:0] iotlb_cd_out; 
wire	iotlb_valid_in = iotlb_cd_in_reg[3];
wire	iotlb_lvl3_in = iotlb_cd_in_reg[0];
wire	iotlb_lvl2_in = iotlb_cd_in_reg[1];
wire	iotlb_lvl1_in = iotlb_cd_in_reg[2];
wire [27:0] iotlb_rd_in = {iotlb_rd_in_reg[27:3], iotlb_lvl1_in, iotlb_lvl2_in, iotlb_lvl3_in}; 
wire [27:0] iotlb_rd_out; 
wire [3:0]  iotlb_addr = iotlb_cntl_reg[3:0];
wire	tlb_we	= iotlb_cntl_reg[7];
wire	tlb_flush = iotlb_cntl_reg[6];
wire	tlb_asel = iotlb_cntl_reg[5];
wire	iotlb_cr = (iotlb_cntl_wrt_d1 & ~tlb_flush & ~tlb_we & tlb_asel);
wire	iotlb_we = (iotlb_cntl_wrt_d2 & ~tlb_flush & tlb_we & tlb_asel);
wire	iotlb_flush = (iotlb_cntl_wrt_d1 & tlb_flush & ~tlb_we & ~tlb_asel);
wire	iotlb_asel = (iotlb_cntl_wrt_d1 & ~tlb_flush & ~tlb_we & tlb_asel)
		| (iotlb_cntl_wrt_d2 & ~tlb_flush & ~tlb_we & tlb_asel)
		| (iotlb_cntl_wrt_d2 & ~tlb_flush & tlb_we & tlb_asel);
wire	iotlb_miss;
// wire	iotlb_valid = iotlb_cd_out[41];
// wire	iotlb_lvl3 = iotlb_cd_out[24];
// wire	iotlb_lvl2 = iotlb_cd_out[31];
// wire	iotlb_lvl1 = iotlb_cd_out[40];
// iotlb_cd_in_reg[31:12] == virtual address (index1,index2,index3)
// iotlb_cd_in_reg[3]     == valid input bit
// iotlb_cd_in_reg[2:0]   == level input bits (level1,level2,level3)
wire	ld_ras_about = (radr_cyc | (cadr_cyc & ~cas_cyc));
wire	ld_cas_about = ((cadr_cyc & cas_cyc) | hold_cyc);
//2.0: fix iotlb_err for pn129 
//wire	iotlb_err = (iotlb_enable & (ld_ras_about | ld_cas_about) & iotlb_miss & ~oe_off); 
//wire	iotlb_err = (iotlb_enable & iotlb_miss & data_cyc & ~data_cyc1); 
wire	dma_err = (iotlb_enable & iotlb_miss & data_cyc & ~data_cyc1) |
		    afx_perr; 

wire	dma_sel_17_12 = ( ~iotlb_enable | iotlb_miss | iotlb_rd_out[0] );
wire	dma_sel_23_18 = ( ~iotlb_enable | iotlb_miss | iotlb_rd_out[1] );
wire	dma_sel_27_24 = ( ~iotlb_enable | iotlb_miss | iotlb_rd_out[2] );
// wire	dma_sel_17_12 = ( ~iotlb_enable | iotlb_miss | ~iotlb_valid | iotlb_lvl3 );
// wire	dma_sel_23_18 = ( ~iotlb_enable | iotlb_miss | ~iotlb_valid | iotlb_lvl2 );
// wire	dma_sel_27_24 = ( ~iotlb_enable | iotlb_miss | ~iotlb_valid | iotlb_lvl1 );

//2.0: add dp_perr[1:0] in bits iotlb_err_address[2:1] & renamed 
//wire [31:0] iotlb_err_address = ({dma_addr[31:2],1'b0,dma_read});
wire [31:0] dma_err_address = ({dma_addr[31:3],memif_perr[1:0],dma_read});

wire [27:12] xdma_addr;
always @(posedge gclk)
  begin
    if (~reset_l)
      begin
      iotlb_cd_out_reg <= #1 32'h00000000;
      iotlb_rd_out_reg <= #1 32'h00000000;
      end
    else if (iotlb_cntl_wrt_d3)
      begin
      iotlb_cd_out_reg <= #1 ({iotlb_cd_out[39:32],iotlb_cd_out[30:25],iotlb_cd_out[23:18],
				8'h00,iotlb_cd_out[41:40],iotlb_cd_out[31],iotlb_cd_out[24]});
      iotlb_rd_out_reg <= #1 ({4'b0000,iotlb_rd_out});
      end 
  end

always @(posedge gclk)
  begin
    if (~reset_l)
      begin
Next12
HierarchyFilesModulesSignalsTasksFunctionsHelp

This page: Created:Thu Aug 19 11:59:54 1999
From: ../../../sparc_v8/ssparc/pcic/afxmaster/rtl/afxmaster.v

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