Index: /trunk/modules/vci_spi/caba/metadata/vci_spi.sd
===================================================================
--- /trunk/modules/vci_spi/caba/metadata/vci_spi.sd	(revision 578)
+++ /trunk/modules/vci_spi/caba/metadata/vci_spi.sd	(revision 579)
@@ -35,5 +35,6 @@
         uses = [
 		    Uses('caba:base_module'),
-            Uses('common:mapping_table'),
+                    Uses('common:mapping_table'),
+		    Uses('caba:generic_fifo'),
 		],
 
Index: /trunk/modules/vci_spi/caba/source/include/vci_spi.h
===================================================================
--- /trunk/modules/vci_spi/caba/source/include/vci_spi.h	(revision 578)
+++ /trunk/modules/vci_spi/caba/source/include/vci_spi.h	(revision 579)
@@ -54,4 +54,5 @@
 #include "vci_initiator.h"
 #include "vci_target.h"
+#include "generic_fifo.h"
 
 namespace soclib {
@@ -76,8 +77,15 @@
     sc_signal<bool>                    r_ctrl_cpha;	// clock phase
     sc_signal<bool>                    r_ctrl_ie;	// interrupt enable
-    sc_signal<bool>                    r_ctrl_go_bsy;
     sc_signal<uint8_t>                 r_ctrl_char_len; // number of bits in xfer
-
+    sc_signal<uint64_t>                r_buf_address;  // memory buffer address 
+    sc_signal<uint32_t>		       r_dma_count;   // DMA burst count
+    sc_signal<bool>		       r_read;	      // DMA read/write
+
+    sc_signal<uint32_t>		       r_burst_word;  // DMA burst word count
+    sc_signal<bool>                    r_dma_error;   // DMA error
+
+    sc_signal<bool>                    r_spi_bsy;    // SPI shifter busy
     sc_signal<uint32_t>		       r_spi_bit_count;
+    sc_signal<uint32_t>	               r_spi_word_count;
     sc_signal<uint32_t>		       r_spi_clk_counter;
     sc_signal<bool>		       r_spi_clk;
@@ -88,15 +96,6 @@
     sc_signal<bool>		       r_irq;
 
-    sc_signal<bool>		       r_read;
-    sc_signal<uint32_t>                r_nblocks;      	   // number of blocks in transfer
-    sc_signal<uint64_t>                r_buf_address;  	   // memory buffer address 
-    sc_signal<uint32_t>                r_index;        	   // word index in local buffer
-    sc_signal<uint32_t>                r_latency_count;    // latency counter 
-    sc_signal<uint32_t>                r_words_count;      // word counter (in a burst)
-    sc_signal<uint32_t>                r_burst_count;      // burst counter (in a block)
-    sc_signal<uint32_t>                r_block_count;  	   // block counter (in a transfer)
-    sc_signal<uint32_t>                r_burst_offset;     // number of non aligned words
-    sc_signal<uint32_t>                r_burst_nwords;     // number of words in a burst
-    sc_signal<bool>                    r_go;           	   // command from T_FSM to M_FSM
+    GenericFifo<typename vci_param::data_t> r_dma_fifo_read; // buffer data from SPI to network
+    GenericFifo<typename vci_param::data_t> r_dma_fifo_write;// buffer data from network to SPI
 
     sc_signal<typename vci_param::srcid_t >	r_srcid;   // save srcid
@@ -106,12 +105,10 @@
     sc_signal<typename vci_param::data_t >	r_rdata;   // save reply
 
-    uint32_t*                          r_local_buffer; 	   // capacity is one block 
-
     // structural parameters
     std::list<soclib::common::Segment> m_seglist;
     uint32_t                           m_srcid;        	   // initiator index
-    const uint32_t		       m_words_per_block;  // block size 
+    const uint32_t                     m_burst_size;       // number of words in a burst
     const uint32_t                     m_words_per_burst;  // number of words in a burst
-    const uint32_t                     m_bursts_per_block; // number of bursts in a block
+    const uint32_t                     m_byte2burst_shift; // log2(burst_size)
 
     // methods
@@ -122,18 +119,11 @@
     enum {
     M_IDLE              = 0,
-
-    M_READ_BLOCK        = 1,
-    M_READ_BURST        = 2,
-    M_READ_CMD          = 3,
-    M_READ_RSP          = 4,
-    M_READ_SUCCESS      = 5,
-    M_READ_ERROR        = 6,
-
-    M_WRITE_BURST       = 7,
-    M_WRITE_CMD         = 8,
-    M_WRITE_RSP         = 9,
-    M_WRITE_BLOCK       = 10,
-    M_WRITE_SUCCESS     = 11,
-    M_WRITE_ERROR       = 12,
+    M_READ_WAIT         = 1,
+    M_READ_CMD          = 2,
+    M_READ_RSP          = 3,
+    M_WRITE_WAIT        = 4,
+    M_WRITE_CMD         = 5,
+    M_WRITE_RSP         = 6,
+    M_WRITE_END         = 7
     };
 
@@ -150,5 +140,9 @@
     enum {
     S_IDLE		= 0,
-    S_XMIT		= 1,
+    S_DMA_RECEIVE	= 1,
+    S_DMA_SEND_START	= 2,
+    S_DMA_SEND		= 3,
+    S_DMA_SEND_END	= 4,
+    S_XMIT		= 5,
     };
 
Index: /trunk/modules/vci_spi/caba/source/src/vci_spi.cpp
===================================================================
--- /trunk/modules/vci_spi/caba/source/src/vci_spi.cpp	(revision 578)
+++ /trunk/modules/vci_spi/caba/source/src/vci_spi.cpp	(revision 579)
@@ -29,4 +29,5 @@
 #include <stdint.h>
 #include <iostream>
+#include <arithmetics.h>
 #include <fcntl.h>
 #include "vci_spi.h"
@@ -43,22 +44,28 @@
 tmpl(void)::transition()
 {
+
+    bool s_dma_bsy = (r_initiator_fsm != M_IDLE);
     if(p_resetn.read() == false) 
     {
 	r_initiator_fsm   = M_IDLE;
 	r_target_fsm      = T_IDLE;
-	r_spi_fsm	 = S_IDLE;
-	r_ss	      = 0;
-	r_divider	 = 0xffff;
+	r_spi_fsm	  = S_IDLE;
+	r_ss	          = 0;
+	r_divider	  = 0xffff;
 	r_ctrl_char_len   = 0;
-	r_ctrl_ie	 = false;
+	r_ctrl_ie	  = false;
 	r_ctrl_cpol       = false;
 	r_ctrl_cpha       = false;
-	r_ctrl_go_bsy     = false;
-	r_spi_clk_counter     = 0xffff;
-	r_spi_clk	 = 0;
+	r_spi_bsy         = false;
+	r_dma_count       = 0;
+	r_spi_clk_counter = 0xffff;
+	r_spi_clk	  = 0;
 	r_spi_done        = false;
 
 	r_irq		  = false;
 	r_read		  = false;
+
+	r_dma_fifo_read.init();
+	r_dma_fifo_write.init();
 
 	return;
@@ -71,5 +78,5 @@
 
     if (r_spi_done)
-	r_ctrl_go_bsy = false;
+	r_spi_bsy = false;
 
     switch(r_target_fsm) {
@@ -102,5 +109,5 @@
 	    	r_target_fsm = T_ERROR_READ;
 	    } else {
-		bool     write  = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) & !r_ctrl_go_bsy;
+		bool     write  = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) & !r_spi_bsy &!s_dma_bsy;
 		uint32_t cell   = (uint32_t)((address & 0x3F)>>2);
 		switch(cell) {
@@ -150,6 +157,8 @@
 		    if (r_ctrl_ie.read()) 
 			data |= SPI_CTRL_IE_EN;
-		    if (r_ctrl_go_bsy.read()) 
+		    if (r_spi_bsy.read()) 
 			data |= SPI_CTRL_GO_BSY;
+		    if (s_dma_bsy) 
+			data |= SPI_CTRL_DMA_BSY;
 		    data |= (uint32_t)r_ctrl_char_len.read();
 		    r_rdata = data;
@@ -159,5 +168,5 @@
 			r_ctrl_ie  = ((wdata & SPI_CTRL_IE_EN) != 0);
 			if (wdata & SPI_CTRL_GO_BSY) 
-				r_ctrl_go_bsy = true;
+				r_spi_bsy = true;
 			r_ctrl_char_len = (wdata & SPI_CTRL_CHAR_LEN_MASK);
 #ifdef SOCLIB_MODULE_DEBUG
@@ -167,5 +176,5 @@
 #endif
 		    } else {
-			r_irq = r_irq & r_ctrl_go_bsy;
+			r_irq = r_irq & r_spi_bsy;
 		    }
 		    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
@@ -186,4 +195,28 @@
 		    if (write) {
 			r_ss = wdata;
+		    }
+		    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
+		    break;
+		case SPI_DMA_BASE:
+		    r_rdata = r_buf_address.read();
+		    if (write) {
+			r_buf_address = (r_buf_address & (uint64_t)0xffffffff00000000) | wdata;
+		    }
+		    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
+		    break;
+		case SPI_DMA_BASEH:
+		    r_rdata = r_buf_address >> 32;
+		    if (write) {
+			r_buf_address = (r_buf_address & (uint64_t)0x00000000ffffffff) | ((uint64_t)wdata << 32);
+		    }
+		    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
+		    break;
+		case SPI_DMA_COUNT:
+		    r_rdata = (r_dma_count.read() << m_byte2burst_shift) |
+			r_read;
+		    if (write) {
+			r_read = (wdata & 0x1);
+			r_dma_count = wdata >> m_byte2burst_shift;
+			r_ctrl_char_len = vci_param::B * 8;
 		    }
 		    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
@@ -214,5 +247,5 @@
     // the SPI FSM controls SPI signals
     //////////////////////////////////////////////////////////////////////////////
-    if (r_ctrl_go_bsy == false)
+    if (r_spi_bsy == false)
 	r_spi_done = false;
     switch (r_spi_fsm) {
@@ -224,6 +257,63 @@
 	r_spi_bit_count = r_ctrl_char_len;
 	r_spi_out = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
-	if (r_ctrl_go_bsy.read() && !r_spi_done.read())
-		r_spi_fsm = S_XMIT;
+	if (r_dma_count != 0) {
+		if (r_read.read())
+			r_spi_fsm = S_DMA_SEND_START;
+		else
+			r_spi_fsm = S_DMA_RECEIVE;
+	} else if (r_spi_bsy.read() && !r_spi_done.read()) {
+	    r_spi_fsm = S_XMIT;
+	}
+	break;
+    case S_DMA_RECEIVE:
+    {
+	r_spi_clk_counter = r_divider.read();
+	r_spi_clk = 0;
+	r_spi_clk_previous = r_ctrl_cpha;
+	r_spi_clk_ignore = r_ctrl_cpha;
+	r_spi_bit_count = r_ctrl_char_len;
+	if (r_initiator_fsm != M_WRITE_RSP || !p_vci_initiator.rspval.read()) {
+	    if (r_dma_fifo_write.rok()) {
+	        typename vci_param::data_t v = r_dma_fifo_write.read();
+	        r_dma_fifo_write.simple_get();
+	        r_txrx[0] = v;
+	        r_spi_out = (v >> ((vci_param::B * 8) - 1)) & 0x1;
+	        r_spi_fsm = S_XMIT;
+	    } else if (r_initiator_fsm == M_WRITE_END) {
+	        r_spi_fsm = S_IDLE;
+	    }
+	}
+	break;
+    }
+    case S_DMA_SEND_START:
+	r_spi_word_count = (r_dma_count << (m_byte2burst_shift - 2)) - 1;
+	r_spi_out = 1;
+	r_txrx[0] = 0xffffffff;
+	r_spi_fsm = S_XMIT;
+	break;
+    case S_DMA_SEND:
+	r_spi_out = 1;
+	r_txrx[0] = 0xffffffff;
+	r_spi_clk_counter = r_divider.read();
+	r_spi_clk = 0;
+	r_spi_clk_previous = r_ctrl_cpha;
+	r_spi_clk_ignore = r_ctrl_cpha;
+	r_spi_bit_count = r_ctrl_char_len;
+	if (r_initiator_fsm != M_READ_CMD) {
+	    if (r_dma_fifo_read.wok()) {
+	        r_dma_fifo_read.simple_put(
+		    (typename vci_param::data_t)r_txrx[0]);
+	        r_spi_word_count = r_spi_word_count - 1;
+	        if ( r_spi_word_count == 0 ) {
+		    r_spi_fsm = S_DMA_SEND_END;
+	        } else {
+		    r_spi_fsm = S_XMIT;
+	        }
+	    }
+	}
+	break;
+    case S_DMA_SEND_END:
+	if (r_initiator_fsm == M_IDLE)
+		r_spi_fsm = S_IDLE;
 	break;
     case S_XMIT:
@@ -241,7 +331,14 @@
 		// high to low transition: change output, or stop
 		if (r_spi_bit_count == 0) {
-		    r_spi_fsm = S_IDLE;
-		    r_irq = r_ctrl_ie;
-		    r_spi_done = true;
+		    if (r_initiator_fsm != M_IDLE) {
+			if (r_read)
+			    r_spi_fsm = S_DMA_SEND;
+			else
+			    r_spi_fsm = S_DMA_RECEIVE;
+		    } else {
+		        r_spi_fsm = S_IDLE;
+		        r_irq = r_ctrl_ie;
+		        r_spi_done = true;
+		    }
 #ifdef SOCLIB_MODULE_DEBUG0
 		    std::cout << name() << " end xfer " << std::dec << (int)r_ctrl_char_len.read() << " data " << std::hex << r_txrx[1] << " " << r_txrx[0] << std::endl;
@@ -265,15 +362,7 @@
     }
     //////////////////////////////////////////////////////////////////////////////
-    // The initiator FSM executes a loop, transfering one block per iteration.
-    // Each block is split in bursts, and the number of bursts depends
-    // on the memory buffer alignment on a burst boundary:
-    // - If buffer aligned, all burst have the same length (m_words_per burst)
-    //   and the number of bursts is (m_bursts_per_block).
-    // - If buffer not aligned, the number of bursts is (m_bursts_per_block + 1)
-    //   and first and last burst are shorter, because all words in a burst 
-    //   must be contained in a single cache line.
-    //   first burst => nwords = m_words_per_burst - offset
-    //   last  burst => nwords = offset
-    //   other burst => nwords = m_words_per_burst
+    // The initiator FSM executes a loop, transfering one burst per iteration.
+    // data comes from or goes to fifos, the other end of the fifos is
+    // feed by or eaten by the SPI fsm.
     //////////////////////////////////////////////////////////////////////////////
 
@@ -282,51 +371,18 @@
     case M_IDLE: 	// check buffer alignment to compute the number of bursts
     {
-	if ( false )  // XXX
+	if ( r_dma_count != 0 )
 	{
-	    r_index	 = 0;
-	    r_block_count   = 0;
-	    r_burst_count   = 0;
-	    r_words_count   = 0;
-
-	    // compute r_burst_offset (zero when buffer aligned)
-	    r_burst_offset = (uint32_t)((r_buf_address.read()>>2) % m_words_per_burst);
-
-	    // start tranfer
-	    if ( r_read.read() ) 	r_initiator_fsm = M_READ_BLOCK;
-	    else		    r_initiator_fsm = M_WRITE_BURST;
-	}
-	break;
-    } 
-    //////////////////
-    case M_READ_BLOCK:  // read one block from disk after waiting m_latency cycles
-    {
-	r_burst_count   = 0;
-	r_words_count    = 0;
-	r_initiator_fsm = M_READ_BURST;
-	break;
-    }
-    //////////////////
-    case M_READ_BURST:  // Compute the number of words and the number of flits in the burst
-			// The number of flits can be smaller than the number of words 
-			// in case of 8 bytes flits...
-    {
-	uint32_t nwords;
-	uint32_t offset = r_burst_offset.read();
-
-	if ( offset )		  // buffer not aligned
-	{
-	    if ( r_burst_count.read() == 0 ) nwords = m_words_per_burst - offset;
-	    else if ( r_burst_count.read() == m_bursts_per_block ) nwords = offset;
-	    else nwords = m_words_per_burst;
-	}
-	else			   // buffer aligned
-	{
-	    nwords = m_words_per_burst;
-	}
-
-	r_burst_nwords  = nwords;
-	r_initiator_fsm = M_READ_CMD;
-	break;
-    }
+	    // start transfer
+	    if ( r_read.read() )    r_initiator_fsm = M_READ_WAIT;
+	    else		    r_initiator_fsm = M_WRITE_WAIT;
+	}
+	break;
+    }
+    case M_READ_WAIT:  // wait for the FIFO to be full
+	if (!r_dma_fifo_read.wok()) {
+		r_burst_word = m_words_per_burst - 1;
+		r_initiator_fsm = M_READ_CMD;
+	}
+	break;
     ////////////////
     case M_READ_CMD:	// Send a multi-flits VCI WRITE command
@@ -334,46 +390,16 @@
 	if ( p_vci_initiator.cmdack.read() )
 	{
-	    uint32_t nwords = r_burst_nwords.read() - r_words_count.read();
-
-	    if ( vci_param::B == 4 )    // one word per flit 
-	    {
-		if ( nwords <= 1 )      // last flit
-		{
-		    r_initiator_fsm = M_READ_RSP;
-		    r_words_count = 0;
-		}
-		else		    // not the last flit
-		{
-		    r_words_count = r_words_count.read() + 1;
-		}
-
-		// compute next word address and next local buffer index
-		r_buf_address = r_buf_address.read() + 4;
-		r_index       = r_index.read() + 1;
-	    }
-	    else			// 2 words per flit
-	    {
-		if ( nwords <= 2 )      // last flit
-		{
-		    r_initiator_fsm = M_READ_RSP;
-		    r_words_count = 0;
-		}
-		else		    // not the last flit
-		{
-		    r_words_count = r_words_count.read() + 2;
-		}
-		    
-		// compute next word address and next local buffer index
-		if ( nwords == 1 )
-		{
-		    r_buf_address = r_buf_address.read() + 4;
-		    r_index       = r_index.read() + 1;
-		}
-		else
-		{
-		    r_buf_address = r_buf_address.read() + 8;
-		    r_index       = r_index.read() + 2;
-		}
-	    }
+	    if ( r_burst_word == 0 )      // last flit
+	    {
+		r_initiator_fsm = M_READ_RSP;
+	    }
+	    else		    // not the last flit
+	    {
+		r_burst_word = r_burst_word.read() - 1;
+	    }
+
+	    r_dma_fifo_read.simple_get(); // consume one fifo word
+	    // compute next word address
+	    r_buf_address = r_buf_address.read() + vci_param::B;
 	}
 	break;
@@ -384,35 +410,27 @@
 	if ( p_vci_initiator.rspval.read() )
 	{
-	    bool aligned = (r_burst_offset.read() == 0);
-
 	    if ( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
 	    {
-		r_initiator_fsm = M_READ_ERROR;
+	        r_burst_word = 0;
+		r_dma_count = 0;
+		r_dma_error = true;
+	        r_initiator_fsm = M_IDLE;
 #ifdef SOCLIB_MODULE_DEBUG
 		std::cout << "vci_bd M_READ_ERROR" << std::endl;
 #endif
 	    }
-	    else if ( (not aligned and (r_burst_count.read() == m_bursts_per_block)) or 
-		      (aligned and (r_burst_count.read() == (m_bursts_per_block-1))) )
-	    {
-		if ( r_block_count.read() == (r_nblocks.read()-1) ) // last burst of last block 
-		{
-		    r_initiator_fsm = M_READ_SUCCESS;
+	    else if ( r_spi_fsm == S_DMA_SEND_END ) // last burst
+	    {
+		r_dma_count = 0;
+		r_initiator_fsm = M_IDLE;
+		r_dma_error = false;
 #ifdef SOCLIB_MODULE_DEBUG
-		    std::cout << "vci_bd M_READ_SUCCESS" << std::endl;
+		std::cout << "vci_bd M_READ_SUCCESS" << std::endl;
 #endif
-		}
-		else					      // last burst not last block
-		{
-		    r_index	  = 0;
-		    r_burst_count    = 0;
-		    r_block_count    = r_block_count.read() + 1;
-		    r_initiator_fsm  = M_READ_BLOCK;
-		}
-	    }
-	    else						// not the last burst
-	    {
-		r_burst_count = r_burst_count.read() + 1;
-		r_initiator_fsm = M_READ_BURST;
+	    }
+	    else // keep on reading
+	    {
+		r_dma_count = r_dma_count - 1;
+		r_initiator_fsm  = M_READ_WAIT;
 	    }
 	}
@@ -420,35 +438,15 @@
     }
     ///////////////////
-    case M_READ_SUCCESS:
-    case M_READ_ERROR:
-    {
-	if( !r_go ) r_initiator_fsm = M_IDLE;
-	break;
-    }
-    ///////////////////
-    case M_WRITE_BURST:  // Compute the number of words in the burst
-    {
-	uint32_t nwords;
-	uint32_t offset = r_burst_offset.read();
-
-	if ( offset )		  // buffer not aligned
-	{
-	    if ( r_burst_count.read() == 0 ) nwords = m_words_per_burst - offset;
-	    else if ( r_burst_count.read() == m_bursts_per_block ) nwords = offset;
-	    else nwords = m_words_per_burst;
-	}
-	else			   // buffer aligned
-	{
-	    nwords = m_words_per_burst;
-	}
-
-	r_burst_nwords  = nwords;
-	r_initiator_fsm =  M_WRITE_CMD;
-	break;
-    }
+    case M_WRITE_WAIT:  // wait for the FIFO to be empty
+	if (!r_dma_fifo_write.rok()) {
+	    r_burst_word = m_words_per_burst - 1;
+	    r_dma_count = r_dma_count - 1;
+	    r_initiator_fsm = M_WRITE_CMD;
+	}
+	break;
     /////////////////
     case M_WRITE_CMD:	// This is actually a single flit VCI READ command
     {
-	    if ( p_vci_initiator.cmdack.read() ) r_initiator_fsm = M_WRITE_RSP;
+	if ( p_vci_initiator.cmdack.read() ) r_initiator_fsm = M_WRITE_RSP;
 	break;
     }
@@ -458,75 +456,47 @@
 	if ( p_vci_initiator.rspval.read() )
 	{
-	    bool aligned = (r_burst_offset.read() == 0);
-
-	    if ( (vci_param::B == 8) and (r_burst_nwords.read() > 1) )
-	    {
-		r_local_buffer[r_index.read()]   = (uint32_t)p_vci_initiator.rdata.read();
-		r_local_buffer[r_index.read()+1] = (uint32_t)(p_vci_initiator.rdata.read()>>32);
-		r_index = r_index.read() + 2;
-	    }
-	    else
-	    {
-		r_local_buffer[r_index.read()]   = (uint32_t)p_vci_initiator.rdata.read();
-		r_index = r_index.read() + 1;
-	    }
-
+	    typename vci_param::data_t v = p_vci_initiator.rdata.read();
+	    typename vci_param::data_t f = 0;
+	    // byte-swap
+	    for (int i = 0; i < (vci_param::B * 8); i += 8) {
+		f |= ((v >> i) & 0xff) << ((vci_param::B * 8) - 8 - i);
+	    }
+	    r_dma_fifo_write.simple_put(f);
+	    r_burst_word = r_burst_word.read() - 1;
 	    if ( p_vci_initiator.reop.read() )  // last flit of the burst
 	    {
-		    r_words_count  = 0;
-		r_buf_address = r_buf_address.read() + (r_burst_nwords.read()<<2); 
-
-		    if( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
+		r_buf_address = r_buf_address.read() + m_burst_size;
+
+		if( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
 		{
-		    r_initiator_fsm = M_WRITE_ERROR;
+		    r_dma_count = 0;
+		    r_dma_error = 1;
+		    r_initiator_fsm = M_WRITE_END;
 #ifdef SOCLIB_MODULE_DEBUG
 		    std::cout << "vci_bd M_WRITE_ERROR" << std::endl;
 #endif
 		}
-		else if ( (not aligned and (r_burst_count.read() == m_bursts_per_block)) or 
-		     (aligned and (r_burst_count.read() == (m_bursts_per_block-1))) ) // last burst
+		else if ( r_dma_count.read() == 0) // last burst
 		{
-		    r_initiator_fsm  = M_WRITE_BLOCK;
+		    r_dma_error = 0;
+		    r_initiator_fsm  = M_WRITE_END;
 		}
 		else					  // not the last burst
 		{
-		    r_burst_count = r_burst_count.read() + 1;
-		    r_initiator_fsm = M_WRITE_BURST;
+		    r_initiator_fsm = M_WRITE_WAIT;
 		}
 	    }
-	    else
-	    {
-		    r_words_count = r_words_count.read() + 1;
-	    }
-	}
-	break;
-    }
-    ///////////////////
-    case M_WRITE_BLOCK:		// write a block to disk after waiting m_latency cycles
-    {
-	if ( r_block_count.read() == r_nblocks.read() - 1 ) 
-	{
-	    r_initiator_fsm = M_WRITE_SUCCESS; 
-#ifdef SOCLIB_MODULE_DEBUG
-	    std::cout << "vci_bd M_WRITE_SUCCESS" << std::endl;
-#endif
-	}
-	else
-	{
-	    r_burst_count    = 0;
-	    r_index	  = 0;
-	    r_block_count    = r_block_count.read() + 1;
-	    r_initiator_fsm  = M_WRITE_BURST;
-	}
-	break;
-    }
-    /////////////////////
-    case M_WRITE_SUCCESS:
-    case M_WRITE_ERROR:
-    {
-	r_initiator_fsm = M_IDLE;
-	break;
-    }
-    } // end switch r_initiator_fsm
+	}
+	break;
+    }
+    /////////////////
+    case M_WRITE_END:	// wait for the write to be complete
+    {
+	if (r_spi_fsm == S_IDLE) { // write complete
+	    r_initiator_fsm  = M_IDLE;
+	}
+	break;
+    }
+  } // end switch r_initiator_fsm
 }  // end transition
 
@@ -590,28 +560,34 @@
 	p_vci_initiator.wdata   = 0;
 	p_vci_initiator.be      = 0;
-	p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(r_burst_nwords.read()<<2);
+	p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(m_burst_size);
 	p_vci_initiator.eop     = true;
 	break;
     case M_READ_CMD:		// It is actually a multi-words VCI WRITE command 
+    {
+	typename vci_param::data_t v = 0;
+	typename vci_param::data_t f;
 	p_vci_initiator.rspack  = false;
 	p_vci_initiator.cmdval  = true;
-	p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read(); 
+	p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read();
 	p_vci_initiator.cmd     = vci_param::CMD_WRITE;
 	p_vci_initiator.pktid   = TYPE_WRITE;
-	p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(r_burst_nwords.read()<<2);
-	if ( (vci_param::B == 8) and ((r_burst_nwords.read() - r_words_count.read()) > 1) )  
+	p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(m_burst_size);
+	f = r_dma_fifo_read.read();
+	// byte-swap
+	for (int i = 0; i < (vci_param::B * 8); i += 8) {
+		v |= ((f >> i) & 0xff) << ((vci_param::B * 8) - 8 - i);
+	}
+	p_vci_initiator.wdata = v;
+	p_vci_initiator.eop   = ( r_burst_word.read() == 0);
+	if (vci_param::B == 8)
 	{
-	    p_vci_initiator.wdata = ((uint64_t)r_local_buffer[r_index.read()  ]) +
-				   (((uint64_t)r_local_buffer[r_index.read()+1]) << 32); 
 	    p_vci_initiator.be    = 0xFF;
-	    p_vci_initiator.eop   = ( (r_burst_nwords.read() - r_words_count.read()) <= 2 );
 	}
 	else
 	{
-	    p_vci_initiator.wdata = r_local_buffer[r_index.read()];
 	    p_vci_initiator.be    = 0xF;
-	    p_vci_initiator.eop   = ( r_words_count.read() == (r_burst_nwords.read() - 1) );
-	}
-	break;
+	}
+	break;
+    }
     case M_READ_RSP:
     case M_WRITE_RSP:
@@ -628,5 +604,5 @@
     p_spi_ss = ((r_ss & 0x1) == 0);
     switch(r_spi_fsm) {
-    case S_IDLE:
+    default:
 	p_spi_mosi = r_spi_out;
 	p_spi_clk = 0;
@@ -663,7 +639,7 @@
 	m_seglist(mt.getSegmentList(tgtid)),
 	m_srcid(mt.indexForId(srcid)),
-	m_words_per_block(512/4),
-	m_words_per_burst(burst_size/4),
-	m_bursts_per_block(512/burst_size),
+	m_burst_size(burst_size),
+	m_words_per_burst(burst_size / vci_param::B),
+	m_byte2burst_shift(soclib::common::uint32_log2(burst_size)),
 	p_clk("p_clk"),
 	p_resetn("p_resetn"),
@@ -674,5 +650,8 @@
 	p_spi_clk("p_spi_clk"),
 	p_spi_mosi("p_spi_mosi"),
-	p_spi_miso("p_spi_miso")
+	p_spi_miso("p_spi_miso"),
+
+	r_dma_fifo_read("r_dma_fifo_read", burst_size / vci_param::B), // one cache line
+	r_dma_fifo_write("r_dma_fifo_read", burst_size / vci_param::B) // one cache line
 {
     std::cout << "  - Building VciSpi " << name << std::endl;
@@ -735,11 +714,8 @@
 	}
 
-	r_local_buffer = new uint32_t[m_words_per_block];
-
 } // end constructor
 
 tmpl(/**/)::~VciSpi()
 {
-    delete [] r_local_buffer;
 }
 
@@ -752,17 +728,12 @@
 		"M_IDLE",
 
-		"M_READ_BLOCK",
-		"M_READ_BURST",
+		"M_READ_WAIT",
 		"M_READ_CMD",
 		"M_READ_RSP",
-		"M_READ_SUCCESS",
-		"M_READ_ERROR",
-
-		"M_WRITE_BURST",
+
+		"M_WRITE_WAIT",
 		"M_WRITE_CMD",
 		"M_WRITE_RSP",
-		"M_WRITE_BLOCK",
-		"M_WRITE_SUCCESS",
-		"M_WRITE_ERROR",
+		"M_WRITE_END",
 	};
 	const char* target_str[] = 
@@ -777,4 +748,8 @@
         {
 		"S_IDLE",
+		"S_DMA_RECEIVE",
+		"S_DMA_SEND_START",
+		"S_DMA_SEND",
+		"S_DMA_SEND_END",
 		"S_XMIT",
 	};
@@ -785,5 +760,5 @@
 	    << " clk_counter " << r_spi_clk_counter.read()
 	    << " r_spi_bit_count " << r_spi_bit_count.read() 
-	    << " r_ctrl_go_bsy " << (int)r_ctrl_go_bsy.read() << std::endl;
+	    << " r_spi_bsy " << (int)r_spi_bsy.read() << std::endl;
 	std::cout << name() << " _SPI : "
 	    << " r_spi_clk " << r_spi_clk.read()
@@ -793,10 +768,12 @@
 	    << " r_txrx 0x" << std::hex
 	    << r_txrx[1].read() << " " << r_txrx[0].read()
+
 	    << std::endl;
 	std::cout << name() << "  _INI : " << initiator_str[r_initiator_fsm.read()] 
 	  << "  buf = " << std::hex << r_buf_address.read()
-	  << "  block = " << std::dec << r_block_count.read() 
-	  << "  burst = " << r_burst_count.read() 
-	  << "  word  = " << r_words_count.read() <<std::endl; 
+	  << "  burst = " << r_burst_word.read() 
+	  << "  count = " << r_dma_count.read() 
+	  << "  spi_count = " << r_spi_word_count.read() 
+	  <<std::endl; 
 }
 
Index: /trunk/modules/vci_spi/include/soclib/vcispi.h
===================================================================
--- /trunk/modules/vci_spi/include/soclib/vcispi.h	(revision 578)
+++ /trunk/modules/vci_spi/include/soclib/vcispi.h	(revision 579)
@@ -35,13 +35,19 @@
     SPI_CTRL,
     SPI_DIVIDER,
-    SPI_SS
+    SPI_SS,
+    SPI_DMA_BASE,
+    SPI_DMA_BASEH,
+    SPI_DMA_COUNT
 };
 
-#define SPI_CTRL_CPOL		(1 << 15) /* Clock polarity                */
-#define SPI_CTRL_CPHA		(1 << 14) /* Clock phase                   */
-#define SPI_CTRL_IE_EN		(1 << 12) /* Interrupt Enable              */
+#define SPI_CTRL_DMA_BSY	(1 << 16) /* R   DMA in progress              */
+#define SPI_CTRL_CPOL		(1 << 15) /* R/W Clock polarity               */
+#define SPI_CTRL_CPHA		(1 << 14) /* R/W Clock phase                  */
+#define SPI_CTRL_IE_EN		(1 << 12) /* R/W Interrupt Enable             */
 // 9-11 reserved
-#define SPI_CTRL_GO_BSY		(1 << 8 ) /* Start the transfer            */
-#define SPI_CTRL_CHAR_LEN_MASK	(0xFF   ) /* Bits transmited in 1 transfer */
+#define SPI_CTRL_GO_BSY		(1 << 8 ) /* R/W Start the transfer           */
+#define SPI_CTRL_CHAR_LEN_MASK	(0xFF   ) /* R/W Bits transmited in 1 transfer*/
+
+#define SPI_DMA_COUNT_READ	(1 << 0) /* operation is a read (else write) */
 
 #endif /* SPISD_H */
