OpenCores
URL https://opencores.org/ocsvn/xulalx25soc/xulalx25soc/trunk

Subversion Repositories xulalx25soc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /xulalx25soc/trunk/bench
    from Rev 47 to Rev 75
    Reverse comparison

Rev 47 → Rev 75

/cpp/sdspisim.h
0,0 → 1,86
////////////////////////////////////////////////////////////////////////////////
//
// Filename: sdspisim.h
//
// Project: Wishbone Controlled SD-Card Controller over SPI port
//
// Purpose: This library simulates the operation of a SPI commanded SD-Card,
// such as might be found on a XuLA2-LX25 board made by xess.com.
//
// This simulator is for testing use in a Verilator/C++ environment, where
// it would be used in place of the actual hardware.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#ifndef SDSPISIM_H
#define SDSPISIM_H
 
typedef enum eRESET_STATES {
SDSPI_POWERUP_RESET,
SDSPI_CMD0_IDLE,
SDSPI_RCVD_CMD8,
SDSPI_RCVD_ACMD41,
SDSPI_RESET_COMPLETE,
SDSPI_IN_OPERATION
} RESET_STATES;
 
#define SDSPI_RSPLEN 8
#define SDSPI_MAXBLKLEN (1+2048+2)
#define SDSPI_CSDLEN (16)
#define SDSPI_CIDLEN (16)
class SDSPISIM {
FILE *m_dev;
unsigned long m_devblocks;
 
int m_last_sck, m_delay, m_mosi;
bool m_busy, m_debug, m_block_address, m_altcmd_flag,
m_syncd, m_host_supports_high_capacity;
 
RESET_STATES m_reset_state;
 
int m_cmdidx, m_bitpos, m_rspidx, m_rspdly, m_blkdly,
m_blklen, m_blkidx, m_last_miso, m_powerup_busy;
char m_cmdbuf[8], m_dat_out, m_dat_in;
char m_rspbuf[SDSPI_RSPLEN];
char m_block_buf[SDSPI_MAXBLKLEN];
char m_csd[SDSPI_CSDLEN], m_cid[SDSPI_CIDLEN];
 
public:
SDSPISIM(void);
void load(const char *fname);
void debug(const bool dbg) { m_debug = dbg; }
bool debug(void) const { return m_debug; }
int operator()(const int csn, const int sck, const int dat);
unsigned cmdcrc(int ln, char *buf) const;
bool check_cmdcrc(char *buf) const;
void add_block_crc(int ln, char *buf) const;
};
 
#endif
/cpp/pipecmdr.cpp
1,8 → 1,8
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename: pipecmdr.cpp
//
// Project: FPGA testbench utilities.
// Project: XuLA2-LX25 SoC based upon the ZipCPU
//
// Purpose: This program attaches to a Verilated Verilog IP core.
// It will not work apart from such a core. Once attached,
13,13 → 13,35
// designed to verify that the IP core works prior to such
// actual hardware implementation.
//
// Creator: Dan Gisselquist
// Gisselquist Tecnology, LLC
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
// Copyright: 2015
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
 
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
class PIPECMDR {
public:
int m_skt, m_con;
/cpp/pipecmdr.h
1,24 → 1,46
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename: pipecmdr.h
//
// Project: FPGA testbench utilities.
// Project: XuLA2-LX25 SoC based upon the ZipCPU
//
// Purpose: This program attaches to a Verilated Verilog IP core.
// It will not work apart from such a core. Once attached,
// it connects the simulated core to a controller via a
// pipe interface designed to act like a UART. Indeed, it
// is hoped that the final interface would be via UART. Until
// that point, however, this is just a simple test facility
// designed to verify that the IP core works prior to such
// actual hardware implementation.
// it connects the simulated core to a controller via a pipe interface
// designed to act like a UART. Indeed, it is hoped that the final
// interface would be via UART. Until that point, however, this is just
// a simple test facility designed to verify that the IP core works
// prior to such actual hardware implementation.
//
// Creator: Dan Gisselquist
// Gisselquist Tecnology, LLC
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
// Copyright: 2015
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#ifndef PIPECMDR_H
#define PIPECMDR_H
 
185,12 → 207,16
if ((TESTB<VA>::m_core->o_tx_data == '\n')||(m_txpos >= sizeof(m_txbuf))) {
int snt = 0;
snt = send(m_con, m_txbuf, m_txpos, 0);
if (snt < 0) {
close(m_con);
m_con = -1;
snt = 0;
}
m_txbuf[m_txpos] = '\0';
printf("> %s", m_txbuf);
if (snt < m_txpos) {
fprintf(stderr, "Only sent %d bytes!\n",
snt);
fprintf(stderr, "Only sent %d bytes of %d!\n",
snt, m_txpos);
}
m_txpos = 0;
}
/cpp/busmaster_tb.cpp
1,5 → 1,5
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename: busmaster_tb.cpp
//
// Project: FPGA library development (XuLA2 development board)
6,17 → 6,40
//
// Purpose: This is piped version of the testbench for the busmaster
// verilog code. The busmaster code is designed to be a complete
// code set implementing all of the functionality of the XESS
// XuLA2 development board. If done well, the programs talking to
// this one should be able to talk to the board and apply the
// same tests to the board itself.
// code set implementing all of the functionality of the XESS XuLA2
// development board. If done well, the programs talking to this one
// should be able to talk to the board and apply the same tests to the
// board itself.
//
// Creator: Dan Gisselquist
// Gisselquist Tecnology, LLC
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
// Copyright: 2015
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include <signal.h>
#include <time.h>
 
28,6 → 51,7
#include "pipecmdr.h"
#include "qspiflashsim.h"
#include "sdramsim.h"
#include "sdspisim.h"
 
#include "port.h"
 
43,9 → 67,11
public:
unsigned long m_tx_busy_count;
QSPIFLASHSIM m_flash;
SDSPISIM m_sdcard;
SDRAMSIM m_sdram;
unsigned m_last_led;
time_t m_start_time;
bool m_last_writeout;
 
BUSMASTER_TB(void) : PIPECMDR(FPGAPORT) {
m_start_time = time(NULL);
56,7 → 82,13
m_core->eval();
}
 
void setsdcard(const char *fn) {
m_sdcard.load(fn);
}
 
void tick(void) {
int flash_miso, sdcard_miso;
 
if ((m_tickcount & ((1<<28)-1))==0) {
double ticks_per_second = m_tickcount;
time_t seconds_passed = time(NULL)-m_start_time;
69,9 → 101,21
 
// Set up the bus before any clock tick
m_core->i_clk = 1;
m_core->i_spi_miso = m_flash(m_core->o_sf_cs_n,
m_core->o_spi_sck,
m_core->o_spi_mosi)&0x02;
flash_miso = (m_flash(m_core->o_sf_cs_n,
m_core->o_spi_sck,
m_core->o_spi_mosi)&0x02)?1:0;
sdcard_miso = m_sdcard(m_core->o_sd_cs_n, m_core->o_spi_sck,
m_core->o_spi_mosi);
 
if ((m_core->o_sf_cs_n)&&(m_core->o_sd_cs_n))
m_core->i_spi_miso = 1;
else if ((!m_core->o_sf_cs_n)&&(m_core->o_sd_cs_n))
m_core->i_spi_miso = flash_miso;
else if ((m_core->o_sf_cs_n)&&(!m_core->o_sd_cs_n))
m_core->i_spi_miso = sdcard_miso;
else
assert((m_core->o_sf_cs_n)||(m_core->o_sd_cs_n));
 
m_core->i_ram_data = m_sdram(1,
m_core->o_ram_cke, m_core->o_ram_cs_n,
m_core->o_ram_ras_n, m_core->o_ram_cas_n,
93,14 → 137,47
else if (m_core->v__DOT__sdram__DOT__bank_active[3])
writeout = true;
*/
if (writeout) {
 
/*
if ((m_core->v__DOT__wbu_cyc)&&(!m_core->v__DOT__wbu_we))
writeout = true;
if (m_core->v__DOT__genbus__DOT__exec_stb)
writeout = true;
*/
 
if (!m_core->v__DOT__zippy__DOT__cmd_halt)
writeout = true;
 
if (!m_core->o_sd_cs_n)
writeout = true;
else if (!m_core->v__DOT__sdcard_cs_n)
writeout = true;
else if ((((m_core->v__DOT__wb_addr ^ 0x0120)&(~0x03))==0)
&&(m_core->v__DOT__wb_cyc))
writeout = true;
 
writeout = (writeout)||(m_core->i_rx_stb)
||((m_core->o_tx_stb)&&(!m_core->i_tx_busy));
writeout = (writeout)||(m_core->v__DOT____Vcellinp__genbus____pinNumber9);
writeout = (writeout)||(m_core->v__DOT__wb_stb);
writeout = (writeout)||(m_core->v__DOT__wb_err);
 
if ((writeout)||(m_last_writeout)) {
printf("%08lx:", m_tickcount);
 
printf("(%d,%d->%d),(%d,%d->%d)|%c[%08x/%08x]@%08x %d%d%c",
/*
printf("%d/%02x %d/%02x%s ",
m_core->i_rx_stb, m_core->i_rx_data,
m_core->o_tx_stb, m_core->o_tx_data,
m_core->i_tx_busy?"/BSY":" ");
*/
 
printf("(%d,%d->%d),(%c:%d,%d->%d)|%c[%08x/%08x]@%08x %c%c%c",
m_core->v__DOT__wbu_cyc,
m_core->v__DOT__dwb_cyc, // was zip_cyc
m_core->v__DOT__wb_cyc,
//
m_core->v__DOT__wbu_zip_arbiter__DOT__r_a_owner?'Z':'j',
m_core->v__DOT__wbu_stb,
// 0, // m_core->v__DOT__dwb_stb, // was zip_stb
m_core->v__DOT__zippy__DOT__thecpu__DOT__mem_stb_gbl,
110,10 → 187,26
m_core->v__DOT__wb_data,
m_core->v__DOT__dwb_idata,
m_core->v__DOT__wb_addr,
m_core->v__DOT__dwb_ack,
m_core->v__DOT__dwb_stall,
(m_core->v__DOT__dwb_ack)?'A':
(m_core->v__DOT____Vcellinp__genbus____pinNumber9)?'a':' ',
(m_core->v__DOT__dwb_stall)?'S':
(m_core->v__DOT____Vcellinp__genbus____pinNumber10)?'s':' ',
(m_core->v__DOT__wb_err)?'E':'.');
 
/*
printf(" RUNWB %d@0x%08x %3x %3x %d %d/%d %d:%09lx",
m_core->v__DOT__genbus__DOT__runwb__DOT__wb_state,
m_core->v__DOT__wbu_addr,
m_core->v__DOT__genbus__DOT__runwb__DOT__r_len,
m_core->v__DOT__genbus__DOT__runwb__DOT__r_acks_needed,
m_core->v__DOT__genbus__DOT__runwb__DOT__w_eow,
m_core->v__DOT__genbus__DOT__runwb__DOT__last_ack,
m_core->v__DOT__genbus__DOT__runwb__DOT__zero_acks,
m_core->v__DOT__genbus__DOT__exec_stb,
m_core->v__DOT__genbus__DOT__exec_word);
*/
 
/*
printf("%c[%d%d%d%d,%d:%04x%c]@%06x(%d) ->%06x%c",
(m_core->v__DOT__sdram_sel)?'!':' ',
m_core->o_ram_cs_n, m_core->o_ram_ras_n,
151,27 → 244,130
?(m_core->v__DOT__sdram__DOT__r_data)
:(m_core->v__DOT__sdram_data),
(m_core->v__DOT__sdram__DOT__r_addr));
*/
 
printf("%s%s%s%s%s%s%s%s%s%s%s%2x",
/*
printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%2x %s%s %2d %2d",
// (m_core->v__DOT__zippy__DOT__dbg_ack)?"A":"-",
// (m_core->v__DOT__zippy__DOT__dbg_stall)?"S":"-",
// (m_core->v__DOT__zippy__DOT__sys_dbg_cyc)?"D":"-",
(m_core->v__DOT__zippy__DOT__cpu_lcl_cyc)?"L":"-",
(m_core->v__DOT__zippy__DOT__cpu_dbg_stall)?"Z":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__r_halted)?"Z":"-",
(m_core->v__DOT__zippy__DOT__cmd_halt)?"H":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__pf_cyc)?"P":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__pf_valid)?"V":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__mem_cyc_gbl)?"G":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__mem_cyc_lcl)?"L":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__dcd_ce)?"k":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__r_dcdvalid)?"D":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__dcd_ce)?"d":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__opvalid)?"O":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__op_ce)?"k":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__opvalid_mem)?"M":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__mem_ce)?"m":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__new_pc)?"N":"-",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__clear_pipeline)?"C":"-",
(m_core->v__DOT__zippy__DOT__cmd_addr));
(m_core->v__DOT__zippy__DOT__cmd_addr),
(m_core->v__DOT__zippy__DOT__thecpu__DOT__ibus_err_flag)?"IB":" ",
(m_core->v__DOT__zippy__DOT__thecpu__DOT__ubus_err_flag)?"UB":" ",
m_core->v__DOT__zippy__DOT__thecpu__DOT__domem__DOT__rdaddr,
m_core->v__DOT__zippy__DOT__thecpu__DOT__domem__DOT__wraddr);
 
printf("\n");
}
printf(" PC0x%08x/%08x/%08x-%08x %s0x%08x",
m_core->v__DOT__zippy__DOT__thecpu__DOT__pf_pc,
m_core->v__DOT__zippy__DOT__thecpu__DOT__ipc,
m_core->v__DOT__zippy__DOT__thecpu__DOT__upc,
m_core->v__DOT__zippy__DOT__thecpu__DOT__instruction,
(m_core->v__DOT__zippy__DOT__thecpu__DOT__instruction_decoder__DOT__genblk3__DOT__r_early_branch)?"EB":" ",
m_core->v__DOT__zippy__DOT__thecpu__DOT__instruction_decoder__DOT__genblk3__DOT__r_branch_pc
);
*/
 
/*
printf("SDSPI[%d,%d(%d),(%d)] ",
m_core->v__DOT__sdcard_controller__DOT__r_cmd_busy,
m_core->v__DOT__sdcard_controller__DOT__r_sdspi_clk,
m_core->v__DOT__sdcard_controller__DOT__r_cmd_state,
m_core->v__DOT__sdcard_controller__DOT__r_rsp_state);
printf("LL[%d,%2x->CK=%d/%2x,%s,ST=%2d,TX=%2x,RX=%2x->%d,%2x] ",
m_core->v__DOT__sdcard_controller__DOT__ll_cmd_stb,
m_core->v__DOT__sdcard_controller__DOT__ll_cmd_dat,
m_core->v__DOT__sdcard_controller__DOT__lowlevel__DOT__r_z_counter,
// (m_core->v__DOT__sdcard_controller__DOT__lowlevel__DOT__r_clk_counter==0)?1:0,
m_core->v__DOT__sdcard_controller__DOT__lowlevel__DOT__r_clk_counter,
(m_core->v__DOT__sdcard_controller__DOT__lowlevel__DOT__r_idle)?"IDLE":" ",
m_core->v__DOT__sdcard_controller__DOT__lowlevel__DOT__r_state,
m_core->v__DOT__sdcard_controller__DOT__lowlevel__DOT__r_byte,
m_core->v__DOT__sdcard_controller__DOT__lowlevel__DOT__r_ireg,
m_core->v__DOT__sdcard_controller__DOT__ll_out_stb,
m_core->v__DOT__sdcard_controller__DOT__ll_out_dat
);
printf(" CRC=%02x/%d",
m_core->v__DOT__sdcard_controller__DOT__r_cmd_crc,
m_core->v__DOT__sdcard_controller__DOT__r_cmd_crc_cnt);
printf(" SPI(%d,%d,%d/%d,%d)->?",
m_core->o_sf_cs_n,
m_core->o_sd_cs_n,
m_core->o_spi_sck, m_core->v__DOT__sdcard_sck,
m_core->o_spi_mosi);
*/
 
/*
printf(" CK=%d,LN=%d",
m_core->v__DOT__sdcard_controller__DOT__r_sdspi_clk,
m_core->v__DOT__sdcard_controller__DOT__r_lgblklen);
*/
 
/*
if (m_core->v__DOT__sdcard_controller__DOT__r_use_fifo){
printf(" FIFO");
if (m_core->v__DOT__sdcard_controller__DOT__r_fifo_wr)
printf("-WR");
else
printf("-RD");
}
 
if (m_core->v__DOT__sdcard_controller__DOT__ll_fifo_rd)
printf(" LL-RD");
if (m_core->v__DOT__sdcard_controller__DOT__ll_fifo_wr)
printf(" LL-WR");
if (m_core->v__DOT__sdcard_controller__DOT__r_have_start_token)
printf(" START-TOK");
printf(" %3d", m_core->v__DOT__sdcard_controller__DOT__ll_fifo_addr);
*/
 
/*
printf(" DMAC[%d]: %08x/%08x/%08x(%03x) -- (%d,%d,%c)%c%c:@%08x-[%4d,%4d/%4d,%4d-#%4d]%08x",
m_core->v__DOT__zippy__DOT__dma_controller__DOT__dma_state,
m_core->v__DOT__zippy__DOT__dma_controller__DOT__cfg_waddr,
m_core->v__DOT__zippy__DOT__dma_controller__DOT__cfg_raddr,
m_core->v__DOT__zippy__DOT__dma_controller__DOT__cfg_len,
m_core->v__DOT__zippy__DOT__dma_controller__DOT__cfg_blocklen_sub_one,
m_core->v__DOT__zippy__DOT__dc_cyc,
// m_core->v__DOT__zippy__DOT__dc_stb,
(m_core->v__DOT__zippy__DOT__dma_controller__DOT__dma_state == 2)?1:0,
 
((m_core->v__DOT__zippy__DOT__dma_controller__DOT__dma_state == 4)
||(m_core->v__DOT__zippy__DOT__dma_controller__DOT__dma_state == 5)
||(m_core->v__DOT__zippy__DOT__dma_controller__DOT__dma_state == 6))?'W':'R',
//(m_core->v__DOT__zippy__DOT__dc_we)?'W':'R',
(m_core->v__DOT__zippy__DOT__dc_ack)?'A':' ',
(m_core->v__DOT__zippy__DOT__dc_stall)?'S':' ',
m_core->v__DOT__zippy__DOT__dc_addr,
m_core->v__DOT__zippy__DOT__dma_controller__DOT__rdaddr,
m_core->v__DOT__zippy__DOT__dma_controller__DOT__nread,
m_core->v__DOT__zippy__DOT__dma_controller__DOT__nracks,
m_core->v__DOT__zippy__DOT__dma_controller__DOT__nwacks,
m_core->v__DOT__zippy__DOT__dma_controller__DOT__nwritten,
m_core->v__DOT__zippy__DOT__dc_data);
 
printf(" %08x-PIC%08x",
m_core->v__DOT__zippy__DOT__main_int_vector,
m_core->v__DOT__zippy__DOT__pic_data);
*/
 
printf("\n"); fflush(stdout);
} m_last_writeout = writeout;
 
}
 
};
180,6 → 376,7
 
void busmaster_kill(int v) {
tb->kill();
fprintf(stderr, "KILLED!!\n");
exit(0);
}
 
190,6 → 387,7
// signal(SIGINT, busmaster_kill);
 
tb->reset();
tb->setsdcard("/dev/zero");
 
while(1)
tb->tick();
/cpp/sdspisim.cpp
0,0 → 1,450
///////////////////////////////////////////////////////////////////////////
//
//
// Filename: sdspisim.cpp
//
// Project: Wishbone Controlled SD-Card Controller over SPI port
//
// Purpose: This library simulates the operation of a SPI commanded SD-Card,
// such as might be found on a XuLA2-LX25 board made by xess.com.
//
// This simulator is for testing use in a Verilator/C++ environment, where
// it would be used in place of the actual hardware.
//
// Creator: Dan Gisselquist
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
 
#include "sdspisim.h"
 
static const unsigned
MICROSECONDS = 80, // Clocks in a microsecond
MILLISECONDS = MICROSECONDS * 1000,
tRESET = 4*MILLISECONDS; // Just a wild guess
/*
static const unsigned DEVID = 0x0115,
DEVESD = 0x014,
MICROSECONDS = 100,
MILLISECONDS = MICROSECONDS * 1000,
SECONDS = MILLISECONDS * 1000,
tW = 50 * MICROSECONDS, // write config cycle time
tBE = 32 * SECONDS,
tDP = 10 * SECONDS,
tRES = 30 * SECONDS,
// Shall we artificially speed up this process?
tPP = 12 * MICROSECONDS,
tSE = 15 * MILLISECONDS;
// or keep it at the original speed
// tPP = 1200 * MICROSECONDS,
// tSE = 1500 * MILLISECONDS;
*/
static const unsigned
CCS = 0; // 0: SDSC card, 1: SDHC or SDXC card
 
SDSPISIM::SDSPISIM(void) {
m_dev = NULL;
m_last_sck = 1;
m_block_address = (CCS==1);
m_host_supports_high_capacity = false;
m_powerup_busy = -1;
m_reset_state = SDSPI_POWERUP_RESET;
//
m_csd[ 0] = 0; // Normal SDcard, not high capacity
m_csd[ 1] = 0x0f;
m_csd[ 2] = 0x0f;
m_csd[ 3] = 0x32; // Can be either 0x32 (25MHz) or 0x5a (50MHz)
m_csd[ 4] = 0x5b; // Could also be 0x07b, if we supported more comands(?)
m_csd[ 5] = 0x59; // 9-> 2^9,or 512 bytes (10->1024, 11->2048, no othrs)
m_csd[ 6] = 0x00; // partial blocks allowed?
m_csd[ 7] = 0x00; // C_SIZE, 2'b00, then top 6 bits
m_csd[ 8] = 0; // C_SIZE, 22-bits, mid 8 bits
m_csd[ 9] = 0; // C_SIZE, 22-bits, bottom 8 bits
m_csd[10] = 0x7f;
m_csd[11] = 0x80;
m_csd[12] = 0x0a;
m_csd[13] = 0x40;
m_csd[14] = 0; // R/W: file format, copy, write protect, etc.
m_csd[15] = cmdcrc(15, m_csd);
 
// CID Register
m_cid[ 0] = 0xba;
m_cid[ 1] = 0xd0;
m_cid[ 2] = 0xda;
m_cid[ 3] = 0xdd;
m_cid[ 4] = 0;
m_cid[ 5] = 0xde;
m_cid[ 6] = 0xad;
m_cid[ 7] = 0xbe;
m_cid[ 8] = 0xef;
m_cid[ 9] = 0x20;
m_cid[10] = 0x16;
m_cid[11] = 0x05;
m_cid[12] = 0x26;
m_cid[13] = 0;
m_cid[14] = 0;
m_cid[15] = cmdcrc(15, m_cid);
 
// m_write_count = 0;
// m_ireg = m_oreg = 0;
// m_sreg = 0x01c;
// m_creg = 0x001; // Iinitial creg on delivery
}
 
void SDSPISIM::load(const char *fname) {
m_dev = fopen(fname, "r+b");
 
if (m_dev) {
unsigned long devln;
fseek(m_dev, 0l, SEEK_END);
devln = ftell(m_dev);
fseek(m_dev, 0l, SEEK_SET);
 
m_devblocks = devln>>9;
}
}
 
int SDSPISIM::operator()(const int csn, const int sck, const int mosi) {
// Keep track of a timer to determine when page program and erase
// cycles complete.
 
/*
if (m_write_count > 0) {
//
}
*/
 
m_delay++;
if (m_powerup_busy>0)
m_powerup_busy--;
 
if (csn) {
m_delay = 0;
m_cmdidx= 0;
m_rspidx= 0;
m_bitpos= 0;
m_delay = 0;
m_busy = false;
m_last_sck = sck;
m_syncd = false;
m_last_miso = 1;
m_dat_out = 0x0ff;
// Reset everything when not selected
return 0;
} else if (sck == m_last_sck) {
m_last_sck = sck;
return m_last_miso;
} else if (!m_last_sck) {
// Register our input on the rising edge
m_mosi = mosi;
m_syncd= true;
m_last_sck = sck;
return m_last_miso;
} if (!m_syncd) {
m_last_sck = sck;
return m_last_miso;
}
 
// Only change our output on the falling edge
 
m_last_sck = sck;
printf("SDSPI: (%3d) [%d,%d,%d] ", m_delay, csn, sck, m_mosi);
// assert(m_delay > 20);
 
m_bitpos++;
m_dat_in = (m_dat_in<<1)|m_mosi;
 
 
printf("(bitpos=%d,dat_in=%02x)\n", m_bitpos&7, m_dat_in&0x0ff);
 
if ((m_bitpos&7)==0) {
printf("SDSPI--RX BYTE %02x\n", m_dat_in&0x0ff);
m_dat_out = 0xff;
if (m_cmdidx < 6) {
printf("SDSPI: CMDIDX = %d\n", m_cmdidx);
// All commands *must* start with a 01... pair of bits.
if (m_cmdidx == 0)
assert((m_dat_in&0xc0)==0x40);
 
// Record the command for later processing
m_cmdbuf[m_cmdidx++] = m_dat_in;
} else if (m_cmdidx == 6) {
// We're going to start a response from here ...
m_rspidx = 0;
m_blkdly = 0;
m_blkidx = SDSPI_MAXBLKLEN;
printf("SDSPI: CMDIDX = %d -- WE HAVE A COMMAND! [ ", m_cmdidx);
for(int i=0; i<6; i++)
printf("%02x ", m_cmdbuf[i] & 0xff);
printf("]\n"); fflush(stdout);
 
unsigned arg;
arg = ((((((m_cmdbuf[1]<<8)|(m_cmdbuf[2]&0x0ff))<<8)
|(m_cmdbuf[3]&0x0ff))<<8)
|(m_cmdbuf[4]&0x0ff));
arg &= 0x0ffffffff;
 
// Check the CRC
if (!check_cmdcrc(m_cmdbuf)) {
assert(0 && "BAD CRC");
m_rspbuf[0] = 0x09;
m_rspdly = 1;
} else if (m_altcmd_flag) {
switch(m_cmdbuf[0]&0x03f) {
case 41: // ACMD41 -- SD_SEND_OP_COND
// and start initialization sequence
assert((m_reset_state == SDSPI_RCVD_CMD8)||(m_reset_state == SDSPI_RCVD_ACMD41)||(m_reset_state == SDSPI_RESET_COMPLETE));
if((unsigned)m_powerup_busy>tRESET)
m_powerup_busy = tRESET;
assert((arg&0x0bfffffff) == 0);
m_rspbuf[0] = (m_powerup_busy)?1:0;
m_rspdly = 2;
m_host_supports_high_capacity = (m_cmdbuf[1]&0x40)?1:0;
m_reset_state = (m_powerup_busy)?
SDSPI_RCVD_ACMD41
:SDSPI_RESET_COMPLETE;
break;
case 13: // ACMD13
case 22: // ACMD22
case 23: // ACMD23
case 42: // ACMD42
case 51: // ACMD51
default: // Unimplemented command!
m_rspbuf[0] = 0x04;
m_rspdly = 4;
fprintf(stderr, "SDSPI ERR: Alt command ACMD%d not implemented!\n", m_cmdbuf[0]&0x03f);
assert(0 && "Not Implemented");
} m_altcmd_flag = false;
} else {
m_altcmd_flag = false;
memset(m_rspbuf, 0x0ff, SDSPI_RSPLEN);
printf("SDSPI: Received a command 0x%02x (%d)\n",
m_cmdbuf[0], m_cmdbuf[0]&0x03f);
switch(m_cmdbuf[0]&0x3f) {
case 0: // CMD0 -- GO_IDLE_STATE
m_rspbuf[0] = 0x01;
m_rspdly = 4;
m_reset_state = SDSPI_CMD0_IDLE;
break;
case 1: // CMD1 -- SEND_OP_COND
assert((arg&0x0bfffffff) == 0);
m_rspbuf[0] = 0x02;
m_rspdly = 4;
m_host_supports_high_capacity = (m_cmdbuf[1]&0x40)?1:0;
break;
case 8: // CMD8 -- SEND_IF_COND
assert((arg&0x0fffff000) == 0);
m_rspbuf[0] = 0x00;
// See p82 for this format
m_rspbuf[1] = 0;
m_rspbuf[2] = 0;
// If we do not accept the voltage range
m_rspbuf[3] = 0;
// Now, check if we accept it
// We only accept 2.7-3.6V in this
// simulation.
if ((arg&0x0f00)==0x0100)
m_rspbuf[3] = 1;
m_rspbuf[4] = (char)(arg&0x0ff);
m_rspdly = 4;
assert((m_reset_state == SDSPI_CMD0_IDLE)||(m_reset_state == SDSPI_RCVD_CMD8));
m_reset_state = SDSPI_RCVD_CMD8;
break;
case 9: // CMD9 -- SEND_CSD
// Block read, returning start token,
// 16 bytes, then 2 crc bytes
assert(m_reset_state == SDSPI_IN_OPERATION);
m_rspbuf[0] = 0x00;
memset(m_block_buf, 0x0ff, SDSPI_MAXBLKLEN);
m_block_buf[0] = 0x0fe;
for(int j=0; j<16; j++)
m_block_buf[j+1] = m_csd[j];
m_blklen = 16;
add_block_crc(m_blklen, m_block_buf);
 
m_blkdly = 60;
m_blkidx = 0;
break;
case 10: // CMD10 -- SEND_CID
// Block read, returning start token,
// 16 bytes, then 2 crc bytes
assert(m_reset_state == SDSPI_IN_OPERATION);
m_rspbuf[0] = 0x00;
memset(m_block_buf, 0x0ff, SDSPI_MAXBLKLEN);
m_block_buf[0] = 0x0fe;
for(int j=0; j<16; j++)
m_block_buf[j+1] = m_cid[j];
m_blklen = 16;
add_block_crc(m_blklen, m_block_buf);
 
m_blkdly = 60;
m_blkidx = 0;
break;
case 13: // CMD13 -- SEND_STATUS
assert(m_reset_state == SDSPI_IN_OPERATION);
m_rspbuf[0] = 0x00;
m_rspbuf[1] = 0x00;
// if (m_wp_fault) m_rspbuf[1]|=0x20;
// if (m_err) m_rspbuf[1]|=0x04;
m_rspdly = 4;
break;
case 17: // CMD17 -- READ_SINGLE_BLOCK
assert(m_reset_state == SDSPI_IN_OPERATION);
m_rspbuf[0] = 0x00;
memset(m_block_buf, 0x0ff, SDSPI_MAXBLKLEN);
if (m_dev) {
if (m_block_address) {
assert(arg < m_devblocks);
fseek(m_dev, arg<<9, SEEK_SET);
} else {
assert(arg < m_devblocks<<9);
fseek(m_dev, arg, SEEK_SET);
}
} m_block_buf[0] = 0x0fe;
m_blklen = (1<<m_csd[5]);
if (m_dev)
fread(&m_block_buf[1], m_blklen, 1, m_dev);
else
memset(&m_block_buf[1], 0, m_blklen);
add_block_crc(m_blklen, m_block_buf);
 
m_blkdly = 60;
m_blkidx = 0;
break;
case 55: // CMD55 -- APP_CMD
m_rspbuf[0] = 0x00;
m_rspdly = 2;
m_altcmd_flag = true;
break;
case 58: // CMD58 -- READ_OCR, respond R7
// argument is stuff bits/dont care
m_rspbuf[0] = 0x00;
// See p112, Tbl 5-1 for this format
m_rspbuf[1] = ((m_powerup_busy)?0x80:0)
|(CCS?0x40:0);
m_rspbuf[2] = 0xff;// 2.7-3.6V supported
m_rspbuf[3] = 0x80;
m_rspbuf[4] = 0; // No low-voltage supt
m_rspdly = 4;
 
if (m_reset_state == SDSPI_RESET_COMPLETE)
m_reset_state = SDSPI_IN_OPERATION;
break;
case 6: // CMD6 -- SWITCH_FUNC
case 12: // CMD12 -- STOP_TRANSMISSION (!impl)
case 16: // CMD16 -- SET_BLOCKLEN
case 18: // CMD18 -- READ_MULTIPLE_BLOCK
case 24: // CMD24 -- WRITE_BLOCK
case 25: // CMD25 -- WRITE_MULTIPLE_BLOCK
case 27: // CMD27 -- PROGRAM_CSD
case 32: // CMD32 -- ERASE_WR_BLK_START_ADDR
case 33: // CMD33 -- ERASE_WR_BLK_END_ADDR
case 38: // CMD38 -- ERASE
case 56: // CMD56 -- GEN_CMD
default: // Unimplemented command
m_rspbuf[0] = 0x04;
m_rspdly = 4;
printf("SDSPI ERR: Command CMD%d not implemented!\n", m_cmdbuf[0]&0x03f);
fflush(stdout);
assert(0 && "Not Implemented");
}
} m_cmdidx++;
 
// If we are using blocks, add bytes for the start
// token and the two CRC bytes
m_blklen += 3;
} else if (m_rspdly > 0) {
assert((m_dat_in&0x0ff) == 0x0ff);
// A delay until a response is given
if (m_busy)
m_dat_out = 0;
m_rspdly--;
} else if (m_rspidx < SDSPI_RSPLEN) {
assert((m_dat_in&0x0ff) == 0x0ff);
m_dat_out = m_rspbuf[m_rspidx++];
} else if (m_blkdly > 0) {
assert((m_dat_in&0x0ff) == 0x0ff);
m_blkdly--;
} else if (m_blkidx < SDSPI_MAXBLKLEN) {
assert((m_dat_in&0x0ff) == 0x0ff);
m_dat_out = m_block_buf[m_blkidx++];
}
// else m_dat_out = 0x0ff; // So set already above
}
 
int result = (m_dat_out&0x80)?1:0;
m_dat_out <<= 1;
m_delay = 0;
m_last_miso = result;
fflush(stdout);
return result;
}
 
unsigned SDSPISIM::cmdcrc(int len, char *buf) const {
unsigned int fill = 0, taps = 0x12;
 
for(int i=0; i<len; i++) {
fill ^= buf[i];
for(int j=0; j<8; j++) {
if (fill&0x80)
fill = (fill<<1)^taps;
else
fill <<= 1;
}
}
 
fill &= 0x0fe; fill |= 1;
return fill;
}
 
bool SDSPISIM::check_cmdcrc(char *buf) const {
unsigned fill = cmdcrc(5, buf);
printf("SDSPI: CRC-CHECK, should have a CRC of %02x\n", fill);
return (fill == (buf[5]&0x0ff));
}
 
void SDSPISIM::add_block_crc(int len, char *buf) const {
unsigned int fill = 0, taps = 0x121;
 
for(int i=1; i<=len; i++) {
fill ^= (buf[i] << 8);
for(int j=0; j<8; j++) {
if (fill&0x8000)
fill = (fill<<1)^taps;
else
fill <<= 1;
}
}
 
buf[len+1] = (fill >> 8)&0x0ff;
buf[len+2] = (fill )&0x0ff;
}
 
/cpp/Makefile
1,4 → 1,47
################################################################################
##
## Filename: Makefile
##
## Project: XuLA2-LX25 SoC based upon the ZipCPU
##
## Purpose: To coordinate the build of a cycle accurate, Verilator based,
## simulation of the busmaster module. Access to the simulation
## is provided via the same software commands that will access the board,
## save that the parameters are a touch different. (See the access
## software for more information ...)
##
## Creator: Dan Gisselquist, Ph.D.
## Gisselquist Technology, LLC
##
################################################################################
##
## Copyright (C) 2015-2016, Gisselquist Technology, LLC
##
## This program is free software (firmware): you can redistribute it and/or
## modify it under the terms of the GNU General Public License as published
## by the Free Software Foundation, either version 3 of the License, or (at
## your option) any later version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with this program. (It's in the $(ROOT)/doc directory, run make with no
## target there if the PDF file isn't present.) If not, see
## <http://www.gnu.org/licenses/> for a copy.
##
## License: GPL, v3, as defined and found on www.gnu.org,
## http://www.gnu.org/licenses/gpl.html
##
##
################################################################################
##
##
.PHONY: all
# Make certain the "all" target is the first and therefore the default target
all:
CXX := g++
OBJDIR := obj-pc
YYMMDD := `date +%Y%m%d`
6,7 → 49,7
VROOT := /usr/share/verilator
VINC := -I$(VROOT)/include -I$(VOBJDR)
CFLAGS := -c -g -Wall -I. $(VINC)
#
# Now return to the "all" target, and fill in some details
all: $(OBJDIR)/ programs archive
 
# GFXFLAGS := `pkg-config gtkmm-3.0 --cflags`
22,10 → 65,12
$(OBJDIR)/:
@bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi"
 
$(OBJDIR)/sdramsim.o: sdramsim.cpp sdramsim.h
CLSHEADERS: qspiflashsim.h sdramsim.h sdspisim.h
CLSSOURCES: $(subst .h,.cpp,$(CLSHEADERS))
CLSOBJECTS: $(addprefix $(OBJDIR)/,$(subst .h,.o,$(CLSHEADERS)))
 
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CFLAGS) $< -o $@
$(OBJDIR)/qspiflashsim.o: qspiflashsim.cpp qspiflashsim.h
$(CXX) $(CFLAGS) $< -o $@
$(OBJDIR)/busmaster_tb.o: busmaster_tb.cpp pipecmdr.h sdramsim.h
$(OBJDIR)/busmaster_tb.o: port.h $(VOBJDR)/Vbusmaster.h
$(CXX) $(CFLAGS) busmaster_tb.cpp -o $@
32,12 → 77,30
$(OBJDIR)/verilated.o: $(VROOT)/include/verilated.cpp
$(CXX) $(CFLAGS) $< -o $@
 
busmaster_tb: $(OBJDIR)/qspiflashsim.o
busmaster_tb: $(OBJDIR)/qspiflashsim.o $(OBJDIR)/sdspisim.o
busmaster_tb: $(OBJDIR)/verilated.o
busmaster_tb: $(VOBJDR)/Vbusmaster__ALL.a
busmaster_tb: $(OBJDIR)/busmaster_tb.o $(OBJDIR)/sdramsim.o
$(CXX) -g -o $@ $^
 
define build-depends
@echo "Building dependency file"
@bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi"
@$(CXX) $(CPPFLAGS) -MM $(SOURCES) > $(OBJDIR)/xdepends.txt
@sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt > $(OBJDIR)/depends.txt
@rm $(OBJDIR)/xdepends.txt
endef
 
tags: $(SOURCES) $(HEADERS)
@echo "Generating tags"
@ctags $(SOURCES) $(HEADERS)
 
.PHONY: depends
depends: tags
$(build-depends)
 
.PHONY: archive
archive:
tar --transform s,^,$(YYMMDD)-bench-cpp/, -chjf $(YYMMDD)-bench-cpp.tjz Makefile *.cpp *.h
 
-include $(OBJDIR)/depends.txt

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.