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

Last change on this file since 551 was 551, checked in by bouyer, 11 years ago

Add vci_spi, a SPI (Serial Peripheral Interface) controller. The initiator
port is unused for now, but a DMA feature will be added soon.

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