/******************************************************************************/
/* */
/* 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.
***
****************************************************************************
****************************************************************************/
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
This page: |
Created: | Thu Aug 19 12:02:38 1999 |
| From: |
../../../sparc_v8/ssparc/pcic/afx_slave/rtl/afx_slave_sm.v
|