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
Line 
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
24 *       manuel.bouyer@lip6.fr october 2013
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    {
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;
57        r_spi_clk_counter     = 0xffff;
58        r_spi_clk        = 0;
59        r_spi_done        = false;
60
61        r_irq             = false;
62        r_read            = false;
63
64        return;
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
72    if (r_spi_done)
73        r_ctrl_go_bsy = false;
74
75    switch(r_target_fsm) {
76    ////////////
77    case T_IDLE:
78    {
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();
86
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            }
93 
94
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;
115                    break;
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;
124                    break;
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;
133                    break;
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;
142                    break;
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);
160                        if (wdata & SPI_CTRL_GO_BSY) 
161                                r_ctrl_go_bsy = true;
162                        r_ctrl_char_len = (wdata & SPI_CTRL_CHAR_LEN_MASK);
163#ifdef SOCLIB_MODULE_DEBUG
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;
173                }
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;
179#endif
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                }
195            }
196        }
197        break;
198    }
199    ////////////////////
200    case T_RSP_READ:
201    case T_RSP_WRITE:
202    case T_ERROR_READ:
203    case T_ERROR_WRITE:
204        if (p_vci_target.rspack.read() ) {
205            r_target_fsm  = T_IDLE;
206        }
207        break;
208    } // end switch target fsm
209
210
211       
212
213    //////////////////////////////////////////////////////////////////////////////
214    // the SPI FSM controls SPI signals
215    //////////////////////////////////////////////////////////////////////////////
216    if (r_ctrl_go_bsy == false)
217        r_spi_done = false;
218    switch (r_spi_fsm) {
219    case S_IDLE:
220        r_spi_clk_counter = r_divider.read();
221        r_spi_clk = 0;
222        r_spi_clk_previous = r_ctrl_cpha;
223        r_spi_clk_ignore = r_ctrl_cpha;
224        r_spi_bit_count = r_ctrl_char_len;
225        r_spi_out = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
226        if (r_ctrl_go_bsy.read() && !r_spi_done.read())
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) {
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;
239                r_spi_bit_count = r_spi_bit_count - 1;
240            } else if (r_spi_clk_previous == 1 && s_clk_sample == 0) {
241                // high to low transition: change output, or stop
242                if (r_spi_bit_count == 0) {
243                    r_spi_fsm = S_IDLE;
244                    r_irq = r_ctrl_ie;
245                    r_spi_done = true;
246#ifdef SOCLIB_MODULE_DEBUG0
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 {
250                    r_spi_out = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
251                }
252            }
253        }
254        r_spi_clk_previous = s_clk_sample;
255        // generate the SPI clock
256        if (r_spi_clk_counter.read() == 0) {
257            r_spi_clk_counter = r_divider.read();
258            r_spi_clk = !r_spi_clk.read();
259            r_spi_clk_ignore = false;
260        } else {
261            r_spi_clk_counter = r_spi_clk_counter.read() - 1;
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    {
284        if ( false )  // XXX
285        {
286            r_index      = 0;
287            r_block_count   = 0;
288            r_burst_count   = 0;
289            r_words_count   = 0;
290
291            // compute r_burst_offset (zero when buffer aligned)
292            r_burst_offset = (uint32_t)((r_buf_address.read()>>2) % m_words_per_burst);
293
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;
299    } 
300    //////////////////
301    case M_READ_BLOCK:  // read one block from disk after waiting m_latency cycles
302    {
303        r_burst_count   = 0;
304        r_words_count    = 0;
305        r_initiator_fsm = M_READ_BURST;
306        break;
307    }
308    //////////////////
309    case M_READ_BURST:  // Compute the number of words and the number of flits in the burst
310                        // The number of flits can be smaller than the number of words
311                        // in case of 8 bytes flits...
312    {
313        uint32_t nwords;
314        uint32_t offset = r_burst_offset.read();
315
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        }
326
327        r_burst_nwords  = nwords;
328        r_initiator_fsm = M_READ_CMD;
329        break;
330    }
331    ////////////////
332    case M_READ_CMD:    // Send a multi-flits VCI WRITE command
333    {
334        if ( p_vci_initiator.cmdack.read() )
335        {
336            uint32_t nwords = r_burst_nwords.read() - r_words_count.read();
337
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                }
349
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;
380    }
381    ////////////////
382    case M_READ_RSP:    // Wait a single flit VCI WRITE response
383    {
384        if ( p_vci_initiator.rspval.read() )
385        {
386            bool aligned = (r_burst_offset.read() == 0);
387
388            if ( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
389            {
390                r_initiator_fsm = M_READ_ERROR;
391#ifdef SOCLIB_MODULE_DEBUG
392                std::cout << "vci_bd M_READ_ERROR" << std::endl;
393#endif
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;
401#ifdef SOCLIB_MODULE_DEBUG
402                    std::cout << "vci_bd M_READ_SUCCESS" << std::endl;
403#endif
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;
420    }
421    ///////////////////
422    case M_READ_SUCCESS:
423    case M_READ_ERROR:
424    {
425        if( !r_go ) r_initiator_fsm = M_IDLE;
426        break;
427    }
428    ///////////////////
429    case M_WRITE_BURST:  // Compute the number of words in the burst
430    {
431        uint32_t nwords;
432        uint32_t offset = r_burst_offset.read();
433
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        }
444
445        r_burst_nwords  = nwords;
446        r_initiator_fsm =  M_WRITE_CMD;
447        break;
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;
453        break;
454    }
455    /////////////////
456    case M_WRITE_RSP:   // This is actually a multi-words VCI READ response
457    {
458        if ( p_vci_initiator.rspval.read() )
459        {
460            bool aligned = (r_burst_offset.read() == 0);
461
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            }
473
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); 
478
479                    if( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
480                {
481                    r_initiator_fsm = M_WRITE_ERROR;
482#ifdef SOCLIB_MODULE_DEBUG
483                    std::cout << "vci_bd M_WRITE_ERROR" << std::endl;
484#endif
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;
503    }
504    ///////////////////
505    case M_WRITE_BLOCK:         // write a block to disk after waiting m_latency cycles
506    {
507        if ( r_block_count.read() == r_nblocks.read() - 1 ) 
508        {
509            r_initiator_fsm = M_WRITE_SUCCESS; 
510#ifdef SOCLIB_MODULE_DEBUG
511            std::cout << "vci_bd M_WRITE_SUCCESS" << std::endl;
512#endif
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;
522    }
523    /////////////////////
524    case M_WRITE_SUCCESS:
525    case M_WRITE_ERROR:
526    {
527        r_initiator_fsm = M_IDLE;
528        break;
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:
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;
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
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;
595    case M_READ_CMD:            // It is actually a multi-words VCI WRITE command
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;
616    case M_READ_RSP:
617    case M_WRITE_RSP:
618        p_vci_initiator.rspack  = true;
619        p_vci_initiator.cmdval  = false;
620        break;
621    default:
622        p_vci_initiator.rspack  = false;
623        p_vci_initiator.cmdval  = false;
624        break;
625    }
626
627    // SPI signals
628    p_spi_ss = ((r_ss & 0x1) == 0);
629    switch(r_spi_fsm) {
630    case S_IDLE:
631        p_spi_mosi = r_spi_out;
632        p_spi_clk = 0;
633        break;
634    case S_XMIT:
635      {
636        bool s_clk_sample = r_spi_clk ^ r_ctrl_cpha;
637        p_spi_clk = r_spi_clk ^ r_ctrl_cpol;
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        }
647        break;
648      }
649    }
650
651    // IRQ signal
652    p_irq = r_irq;
653} // end GenMoore()
654
655//////////////////////////////////////////////////////////////////////////////
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)
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    {
692        nbsegs++;
693       
694            if ( (seg->baseAddress() & 0x0000003F) != 0 ) 
695            {
696                    std::cout << "Error in component VciSpi : " << name
697                              << "The base address of segment " << seg->name()
698                      << " must be multiple of 64 bytes" << std::endl;
699                    exit(1);
700            }
701            if ( seg->size() < 64 ) 
702            {
703                    std::cout << "Error in component VciSpi : " << name
704                          << "The size of segment " << seg->name()
705                      << " cannot be smaller than 64 bytes" << std::endl;
706                    exit(1);
707            }
708        std::cout << "    => segment " << seg->name()
709                  << " / base = " << std::hex << seg->baseAddress()
710                  << " / size = " << seg->size() << std::endl; 
711    }
712
713    if( nbsegs == 0 )
714    {
715                std::cout << "Error in component VciSpi : " << name
716                          << " No segment allocated" << std::endl;
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
726                          << " The burst size must be 8, 16, 32 or 64 bytes" << std::endl;
727                exit(1);
728        }
729
730        if ( (vci_param::B != 4) and (vci_param::B != 8) )
731        {
732                std::cout << "Error in component VciSpi : " << name           
733                          << " The VCI data fields must have 32 bits or 64 bits" << std::endl;
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[] = 
769        {
770                "T_IDLE",
771                "T_RSP_READ",
772                "T_RSP_WRITE",
773                "T_ERROR_READ",
774                "T_ERROR_WRITE",
775        };
776        const char* spi_str[] = 
777        {
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()] 
785            << " clk_counter " << r_spi_clk_counter.read()
786            << " r_spi_bit_count " << r_spi_bit_count.read() 
787            << " r_ctrl_go_bsy " << (int)r_ctrl_go_bsy.read() << std::endl;
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()] 
797          << "  buf = " << std::hex << r_buf_address.read()
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.