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

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

Make sure MOSI data changes on SPI clock falling edge,
not one system clock cycle later. With a dividor of 0, this would
delay the MOSI change to the SPI clock rising edge.

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 = 0;
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.