2
0
mirror of https://github.com/m-labs/artiq.git synced 2024-12-24 19:04:02 +08:00

Remove UP support.

The only advantage of UP is to support the Papilio Pro, but that port is also very limited in other ways and the Pipistrello provides a more reasonable platform that also supports AMP.

On the other hand, RPCs on UP are difficult to implement with the session.c protocol system (without an operating system or coroutines), along with many other minor difficulties and maintainance issues. Planned features such as watchdogs in the core device are also difficult on UP.
This commit is contained in:
Sebastien Bourdeauducq 2015-04-27 20:43:45 +08:00
parent 1ca49787b4
commit 938e1c2842
14 changed files with 51 additions and 379 deletions

View File

@ -1,9 +1,11 @@
#!/bin/bash
set -e
ARTIQ_PREFIX=$(python3 -c "import artiq; print(artiq.__path__[0])")
# Default is ppro
BOARD=ppro
# Default is kc705
BOARD=kc705
while getopts "bBrht:d:" opt
do
@ -21,15 +23,12 @@ do
if [ "$OPTARG" == "kc705" ]
then
BOARD=kc705
elif [ "$OPTARG" == "ppro" ]
then
BOARD=ppro
elif [ "$OPTARG" == "pipistrello" ]
then
BOARD=pipistrello
else
echo "Supported targets (-t option) are:"
echo "kc705, ppro, or pipistrello"
echo "kc705 or pipistrello"
exit 1
fi
;;
@ -47,12 +46,12 @@ do
echo ""
echo "To flash everything, do not use any of the -b|-B|-r option."
echo ""
echo "usage: $0 [-b] [-B] [-r] [-h] [-t kc705|ppro|pipistrello] [-d path]"
echo "usage: $0 [-b] [-B] [-r] [-h] [-t kc705|pipistrello] [-d path]"
echo "-b Flash bitstream"
echo "-B Flash BIOS"
echo "-r Flash ARTIQ runtime"
echo "-h Show this help message"
echo "-t Target (kc705, pipistrello, ppro, default is: ppro)"
echo "-t Target (kc705, pipistrello, default is: kc705)"
echo "-d Directory containing the binaries to be flashed"
exit 1
;;
@ -88,27 +87,7 @@ then
BIN_PREFIX=$BIN_PATH
fi
if [ "$BOARD" == "ppro" ]
then
UDEV_RULES=99-ppro.rules
BITSTREAM=artiq_ppro-up-papilio_pro.bin
CABLE=papilio
PROXY=bscan_spi_lx9_papilio.bit
BIOS_ADDR=0x60000
RUNTIME_ADDR=0x70000
if [ -z "$BIN_PREFIX" ]; then BIN_PREFIX=$ARTIQ_PREFIX/binaries/ppro; fi
search_for_proxy $PROXY
elif [ "$BOARD" == "pipistrello" ]
then
UDEV_RULES=99-ppro.rules
BITSTREAM=artiq_pipistrello-amp-pipistrello.bin
CABLE=papilio
PROXY=bscan_spi_lx9_csg324.bit
BIOS_ADDR=0x170000
RUNTIME_ADDR=0x180000
if [ -z "$BIN_PREFIX" ]; then BIN_PREFIX=$ARTIQ_PREFIX/binaries/pipistrello; fi
search_for_proxy $PROXY
elif [ "$BOARD" == "kc705" ]
if [ "$BOARD" == "kc705" ]
then
UDEV_RULES=99-kc705.rules
BITSTREAM=artiq_kc705-artiqsocbasic-kc705.bit
@ -118,6 +97,16 @@ then
RUNTIME_ADDR=0xb00000
if [ -z "$BIN_PREFIX" ]; then BIN_PREFIX=$ARTIQ_PREFIX/binaries/kc705; fi
search_for_proxy $PROXY
elif [ "$BOARD" == "pipistrello" ]
then
UDEV_RULES=99-papilio.rules
BITSTREAM=artiq_pipistrello-amp-pipistrello.bin
CABLE=papilio
PROXY=bscan_spi_lx9_csg324.bit
BIOS_ADDR=0x170000
RUNTIME_ADDR=0x180000
if [ -z "$BIN_PREFIX" ]; then BIN_PREFIX=$ARTIQ_PREFIX/binaries/pipistrello; fi
search_for_proxy $PROXY
fi
# Check if neither of -b|-B|-r have been used

View File

@ -6,12 +6,12 @@ KC705
The main target board for the ARTIQ core device is the KC705 development board from Xilinx.
Papilio Pro
Pipistrello
-----------
The low-cost Papilio Pro FPGA board can be used with some limitations.
The low-cost Pipistrello FPGA board can be used as a lower-cost but slower alternative.
When plugged to an adapter, the NIST QC1 hardware can be used with a limited number of TTL channels. The TTL lines are mapped to RTIO channels as follows:
When plugged to an adapter, the NIST QC1 hardware can be used. The TTL lines are mapped to RTIO channels as follows:
+--------------+----------+-----------------+
| RTIO channel | TTL line | Capability |
@ -20,19 +20,13 @@ When plugged to an adapter, the NIST QC1 hardware can be used with a limited num
+--------------+----------+-----------------+
| 1 | PMT1 | Input only |
+--------------+----------+-----------------+
| 2 | TTL0 | Output only |
| 2-18 | TTL0-16 | Output only |
+--------------+----------+-----------------+
| 3 | TTL1 | Output only |
| 19-21 | LEDs | Output only |
+--------------+----------+-----------------+
| 4 | TTL2 | Output only |
+--------------+----------+-----------------+
| 5 | TTL3 | Output only |
+--------------+----------+-----------------+
| 6 | TTL4 | Output only |
+--------------+----------+-----------------+
| 7 | FUD | DDS driver only |
| 22 | TTL2 | Output only |
+--------------+----------+-----------------+
The input only limitation on channels 0 and 1 comes from the QC-DAQ adapter. When the adapter is not used (and physically unplugged from the Papilio Pro board), the corresponding pins on the Papilio Pro can be used as outputs. Do not configure these channels as outputs when the adapter is plugged, as this would cause electrical contention.
The input only limitation on channels 0 and 1 comes from the QC-DAQ adapter. When the adapter is not used (and physically unplugged from the Pipistrello board), the corresponding pins on the Pipistrello can be used as outputs. Do not configure these channels as outputs when the adapter is plugged, as this would cause electrical contention.
The board can accept an external RTIO clock connected to XTRIG.
The board can accept an external RTIO clock connected to PMT2.

View File

@ -100,7 +100,7 @@ Create a new file ``rtio.py`` containing the following: ::
delay(2*us)
Connect an oscilloscope or logic analyzer to TTL0 (pin C11 on the Papilio Pro) and run ``artiq_run.py led.py``. Notice that the generated signal's period is precisely 4 microseconds, and that it has a duty cycle of precisely 50%. This is not what you would expect if the delay and the pulse were implemented with CPU-controlled GPIO: overhead from the loop management, function calls, etc. would increase the signal's period, and asymmetry in the overhead would cause duty cycle distortion.
Connect an oscilloscope or logic analyzer to TTL0 (pin C11 on the Pipistrello) and run ``artiq_run.py led.py``. Notice that the generated signal's period is precisely 4 microseconds, and that it has a duty cycle of precisely 50%. This is not what you would expect if the delay and the pulse were implemented with CPU-controlled GPIO: overhead from the loop management, function calls, etc. would increase the signal's period, and asymmetry in the overhead would cause duty cycle distortion.
Instead, inside the core device, output timing is generated by the gateware and the CPU only programs switching commands with certain timestamps that the CPU computes. This guarantees precise timing as long as the CPU can keep generating timestamps that are increasing fast enough. In case it fails to do that (and attempts to program an event with a timestamp in the past), the :class:`artiq.coredevice.runtime_exceptions.RTIOUnderflow` exception is raised. The kernel causing it may catch it (using a regular ``try... except...`` construct), or it will be propagated to the host.
@ -138,7 +138,7 @@ Try the following code and observe the generated pulses on a 2-channel oscillosc
self.ttl1.pulse(4*us)
delay(4*us)
TTL1 is assigned to the pin C10 of the Papilio Pro. The name of the attributes (``ttl0`` and ``ttl1``) is used to look up hardware in the device database.
TTL1 is assigned to the pin C10 of the Pipistrello. The name of the attributes (``ttl0`` and ``ttl1``) is used to look up hardware in the device database.
Within a parallel block, some statements can be made sequential again using a ``with sequential`` construct. Observe the pulses generated by this code: ::

View File

@ -8,9 +8,9 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
* Install the FPGA vendor tools (e.g. Xilinx ISE and/or Vivado):
* Get Xilinx tools from http://www.xilinx.com/support/download/index.htm. ISE can build bitstreams both for boards using the Spartan-6 (Papilio Pro) and 7-series devices (KC705), while Vivado supports only boards using 7-series devices.
* Get Xilinx tools from http://www.xilinx.com/support/download/index.htm. ISE can build bitstreams both for boards using the Spartan-6 (Pipistrello) and 7-series devices (KC705), while Vivado supports only boards using 7-series devices.
* The Papilio Pro is supported by Webpack, the KC705 is not.
* The Pipistrello is supported by Webpack, the KC705 is not.
* During the Xilinx toolchain installation, uncheck ``Install cable drivers`` (they are not required as we use better and open source alternatives).
@ -52,7 +52,7 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
$ make -j4
$ sudo make install
* Install JTAG tools needed to program Papilio Pro and KC705:
* Install JTAG tools needed to program the Pipistrello and KC705:
::
@ -69,14 +69,14 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
The purpose of the flash proxy bitstream is to give programming software fast JTAG access to the flash connected to the FPGA.
* Papilio Pro:
* Pipistrello:
::
$ cd ~/artiq-dev
$ git clone https://github.com/GadgetFactory/Papilio-Loader
$ wget http://www.phys.ethz.ch/~robertjo/bscan_spi_lx45_csg324.bit
Then copy ``~/artiq-dev/Papilio-Loader/xc3sprog/trunk/bscan_spi/bscan_spi_lx9_papilio.bit`` to ``~/.migen``, ``/usr/local/share/migen`` or ``/usr/share/migen``.
Then copy ``~/artiq-dev/bscan_spi_lx45_csg324.bit`` to ``~/.migen``, ``/usr/local/share/migen`` or ``/usr/share/migen``.
* KC705:
@ -107,9 +107,9 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
* Then, build and flash the ARTIQ runtime: ::
$ cd ~/artiq-dev/artiq/soc/runtime && make runtime.fbi
$ ~/artiq-dev/artiq/artiq/frontend/artiq_flash.sh -t ppro -d $PWD -r
$ ~/artiq-dev/artiq/artiq/frontend/artiq_flash.sh -t pipistrello -d $PWD -r
.. note:: The `-t` option specifies the board your are targeting. Available options are `ppro` for Papilio Pro, `kc705` for KC705 and `pipistrello` for Pipistrello.
.. note:: The `-t` option specifies the board your are targeting. Available options are ``kc705`` and ``pipistrello``.
* Check that the board boots by running a serial terminal program (you may need to press its FPGA reconfiguration button or power-cycle it to load the bitstream that was newly written into the flash): ::
@ -192,7 +192,7 @@ This command installs all the required packages: ::
Note that ARTIQ requires Python 3.4 or above.
To set user permissions on the JTAG and serial ports of the Papilio Pro, create a ``/etc/udev/rules.d/30-usb-papilio-pro.rules`` file containing the following: ::
To set user permissions on the JTAG and serial ports of the Pipistrello, create a ``/etc/udev/rules.d/30-usb-papilio.rules`` file containing the following: ::
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", GROUP="dialout"

View File

@ -1,24 +1,7 @@
include $(MSCDIR)/software/common.mak
OBJECTS := isr.o flash_storage.o elf_loader.o services.o session.o log.o test_mode.o kloader.o main.o
OBJECTS_KSUPPORT := exception_jmp.o exceptions.o rtio.o dds.o
# NOTE: this does not handle dependencies well. Run "make clean"
# when switching between UP and AMP.
UNIPROCESSOR := $(shell printf "\#include <generated/csr.h>\nCSR_KERNEL_CPU_BASE" | $(CC_normal) $(CFLAGS) -E - | tail -n 1 | grep -c CSR_KERNEL_CPU_BASE)
ifeq ($(UNIPROCESSOR),0)
OBJECTS += mailbox.o ksupport_data.o
OBJECTS_KSUPPORT += mailbox.o bridge.o ksupport.o
CFLAGS += -DARTIQ_AMP
SERVICE_TABLE_INPUT = ksupport.elf
else
ifeq ($(UNIPROCESSOR),1)
OBJECTS += $(OBJECTS_KSUPPORT)
else
$(error failed to determine UP/AMP build)
endif
endif
OBJECTS := isr.o flash_storage.o elf_loader.o services.o session.o log.o test_mode.o kloader.o mailbox.o ksupport_data.o main.o
OBJECTS_KSUPPORT := ksupport.o exception_jmp.o exceptions.o mailbox.o bridge.o rtio.o dds.o
CFLAGS += -Ilwip/src/include -Iliblwip
@ -57,8 +40,8 @@ ksupport.elf: $(OBJECTS_KSUPPORT)
ksupport_data.o: ksupport.bin
$(LD) -r -b binary -o $@ $<
service_table.h: $(SERVICE_TABLE_INPUT) gen_service_table.py
@echo " GEN " $@ && ./gen_service_table.py $(SERVICE_TABLE_INPUT) > $@
service_table.h: ksupport.elf gen_service_table.py
@echo " GEN " $@ && ./gen_service_table.py ksupport.elf > $@
services.c: service_table.h

View File

@ -2,6 +2,8 @@
import sys
from elftools.elf.elffile import ELFFile
services = [
("syscalls", [
@ -24,17 +26,7 @@ services = [
]
def print_up():
for name, contents in services:
print("static const struct symbol {}[] = {{".format(name))
for name, value in contents:
print(" {{\"{}\", {}}},".format(name, value))
print(" {NULL, NULL}")
print("};")
def print_amp(ksupport_elf_filename):
from elftools.elf.elffile import ELFFile
def print_service_table(ksupport_elf_filename):
with open(ksupport_elf_filename, "rb") as f:
elf = ELFFile(f)
symtab = elf.get_section_by_name(b".symtab")
@ -50,10 +42,8 @@ def print_amp(ksupport_elf_filename):
def main():
if len(sys.argv) == 1:
print_up()
elif len(sys.argv) == 2:
print_amp(sys.argv[1])
if len(sys.argv) == 2:
print_service_table(sys.argv[1])
else:
print("Incorrect number of command line arguments")
sys.exit(1)

View File

@ -49,12 +49,10 @@ static int symtab_add(const char *name, void *target)
int kloader_load(void *buffer, int length)
{
#ifdef ARTIQ_AMP
if(!kernel_cpu_reset_read()) {
log("BUG: attempted to load while kernel CPU running");
return 0;
}
#endif
symtab_init();
return load_elf(
resolve_service_symbol, symtab_add,
@ -66,8 +64,6 @@ kernel_function kloader_find(const char *name)
return find_symbol(symtab, name);
}
#ifdef ARTIQ_AMP
extern char _binary_ksupport_bin_start;
extern char _binary_ksupport_bin_end;
@ -107,5 +103,3 @@ void kloader_stop_kernel(void)
{
kernel_cpu_reset_write(1);
}
#endif

View File

@ -9,11 +9,9 @@ typedef void (*kernel_function)(void);
int kloader_load(void *buffer, int length);
kernel_function kloader_find(const char *name);
#ifdef ARTIQ_AMP
void kloader_start_bridge(void);
void kloader_start_idle_kernel(void);
void kloader_start_user_kernel(kernel_function k);
void kloader_stop_kernel(void);
#endif
#endif /* __KLOADER_H */

View File

@ -3,15 +3,8 @@
#include <generated/csr.h>
#ifdef ARTIQ_AMP
#include "mailbox.h"
#include "messages.h"
#else
#include <system.h>
#include "exceptions.h"
#include "rtio.h"
#include "dds.h"
#endif
#include "log.h"
#include "kloader.h"
@ -73,18 +66,14 @@ void session_start(void)
buffer_out_index_data = 0;
buffer_out_index_mem = 0;
memset(&buffer_out[4], 0, 4);
#ifdef ARTIQ_AMP
kloader_stop_kernel();
#endif
user_kernel_state = USER_KERNEL_NONE;
}
void session_end(void)
{
#ifdef ARTIQ_AMP
kloader_stop_kernel();
kloader_start_idle_kernel();
#endif
}
/* host to device */
@ -204,53 +193,6 @@ static int send_rpc_request(int rpc_num, va_list args)
return 1;
}
#ifndef ARTIQ_AMP
static int rpc_reply_eid;
static int rpc_reply_retval;
int rpc(int rpc_num, ...)
{
va_list args;
va_start(args, rpc_num);
send_rpc_request(rpc_num, args);
va_end(args);
user_kernel_state = USER_KERNEL_WAIT_RPC;
/*while(user_kernel_state == USER_KERNEL_WAIT_RPC)
comm_service();*/
if(rpc_reply_eid != EID_NONE)
exception_raise(rpc_reply_eid);
return rpc_reply_retval;
}
/* assumes output buffer is empty when called */
static void run_kernel_up(kernel_function k)
{
void *jb;
int eid;
long long eparams[3];
jb = exception_push();
if(exception_setjmp(jb)) {
eid = exception_getid(eparams);
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_EXCEPTION;
memcpy(&buffer_out[9], &eid, 4);
memcpy(&buffer_out[13], eparams, 3*8);
submit_output(9+4+3*8);
} else {
dds_init();
rtio_init();
flush_cpu_icache();
k();
exception_pop(1);
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_FINISHED;
submit_output(9);
}
}
#endif /* !ARTIQ_AMP */
static int process_input(void)
{
switch(buffer_in[8]) {
@ -321,35 +263,22 @@ static int process_input(void)
break;
}
#ifdef ARTIQ_AMP
kloader_start_user_kernel(k);
user_kernel_state = USER_KERNEL_RUNNING;
#else
user_kernel_state = USER_KERNEL_RUNNING;
run_kernel_up(k);
user_kernel_state = USER_KERNEL_LOADED;
#endif
break;
}
case REMOTEMSG_TYPE_RPC_REPLY: {
#ifdef ARTIQ_AMP
struct msg_rpc_reply reply;
#endif
if(user_kernel_state != USER_KERNEL_WAIT_RPC) {
log("Unsolicited RPC reply");
return 0;
}
#ifdef ARTIQ_AMP
reply.type = MESSAGE_TYPE_RPC_REPLY;
memcpy(&reply.eid, &buffer_in[9], 4);
memcpy(&reply.retval, &buffer_in[13], 4);
mailbox_send_and_wait(&reply);
#else
memcpy(&rpc_reply_eid, &buffer_in[9], 4);
memcpy(&rpc_reply_retval, &buffer_in[13], 4);
#endif
user_kernel_state = USER_KERNEL_RUNNING;
break;
}
@ -411,7 +340,6 @@ int session_input(void *data, int len)
return consumed;
}
#ifdef ARTIQ_AMP
/* assumes output buffer is empty when called */
static void process_kmsg(struct msg_base *umsg)
{
@ -470,7 +398,6 @@ static void process_kmsg(struct msg_base *umsg)
}
}
}
#endif /* ARTIQ_AMP */
void session_poll(void **data, int *len)
{
@ -478,7 +405,6 @@ void session_poll(void **data, int *len)
l = get_out_packet_len();
#ifdef ARTIQ_AMP
/* If the output buffer is available,
* check if the kernel CPU has something to transmit.
*/
@ -492,7 +418,6 @@ void session_poll(void **data, int *len)
}
l = get_out_packet_len();
}
#endif
*len = l - buffer_out_index_data;
*data = &buffer_out[buffer_out_index_data];

View File

@ -7,14 +7,13 @@
#include <generated/csr.h>
#include <console.h>
#include "dds.h"
#include "test_mode.h"
#ifdef ARTIQ_AMP
#include "kloader.h"
#include "mailbox.h"
#include "messages.h"
#include "dds.h"
#include "test_mode.h"
/* bridge access functions */
static void amp_bridge_init(void)
{
@ -102,48 +101,7 @@ static void p_ddsfud(void)
mailbox_send_and_wait(&msg);
}
#else /* ARTIQ_AMP */
#include "rtio.h"
static void p_ttlout(int n, int value)
{
rtio_init();
rtio_set_oe(rtio_get_counter() + 8000, n, 1);
rtio_set_o(rtio_get_counter() + 8000, n, value);
}
static void p_ddssel(int channel)
{
DDS_WRITE(DDS_GPIO, channel);
}
static void p_ddsreset(void)
{
unsigned int g;
g = DDS_READ(DDS_GPIO);
DDS_WRITE(DDS_GPIO, g | (1 << 7));
DDS_WRITE(DDS_GPIO, g);
}
static unsigned int p_ddsread(unsigned int address)
{
return DDS_READ(address);
}
static void p_ddswrite(unsigned int address, unsigned int data)
{
DDS_WRITE(address, data);
}
static void p_ddsfud(void)
{
rtio_init();
rtio_fud(rtio_get_counter() + 8000);
}
#endif /* ARTIQ_AMP */
/* */
static void leds(char *value)
{
@ -462,9 +420,7 @@ void test_main(void)
{
char buffer[64];
#ifdef ARTIQ_AMP
amp_bridge_init();
#endif
while(1) {
putsnonl("\e[1mtest>\e[0m ");

View File

@ -94,18 +94,6 @@ set_false_path -from [get_clocks rsys_clk] -to [get_clocks rio_clk]
set_false_path -from [get_clocks rio_clk] -to [get_clocks rsys_clk]
""", rsys_clk=self.rtio.cd_rsys.clk, rio_clk=self.rtio.cd_rio.clk)
class UP(_Peripherals):
def __init__(self, *args, **kwargs):
_Peripherals.__init__(self, *args, **kwargs)
rtio_csrs = self.rtio.get_csrs()
self.submodules.rtiowb = wbgen.Bank(rtio_csrs)
self.add_wb_slave(mem_decoder(self.mem_map["rtio"]), self.rtiowb.bus)
self.add_csr_region("rtio", self.mem_map["rtio"] + 0x80000000, 32, rtio_csrs)
self.add_wb_slave(mem_decoder(self.mem_map["dds"]), self.dds.bus)
self.add_memory_region("dds", self.mem_map["dds"] + 0x80000000, 64*4)
class AMP(_Peripherals):
csr_map = {

View File

@ -121,20 +121,6 @@ trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd
self.comb += dds_pads.fud_n.eq(~fud)
class UP(_Peripherals):
def __init__(self, platform, **kwargs):
_Peripherals.__init__(self, platform, **kwargs)
rtio_csrs = self.rtio.get_csrs()
self.submodules.rtiowb = wbgen.Bank(rtio_csrs)
self.add_wb_slave(mem_decoder(self.mem_map["rtio"]), self.rtiowb.bus)
self.add_csr_region("rtio", self.mem_map["rtio"] + 0x80000000, 32,
rtio_csrs)
self.add_wb_slave(mem_decoder(self.mem_map["dds"]), self.dds.bus)
self.add_memory_region("dds", self.mem_map["dds"] + 0x80000000, 64*4)
class AMP(_Peripherals):
csr_map = {
"kernel_cpu": 14

View File

@ -1,131 +0,0 @@
from migen.fhdl.std import *
from migen.bank.description import *
from migen.bank import wbgen
from mibuild.generic_platform import *
from misoclib.com import gpio
from misoclib.soc import mem_decoder
from misoclib.mem.sdram.core.minicon import MiniconSettings
from targets.ppro import BaseSoC
from artiq.gateware import rtio, ad9858, nist_qc1
from artiq.gateware.rtio.phy import ttl_simple
class _TestGen(Module):
def __init__(self, pad):
divc = Signal(15)
ce = Signal()
self.sync += Cat(divc, ce).eq(divc + 1)
sr = Signal(8, reset=0b10101000)
self.sync += If(ce, sr.eq(Cat(sr[1:], sr[0])))
self.comb += pad.eq(sr[0])
class _RTIOMiniCRG(Module, AutoCSR):
def __init__(self, platform):
self._clock_sel = CSRStorage()
self.clock_domains.cd_rtio = ClockDomain()
# 80MHz -> 125MHz
rtio_internal_clk = Signal()
self.specials += Instance("DCM_CLKGEN",
p_CLKFXDV_DIVIDE=2,
p_CLKFX_DIVIDE=16, p_CLKFX_MD_MAX=1.6, p_CLKFX_MULTIPLY=25,
p_CLKIN_PERIOD=12.5, p_SPREAD_SPECTRUM="NONE",
p_STARTUP_WAIT="FALSE",
i_CLKIN=ClockSignal(), o_CLKFX=rtio_internal_clk,
i_FREEZEDCM=0, i_RST=ResetSignal())
rtio_external_clk = platform.request("xtrig")
platform.add_period_constraint(rtio_external_clk, 8.0)
self.specials += Instance("BUFGMUX",
i_I0=rtio_internal_clk,
i_I1=rtio_external_clk,
i_S=self._clock_sel.storage,
o_O=self.cd_rtio.clk)
platform.add_platform_command("""
NET "{int_clk}" TNM_NET = "GRPint_clk";
NET "{ext_clk}" TNM_NET = "GRPext_clk";
NET "sys_clk" TNM_NET = "GRPsys_clk";
TIMESPEC "TSfix_ise1" = FROM "GRPint_clk" TO "GRPsys_clk" TIG;
TIMESPEC "TSfix_ise2" = FROM "GRPsys_clk" TO "GRPint_clk" TIG;
TIMESPEC "TSfix_ise3" = FROM "GRPext_clk" TO "GRPsys_clk" TIG;
TIMESPEC "TSfix_ise4" = FROM "GRPsys_clk" TO "GRPext_clk" TIG;
TIMESPEC "TSfix_ise5" = FROM "GRPext_clk" TO "GRPint_clk" TIG;
TIMESPEC "TSfix_ise6" = FROM "GRPint_clk" TO "GRPext_clk" TIG;
""", int_clk=rtio_internal_clk, ext_clk=rtio_external_clk)
class UP(BaseSoC):
csr_map = {
"rtio": None, # mapped on Wishbone instead
"rtiocrg": 13
}
csr_map.update(BaseSoC.csr_map)
mem_map = {
"rtio": 0x20000000, # (shadow @0xa0000000)
"dds": 0x50000000, # (shadow @0xd0000000)
}
mem_map.update(BaseSoC.mem_map)
def __init__(self, platform, cpu_type="or1k",
with_test_gen=False, **kwargs):
BaseSoC.__init__(self, platform,
cpu_type=cpu_type,
sdram_controller_settings=MiniconSettings(),
**kwargs)
platform.add_extension(nist_qc1.papilio_adapter_io)
self.submodules.leds = gpio.GPIOOut(Cat(
platform.request("user_led", 0),
platform.request("ext_led", 0)))
self.comb += [
platform.request("ttl_l_tx_en").eq(1),
platform.request("ttl_h_tx_en").eq(1)
]
# RTIO channels
rtio_channels = []
for i in range(2):
phy = ttl_simple.Inout(platform.request("pmt", i))
self.submodules += phy
rtio_channels.append(rtio.Channel(phy.rtlink))
for i in range(5):
phy = ttl_simple.Output(platform.request("ttl", i))
self.submodules += phy
rtio_channels.append(rtio.Channel(phy.rtlink))
fud = Signal()
self.add_constant("RTIO_FUD_CHANNEL", len(rtio_channels))
phy = ttl_simple.Output(fud)
self.submodules += phy
rtio_channels.append(rtio.Channel(phy.rtlink))
# RTIO core
self.submodules.rtiocrg = _RTIOMiniCRG(platform)
self.submodules.rtio = rtio.RTIO(rtio_channels,
clk_freq=125000000,
counter_width=32)
rtio_csrs = self.rtio.get_csrs()
self.submodules.rtiowb = wbgen.Bank(rtio_csrs)
self.add_wb_slave(mem_decoder(self.mem_map["rtio"]), self.rtiowb.bus)
self.add_csr_region("rtio", self.mem_map["rtio"] + 0x80000000,
32, rtio_csrs)
if with_test_gen:
self.submodules.test_gen = _TestGen(platform.request("ttl", 8))
dds_pads = platform.request("dds")
self.submodules.dds = ad9858.AD9858(dds_pads)
self.add_wb_slave(mem_decoder(self.mem_map["dds"]), self.dds.bus)
self.add_memory_region("dds", self.mem_map["dds"] + 0x80000000, 64*4)
self.comb += dds_pads.fud_n.eq(~fud)
default_subtarget = UP