source: trunk/modules/vci_spi/caba/source/src/vci_spi.cpp @ 576

Last change on this file since 576 was 576, checked in by bouyer, 10 years ago

Sync with vhdl: when spi_fsm is IDLE get MOSI value from the saved
value instead setting it to 0. Real SD/MMC hardware seems to require that.

File size: 23.1 KB
RevLine 
[551]1/* -*- c++ -*-
2 *
3 * SOCLIB_LGPL_HEADER_BEGIN
4 *
5 * This file is part of SoCLib, GNU LGPLv2.1.
6 *
7 * SoCLib is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 of the License.
10 *
11 * SoCLib is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with SoCLib; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 * SOCLIB_LGPL_HEADER_END
22 *
23 * Copyright (c) UPMC, Lip6, SoC
[558]24 *       manuel.bouyer@lip6.fr october 2013
[551]25 *
26 * Maintainers: bouyer
27 */
28
29#include <stdint.h>
30#include <iostream>
31#include <fcntl.h>
32#include "vci_spi.h"
33#include "vcispi.h"
34
35namespace soclib { namespace caba {
36
37#define tmpl(t) template<typename vci_param> t VciSpi<vci_param>
38
39using namespace soclib::caba;
40using namespace soclib::common;
41
42////////////////////////
43tmpl(void)::transition()
44{
45    if(p_resetn.read() == false) 
46    {
[558]47        r_initiator_fsm   = M_IDLE;
48        r_target_fsm      = T_IDLE;
49        r_spi_fsm        = S_IDLE;
50        r_ss          = 0;
51        r_divider        = 0xffff;
52        r_ctrl_char_len   = 0;
53        r_ctrl_ie        = false;
54        r_ctrl_cpol       = false;
55        r_ctrl_cpha       = false;
56        r_ctrl_go_bsy     = false;
[565]57        r_spi_clk_counter     = 0xffff;
[558]58        r_spi_clk        = 0;
[565]59        r_spi_done        = false;
[551]60
61        r_irq             = false;
62        r_read            = false;
63
[558]64        return;
[551]65    } 
66
67    //////////////////////////////////////////////////////////////////////////////
68    // The Target FSM controls the following registers:
69    // r_target_fsm, r_irq_enable, r_nblocks, r_buf adress, r_lba, r_go, r_read
70    //////////////////////////////////////////////////////////////////////////////
71
[565]72    if (r_spi_done)
73        r_ctrl_go_bsy = false;
74
[551]75    switch(r_target_fsm) {
76    ////////////
77    case T_IDLE:
78    {
[558]79        if ( p_vci_target.cmdval.read() ) 
80        { 
81            r_srcid = p_vci_target.srcid.read();
82            r_trdid = p_vci_target.trdid.read();
83            r_pktid = p_vci_target.pktid.read();
84            uint32_t wdata = p_vci_target.wdata.read();
85            sc_dt::sc_uint<vci_param::N> address = p_vci_target.address.read();
[551]86
[558]87            bool found = false;
88            std::list<soclib::common::Segment>::iterator seg;
89            for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) 
90            {
91                if ( seg->contains(address) ) found = true;
92            }
[551]93 
94
[558]95            if (not found) {
96                if (p_vci_target.cmd.read() == vci_param::CMD_WRITE)
97                    r_target_fsm = T_ERROR_WRITE;
98                else
99                    r_target_fsm = T_ERROR_READ;
100            } else if (p_vci_target.cmd.read() != vci_param::CMD_READ &&
101                       p_vci_target.cmd.read() != vci_param::CMD_WRITE) {
102                r_target_fsm = T_ERROR_READ;
103            } else {
104                bool     write  = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) & !r_ctrl_go_bsy;
105                uint32_t cell   = (uint32_t)((address & 0x3F)>>2);
106                switch(cell) {
107                case SPI_DATA_TXRX0:
108                    r_rdata = r_txrx[0] & (uint64_t)0x00000000ffffffffULL;
109                    if (write) {
110                        r_txrx[0] =
111                           (r_txrx[0] & (uint64_t)0xffffffff00000000ULL) |
112                           ((uint64_t)wdata);
113                    }
114                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
[551]115                    break;
[558]116                case SPI_DATA_TXRX1:
117                    r_rdata = r_txrx[0] >> 32;
118                    if (write) {
119                        r_txrx[0] =
120                            (r_txrx[0] & (uint64_t)0x00000000ffffffffULL) |
121                            ((uint64_t)wdata << 32);
122                    }
123                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
[551]124                    break;
[558]125                case SPI_DATA_TXRX2:
126                    r_rdata = r_txrx[1] & (uint64_t)0x00000000ffffffffULL;
127                    if (write) {
128                        r_txrx[1] =
129                           (r_txrx[1] & (uint64_t)0xffffffff00000000ULL) |
130                           ((uint64_t)wdata);
131                    }
132                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
[551]133                    break;
[558]134                case SPI_DATA_TXRX3:
135                    r_rdata = r_txrx[1] >> 32;
136                    if (write) {
137                        r_txrx[1] =
138                            (r_txrx[1] & (uint64_t)0x00000000ffffffffULL) |
139                            ((uint64_t)wdata << 32);
140                    }
141                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
[551]142                    break;
[558]143                case SPI_CTRL:
144                {
145                    uint32_t data = 0;
146                    if (r_ctrl_cpol.read()) 
147                        data |= SPI_CTRL_CPOL;
148                    if (r_ctrl_cpha.read()) 
149                        data |= SPI_CTRL_CPHA;
150                    if (r_ctrl_ie.read()) 
151                        data |= SPI_CTRL_IE_EN;
152                    if (r_ctrl_go_bsy.read()) 
153                        data |= SPI_CTRL_GO_BSY;
154                    data |= (uint32_t)r_ctrl_char_len.read();
155                    r_rdata = data;
156                    if (write) {
157                        r_ctrl_cpol = ((wdata & SPI_CTRL_CPOL) != 0);
158                        r_ctrl_cpha = ((wdata & SPI_CTRL_CPHA) != 0);
159                        r_ctrl_ie  = ((wdata & SPI_CTRL_IE_EN) != 0);
[564]160                        if (wdata & SPI_CTRL_GO_BSY) 
161                                r_ctrl_go_bsy = true;
[558]162                        r_ctrl_char_len = (wdata & SPI_CTRL_CHAR_LEN_MASK);
[551]163#ifdef SOCLIB_MODULE_DEBUG
[558]164                        if ((wdata & SPI_CTRL_GO_BSY) != 0) {
165                            std::cout << name() << " start xfer " << std::dec << (int)r_ctrl_char_len.read() << " data " << std::hex << r_txrx[1] << " " << r_txrx[0] << std::endl;
166                        }
167#endif
168                    } else {
169                        r_irq = r_irq & r_ctrl_go_bsy;
170                    }
171                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
172                    break;
[551]173                }
[558]174                case SPI_DIVIDER:
175                    r_rdata = r_divider.read();
176                    if (write) {
177#ifdef SOCLIB_MODULE_DEBUG
178                        std::cout << name() << " divider set to " << std::dec << wdata << std::endl;
[551]179#endif
[558]180                        r_divider = wdata;
181                    }
182                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
183                    break;
184                case SPI_SS:
185                    r_rdata = r_ss.read();
186                    if (write) {
187                        r_ss = wdata;
188                    }
189                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
190                    break;
191                default:
192                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_ERROR_WRITE : T_ERROR_READ;
193                    break;
194                }
[551]195            }
196        }
[558]197        break;
[551]198    }
[558]199    ////////////////////
200    case T_RSP_READ:
201    case T_RSP_WRITE:
202    case T_ERROR_READ:
203    case T_ERROR_WRITE:
[551]204        if (p_vci_target.rspack.read() ) {
[558]205            r_target_fsm  = T_IDLE;
[551]206        }
[558]207        break;
[551]208    } // end switch target fsm
209
210
211       
212
213    //////////////////////////////////////////////////////////////////////////////
214    // the SPI FSM controls SPI signals
215    //////////////////////////////////////////////////////////////////////////////
[565]216    if (r_ctrl_go_bsy == false)
217        r_spi_done = false;
[551]218    switch (r_spi_fsm) {
219    case S_IDLE:
[565]220        r_spi_clk_counter = r_divider.read();
[551]221        r_spi_clk = 0;
222        r_spi_clk_previous = r_ctrl_cpha;
223        r_spi_clk_ignore = r_ctrl_cpha;
[565]224        r_spi_bit_count = r_ctrl_char_len;
[553]225        r_spi_out = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
[565]226        if (r_ctrl_go_bsy.read() && !r_spi_done.read())
[551]227                r_spi_fsm = S_XMIT;
228        break;
229    case S_XMIT:
230      {
231        bool s_clk_sample;
232        // on clock transition, sample input line, and shift data
233        s_clk_sample = r_spi_clk ^ r_ctrl_cpha;
234        if (!r_spi_clk_ignore) {
235            if (r_spi_clk_previous == 0 && s_clk_sample == 1) {
[558]236                // low to high transition: shift and sample
237                r_txrx[1] = (r_txrx[1] << 1) | (r_txrx[0] >> 63);
238                r_txrx[0] = (r_txrx[0] << 1) | p_spi_miso;
[565]239                r_spi_bit_count = r_spi_bit_count - 1;
[551]240            } else if (r_spi_clk_previous == 1 && s_clk_sample == 0) {
[558]241                // high to low transition: change output, or stop
[565]242                if (r_spi_bit_count == 0) {
[551]243                    r_spi_fsm = S_IDLE;
244                    r_irq = r_ctrl_ie;
[565]245                    r_spi_done = true;
[558]246#ifdef SOCLIB_MODULE_DEBUG0
[551]247                    std::cout << name() << " end xfer " << std::dec << (int)r_ctrl_char_len.read() << " data " << std::hex << r_txrx[1] << " " << r_txrx[0] << std::endl;
248#endif
249                } else {
[553]250                    r_spi_out = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
[551]251                }
252            }
253        }
254        r_spi_clk_previous = s_clk_sample;
[558]255        // generate the SPI clock
[565]256        if (r_spi_clk_counter.read() == 0) {
257            r_spi_clk_counter = r_divider.read();
[551]258            r_spi_clk = !r_spi_clk.read();
259            r_spi_clk_ignore = false;
260        } else {
[565]261            r_spi_clk_counter = r_spi_clk_counter.read() - 1;
[551]262        }
263        break;
264      }
265    }
266    //////////////////////////////////////////////////////////////////////////////
267    // The initiator FSM executes a loop, transfering one block per iteration.
268    // Each block is split in bursts, and the number of bursts depends
269    // on the memory buffer alignment on a burst boundary:
270    // - If buffer aligned, all burst have the same length (m_words_per burst)
271    //   and the number of bursts is (m_bursts_per_block).
272    // - If buffer not aligned, the number of bursts is (m_bursts_per_block + 1)
273    //   and first and last burst are shorter, because all words in a burst
274    //   must be contained in a single cache line.
275    //   first burst => nwords = m_words_per_burst - offset
276    //   last  burst => nwords = offset
277    //   other burst => nwords = m_words_per_burst
278    //////////////////////////////////////////////////////////////////////////////
279
280    switch( r_initiator_fsm.read() ) {
281    ////////////
282    case M_IDLE:        // check buffer alignment to compute the number of bursts
283    {
[558]284        if ( false )  // XXX
285        {
286            r_index      = 0;
287            r_block_count   = 0;
288            r_burst_count   = 0;
289            r_words_count   = 0;
[551]290
[558]291            // compute r_burst_offset (zero when buffer aligned)
292            r_burst_offset = (uint32_t)((r_buf_address.read()>>2) % m_words_per_burst);
[551]293
[558]294            // start tranfer
295            if ( r_read.read() )        r_initiator_fsm = M_READ_BLOCK;
296            else                    r_initiator_fsm = M_WRITE_BURST;
297        }
298        break;
[551]299    } 
300    //////////////////
301    case M_READ_BLOCK:  // read one block from disk after waiting m_latency cycles
302    {
[558]303        r_burst_count   = 0;
304        r_words_count    = 0;
305        r_initiator_fsm = M_READ_BURST;
306        break;
[551]307    }
308    //////////////////
309    case M_READ_BURST:  // Compute the number of words and the number of flits in the burst
[558]310                        // The number of flits can be smaller than the number of words
311                        // in case of 8 bytes flits...
[551]312    {
[558]313        uint32_t nwords;
314        uint32_t offset = r_burst_offset.read();
[551]315
[558]316        if ( offset )             // buffer not aligned
317        {
318            if ( r_burst_count.read() == 0 ) nwords = m_words_per_burst - offset;
319            else if ( r_burst_count.read() == m_bursts_per_block ) nwords = offset;
320            else nwords = m_words_per_burst;
321        }
322        else                       // buffer aligned
323        {
324            nwords = m_words_per_burst;
325        }
[551]326
[558]327        r_burst_nwords  = nwords;
328        r_initiator_fsm = M_READ_CMD;
329        break;
[551]330    }
331    ////////////////
332    case M_READ_CMD:    // Send a multi-flits VCI WRITE command
333    {
[558]334        if ( p_vci_initiator.cmdack.read() )
335        {
336            uint32_t nwords = r_burst_nwords.read() - r_words_count.read();
[551]337
[558]338            if ( vci_param::B == 4 )    // one word per flit
339            {
340                if ( nwords <= 1 )      // last flit
341                {
342                    r_initiator_fsm = M_READ_RSP;
343                    r_words_count = 0;
344                }
345                else                // not the last flit
346                {
347                    r_words_count = r_words_count.read() + 1;
348                }
[551]349
[558]350                // compute next word address and next local buffer index
351                r_buf_address = r_buf_address.read() + 4;
352                r_index       = r_index.read() + 1;
353            }
354            else                        // 2 words per flit
355            {
356                if ( nwords <= 2 )      // last flit
357                {
358                    r_initiator_fsm = M_READ_RSP;
359                    r_words_count = 0;
360                }
361                else                // not the last flit
362                {
363                    r_words_count = r_words_count.read() + 2;
364                }
365                   
366                // compute next word address and next local buffer index
367                if ( nwords == 1 )
368                {
369                    r_buf_address = r_buf_address.read() + 4;
370                    r_index       = r_index.read() + 1;
371                }
372                else
373                {
374                    r_buf_address = r_buf_address.read() + 8;
375                    r_index       = r_index.read() + 2;
376                }
377            }
378        }
379        break;
[551]380    }
381    ////////////////
382    case M_READ_RSP:    // Wait a single flit VCI WRITE response
383    {
[558]384        if ( p_vci_initiator.rspval.read() )
385        {
386            bool aligned = (r_burst_offset.read() == 0);
[551]387
[558]388            if ( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
389            {
390                r_initiator_fsm = M_READ_ERROR;
[551]391#ifdef SOCLIB_MODULE_DEBUG
392                std::cout << "vci_bd M_READ_ERROR" << std::endl;
393#endif
[558]394            }
395            else if ( (not aligned and (r_burst_count.read() == m_bursts_per_block)) or
396                      (aligned and (r_burst_count.read() == (m_bursts_per_block-1))) )
397            {
398                if ( r_block_count.read() == (r_nblocks.read()-1) ) // last burst of last block
399                {
400                    r_initiator_fsm = M_READ_SUCCESS;
[551]401#ifdef SOCLIB_MODULE_DEBUG
402                    std::cout << "vci_bd M_READ_SUCCESS" << std::endl;
403#endif
[558]404                }
405                else                                          // last burst not last block
406                {
407                    r_index       = 0;
408                    r_burst_count    = 0;
409                    r_block_count    = r_block_count.read() + 1;
410                    r_initiator_fsm  = M_READ_BLOCK;
411                }
412            }
413            else                                                // not the last burst
414            {
415                r_burst_count = r_burst_count.read() + 1;
416                r_initiator_fsm = M_READ_BURST;
417            }
418        }
419        break;
[551]420    }
421    ///////////////////
422    case M_READ_SUCCESS:
423    case M_READ_ERROR:
424    {
[558]425        if( !r_go ) r_initiator_fsm = M_IDLE;
426        break;
[551]427    }
428    ///////////////////
429    case M_WRITE_BURST:  // Compute the number of words in the burst
430    {
[558]431        uint32_t nwords;
432        uint32_t offset = r_burst_offset.read();
[551]433
[558]434        if ( offset )             // buffer not aligned
435        {
436            if ( r_burst_count.read() == 0 ) nwords = m_words_per_burst - offset;
437            else if ( r_burst_count.read() == m_bursts_per_block ) nwords = offset;
438            else nwords = m_words_per_burst;
439        }
440        else                       // buffer aligned
441        {
442            nwords = m_words_per_burst;
443        }
[551]444
[558]445        r_burst_nwords  = nwords;
446        r_initiator_fsm =  M_WRITE_CMD;
447        break;
[551]448    }
449    /////////////////
450    case M_WRITE_CMD:   // This is actually a single flit VCI READ command
451    {
452            if ( p_vci_initiator.cmdack.read() ) r_initiator_fsm = M_WRITE_RSP;
[558]453        break;
[551]454    }
455    /////////////////
456    case M_WRITE_RSP:   // This is actually a multi-words VCI READ response
457    {
[558]458        if ( p_vci_initiator.rspval.read() )
459        {
460            bool aligned = (r_burst_offset.read() == 0);
[551]461
[558]462            if ( (vci_param::B == 8) and (r_burst_nwords.read() > 1) )
463            {
464                r_local_buffer[r_index.read()]   = (uint32_t)p_vci_initiator.rdata.read();
465                r_local_buffer[r_index.read()+1] = (uint32_t)(p_vci_initiator.rdata.read()>>32);
466                r_index = r_index.read() + 2;
467            }
468            else
469            {
470                r_local_buffer[r_index.read()]   = (uint32_t)p_vci_initiator.rdata.read();
471                r_index = r_index.read() + 1;
472            }
[551]473
[558]474            if ( p_vci_initiator.reop.read() )  // last flit of the burst
475            {
476                    r_words_count  = 0;
477                r_buf_address = r_buf_address.read() + (r_burst_nwords.read()<<2); 
[551]478
[558]479                    if( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
480                {
481                    r_initiator_fsm = M_WRITE_ERROR;
[551]482#ifdef SOCLIB_MODULE_DEBUG
483                    std::cout << "vci_bd M_WRITE_ERROR" << std::endl;
484#endif
[558]485                }
486                else if ( (not aligned and (r_burst_count.read() == m_bursts_per_block)) or
487                     (aligned and (r_burst_count.read() == (m_bursts_per_block-1))) ) // last burst
488                {
489                    r_initiator_fsm  = M_WRITE_BLOCK;
490                }
491                else                                      // not the last burst
492                {
493                    r_burst_count = r_burst_count.read() + 1;
494                    r_initiator_fsm = M_WRITE_BURST;
495                }
496            }
497            else
498            {
499                    r_words_count = r_words_count.read() + 1;
500            }
501        }
502        break;
[551]503    }
504    ///////////////////
505    case M_WRITE_BLOCK:         // write a block to disk after waiting m_latency cycles
506    {
[558]507        if ( r_block_count.read() == r_nblocks.read() - 1 ) 
508        {
509            r_initiator_fsm = M_WRITE_SUCCESS; 
[551]510#ifdef SOCLIB_MODULE_DEBUG
511            std::cout << "vci_bd M_WRITE_SUCCESS" << std::endl;
512#endif
[558]513        }
514        else
515        {
516            r_burst_count    = 0;
517            r_index       = 0;
518            r_block_count    = r_block_count.read() + 1;
519            r_initiator_fsm  = M_WRITE_BURST;
520        }
521        break;
[551]522    }
523    /////////////////////
524    case M_WRITE_SUCCESS:
525    case M_WRITE_ERROR:
526    {
[558]527        r_initiator_fsm = M_IDLE;
528        break;
[551]529    }
530    } // end switch r_initiator_fsm
531}  // end transition
532
533//////////////////////
534tmpl(void)::genMoore()
535{
536    // p_vci_target port   
537    p_vci_target.rsrcid = (sc_dt::sc_uint<vci_param::S>)r_srcid.read();
538    p_vci_target.rtrdid = (sc_dt::sc_uint<vci_param::T>)r_trdid.read();
539    p_vci_target.rpktid = (sc_dt::sc_uint<vci_param::P>)r_pktid.read();
540    p_vci_target.reop   = true;
541
542    switch(r_target_fsm) {
543    case T_IDLE:
[558]544        p_vci_target.cmdack = true;
545        p_vci_target.rspval = false;
546        p_vci_target.rdata  = 0;
547        break;
548    case T_RSP_READ:
549        p_vci_target.cmdack = false;
550        p_vci_target.rspval = true;
551        p_vci_target.rdata = r_rdata;
552        p_vci_target.rerror = VCI_READ_OK;
553        break;
554    case T_RSP_WRITE:
555        p_vci_target.cmdack = false;
556        p_vci_target.rspval = true;
557        p_vci_target.rdata  = 0;
558        p_vci_target.rerror = VCI_WRITE_OK;
559        break;
560    case T_ERROR_READ:
561        p_vci_target.cmdack = false;
562        p_vci_target.rspval = true;
563        p_vci_target.rdata  = 0;
564        p_vci_target.rerror = VCI_READ_ERROR;
565        break;
566    case T_ERROR_WRITE:
567        p_vci_target.cmdack = false;
568        p_vci_target.rspval = true;
569        p_vci_target.rdata  = 0;
570        p_vci_target.rerror = VCI_WRITE_ERROR;
571        break;
[551]572    } // end switch target fsm
573
574    // p_vci_initiator port
575    p_vci_initiator.srcid  = (sc_dt::sc_uint<vci_param::S>)m_srcid;
576    p_vci_initiator.trdid  = 0;
577    p_vci_initiator.contig = true;
578    p_vci_initiator.cons   = false;
579    p_vci_initiator.wrap   = false;
580    p_vci_initiator.cfixed = false;
581    p_vci_initiator.clen   = 0;
582
583    switch (r_initiator_fsm) {
584    case M_WRITE_CMD:           // It is actually a single flit VCI read command
[558]585        p_vci_initiator.rspack  = false;
586        p_vci_initiator.cmdval  = true;
587        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read();
588        p_vci_initiator.cmd     = vci_param::CMD_READ;
589        p_vci_initiator.pktid   = TYPE_READ_DATA_UNC; 
590        p_vci_initiator.wdata   = 0;
591        p_vci_initiator.be      = 0;
592        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(r_burst_nwords.read()<<2);
593        p_vci_initiator.eop     = true;
594        break;
[551]595    case M_READ_CMD:            // It is actually a multi-words VCI WRITE command
[558]596        p_vci_initiator.rspack  = false;
597        p_vci_initiator.cmdval  = true;
598        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read(); 
599        p_vci_initiator.cmd     = vci_param::CMD_WRITE;
600        p_vci_initiator.pktid   = TYPE_WRITE;
601        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(r_burst_nwords.read()<<2);
602        if ( (vci_param::B == 8) and ((r_burst_nwords.read() - r_words_count.read()) > 1) ) 
603        {
604            p_vci_initiator.wdata = ((uint64_t)r_local_buffer[r_index.read()  ]) +
605                                   (((uint64_t)r_local_buffer[r_index.read()+1]) << 32); 
606            p_vci_initiator.be    = 0xFF;
607            p_vci_initiator.eop   = ( (r_burst_nwords.read() - r_words_count.read()) <= 2 );
608        }
609        else
610        {
611            p_vci_initiator.wdata = r_local_buffer[r_index.read()];
612            p_vci_initiator.be    = 0xF;
613            p_vci_initiator.eop   = ( r_words_count.read() == (r_burst_nwords.read() - 1) );
614        }
615        break;
[551]616    case M_READ_RSP:
617    case M_WRITE_RSP:
[558]618        p_vci_initiator.rspack  = true;
619        p_vci_initiator.cmdval  = false;
620        break;
[551]621    default:
[558]622        p_vci_initiator.rspack  = false;
623        p_vci_initiator.cmdval  = false;
624        break;
[551]625    }
626
627    // SPI signals
628    p_spi_ss = ((r_ss & 0x1) == 0);
629    switch(r_spi_fsm) {
630    case S_IDLE:
[576]631        p_spi_mosi = r_spi_out;
[551]632        p_spi_clk = 0;
633        break;
634    case S_XMIT:
[575]635      {
636        bool s_clk_sample = r_spi_clk ^ r_ctrl_cpha;
[551]637        p_spi_clk = r_spi_clk ^ r_ctrl_cpol;
[575]638        if (s_clk_sample == 0) {
639            // clock low: get data directly from shift register
640            // as r_spi_out may be delayed by one clock cycle
641            p_spi_mosi = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
642        } else {
643            // clock high: get data from saved value, as the shift register
644            // may have changed
645            p_spi_mosi = r_spi_out;
646        }
[551]647        break;
[575]648      }
[551]649    }
650
651    // IRQ signal
652    p_irq = r_irq;
653} // end GenMoore()
654
655//////////////////////////////////////////////////////////////////////////////
[558]656tmpl(/**/)::VciSpi( sc_core::sc_module_name           name, 
657                                const soclib::common::MappingTable   &mt,
658                                const soclib::common::IntTab     &srcid,
659                                const soclib::common::IntTab     &tgtid,
660                                const uint32_t                 burst_size)
[551]661
662: caba::BaseModule(name),
663        m_seglist(mt.getSegmentList(tgtid)),
664        m_srcid(mt.indexForId(srcid)),
665        m_words_per_block(512/4),
666        m_words_per_burst(burst_size/4),
667        m_bursts_per_block(512/burst_size),
668        p_clk("p_clk"),
669        p_resetn("p_resetn"),
670        p_vci_initiator("p_vci_initiator"),
671        p_vci_target("p_vci_target"),
672        p_irq("p_irq"),
673        p_spi_ss("p_spi_ss"),
674        p_spi_clk("p_spi_clk"),
675        p_spi_mosi("p_spi_mosi"),
676        p_spi_miso("p_spi_miso")
677{
678    std::cout << "  - Building VciSpi " << name << std::endl;
679
680        SC_METHOD(transition);
681    dont_initialize();
682    sensitive << p_clk.pos();
683
684        SC_METHOD(genMoore);
685    dont_initialize();
686    sensitive << p_clk.neg();
687
688    size_t nbsegs = 0;
689    std::list<soclib::common::Segment>::iterator seg;
690    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) 
691    {
[558]692        nbsegs++;
693       
[551]694            if ( (seg->baseAddress() & 0x0000003F) != 0 ) 
695            {
696                    std::cout << "Error in component VciSpi : " << name
[558]697                              << "The base address of segment " << seg->name()
698                      << " must be multiple of 64 bytes" << std::endl;
[551]699                    exit(1);
700            }
701            if ( seg->size() < 64 ) 
702            {
703                    std::cout << "Error in component VciSpi : " << name
[558]704                          << "The size of segment " << seg->name()
705                      << " cannot be smaller than 64 bytes" << std::endl;
[551]706                    exit(1);
707            }
[558]708        std::cout << "    => segment " << seg->name()
709                  << " / base = " << std::hex << seg->baseAddress()
710                  << " / size = " << seg->size() << std::endl; 
[551]711    }
712
713    if( nbsegs == 0 )
714    {
715                std::cout << "Error in component VciSpi : " << name
[558]716                          << " No segment allocated" << std::endl;
[551]717                exit(1);
718    }
719
720    if( (burst_size != 8 ) && 
721                (burst_size != 16) && 
722                (burst_size != 32) && 
723                (burst_size != 64) )
724        {
725                std::cout << "Error in component VciSpi : " << name
[558]726                          << " The burst size must be 8, 16, 32 or 64 bytes" << std::endl;
[551]727                exit(1);
728        }
729
730        if ( (vci_param::B != 4) and (vci_param::B != 8) )
731        {
[558]732                std::cout << "Error in component VciSpi : " << name           
733                          << " The VCI data fields must have 32 bits or 64 bits" << std::endl;
[551]734                exit(1);
735        }
736
737        r_local_buffer = new uint32_t[m_words_per_block];
738
739} // end constructor
740
741tmpl(/**/)::~VciSpi()
742{
743    delete [] r_local_buffer;
744}
745
746
747//////////////////////////
748tmpl(void)::print_trace()
749{
750        const char* initiator_str[] = 
751    {
752                "M_IDLE",
753
754                "M_READ_BLOCK",
755                "M_READ_BURST",
756                "M_READ_CMD",
757                "M_READ_RSP",
758                "M_READ_SUCCESS",
759                "M_READ_ERROR",
760
761                "M_WRITE_BURST",
762                "M_WRITE_CMD",
763                "M_WRITE_RSP",
764                "M_WRITE_BLOCK",
765                "M_WRITE_SUCCESS",
766                "M_WRITE_ERROR",
767        };
768        const char* target_str[] = 
[558]769        {
[551]770                "T_IDLE",
[558]771                "T_RSP_READ",
772                "T_RSP_WRITE",
773                "T_ERROR_READ",
774                "T_ERROR_WRITE",
[551]775        };
776        const char* spi_str[] = 
[558]777        {
[551]778                "S_IDLE",
779                "S_XMIT",
780        };
781
782        std::cout << name() << " _TGT : " << target_str[r_target_fsm.read()] 
783            << std::endl;
784        std::cout << name() << " _SPI : " << spi_str[r_spi_fsm.read()] 
[565]785            << " clk_counter " << r_spi_clk_counter.read()
786            << " r_spi_bit_count " << r_spi_bit_count.read() 
[564]787            << " r_ctrl_go_bsy " << (int)r_ctrl_go_bsy.read() << std::endl;
[551]788        std::cout << name() << " _SPI : "
789            << " r_spi_clk " << r_spi_clk.read()
790            << " cpol " << r_ctrl_cpol.read()
791            << " cpha " << r_ctrl_cpha.read()
792            << " r_spi_clk_ignore " << r_spi_clk_ignore.read()
793            << " r_txrx 0x" << std::hex
794            << r_txrx[1].read() << " " << r_txrx[0].read()
795            << std::endl;
796        std::cout << name() << "  _INI : " << initiator_str[r_initiator_fsm.read()] 
[558]797          << "  buf = " << std::hex << r_buf_address.read()
[551]798          << "  block = " << std::dec << r_block_count.read() 
799          << "  burst = " << r_burst_count.read() 
800          << "  word  = " << r_words_count.read() <<std::endl; 
801}
802
803}} // end namespace
804
805// Local Variables:
806// tab-width: 4
807// c-basic-offset: 4
808// c-file-offsets:((innamespace . 0)(inline-open . 0))
809// indent-tabs-mode: nil
810// End:
811
812// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
813
Note: See TracBrowser for help on using the repository browser.