+++ /dev/null
-../../submodule/ulan-app/app-host/usb_sendhex/
\ No newline at end of file
--- /dev/null
+From 225b899f1e904128ed4794041dc625751c08fc3f Mon Sep 17 00:00:00 2001
+From: Martin Meloun <meloumar@cmp.felk.cvut.cz>
+Date: Mon, 26 Aug 2013 11:23:24 +0200
+Subject: [PATCH] Implement USB_VENDOR_CALL feature in usb_sendhex
+
+USB_VENDOR_CALL feature sends a command with a argument
+(both 16bit) and expects 16bit return value. It is used
+for calling functions on the target. If mixed with other
+arguments, it is executed right before GOTO.
+
+Signed-off-by: Martin Meloun <meloumar@cmp.felk.cvut.cz>
+---
+ app-host/usb_sendhex/usb_sendhex.c | 57 ++++++++++++++++++++++++++++++++++----
+ 1 file changed, 52 insertions(+), 5 deletions(-)
+
+diff --git a/app-host/usb_sendhex/usb_sendhex.c b/app-host/usb_sendhex/usb_sendhex.c
+index 16f4907..c297822 100644
+--- a/app-host/usb_sendhex/usb_sendhex.c
++++ b/app-host/usb_sendhex/usb_sendhex.c
+@@ -3,7 +3,7 @@
+ *
+ * Based on 'ul_sendhex'
+ *
+- * Version 1.0 - 2004/02/03
++ * Version 1.1 - 2013/08/26
+ */
+ #define _GNU_SOURCE
+
+@@ -52,6 +52,9 @@ unsigned long mem_length = 0xff00;
+ unsigned long max_block = 1024;
+ unsigned long go_addr = 3;
+ int go_flg = 0;
++int call = 0xFFFF;
++int arg = 0;
++int call_flg = 0;
+ int reset_flg = 0;
+ int prt_modules = 0;
+ int debugk = 0;
+@@ -579,6 +582,33 @@ int download_file(char *file_name, char *format)
+ return ret;
+ }
+
++int send_cmd_call(int cmd, int val)
++{
++ int ret, resp_val;
++ usb_dev_handle *hdev;
++ char resp[10];
++
++ hdev = usb_open_device(vid, pid);
++
++ if (!hdev)
++ {
++ perror("send_cmd_call : USB open failed");
++ return -1;
++ }
++
++ ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
++ USB_VENDOR_CALL, val & 0xffff, cmd & 0xffff, resp, sizeof(resp), USB_TIMEOUT);
++ resp_val = usb_swab16(*((uint16_t *)(resp)));
++
++ if (ret < 0)
++ printf("Call %4X (%4X) ERROR %d: %s\n", (uint16_t)(cmd & 0xffff), (uint16_t)(val & 0xffff), ret, usb_strerror());
++ else
++ printf("Call %4X (%4X): %4X\n", (uint16_t)(cmd & 0xffff), (uint16_t)(val & 0xffff), resp_val);
++
++ usb_close_device(hdev);
++ return ret;
++}
++
+ int send_cmd_go(unsigned long addr)
+ {
+ int ret;
+@@ -893,6 +923,8 @@ usage(void)
+ printf(" -s, --start <addr> start address of transfer\n");
+ printf(" -l, --length <num> length of upload block\n");
+ printf(" -b, --block <num> maximal block length\n");
++ printf(" -c, --call <num> vendor custom call\n");
++ printf(" -a, --argument <num> argument for vendor custom call\n");
+ printf(" -g, --go <addr> start program from address\n");
+ printf(" -r, --reset reset before download\n");
+ printf(" -E, --mass-erase <mode> full device erase\n");
+@@ -917,6 +949,8 @@ int main(int argc, char *argv[])
+ { "start", 1, 0, 's' },
+ { "length", 1, 0, 'l' },
+ { "block", 1, 0, 'b' },
++ { "call", 1, 0, 'c' },
++ { "argument", 1, 0, 'a' },
+ { "go", 1, 0, 'g' },
+ { "reset", 0, 0, 'r' },
+ { "mass-erase", 1, 0, 'E' },
+@@ -934,9 +968,9 @@ int main(int argc, char *argv[])
+ int opt;
+
+ #ifndef HAS_GETOPT_LONG
+- while ((opt = getopt(argc, argv, "d:i:t:s:l:b:g:rE:euwf:pvVhD:")) != EOF)
++ while ((opt = getopt(argc, argv, "d:i:t:s:l:b:c:a::g:rE:euwf:pvVhD:")) != EOF)
+ #else
+- while ((opt = getopt_long(argc, argv, "d:i:t:s:l:b:g:rE:euwf:pvVh", &long_opts[0], NULL)) != EOF)
++ while ((opt = getopt_long(argc, argv, "d:i:t:s:l:b:c:a:g:rE:euwf:pvVh", &long_opts[0], NULL)) != EOF)
+ #endif
+
+ switch (opt)
+@@ -979,6 +1013,13 @@ int main(int argc, char *argv[])
+ case 'b':
+ max_block = strtoul(optarg, NULL, 0);
+ break;
++ case 'c':
++ call = strtoul(optarg, NULL, 0);
++ call_flg = 1;
++ break;
++ case 'a':
++ arg = strtoul(optarg, NULL, 0);
++ break;
+ case 'g':
+ go_addr = strtoul(optarg, NULL, 0);
+ go_flg = 1;
+@@ -1013,7 +1054,7 @@ int main(int argc, char *argv[])
+ verbose = 1;
+ break;
+ case 'V':
+- fputs("USB sendhex v.1.0\n", stdout);
++ fputs("USB sendhex v.1.1\n", stdout);
+ exit(0);
+ case 'h':
+ default:
+@@ -1021,7 +1062,7 @@ int main(int argc, char *argv[])
+ exit(opt == 'h' ? 0 : 1);
+ }
+
+- if ((optind >= argc) && !go_flg && !prt_modules && !debugk_flg
++ if ((optind >= argc) && !go_flg && !call_flg && !prt_modules && !debugk_flg
+ && !masserase_flg && !regerase_flg && !reset_flg)
+ {
+ usage();
+@@ -1062,6 +1103,12 @@ int main(int argc, char *argv[])
+ exit(2);
+ }
+
++ if (call_flg)
++ {
++ if (send_cmd_call(call, arg) < 0)
++ exit(2);
++ }
++
+ if (go_flg)
+ {
+ if (send_cmd_go(go_addr) < 0)
+--
+1.8.4.5
+
--- /dev/null
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+ @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
--- /dev/null
+default_CONFIG = CONFIG_APP_USB_SENDHEX=x
+
+ifeq ($(CONFIG_APP_USB_SENDHEX),y)
+
+bin_PROGRAMS = usb_sendhex
+
+usb_sendhex_SOURCES = usb_sendhex.c
+
+lib_LOADLIBES = usb
+
+endif #CONFIG_APP_USB_SENDHEX
--- /dev/null
+/* usb_sendhex - program for manage device firmware by USB
+ * R.Bartosinski <bartosr@centrum.cz> (C)2004
+ *
+ * Based on 'ul_sendhex'
+ *
+ * Version 1.1 - 2013/08/26
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <usb.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <endian.h>
+
+#if !defined(_WIN32) && !defined(__DJGPP__) && !defined(HAS_GETDELIM)
+#define HAS_GETDELIM
+#endif
+#define HAS_GETOPT_LONG
+
+#define USB_DEV_VID 0xDEAD
+#define USB_DEV_PID 0x1000
+
+#define USB_TIMEOUT 500
+
+// USB vendor defines
+
+#define USB_VENDOR_GET_CAPABILITIES 0x00 // get capabilities
+#define USB_VENDOR_RESET_DEVICE 0x08
+// #define USB_VENDOR_SET_BYTE 0x10
+// #define USB_VENDOR_SET_WORD 0x20
+#define USB_VENDOR_GET_SET_MEMORY 0x30
+#define USB_VENDOR_ERASE_MEMORY 0x40 // erase memory for 1 Byte
+#define USB_VENDOR_ERASE_1KB_MEMORY 0x48 // erase memory for 1 KB
+#define USB_VENDOR_MASS_ERASE 0x50 // erase all device memory
+#define USB_VENDOR_GOTO 0x60
+#define USB_VENDOR_CALL 0x70
+#define USB_VENDOR_GET_STATUS 0xF0
+#define USB_VENDOR_MASK 0xF8 // mask for vendor commands
+
+#define USB_VENDOR_MEMORY_BY_BULK 0x80
+
+int vid = USB_DEV_VID;
+int pid = USB_DEV_PID;
+int upload_flg = 0;
+int mem_type = 2;
+unsigned long mem_start = 0;
+unsigned long mem_length = 0xff00;
+unsigned long max_block = 1024;
+unsigned long go_addr = 3;
+int go_flg = 0;
+int call = 0xFFFF;
+int arg = 0;
+int call_flg = 0;
+int reset_flg = 0;
+int prt_modules = 0;
+int debugk = 0;
+int debugk_flg = 0;
+int verbose = 0;
+int wait_for_device_flg = 0;
+char *file_format = NULL;
+int regerase_flg = 0;
+int masserase_flg = 0;
+unsigned long masserase_mode = 0;
+
+/*****************************************************************************/
+
+typedef struct tform_file
+{
+ unsigned char *buf;
+ int buf_len;
+ int buf_addr;
+ int buf_bytes;
+ FILE *file;
+ char *line_buf;
+ int line_addr;
+ int line_bytes;
+ int line_offs;
+ int start_addr;
+ int (*read)(struct tform_file *tform);
+ int (*done)(struct tform_file *tform);
+} tform_file;
+
+/*****************************************************************************/
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+uint16_t usb_swab16(uint16_t x)
+{
+ return x << 8 | x >> 8;
+}
+#else
+uint16_t usb_swab16(uint16_t x)
+{
+ return x;
+}
+#endif
+
+#ifndef HAS_GETDELIM
+int getdelim(char **line, size_t *linelen, char delim, FILE *F)
+{
+ char c;
+ size_t l = 0;
+
+ do
+ {
+ if (l + 1 >= *linelen)
+ {
+ *linelen = l + 20;
+
+ if (!*line)
+ *line = (char *)malloc(*linelen);
+ else
+ *line = (char *)realloc(*line, *linelen);
+ }
+
+ c = fgetc(F);
+
+ if (feof(F))
+ {
+ if (l)
+ break;
+ else
+ return -1;
+ }
+
+ if (c != '\r')
+ (*line)[l++] = c;
+ }
+ while (c != delim);
+
+ (*line)[l] = 0;
+ return l;
+}
+#endif
+
+int get_hex(char **p, unsigned *v, int chars)
+{
+ unsigned u = 0;
+ char c;
+ *v = 0;
+
+ while (**p == ' ')
+ (*p)++;
+
+ while (chars--)
+ {
+ u <<= 4;
+ c = **p;
+
+ if ((c >= '0') && (c <= '9'))
+ u += c - '0';
+ else if ((c >= 'A') && (c <= 'F'))
+ u += c - 'A' + 10;
+ else
+ return -1;
+
+ (*p)++;
+ };
+
+ *v = u;
+
+ return 0;
+}
+
+int tform_init(tform_file *tform, int buf_len)
+{
+ if (!buf_len) buf_len = 1024;
+
+ tform->file = NULL;
+ tform->buf_len = buf_len;
+ tform->buf = malloc(tform->buf_len);
+ tform->buf_addr = 0;
+ tform->line_buf = NULL;
+ tform->line_offs = 0;
+ tform->line_bytes = 0;
+ tform->start_addr = -1;
+ tform->buf_bytes = 0;
+ tform->read = NULL;
+ tform->done = NULL;
+ return 0;
+}
+
+int tform_done(tform_file *tform)
+{
+ if (tform->done)
+ return tform->done(tform);
+
+ fclose(tform->file);
+
+ if (tform->buf)
+ free(tform->buf);
+
+ if (tform->line_buf)
+ free(tform->line_buf);
+
+ return 0;
+};
+
+int tform_read(tform_file *tform)
+{
+ return tform->read(tform);
+}
+
+int tform_read_ihex(tform_file *tform)
+{
+ int cn, len = 0;
+ int addr = 0;
+ unsigned u, v;
+ char *p, *r;
+ char *line = NULL;
+ size_t line_len = 0;
+
+ while (len < tform->buf_len)
+ {
+ if (!tform->line_bytes)
+ {
+ int checksum = 0;
+ int ihex_type = 0;
+
+ tform->line_offs = 0;
+
+ if (getdelim(&line, &line_len, '\n', tform->file) == -1)
+ break;
+
+ p = line;
+
+ if (*p++ != ':')
+ printf("tform_read : strange line %s\n", line);
+ else
+ {
+ if (get_hex(&p, &u, 2) < 0)
+ {
+ printf("tform_read_ihex : bad ihex cnt\n");
+ return -1;
+ }
+
+ checksum += cn = tform->line_bytes = u;
+
+ if (!tform->line_buf)
+ tform->line_buf = malloc(cn);
+ else
+ tform->line_buf = realloc(tform->line_buf, cn);
+
+ if (get_hex(&p, &u, 2) < 0)
+ {
+ printf("tform_read_ihex : bad ihex addr\n");
+ return -1;
+ }
+
+ if (get_hex(&p, &v, 2) < 0)
+ {
+ printf("tform_read_ihex : bad ihex addr\n");
+ return -1;
+ }
+
+ checksum += u + v;
+ tform->line_addr = (u << 8) + v;
+
+ if (get_hex(&p, &u, 2) < 0)
+ {
+ printf("tform_read_ihex : bad ihex type\n");
+ return -1;
+ }
+
+ checksum += ihex_type = u;
+
+ if (ihex_type == 0 || ihex_type == 1)
+ {
+ r = tform->line_buf;
+
+ while (cn--)
+ {
+ if (get_hex(&p, &u, 2) < 0)
+ {
+ printf("tform_read_ihex : bad ihex data\n");
+ return -1;
+ }
+
+ checksum += *r++ = u;
+ }
+
+ if (get_hex(&p, &u, 2) < 0)
+ {
+ printf("tform_read_ihex : bad ihex csum\n");
+ return -1;
+ }
+
+ checksum += u;
+
+ if (checksum & 0xff)
+ {
+ printf("tform_read_ihex : error ihex csum %d\n",
+ checksum);
+ return -1;
+ }
+
+ while ((u = *p++)) if (u != ' ' && u != '\n' && u != '\r')
+ {
+ printf("tform_read_ihex : residual chars on line\n");
+ return -1;
+ }
+ }
+
+ if (ihex_type == 1)
+ {
+ tform->line_bytes = 0;
+ tform->start_addr = tform->line_addr;
+ }
+ }
+ }
+
+ if (tform->line_bytes)
+ {
+ if (!len)
+ addr = tform->buf_addr = tform->line_addr + tform->line_offs;
+ else if (addr != tform->line_addr + tform->line_offs)
+ break;
+
+ cn = tform->line_bytes - tform->line_offs;
+
+ if (cn + len > tform->buf_len) cn = tform->buf_len - len;
+
+ memcpy(tform->buf + len, tform->line_buf + tform->line_offs, cn);
+ len += cn;
+ addr += cn;
+ tform->line_offs += cn;
+
+ if (tform->line_bytes == tform->line_offs)
+ tform->line_bytes = 0;
+ }
+ }
+
+ tform->buf_bytes = len;
+
+ return len;
+}
+
+int tform_read_binary(tform_file *tform)
+{
+ int len = 0;
+
+ tform->buf_addr += tform->buf_bytes;
+ len = fread(tform->buf, 1, tform->buf_len, tform->file);
+
+ if (len < 0)
+ {
+ perror("tform_read_binary : read error");
+ return -1;
+ }
+
+ tform->buf_bytes = len;
+ return len;
+}
+
+int tform_open(tform_file *tform, char *file_name,
+ char *format, int buf_len, int wr_fl)
+{
+ FILE *file;
+
+ if (!format || !strcmp("ihex", format))
+ {
+ if ((file = fopen(file_name, "r")) == NULL)
+ {
+ perror("download_file : hex file open");
+ return -1;
+ }
+
+ tform_init(tform, buf_len);
+ tform->file = file;
+ tform->read = tform_read_ihex;
+ }
+ else if (!strcmp("binary", format))
+ {
+ if ((file = fopen(file_name, "rb")) == NULL)
+ {
+ perror("download_file : binary file open");
+ return -1;
+ };
+
+ tform_init(tform, buf_len);
+ tform->file = file;
+ tform->read = tform_read_binary;
+ }
+ else
+ {
+ fprintf(stderr, "requested unknown format %s\n", format);
+ return -1;
+ }
+
+ return 1;
+}
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/* USB functions */
+void print_devices(void)
+{
+ struct usb_bus *bus;
+ struct usb_device *dev;
+ int i = 0;
+
+ usb_init(); // NO for more devices
+ usb_find_busses();
+ usb_find_devices();
+
+ printf("All connected usb devices\n");
+ printf(" bus/device idVendor/idProduct\n");
+
+ for (bus = usb_busses; bus; bus = bus->next)
+ {
+ for (dev = bus->devices; dev; dev = dev->next)
+ {
+ i++;
+ printf(" %s/%s 0x%04X/0x%04X\n", bus->dirname, dev->filename, dev->descriptor.idVendor, dev->descriptor.idProduct);
+ }
+ }
+
+ if (!i)
+ printf(" -- no device.\n");
+}
+
+struct usb_device *find_usb_device(int vendor, int product)
+{
+ struct usb_bus *bus;
+ struct usb_device *dev;
+
+ for (bus = usb_busses; bus; bus = bus->next)
+ {
+ for (dev = bus->devices; dev; dev = dev->next)
+ {
+ if ((dev->descriptor.idVendor == vendor) &&
+ (dev->descriptor.idProduct) == product)
+ return dev;
+ }
+ }
+
+ return NULL;
+}
+
+usb_dev_handle *usb_open_device(int uvid, int upid)
+{
+ struct usb_device *dev;
+ usb_dev_handle *hdev;
+
+ usb_init(); // NO for more devices
+ usb_find_busses();
+ usb_find_devices();
+
+ dev = find_usb_device(uvid, upid);
+
+ if (!dev)
+ {
+ if (verbose)
+ printf("!!! Cannot find device 0x%04X:0x%04X\n", uvid, upid);
+
+ return NULL;
+ }
+
+ if ((hdev = usb_open(dev)) == NULL)
+ {
+ if (verbose)
+ printf("!!! USB device wasn't opened !!!\n");
+
+ return NULL;
+ }
+
+ usb_claim_interface(hdev, 0);
+
+ if (verbose)
+ printf(" USB Device 0x%04X:0x%04X '%s' is open.\n", uvid, upid, dev->filename);
+
+ return hdev;
+}
+
+int usb_close_device(usb_dev_handle *hdev)
+{
+ int bRes = 1;
+ usb_release_interface(hdev, 0);
+ bRes = usb_close(hdev);
+
+ if (bRes && verbose)
+ printf("!!! USB Device wasn't closed !!!\n");
+
+ return bRes;
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+int download_file(char *file_name, char *format)
+{
+ usb_dev_handle *hdev;
+ tform_file tform;
+ int len;
+ int i;
+ int ret = 0;
+// int stamp;
+ unsigned long shift_addr = 0;
+
+ struct timeval time1, time2;
+ struct timezone tz;
+
+ shift_addr = mem_start;
+
+ hdev = usb_open_device(vid, pid);
+
+ if (!hdev)
+ {
+ perror("download_file : usb device open failed");
+ return -1;
+ }
+
+ /* ul_drv_debflg(ul_fd,0x11); */ /* 0x9 0x11 */
+
+ if (tform_open(&tform, file_name, format, max_block, 0) < 0)
+ {
+ usb_close_device(hdev);
+ return -1;
+ }
+
+ gettimeofday(&time1, &tz);
+
+ do
+ {
+ len = tform_read(&tform);
+
+ if (!len) break;
+
+ if (len < 0)
+ {
+ perror("download_file : ihex");
+ ret = -1;
+ break;
+ }
+
+ printf("addr %4lX len %4X\n", tform.buf_addr + shift_addr, len);
+
+ /* send data */
+
+ // if((stamp=ul_new_memrq_write(ul_fd,module,mem_type,
+ // tform.buf_addr+shift_addr,len,tform.buf))<0)
+ // { printf("download_file : send message error\n");
+ // ret=-1; break;
+ // };
+ i = 3;
+
+ do
+ {
+ ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, USB_VENDOR_GET_SET_MEMORY | mem_type /*USB_VENDOR_TARGET_XDATA*/,
+ (unsigned long)(tform.buf_addr + shift_addr) & 0xffff, (((unsigned long)(tform.buf_addr + shift_addr)) >> 16) & 0xffff, (void *)tform.buf, len, 150 + len); //USB_TIMEOUT);
+// ret = usb_bulk_write( hdev, USB_ENDPOINT_IN | 0x02, buf, len, 1000);
+
+ if (verbose && ret < 0) printf("Mem read error %d - again\n", ret);
+
+ i--;
+ }
+ while (ret < 0 && i);
+
+ }
+ while (1);
+
+ gettimeofday(&time2, &tz);
+
+ if (verbose)
+ {
+ long dus = (time2.tv_sec * 1000000 + time2.tv_usec) - (time1.tv_sec * 1000000 + time1.tv_usec);
+ printf("Upload time %lu.%lu s\n", dus / 1000000, dus % 1000000);
+ }
+
+
+ if (tform.start_addr != -1)
+ printf("Found start address %4X\n", tform.start_addr);
+
+ tform_done(&tform);
+ usb_close_device(hdev);
+ return ret;
+}
+
+int send_cmd_call(int cmd, int val)
+{
+ int ret, resp_val;
+ usb_dev_handle *hdev;
+ char resp[10];
+
+ hdev = usb_open_device(vid, pid);
+
+ if (!hdev)
+ {
+ perror("send_cmd_call : USB open failed");
+ return -1;
+ }
+
+ ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USB_VENDOR_CALL, val & 0xffff, cmd & 0xffff, resp, sizeof(resp), USB_TIMEOUT);
+ resp_val = usb_swab16(*((uint16_t *)(resp)));
+
+ if (ret < 0)
+ printf("Call %4X (%4X) ERROR %d: %s\n", (uint16_t)(cmd & 0xffff), (uint16_t)(val & 0xffff), ret, usb_strerror());
+ else
+ printf("Call %4X (%4X): %4X\n", (uint16_t)(cmd & 0xffff), (uint16_t)(val & 0xffff), resp_val);
+
+ usb_close_device(hdev);
+ return ret;
+}
+
+int send_cmd_go(unsigned long addr)
+{
+ int ret;
+ usb_dev_handle *hdev;
+
+ hdev = usb_open_device(vid, pid);
+
+ if (!hdev)
+ {
+ perror("send_cmd_go : USB open failed");
+ return -1;
+ }
+
+ ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USB_VENDOR_GOTO, addr & 0xffff, (addr >> 16) & 0xffff, NULL, 0, USB_TIMEOUT);
+
+ if (ret < 0) printf("Goto to %4lX ERROR %d: %s\n", addr, ret, usb_strerror());
+ else printf("Goto to %4lX OK\n", addr);
+
+ usb_close_device(hdev);
+ return ret;
+}
+
+int send_cmd_reset()
+{
+ int ret;
+ usb_dev_handle *hdev;
+
+ hdev = usb_open_device(vid, pid);
+
+ if (!hdev)
+ {
+ perror("send_cmd_reset : USB open failed");
+ return -1;
+ }
+
+ ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USB_VENDOR_RESET_DEVICE, 0, 0, NULL, 0, USB_TIMEOUT);
+
+ if (ret < 0)
+ printf("Reset device ERROR %d: %s\n", ret, usb_strerror());
+ else
+ printf("Reset OK\n");
+
+ usb_close_device(hdev);
+ return ret;
+};
+
+
+int send_cmd_regerase(unsigned long addr, unsigned long len)
+{
+ int ret;
+ usb_dev_handle *hdev;
+
+ hdev = usb_open_device(vid, pid);
+
+ if (!hdev)
+ {
+ perror("send_cmd_regerase : USB open failed");
+ return -1;
+ }
+
+ if (addr + len < 0x10000)
+ {
+ ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USB_VENDOR_ERASE_MEMORY, addr, len, NULL, 0, USB_TIMEOUT * 5);
+ }
+ else
+ {
+ len += addr & 0x3ff;
+ ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USB_VENDOR_ERASE_1KB_MEMORY, addr >> 10, len >> 10, NULL, 0, USB_TIMEOUT * 10);
+ }
+
+ if (ret < 0)
+ printf("Region Erase from %4lX ERROR %d: %s\n", addr, ret, usb_strerror());
+ else
+ printf("Region Erase from %4lX OK\n", addr);
+
+ usb_close_device(hdev);
+ return ret;
+};
+
+
+
+int send_cmd_masserase(unsigned long mode)
+{
+ int ret;
+ usb_dev_handle *hdev;
+
+ hdev = usb_open_device(vid, pid);
+
+ if (!hdev)
+ {
+ perror("send_cmd_masserase : USB open failed");
+ return -1;
+ };
+
+ ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
+ USB_VENDOR_MASS_ERASE, mode & 0xffff, (mode >> 16) & 0xffff, NULL, 0, USB_TIMEOUT * 20);
+
+ if (ret < 0)
+ printf("Mass Erase to %4lX ERROR %d: %s\n", mode, ret, usb_strerror());
+ else printf("Mass Erase to %4lX OK\n", mode);
+
+ usb_close_device(hdev);
+ return ret;
+};
+
+
+int upload_file(char *file_name, char *format)
+{
+ usb_dev_handle *hdev;
+ FILE *file;
+ int ret = 0;
+ unsigned char buf[0x400];
+ unsigned char *p;
+ char *mode = "w";
+ enum {fmt_ihex, fmt_binary, fmt_dump} fmt;
+ int i, l, csum;
+ unsigned long mem_adr = mem_start;
+ unsigned long mem_len = mem_length;
+ unsigned long len;
+
+ struct timeval time1, time2;
+ struct timezone tz;
+
+ if (max_block > 0x400)
+ max_block = 0x400;
+
+ if (!format || !strcmp("ihex", format))
+ fmt = fmt_ihex;
+ else if (!strcmp("binary", format))
+ {
+ mode = "wb";
+ fmt = fmt_binary;
+ }
+ else if (!strcmp("dump", format))
+ fmt = fmt_dump;
+ else
+ {
+ fprintf(stderr, "requested unknown format %s\n", format);
+ return -1;
+ }
+
+ if (!strcmp(file_name, "-"))
+ file_name = NULL;
+
+ hdev = usb_open_device(vid, pid);
+
+ if (!hdev)
+ {
+ perror("upload_file : open failed");
+ return -1;
+ };
+
+ /* ul_drv_debflg(ul_fd,0x11); */ /* 0x9 0x11 */
+
+ if (file_name)
+ {
+ if ((file = fopen(file_name, mode)) == NULL)
+ {
+ perror("upload_file : file open");
+ usb_close_device(hdev);
+ return -1;
+ }
+ }
+ else file = stdout;
+
+ gettimeofday(&time1, &tz);
+
+// ret = usb_control_msg( hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, USB_VENDOR_MEMORY_BY_BULK | USB_VENDOR_TARGET_XDATA,
+// mem_adr & 0xffff, mem_len, NULL, 0, 2000); //USB_TIMEOUT);
+
+ if (ret < 0)
+ {
+ printf("ERR ctrl msg\n");
+ mem_len = 0;
+ }
+
+ while (mem_len)
+ {
+ len = mem_len < max_block ? mem_len : max_block;
+ /* read data */
+ i = 3;
+
+ do
+ {
+ ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, USB_VENDOR_GET_SET_MEMORY | mem_type /*USB_VENDOR_TARGET_XDATA*/,
+ mem_adr & 0xffff, (mem_adr >> 16) & 0xffff, (void *)buf, len, 100 + len); //USB_TIMEOUT);
+// ret = usb_bulk_read( hdev, USB_ENDPOINT_IN | 0x02, buf, len, 1000);
+
+ if (verbose && ret < 0)
+ printf("Mem read error - again\n");
+
+ i--;
+ }
+ while (ret < 0 && i);
+
+ if (ret < 0)
+ {
+ printf("Mem read returns %d: %s\n", ret, usb_strerror());
+ break;
+ }
+
+ if (file_name) printf("%04lX\n", mem_adr);
+
+ switch (fmt)
+ {
+ case fmt_ihex:
+ p = buf;
+ i = 0;
+
+ while (i < len)
+ {
+ l = len - i;
+
+ if (l > 16) l = 16;
+
+ csum = l + (mem_adr + i) + ((mem_adr + i) >> 8);
+ fprintf(file, ":%02X%04lX00", l, (mem_adr + i) & 0xffff);
+
+ while (l--)
+ {
+ fprintf(file, "%02X", buf[i]);
+ csum += buf[i++];
+ };
+
+ fprintf(file, "%02X\n", (-csum) & 0xFF);
+ }
+
+ break;
+
+ case fmt_binary:
+ if (fwrite(buf, len, 1, file) != 1)
+ {
+ perror("upload_file : file write");
+ return -1;
+ }
+
+ break;
+
+ case fmt_dump:
+ i = 0;
+ p = buf;
+
+ while (i < len)
+ {
+ if (i & 0xf) printf(" %02X", *(p++));
+ else printf(i ? "\n%04lX:%02X" : "%04lX:%02X", mem_adr + i, *(p++));
+
+ i++;
+ }
+
+ printf("\n");
+ break;
+ }
+
+ mem_adr += len;
+ mem_len -= len;
+ }
+
+ gettimeofday(&time2, &tz);
+
+ if (verbose)
+ {
+ long dus = (time2.tv_sec * 1000000 + time2.tv_usec) - (time1.tv_sec * 1000000 + time1.tv_usec);
+ printf("Upload time %lu.%lu s\n", dus / 1000000, dus % 1000000);
+ }
+
+ if (file_name)
+ fclose(file);
+
+ usb_close_device(hdev);
+
+ return 0;
+};
+
+static int wait_for_device(int timeout)
+{
+ usb_dev_handle *hdev;
+
+ while (timeout)
+ {
+ hdev = usb_open_device(vid, pid);
+
+ if (hdev)
+ break;
+
+#ifdef _WIN32
+ Sleep(1000);
+#else
+ sleep(1);
+#endif
+ timeout--;
+ }
+
+ return timeout ? 0 : -1;
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+static void
+usage(void)
+{
+ printf("Usage: usb_sendhex <parameters> <hex_file>\n");
+ printf(" -d, --vid <num> device vendor id (VID) [0x%04X]\n", USB_DEV_VID);
+ printf(" -i, --pid <num> product id (PID) [0x%04X]\n", USB_DEV_PID);
+ printf(" -t, --type <num> target module memory space\n");
+ printf(" -s, --start <addr> start address of transfer\n");
+ printf(" -l, --length <num> length of upload block\n");
+ printf(" -b, --block <num> maximal block length\n");
+ printf(" -c, --call <num> vendor custom call\n");
+ printf(" -a, --argument <num> argument for vendor custom call\n");
+ printf(" -g, --go <addr> start program from address\n");
+ printf(" -r, --reset reset before download\n");
+ printf(" -E, --mass-erase <mode> full device erase\n");
+ printf(" -e, --erase erase region defined by -s -l\n");
+ printf(" -u, --upload upload memory block [download]\n");
+ printf(" -w, --wait wait for device to be on\n");
+ printf(" -f, --format <format> format of data file [ihex]\n");
+ printf(" -p, --print print devices\n");
+ printf(" --debug-kernel <m> flags to debug kernel\n");
+ printf(" -v, --verbose verbose program\n");
+ printf(" -V, --version show version\n");
+ printf(" -h, --help this usage screen\n");
+}
+
+int main(int argc, char *argv[])
+{
+ static struct option long_opts[] =
+ {
+ { "vid", 1, 0, 'd' },
+ { "pid", 1, 0, 'i' },
+ { "type", 1, 0, 't' },
+ { "start", 1, 0, 's' },
+ { "length", 1, 0, 'l' },
+ { "block", 1, 0, 'b' },
+ { "call", 1, 0, 'c' },
+ { "argument", 1, 0, 'a' },
+ { "go", 1, 0, 'g' },
+ { "reset", 0, 0, 'r' },
+ { "mass-erase", 1, 0, 'E' },
+ { "erase", 0, 0, 'e' },
+ { "upload", 0, 0, 'u' },
+ { "wait", 0, 0, 'w' },
+ { "format", 1, 0, 'f' },
+ { "print", 0, 0, 'p' },
+ { "verbose", 0, 0, 'v' },
+ { "version", 0, 0, 'V' },
+ { "help", 0, 0, 'h' },
+ { "debug-kernel", 1, 0, 'D' },
+ { 0, 0, 0, 0}
+ };
+ int opt;
+
+#ifndef HAS_GETOPT_LONG
+ while ((opt = getopt(argc, argv, "d:i:t:s:l:b:c:a::g:rE:euwf:pvVhD:")) != EOF)
+#else
+ while ((opt = getopt_long(argc, argv, "d:i:t:s:l:b:c:a:g:rE:euwf:pvVh", &long_opts[0], NULL)) != EOF)
+#endif
+
+ switch (opt)
+ {
+ char *p;
+ case 'd':
+ vid = strtol(optarg, &p, 16);
+
+ if (!p || (p == optarg))
+ {
+ printf("usb_sendhex : vendor ID is not hexadecimal number\n");
+ exit(1);
+ }
+
+ if (*p == ':')
+ {
+ char *r = p + 1;
+ pid = strtol(r, &p, 16);
+
+ if (!p || (p == r))
+ {
+ printf("usb_sendhex : product ID is not hexadecimal number\n");
+ exit(1);
+ }
+ }
+
+ break;
+ case 'i':
+ pid = strtol(optarg, &p, 16);
+ break;
+ case 't':
+ mem_type = strtol(optarg, NULL, 0);
+ break;
+ case 's':
+ mem_start = strtoul(optarg, NULL, 0);
+ break;
+ case 'l':
+ mem_length = strtoul(optarg, NULL, 0);
+ break;
+ case 'b':
+ max_block = strtoul(optarg, NULL, 0);
+ break;
+ case 'c':
+ call = strtoul(optarg, NULL, 0);
+ call_flg = 1;
+ break;
+ case 'a':
+ arg = strtoul(optarg, NULL, 0);
+ break;
+ case 'g':
+ go_addr = strtoul(optarg, NULL, 0);
+ go_flg = 1;
+ break;
+ case 'r':
+ reset_flg = 1;
+ break;
+ case 'E':
+ masserase_mode = strtoul(optarg, NULL, 0);
+ masserase_flg = 1;
+ break;
+ case 'e':
+ regerase_flg = 1;
+ break;
+ case 'u':
+ upload_flg = 1;
+ break;
+ case 'w':
+ wait_for_device_flg = 1;
+ break;
+ case 'f':
+ file_format = optarg;
+ break;
+ case 'p':
+ prt_modules = 1;
+ break;
+ case 'D':
+ debugk = strtol(optarg, NULL, 0);
+ debugk_flg = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'V':
+ fputs("USB sendhex v.1.1\n", stdout);
+ exit(0);
+ case 'h':
+ default:
+ usage();
+ exit(opt == 'h' ? 0 : 1);
+ }
+
+ if ((optind >= argc) && !go_flg && !call_flg && !prt_modules && !debugk_flg
+ && !masserase_flg && !regerase_flg && !reset_flg)
+ {
+ usage();
+ exit(1);
+ }
+
+ if (prt_modules)
+ print_devices();
+
+ if (wait_for_device_flg)
+ if (wait_for_device(100) < 0)
+ exit(2);
+
+ if (reset_flg)
+ send_cmd_reset();
+
+ if (regerase_flg)
+ send_cmd_regerase(mem_start, mem_length);
+
+ if (masserase_flg)
+ send_cmd_masserase(masserase_mode);
+
+ if (!upload_flg)
+ {
+ while (optind < argc)
+ if (download_file(argv[optind++], file_format) < 0)
+ exit(2);
+ }
+ else
+ {
+ if (optind + 1 != argc)
+ {
+ printf("upload_file : needs exactly one filename\n");
+ exit(1);
+ }
+
+ if (upload_file(argv[optind], file_format) < 0)
+ exit(2);
+ }
+
+ if (call_flg)
+ {
+ if (send_cmd_call(call, arg) < 0)
+ exit(2);
+ }
+
+ if (go_flg)
+ {
+ if (send_cmd_go(go_addr) < 0)
+ exit(2);
+ }
+
+ return 0;
+}
REQ_FIRMWARE := $(OUT)/imem.bin $(OUT)/imem.asm $(OUT)/dmem.bin $(OUT)/firmware.lst
#===============================================================================
-# Sythesis settings
+# Sythesis settings (SmartXplorer)
XST_GLOB_OPT := AllClockNets
XST_OPT_LEVEL := 2
+XST_OPT_MODE := Speed
XST_IOB_PACKING := False
+XST_POWER := NO
XST_KEEP_HIEARCHY := No
XST_NETLIST_HIEARCHY := As_Optimized
XST_READ_CORES := YES
XST_CROSS_CLOCK_ANALYSIS := NO
XST_CASE := Maintain
XST_REDUCE_CONTROL_SETS := Auto
-XST_REGISTER_DUPLICATION := Yes
+XST_REGISTER_DUPLICATION := YES
XST_REGISTER_BALANCING := Yes
XST_MOVE_FIRST_STAGE := YES
XST_MOVE_LAST_STAGE := YES
XST_MAX_FANOUT := 100000
XST_RESOURCE_SHARING := YES
XST_SLICE_UTILIZATION_RATIO_MARGIN := 5
-
+XST_SLICE_UTILIZATION_RATIO := 100
+XST_BRAM_UTILIZATION_RATIO := 100
+XST_DSP_UTILIZATION_RATIO := 100
+XST_USE_DSP48 := Auto
+XST_USE_SYNC_SET := Auto
+XST_USE_SYNC_RESET := Auto
+XST_SAFE_IMPLEMENTATION := No
+
+MAP_PLACER_COST_TABLE := 2
MAP_LOGIC_OPT := on
MAP_GLOBAL_OPT := off
MAP_EQUIVALENT_REGISTER_REMOVAL := off
C_OBJS := $(OUT)/firmware.o
A_OBJS :=
-CFLAGS := -mxl-soft-div -msoft-float -mno-xl-soft-mul -mxl-barrel-shift -Wno-main -Wl,-no-check-sections -fno-zero-initialized-in-bss -g -O2 -Wall
+CFLAGS := -mxl-soft-div -msoft-float -Wno-main -Wl,-no-check-sections -ffunction-sections -fno-zero-initialized-in-bss -g -O2 -Wall
AFLAGS := -D__ASSEMBLY__ $(CFLAGS)
-LDFLAGS := -static -nostdlib -defsym _STACK_SIZE=0x0200
+LDFLAGS := -static -nostdlib -relax -defsym _STACK_SIZE=0x0200 --gc-sections
OBJS := $(OUT)/start.o $(C_OBJS) $(A_OBJS)
-ofmt NGC \
-top $(TOP) \
-p $(DEVICE) \
- -opt_mode Speed \
-keep_hierarchy $(XST_KEEP_HIEARCHY) \
-glob_opt $(XST_GLOB_OPT) \
+ -opt_mode $(XST_OPT_MODE) \
-opt_level $(XST_OPT_LEVEL) \
+ -power $(XST_POWER) \
-iob $(XST_IOB_PACKING) \
-read_cores $(XST_READ_CORES) \
-write_timing_constraints $(XST_WRITE_TIMING_CONSTRAINTS) \
-optimize_primitives $(XST_OPTIMIZE_PRIMITIVES) \
-use_clock_enable $(XST_USE_CLOCK_ENABLE) \
-equivalent_register_removal $(XST_EQUIVALENT_REGISTER_REMOVAL) \
- -slice_utilization_ratio_maxmargin $(XST_SLICE_UTILIZATION_RATIO_MARGIN)" | xst | tee xst.log
+ -slice_utilization_ratio_maxmargin $(XST_SLICE_UTILIZATION_RATIO_MARGIN) \
+ -slice_utilization_ratio $(XST_SLICE_UTILIZATION_RATIO) \
+ -bram_utilization_ratio $(XST_BRAM_UTILIZATION_RATIO) \
+ -dsp_utilization_ratio $(XST_DSP_UTILIZATION_RATIO)" | xst | tee xst.log
.PHONY: re-translate
re-translate $(REQ_NGD): $(REQ_NGC) $(REQ_UCF)
.PHONY: re-map
re-map $(REQ_NCD_MAP) $(REQ_PCF): $(REQ_NGD)
cd $(OUT); \
- map -w -intstyle $(INTSTYLE) -p $(DEVICE) -logic_opt $(MAP_LOGIC_OPT) -ol high -t 1 -xt 0 \
+ map -w -intstyle $(INTSTYLE) -p $(DEVICE) -logic_opt $(MAP_LOGIC_OPT) -ol high -t $(MAP_PLACER_COST_TABLE) -xt 0 \
-r 4 -global_opt $(MAP_GLOBAL_OPT) -mt off -ir off -pr off -lc $(MAP_LUT_COMBINING) \
-power off -equivalent_register_removal $(MAP_EQUIVALENT_REGISTER_REMOVAL) \
-o $(NCD_MAP) $(NGD) $(PCF) | tee map.log
.PHONY: re-par
re-par $(REQ_NCD): $(REQ_NCD_MAP) $(REQ_PCF)
cd $(OUT); \
- par -w -intstyle $(INTSTYLE) -ol high -mt off $(NCD_MAP) $(NCD) $(PCF) | tee par.log
+ par -w -intstyle $(INTSTYLE) -ol high -xe n -mt off $(NCD_MAP) $(NCD) $(PCF) | tee par.log
.PHONY: re-gen
re-gen $(REQ_BIN): $(REQ_NCD)
+++ /dev/null
-library ieee;
-use ieee.std_logic_1164.all;
-use ieee.std_logic_arith.all;
-use ieee.std_logic_unsigned.all;
-use ieee.numeric_std.all;
-use work.lx_rocon_pkg.all;
-
--- Memory bus calibration
--- Holds the signal for one clock to simulate longest route
-
-entity bus_calibration is
- port
- (
- -- Clock
- clk_i : in std_logic;
- -- Reset
- reset_i : in std_logic;
- -- Chip enable
- ce_i : in std_logic;
- -- Address
- address_i : in std_logic_vector(1 downto 0);
- -- Data bus
- data_i : in std_logic_vector(31 downto 0);
- data_o : out std_logic_vector(31 downto 0);
- -- Bus signals
- rd_i : in std_logic;
- bls_i : in std_logic_vector(3 downto 0);
- ta_o : out std_logic
- );
-end bus_calibration;
-
-architecture Behavioral of bus_calibration is
-
- -- Wiring
- signal read1_out_s : std_logic_vector(31 downto 0);
- signal read1_ta_s : std_logic;
-
- signal read2_out_s : std_logic_vector(31 downto 0);
- signal read2_ta_s : std_logic;
-
- signal write1_out_s : std_logic_vector(31 downto 0);
- signal write1_ta_s : std_logic;
- signal write1_ce_s : std_logic;
-
- signal write2_out_s : std_logic_vector(31 downto 0);
- signal write2_ta_s : std_logic;
- signal write2_ce_s : std_logic;
-
-begin
-
- -- First read calibration register (0xAAAAAAAA)
- memory_bus_calib_read1: calibration_read_register
- generic map
- (
- id_g => "10101010101010101010101010101010"
- )
- port map
- (
- rd_i => rd_i,
- ta_o => read1_ta_s,
- data_o => read1_out_s
- );
-
- -- Second read calibration register (=0x55555555)
- memory_bus_calib_read2: calibration_read_register
- generic map
- (
- id_g => "01010101010101010101010101010101"
- )
- port map
- (
- rd_i => rd_i,
- ta_o => read2_ta_s,
- data_o => read2_out_s
- );
-
- -- First write calibration register
- memory_bus_calib_write1: calibration_write_register
- port map
- (
- clk_i => clk_i,
- ce_i => write1_ce_s,
- reset_i => reset_i,
- rd_i => rd_i,
- bls_i => bls_i,
- ta_o => write1_ta_s,
- data_i => data_i,
- data_o => write1_out_s
- );
-
- -- Second write calibration register
- memory_bus_calib_write2: calibration_write_register
- port map
- (
- clk_i => clk_i,
- ce_i => write2_ce_s,
- reset_i => reset_i,
- rd_i => rd_i,
- bls_i => bls_i,
- ta_o => write2_ta_s,
- data_i => data_i,
- data_o => write2_out_s
- );
-
- -- Processes
-update:
- process (clk_i)
- begin
-
- if clk_i = '1' and clk_i'event then
-
- -- Defaults
- write1_ce_s <= '0';
- write2_ce_s <= '0';
- ta_o <= '0';
- data_o <= (others => 'X');
-
- -- Chip Enable
- -- This will delay the register read / write
- if ce_i = '1' then
- case address_i is
- when "00" => -- Read1
- ta_o <= read1_ta_s;
- data_o <= read1_out_s;
- when "01" => -- Read2
- ta_o <= read2_ta_s;
- data_o <= read2_out_s;
- when "10" => -- Write1
- write1_ce_s <= '1';
- ta_o <= write1_ta_s;
- data_o <= write1_out_s;
- when "11" => -- Write2
- write2_ce_s <= '1';
- ta_o <= write2_ta_s;
- data_o <= write2_out_s;
- when others =>
- null;
- end case;
- end if;
-
- end if;
-
- end process;
-
-end Behavioral;
-
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
-use work.mbl_Pkg.all;
+use work.mbl_pkg.all;
use work.lx_rocon_pkg.all;
-- IRC bus interconnect
(
clk_i : in std_logic;
reset_i : in std_logic;
- -- Address (needs just last 4 bits, rest is wired to CE)
- address_i : in std_logic_vector(3 downto 0);
- ce_i : in std_logic;
-- Data bus
+ address_i : in std_logic_vector(3 downto 0);
+ next_ce_i : in std_logic;
data_i : in std_logic_vector(31 downto 0);
data_o : out std_logic_vector(31 downto 0);
- -- Bus signals
- rd_i : in std_logic;
+ --
bls_i : in std_logic_vector(3 downto 0);
- ta_o : out std_logic;
-- Signals for IRC
- irc1_i : in IRC_INPUT_Type;
- irc2_i : in IRC_INPUT_Type;
- irc3_i : in IRC_INPUT_Type;
- irc4_i : in IRC_INPUT_Type;
- -- Secondary data bus (slave)
- address_2_i : in std_logic_vector(3 downto 0);
- ce_2_i : in std_logic;
- --
- rd_2_i : in std_logic;
- bls_2_i : in std_logic_vector(3 downto 0);
- ta_2_o : out std_logic
+ irc_i : in IRC_INPUT_Array_Type(3 downto 0)
);
end bus_irc;
architecture Behavioral of bus_irc is
- signal irc1_s, irc2_s, irc3_s, irc4_s : IRC_OUTPUT_Type;
- signal reset_index_event_s : std_logic_vector(3 downto 0);
- signal reset_ab_error_s : std_logic_vector(3 downto 0);
- signal irc_en_s : std_logic;
- signal irc_bls_s : std_logic_vector(3 downto 0);
- signal irc_addr_s : std_logic_vector(2 downto 0);
- signal irc_data_s : std_logic_vector(31 downto 0);
-
+ signal irc_o_s : IRC_OUTPUT_Array_Type(3 downto 0);
+ signal reset_index_event_s : std_logic_vector(3 downto 0);
+ signal reset_ab_error_s : std_logic_vector(3 downto 0);
+ signal state_o_s : std_logic_vector(1 downto 0);
+ signal state_o_r : std_logic_vector(1 downto 0);
+ --
+ signal irc_en_s : std_logic;
+ signal irc_bls_s : std_logic_vector(3 downto 0);
+ signal irc_addr_s : std_logic_vector(2 downto 0);
+ signal irc_data_s : std_logic_vector(31 downto 0);
+ signal irc_out_s : std_logic;
+ signal irc_out_r : std_logic;
+ --
+ signal reset_reg_s : std_logic;
+ signal reset_reg_r : std_logic;
+ signal reset_reg_wr_s : std_logic;
+ signal reset_s : std_logic;
+ signal ce_s : std_logic;
begin
- irc1 : irc_reader
+irc1 : irc_reader
port map
(
clk_i => clk_i,
- reset_i => reset_i,
- irc_i => irc1_i,
+ reset_i => reset_s,
+ irc_i => irc_i(0),
reset_index_event_i => reset_index_event_s(0),
reset_ab_error_i => reset_ab_error_s(0),
- irc_o => irc1_s
+ irc_o => irc_o_s(0)
);
- irc2 : irc_reader
+irc2 : irc_reader
port map
(
clk_i => clk_i,
- reset_i => reset_i,
- irc_i => irc2_i,
+ reset_i => reset_s,
+ irc_i => irc_i(1),
reset_index_event_i => reset_index_event_s(1),
reset_ab_error_i => reset_ab_error_s(1),
- irc_o => irc2_s
+ irc_o => irc_o_s(1)
);
- irc3 : irc_reader
+irc3 : irc_reader
port map
(
clk_i => clk_i,
- reset_i => reset_i,
- irc_i => irc3_i,
+ reset_i => reset_s,
+ irc_i => irc_i(2),
reset_index_event_i => reset_index_event_s(2),
reset_ab_error_i => reset_ab_error_s(2),
- irc_o => irc3_s
+ irc_o => irc_o_s(2)
);
- irc4 : irc_reader
+irc4 : irc_reader
port map
(
clk_i => clk_i,
- reset_i => reset_i,
- irc_i => irc4_i,
+ reset_i => reset_s,
+ irc_i => irc_i(3),
reset_index_event_i => reset_index_event_s(3),
reset_ab_error_i => reset_ab_error_s(3),
- irc_o => irc4_s
+ irc_o => irc_o_s(3)
);
- irc_proc : irc_proc_main
+irc_proc : irc_proc_main
port map
(
- clk_i => clk_i,
- reset_i => reset_i,
- irc1_i.qcount => irc1_s.qcount,
- irc1_i.index => irc1_s.index,
- irc1_i.index_event => irc1_s.index_event,
- irc2_i.qcount => irc2_s.qcount,
- irc2_i.index => irc2_s.index,
- irc2_i.index_event => irc2_s.index_event,
- irc3_i.qcount => irc3_s.qcount,
- irc3_i.index => irc3_s.index,
- irc3_i.index_event => irc3_s.index_event,
- irc4_i.qcount => irc4_s.qcount,
- irc4_i.index => irc4_s.index,
- irc4_i.index_event => irc4_s.index_event,
- irc_index_reset_o => reset_index_event_s,
- -- BRAM access (the other port)
- mem_clk_i => clk_i,
- mem_en_i => irc_en_s,
- mem_we_i => irc_bls_s,
- mem_addr_i => irc_addr_s,
- mem_data_i => data_i,
- mem_data_o => irc_data_s
+ clk_i => clk_i,
+ reset_i => reset_s,
+ -- IRC
+ irc_i(0) => irc_o_s(0).count,
+ irc_i(1) => irc_o_s(1).count,
+ irc_i(2) => irc_o_s(2).count,
+ irc_i(3) => irc_o_s(3).count,
+ irc_index_reset_o => reset_index_event_s,
+ -- BRAM
+ mem_clk_i => clk_i,
+ mem_en_i => irc_en_s,
+ mem_we_i => irc_bls_s,
+ mem_addr_i => irc_addr_s,
+ mem_data_i => data_i,
+ mem_data_o => irc_data_s
);
-wire:
- process(ce_i, ce_2_i, rd_i, rd_2_i, bls_i, bls_2_i, address_i, address_2_i, irc_data_s, irc1_s, irc2_s, irc3_s, irc4_s, data_i)
- variable ce_v : std_logic;
- variable rd_v : std_logic;
- variable bls_v : std_logic_vector(3 downto 0);
- variable address_v : std_logic_vector(3 downto 0);
+ reset_s <= reset_reg_r or reset_i;
+
+wire_in:
+ process(next_ce_i, ce_s, reset_reg_s, bls_i, address_i, irc_data_s, data_i, irc_o_s)
begin
-- init values
- data_o <= (others => 'X');
irc_en_s <= '0';
+ irc_out_s <= '0';
irc_bls_s <= (others => '0');
- irc_addr_s <= (others => 'X');
+ irc_addr_s <= (others => '0');
reset_ab_error_s <= (others => '0');
+ state_o_s <= (others => 'X');
+ reset_reg_s <= '0';
+ reset_reg_wr_s <= '0';
- -- init variables
- ce_v := ce_i or ce_2_i;
-
- if ce_i = '1' then
- rd_v := rd_i;
- bls_v := bls_i;
- address_v := address_i;
- elsif ce_2_i = '1' then
- rd_v := rd_2_i;
- bls_v := bls_2_i;
- address_v := address_2_i;
- else
- rd_v := '0';
- bls_v := (others => '0');
- address_v := (others => '0');
- end if;
-
- -- Bus request
- if ce_v = '1' then
+ -- Incoming bus request
+ if next_ce_i = '1' then
-- Mapping:
- -- 0 & axis & irc / index - (all read from bram) (R/w)
+ -- 0 & axis & irc / index - (all read from bram) (R/W)
-- 1 & axis & 0 - status register (R/W)
- if address_v(3) = '0' then
- irc_addr_s <= address_i(2 downto 0);
- irc_en_s <= '1';
- irc_bls_s <= bls_i;
- data_o <= irc_data_s;
- elsif address_v(0) = '0' then
- if rd_v = '1' then
-
- case address_v(2 downto 1) is
- when "00" =>
- data_o(0) <= irc1_s.mark;
- data_o(1) <= irc1_s.ab_error;
- when "01" =>
- data_o(0) <= irc2_s.mark;
- data_o(1) <= irc2_s.ab_error;
- when "10" =>
- data_o(0) <= irc3_s.mark;
- data_o(1) <= irc3_s.ab_error;
- when "11" =>
- data_o(0) <= irc4_s.mark;
- data_o(1) <= irc4_s.ab_error;
- when others =>
- null;
- end case;
-
- data_o(31 downto 2) <= (others => '0');
-
- elsif bls_v(0) = '1' and data_i(0) = '1' then
- reset_ab_error_s(to_integer(unsigned(address_v(2 downto 1)))) <= '1';
+ -- 1 & 00 & 1 - reset
+ if address_i(3) = '0' then
+
+ irc_addr_s <= address_i(2 downto 0);
+ irc_en_s <= '1';
+ irc_bls_s <= bls_i;
+ irc_out_s <= '1';
+
+ -- Maybe these would be better to latch in next_ce_i cycle,
+ -- and then just pass them
+ elsif address_i(0) = '0' then
+
+ case address_i(2 downto 1) is
+ when "00" =>
+ state_o_s(0) <= irc_o_s(0).state.mark;
+ state_o_s(1) <= irc_o_s(0).state.ab_error;
+ when "01" =>
+ state_o_s(0) <= irc_o_s(1).state.mark;
+ state_o_s(1) <= irc_o_s(1).state.ab_error;
+ when "10" =>
+ state_o_s(0) <= irc_o_s(2).state.mark;
+ state_o_s(1) <= irc_o_s(2).state.ab_error;
+ when "11" =>
+ state_o_s(0) <= irc_o_s(3).state.mark;
+ state_o_s(1) <= irc_o_s(3).state.ab_error;
+ when others =>
+ null;
+ end case;
+
+ if bls_i(0) = '1' and data_i(1) = '1' then
+ reset_ab_error_s(to_integer(unsigned(address_i(2 downto 1)))) <= '1';
end if;
+ elsif address_i = "1001" then
+
+ if bls_i(0) = '1' then
+ reset_reg_s <= data_i(0);
+ reset_reg_wr_s <= '1';
+ else
+ -- Ugh, hack :-)
+ state_o_s(0) <= reset_reg_s;
+ state_o_s(1) <= '0';
+ end if;
+
end if;
end if;
end process;
-ta:
- process(clk_i)
+wire_out:
+ process(ce_s, irc_data_s, irc_out_r, state_o_r)
begin
- if clk_i = '1' and clk_i'event then
- ta_o <= rd_i;
- if rd_i = '0' and rd_2_i = '1' then
- ta_2_o <= rd_2_i;
- else
- ta_2_o <= '0';
- end if;
+ data_o <= (others => 'X');
+
+ if ce_s = '1' then
+ if irc_out_r = '1' then
+ data_o <= irc_data_s;
+ else
+ data_o(1 downto 0) <= state_o_r;
end if;
+
+ end if;
+
+
+ end process;
+
+update:
+ process
+ begin
+ wait until clk_i'event and clk_i= '1';
+ ce_s <= next_ce_i;
+ irc_out_r <= irc_out_s;
+ state_o_r <= state_o_s;
+
+ if reset_i = '1' then
+ reset_reg_r <= '1';
+ elsif reset_reg_wr_s = '1' then
+ reset_reg_r <= reset_reg_s;
+ end if;
+
end process;
end Behavioral;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
+
+-- LX Master bus interconnect
+entity bus_lxmaster is
+ port
+ (
+ clk_i : in std_logic;
+ reset_i : in std_logic;
+ -- Data bus
+ address_i : in std_logic_vector(8 downto 0);
+ next_ce_i : in std_logic;
+ data_i : in std_logic_vector(15 downto 0);
+ data_o : out std_logic_vector(15 downto 0);
+ --
+ bls_i : in std_logic_vector(1 downto 0);
+ -- Signals for LX Master
+ mosi_o : out std_logic;
+ clock_o : out std_logic;
+ sync_o : out std_logic
+ );
+end bus_lxmaster;
+
+architecture Behavioral of bus_lxmaster is
+begin
+
+master: lxmaster
+ port map
+ (
+ clk_i => clk_i,
+ reset_i => reset_i,
+ --
+ mosi_o => mosi_o,
+ clock_o => clock_o,
+ sync_o => sync_o,
+ -- BRAM
+ mem_clk_i => clk_i,
+ mem_en_i => next_ce_i,
+ mem_we_i => bls_i,
+ mem_addr_i => address_i,
+ mem_data_i => data_i,
+ mem_data_o => data_o
+ );
+
+
+end Behavioral;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
+
+-- Memory bus measurement
+-- Holds the signal for one clock to simulate longest route
+
+entity bus_measurement is
+ port
+ (
+ -- Clock
+ clk_i : in std_logic;
+ -- Reset
+ reset_i : in std_logic;
+ -- Chip enable
+ ce_i : in std_logic;
+ -- Address
+ address_i : in std_logic_vector(1 downto 0);
+ -- Data bus
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
+ -- Bus signals
+ bls_i : in std_logic_vector(3 downto 0)
+ );
+end bus_measurement;
+
+architecture Behavioral of bus_measurement is
+
+ -- Wiring
+ signal meas1_out_s : std_logic_vector(31 downto 0);
+ signal meas1_ce_s : std_logic;
+ --
+ signal meas2_out_s : std_logic_vector(31 downto 0);
+ signal meas2_ce_s : std_logic;
+
+begin
+
+ -- First measurement register (0xAAAAAAAA)
+measurement1: measurement_register
+ generic map
+ (
+ id_g => "10101010101010101010101010101010"
+ )
+ port map
+ (
+ clk_i => clk_i,
+ ce_i => meas1_ce_s,
+ switch_i => address_i(0),
+ reset_i => reset_i,
+ bls_i => bls_i,
+ data_i => data_i,
+ data_o => meas1_out_s
+ );
+
+ -- Second measurement register (=0x55555555)
+measurement2: measurement_register
+ generic map
+ (
+ id_g => "01010101010101010101010101010101"
+ )
+ port map
+ (
+ clk_i => clk_i,
+ ce_i => meas2_ce_s,
+ switch_i => address_i(0),
+ reset_i => reset_i,
+ bls_i => bls_i,
+ data_i => data_i,
+ data_o => meas2_out_s
+ );
+
+-- Bus process
+update:
+ process (ce_i, address_i, meas1_out_s, meas2_out_s)
+ begin
+
+ -- Defaults
+ meas1_ce_s <= '0';
+ meas2_ce_s <= '0';
+ data_o <= (others => 'X');
+
+ -- Chip Enable
+ if ce_i = '1' then
+ if address_i(1) = '0' then
+ meas1_ce_s <= '1';
+ data_o <= meas1_out_s;
+ else
+ meas2_ce_s <= '1';
+ data_o <= meas2_out_s;
+ end if;
+ end if;
+
+ end process;
+
+end Behavioral;
+
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
-use work.mbl_Pkg.all;
+use work.mbl_pkg.all;
use work.lx_rocon_pkg.all;
-- Connects tumbl to the Master CPU
port
(
-- Clock
- clk_100m_i : in std_logic;
- clk_50m_i : in std_logic;
+ clk_i : in std_logic;
-- Chip enable
- ce_100m_i : in std_logic;
+ ce_i : in std_logic;
-- Global Reset
- reset_100m_i : in std_logic;
+ reset_i : in std_logic;
-- Master CPU bus for the memory
- rd_100m_i : in std_logic;
- bls_100m_i : in std_logic_vector(3 downto 0);
- address_100m_i : in std_logic_vector(11 downto 0);
- data_100m_i : in std_logic_vector(31 downto 0);
- data_100m_o : out std_logic_vector(31 downto 0);
- ta_100m_o : out std_logic;
+ bls_i : in std_logic_vector(3 downto 0);
+ address_i : in std_logic_vector(11 downto 0);
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
-- Tumbl extrenal memory bus
- xmemb_sel_100m_o : out std_logic;
- xmemb_100m_i : in DMEMB2CORE_Type;
- xmemb_100m_o : out CORE2DMEMB_Type
+ xmemb_sel_o : out std_logic;
+ xmemb_i : in DMEMB2CORE_Type;
+ xmemb_o : out CORE2DMEMB_Type
);
end bus_tumbl;
architecture Behavioral of bus_tumbl is
-
- -- Internal state
- -- The following signals are driven by 100M clock
- signal tumbl_reset_100m_s : std_logic;
- signal tumbl_halt_100m_s : std_logic;
- signal tumbl_int_100m_s : std_logic;
- signal tumbl_trace_100m_s : std_logic;
-
- -- The following signals kick in at 50M clock
- signal tumbl_reset_50m_s : std_logic;
- signal tumbl_halt_50m_s : std_logic;
- signal tumbl_int_50m_s : std_logic;
- signal tumbl_trace_50m_s : std_logic;
-
- -- Trace kick (since this is "one cycle command", it needs req / ack)
- signal tumbl_trace_kick_50m_s : std_logic;
- signal tumbl_trace_kick_ack_50m_s : std_logic;
- signal tumbl_trace_kick_req_100m_s : std_logic;
-
- -- Tumbl PC (copy it with cpu clock and then wire further)
- signal tumbl_pc_50m_s : std_logic_vector(31 downto 0);
-
- -- Halting using halt instruction
- -- Driven by 50M clock
- signal tumbl_halted_50m_s : std_logic;
- signal tumbl_halt_code_50m_s : std_logic_vector(4 downto 0);
-
- -- Tumbl signals under 100M domain
- -- Driven by 100M clock
- signal tumbl_pc_100m_s : std_logic_vector(31 downto 0);
- signal tumbl_halted_100m_s : std_logic;
- signal tumbl_halt_code_100m_s : std_logic_vector(4 downto 0);
+ -- Types
+ type TUMBL_Input_Type is record
+ halt : std_logic;
+ int : std_logic;
+ trace : std_logic;
+ trace_kick : std_logic;
+ end record;
+
+ type TUMBL_State_Type is record
+ pc : std_logic_vector(31 downto 0);
+ halted : std_logic;
+ halt_code : std_logic_vector(4 downto 0);
+ end record;
+
+ -- Reset
+ signal tumbl_reset_s : std_logic;
+ -- Internals
+ signal tumbl_input_s : TUMBL_Input_Type;
+ signal tumbl_state_s : TUMBL_State_Type;
-- Internal memory signals
- -- Driven by 100M clock
- signal imem_en_100m_s : std_logic;
- signal dmem_en_100m_s : std_logic;
-
- signal imem_we_100m_s : std_logic_vector(3 downto 0);
- signal dmem_we_100m_s : std_logic_vector(3 downto 0);
+ signal imem_en_s : std_logic;
+ signal dmem_en_s : std_logic;
- signal imem_data_o_100m_s : std_logic_vector(31 downto 0);
- signal dmem_data_o_100m_s : std_logic_vector(31 downto 0);
+ signal imem_we_s : std_logic_vector(3 downto 0);
+ signal dmem_we_s : std_logic_vector(3 downto 0);
- -- Tumbl external memory
- -- Driven by 50M clock
- signal xmemb_sel_50m_s : std_logic;
- signal xmemb_50m_i_s : DMEMB2CORE_Type;
- signal xmemb_50m_o_s : CORE2DMEMB_Type;
+ signal imem_data_o_s : std_logic_vector(31 downto 0);
+ signal dmem_data_o_s : std_logic_vector(31 downto 0);
-- Internal bus structure
-- 12 address bits: 2 bits for selection, 10 bits for address
I_TUMBL: lx_rocon_tumbl
generic map
(
- IMEM_ABITS_g => 11,
- DMEM_ABITS_g => 12,
+ IMEM_ABITS_g => 9,
+ DMEM_ABITS_g => 10,
--
- USE_HW_MUL_g => true,
- USE_BARREL_g => true,
+ USE_HW_MUL_g => true,
+ USE_BARREL_g => true,
COMPATIBILITY_MODE_g => false
)
port map
(
- clk_i => clk_50m_i,
- rst_i => tumbl_reset_50m_s,
- halt_i => tumbl_halt_50m_s,
- int_i => tumbl_int_50m_s,
- trace_i => tumbl_trace_50m_s,
- trace_kick_i => tumbl_trace_kick_50m_s,
+ clk_i => clk_i,
+ rst_i => tumbl_reset_s,
+ halt_i => tumbl_input_s.halt,
+ int_i => tumbl_input_s.int,
+ trace_i => tumbl_input_s.trace,
+ trace_kick_i => tumbl_input_s.trace_kick,
- pc_o => tumbl_pc_50m_s,
- halted_o => tumbl_halted_50m_s,
- halt_code_o => tumbl_halt_code_50m_s,
+ pc_o => tumbl_state_s.pc,
+ halted_o => tumbl_state_s.halted,
+ halt_code_o => tumbl_state_s.halt_code,
-- Internal memory (instruction)
- imem_clk_i => clk_100m_i,
- imem_en_i => imem_en_100m_s,
- imem_we_i => imem_we_100m_s,
- imem_addr_i => address_100m_i(8 downto 0),
- imem_data_i => data_100m_i,
- imem_data_o => imem_data_o_100m_s,
+ imem_clk_i => clk_i,
+ imem_en_i => imem_en_s,
+ imem_we_i => imem_we_s,
+ imem_addr_i => address_i(8 downto 0),
+ imem_data_i => data_i,
+ imem_data_o => imem_data_o_s,
-- Internal memory (data)
- dmem_clk_i => clk_100m_i,
- dmem_en_i => dmem_en_100m_s,
- dmem_we_i => dmem_we_100m_s,
- dmem_addr_i => address_100m_i(9 downto 0),
- dmem_data_i => data_100m_i,
- dmem_data_o => dmem_data_o_100m_s,
+ dmem_clk_i => clk_i,
+ dmem_en_i => dmem_en_s,
+ dmem_we_i => dmem_we_s,
+ dmem_addr_i => address_i(9 downto 0),
+ dmem_data_i => data_i,
+ dmem_data_o => dmem_data_o_s,
-- External memory bus
- xmemb_sel_o => xmemb_sel_50m_s,
- xmemb_i => xmemb_50m_i_s,
- xmemb_o => xmemb_50m_o_s
+ xmemb_sel_o => xmemb_sel_o,
+ xmemb_i => xmemb_i,
+ xmemb_o => xmemb_o
);
- -- Enabling
- enabling: process(ce_100m_i, address_100m_i)
+-- Enabling
+enabling: process(ce_i, address_i)
begin
- if ce_100m_i = '1' and address_100m_i(11 downto 10) = "00" then
- imem_en_100m_s <= '1';
+ if ce_i = '1' and address_i(11 downto 10) = "00" then
+ imem_en_s <= '1';
else
- imem_en_100m_s <= '0';
+ imem_en_s <= '0';
end if;
- if ce_100m_i = '1' and address_100m_i(11 downto 10) = "01" then
- dmem_en_100m_s <= '1';
+ if ce_i = '1' and address_i(11 downto 10) = "01" then
+ dmem_en_s <= '1';
else
- dmem_en_100m_s <= '0';
+ dmem_en_s <= '0';
end if;
end process;
- -- Wiring
- -- NOTE: This is only modifying signals inside 100m domain
- wiring: process(ce_100m_i, rd_100m_i, bls_100m_i, address_100m_i, imem_en_100m_s, imem_data_o_100m_s, dmem_en_100m_s,
- dmem_data_o_100m_s, tumbl_reset_100m_s, tumbl_int_100m_s, tumbl_halt_100m_s, tumbl_trace_100m_s,
- tumbl_halted_100m_s, tumbl_halt_code_100m_s, tumbl_pc_100m_s)
+-- Wiring
+wiring:
+ process(ce_i, bls_i, address_i, imem_en_s, imem_data_o_s, dmem_en_s,
+ dmem_data_o_s, tumbl_reset_s, tumbl_input_s, tumbl_state_s)
begin
- if imem_en_100m_s = '1' then
- imem_we_100m_s <= bls_100m_i;
+ if imem_en_s = '1' then
+ imem_we_s <= bls_i;
else
- imem_we_100m_s <= "0000";
+ imem_we_s <= "0000";
end if;
- if dmem_en_100m_s = '1' then
- dmem_we_100m_s <= bls_100m_i;
+ if dmem_en_s = '1' then
+ dmem_we_s <= bls_i;
else
- dmem_we_100m_s <= "0000";
+ dmem_we_s <= "0000";
end if;
- if imem_en_100m_s = '1' then
- data_100m_o <= imem_data_o_100m_s;
- elsif dmem_en_100m_s = '1' then
- data_100m_o <= dmem_data_o_100m_s;
- elsif ce_100m_i = '1' and rd_100m_i = '1' and address_100m_i(11 downto 10) = "11" then
- if address_100m_i(9 downto 0) = "0000000000" then
- data_100m_o(0) <= tumbl_reset_100m_s;
- data_100m_o(1) <= tumbl_int_100m_s;
- data_100m_o(2) <= tumbl_halt_100m_s;
- data_100m_o(3) <= tumbl_trace_100m_s;
- data_100m_o(4) <= tumbl_halted_100m_s;
- data_100m_o(31 downto 5) <= (others => '0');
- elsif address_100m_i(9 downto 0) = "0000000010" then
- data_100m_o <= tumbl_pc_100m_s;
- elsif address_100m_i(9 downto 0) = "0000000011" then
- data_100m_o(4 downto 0) <= tumbl_halt_code_100m_s;
- data_100m_o(31 downto 5) <= (others => '0');
+ if imem_en_s = '1' then
+ data_o <= imem_data_o_s;
+ elsif dmem_en_s = '1' then
+ data_o <= dmem_data_o_s;
+ elsif ce_i = '1' and address_i(11 downto 10) = "11" then
+ if address_i(9 downto 0) = "0000000000" then
+ data_o(0) <= tumbl_reset_s;
+ data_o(1) <= tumbl_input_s.int;
+ data_o(2) <= tumbl_input_s.halt;
+ data_o(3) <= tumbl_input_s.trace;
+ data_o(4) <= tumbl_state_s.halted;
+ data_o(31 downto 5) <= (others => '0');
+ elsif address_i(9 downto 0) = "0000000010" then
+ data_o <= tumbl_state_s.pc;
+ elsif address_i(9 downto 0) = "0000000011" then
+ data_o(4 downto 0) <= tumbl_state_s.halt_code;
+ data_o(31 downto 5) <= (others => '0');
else
- data_100m_o <= (others => 'X');
+ data_o <= (others => 'X');
end if;
else
- data_100m_o <= (others => 'X');
+ data_o <= (others => 'X');
end if;
end process;
- -- Transaction acknowledge and writing to registers
- -- The clocks are synchronous!
- update: process(clk_100m_i)
+-- Transaction acknowledge and writing to registers
+update:
+ process
begin
- -- Update on the 100 MHz clock
- if clk_100m_i = '1' and clk_100m_i'event then
- ta_100m_o <= '0';
+ -- Update
+ wait until clk_i'event and clk_i = '1';
- -- Copy the 50M driven signals to 100M domain
- tumbl_pc_100m_s <= tumbl_pc_50m_s;
- tumbl_halted_100m_s <= tumbl_halted_50m_s;
- tumbl_halt_code_100m_s <= tumbl_halt_code_50m_s;
- --
- xmemb_sel_100m_o <= xmemb_sel_50m_s;
- xmemb_100m_o <= xmemb_50m_o_s;
+ tumbl_input_s.trace_kick <= '0';
- if imem_en_100m_s = '1' or dmem_en_100m_s = '1' then
- ta_100m_o <= '1';
- end if;
+ if reset_i = '1' then
+ tumbl_reset_s <= '1';
+ tumbl_input_s.int <= '0';
+ tumbl_input_s.halt <= '0';
+ tumbl_input_s.trace <= '0';
- if reset_100m_i = '1' then
- tumbl_reset_100m_s <= '1';
- tumbl_int_100m_s <= '0';
- tumbl_halt_100m_s <= '0';
- tumbl_trace_100m_s <= '0';
- tumbl_trace_kick_req_100m_s <= '0';
- else
- if tumbl_trace_kick_ack_50m_s = '1' then
- tumbl_trace_kick_req_100m_s <= '0';
- end if;
+ else
- if ce_100m_i = '1' and address_100m_i(11 downto 10) = "11" then
- if bls_100m_i(0) = '1' then
- if address_100m_i(9 downto 0) = "0000000000" then
- tumbl_reset_100m_s <= data_100m_i(0);
- tumbl_int_100m_s <= data_100m_i(1);
- tumbl_halt_100m_s <= data_100m_i(2);
- tumbl_trace_100m_s <= data_100m_i(3);
- elsif address_100m_i(9 downto 0) = "0000000001" then
- if data_100m_i(0) = '1' then
- tumbl_trace_kick_req_100m_s <= '1';
- end if;
+ if ce_i = '1' and address_i(11 downto 10) = "11" then
+ if bls_i(0) = '1' then
+ if address_i(9 downto 0) = "0000000000" then
+ tumbl_reset_s <= data_i(0);
+ tumbl_input_s.int <= data_i(1);
+ tumbl_input_s.halt <= data_i(2);
+ tumbl_input_s.trace <= data_i(3);
+ elsif address_i(9 downto 0) = "0000000001" then
+ if data_i(0) = '1' then
+ tumbl_input_s.trace_kick <= '1';
end if;
end if;
-
- if rd_100m_i = '1' then
- ta_100m_o <= '1';
- end if;
- end if;
- end if;
-
- end if;
- end process;
-
- -- Update tracing
- tumbl: process(clk_50m_i)
- begin
-
- -- Update on the 50 MHz clock
- if clk_50m_i = '1' and clk_50m_i'event then
-
- -- Copy the 100M driven signals to their 50M domain
- -- and then route them further
- tumbl_reset_50m_s <= tumbl_reset_100m_s;
- tumbl_int_50m_s <= tumbl_int_100m_s;
- tumbl_halt_50m_s <= tumbl_halt_100m_s;
- tumbl_trace_50m_s <= tumbl_trace_100m_s;
- --
- xmemb_50m_i_s <= xmemb_100m_i;
-
- if reset_100m_i = '1' then
- tumbl_trace_kick_50m_s <= '0';
- tumbl_trace_kick_ack_50m_s <= '0';
- else
- if tumbl_trace_kick_50m_s = '0' and tumbl_trace_kick_req_100m_s = '1' then
- tumbl_trace_kick_50m_s <= '1';
- tumbl_trace_kick_ack_50m_s <= '1';
- else
- tumbl_trace_kick_50m_s <= '0';
end if;
end if;
-
- if tumbl_trace_kick_req_100m_s = '0' then
- tumbl_trace_kick_ack_50m_s <= '0';
- end if;
-
end if;
end process;
+++ /dev/null
-library ieee;
-use ieee.std_logic_1164.all;
-use ieee.std_logic_arith.all;
-use ieee.std_logic_unsigned.all;
-use ieee.numeric_std.all;
-use work.lx_rocon_pkg.all;
-
--- Memory bus interconnect between tumbl and master cpu
-
-entity bus_tumbl_interconnect is
- generic
- (
- )
- port
- (
- -- Clock
- clk_100m_i : in std_logic;
- clk_50m_i : in std_logic;
- -- Global Reset
- reset_100m_i : in std_logic;
- -- Master CPU memory bus
- rd_100m_i : in std_logic;
- bls_100m_i : in std_logic_vector(3 downto 0);
- address_100m_i : in std_logic_vector(11 downto 0);
- data_100m_i : in std_logic_vector(31 downto 0);
- data_100m_o : out std_logic_vector(31 downto 0);
- ta_100m_o : out std_logic;
- -- Tumbl memory bus
- XMEMB_sel_50m_i : in std_logic;
- XMEMB_50m_i : in CORE2DMEMB_Type
- XMEMB_50m_o : out DMEMB2CORE_Type;
- -- BRAM port (has to be 100 MHz clocked)
- mem_en_o : out std_logic;
- mem_we_o : out std_logic_vector(3 downto 0);
- mem_addr_o : out std_logic_vector(8 downto 0);
- mem_data_i : in std_logic_vector(31 downto 0);
- mem_data_o : out std_logic_vector(31 downto 0);
-
- );
-end bus_tumbl_interconnect;
-
-architecture Behavioral of bus_tumbl_interconnect is
-
-begin
-
-
-end Behavioral;
-
+++ /dev/null
-library ieee;
-use ieee.std_logic_1164.all;
-use ieee.std_logic_arith.all;
-use ieee.std_logic_unsigned.all;
-use ieee.numeric_std.all;
-
--- Calibration read register - returns fixed value
--- Uses clock for writing the ID to the bus
-
-entity calibration_read_register is
- generic
- (
- id_g : std_logic_vector(31 downto 0) := (others => '0')
- );
- port
- (
- -- Data bus (read only)
- data_o : out std_logic_vector(31 downto 0);
- -- Bus signals
- rd_i : in std_logic;
- ta_o : out std_logic
- );
-end calibration_read_register;
-
-architecture Behavioral of calibration_read_register is
-begin
-
-memory_bus:
- process(rd_i)
- begin
- ta_o <= rd_i;
- data_o <= id_g;
- end process;
-
-end Behavioral;
+++ /dev/null
-library ieee;
-use ieee.std_logic_1164.all;
-use ieee.std_logic_arith.all;
-use ieee.std_logic_unsigned.all;
-use ieee.numeric_std.all;
-
--- Calibration write register
--- Used to calibrate writing timing
-
-entity calibration_write_register is
- port
- (
- -- Clock
- clk_i : in std_logic;
- -- Reset
- reset_i : in std_logic;
- -- Chip enable
- ce_i : in std_logic;
- -- Data bus
- data_i : in std_logic_vector(31 downto 0);
- data_o : out std_logic_vector(31 downto 0);
- -- Bus signals
- rd_i : in std_logic;
- bls_i : in std_logic_vector(3 downto 0);
- ta_o : out std_logic
- );
-end calibration_write_register;
-
-architecture Behavioral of calibration_write_register is
- signal value_s : std_logic_vector(31 downto 0);
-begin
-
- -- Read is immideate
- memory_bus_read: process(rd_i, value_s)
- begin
- ta_o <= rd_i;
- data_o <= value_s;
- end process;
-
- -- Write waits for clock
- memory_bus_write: process(clk_i)
- begin
-
- if clk_i = '1' and clk_i'event then
-
- if reset_i = '1' then
- value_s <= (others => '0');
- else
-
- if ce_i = '1' and bls_i /= "0000" then
-
- if bls_i(0) = '1' then
- value_s(7 downto 0) <= data_i(7 downto 0);
- end if;
- if bls_i(1) = '1' then
- value_s(15 downto 8) <= data_i(15 downto 8);
- end if;
- if bls_i(2) = '1' then
- value_s(23 downto 16) <= data_i(23 downto 16);
- end if;
- if bls_i(3) = '1' then
- value_s(31 downto 24) <= data_i(31 downto 24);
- end if;
-
- end if;
- end if;
- end if;
-
- end process;
-
-end Behavioral;
-
--- /dev/null
+--
+-- * CRC-8 generator *
+--
+-- part of LXPWR motion control board (c) PiKRON Ltd
+-- idea by Pavel Pisa PiKRON Ltd <pisa@cmp.felk.cvut.cz>
+-- code by Marek Peca <mp@duch.cz>
+-- 01/2013
+--
+-- license: GNU GPLv3
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity crc is
+ port
+ (
+ clk_i : in std_logic;
+ reset_i : in std_logic;
+ input_i : in std_logic;
+ crc_o : out std_logic_vector(7 downto 0)
+ );
+end crc;
+
+architecture behavioral of crc is
+ signal reg_s, next_reg_s : std_logic_vector(7 downto 0);
+begin
+ crc_o <= next_reg_s;
+
+comb: process (reset_i, input_i, reg_s)
+ begin
+ if reset_i = '1' then
+ next_reg_s <= (others => '1');
+ else
+ next_reg_s(4 downto 0) <= reg_s(5 downto 1);
+ next_reg_s(5) <= reg_s(0) xor reg_s(6);
+ next_reg_s(6) <= reg_s(0) xor reg_s(7);
+ next_reg_s(7) <= reg_s(0) xor input_i;
+ end if;
+ end process;
+
+seq: process
+ begin
+ wait until clk_i'event and clk_i = '1';
+ reg_s <= next_reg_s;
+ end process;
+
+end behavioral;
+++ /dev/null
-library ieee;
-use ieee.std_logic_1164.all;
-use ieee.std_logic_arith.all;
-use ieee.std_logic_unsigned.all;
-use ieee.numeric_std.all;
-
--- D circuit
-
-entity dff is
- port
- (
- clk_i : in std_logic;
- reset_i : in std_logic;
- d_i : in std_logic;
- q_o : out std_logic
- );
-end dff2;
-
-architecture behavioral of dff is
-begin
-
-seq:
- process(clk_i)
- begin
- if clk_i = '1' and clk_i'event then
- if reset_i = '1' then
- q_o <= '0';
- else
- q_o <= d_i;
- end if;
- end if;
- end process;
-
-end behavioral;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
-- D circuit (filtered)
q_o <= data_s;
seq:
- process(clk_i)
+ process
begin
- if clk_i = '1' and clk_i'event then
- if reset_i = '1' then
- last_d_s <= '0';
- data_s <= '0';
- else
- if d_i = last_d_s then
- data_s <= d_i;
- end if;
+ wait until clk_i'event and clk_i = '1';
+ if reset_i = '1' then
+ last_d_s <= '0';
+ data_s <= '0';
+ else
+ if d_i = last_d_s then
+ data_s <= d_i;
end if;
-
- last_d_s <= d_i;
end if;
+
+ last_d_s <= d_i;
end process;
end behavioral;
op_o <= num_s(1 downto 0);
inc:
- process (clk_i)
+ process
begin
- if clk_i = '1' and clk_i'event then
- if reset_i = '1' then
- num_s <= (others => '0');
- else
- num_s <= std_logic_vector(num_s + 1);
- end if;
+ wait until clk_i'event and clk_i = '1';
+
+ if reset_i = '1' then
+ num_s <= (others => '0');
+ else
+ num_s <= std_logic_vector(num_s + 1);
end if;
end process;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
-use work.mbl_Pkg.all;
+use work.mbl_pkg.all;
use work.lx_rocon_pkg.all;
-- Main unit in the IRC cooprocessor
+-- This could be written as generic (n IRC axes)
+-- >100 MHz
entity irc_proc_main is
port
(
clk_i : in std_logic;
reset_i : in std_logic;
-- Signals from IRC
- irc1_i : in IRC_SLIM_OUTPUT_Type;
- irc2_i : in IRC_SLIM_OUTPUT_Type;
- irc3_i : in IRC_SLIM_OUTPUT_Type;
- irc4_i : in IRC_SLIM_OUTPUT_Type;
+ irc_i : in IRC_COUNT_OUTPUT_Array_Type(3 downto 0);
-- Index resetting
irc_index_reset_o : out std_logic_vector(3 downto 0);
- -- BRAM access (the other port)
+ -- BRAM access
mem_clk_i : in std_logic;
mem_en_i : in std_logic;
mem_we_i : in std_logic_vector(3 downto 0);
architecture Behavioral of irc_proc_main is
- -- IRC Output array
- type IRC_OUTPUT_Array_Type is array (0 to 3) of IRC_SLIM_OUTPUT_Type;
+ signal op_s : std_logic_vector(1 downto 0);
+ signal axis_s : std_logic_vector(1 downto 0);
--
- signal op_s : std_logic_vector(1 downto 0);
- signal axis_s : std_logic_vector(1 downto 0);
+ signal op_r : std_logic_vector(1 downto 0);
+ signal axis_r : std_logic_vector(1 downto 0);
--
- signal op_r : std_logic_vector(1 downto 0);
- signal axis_r : std_logic_vector(1 downto 0);
- --
- signal irc_array_s : IRC_OUTPUT_Array_Type;
- --
- signal ram_en_s : std_logic;
- signal ram_addr_s : std_logic_vector(2 downto 0);
- signal ram_write_s : std_logic_vector(3 downto 0);
- signal ram_data_i_s : std_logic_vector(31 downto 0);
- signal ram_data_o_s : std_logic_vector(31 downto 0);
+ signal ram_en_s : std_logic;
+ signal ram_addr_s : std_logic_vector(2 downto 0);
+ signal ram_write_s : std_logic_vector(3 downto 0);
+ signal ram_data_i_s : std_logic_vector(31 downto 0);
+ signal ram_data_o_s : std_logic_vector(31 downto 0);
begin
-- RAM address (delayed by a cycle when writing)
ram_addr_s <= (axis_r & op_r(1)) when ram_write_s = "1111" else (axis_s & op_s(1));
- -- IRC packing
- irc_array_s(0) <= irc1_i;
- irc_array_s(1) <= irc2_i;
- irc_array_s(2) <= irc3_i;
- irc_array_s(3) <= irc4_i;
seq:
- process (clk_i)
+ process
variable skip_v : std_logic;
- variable irc_v : IRC_SLIM_OUTPUT_Type;
+ variable irc_v : IRC_COUNT_OUTPUT_Type;
variable res_v : std_logic_vector(31 downto 0);
variable count_v : std_logic_vector(31 downto 0);
begin
- if clk_i = '1' and clk_i'event then
-
- -- Init (reset the index reset events)
- irc_index_reset_o <= (others => '0');
-
- if reset_i = '1' then
- -- Reset
- ram_en_s <= '1';
- ram_write_s <= "0000";
- ram_data_i_s <= (others => '0');
- --
- op_r <= (others => '0');
- axis_r <= (others => '0');
-
- else
- -- Defaults
- skip_v := '1';
- ram_en_s <= '0';
- ram_write_s <= "0000";
-
- -- Caluclating step
- if op_r(1) = '0' then
- -- get source
- irc_v := irc_array_s(to_integer(unsigned(axis_s)));
-
- if op_r(0) = '0' then
- count_v(7 downto 0) := irc_v.qcount;
+ wait until clk_i'event and clk_i = '1';
+
+ -- Init (reset the index reset events)
+ irc_index_reset_o <= (others => '0');
+
+ if reset_i = '1' then
+ -- Reset
+ ram_en_s <= '1';
+ ram_write_s <= "0000";
+ ram_data_i_s <= (others => '0');
+ --
+ op_r <= (others => '0');
+ axis_r <= (others => '0');
+
+ else
+ -- Defaults
+ skip_v := '1';
+ ram_en_s <= '0';
+ ram_write_s <= "0000";
+
+ -- Caluclating step
+ if op_r(1) = '0' then
+ -- get source
+ irc_v := irc_i(to_integer(unsigned(axis_s)));
+
+ if op_r(0) = '0' then
+ count_v(7 downto 0) := irc_v.qcount;
+ skip_v := '0';
+ else
+ if irc_v.index_event = '1' then
+ irc_index_reset_o(to_integer(unsigned(axis_s))) <= '1';
+ count_v(7 downto 0) := irc_v.index;
skip_v := '0';
+ end if;
+ end if;
+
+ if skip_v = '0' then
+ -- signed extension
+ if count_v(7) = '1' then
+ count_v(31 downto 8) := (others => '1');
else
- if irc_v.index_event = '1' then
- irc_index_reset_o(to_integer(unsigned(axis_s))) <= '1';
- count_v(7 downto 0) := irc_v.index;
- skip_v := '0';
- end if;
+ count_v(31 downto 8) := (others => '0');
end if;
- if skip_v = '0' then
- -- signed extension
- if count_v(7) = '1' then
- count_v(31 downto 8) := (others => '1');
- else
- count_v(31 downto 8) := (others => '0');
- end if;
-
- -- calculate qs8
- ep_add32nc(count_v, not ram_data_o_s, '1', res_v);
-
- -- extend it
- count_v(7 downto 0) := res_v(7 downto 0);
-
- if res_v(7) = '1' then
- count_v(31 downto 8) := (others => '1');
- else
- count_v(31 downto 8) := (others => '0');
- end if;
-
- -- add it back
- ep_add32nc(ram_data_o_s, count_v, '0', res_v);
-
- -- store it
- ram_en_s <= '1';
- ram_write_s <= "1111";
- ram_data_i_s <= res_v;
+ -- calculate qs8
+ ep_add32nc(count_v, not ram_data_o_s, '1', res_v);
+
+ -- extend it
+ count_v(7 downto 0) := res_v(7 downto 0);
+
+ if res_v(7) = '1' then
+ count_v(31 downto 8) := (others => '1');
+ else
+ count_v(31 downto 8) := (others => '0');
end if;
- end if;
+ -- add it back
+ ep_add32nc(ram_data_o_s, count_v, '0', res_v);
- -- Read next stored IRC
- if op_r = "10" then
- ram_en_s <= '1';
+ -- store it
+ ram_en_s <= '1';
+ ram_write_s <= "1111";
+ ram_data_i_s <= res_v;
end if;
end if;
- op_r <= op_s;
- axis_r <= axis_s;
+ -- Read next stored IRC
+ -- FIXME: Wire the enabling directly so it takes one cycle less,
+ -- although op_r = "11" is reserved for potential extesion for 2nd index,
+ -- so not very important
+ if op_r = "10" then
+ ram_en_s <= '1';
+ end if;
end if;
+ op_r <= op_s;
+ axis_r <= axis_s;
+
end process;
end Behavioral;
end irc_reader;
architecture rtl of irc_reader is
-
begin
- dff_mark: dff2
+dff_mark: dff2
port map
(
clk_i => clk_i,
reset_i => '0',
d_i => irc_i.mark,
- q_o => irc_o.mark
+ q_o => irc_o.state.mark
);
- qctr: qcounter
+qctr: qcounter
port map
(
clk_i => clk_i,
index0_i => irc_i.index,
reset_index_event_i => reset_index_event_i,
reset_ab_error_i => reset_ab_error_i,
- qcount_o => irc_o.qcount,
- qcount_index_o => irc_o.index,
- ab_error_o => irc_o.ab_error,
+ qcount_o => irc_o.count.qcount,
+ qcount_index_o => irc_o.count.index,
+ ab_error_o => irc_o.state.ab_error,
ab_event_o => open,
- index_event_o => irc_o.index_event,
+ index_event_o => irc_o.count.index_event,
a_rise_o => open,
a_fall_o => open,
b_rise_o => open,
# ====================================================================
# Clock
-#NET CLK_CPU PERIOD = 13.8ns HIGH 50%;
-#NET CLK_CPU LOC = P15 | IOSTANDARD = LVCMOS33;
-NET CLK_50M PERIOD = 20.0ns HIGH 50%;
-NET CLK_50M LOC = P14 | IOSTANDARD = LVCMOS33;
+#NET CLK_CPU PERIOD = 13.88ns HIGH 50%;
+#NET CLK_CPU LOC = P15 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET CLK_50M PERIOD = 20.00ns HIGH 50%;
+NET CLK_50M LOC = P14 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
# Reset (active LOW)
-NET INIT LOC = P39 | IOSTANDARD = LVCMOS33;
+NET INIT LOC = P39 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
# Memory peripheral
NET CS0_XC LOC = P64 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
NET DATA<31> LOC = P137 | IOSTANDARD = LVCMOS33 | SLEW = SLOW;
# IRC
-NET IRC1_A LOC = P2 | IOSTANDARD = LVCMOS33;
-NET IRC1_B LOC = P6 | IOSTANDARD = LVCMOS33;
-NET IRC1_INDEX LOC = P7 | IOSTANDARD = LVCMOS33;
-NET IRC1_MARK LOC = P5 | IOSTANDARD = LVCMOS33;
+NET IRC1_A LOC = P2 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC1_B LOC = P6 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC1_INDEX LOC = P7 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC1_MARK LOC = P5 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
-NET IRC2_A LOC = P8 | IOSTANDARD = LVCMOS33;
-NET IRC2_B LOC = P10 | IOSTANDARD = LVCMOS33;
-NET IRC2_INDEX LOC = P11 | IOSTANDARD = LVCMOS33;
-NET IRC2_MARK LOC = P9 | IOSTANDARD = LVCMOS33;
+NET IRC2_A LOC = P8 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC2_B LOC = P10 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC2_INDEX LOC = P11 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC2_MARK LOC = P9 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
-NET IRC3_A LOC = P12 | IOSTANDARD = LVCMOS33;
-NET IRC3_B LOC = P17 | IOSTANDARD = LVCMOS33;
-NET IRC3_INDEX LOC = P21 | IOSTANDARD = LVCMOS33;
-NET IRC3_MARK LOC = P16 | IOSTANDARD = LVCMOS33;
+NET IRC3_A LOC = P12 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC3_B LOC = P17 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC3_INDEX LOC = P21 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC3_MARK LOC = P16 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
-NET IRC4_A LOC = P22 | IOSTANDARD = LVCMOS33;
-NET IRC4_B LOC = P24 | IOSTANDARD = LVCMOS33;
-NET IRC4_INDEX LOC = P26 | IOSTANDARD = LVCMOS33;
-NET IRC4_MARK LOC = P23 | IOSTANDARD = LVCMOS33;
+NET IRC4_A LOC = P22 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC4_B LOC = P24 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC4_INDEX LOC = P26 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET IRC4_MARK LOC = P23 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
# ====================================================================
-# OUTPUTS
+# S1 Interface
# ====================================================================
-#NET OUTPUT<47> LOC = P112 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<48> LOC = P111 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<49> LOC = P105 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<50> LOC = P104 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<51> LOC = P102 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<52> LOC = P101 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<53> LOC = P100 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<54> LOC = P99 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<55> LOC = P98 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<56> LOC = P97 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<57> LOC = P95 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<58> LOC = P94 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<59> LOC = P93 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<60> LOC = P92 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<61> LOC = P88 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<62> LOC = P87 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<63> LOC = P85 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<64> LOC = P84 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<65> LOC = P83 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<66> LOC = P82 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<67> LOC = P81 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<68> LOC = P80 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<69> LOC = P79 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<70> LOC = P78 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<71> LOC = P75 | IOSTANDARD = LVCMOS33;
-#NET OUTPUT<72> LOC = P74 | IOSTANDARD = LVCMOS33;
+NET S1_CLK_OUT LOC = P94 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET S1_SYNC_OUT LOC = P101 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
+NET S1_MOSI LOC = P97 | IOSTANDARD = LVCMOS33 | SLEW = FAST;
a_settings.acc_dev = 0;
}
+void read_input(axis_io* io)
+{
+ io->irc_last = io->irc;
+ io->irc = *((int32_t*)0x8000);
+}
+
void update_axis(axis_settings *settings, axis_io* io)
{
int i;
{
while (1)
{
+ read_input(&a_io);
update_axis(&a_settings, &a_io);
a_io.irc = irc_a_reg;
a_io.current = current_a_reg;
count++;
}
}
-
addi r6, r0, _sdata
addi r7, r0, _edata
rsub r18, r6, r7
- blei r18, .Lenddata
+ brci le, r18, .Lenddata
.Lloopdata:
swi r0, r6, 0
addi r6, r6, 4
rsub r18, r6, r7
- bgti r18, .Lloopdata
+ brci gt, r18, .Lloopdata
.Lenddata:
/* Init default values */
brli r15, init_defvals
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
-use work.mbl_Pkg.all;
+use work.mbl_pkg.all;
use work.lx_rocon_pkg.all;
-- 4 kB data memory for Thumbl core
-- Memory wiring for Tumbl
clk_i : in std_logic;
ce_i : in std_logic;
- adr_i : in std_logic_vector(11 downto 2);
- wre_i : in std_logic;
- bsel_i : in std_logic_vector(3 downto 0);
+ adr_i : in std_logic_vector(9 downto 0);
+ bls_i : in std_logic_vector(3 downto 0);
dat_i : in std_logic_vector(31 downto 0);
dat_o : out std_logic_vector(31 downto 0);
-- Memory wiring for Master CPU
end lx_rocon_dmem;
architecture rtl of lx_rocon_dmem is
-
- signal wre_i_s : std_logic_vector(3 downto 0);
-
begin
- wre_i_s <= bsel_i when (wre_i = '1') else "0000";
-
- I_RAMB: xilinx_dualport_bram_write_first
+I_RAMB: xilinx_dualport_bram_write_first
generic map
(
we_width => 4,
clka => clk_i,
rsta => '0',
ena => ce_i,
- wea => wre_i_s,
- addra => adr_i(11 downto 2),
+ wea => bls_i,
+ addra => adr_i,
dina => dat_i,
douta => dat_o,
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
-use work.mbl_Pkg.all;
+use work.mbl_pkg.all;
use work.lx_rocon_pkg.all;
-- 32x32b General Puprose Registers for Tumbl Core
I_rA: xilinx_dualport_bram_write_first
generic map
(
- byte_width => 32,
- we_width => 1,
+ byte_width => 32,
+ we_width => 1,
address_width => 5
)
port map
(
- clka => clk_i,
- rsta => rst_i,
- ena => ena_rA_s,
+ clka => clk_i,
+ rsta => rst_i,
+ ena => ena_rA_s,
wea(0) => rst_i,
- addra => rdix_rA_s,
- dina => C_32_ZEROS,
- douta => rA_DOA_s,
+ addra => rdix_rA_s,
+ dina => C_32_ZEROS,
+ douta => rA_DOA_s,
-- Write-back
- clkb => clk_i,
- rstb => rst_i,
- enb => clken_s,
+ clkb => clk_i,
+ rstb => rst_i,
+ enb => clken_s,
web(0) => wre_rD_s,
- addrb => MEM_WRB_i.wrix_rD,
- dinb => MEM_WRB_i.data_rD,
- doutb => rA_DOB_s
+ addrb => MEM_WRB_i.wrix_rD,
+ dinb => MEM_WRB_i.data_rD,
+ doutb => rA_DOB_s
);
I_rB: xilinx_dualport_bram_write_first
generic map
(
- byte_width => 32,
- we_width => 1,
+ byte_width => 32,
+ we_width => 1,
address_width => 5
)
port map
(
- clka => clk_i,
- rsta => rst_i,
- ena => ena_rB_s,
+ clka => clk_i,
+ rsta => rst_i,
+ ena => ena_rB_s,
wea(0) => rst_i,
- addra => rdix_rB_s,
- dina => C_32_ZEROS,
- douta => rB_DOA_s,
+ addra => rdix_rB_s,
+ dina => C_32_ZEROS,
+ douta => rB_DOA_s,
-- Write-back
- clkb => clk_i,
- rstb => rst_i,
- enb => clken_s,
+ clkb => clk_i,
+ rstb => rst_i,
+ enb => clken_s,
web(0) => wre_rD_s,
- addrb => MEM_WRB_i.wrix_rD,
- dinb => MEM_WRB_i.data_rD,
- doutb => rB_DOB_s
+ addrb => MEM_WRB_i.wrix_rD,
+ dinb => MEM_WRB_i.data_rD,
+ doutb => rB_DOB_s
);
I_rD: xilinx_dualport_bram_write_first
generic map
(
- byte_width => 32,
- we_width => 1,
+ byte_width => 32,
+ we_width => 1,
address_width => 5
)
port map
(
- clka => clk_i,
- rsta => rst_i,
- ena => ena_rD_s,
+ clka => clk_i,
+ rsta => rst_i,
+ ena => ena_rD_s,
wea(0) => rst_i,
- addra => rdix_rD_s,
- dina => C_32_ZEROS,
- douta => rD_DOA_s,
+ addra => rdix_rD_s,
+ dina => C_32_ZEROS,
+ douta => rD_DOA_s,
-- Write-back
- clkb => clk_i,
- rstb => rst_i,
- enb => clken_s,
+ clkb => clk_i,
+ rstb => rst_i,
+ enb => clken_s,
web(0) => wre_rD_s,
- addrb => MEM_WRB_i.wrix_rD,
- dinb => MEM_WRB_i.data_rD,
- doutb => rD_DOB_s
+ addrb => MEM_WRB_i.wrix_rD,
+ dinb => MEM_WRB_i.data_rD,
+ doutb => rD_DOB_s
);
- p_regd: process(clk_i)
+p_regd:
+ process
begin
- if clk_i = '1' and clk_i'event then
- if (clken_i = '1') then
- wthru_rA_r <= not ena_rA_s;
- wthru_rB_r <= not ena_rB_s;
- wthru_rD_r <= not ena_rD_s;
- end if;
+ wait until clk_i'event and clk_i = '1';
+ if (clken_i = '1') then
+ wthru_rA_r <= not ena_rA_s;
+ wthru_rB_r <= not ena_rB_s;
+ wthru_rD_r <= not ena_rD_s;
end if;
end process;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
-use work.mbl_Pkg.all;
+use work.mbl_pkg.all;
use work.lx_rocon_pkg.all;
-- 2 kB instruction memory for Thumbl core
-- Memory wiring for Tumbl
clk_i : in std_logic;
cs_i : in std_logic;
- adr_i : in std_logic_vector(10 downto 2);
+ adr_i : in std_logic_vector(8 downto 0);
dat_o : out std_logic_vector(31 downto 0);
-- Memory wiring for Master CPU
clk_m : in std_logic;
architecture rtl of lx_rocon_imem is
begin
- I_RAMB: xilinx_dualport_bram_write_first
+I_RAMB: xilinx_dualport_bram_write_first
generic map
(
we_width => 4,
rsta => '0',
ena => cs_i,
wea => "0000",
- addra => adr_i(10 downto 2),
+ addra => adr_i,
dina => C_32_ZEROS,
douta => dat_o,
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
-use work.mbl_Pkg.all;
+use work.mbl_pkg.all;
use work.lx_rocon_pkg.all;
-- Tumbl configured as a coprocessor for lx_rocon
--- Uses 10 bits width address bus with HW barrel and multiplier
+-- Uses 12 bits width address bus with HW barrel and multiplier
entity lx_rocon_tumbl is
generic
(
- IMEM_ABITS_g : positive := 11;
- DMEM_ABITS_g : positive := 12;
+ -- This is for 32-bit addressing
+ IMEM_ABITS_g : positive := 9;
+ DMEM_ABITS_g : positive := 10;
--
USE_HW_MUL_g : boolean := true;
USE_BARREL_g : boolean := true;
architecture rtl of lx_rocon_tumbl is
- constant DMEM_TEST_c : std_logic_vector((31-DMEM_ABITS_g) downto 0) := (others => '0');
+ constant DMEM_TEST_c : std_logic_vector((14-DMEM_ABITS_g) downto 0) := (others => '0');
signal imem_clken_s : std_logic;
- signal imem_addr_s : std_logic_vector(31 downto 0);
+ signal imem_addr_s : std_logic_vector((IMEM_ABITS_g-1) downto 0);
signal imem_data_s : std_logic_vector(31 downto 0);
signal gprf_clken_s : std_logic;
signal core_clken_s : std_logic;
signal dmem_really_sel_s : std_logic;
signal gprf_really_clken_s : std_logic;
+
begin
-- select internal data memory when all address bits above DMEM_ABITS_g are zero
- dmem_sel_s <= '1' when (c2dmemb_s.addr(31 downto DMEM_ABITS_g) = DMEM_TEST_c)
+ dmem_sel_s <= '1' when (c2dmemb_s.addr(14 downto DMEM_ABITS_g) = DMEM_TEST_c)
else '0';
XMEMB_sel_o <= (not dmem_sel_s) and core_clken_s;
XMEMB_o <= c2dmemb_s;
dmem_really_sel_s <= dmem_sel_s and core_clken_s;
gprf_really_clken_s <= gprf_clken_s and core_clken_s;
- I_IMEM: lx_rocon_imem
+I_IMEM: lx_rocon_imem
port map
(
clk_i => clk_i,
cs_i => imem_really_clken_s,
- adr_i => imem_addr_s((IMEM_ABITS_g-1) downto 2),
+ adr_i => imem_addr_s((IMEM_ABITS_g-1) downto 0),
dat_o => imem_data_s,
clk_m => imem_clk_i,
dout_m => imem_data_o
);
- I_DMEM: lx_rocon_dmem
+I_DMEM: lx_rocon_dmem
port map
(
clk_i => clk_i,
ce_i => dmem_really_sel_s,
- adr_i => c2dmemb_s.addr((DMEM_ABITS_g-1) downto 2),
- wre_i => c2dmemb_s.wre,
- bsel_i => c2dmemb_s.bSel,
+ adr_i => c2dmemb_s.addr((DMEM_ABITS_g-1) downto 0),
+ bls_i => c2dmemb_s.bls,
dat_i => c2dmemb_s.data,
dat_o => dmem_data_s,
dout_m => dmem_data_o
);
- I_FETCH: fetch
+I_FETCH: fetch
port map
(
prog_cntr_i => IF2ID_r.program_counter,
IF2ID_o => IF2ID_s
);
- I_DECODE: decode
+I_DECODE: decode
generic map(USE_HW_MUL_g, USE_BARREL_g, COMPATIBILITY_MODE_g)
port map
(
ID2CTRL_o => ID2CTRL_s
);
- I_GPRF: lx_rocon_gprf_abd
+I_GPRF: lx_rocon_gprf_abd
port map
(
clk_i => clk_i,
GPRF2EX_o => GPRF2EX_s
);
- I_EXEQ: exeq
+I_EXEQ: exeq
generic map(USE_HW_MUL_g, USE_BARREL_g, COMPATIBILITY_MODE_g)
port map
(
-- this is a very simple address block decoder, just "internal" dmem or "external"
-- clken and int hardwired for fast internal data-memory
- DMEMB_i_s.clken <= '1' when (dmem_sel_s = '1') else XMEMB_i.clken;
- DMEMB_i_s.data <= dmem_data_s when (dmem_sel_r = '1') else XMEMB_i.data;
+ DMEMB_i_s.clken <= '1' when (dmem_sel_s = '1') else XMEMB_i.clken;
+ DMEMB_i_s.data <= dmem_data_s when (dmem_sel_r = '1') else XMEMB_i.data;
DMEMB_i_s.int <= XMEMB_i.int;
- I_MEM: mem
+I_MEM: mem
port map
(
EX2MEM_i => EX2MEM_r,
MEM2CTRL_o => MEM2CTRL_s
);
- I_CTRL: core_ctrl
- generic map (COMPATIBILITY_MODE_g)
+I_CTRL: core_ctrl
+ generic map (IMEM_ABITS_g, COMPATIBILITY_MODE_g)
port map
(
clk_i => clk_i,
MEM2CTRL_i => MEM2CTRL_s
);
- regd_proc: process(clk_i, rst_i)
+regd_proc:
+ process
begin
- if clk_i = '1' and clk_i'event then
- if (rst_i = '1') then -- synchronous reset ...
- dmem_sel_r <= '1';
- else -- delay select_external_mem (needed for reading ...)
- if (DMEMB_i_s.clken = '1') then
- dmem_sel_r <= dmem_sel_s; -- OR c2dmemb_s.wre; ??
- end if;
+ wait until clk_i'event and clk_i = '1';
+ if (rst_i = '1') then -- synchronous reset ...
+ dmem_sel_r <= '1';
+ else -- delay select_external_mem (needed for reading ...)
+ if (DMEMB_i_s.clken = '1') then
+ dmem_sel_r <= dmem_sel_s; -- OR c2dmemb_s.wre; ??
end if;
end if;
end process regd_proc;
mark : std_logic;
end record;
--
- type IRC_OUTPUT_Type is record
+ type IRC_COUNT_OUTPUT_Type is record
qcount : std_logic_vector(7 downto 0);
index : std_logic_vector(7 downto 0);
index_event : std_logic;
+ end record;
+ --
+ type IRC_STATE_OUTPUT_Type is record
ab_error : std_logic;
mark : std_logic;
end record;
--
- type IRC_SLIM_OUTPUT_Type is record
- qcount : std_logic_vector(7 downto 0);
- index : std_logic_vector(7 downto 0);
- index_event : std_logic;
+ type IRC_OUTPUT_Type is record
+ count : IRC_COUNT_OUTPUT_Type;
+ state : IRC_STATE_OUTPUT_Type;
end record;
+ -- Arrays
+ type IRC_INPUT_Array_Type is array (natural range <>) of IRC_INPUT_Type;
+ type IRC_OUTPUT_Array_Type is array (natural range <>) of IRC_OUTPUT_Type;
+ type IRC_COUNT_OUTPUT_Array_Type is array (natural range <>) of IRC_COUNT_OUTPUT_Type;
+ type IRC_STATE_OUTPUT_Array_Type is array (natural range <>) of IRC_STATE_OUTPUT_Type;
+
-- IRC coprocessor MAIN
component irc_proc_main
port
clk_i : in std_logic;
reset_i : in std_logic;
-- Signals from IRC
- irc1_i : in IRC_SLIM_OUTPUT_Type;
- irc2_i : in IRC_SLIM_OUTPUT_Type;
- irc3_i : in IRC_SLIM_OUTPUT_Type;
- irc4_i : in IRC_SLIM_OUTPUT_Type;
+ irc_i : in IRC_COUNT_OUTPUT_Array_Type(3 downto 0);
-- Index resetting
irc_index_reset_o : out std_logic_vector(3 downto 0);
- -- BRAM access (the other port)
+ -- BRAM access
mem_clk_i : in std_logic;
mem_en_i : in std_logic;
mem_we_i : in std_logic_vector(3 downto 0);
reset_index_event_i : in std_logic;
reset_ab_error_i : in std_logic;
-- Outputs
- qcount_o : out std_logic_vector (7 downto 0);
- qcount_index_o : out std_logic_vector (7 downto 0);
+ qcount_o : out std_logic_vector(7 downto 0);
+ qcount_index_o : out std_logic_vector(7 downto 0);
index_event_o : out std_logic;
a_rise_o, a_fall_o : out std_logic;
b_rise_o, b_fall_o : out std_logic;
);
end component;
+ component crc
+ port
+ (
+ clk_i : in std_logic;
+ reset_i : in std_logic;
+ input_i : in std_logic;
+ crc_o : out std_logic_vector(7 downto 0)
+ );
+ end component;
+
+ -- LX Master
+ component lxmaster
+ port
+ (
+ clk_i : in std_logic;
+ reset_i : in std_logic;
+ --
+ mosi_o : out std_logic;
+ clock_o : out std_logic;
+ sync_o : out std_logic;
+ -- BRAM access
+ mem_clk_i : in std_logic;
+ mem_en_i : in std_logic;
+ mem_we_i : in std_logic_vector(1 downto 0);
+ mem_addr_i : in std_logic_vector(8 downto 0);
+ mem_data_i : in std_logic_vector(15 downto 0);
+ mem_data_o : out std_logic_vector(15 downto 0)
+ );
+ end component;
+
--------------------------------------------------------------------------------
-- TUMBL
--------------------------------------------------------------------------------
clk_i : in std_logic;
ce_i : in std_logic;
adr_i : in std_logic_vector(11 downto 2);
- wre_i : in std_logic;
- bsel_i : in std_logic_vector(3 downto 0);
+ bls_i : in std_logic_vector(3 downto 0);
dat_i : in std_logic_vector(31 downto 0);
dat_o : out std_logic_vector(31 downto 0);
-- Memory wiring for Master CPU
-- MEMORY BUS
--------------------------------------------------------------------------------
- -- Calibration read register
- component calibration_read_register
+ -- Measurement register
+ component measurement_register
generic
(
id_g : std_logic_vector(31 downto 0) := (others => '0')
);
port
(
- -- Data bus (read only)
- data_o : out std_logic_vector(31 downto 0);
+ -- Clock
+ clk_i : in std_logic;
+ -- Reset
+ reset_i : in std_logic;
+ -- Chip enable
+ ce_i : in std_logic;
+ -- Switch
+ switch_i : in std_logic;
+ -- Data bus
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
-- Bus signals
- rd_i : in std_logic;
- ta_o : out std_logic
+ bls_i : in std_logic_vector(3 downto 0)
);
end component;
(
clk_i : in std_logic;
reset_i : in std_logic;
- -- Address (needs just last 4 bits, rest is wired to CE)
- address_i : in std_logic_vector(3 downto 0);
- ce_i : in std_logic;
-- Data bus
+ address_i : in std_logic_vector(3 downto 0);
+ next_ce_i : in std_logic;
data_i : in std_logic_vector(31 downto 0);
data_o : out std_logic_vector(31 downto 0);
- -- Bus signals
- rd_i : in std_logic;
+ --
bls_i : in std_logic_vector(3 downto 0);
- ta_o : out std_logic;
-- Signals for IRC
- irc1_i : in IRC_INPUT_Type;
- irc2_i : in IRC_INPUT_Type;
- irc3_i : in IRC_INPUT_Type;
- irc4_i : in IRC_INPUT_Type;
- -- Secondary data bus (slave)
- address_2_i : in std_logic_vector(3 downto 0);
- ce_2_i : in std_logic;
- --
- rd_2_i : in std_logic;
- bls_2_i : in std_logic_vector(3 downto 0);
- ta_2_o : out std_logic
+ irc_i : in IRC_INPUT_Array_Type(3 downto 0)
);
end component;
- -- Calibration write register
- component calibration_write_register
- port
- (
- -- Clock
- clk_i : in std_logic;
- -- Reset
- reset_i : in std_logic;
- -- Chip enable
- ce_i : in std_logic;
- -- Data bus
- data_i : in std_logic_vector(31 downto 0);
- data_o : out std_logic_vector(31 downto 0);
- -- Bus signals
- rd_i : in std_logic;
- bls_i : in std_logic_vector(3 downto 0);
- ta_o : out std_logic
- );
- end component;
-
- -- Calibration interconnect
- component bus_calibration
+ -- Measurement interconnect
+ component bus_measurement
port
(
-- Clock
data_i : in std_logic_vector(31 downto 0);
data_o : out std_logic_vector(31 downto 0);
-- Bus signals
- rd_i : in std_logic;
- bls_i : in std_logic_vector(3 downto 0);
- ta_o : out std_logic
+ bls_i : in std_logic_vector(3 downto 0)
);
end component;
port
(
-- Clock
- clk_100m_i : in std_logic;
- clk_50m_i : in std_logic;
+ clk_i : in std_logic;
-- Chip enable
- ce_100m_i : in std_logic;
+ ce_i : in std_logic;
-- Global Reset
- reset_100m_i : in std_logic;
+ reset_i : in std_logic;
-- Master CPU bus for the memory
- rd_100m_i : in std_logic;
- bls_100m_i : in std_logic_vector(3 downto 0);
- address_100m_i : in std_logic_vector(11 downto 0);
- data_100m_i : in std_logic_vector(31 downto 0);
- data_100m_o : out std_logic_vector(31 downto 0);
- ta_100m_o : out std_logic;
+ bls_i : in std_logic_vector(3 downto 0);
+ address_i : in std_logic_vector(11 downto 0);
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
-- Tumbl extrenal memory bus
- xmemb_sel_100m_o : out std_logic;
- xmemb_100m_i : in DMEMB2CORE_Type;
- xmemb_100m_o : out CORE2DMEMB_Type
+ xmemb_sel_o : out std_logic;
+ xmemb_i : in DMEMB2CORE_Type;
+ xmemb_o : out CORE2DMEMB_Type
);
end component;
+ -- Register on the bus
+ component bus_register is
+ generic
+ (
+ -- Reset value
+ reset_value_g : std_logic_vector(31 downto 0) := (others => '0');
+ -- Width
+ b0_g : natural := 8;
+ b1_g : natural := 8;
+ b2_g : natural := 8;
+ b3_g : natural := 8
+ );
+ port
+ (
+ -- Clock
+ clk_i : in std_logic;
+ -- Reset
+ reset_i : in std_logic;
+ -- Chip enable
+ ce_i : in std_logic;
+ -- Data bus
+ data_i : in std_logic_vector((b0_g+b1_g+b2_g+b3_g-1) downto 0);
+ data_o : out std_logic_vector((b0_g+b1_g+b2_g+b3_g-1) downto 0);
+ -- Bus signals
+ bls_i : in std_logic_vector(3 downto 0)
+ );
+ end component;
+
+ -- LX Master bus interconnect
+ component bus_lxmaster
+ port
+ (
+ clk_i : in std_logic;
+ reset_i : in std_logic;
+ -- Data bus
+ address_i : in std_logic_vector(8 downto 0);
+ next_ce_i : in std_logic;
+ data_i : in std_logic_vector(15 downto 0);
+ data_o : out std_logic_vector(15 downto 0);
+ --
+ bls_i : in std_logic_vector(1 downto 0);
+ -- Signals for LX Master
+ mosi_o : out std_logic;
+ clock_o : out std_logic;
+ sync_o : out std_logic
+ );
+ end component;
+
--------------------------------------------------------------------------------
-- BRAM
--------------------------------------------------------------------------------
-vhdl work "tumbl/mbl_Pkg.vhd"
+vhdl work "tumbl/mbl_pkg.vhd"
vhdl work "lx_rocon_pkg.vhd"
vhdl work "xilinx_dualport_bram_write_first.vhd"
vhdl work "dff2.vhd"
vhdl work "xilinx_dualport_bram_no_change.vhd"
+vhdl work "util_pkg.vhd"
vhdl work "tumbl/mem.vhd"
vhdl work "tumbl/fetch.vhd"
vhdl work "tumbl/exeq.vhd"
vhdl work "lx-rocon_tumbl/lx_rocon_gprf_abd.vhd"
vhdl work "lx-rocon_tumbl/lx_rocon_dmem.vhd"
vhdl work "irc_proc_inc.vhd"
+vhdl work "crc.vhd"
+vhdl work "measurement_register.vhd"
+vhdl work "lxmaster.vhd"
vhdl work "lx-rocon_tumbl/lx_rocon_tumbl.vhd"
vhdl work "irc_reader.vhd"
vhdl work "irc_proc_main.vhd"
-vhdl work "calibration_write_register.vhd"
-vhdl work "calibration_read_register.vhd"
vhdl work "bus_tumbl.vhd"
+vhdl work "bus_measurement.vhd"
+vhdl work "bus_lxmaster.vhd"
vhdl work "bus_irc.vhd"
-vhdl work "bus_calibration.vhd"
vhdl work "lx_rocon_top.vhd"
library unisim;
use unisim.vcomponents.all;
-use work.mbl_Pkg.all;
+use work.mbl_pkg.all;
use work.lx_rocon_pkg.all;
-- lx_rocon_top - wires the modules with the outside world
--
-- Master cpu memory bus has the following wires:
--
--- - address[15..0] The address
+-- - address[15..0] The address, used to mark chip enable
-- - data_in[31..0] The data coming to bus
-- - data_out[31..0] The data coming from bus, multiplexed
--- - rd Read enable, active LOW
--- - bls[3..0] Write enable for respective bytes, active LOW
--- In some cases, only WR is used
--- - ta Transaction acknowledge (latches data out), active LOW, multiplexed
+-- - bls[3..0] Write enable for respective bytes
entity lx_rocon_top is
port
(
-- External
- --clk_cpu : in std_logic;
- clk_50m : in std_logic;
+ --clk_cpu : in std_logic;
+ clk_50m : in std_logic;
--
- cs0_xc : in std_logic;
+ cs0_xc : in std_logic;
--
- rd : in std_logic;
- bls : in std_logic_vector(3 downto 0);
- address : in std_logic_vector(15 downto 0);
- data : inout std_logic_vector(31 downto 0);
+ rd : in std_logic;
+ bls : in std_logic_vector(3 downto 0);
+ address : in std_logic_vector(15 downto 0);
+ data : inout std_logic_vector(31 downto 0);
--
- irc1_a : in std_logic;
- irc1_b : in std_logic;
- irc1_index : in std_logic;
- irc1_mark : in std_logic;
+ irc1_a : in std_logic;
+ irc1_b : in std_logic;
+ irc1_index : in std_logic;
+ irc1_mark : in std_logic;
--
- irc2_a : in std_logic;
- irc2_b : in std_logic;
- irc2_index : in std_logic;
- irc2_mark : in std_logic;
+ irc2_a : in std_logic;
+ irc2_b : in std_logic;
+ irc2_index : in std_logic;
+ irc2_mark : in std_logic;
--
- irc3_a : in std_logic;
- irc3_b : in std_logic;
- irc3_index : in std_logic;
- irc3_mark : in std_logic;
+ irc3_a : in std_logic;
+ irc3_b : in std_logic;
+ irc3_index : in std_logic;
+ irc3_mark : in std_logic;
--
- irc4_a : in std_logic;
- irc4_b : in std_logic;
- irc4_index : in std_logic;
- irc4_mark : in std_logic;
+ irc4_a : in std_logic;
+ irc4_b : in std_logic;
+ irc4_index : in std_logic;
+ irc4_mark : in std_logic;
--
- init : in std_logic
+ init : in std_logic;
+ --
+ s1_clk_out : out std_logic;
+ s1_sync_out : out std_logic;
+ s1_mosi : out std_logic
);
end lx_rocon_top;
architecture Behavioral of lx_rocon_top is
-- Reset signal
- signal reset_s : std_logic;
- signal neg_init_s : std_logic;
- -- 100 MHz clock
- signal clk_100m_s : std_logic;
- signal clk_100m_fb_s : std_logic;
- signal clk_100m_locked_s : std_logic;
- -- Peripherals on the memory bus
- signal tumbl_out_s : std_logic_vector(31 downto 0);
- signal tumbl_ta_s : std_logic;
- signal tumbl_ce_s : std_logic;
- --
- signal irc_reg_out_s : std_logic_vector(31 downto 0);
- signal irc_reg_ta_s : std_logic;
- signal irc_reg_ce_s : std_logic;
- --
- signal calib_out_s : std_logic_vector(31 downto 0);
- signal calib_ta_s : std_logic;
- signal calib_ce_s : std_logic;
+ signal reset_s : std_logic;
+ signal init_f_s : std_logic;
+ signal init_f_r : std_logic;
+ -- Peripherals on the memory buses
+ -- Master to Tumbl DMEM / IMEM (Master)
+ signal tumbl_out_s : std_logic_vector(31 downto 0);
+ signal tumbl_ce_s : std_logic;
+ -- Measurement (Master)
+ signal meas_out_s : std_logic_vector(31 downto 0);
+ signal meas_ce_s : std_logic;
+ -- Master to Tumbl XMEM
+ signal master_tumbl_xmem_out_s : std_logic_vector(31 downto 0);
+ signal master_tumbl_xmem_ce_s : std_logic;
+ signal master_tumbl_xmem_lock_s : std_logic;
+ -- IRC (Tumbl)
+ signal irc_proc_out_s : std_logic_vector(31 downto 0);
+ signal irc_proc_ce_s : std_logic;
+ signal irc_proc_next_ce_s : std_logic;
+ -- LX Master (Tumbl)
+ signal lxmaster_out_s : std_logic_vector(15 downto 0);
+ signal lxmaster_ce_s : std_logic;
+ signal lxmaster_next_ce_s : std_logic;
-- Signals for external bus transmission
- signal data_i_s : std_logic_vector(31 downto 0);
- signal data_o_s : std_logic_vector(31 downto 0);
+ signal data_i_s : std_logic_vector(31 downto 0);
+ signal data_o_s : std_logic_vector(31 downto 0);
-- Signals for internal transaction
- signal last_address_s : std_logic_vector(15 downto 0);
- signal last_rd_s : std_logic;
- signal last_bls_s : std_logic_vector(3 downto 0);
+ signal last_address_s : std_logic_vector(15 downto 0);
+ signal last_rd_s : std_logic;
+ signal last_bls_s : std_logic_vector(3 downto 0);
- -- Reading logic:
+ -- Reading logic for Master CPU:
-- Broadcast rd only till ta (transaction acknowledge)
-- is received, then latch the data till the state of
-- rd or address changes
--
-- Data latching is synchronous - it's purpose is to
- -- provide stable data for CPU on the bus on high rise
- -- of trans. ack signal
+ -- provide stable data for CPU on the bus
signal rd_f_s : std_logic; -- Filtered RD
signal rd_d_s : std_logic; -- D over RD
- signal i_ta_s : std_logic; -- Internal bus TA (active 1)
signal i_rd_s : std_logic; -- Internal bus RD (active 1)
+ signal last_i_rd_s : std_logic; -- Delayed RD bus, used for latching
--
- signal data_read_s : std_logic_vector(31 downto 0); -- Latched read data
+ signal address_f_s : std_logic_vector(15 downto 0); -- Filtered address
+ signal address_d_s : std_logic_vector(15 downto 0); -- D over address
--
- signal acked_s : std_logic;
+ signal data_read_s : std_logic_vector(31 downto 0); -- Latched read data
-- Writing logic:
signal bls_f_s : std_logic_vector(3 downto 0); -- Filtered BLS
signal data_write_s : std_logic_vector(31 downto 0); -- Data broadcasted to write
-- Tumbl:
- signal tumbl_rd_s : std_logic;
signal tumbl_bls_s : std_logic_vector(3 downto 0);
+ signal tumbl_address_s : std_logic_vector(14 downto 0);
+ signal tumbl_data_i_s : std_logic_vector(31 downto 0);
+ --
signal tumbl_xmemb_o_s : CORE2DMEMB_Type;
signal tumbl_xmemb_i_s : DMEMB2CORE_Type;
- signal tumbl_sel_s : std_logic;
- --
- signal tumbl_irc_reg_ta_s : std_logic;
- signal tumbl_irc_reg_ce_s : std_logic;
+ signal tumbl_xmemb_sel_s : std_logic;
begin
- -- Clocking
- clk_100m_dcm_sp : DCM_SP
- generic map
+-- Tumbl coprocessor
+memory_bus_tumbl: bus_tumbl
+ port map
(
- clkdv_divide => 2.0,
- clkfx_divide => 1,
- clkfx_multiply => 2,
- clkin_divide_by_2 => false,
- clkin_period => 20.0, -- 50 MHz
- clkout_phase_shift => "NONE",
- clk_feedback => "1X",
- deskew_adjust => "SYSTEM_SYNCHRONOUS",
- dfs_frequency_mode => "LOW",
- dll_frequency_mode => "LOW",
- dss_mode => "NONE",
- duty_cycle_correction => true,
- factory_jf => X"c080",
- phase_shift => 0,
- startup_wait => false
- )
+ clk_i => clk_50m,
+ reset_i => reset_s,
+ ce_i => tumbl_ce_s,
+ bls_i => i_bls_s,
+ address_i => address_f_s(11 downto 0),
+ data_i => data_i_s,
+ data_o => tumbl_out_s,
+ --
+ xmemb_o => tumbl_xmemb_o_s,
+ xmemb_i => tumbl_xmemb_i_s,
+ xmemb_sel_o => tumbl_xmemb_sel_s
+ );
+
+-- Measurement
+memory_bus_measurement: bus_measurement
port map
(
- clk0 => clk_100m_fb_s,
- clk180 => open,
- clk270 => open,
- clk2x => clk_100m_s,
- clk2x180 => open,
- clk90 => open,
- clkdv => open,
- clkfx => open,
- clkfx180 => open,
- locked => clk_100m_locked_s,
- psdone => open,
- status => open,
- clkfb => clk_100m_fb_s,
- clkin => clk_50m,
- dssen => '0',
- psclk => '0',
- psen => '0',
- psincdec => '0',
- rst => neg_init_s
+ clk_i => clk_50m,
+ reset_i => reset_s,
+ ce_i => meas_ce_s,
+ address_i => address_f_s(1 downto 0),
+ bls_i => i_bls_s,
+ data_i => data_i_s,
+ data_o => meas_out_s
);
- -- IRC interconnect
- memory_bus_irc: bus_irc
+-- IRC interconnect
+memory_bus_irc: bus_irc
port map
(
- clk_i => clk_100m_s,
- reset_i => reset_s,
- address_i => address(3 downto 0),
- ce_i => irc_reg_ce_s,
- data_i => data_i_s,
- data_o => irc_reg_out_s,
- rd_i => i_rd_s,
- bls_i => i_bls_s,
- ta_o => irc_reg_ta_s,
+ reset_i => reset_s,
--
- address_2_i => tumbl_xmemb_o_s.addr(3 downto 0),
- ce_2_i => tumbl_irc_reg_ce_s,
- rd_2_i => tumbl_rd_s,
- bls_2_i => tumbl_bls_s,
- ta_2_o => tumbl_irc_reg_ta_s,
+ clk_i => clk_50m,
+ address_i => tumbl_address_s(3 downto 0),
+ next_ce_i => irc_proc_next_ce_s,
+ data_i => tumbl_data_i_s,
+ data_o => irc_proc_out_s,
+ bls_i => tumbl_bls_s,
--
- irc1_i.a => irc1_a,
- irc1_i.b => irc1_b,
- irc1_i.index => irc1_index,
- irc1_i.mark => irc1_mark,
+ irc_i(0).a => irc1_a,
+ irc_i(0).b => irc1_b,
+ irc_i(0).index => irc1_index,
+ irc_i(0).mark => irc1_mark,
--
- irc2_i.a => irc2_a,
- irc2_i.b => irc2_b,
- irc2_i.index => irc2_index,
- irc2_i.mark => irc2_mark,
+ irc_i(1).a => irc2_a,
+ irc_i(1).b => irc2_b,
+ irc_i(1).index => irc2_index,
+ irc_i(1).mark => irc2_mark,
--
- irc3_i.a => irc3_a,
- irc3_i.b => irc3_b,
- irc3_i.index => irc3_index,
- irc3_i.mark => irc3_mark,
+ irc_i(2).a => irc3_a,
+ irc_i(2).b => irc3_b,
+ irc_i(2).index => irc3_index,
+ irc_i(2).mark => irc3_mark,
--
- irc4_i.a => irc4_a,
- irc4_i.b => irc4_b,
- irc4_i.index => irc4_index,
- irc4_i.mark => irc4_mark
+ irc_i(3).a => irc4_a,
+ irc_i(3).b => irc4_b,
+ irc_i(3).index => irc4_index,
+ irc_i(3).mark => irc4_mark
);
- -- Tumbl coprocessor
- memory_bus_tumbl: bus_tumbl
+-- LX Master
+memory_bus_lxmaster: bus_lxmaster
port map
(
- clk_100m_i => clk_100m_s,
- clk_50m_i => clk_50m,
- reset_100m_i => reset_s,
- ce_100m_i => tumbl_ce_s,
- ta_100m_o => tumbl_ta_s,
- rd_100m_i => i_rd_s,
- bls_100m_i => i_bls_s,
- address_100m_i => address(11 downto 0),
- data_100m_i => data_i_s,
- data_100m_o => tumbl_out_s,
+ reset_i => reset_s,
--
- xmemb_100m_o => tumbl_xmemb_o_s,
- xmemb_100m_i => tumbl_xmemb_i_s,
- xmemb_sel_100m_o => tumbl_sel_s
- );
-
- -- Calibration
- memory_bus_calibration: bus_calibration
- port map
- (
- clk_i => clk_100m_s,
- reset_i => reset_s,
- ce_i => calib_ce_s,
- address_i => address(1 downto 0),
- rd_i => i_rd_s,
- bls_i => i_bls_s,
- ta_o => calib_ta_s,
- data_i => data_i_s,
- data_o => calib_out_s
+ clk_i => clk_50m,
+ address_i => tumbl_address_s(8 downto 0),
+ next_ce_i => lxmaster_next_ce_s,
+ data_i => tumbl_data_i_s(15 downto 0),
+ data_o => lxmaster_out_s,
+ bls_i => tumbl_bls_s(1 downto 0),
+ --
+ mosi_o => s1_mosi,
+ clock_o => s1_clk_out,
+ sync_o => s1_sync_out
);
-- Filters
--bls_f <= bls when bls = bls_d else "1111";
- bls_f_s(0) <= bls(0) when bls(0) = bls_d_s(0) else '1';
- bls_f_s(1) <= bls(2) when bls(2) = bls_d_s(2) else '1';
- bls_f_s(2) <= bls(2) when bls(2) = bls_d_s(2) else '1';
- bls_f_s(3) <= bls(3) when bls(3) = bls_d_s(3) else '1';
- rd_f_s <= rd when rd = rd_d_s else '1';
+ bls_f_s(0) <= bls(0) when bls(0) = bls_d_s(0) else '1';
+ bls_f_s(1) <= bls(2) when bls(2) = bls_d_s(2) else '1'; -- FIXME: BLS(1) not soldered properly on my board
+ bls_f_s(2) <= bls(2) when bls(2) = bls_d_s(2) else '1';
+ bls_f_s(3) <= bls(3) when bls(3) = bls_d_s(3) else '1';
+ rd_f_s <= rd when rd = rd_d_s else '1';
+ address_f_s <= address when address = address_d_s else last_address_s; -- Use last address on mismatch!
+
+ -- Signalling
+ data_i_s <= data_write_s when i_bls_s /= "0000" else (others => '0');
-- Tumbl
- tumbl_rd_s <= tumbl_xmemb_o_s.ena when (tumbl_sel_s = '1') else '0';
- tumbl_bls_s <= tumbl_xmemb_o_s.bSel when (tumbl_sel_s = '1' and tumbl_xmemb_o_s.wre = '1') else "0000";
+ tumbl_bls_s <= i_bls_s when (master_tumbl_xmem_lock_s = '1')
+ else tumbl_xmemb_o_s.bls when (tumbl_xmemb_sel_s = '1')
+ else "0000";
+ tumbl_address_s <= address_f_s(14 downto 0) when (master_tumbl_xmem_lock_s = '1')
+ else tumbl_xmemb_o_s.addr when (tumbl_xmemb_sel_s = '1')
+ else (others => '0');
+ tumbl_data_i_s <= data_i_s when (master_tumbl_xmem_lock_s = '1')
+ else tumbl_xmemb_o_s.data when (tumbl_xmemb_sel_s = '1')
+ else (others => '0');
--
tumbl_xmemb_i_s.int <= '0'; -- No interrupt
- -- Bus update
+ -- Enable clken only when available for Tumbl
+ tumbl_xmemb_i_s.clken <= not master_tumbl_xmem_lock_s;
+
+-- Bus update
memory_bus_update:
- process(clk_100m_s)
+ process
begin
- if clk_100m_s = '1' and clk_100m_s'event then
-
- -- ======================================================
- -- MASTER CPU
- -- ======================================================
-
- -- Set every signal to inactive state here
- irc_reg_ce_s <= '0';
- tumbl_ce_s <= '0';
- calib_ce_s <= '0';
- i_rd_s <= '0';
- i_bls_s <= (others => '0');
-
- -- Check if we have chip select
- if reset_s = '1' then
- acked_s <= '1';
- i_ta_s <= '0';
- data_read_s <= (others => '0');
- elsif cs0_xc = '0' then
-
- -- Memory Map (16-bit address @ 32-bit each)
-
- -- Each address is seen as 32-bit entry now
- -- 0x0000 - 0x0FFF: Tumbl
- -- 0x8000 - 0x800F: IRC registers
- -- 0xFFFC - 0xFFFF: Calibration
-
- if address < "0001000000000000" then -- Tumbl
- tumbl_ce_s <= '1';
- i_ta_s <= tumbl_ta_s;
- data_o_s <= tumbl_out_s;
- elsif address(15 downto 4) = "100000000000" then -- IRC
- irc_reg_ce_s <= '1';
- i_ta_s <= irc_reg_ta_s;
- data_o_s <= irc_reg_out_s;
- elsif address(15 downto 2) = "11111111111111" then -- Calibration
- calib_ce_s <= '1';
- i_ta_s <= calib_ta_s;
- data_o_s <= calib_out_s;
+ wait until clk_50m = '1' and clk_50m'event;
+
+ -- Defaults
+ i_bls_s <= "0000";
+ i_rd_s <= '0';
+
+ -- Check if we have chip select
+ if cs0_xc = '0' then
+
+ -- Reading
+ if rd_f_s = '0' then
+
+ -- Internal read
+ if (last_rd_s = '1' or last_address_s /= address_f_s) then
+ i_rd_s <= '1';
end if;
- -- Reading
- if rd_f_s = '0' then
- if last_rd_s = '1' or last_address_s /= address then
- -- Getting something new
- -- Set internal RD to active and reset ack and latched data
- acked_s <= '0';
- i_rd_s <= '1';
- -- Data latching - synchronous
- data_read_s <= (others => 'X');
- elsif i_rd_s = '1' and acked_s = '0' and i_ta_s = '1' then
- -- Got acknowledge, latch data
- acked_s <= '1';
- data_read_s <= data_o_s;
- elsif acked_s = '0' then
- -- Ongoing read, keep the signal active
- i_rd_s <= '1';
- data_read_s <= (others => 'X');
- end if;
-
- last_address_s <= address;
- else
- -- Not reading, anything goes
- data_read_s <= (others => 'X');
+ if i_rd_s = '0' and last_i_rd_s = '1' then
+ -- Latch data we just read - they are valid in this cycle
+ data_read_s <= data_o_s;
end if;
- last_rd_s <= rd_f_s;
+ last_address_s <= address_f_s;
+ else
+ -- Not reading, anything goes
+ data_read_s <= (others => 'X');
+ end if;
- -- Writing
- if bls_f_s /= "1111" then
+ last_rd_s <= rd_f_s;
- if last_bls_s /= bls_f_s or last_address_s /= address then
- -- Broadcast BLS for once cycle to write the data
- i_bls_s <= not bls_f_s;
- -- Data broadcasting is in a separate process
- end if;
+ -- Writing
+ if bls_f_s /= "1111" then
- last_address_s <= address;
+ -- Internal write
+ if (last_bls_s /= bls_f_s or last_address_s /= address_f_s) then
+ i_bls_s <= not bls_f_s;
end if;
- last_bls_s <= bls_f_s;
+ last_address_s <= address_f_s;
+ end if;
- else
+ last_bls_s <= bls_f_s;
- -- Set last read / bls to '1' if CS0 is not asserted
- last_rd_s <= '1';
- last_bls_s <= (others => '1');
+ else
- end if;
+ -- Set last read / bls to '1' if CS0 is not asserted
+ last_rd_s <= '1';
+ last_bls_s <= (others => '1');
+ last_address_s <= address_d_s;
+
+ end if;
+
+ -- Filters
+ bls_d_s <= bls;
+ rd_d_s <= rd;
+ address_d_s <= address;
+ --
+ last_i_rd_s <= i_rd_s;
- -- Filters
- bls_d_s <= bls;
- rd_d_s <= rd;
+ -- ======================================================
+ -- TUMBL BUS
+ -- ======================================================
+
+ -- Just copy these to their desired next state
+ irc_proc_ce_s <= irc_proc_next_ce_s;
+ lxmaster_ce_s <= lxmaster_next_ce_s;
+
+ -- Other
+ init_f_s <= init;
+ init_f_r <= init_f_s;
+
+ end process;
+
+-- Do the actual wiring here
+memory_bus_wiring:
+ process(cs0_xc, address_f_s, tumbl_out_s, meas_out_s, master_tumbl_xmem_out_s)
+ begin
+
+ -- Inactive by default
+ tumbl_ce_s <= '0';
+ meas_ce_s <= '0';
+ master_tumbl_xmem_ce_s <= '0';
+ data_o_s <= (others => '0');
+
+ if cs0_xc = '0' then
+
+ -- Memory Map (16-bit address @ 32-bit each)
+
+ -- Each address is seen as 32-bit entry now
+ -- 0x0000 - 0x0FFF: Tumbl IMEM / DMEM
+ -- 0x1FFC - 0x1FFF: Measurement
+ -- 0x8000 - 0x8FFF: Tumbl BUS
+
+ if address_f_s < "0001000000000000" then -- Tumbl
+ tumbl_ce_s <= '1';
+ data_o_s <= tumbl_out_s;
+ elsif address_f_s(15 downto 2) = "00011111111111" then -- Measurement
+ meas_ce_s <= '1';
+ data_o_s <= meas_out_s;
+ elsif address_f_s(15) = '1' then -- Tumbl External BUS
+ master_tumbl_xmem_ce_s <= '1';
+ data_o_s <= master_tumbl_xmem_out_s;
+ end if;
end if;
end process;
- -- If RD and BLS is not high, we must keep DATA at high impedance
- -- or the FPGA collides with SDRAM (damaging each other)
+-- If RD and BLS is not high, we must keep DATA at high impedance
+-- or the FPGA collides with SDRAM (damaging each other)
memory_bus_out:
process(cs0_xc, rd, data, data_read_s)
begin
-- CS0 / RD / BLS are active LOW
if cs0_xc = '0' and rd = '0' then
+ -- Don't risk flipping (between data_o_s and latched data_read_s, it's better to wait)
+ -- Maybe check this later.
+ -- if last_i_rd_s = '1' then
+ -- data <= data_o_s;
+ -- else
data <= data_read_s;
+ -- end if;
else
-- IMPORTANT!!!
data <= (others => 'Z');
end process;
-tumbl_bus:
- process(tumbl_sel_s, tumbl_xmemb_o_s, tumbl_irc_reg_ta_s, irc_reg_out_s, cs0_xc)
+-- Outputs from Tumbl (enabling and address muxing) and Master CPU
+tumbl_bus_o:
+ process(tumbl_xmemb_sel_s, tumbl_xmemb_o_s, master_tumbl_xmem_ce_s, address_f_s, i_rd_s, i_bls_s)
+ variable addr_v : std_logic_vector(14 downto 0); -- This space is visible by both (32-bit)
+ variable sel_v : std_logic;
begin
- -- ======================================================
- -- TUMBL
- -- ======================================================
-
- -- This is purely internal slave bus
-
-- Defaults
- tumbl_xmemb_i_s.clken <= '1'; -- No haltfire :-)
- tumbl_xmemb_i_s.data <= (others => 'X');
- tumbl_irc_reg_ce_s <= '0';
-
- if tumbl_sel_s = '1' then
- -- IRC 0x1000 - 0x100F
- if tumbl_xmemb_o_s.addr(12) = '1' then
- tumbl_irc_reg_ce_s <= '1';
- tumbl_xmemb_i_s.clken <= tumbl_irc_reg_ta_s;
- -- Cannot latch here (too cost, abort if bad timing)
- tumbl_xmemb_i_s.data <= irc_reg_out_s;
- -- Data writing and signal is done elsewhere
+ irc_proc_next_ce_s <= '0';
+ lxmaster_next_ce_s <= '0';
+ master_tumbl_xmem_lock_s <= '0';
+ --
+ addr_v := (others => '0');
+ sel_v := '0';
+
+ -- Check who is accessing
+ if master_tumbl_xmem_ce_s = '1' and (i_rd_s = '1' or i_bls_s /= "0000") then
+ -- Master blocks Tumbl
+ master_tumbl_xmem_lock_s <= '1';
+ addr_v := address_f_s(14 downto 0);
+ sel_v := '1';
+ else
+ addr_v := tumbl_xmemb_o_s.addr;
+ sel_v := '1';
+ end if;
+
+ if sel_v = '1' then
+ -- IRC: 0x0800 - 0x080F (32-bit address)
+ -- LX MASTER: 0x0A00 - 0x0BFF (32-bit address)
+ if addr_v(14 downto 4) = "00010000000" then
+ irc_proc_next_ce_s <= '1';
+ elsif addr_v(14 downto 9) = "000101" then
+ lxmaster_next_ce_s <= '1';
end if;
end if;
end process;
- -- Data broadcast
-data_i_write:
- process(cs0_xc, bls_f_s, data_write_s, tumbl_sel_s, tumbl_bls_s, tumbl_xmemb_o_s)
+-- Inputs to Tumbl (enabling and address muxing)
+tumbl_bus_i:
+ process(irc_proc_ce_s, irc_proc_out_s, lxmaster_ce_s, lxmaster_out_s, tumbl_xmemb_i_s)
begin
- if cs0_xc = '0' and bls_f_s /= "1111" then -- External, log. 0 active
- data_i_s <= data_write_s;
- elsif tumbl_sel_s = '1' and tumbl_bls_s /= "0000" then -- Internal, log. 1 active
- data_i_s <= tumbl_xmemb_o_s.data;
- else
- data_i_s <= (others => 'X');
+ tumbl_xmemb_i_s.data <= (others => 'X');
+
+ -- NOTE: This is input to Tumbl EXEQ - with MUL instruction for input > 18-bit,
+ -- (i.e. more DSPs in a sequence), this already has tough timing constraints
+ -- and SmartXplorer has to be used with XiSE or use Synplify.
+ if irc_proc_ce_s = '1' then
+ tumbl_xmemb_i_s.data <= irc_proc_out_s;
+ elsif lxmaster_ce_s = '1' then
+ tumbl_xmemb_i_s.data(15 downto 0) <= lxmaster_out_s;
+ tumbl_xmemb_i_s.data(31 downto 16) <= (others => '0');
end if;
+ master_tumbl_xmem_out_s <= tumbl_xmemb_i_s.data;
+
end process;
- -- Reset
+-- Reset
initialization:
- process(init, clk_100m_locked_s)
+ process(init_f_s, init_f_r)
begin
- -- TODO: Proper reset (lacks filter and propagation with ack as we use PLL)
- neg_init_s <= not init;
- reset_s <= (not init) or (not clk_100m_locked_s);
+ reset_s <= (not init_f_s) and (not init_f_r);
end process;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.util_pkg.all;
+use work.lx_rocon_pkg.all;
+
+-- LX Master
+entity lxmaster is
+ port
+ (
+ clk_i : in std_logic;
+ reset_i : in std_logic;
+ --
+ mosi_o : out std_logic;
+ clock_o : out std_logic;
+ sync_o : out std_logic;
+ -- BRAM access
+ mem_clk_i : in std_logic;
+ mem_en_i : in std_logic;
+ mem_we_i : in std_logic_vector(1 downto 0);
+ mem_addr_i : in std_logic_vector(8 downto 0);
+ mem_data_i : in std_logic_vector(15 downto 0);
+ mem_data_o : out std_logic_vector(15 downto 0)
+ );
+end lxmaster;
+
+architecture Behavioral of lxmaster is
+
+ -- Types
+ type state_t is (ST_BEGIN, ST_DECIDE, ST_PREINIT, ST_INIT, ST_READY, ST_XFER, ST_CRC, ST_END);
+ constant frame_length_c : positive := 2500; -- 50 MHz -> 20 kHz
+ -- RAM Access (both ARM and Tumbl)
+ signal ram_en_s : std_logic;
+ signal ram_rst_s : std_logic;
+ --
+ signal ram_addr_s : std_logic_vector(8 downto 0);
+ signal ram_data_o_s : std_logic_vector(15 downto 0);
+ -- State
+ signal lxmaster_state_s : state_t;
+ signal lxmaster_not_last_word_s : std_logic;
+ -- Data
+ signal lxmaster_num_data_s : std_logic_vector(7 downto 0); -- If 0 then the peripheral is not active this cycle
+ signal lxmaster_loaded_data_s : std_logic_vector(15 downto 0);
+ signal lxmaster_data_counter_s : std_logic_vector(3 downto 0); -- Shift: 0 - 15
+ -- Transmission
+ signal lxmaster_sync_s : std_logic;
+ -- Frame counter
+ signal lxmaster_frame_counter_s : natural range 0 to (frame_length_c-1);
+ -- CRC
+ signal lxmaster_crc_data_s : std_logic;
+ signal lxmaster_crc_reset_s : std_logic;
+ signal lxmaster_crc_out_s : std_logic_vector(7 downto 0);
+ -- RAM reset
+ signal lxmaster_ram_reset_s : std_logic;
+
+begin
+
+ -- Directly route out some signals
+ clock_o <= clk_i; -- Cannot mix with logic
+ sync_o <= not lxmaster_sync_s; -- Active in log. 0
+ mosi_o <= '1' when lxmaster_sync_s = '0'
+ else lxmaster_crc_out_s(0) when lxmaster_state_s = ST_CRC
+ else lxmaster_loaded_data_s(0);
+ -- CRC
+ lxmaster_crc_data_s <= '1' when lxmaster_state_s = ST_CRC else lxmaster_loaded_data_s(0);
+ lxmaster_crc_reset_s <= '1' when lxmaster_state_s = ST_READY or reset_i = '1' else '0';
+
+ram: xilinx_dualport_bram_write_first
+ generic map
+ (
+ we_width => 2,
+ byte_width => 8,
+ address_width => 9
+ )
+ port map
+ (
+ -- Internal
+ clka => clk_i,
+ rsta => ram_rst_s,
+ ena => ram_en_s,
+ wea => (others => '0'),
+ addra => ram_addr_s,
+ dina => (others => '0'),
+ douta => ram_data_o_s,
+ -- External
+ clkb => mem_clk_i,
+ rstb => '0',
+ enb => mem_en_i,
+ web => mem_we_i,
+ addrb => mem_addr_i,
+ dinb => mem_data_i,
+ doutb => mem_data_o
+ );
+
+crc_out: crc
+ port map
+ (
+ clk_i => clk_i,
+ reset_i => lxmaster_crc_reset_s,
+ input_i => lxmaster_crc_data_s,
+ crc_o => lxmaster_crc_out_s
+ );
+
+ ram_rst_s <= reset_i or lxmaster_ram_reset_s;
+
+-- This function toggles outputs directly, make sure the outputs
+-- are updated with clock.
+-- TODO: When finalized, all RAM enabling to happen immediatelly, not with next cycle!
+-- TODO: Maybe some exception handling (overflows etc.)
+update:
+ process
+ variable ram_addr_v : std_logic_vector(8 downto 0);
+ begin
+
+ wait until clk_i'event and clk_i = '1';
+
+ lxmaster_ram_reset_s <= '0';
+
+ if reset_i = '1' then
+ lxmaster_frame_counter_s <= 0;
+ lxmaster_num_data_s <= x"00";
+ lxmaster_loaded_data_s <= x"0000";
+ lxmaster_state_s <= ST_BEGIN;
+ lxmaster_sync_s <= '0';
+
+ ram_addr_s <= '0' & x"00";
+ ram_en_s <= '1';
+ else
+ -- OK, we are enabled, default values
+ lxmaster_sync_s <= '0'; -- Not transferring
+ ram_en_s <= '0'; -- Not reading
+
+ case lxmaster_state_s is
+ when ST_BEGIN =>
+ -- We're reading address 0x000 now
+ lxmaster_state_s <= ST_DECIDE;
+
+ when ST_DECIDE =>
+ -- We just read address 0, check which buffer we should use
+ if ram_data_o_s(15) = '0' then
+ ram_addr_s <= '0' & x"00"; -- First buffer
+ else
+ ram_addr_s <= '1' & x"00"; -- Second buffer
+ end if;
+
+ ram_en_s <= '1'; -- Read
+ lxmaster_state_s <= ST_PREINIT; -- Go to second decide
+
+ when ST_PREINIT =>
+ -- Advance reading
+ ram_addr_s <= ram_addr_s + 1; -- Update address
+ ram_en_s <= '1'; -- Read
+ lxmaster_state_s <= ST_INIT; -- Go to init
+
+ when ST_INIT =>
+ -- We just read number of commands
+ if ram_data_o_s(7 downto 0) = x"00" then
+ lxmaster_state_s <= ST_END; --Nothing
+ else
+ lxmaster_state_s <= ST_READY; -- Make next read init the transfer
+ end if;
+
+ -- Regardless, write the number of data
+ lxmaster_num_data_s <= ram_data_o_s(7 downto 0);
+
+ -- No need to forward it here
+ when ST_READY =>
+ -- We have first word on data and start transfer
+ lxmaster_loaded_data_s <= ram_data_o_s;
+ lxmaster_sync_s <= '1'; -- Transferring data next cycle
+ lxmaster_data_counter_s <= x"0"; -- Reset counter
+ lxmaster_state_s <= ST_XFER; --Go to transfer loop
+ lxmaster_not_last_word_s <= '0'; -- Not last word
+
+ when ST_XFER =>
+ lxmaster_loaded_data_s <= '0' & lxmaster_loaded_data_s(15 downto 1); -- Shift it
+ lxmaster_sync_s <= '1'; -- Transferring data next cycle
+
+ if lxmaster_data_counter_s = x"D" and ram_addr_s(7 downto 0) /= lxmaster_num_data_s then
+ -- At 13th bit, we need to read from RAM if more words are to come (RAM address starts with 1 for data!)
+ ram_addr_s <= ram_addr_s + 1; -- Update address
+ lxmaster_data_counter_s <= lxmaster_data_counter_s + 1; -- Increment
+ ram_en_s <= '1'; -- Read
+ lxmaster_not_last_word_s <= '1';
+ elsif lxmaster_data_counter_s = x"F" then
+ -- At 15th bit, we either stop if ram_addr_s equals lxmaster_num_data_s (wasn't updated so it would not overflow)
+ if ram_addr_s(7 downto 0) = lxmaster_num_data_s and lxmaster_not_last_word_s = '0' then
+ lxmaster_state_s <= ST_CRC;
+ lxmaster_data_counter_s <= x"0";
+ else
+ lxmaster_loaded_data_s <= ram_data_o_s;
+ lxmaster_data_counter_s <= x"0";
+ lxmaster_not_last_word_s <= '0';
+ end if;
+ else
+ -- Increment
+ lxmaster_data_counter_s <= lxmaster_data_counter_s + 1;
+ end if;
+
+ when ST_CRC =>
+
+ -- Check if this is last command, first read one more
+ if lxmaster_data_counter_s = x"0" then
+ if (ram_addr_s(7 downto 0) = x"FF") then
+ lxmaster_ram_reset_s <= '1'; -- Make sure we read 0 in this case
+ end if;
+
+ ram_addr_s <= ram_addr_s + 1; -- Update address
+ ram_en_s <= '1'; -- Read
+ elsif lxmaster_data_counter_s = x"2" then
+
+ if ram_data_o_s(7 downto 0) /= x"00" then -- Need to read first command
+ ram_addr_v := ram_addr_s(8) & ram_data_o_s(15 downto 8); -- Update address
+ ram_addr_s <= ram_addr_v;
+ lxmaster_num_data_s <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
+ ram_en_s <= '1'; -- Read
+ else
+ lxmaster_num_data_s <= x"00"; -- Signalize termination
+ end if;
+
+ end if;
+
+ if lxmaster_data_counter_s = x"7" then -- Ending
+ lxmaster_data_counter_s <= x"0";
+
+ if lxmaster_num_data_s(7 downto 0) = x"00" then
+ lxmaster_state_s <= ST_END; -- Last command
+ else
+ -- We are at init at the moment
+ lxmaster_state_s <= ST_READY; -- Sync goes inactive for a cycle
+ end if;
+
+ else
+ lxmaster_sync_s <= '1'; -- Transferring data next cycle
+ lxmaster_data_counter_s <= lxmaster_data_counter_s + 1; -- Increment
+ end if;
+
+ when ST_END =>
+ if lxmaster_frame_counter_s = (frame_length_c - 1) then
+ -- Initialize first step
+ lxmaster_state_s <= ST_BEGIN;
+ ram_addr_s <= '0' & x"00";
+ ram_en_s <= '1';
+ end if;
+
+ end case;
+
+ -- Increment counter
+ if lxmaster_frame_counter_s = (frame_length_c - 1) then
+ lxmaster_frame_counter_s <= 0;
+ else
+ lxmaster_frame_counter_s <= lxmaster_frame_counter_s + 1;
+ end if;
+
+ end if;
+
+ end process;
+
+end Behavioral;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
+
+-- Transaction measurement register
+
+entity measurement_register is
+ generic
+ (
+ id_g : std_logic_vector(31 downto 0) := (others => '0')
+ );
+ port
+ (
+ -- Clock
+ clk_i : in std_logic;
+ -- Reset
+ reset_i : in std_logic;
+ -- Chip enable
+ ce_i : in std_logic;
+ -- Switch
+ switch_i : in std_logic;
+ -- Data bus
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
+ -- Bus signals
+ bls_i : in std_logic_vector(3 downto 0)
+ );
+end measurement_register;
+
+architecture Behavioral of measurement_register is
+ signal value_s : std_logic_vector(31 downto 0);
+begin
+
+ data_o <= value_s when switch_i = '1' else id_g;
+
+-- Write waits for clock
+memory_bus_write:
+ process
+ begin
+
+ wait until clk_i'event and clk_i = '1';
+
+ if reset_i = '1' then
+ value_s <= (others => '0');
+ else
+
+ if ce_i = '1' and bls_i /= "0000" then
+
+ if bls_i(0) = '1' then
+ value_s(7 downto 0) <= data_i(7 downto 0);
+ end if;
+ if bls_i(1) = '1' then
+ value_s(15 downto 8) <= data_i(15 downto 8);
+ end if;
+ if bls_i(2) = '1' then
+ value_s(23 downto 16) <= data_i(23 downto 16);
+ end if;
+ if bls_i(3) = '1' then
+ value_s(31 downto 24) <= data_i(31 downto 24);
+ end if;
+
+ end if;
+ end if;
+
+ end process;
+
+end Behavioral;
+
signal count_index_s : std_logic_vector (7 downto 0);
begin
- dff_a: dff2
+dff_a: dff2
port map
(
clk_i => clk_i,
q_o => a_s
);
- dff_b: dff2
+ dff_b: dff2
port map
(
clk_i => clk_i,
q_o => b_s
);
- dff_index: dff2
+dff_index: dff2
port map
(
clk_i => clk_i,
end process;
seq:
- process (clk_i)
+ process
begin
-- Reset for qcounter is synchronous and lasts at least one more cycle
-- to prevent hazardous states after releasing it
- if clk_i = '1' and clk_i'event then
- if reset_i = '1' then
- count_prev_s <= (others => '0');
- count_index_prev_s <= (others => '0');
- index_event_int_s <= '0';
- ab_error_int_s <= '0';
+ wait until clk_i'event and clk_i = '1';
+
+ if reset_i = '1' then
+ count_prev_s <= (others => '0');
+ count_index_prev_s <= (others => '0');
+ index_event_int_s <= '0';
+ ab_error_int_s <= '0';
+ else
+ count_prev_s <= count_s;
+ count_index_prev_s <= count_index_s;
+ --
+ if reset_index_event_i = '1' then
+ index_event_int_s <= '0';
else
- count_prev_s <= count_s;
- count_index_prev_s <= count_index_s;
- --
- if reset_index_event_i = '1' then
- index_event_int_s <= '0';
- else
- index_event_int_s <= index_event_int_s or index_event_s;
- end if;
- --
- if reset_ab_error_i = '1' then
- ab_error_int_s <= '0';
- else
- ab_error_int_s <= ab_error_int_s or ab_error_s;
- end if;
+ index_event_int_s <= index_event_int_s or index_event_s;
+ end if;
+ --
+ if reset_ab_error_i = '1' then
+ ab_error_int_s <= '0';
+ else
+ ab_error_int_s <= ab_error_int_s or ab_error_s;
end if;
- a_prev_s <= a_s;
- b_prev_s <= b_s;
- last_reset_s <= reset_i;
end if;
+ a_prev_s <= a_s;
+ b_prev_s <= b_s;
+ last_reset_s <= reset_i;
end process;
end behavioral;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+package util_pkg is
+ -- ceil(log2(n))
+ function ceil_log2(n: natural) return natural;
+ -- ceil(a/b)
+ function ceil_div(a: integer; b: integer) return integer;
+ --
+ function max(left, right: integer) return integer;
+ function min(left, right: integer) return integer;
+end;
+
+---
+
+package body util_pkg is
+
+ function ceil_log2(n: natural) return natural is
+ begin
+ if n <= 1 then
+ return 0;
+ else
+ if n mod 2 = 0 then
+ return 1 + ceil_log2(n/2);
+ else
+ return 1 + ceil_log2((n+1)/2);
+ end if;
+ end if;
+ end function ceil_log2;
+
+ function ceil_div(a: integer; b: integer) return integer is
+ begin
+ return (a+b-1)/b;
+ end function ceil_div;
+
+ function max(left, right: integer) return integer is
+ begin
+ if left > right then return left;
+ else return right;
+ end if;
+ end;
+
+ function min(left, right: integer) return integer is
+ begin
+ if left < right then return left;
+ else return right;
+ end if;
+ end;
+
+end util_pkg;
begin
- -- CLKA process
- ram_process_a : process(clka)
+-- CLKA process
+ram_process_a:
+ process
begin
- if clka = '1' and clka'event then
+ wait until clka'event and clka = '1';
- if ena = '1' then
+ if ena = '1' then
- for i in 0 to (we_width-1) loop
- if wea(i) = '1' then
- ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width))
- := dina(((i+1)*byte_width-1) downto (i*byte_width));
- end if;
- end loop;
-
- if to_integer(unsigned(wea)) = 0 then
- if rsta = '1' then
- douta <= (others => '0');
- else
- douta <= ram_block(to_integer(unsigned(addra)));
- end if;
+ for i in 0 to (we_width-1) loop
+ if wea(i) = '1' then
+ ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dina(((i+1)*byte_width-1) downto (i*byte_width));
end if;
+ end loop;
+ if to_integer(unsigned(wea)) = 0 then
+ if rsta = '1' then
+ douta <= (others => '0');
+ else
+ douta <= ram_block(to_integer(unsigned(addra)));
+ end if;
end if;
end if;
end process;
- -- CLKB process
- ram_process_b : process(clkb)
+-- CLKB process
+ram_process_b:
+ process
begin
- if clkb = '1' and clkb'event then
+ wait until clkb'event and clkb = '1';
- if enb = '1' then
+ if enb = '1' then
- for i in 0 to (we_width-1) loop
- if web(i) = '1' then
- ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width))
- := dinb(((i+1)*byte_width-1) downto (i*byte_width));
- end if;
- end loop;
-
- if to_integer(unsigned(web)) = 0 then
- if rstb = '1' then
- doutb <= (others => '0');
- else
- doutb <= ram_block(to_integer(unsigned(addrb)));
- end if;
+ for i in 0 to (we_width-1) loop
+ if web(i) = '1' then
+ ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dinb(((i+1)*byte_width-1) downto (i*byte_width));
end if;
+ end loop;
+ if to_integer(unsigned(web)) = 0 then
+ if rstb = '1' then
+ doutb <= (others => '0');
+ else
+ doutb <= ram_block(to_integer(unsigned(addrb)));
+ end if;
end if;
end if;
begin
- -- CLKA process
- ram_process_a : process(clka)
+-- CLKA process
+ram_process_a:
+ process
begin
- if clka = '1' and clka'event then
+ wait until clka'event and clka = '1';
+ if ena = '1' then
- if ena = '1' then
-
- for i in 0 to (we_width-1) loop
- if wea(i) = '1' then
- ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width))
- := dina(((i+1)*byte_width-1) downto (i*byte_width));
- end if;
- end loop;
-
- if rsta = '1' then
- douta <= (others => '0');
- else
- douta <= ram_block(to_integer(unsigned(addra)));
+ for i in 0 to (we_width-1) loop
+ if wea(i) = '1' then
+ ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dina(((i+1)*byte_width-1) downto (i*byte_width));
end if;
+ end loop;
+ if rsta = '1' then
+ douta <= (others => '0');
+ else
+ douta <= ram_block(to_integer(unsigned(addra)));
end if;
end if;
end process;
- -- CLKB process
- ram_process_b : process(clkb)
+-- CLKB process
+ram_process_b:
+ process
begin
- if clkb = '1' and clkb'event then
-
- if enb = '1' then
-
- for i in 0 to (we_width-1) loop
- if web(i) = '1' then
- ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width))
- := dinb(((i+1)*byte_width-1) downto (i*byte_width));
- end if;
- end loop;
+ wait until clkb'event and clkb = '1';
+ if enb = '1' then
- if rstb = '1' then
- doutb <= (others => '0');
- else
- doutb <= ram_block(to_integer(unsigned(addrb)));
+ for i in 0 to (we_width-1) loop
+ if web(i) = '1' then
+ ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width))
+ := dinb(((i+1)*byte_width-1) downto (i*byte_width));
end if;
+ end loop;
+ if rstb = '1' then
+ doutb <= (others => '0');
+ else
+ doutb <= ram_block(to_integer(unsigned(addrb)));
end if;
end if;
-Subproject commit 225b899f1e904128ed4794041dc625751c08fc3f
+Subproject commit a3fc9411ccca6a85ea488c51699523610369ff53
volatile struct irc_register *irc3 = (volatile struct irc_register *)FPGA_IRC3_BASE;
volatile struct irc_register *irc4 = (volatile struct irc_register *)FPGA_IRC4_BASE;
+volatile uint8_t *irc1_state = (volatile uint8_t *)(FPGA_IRC1_BASE + 0x20);
+volatile uint8_t *irc2_state = (volatile uint8_t *)(FPGA_IRC2_BASE + 0x20);
+volatile uint8_t *irc3_state = (volatile uint8_t *)(FPGA_IRC3_BASE + 0x20);
+volatile uint8_t *irc4_state = (volatile uint8_t *)(FPGA_IRC4_BASE + 0x20);
+
/* Variables for configuration */
-volatile uint16_t *fpga_configure_line = (volatile uint16_t *)0x8003FFFC;
+volatile uint16_t *fpga_configure_line = (volatile uint16_t *)0x80007FF0;
int fpga_configured = 0;
int fpga_reconfiguration_locked = 1;
-/* BUS calibration - registers to measure the delay necessary for reading and writing */
-volatile uint32_t *fpga_bus_calib_read1 = (volatile uint32_t *)0x8003FFF0;
-volatile uint32_t *fpga_bus_calib_read2 = (volatile uint32_t *)0x8003FFF4;
+/* BUS measurement - registers to measure the delay necessary for reading and writing */
+volatile uint32_t *fpga_bus_meas_read1 = (volatile uint32_t *)0x80007FF0;
+volatile uint32_t *fpga_bus_meas_write1 = (volatile uint32_t *)0x80007FF4;
-volatile uint32_t *fpga_bus_calib_write1 = (volatile uint32_t *)0x8003FFF8;
-volatile uint32_t *fpga_bus_calib_write2 = (volatile uint32_t *)0x8003FFFC;
+volatile uint32_t *fpga_bus_meas_read2 = (volatile uint32_t *)0x80007FF8;
+volatile uint32_t *fpga_bus_meas_write2 = (volatile uint32_t *)0x80007FFC;
-/* BUS calibration - values (shifting all bits) */
-#define CALIB_VAL1 0xAAAAAAAA
-#define CALIB_VAL2 0x55555555
+/* BUS measurement - values (shifting all bits) */
+#define MEAS_VAL1 0xAAAAAAAA
+#define MEAS_VAL2 0x55555555
void appl_fpga_init()
{
*/
LPC_EMC->StaticConfig0 = 0x00000002;
- /* Delays - not calibrated at this point
+ /* Delays - not measured at this point
* We're running on 72 MHz, FPGA bus is running on 100 MHz async.
* Read: 32 cycles
* Write: 33 cycles
}
int appl_fpga_tumbl_set_reset(int reset)
-{
- int i;
-
+{
if (reset)
*tumbl_control |= FPGA_TUMBL_CONTROL_REG_RESET_BIT;
else
}
/*
- * Bus calibration - functions can be called via USB interface
+ * Bus measurement - functions can be called via USB interface
* Proper usage:
- * 1) Calibrate read
- * 2) Calibrate write
+ * 1) Measurement read
+ * 2) Measurement write
* 3) Set turnaround
* bus is not pipelined, therefore
* just necessary delay for I/O to enter
/* Cannot be on stack due to memory barrier for gcc */
static uint32_t a, b;
-int appl_fpga_calibrate_bus_read()
+int appl_fpga_measure_bus_read()
{
int i;
/* Read the values several times - so there are two flips at least
* NOTE: SDRAM reads / writes may occur in between!
*/
- a = *fpga_bus_calib_read1;
- b = *fpga_bus_calib_read2;
- a = *fpga_bus_calib_read1;
- b = *fpga_bus_calib_read2;
- a = *fpga_bus_calib_read1;
- b = *fpga_bus_calib_read2;
- a = *fpga_bus_calib_read1;
- b = *fpga_bus_calib_read2;
+ a = *fpga_bus_meas_read1;
+ b = *fpga_bus_meas_read2;
+ a = *fpga_bus_meas_read1;
+ b = *fpga_bus_meas_read2;
+ a = *fpga_bus_meas_read1;
+ b = *fpga_bus_meas_read2;
+ a = *fpga_bus_meas_read1;
+ b = *fpga_bus_meas_read2;
__memory_barrier();
/* Verify */
- if (a != CALIB_VAL1 || b != CALIB_VAL2)
+ if (a != MEAS_VAL1 || b != MEAS_VAL2)
{
if (LPC_EMC->StaticWaitRd0 == 0x1F)
{
return 0;
}
-int appl_fpga_calibrate_bus_write()
+int appl_fpga_measure_bus_write()
{
int i;
{
/* Make sure there is nothing other going on */
__memory_barrier();
- *fpga_bus_calib_write1 = 0x00000000;
- *fpga_bus_calib_write2 = 0x00000000;
+ *fpga_bus_meas_write1 = 0x00000000;
+ *fpga_bus_meas_write2 = 0x00000000;
__memory_barrier();
a = 0xFFFFFFFF;
b = 0xFFFFFFFF;
/* Write the values several times - so there are two flips at least
* NOTE: SDRAM reads / writes may occur in between!
*/
- *fpga_bus_calib_write1 = CALIB_VAL1;
- *fpga_bus_calib_write2 = CALIB_VAL2;
- *fpga_bus_calib_write1 = CALIB_VAL1;
- *fpga_bus_calib_write2 = CALIB_VAL2;
- *fpga_bus_calib_write1 = CALIB_VAL1;
- *fpga_bus_calib_write2 = CALIB_VAL2;
- *fpga_bus_calib_write1 = CALIB_VAL1;
- *fpga_bus_calib_write2 = CALIB_VAL2;
+ *fpga_bus_meas_write1 = MEAS_VAL1;
+ *fpga_bus_meas_write2 = MEAS_VAL2;
+ *fpga_bus_meas_write1 = MEAS_VAL1;
+ *fpga_bus_meas_write2 = MEAS_VAL2;
+ *fpga_bus_meas_write1 = MEAS_VAL1;
+ *fpga_bus_meas_write2 = MEAS_VAL2;
+ *fpga_bus_meas_write1 = MEAS_VAL1;
+ *fpga_bus_meas_write2 = MEAS_VAL2;
/*
* Strongly ordered memory
* GCC is blocked by volatilness
*/
__memory_barrier();
- a = *fpga_bus_calib_write1;
- b = *fpga_bus_calib_write2;
+ a = *fpga_bus_meas_write1;
+ b = *fpga_bus_meas_write2;
__memory_barrier();
/* Verify */
- if (a != CALIB_VAL1 || b != CALIB_VAL2)
+ if (a != MEAS_VAL1 || b != MEAS_VAL2)
{
if (LPC_EMC->StaticWaitWr0 == 0x1F)
{
for (i = 0; i < 128; i++)
{}
- /* Use EMC delays obtained through calibration */
- LPC_EMC->StaticWaitRd0 = 0x04;
- LPC_EMC->StaticWaitWr0 = 0x01;
+ /* Use EMC delays obtained through measurement */
+ LPC_EMC->StaticWaitRd0 = 0x07;
+ LPC_EMC->StaticWaitWr0 = 0x03;
/* Lift the reset */
hal_gpio_direction_output(XC_INIT_PIN, 1);
extern volatile uint32_t *tumbl_control;
extern volatile uint32_t *tumbl_trace_kick;
+extern volatile uint32_t *tumbl_pc;
extern volatile uint32_t *tumbl_imem;
extern volatile uint32_t *tumbl_dmem;
/* IRC */
-#define FPGA_IRC1_BASE 0x80020000
-#define FPGA_IRC2_BASE 0x80020010
-#define FPGA_IRC3_BASE 0x80020020
-#define FPGA_IRC4_BASE 0x80020030
+#define FPGA_IRC1_BASE 0x80022000
+#define FPGA_IRC2_BASE 0x80022008
+#define FPGA_IRC3_BASE 0x80022010
+#define FPGA_IRC4_BASE 0x80022018
struct irc_register
{
uint32_t count;
uint32_t count_index;
- uint32_t state;
};
extern volatile struct irc_register *irc1;
extern volatile struct irc_register *irc3;
extern volatile struct irc_register *irc4;
-extern volatile uint32_t *fpga_bcd;
+extern volatile uint8_t *irc1_state;
+extern volatile uint8_t *irc2_state;
+extern volatile uint8_t *irc3_state;
+extern volatile uint8_t *irc4_state;
+
/* Configuration defines */
void appl_fpga_init();
int appl_fpga_configure();
-int appl_fpga_calibrate_bus_read();
-int appl_fpga_calibrate_bus_write();
+int appl_fpga_measure_bus_read();
+int appl_fpga_measure_bus_write();
void appl_fpga_set_reconfiguration_lock(int lock);
int appl_fpga_get_reconfiguration_lock();
#define SWAP(x) (x)
#endif
-#define USB_VENDOR_TARGET_TUMBL 0x03
+#define USB_VENDOR_TARGET_TUMBL 0x03
-#define USB_CMD_FPGA_CONFIGURE 0xF000
-#define USB_CMD_FPGA_CALIBRATE_READ 0xF001
-#define USB_CMD_FPGA_CALIBRATE_WRITE 0xF002
-#define USB_CMD_FPGA_TEST_IRC 0xF004
-#define USB_CMD_FPGA_TEST_BCD 0xF005
+#define USB_CMD_FPGA_CONFIGURE 0xF000
+#define USB_CMD_FPGA_MEASURE_READ 0xF001
+#define USB_CMD_FPGA_MEASURE_WRITE 0xF002
+#define USB_CMD_FPGA_TEST_IRC 0xF004
-#define USB_CMD_FPGA_TUMBL_SET_RESET 0xF100
-#define USB_CMD_FPGA_TUMBL_SET_HALT 0xF101
-#define USB_CMD_FPGA_TUMBL_SET_TRACE 0xF102
-#define USB_CMD_FPGA_TUMBL_KICK_TRACE 0xF103
+#define USB_CMD_FPGA_TUMBL_SET_RESET 0xF100
+#define USB_CMD_FPGA_TUMBL_SET_HALT 0xF101
+#define USB_CMD_FPGA_TUMBL_SET_TRACE 0xF102
+#define USB_CMD_FPGA_TUMBL_KICK_TRACE 0xF103
+#define USB_CMD_FPGA_TUMBL_GET_PC 0xF104
-#define USB_CMD_FPGA_TUMBL_DUMP_IMEM 0xF200
-#define USB_CMD_FPGA_TUMBL_DUMP_DMEM 0xF201
+#define USB_CMD_FPGA_TUMBL_DUMP_IMEM 0xF200
+#define USB_CMD_FPGA_TUMBL_DUMP_DMEM 0xF201
-#define USB_CMD_FPGA_RESET 0xFFFF
+#define USB_CMD_FPGA_RESET 0xFFFF
usb_device_t usb_device;
usb_ep_t eps[NUM_ENDPOINTS];
case USB_CMD_FPGA_CONFIGURE:
return appl_fpga_configure();
- case USB_CMD_FPGA_CALIBRATE_READ:
- return appl_fpga_calibrate_bus_read();
+ case USB_CMD_FPGA_MEASURE_READ:
+ return appl_fpga_measure_bus_read();
- case USB_CMD_FPGA_CALIBRATE_WRITE:
- return appl_fpga_calibrate_bus_write();
+ case USB_CMD_FPGA_MEASURE_WRITE:
+ return appl_fpga_measure_bus_write();
case USB_CMD_FPGA_TEST_IRC:
printf("IRC1: count = %d, count index = %d\n", (unsigned int) irc1->count, (unsigned int) irc1->count_index);
case USB_CMD_FPGA_TUMBL_KICK_TRACE:
return appl_fpga_tumbl_kick_trace();
+
+ case USB_CMD_FPGA_TUMBL_GET_PC:
+ printf("Tubml PC: 0x%08X\n", (unsigned int) *tumbl_pc);
+ return 0;
case USB_CMD_FPGA_TUMBL_DUMP_IMEM:
printf("TUMBL IMEM:\n");