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

Last change on this file since 579 was 579, checked in by bouyer, 13 years ago

Add some basic DMA capabilities. Passes basic read/write tests.
Can only do line-aligned transfers which are multiple of a cache line in size,
but shouldn't be a strong limitation for real use.

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