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

Subversion Repositories xulalx25soc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /xulalx25soc
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/trunk/bench/asm/memtest.S
0,0 → 1,162
////////////////////////////////////////////////////////////////////////////////
//
// Filename: memtest.S
//
// Project: XuLA2 board
//
// Purpose: To test whether or not we can interface with the SDRAM on the
// XuLA2 board.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, 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.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#define LFSRFILL 0x000001
// #define LFSRTAPS 0x004597f
#define LFSRTAPS 0x0408b85
#define SDRAMBASE 0x0800000
// #define SDRAMLEN 0x0800000
#define SDRAMLEN 0x0800000
#define RAMSCOPE 0x011c
#define ZIPSCOPE 0x011e
master_entry:
MOV user_entry(PC),uPC
; LDI RAMSCOPE,R8
; LDI 0x04000000,R9
; STO R9,(R8)
RTU
; // Capture what just happened
; LDI 0x8c000000,R9
; STO R9,(R8)
; NOP
;
HALT
 
user_entry:
// #define CLEAR_MEMORY
#ifdef CLEAR_MEMORY
clear_memory:
LDI SDRAMBASE,R0
LDI SDRAMLEN,R1
ADD R0,R1
CLR R2
clear_memory_loop:
STO R2,(R0)
ADD 1,R0
CMP R0,R1
BGT clear_memory_loop
end_clear_memory:
#endif
 
LDI LFSRFILL,R2
LDI LFSRTAPS,R3
CLR R12
 
write_test:
LDI SDRAMBASE,R0
LDI SDRAMLEN,R1
MOV R2,R7 ; Copy our initial fill
CMP 0,R2
HALT.Z
// #define WAIT_FOR_WRITE_SCOPE
#ifdef WAIT_FOR_WRITE_SCOPE
LDI RAMSCOPE,R8
LDI 0x01ffc,R9
STO R9,(R8) ; Reset the SDRAM scope
NOP ; Give it a chance to reset
LDI 0x10000000,R10
scope_not_ready:
NOP
LOD (R8),R9
TST R10,R9
BZ scope_not_ready
#endif
 
write_test_loop:
LSR 1,R2
XOR.C R3,R2
MOV R2,R4
 
LSR 1,R2
XOR.C R3,R2
MOV R2,R5
 
LSR 1,R2
XOR.C R3,R2 ; wr_reg_ce = R2
 
STO R4,(R0) ; op = R4
STO R5,1(R0) ; dcdA = R5
STO R2,2(R0) ; instruction - R2
ADD 3,R0
SUB 3,R1
CMP 3,R1
BGE write_test_loop
 
read_test:
LDI SDRAMBASE,R0
LDI SDRAMLEN,R1
// #define WAIT_FOR_READ_SCOPE
#ifdef WAIT_FOR_READ_SCOPE
LDI RAMSCOPE,R8
LDI 0x01ffc,R9
STO R9,(R8) ; Reset the SDRAM scope
NOP ; Give it a chance to reset
LDI 0x10000000,R10
not_ready:
NOP
LOD (R8),R9
TST R10,R9
BZ not_ready
#endif
//
// RAM[49072] = 0x02b39ba ... not RAM[0]. What's going on here?
//
read_test_loop:
LOD (R0),R4
LOD 1(R0),R5
LOD 2(R0),R6
 
LSR 1,R7
XOR.C R3,R7
CMP R7,R4
TRAP.NZ 0
 
LSR 1,R7
XOR.C R3,R7
CMP R7,R5
TRAP.NZ 0
 
LSR 1,R7
XOR.C R3,R7
CMP R7,R6
TRAP.NZ 0
 
ADD 3,R0
SUB 3,R1
CMP 3,R1
 
BGE read_test_loop
 
ADD 1,R12
BRA write_test
/trunk/bench/asm/dev.i
0,0 → 1,21
dev.base equ 0x0100
dev.version equ 2
dev.pic equ 3
dev.buserr equ 4
dev.rtc.date equ 5
dev.gpio equ 6
dev.uart.ctrl equ 7
dev.pwm equ 8
dev.uart.rx equ 10
dev.uart.tx equ 11
dev.qspi equ 12
dev.rtc.clock equ 16
dev.rtc.timer equ 17
dev.rtc.stopwatch equ 18
dev.rtc.alarm equ 19
dev.fscope equ 0x01c
dev.ramscope equ 0x01e
dev.mem.base equ 0x0002000
dev.mem.last equ 0x0003fff
dev.flash.base equ 0x0040000
dev.sdram.base equ 0x0800000
/trunk/bench/asm/genlrs.S
0,0 → 1,72
////////////////////////////////////////////////////////////////////////////////
//
// Filename: genlrs.S
//
// Project: XuLA2 board
//
// Purpose:
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, 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.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
entry:
; ; R0 -- used by test_lrs
; ; R1 -- used by test_lrs
; ; R2 -- used by test_lrs
; ; R3 = return address
LDI 0x80000000,R4 ; Taps
LDI 0x00800000,R6 ; Current Memory Address
MOV R6,R7 ; Start of memory
LDI 0x00ffffff,R8 ; End of memory
test_next_lrs:
MOV __HERE__+2(PC),R3
BRA test_lrs
CMP 0,R0
BGE next_tap_set
STO R0,(R6)
ADD 1,R6
AND R8,R6
OR R7,R6
next_tap_set:
ADD 1,R4
BNZ test_next_lrs
HALT
 
test_lrs:
; R0 = taps on entry
; R0 = length on return
; R3 = return PC address
CLR R1 ; R1 will be our length
LDI 1,R2 ; R2 will be our fill
test_lrs_loop:
LSR 1,R2
XOR.C R0,R2
ADD 1,R1
CMP 1,R2
BNZ test_lrs_loop
MOV R1,R0
 
MOV R3,PC
/trunk/bench/asm/Makefile
0,0 → 1,62
################################################################################
##
## Filename: Makefile
##
## Project: XuLA2 board
##
## Purpose:
##
##
## Creator: Dan Gisselquist, Ph.D.
## Gisselquist Technology, LLC
##
################################################################################
##
## Copyright (C) 2015, 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.
##
## License: GPL, v3, as defined and found on www.gnu.org,
## http:##www.gnu.org/licenses/gpl.html
##
##
################################################################################
##
##
all: memtest.z
ZIPD := $(HOME)/work/rnd/zipcpu/trunk
ZASM := $(ZIPD)/sw/zasm/zasm
ZDUMP:= $(ZIPD)/sw/zasm/zdump
 
.PHONY: genlrs
genlrs: genlrs.z
genlrs.z: genlrs.S
$(ZASM) $< -o $@
genlrs.txt: genlrs.z
$(ZDUMP) $< > $@
 
.PHONY: cputest
cputest: cputest.z
cputest.z: cputest.S sys.i
$(ZASM) $< -o $@
cputest.txt: cputest.z
$(ZDUMP) $< > $@
 
.PHONY: memtest
memtest: memtest.z
memtest.z: memtest.S
$(ZASM) $< -o $@
memtest.txt: memtest.z
$(ZDUMP) $< > $@
 
.PHONY:
clean:
@rm memtest.z memtest.txt
/trunk/bench/cpp/sdramsim.cpp
0,0 → 1,226
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
 
#include "sdramsim.h"
 
short SDRAMSIM::operator()(int clk, int cke, int cs_n, int ras_n, int cas_n, int we_n,
int bs, unsigned addr, int driv, short data) {
short result = 0;
 
if (driv)
result = data;
else if (!clk)
return m_last_value;
if (!cke) {
fprintf(stderr, "This simulation only supports CKE high!\n");
fprintf(stderr, "\tCKE = %d\n", cke);
fprintf(stderr, "\tCS_n = %d\n", cs_n);
fprintf(stderr, "\tRAS_n = %d\n", ras_n);
fprintf(stderr, "\tCAS_n = %d\n", cas_n);
fprintf(stderr, "\tWE_n = %d\n", we_n);
assert(cke);
}
 
if (m_pwrup < POWERED_UP_STATE) {
if (m_clocks_till_idle > 0)
m_clocks_till_idle--;
if (m_pwrup == 0) {
assert((ras_n)&&(cas_n)&&(we_n));
if (m_clocks_till_idle == 0) {
m_pwrup++;
printf("Successful power up wait, moving to state #1\n");
}
} else if (m_pwrup == 1) {
if ((!cs_n)&&(!ras_n)&&(cas_n)&&(!we_n)&&(addr&0x0400)) {
// Wait until a precharge all banks command
m_pwrup++;
printf("Successful precharge command, moving to state #2\n");
m_clocks_till_idle = 8;
}
} else if (m_pwrup == 2) {
// Need 8 auto refresh cycles before or after the mode
// set command. We'll insist they be before.
if (m_clocks_till_idle == 0) {
m_pwrup++;
printf("Successful initial auto-refresh, waiting for mode-set\n");
for(int i=0; i<m_nrefresh; i++)
m_refresh_time[i] = MAX_REFRESH_TIME;
} else
assert((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n));
} else if (m_pwrup == 3) {
const int tRSC = 2;
if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(!we_n)){
// mode set
printf("Mode set: %08x\n", addr);
assert(addr == 0x021);
m_pwrup++;
printf("Successful mode set, moving to state #3, tRSC = %d\n", tRSC);
m_clocks_till_idle=tRSC;
}
} else if (m_pwrup == 4) {
assert(cs_n);
if (m_clocks_till_idle == 0) {
m_pwrup = POWERED_UP_STATE;
m_clocks_till_idle = 0;
printf("Successful settup! SDRAM switching to operational\n");
} else if (m_clocks_till_idle == 1) {
;
} else assert(0 && "Should never get here!");
} else if (m_pwrup == 5) {
if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n)) {
if (m_clocks_till_idle == 0) {
m_pwrup = POWERED_UP_STATE;
m_clocks_till_idle = 0;
 
for(int i=0; i<m_nrefresh; i++)
m_refresh_time[i] = MAX_REFRESH_TIME;
}
} else {
assert(0);
}
}
m_next_wr = false;
} else { // In operation ...
for(int i=0; i<m_nrefresh; i++)
m_refresh_time[i]--;
if (m_refresh_time[m_refresh_loc] < 0) {
assert(0 && "Failed refresh requirement");
} for(int i=0; i<NBANKS; i++) {
m_bank_status[i] >>= 1;
if (m_bank_status[i]&2)
m_bank_status[i] |= 4;
if (m_bank_status[i]&1) { // Bank is open
m_bank_open_time[i] --;
if (m_bank_open_time[i] < 0) {
assert(0 && "Bank held open too long");
}
}
}
 
if (m_clocks_till_idle)
m_clocks_till_idle--;
 
if (m_fail > 0) {
m_fail--;
if (m_fail == 0) {
fprintf(stderr, "Failing on schedule\n");
exit(-3);
}
}
 
if ((m_clocks_till_idle > 0)&&(m_next_wr)) {
printf("SDRAM[%08x] <= %04x\n", m_wr_addr, data & 0x0ffff);
m_mem[m_wr_addr++] = data;
result = data;
m_next_wr = false;
} else {
result = (driv)?data:m_qdata[m_qloc];
}
m_qloc = (m_qloc + 1)&m_qmask;
 
if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n)) {
// Auto-refresh command
m_refresh_time[m_refresh_loc] = MAX_REFRESH_TIME;
m_refresh_loc++;
if (m_refresh_loc >= m_nrefresh)
m_refresh_loc = 0;
assert((m_bank_status[0]&6) == 0);
assert((m_bank_status[1]&6) == 0);
assert((m_bank_status[2]&6) == 0);
assert((m_bank_status[3]&6) == 0);
} else if ((!cs_n)&&(!ras_n)&&(cas_n)&&(!we_n)) {
if (addr&0x0400) {
// Bank/Precharge All CMD
for(int i=0; i<NBANKS; i++)
m_bank_status[i] &= 0x03;
} else {
// Precharge/close single bank
assert(0 == (bs & (~3))); // Assert w/in bounds
m_bank_status[bs] &= 0x03; // Close the bank
 
printf("Precharging bank %d\n", bs);
}
} else if ((!cs_n)&&(!ras_n)&&(cas_n)&&(we_n)) {
printf("Activating bank %d\n", bs);
// Activate a bank!
if (0 != (bs & (~3))) {
m_fail = 2;
fprintf(stderr, "ERR: Activating a bank w/ more than 2 bits\n");
// assert(0 == (bs & (~3))); // Assert w/in bounds
} else if (m_bank_status[bs] != 0) {
fprintf(stderr, "ERR: Status of bank [bs=%d] = %d != 0\n",
bs, m_bank_status[bs]);
m_fail = 4;
// assert(m_bank_status[bs]==0); // Assert bank was closed
}
m_bank_status[bs] |= 4;
m_bank_open_time[bs] = MAX_BANKOPEN_TIME;
m_bank_row[bs] = addr;
} else if ((!cs_n)&&(ras_n)&&(!cas_n)) {
printf("R/W Op\n");
if (!we_n) {
// Initiate a write
assert(0 == (bs & (~3))); // Assert w/in bounds
assert(m_bank_status[bs]&1); // Assert bank is open
 
m_wr_addr = m_bank_row[bs];
m_wr_addr <<= 2;
m_wr_addr |= bs;
m_wr_addr <<= 9;
m_wr_addr |= (addr & 0x01ff);
 
assert(driv);
printf("SDRAM[%08x] <= %04x\n", m_wr_addr, data & 0x0ffff);
m_mem[m_wr_addr++] = data;
m_clocks_till_idle = 2;
m_next_wr = true;
 
if (addr & 0x0400) { // Auto precharge
m_bank_status[bs] &= 3;
m_bank_open_time[bs] = MAX_BANKOPEN_TIME;
}
} else { // Initiate a read
assert(0 == (bs & (~3))); // Assert w/in bounds
assert(m_bank_status[bs]&1); // Assert bank is open
 
unsigned rd_addr;
 
rd_addr = m_bank_row[bs] & 0x01fff;
rd_addr <<= 2;
rd_addr |= bs;
rd_addr <<= 9;
rd_addr |= (addr & 0x01ff);
 
assert(!driv);
printf("SDRAM.Q %04x <= SDRAM[%08x]\n",
m_mem[rd_addr] & 0x0ffff, rd_addr);
m_qdata[(m_qloc+1)&m_qmask] = m_mem[rd_addr++];
printf("SDRAM.Q %04x <= SDRAM[%08x]\n",
m_mem[rd_addr] & 0x0ffff, rd_addr);
m_qdata[(m_qloc+2)&m_qmask] = m_mem[rd_addr++];
m_clocks_till_idle = 2;
 
if (addr & 0x0400) { // Auto precharge
m_bank_status[bs] &= 3;
m_bank_open_time[bs] = MAX_BANKOPEN_TIME;
}
}
} else if (cs_n) {
// Chips not asserted, DESELECT CMD equivalent of a NOOP
} else if ((ras_n)&&(cas_n)&&(we_n)) {
// NOOP command
} else {
fprintf(stderr, "Unrecognized memory command!\n");
fprintf(stderr, "\tCS_n = %d\n", cs_n);
fprintf(stderr, "\tRAS_n = %d\n", ras_n);
fprintf(stderr, "\tCAS_n = %d\n", cas_n);
fprintf(stderr, "\tWE_n = %d\n", we_n);
assert(0 && "Unrecognizned command");
}
}
 
return result & 0x0ffff;
}
 
 
/trunk/bench/cpp/pipecmdr.cpp
0,0 → 1,107
//
//
// Filename: pipecmdr.cpp
//
// Project: FPGA testbench utilities.
//
// 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.
//
// Creator: Dan Gisselquist
// Gisselquist Tecnology, LLC
//
// Copyright: 2015
//
//
 
class PIPECMDR {
public:
int m_skt, m_con;
char m_txbuf[256], m_rxbuf[256];
int m_ilen, m_rxpos, m_txpos;
 
setup_listener(port);
UARTIPCMDR(const int port) {
setup_listener(port);
}
 
void tick(void) {
if (m_fd <= 0) {
// Can we accept a connection?
struct pollfd pb;
 
pb.fd = m_skt;
pb.events = POLLIN;
poll(&pb, 1, 0);
 
if (pb.revents & POLLIN) {
m_fd = accept(m_skt, 0, 0);
}
}
 
m_core->i_uart_rd = 0;
if (m_ilen > 0) {
// Is there a byte in our buffer somewhere?
m_core->i_uart_rd = 1;
m_core->i_uart_data = m_rxbuf[m_pos++];
m_ilen--;
} else if (m_fd > 0) {
// Is there a byte to be read here?
struct pollfd pb;
pb.fd = m_fd;
pb.events = POLLIN;
poll(&pb, 1, 0);
if (pb.revents & POLLIN) {
char buf[2];
if ((m_ilen =recv(m_fd, m_rxbuf, sizeof(m_rxbuf), MSG_DONTWAIT)) > 0) {
m_core->i_uart_rd = 1;
m_core->i_uart_data = m_rxbuf[0];
m_pos = 1; m_ilen--;
} else { // the connection closed on us
close(m_fd);
m_fd = -1;
}
}
}
 
tick();
 
if ((m_core->o_uart_tx)&&(m_fd > 0)) {
m_txbuf[m_txpos++] = m_core->o_uart_data;
if ((m_core->o_uart_data == '\n')||(m_txpos >= sizeof(m_txbuf))) {
send(m_fd, m_txbuf, m_txpos, 0);
m_txpos = 0;
}
}
}
};
 
void PIPECMDR::setup_listener(void) {
printf("Listening on port %d\n", PORT);
 
m_skt = socket(AF_INET, SOCK_STREAM, 0);
 
{
int optval = 1, er;
er = setsockopt(m_skt, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if (er != 0) {
perror("SockOpt Err: ");
exit(-2);
}
}
 
memset(&my_addr, 0, sizeof(struct sockaddr_un)); // clear structure
my-addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
my_addr.sin_port = htons(PORT);
 
bind(m_skt, (SA *)&my_addr, sizeof(my_addr));
listen(m_skt, 1);
}
 
/trunk/bench/cpp/qspiflashsim.cpp
0,0 → 1,470
///////////////////////////////////////////////////////////////////////////
//
//
// Filename: spiflashsim.cpp
//
// Project: Wishbone Controlled Quad SPI Flash Controller
//
// Purpose: This library simulates the operation of a Quad-SPI commanded
// flash, such as the S25FL032P used on the Basys-3 development
// board by Digilent. As such, it is defined by 32 Mbits of
// memory (4 Mbyte).
//
// This simulator is useful for testing in a Verilator/C++
// environment, where this simulator can be used in place of
// the actual hardware.
//
// Creator: Dan Gisselquist
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, 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 "qspiflashsim.h"
 
#define MEMBYTES (1<<22)
 
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;
 
QSPIFLASHSIM::QSPIFLASHSIM(void) {
m_mem = new char[MEMBYTES];
m_pmem = new char[256];
m_state = QSPIF_IDLE;
m_last_sck = 1;
m_write_count = 0;
m_ireg = m_oreg = 0;
m_sreg = 0x01c;
m_creg = 0x001; // Iinitial creg on delivery
m_quad_mode = false;
m_mode_byte = 0;
 
memset(m_mem, 0x0ff, MEMBYTES);
}
 
void QSPIFLASHSIM::load(const char *fname) {
FILE *fp;
int nr = 0;
 
if (NULL != (fp = fopen(fname, "r"))) {
nr = fread(m_mem, sizeof(char), MEMBYTES, fp);
fclose(fp);
} else {
fprintf(stderr, "SPI-FLASH: Could not open %s\n", fname);
perror("O/S Err:");
}
 
for(int i=nr; i<MEMBYTES; i++)
m_mem[i] = 0x0ff;
}
 
#define QOREG(A) m_oreg = ((m_oreg & (~0x0ff))|(A&0x0ff))
 
int QSPIFLASHSIM::operator()(const int csn, const int sck, const int dat) {
// Keep track of a timer to determine when page program and erase
// cycles complete.
 
if (m_write_count > 0) {
if (0 == (--m_write_count)) {// When done with erase/page pgm,
m_sreg &= 0x0fc; // Clear the write in progress bit
if (m_debug) printf("Write complete, clearing WIP (inside SIM)\n");
}
}
 
if (csn) {
m_last_sck = 1;
m_ireg = 0; m_oreg = 0;
m_count= 0;
 
if ((QSPIF_PP == m_state)||(QSPIF_QPP == m_state)) {
// Start a page program
if (m_debug) printf("QSPI: Page Program write cycle begins\n");
if (m_debug) printf("CK = %d & 7 = %d\n", m_count, m_count & 0x07);
if (m_debug) printf("QSPI: pmem = %08lx\n", (unsigned long)m_pmem);
m_write_count = tPP;
m_state = QSPIF_IDLE;
m_sreg &= (~QSPIF_WEL_FLAG);
m_sreg |= (QSPIF_WIP_FLAG);
for(int i=0; i<256; i++) {
/*
if (m_debug) printf("%02x: m_mem[%02x] = %02x &= %02x = %02x\n",
i, (m_addr&(~0x0ff))+i,
m_mem[(m_addr&(~0x0ff))+i]&0x0ff, m_pmem[i]&0x0ff,
m_mem[(m_addr&(~0x0ff))+i]& m_pmem[i]&0x0ff);
*/
m_mem[(m_addr&(~0x0ff))+i] &= m_pmem[i];
}
m_quad_mode = false;
} else if (m_state == QSPIF_SECTOR_ERASE) {
if (m_debug) printf("Actually Erasing sector, from %08x\n", m_addr);
m_write_count = tSE;
m_state = QSPIF_IDLE;
m_sreg &= (~QSPIF_WEL_FLAG);
m_sreg |= (QSPIF_WIP_FLAG);
m_addr &= (-1<<16);
for(int i=0; i<(1<<16); i++)
m_mem[m_addr + i] = 0x0ff;
if (m_debug) printf("Now waiting %d ticks delay\n", m_write_count);
} else if (QSPIF_WRSR == m_state) {
if (m_debug) printf("Actually writing status register\n");
m_write_count = tW;
m_state = QSPIF_IDLE;
m_sreg &= (~QSPIF_WEL_FLAG);
m_sreg |= (QSPIF_WIP_FLAG);
} else if (QSPIF_CLSR == m_state) {
if (m_debug) printf("Actually clearing the status register bits\n");
m_state = QSPIF_IDLE;
m_sreg &= 0x09f;
} else if (m_state == QSPIF_BULK_ERASE) {
m_write_count = tBE;
m_state = QSPIF_IDLE;
m_sreg &= (~QSPIF_WEL_FLAG);
m_sreg |= (QSPIF_WIP_FLAG);
for(int i=0; i<MEMBYTES; i++)
m_mem[i] = 0x0ff;
} else if (m_state == QSPIF_DEEP_POWER_DOWN) {
m_write_count = tDP;
m_state = QSPIF_IDLE;
} else if (m_state == QSPIF_RELEASE) {
m_write_count = tRES;
m_state = QSPIF_IDLE;
} else if (m_state == QSPIF_QUAD_READ_CMD) {
if ((m_mode_byte & 0x0f0)!=0x0a0)
m_quad_mode = false;
else
m_state = QSPIF_QUAD_READ_IDLE;
} else if (m_state == QSPIF_QUAD_READ) {
if ((m_mode_byte & 0x0f0)!=0x0a0)
m_quad_mode = false;
else
m_state = QSPIF_QUAD_READ_IDLE;
} else if (m_state == QSPIF_QUAD_READ_IDLE) {
}
 
m_oreg = 0x0fe;
return dat;
} else if ((!m_last_sck)||(sck == m_last_sck)) {
// Only change on the falling clock edge
// printf("SFLASH-SKIP, CLK=%d -> %d\n", m_last_sck, sck);
m_last_sck = sck;
if (m_quad_mode)
return (m_oreg>>8)&0x0f;
else
// return ((m_oreg & 0x0100)?2:0) | (dat & 0x0d);
return (m_oreg & 0x0100)?2:0;
}
 
// We'll only get here if ...
// last_sck = 1, and sck = 0, thus transitioning on the
// negative edge as with everything else in this interface
if (m_quad_mode) {
m_ireg = (m_ireg << 4) | (dat & 0x0f);
m_count+=4;
m_oreg <<= 4;
} else {
m_ireg = (m_ireg << 1) | (dat & 1);
m_count++;
m_oreg <<= 1;
}
 
 
// printf("PROCESS, COUNT = %d, IREG = %02x\n", m_count, m_ireg);
if (m_state == QSPIF_QUAD_READ_IDLE) {
assert(m_quad_mode);
if (m_count == 24) {
if (m_debug) printf("QSPI: Entering from Quad-Read Idle to Quad-Read\n");
if (m_debug) printf("QSPI: QI/O Idle Addr = %02x\n", m_ireg&0x0ffffff);
m_addr = (m_ireg) & 0x0ffffff;
assert((m_addr & 0xfc00000)==0);
m_state = QSPIF_QUAD_READ;
} m_oreg = 0;
} else if (m_count == 8) {
QOREG(0x0a5);
// printf("SFLASH-CMD = %02x\n", m_ireg & 0x0ff);
// Figure out what command we've been given
if (m_debug) printf("SPI FLASH CMD %02x\n", m_ireg&0x0ff);
switch(m_ireg & 0x0ff) {
case 0x01: // Write status register
if (2 !=(m_sreg & 0x203)) {
if (m_debug) printf("QSPI: WEL not set, cannot write status reg\n");
m_state = QSPIF_INVALID;
} else
m_state = QSPIF_WRSR;
break;
case 0x02: // Page program
if (2 != (m_sreg & 0x203)) {
if (m_debug) printf("QSPI: Cannot program at this time, SREG = %x\n", m_sreg);
m_state = QSPIF_INVALID;
} else {
m_state = QSPIF_PP;
if (m_debug) printf("PAGE-PROGRAM COMMAND ACCEPTED\n");
}
break;
case 0x03: // Read data bytes
// Our clock won't support this command, so go
// to an invalid state
if (m_debug) printf("QSPI INVALID: This sim does not support slow reading\n");
m_state = QSPIF_INVALID;
break;
case 0x04: // Write disable
m_state = QSPIF_IDLE;
m_sreg &= (~QSPIF_WEL_FLAG);
break;
case 0x05: // Read status register
m_state = QSPIF_RDSR;
if (m_debug) printf("QSPI: READING STATUS REGISTER: %02x\n", m_sreg);
QOREG(m_sreg);
break;
case 0x06: // Write enable
m_state = QSPIF_IDLE;
m_sreg |= QSPIF_WEL_FLAG;
if (m_debug) printf("QSPI: WRITE-ENABLE COMMAND ACCEPTED\n");
break;
case 0x0b: // Here's the read that we support
if (m_debug) printf("QSPI: FAST-READ (single-bit)\n");
m_state = QSPIF_FAST_READ;
break;
case 0x30:
if (m_debug) printf("QSPI: CLEAR STATUS REGISTER COMMAND\n");
m_state = QSPIF_CLSR;
break;
case 0x32: // QUAD Page program, 4 bits at a time
if (2 != (m_sreg & 0x203)) {
if (m_debug) printf("QSPI: Cannot program at this time, SREG = %x\n", m_sreg);
m_state = QSPIF_INVALID;
} else {
m_state = QSPIF_QPP;
if (m_debug) printf("QSPI: QUAD-PAGE-PROGRAM COMMAND ACCEPTED\n");
if (m_debug) printf("QSPI: pmem = %08lx\n", (unsigned long)m_pmem);
}
break;
case 0x35: // Read configuration register
m_state = QSPIF_RDCR;
if (m_debug) printf("QSPI: READING CONFIGURATION REGISTER: %02x\n", m_creg);
QOREG(m_creg);
break;
case 0x9f: // Read ID
m_state = QSPIF_RDID;
if (m_debug) printf("QSPI: READING ID, %02x\n", (DEVID>>24)&0x0ff);
QOREG(0xfe);
break;
case 0xab: // Release from DEEP POWER DOWN
if (m_sreg & QSPIF_DEEP_POWER_DOWN_FLAG) {
if (m_debug) printf("QSPI: Release from deep power down\n");
m_sreg &= (~QSPIF_DEEP_POWER_DOWN_FLAG);
m_write_count = tRES;
} m_state = QSPIF_RELEASE;
break;
case 0xb9: // DEEP POWER DOWN
if (0 != (m_sreg & 0x01)) {
if (m_debug) printf("QSPI: Cannot enter DEEP POWER DOWN, in middle of write/erase\n");
m_state = QSPIF_INVALID;
} else {
m_sreg |= QSPIF_DEEP_POWER_DOWN_FLAG;
m_state = QSPIF_IDLE;
}
break;
case 0xc7: // Bulk Erase
if (2 != (m_sreg & 0x203)) {
if (m_debug) printf("QSPI: WEL not set, cannot erase device\n");
m_state = QSPIF_INVALID;
} else
m_state = QSPIF_BULK_ERASE;
break;
case 0xd8: // Sector Erase
if (2 != (m_sreg & 0x203)) {
if (m_debug) printf("QSPI: WEL not set, cannot erase sector\n");
m_state = QSPIF_INVALID;
} else {
m_state = QSPIF_SECTOR_ERASE;
if (m_debug) printf("QSPI: SECTOR_ERASE COMMAND\n");
}
break;
case 0x0eb: // Here's the (other) read that we support
// printf("QSPI: QUAD-I/O-READ\n");
m_state = QSPIF_QUAD_READ_CMD;
m_quad_mode = true;
break;
default:
printf("QSPI: UNRECOGNIZED SPI FLASH CMD: %02x\n", m_ireg&0x0ff);
m_state = QSPIF_INVALID;
assert(0 && "Unrecognized command\n");
break;
}
} else if ((0 == (m_count&0x07))&&(m_count != 0)) {
QOREG(0);
switch(m_state) {
case QSPIF_IDLE:
printf("TOO MANY CLOCKS, SPIF in IDLE\n");
break;
case QSPIF_WRSR:
if (m_count == 16) {
m_sreg = (m_sreg & 0x061) | (m_ireg & 0x09c);
if (m_debug) printf("Request to set sreg to 0x%02x\n",
m_ireg&0x0ff);
} else if (m_count == 24) {
m_creg = (m_creg & 0x0fd) | (m_ireg & 0x02);
if (m_debug) printf("Request to set creg to 0x%02x\n",
m_ireg&0x0ff);
} else {
printf("TOO MANY CLOCKS FOR WRR!!!\n");
exit(-2);
m_state = QSPIF_IDLE;
}
break;
case QSPIF_CLSR:
assert(0 && "Too many clocks for CLSR command!!\n");
break;
case QSPIF_RDID:
if (m_count == 32) {
m_addr = m_ireg & 0x0ffffff;
if (m_debug) printf("READID, ADDR = %08x\n", m_addr);
QOREG((DEVID>>8));
if (m_debug) printf("QSPI: READING ID, %02x\n", (DEVID>>8)&0x0ff);
} else if (m_count > 32) {
if (((m_count-32)>>3)&1)
QOREG((DEVID));
else
QOREG((DEVID>>8));
if (m_debug) printf("QSPI: READING ID, %02x -- DONE\n", 0x00);
}
// m_oreg = (DEVID >> (2-(m_count>>3)-1)) & 0x0ff;
break;
case QSPIF_RDSR:
// printf("Read SREG = %02x, wait = %08x\n", m_sreg,
// m_write_count);
QOREG(m_sreg);
break;
case QSPIF_RDCR:
if (m_debug) printf("Read CREG = %02x\n", m_creg);
QOREG(m_creg);
break;
case QSPIF_FAST_READ:
if (m_count == 32) {
m_addr = m_ireg & 0x0ffffff;
if (m_debug) printf("FAST READ, ADDR = %08x\n", m_addr);
QOREG(0x0c3);
assert((m_addr & 0xfc00000)==0);
} else if ((m_count >= 40)&&(0 == (m_sreg&0x01))) {
if (m_count == 40)
printf("DUMMY BYTE COMPLETE ...\n");
QOREG(m_mem[m_addr++]);
// if (m_debug) printf("SPIF[%08x] = %02x\n", m_addr-1, m_oreg);
} else m_oreg = 0;
break;
case QSPIF_QUAD_READ_CMD:
// The command to go into quad read mode took 8 bits
// that changes the timings, else we'd use quad_Read
// below
if (m_count == 32) {
m_addr = m_ireg & 0x0ffffff;
// printf("FAST READ, ADDR = %08x\n", m_addr);
// printf("QSPI: QUAD READ, ADDR = %06x\n", m_addr);
assert((m_addr & 0xfc00000)==0);
} else if (m_count == 32+24) {
m_mode_byte = (m_ireg>>16) & 0x0ff;
// printf("QSPI: MODE BYTE = %02x\n", m_mode_byte);
} else if ((m_count > 32+24)&&(0 == (m_sreg&0x01))) {
QOREG(m_mem[m_addr++]);
// printf("QSPIF[%08x]/QR = %02x\n",
// m_addr-1, m_oreg);
} else m_oreg = 0;
break;
case QSPIF_QUAD_READ:
if (m_count == 32) {
m_mode_byte = (m_ireg & 0x0ff);
// printf("QSPI/QR: MODE BYTE = %02x\n", m_mode_byte);
} else if ((m_count >= 32+16)&&(0 == (m_sreg&0x01))) {
QOREG(m_mem[m_addr++]);
// printf("QSPIF[%08x]/QR = %02x\n", m_addr-1, m_oreg & 0x0ff);
} else m_oreg = 0;
break;
case QSPIF_PP:
if (m_count == 32) {
m_addr = m_ireg & 0x0ffffff;
if (m_debug) printf("QSPI: PAGE-PROGRAM ADDR = %06x\n", m_addr);
assert((m_addr & 0xfc00000)==0);
// m_page = m_addr >> 8;
for(int i=0; i<256; i++)
m_pmem[i] = 0x0ff;
} else if (m_count >= 40) {
m_pmem[m_addr & 0x0ff] = m_ireg & 0x0ff;
// printf("QSPI: PMEM[%02x] = 0x%02x -> %02x\n", m_addr & 0x0ff, m_ireg & 0x0ff, (m_pmem[(m_addr & 0x0ff)]&0x0ff));
m_addr = (m_addr & (~0x0ff)) | ((m_addr+1)&0x0ff);
} break;
case QSPIF_QPP:
if (m_count == 32) {
m_addr = m_ireg & 0x0ffffff;
m_quad_mode = true;
if (m_debug) printf("QSPI/QR: PAGE-PROGRAM ADDR = %06x\n", m_addr);
assert((m_addr & 0xfc00000)==0);
// m_page = m_addr >> 8;
for(int i=0; i<256; i++)
m_pmem[i] = 0x0ff;
} else if (m_count >= 40) {
m_pmem[m_addr & 0x0ff] = m_ireg & 0x0ff;
// printf("QSPI/QR: PMEM[%02x] = 0x%02x -> %02x\n", m_addr & 0x0ff, m_ireg & 0x0ff, (m_pmem[(m_addr & 0x0ff)]&0x0ff));
m_addr = (m_addr & (~0x0ff)) | ((m_addr+1)&0x0ff);
} break;
case QSPIF_SECTOR_ERASE:
if (m_count == 32) {
m_addr = m_ireg & 0x0ffc000;
if (m_debug) printf("SECTOR_ERASE ADDRESS = %08x\n", m_addr);
assert((m_addr & 0xfc00000)==0);
} break;
case QSPIF_RELEASE:
if (m_count >= 32) {
QOREG(DEVESD);
} break;
default:
break;
}
} // else printf("SFLASH->count = %d\n", m_count);
 
m_last_sck = sck;
if (m_quad_mode)
return (m_oreg>>8)&0x0f;
else
// return ((m_oreg & 0x0100)?2:0) | (dat & 0x0d);
return (m_oreg & 0x0100)?2:0;
}
 
/trunk/bench/cpp/sdramsim.h
0,0 → 1,57
#ifndef SDRAMSIM_H
 
#define NBANKS 4
#define POWERED_UP_STATE 6
#define CLK_RATE_HZ 100000000 // = 100 MHz = 100 * 10^6
#define PWRUP_WAIT_CKS ((int)(.000200 * CLK_RATE_HZ))
#define MAX_BANKOPEN_TIME ((int)(.000100 * CLK_RATE_HZ))
#define MAX_REFRESH_TIME ((int)(.064 * CLK_RATE_HZ))
 
class SDRAMSIM {
int m_pwrup;
short *m_mem;
short m_last_value, m_qmem[4];
int m_bank_status[NBANKS];
int m_bank_row[NBANKS];
int m_bank_open_time[NBANKS];
unsigned *m_refresh_time;
int m_refresh_loc, m_nrefresh;
int m_qloc, m_qdata[8], m_qmask, m_wr_addr;
int m_clocks_till_idle;
bool m_next_wr;
unsigned m_fail;
public:
SDRAMSIM(void) {
m_mem = new short[(1<<24)]; // 32 MB, or 16 Mshorts
 
m_refresh_time = new unsigned[(1<<13)];
for(int i=0; i<m_nrefresh; i++)
m_refresh_time[i] = 0;
m_refresh_loc = 0;
 
m_pwrup = 0;
m_clocks_till_idle = 0;
 
m_last_value = 0;
m_clocks_till_idle = PWRUP_WAIT_CKS;
m_wr_addr = 0;
 
m_qloc = 0;
m_qmask = 7;
 
m_next_wr = true;
m_fail = 0;
}
 
~SDRAMSIM(void) {
delete m_mem;
}
 
short operator()(int clk, int cke,
int cs_n, int ras_n, int cas_n, int we_n, int bs,
unsigned addr,
int driv, short data);
int pwrup(void) const { return m_pwrup; }
};
 
#endif
/trunk/bench/cpp/testb.h
0,0 → 1,70
////////////////////////////////////////////////////////////////////////////////
//
// Filename: testb.h
//
// Project: Zip CPU -- a small, lightweight, RISC CPU core
//
// Purpose: A wrapper for a common interface to a clocked FPGA core
// begin exercised in Verilator.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Tecnology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, 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 TESTB_H
#define TESTB_H
 
template <class VA> class TESTB {
public:
VA *m_core;
unsigned long m_tickcount;
 
TESTB(void) { m_core = new VA; }
~TESTB(void) { delete m_core; m_core = NULL; }
 
virtual void eval(void) {
m_core->eval();
}
 
virtual void tick(void) {
m_core->i_clk = 1;
eval();
m_core->i_clk = 0;
eval();
 
m_tickcount++;
}
 
virtual void reset(void) {
m_core->i_rst = 1;
tick();
m_core->i_rst = 0;
m_tickcount = 0l;
// printf("RESET\n");
}
};
 
#endif
/trunk/bench/cpp/usbi.h
0,0 → 1,70
link ../../sw/usbi.h
trunk/bench/cpp/usbi.h Property changes : Added: svn:special ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/bench/cpp/pipecmdr.h =================================================================== --- trunk/bench/cpp/pipecmdr.h (nonexistent) +++ trunk/bench/cpp/pipecmdr.h (revision 4) @@ -0,0 +1,217 @@ +// +// +// Filename: pipecmdr.h +// +// Project: FPGA testbench utilities. +// +// 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. +// +// Creator: Dan Gisselquist +// Gisselquist Tecnology, LLC +// +// Copyright: 2015 +// +// +#ifndef PIPECMDR_H +#define PIPECMDR_H + +#include +#include +#include +#include +#include + +#include "testb.h" + +#define PIPEBUFLEN 256 + +// At 115200 Baud, 8 bits of data, no parity and one stop bit, there will +// bit ten bits per character and therefore 8681 clocks per transfer +// 8681 ~= 100 MHz / 115200 (bauds / second) * 10 bauds / character +// +// #define UARTLEN 8681 // Minimum ticks per character, 115200 Baud +// +// At 4MBaud, each bit takes 25 clocks. 10 bits would thus take 250 clocks +// +#define UARTLEN 250 // Minimum ticks per character, 4M Baud +// #define UARTLEN 8 // Minimum ticks per character + +template class PIPECMDR : public TESTB { + void setup_listener(const int port) { + struct sockaddr_in my_addr; + + printf("Listening on port %d\n", port); + + m_skt = socket(AF_INET, SOCK_STREAM, 0); + if (m_skt < 0) { + perror("Could not allocate socket: "); + exit(-1); + } + + // Set the reuse address option + { + int optv = 1, er; + er = setsockopt(m_skt, SOL_SOCKET, SO_REUSEADDR, &optv, sizeof(optv)); + if (er != 0) { + perror("SockOpt Err:"); + exit(-1); + } + } + + memset(&my_addr, 0, sizeof(struct sockaddr_in)); // clear structure + my_addr.sin_family = AF_INET; + my_addr.sin_addr.s_addr = htonl(INADDR_ANY); + my_addr.sin_port = htons(port); + + if (bind(m_skt, (struct sockaddr *)&my_addr, sizeof(my_addr))!=0) { + perror("BIND FAILED:"); + exit(-1); + } + + if (listen(m_skt, 1) != 0) { + perror("Listen failed:"); + exit(-1); + } + } + +public: + int m_skt, m_con; + char m_txbuf[PIPEBUFLEN], m_rxbuf[PIPEBUFLEN]; + int m_ilen, m_rxpos, m_txpos, m_uart_wait; + bool m_started_flag; + + PIPECMDR(const int port) : TESTB() { + m_con = m_skt = -1; + setup_listener(port); + m_rxpos = m_txpos = m_ilen = 0; + m_started_flag = false; + m_uart_wait = 0; + } + + virtual void kill(void) { + // Close any active connection + if (m_con >= 0) close(m_con); + if (m_skt >= 0) close(m_skt); + } + + virtual void tick(void) { + if (m_con < 0) { + // Can we accept a connection? + struct pollfd pb; + + pb.fd = m_skt; + pb.events = POLLIN; + poll(&pb, 1, 0); + + if (pb.revents & POLLIN) { + m_con = accept(m_skt, 0, 0); + + if (m_con < 0) + perror("Accept failed:"); + } + } + + TESTB::m_core->i_rx_stb = 0; + + if (m_uart_wait == 0) { + if (m_ilen > 0) { + // Is there a byte in our buffer somewhere? + TESTB::m_core->i_rx_stb = 1; + TESTB::m_core->i_rx_data = m_rxbuf[m_rxpos++]; + m_ilen--; + } else if (m_con > 0) { + // Is there a byte to be read here? + struct pollfd pb; + pb.fd = m_con; + pb.events = POLLIN; + if (poll(&pb, 1, 0) < 0) + perror("Polling error:"); + if (pb.revents & POLLIN) { + if ((m_ilen =recv(m_con, m_rxbuf, sizeof(m_rxbuf), MSG_DONTWAIT)) > 0) { + m_rxbuf[m_ilen] = '\0'; + if (m_rxbuf[m_ilen-1] == '\n') { + m_rxbuf[m_ilen-1] = '\0'; + printf("< \'%s\'\n", m_rxbuf); + m_rxbuf[m_ilen-1] = '\n'; + } else printf("< \'%s\'\n", m_rxbuf); + TESTB::m_core->i_rx_stb = 1; + TESTB::m_core->i_rx_data = m_rxbuf[0]; + m_rxpos = 1; m_ilen--; + m_started_flag = true; + } else if (m_ilen < 0) { + // An error occurred, close the connection + perror("Read error: "); + fprintf(stderr, "Closing connection\n"); + close(m_con); + m_con = -1; + } else { // the connection closed on us + close(m_con); + m_con = -1; + } + } + } m_uart_wait = (TESTB::m_core->i_rx_stb)?UARTLEN:0; + } else { + // Still working on transmitting a character + m_uart_wait = m_uart_wait - 1; + } + + /* + if (TESTB::m_core->i_rx_stb) { + putchar(TESTB::m_core->i_rx_data); + fflush(stdout); + } + */ + TESTB::tick(); + + if ((TESTB::m_core->o_tx_stb)&&(m_con > 0)) { + m_txbuf[m_txpos++] = TESTB::m_core->o_tx_data; + if ((TESTB::m_core->o_tx_data == '\n')||(m_txpos >= sizeof(m_txbuf))) { + int snt = 0; + snt = send(m_con, m_txbuf, m_txpos, 0); + + m_txbuf[m_txpos] = '\0'; + printf("> %s", m_txbuf); + if (snt < m_txpos) { + fprintf(stderr, "Only sent %d bytes!\n", + snt); + } + m_txpos = 0; + } + } + + /* + if((TESTB::m_core->o_wb_cyc)||(TESTB::m_core->o_wb_stb)){ + printf("BUS: %d,%d,%d %8x %8x\n", + TESTB::m_core->o_wb_cyc, + TESTB::m_core->o_wb_stb, + TESTB::m_core->o_wb_we, + TESTB::m_core->o_wb_addr, + TESTB::m_core->o_wb_data); + } else if (m_started_flag) { + printf("%02x,%c,%d,%d,%02x -> %d,%d,%d, %2x,%2x,%2x\n", + TESTB::m_core->i_rx_data, + (TESTB::m_core->i_rx_stb)?(TESTB::m_core->i_rx_data):' ', + TESTB::m_core->v__DOT__decodewb__DOT__r_valid, + TESTB::m_core->v__DOT__decodewb__DOT__rx_eol, + TESTB::m_core->v__DOT__decodewb__DOT__rx_six_bits, + // + TESTB::m_core->v__DOT__decodewb__DOT__o_rq_strobe, + TESTB::m_core->v__DOT__decodewb__DOT__o_rq_hold, + TESTB::m_core->v__DOT__decodewb__DOT__o_rq_we, + // + TESTB::m_core->v__DOT__decodewb__DOT__state, + TESTB::m_core->v__DOT__decodewb__DOT__nreg, + TESTB::m_core->v__DOT__decodewb__DOT__szreg); + } + */ + } +}; + +#endif Index: trunk/bench/cpp/qspiflashsim.h =================================================================== --- trunk/bench/cpp/qspiflashsim.h (nonexistent) +++ trunk/bench/cpp/qspiflashsim.h (revision 4) @@ -0,0 +1,81 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Filename: spiflashsim.h +// +// Project: Wishbone Controlled Quad SPI Flash Controller +// +// Purpose: This library simulates the operation of a Quad-SPI commanded +// flash, such as the S25FL032P used on the Basys-3 development +// board by Digilent. As such, it is defined by 32 Mbits of +// memory (4 Mbyte). +// +// Creator: Dan Gisselquist +// Gisselquist Technology, LLC +// +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015, 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 +// for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +/////////////////////////////////////////////////////////////////////////// +#ifndef QSPIFLASHSIM_H +#define QSPIFLASHSIM_H + +#define QSPIF_WIP_FLAG 0x0001 +#define QSPIF_WEL_FLAG 0x0002 +#define QSPIF_DEEP_POWER_DOWN_FLAG 0x0200 +class QSPIFLASHSIM { + typedef enum { + QSPIF_IDLE, + QSPIF_QUAD_READ_IDLE, + QSPIF_RDSR, + QSPIF_RDCR, + QSPIF_WRSR, + QSPIF_CLSR, + QSPIF_RDID, + QSPIF_RELEASE, + QSPIF_FAST_READ, + QSPIF_QUAD_READ_CMD, + QSPIF_QUAD_READ, + QSPIF_SECTOR_ERASE, + QSPIF_PP, + QSPIF_QPP, + QSPIF_BULK_ERASE, + QSPIF_DEEP_POWER_DOWN, + QSPIF_INVALID + } QSPIF_STATE; + + QSPIF_STATE m_state; + char *m_mem, *m_pmem; + int m_last_sck; + unsigned m_write_count, m_ireg, m_oreg, m_sreg, m_addr, + m_count, m_config, m_mode_byte, m_creg; + bool m_quad_mode, m_debug; + +public: + QSPIFLASHSIM(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); +}; + +#endif Index: trunk/bench/cpp/port.h =================================================================== --- trunk/bench/cpp/port.h (nonexistent) +++ trunk/bench/cpp/port.h (revision 4) @@ -0,0 +1 @@ +link ../../sw/port.h \ No newline at end of file
trunk/bench/cpp/port.h Property changes : Added: svn:special ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/bench/cpp/busmaster_tb.cpp =================================================================== --- trunk/bench/cpp/busmaster_tb.cpp (nonexistent) +++ trunk/bench/cpp/busmaster_tb.cpp (revision 4) @@ -0,0 +1,217 @@ +// +// +// Filename: busmaster_tb.cpp +// +// Project: FPGA library development (XuLA2 development board) +// +// 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. +// +// Creator: Dan Gisselquist +// Gisselquist Tecnology, LLC +// +// Copyright: 2015 +// +// +#include +#include + +#include "verilated.h" +#include "Vbusmaster.h" + +#include "testb.h" +// #include "twoc.h" +#include "pipecmdr.h" +#include "qspiflashsim.h" +#include "sdramsim.h" + +#include "port.h" + +// Add a reset line, since Vbusmaster doesn't have one +class Vbusmasterr : public Vbusmaster { +public: + int i_rst; + virtual ~Vbusmasterr() {} +}; + +// No particular "parameters" need definition or redefinition here. +class BUSMASTER_TB : public PIPECMDR { +public: + unsigned long m_tx_busy_count; + QSPIFLASHSIM m_flash; + SDRAMSIM m_sdram; + unsigned m_last_led; + time_t m_start_time; + + BUSMASTER_TB(void) : PIPECMDR(FPGAPORT) { + m_start_time = time(NULL); + } + + void reset(void) { + m_core->i_clk = 1; + m_core->eval(); + } + + void tick(void) { + if ((m_tickcount & ((1<<28)-1))==0) { + double ticks_per_second = m_tickcount; + ticks_per_second /= (double)(time(NULL) - m_start_time); + printf(" ******** %.6f TICKS PER SECOND\n", + ticks_per_second); + } + + // 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; + 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, + m_core->o_ram_we_n, m_core->o_ram_bs, + m_core->o_ram_addr, m_core->o_ram_drive_data, + m_core->o_ram_data); + PIPECMDR::tick(); + + bool writeout = false; + /* + if (m_core->v__DOT__runio__DOT__themouse__DOT__driver__DOT__rx_stb) + writeout = true; + else if (m_core->v__DOT__runio__DOT__themouse__DOT__driver__DOT__ps2iface__DOT__state != m_last_ps2_state) + writeout = true; + else if (m_core->v__DOT__runio__DOT__themouse__DOT__m_state != m_last_mouse_state) + writeout = true; + else if (m_core->i_ps2 != m_last_ps2) + writeout = true; + else if (m_core->o_ps2 != m_last_ops2) + writeout = true; + else if (m_core->v__DOT__runio__DOT__themouse__DOT__driver__DOT__ps2_perr) + writeout = true; + else if (m_core->v__DOT__runio__DOT__themouse__DOT__driver__DOT__ps2_ferr) + writeout = true; + */ + // if ((m_core->v__DOT__genbus__DOT__runwb__DOT__o_wb_cyc)||(m_core->v__DOT__bus_cyc)) + // writeout = true; + // else if (m_last_cyc) + // writeout = true; + if ((m_tickcount > 0x5010)&&(m_core->v__DOT__sdram__DOT__r_state != 0)) + writeout = true; + else if ((m_core->v__DOT__dwb_cyc)&&((m_core->v__DOT__wb_stb) + ||(m_core->v__DOT__dwb_stall) + ||(m_core->v__DOT__dwb_ack))) + writeout = true; + else if (m_core->v__DOT__dwb_cyc) + writeout = true; + else if (m_core->v__DOT__sdram__DOT__need_refresh) + writeout = true; + else if ((m_core->v__DOT__wbu_cyc)&&((m_core->v__DOT__wbu_addr == 0x106)||(m_core->v__DOT__wbu_addr == 0x0107))) + writeout = true; + if (m_tickcount < 0x05010) + writeout = false; + if (writeout) { + printf("%08lx:", m_tickcount); + + printf("(%d,%d->%d),(%d,%d->%d)|%c[%08x/%08x]@%08x %d%d%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_stb, + // 0, // m_core->v__DOT__dwb_stb, // was zip_stb + m_core->v__DOT__zippy__DOT__thecpu__DOT__mem_stb_gbl, + m_core->v__DOT__wb_stb, + // + (m_core->v__DOT__wb_we)?'W':'R', + 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__wb_err)?'E':'.'); + + 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, + m_core->o_ram_cas_n, m_core->o_ram_we_n, + m_core->o_ram_bs, m_core->o_ram_data, + (m_core->o_ram_drive_data)?'D':'-', + m_core->o_ram_addr, + (m_core->o_ram_addr>>10)&1, + m_core->i_ram_data, + (m_core->o_ram_drive_data)?'-':'V'); + + printf(" SD[%d,%d-%3x%d]", + m_core->v__DOT__sdram__DOT__r_state, + m_sdram.pwrup(), + m_core->v__DOT__sdram__DOT__refresh_clk, + m_core->v__DOT__sdram__DOT__need_refresh); + + printf(" BNK[%d:%6x,%d:%6x,%d:%6x,%d:%6x],%x%d", + m_core->v__DOT__sdram__DOT__bank_active[0], + m_core->v__DOT__sdram__DOT__bank_row[0], + m_core->v__DOT__sdram__DOT__bank_active[1], + m_core->v__DOT__sdram__DOT__bank_row[1], + m_core->v__DOT__sdram__DOT__bank_active[2], + m_core->v__DOT__sdram__DOT__bank_row[2], + m_core->v__DOT__sdram__DOT__bank_active[3], + m_core->v__DOT__sdram__DOT__bank_row[3], + m_core->v__DOT__sdram__DOT__clocks_til_idle, + m_core->v__DOT__sdram__DOT__r_barrell_ack); + + printf(" %s%s%c[%08x@%06x]", + (m_core->v__DOT__sdram__DOT__bus_cyc)?"C":" ", + (m_core->v__DOT__sdram__DOT__r_pending)?"PND":" ", + (m_core->v__DOT__sdram__DOT__r_we)?'W':'R', + (m_core->v__DOT__sdram__DOT__r_data), + (m_core->v__DOT__sdram__DOT__r_addr)); + + printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%2x", + (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__cmd_halt)?"H":"-", + (m_core->v__DOT__zippy__DOT__thecpu__DOT__pf_cyc)?"P":"-", + (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__dcdvalid)?"D":"-", + (m_core->v__DOT__zippy__DOT__thecpu__DOT__dcd_ce)?"k":"-", + (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__new_pc)?"N":"-", + (m_core->v__DOT__zippy__DOT__thecpu__DOT__clear_pipeline)?"C":"-", + (m_core->v__DOT__zippy__DOT__cmd_addr)); + + printf("\n"); + } + + } + +}; + +BUSMASTER_TB *tb; + +void busmaster_kill(int v) { + tb->kill(); + exit(0); +} + +int main(int argc, char **argv) { + Verilated::commandArgs(argc, argv); + tb = new BUSMASTER_TB; + + // signal(SIGINT, busmaster_kill); + + tb->reset(); + + while(1) + tb->tick(); + + exit(0); +} + Index: trunk/bench/cpp/Makefile =================================================================== --- trunk/bench/cpp/Makefile (nonexistent) +++ trunk/bench/cpp/Makefile (revision 4) @@ -0,0 +1,43 @@ +.PHONY: all +CXX := g++ +OBJDIR := obj-pc +YYMMDD := `date +%Y%m%d` +VOBJDR := ../../rtl/obj_dir +VROOT := /usr/share/verilator +VINC := -I$(VROOT)/include -I$(VOBJDR) +CFLAGS := -c -g -Wall -I. $(VINC) +# +all: $(OBJDIR)/ programs archive + +# GFXFLAGS := `pkg-config gtkmm-3.0 --cflags` +# GFXLIBS := `pkg-config gtkmm-3.0 --cflags --libs` + +.PHONY: programs +programs: busmaster_tb + +.PHONY: clean +clean: + rm -f busmaster_rb $(OBJDIR)/*.o + +$(OBJDIR)/: + @bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi" + +$(OBJDIR)/sdramsim.o: sdramsim.cpp sdramsim.h + $(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 $@ +$(OBJDIR)/verilated.o: $(VROOT)/include/verilated.cpp + $(CXX) $(CFLAGS) $< -o $@ + +busmaster_tb: $(OBJDIR)/qspiflashsim.o +busmaster_tb: $(OBJDIR)/verilated.o +busmaster_tb: $(VOBJDR)/Vbusmaster__ALL.a +busmaster_tb: $(OBJDIR)/busmaster_tb.o $(OBJDIR)/sdramsim.o + $(CXX) -g -o $@ $^ + +.PHONY: archive +archive: + tar --transform s,^,$(YYMMDD)-bench-cpp/, -chjf $(YYMMDD)-bench-cpp.tjz Makefile *.cpp *.h

powered by: WebSVN 2.1.0

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