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

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

Sync with VHDL, make IRQ work for DMA.

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