From: Martin Meloun Date: Sun, 11 May 2014 21:43:17 +0000 (+0200) Subject: Multiple patches X-Git-Url: https://rtime.felk.cvut.cz/gitweb/fpga/lx-cpu1/lx-rocon.git/commitdiff_plain/c48c9255328d2e545d223a02d82109f4251ed6d9 Multiple patches 1) USB sendhex forked due to changes (patch included) 2) Synthesis profiling for HW 3) Added LX master 4) Calbration -> Measuerement 5) Master CPU bus is 50 MHz and wired to Tumbl external bus, fixes in wiring 6) Cleanups 7) Other crap I forgot in the meantime :-) Signed-off-by: Martin Meloun --- diff --git a/host/app/usb_sendhex b/host/app/usb_sendhex deleted file mode 120000 index e5d04b2..0000000 --- a/host/app/usb_sendhex +++ /dev/null @@ -1 +0,0 @@ -../../submodule/ulan-app/app-host/usb_sendhex/ \ No newline at end of file diff --git a/host/app/usb_sendhex/0001-Implement-USB_VENDOR_CALL-feature-in-usb_sendhex.patch b/host/app/usb_sendhex/0001-Implement-USB_VENDOR_CALL-feature-in-usb_sendhex.patch new file mode 100644 index 0000000..2cb9db5 --- /dev/null +++ b/host/app/usb_sendhex/0001-Implement-USB_VENDOR_CALL-feature-in-usb_sendhex.patch @@ -0,0 +1,150 @@ +From 225b899f1e904128ed4794041dc625751c08fc3f Mon Sep 17 00:00:00 2001 +From: Martin Meloun +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 +--- + 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 start address of transfer\n"); + printf(" -l, --length length of upload block\n"); + printf(" -b, --block maximal block length\n"); ++ printf(" -c, --call vendor custom call\n"); ++ printf(" -a, --argument argument for vendor custom call\n"); + printf(" -g, --go start program from address\n"); + printf(" -r, --reset reset before download\n"); + printf(" -E, --mass-erase 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 + diff --git a/host/app/usb_sendhex/Makefile b/host/app/usb_sendhex/Makefile new file mode 100644 index 0000000..b22a357 --- /dev/null +++ b/host/app/usb_sendhex/Makefile @@ -0,0 +1,14 @@ +# 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 + diff --git a/host/app/usb_sendhex/Makefile.omk b/host/app/usb_sendhex/Makefile.omk new file mode 100644 index 0000000..7bd55e2 --- /dev/null +++ b/host/app/usb_sendhex/Makefile.omk @@ -0,0 +1,11 @@ +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 diff --git a/host/app/usb_sendhex/usb_sendhex.c b/host/app/usb_sendhex/usb_sendhex.c new file mode 100644 index 0000000..c297822 --- /dev/null +++ b/host/app/usb_sendhex/usb_sendhex.c @@ -0,0 +1,1119 @@ +/* usb_sendhex - program for manage device firmware by USB + * R.Bartosinski (C)2004 + * + * Based on 'ul_sendhex' + * + * Version 1.1 - 2013/08/26 + */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 \n"); + printf(" -d, --vid device vendor id (VID) [0x%04X]\n", USB_DEV_VID); + printf(" -i, --pid product id (PID) [0x%04X]\n", USB_DEV_PID); + printf(" -t, --type target module memory space\n"); + printf(" -s, --start start address of transfer\n"); + printf(" -l, --length length of upload block\n"); + printf(" -b, --block maximal block length\n"); + printf(" -c, --call vendor custom call\n"); + printf(" -a, --argument argument for vendor custom call\n"); + printf(" -g, --go start program from address\n"); + printf(" -r, --reset reset before download\n"); + printf(" -E, --mass-erase 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 of data file [ihex]\n"); + printf(" -p, --print print devices\n"); + printf(" --debug-kernel 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; +} diff --git a/hw/Makefile b/hw/Makefile index cfdb561..f67a1c0 100644 --- a/hw/Makefile +++ b/hw/Makefile @@ -60,11 +60,13 @@ REQ_SRC := . 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 @@ -72,7 +74,7 @@ XST_WRITE_TIMING_CONSTRAINTS := NO 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 @@ -83,7 +85,15 @@ XST_IOBUF := 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 @@ -100,9 +110,9 @@ TARGET_OBJDUMP := $(MB_CROSS_COMPILE)objdump 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) @@ -133,10 +143,11 @@ re-synthesize $(REQ_NGC): $(addprefix $(REQ_SRC)/,$(PRJ)) -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) \ @@ -153,7 +164,10 @@ re-synthesize $(REQ_NGC): $(addprefix $(REQ_SRC)/,$(PRJ)) -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) @@ -166,7 +180,7 @@ 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 @@ -174,7 +188,7 @@ re-map $(REQ_NCD_MAP) $(REQ_PCF): $(REQ_NGD) .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) diff --git a/hw/bus_calibration.vhd b/hw/bus_calibration.vhd deleted file mode 100644 index 2c63a6a..0000000 --- a/hw/bus_calibration.vhd +++ /dev/null @@ -1,146 +0,0 @@ -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; - diff --git a/hw/bus_irc.vhd b/hw/bus_irc.vhd index 8ca630a..6eb65fc 100644 --- a/hw/bus_irc.vhd +++ b/hw/bus_irc.vhd @@ -2,7 +2,7 @@ library ieee; 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 @@ -11,199 +11,206 @@ entity bus_irc is ( 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; diff --git a/hw/bus_lxmaster.vhd b/hw/bus_lxmaster.vhd new file mode 100644 index 0000000..948d0a2 --- /dev/null +++ b/hw/bus_lxmaster.vhd @@ -0,0 +1,49 @@ +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; diff --git a/hw/bus_measurement.vhd b/hw/bus_measurement.vhd new file mode 100644 index 0000000..e681c9f --- /dev/null +++ b/hw/bus_measurement.vhd @@ -0,0 +1,99 @@ +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; + diff --git a/hw/bus_tumbl.vhd b/hw/bus_tumbl.vhd index 712cc74..2496570 100644 --- a/hw/bus_tumbl.vhd +++ b/hw/bus_tumbl.vhd @@ -4,7 +4,7 @@ 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.mbl_Pkg.all; +use work.mbl_pkg.all; use work.lx_rocon_pkg.all; -- Connects tumbl to the Master CPU @@ -13,76 +13,53 @@ entity bus_tumbl is 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 @@ -117,198 +94,142 @@ begin 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; diff --git a/hw/bus_tumbl_interconnect.vhd b/hw/bus_tumbl_interconnect.vhd deleted file mode 100644 index 30b3e99..0000000 --- a/hw/bus_tumbl_interconnect.vhd +++ /dev/null @@ -1,48 +0,0 @@ -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; - diff --git a/hw/calibration_read_register.vhd b/hw/calibration_read_register.vhd deleted file mode 100644 index 09f07f2..0000000 --- a/hw/calibration_read_register.vhd +++ /dev/null @@ -1,35 +0,0 @@ -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; diff --git a/hw/calibration_write_register.vhd b/hw/calibration_write_register.vhd deleted file mode 100644 index 33922fb..0000000 --- a/hw/calibration_write_register.vhd +++ /dev/null @@ -1,72 +0,0 @@ -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; - diff --git a/hw/crc.vhd b/hw/crc.vhd new file mode 100644 index 0000000..55d6781 --- /dev/null +++ b/hw/crc.vhd @@ -0,0 +1,49 @@ +-- +-- * CRC-8 generator * +-- +-- part of LXPWR motion control board (c) PiKRON Ltd +-- idea by Pavel Pisa PiKRON Ltd +-- code by Marek Peca +-- 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; diff --git a/hw/dff.vhd b/hw/dff.vhd deleted file mode 100644 index 10da173..0000000 --- a/hw/dff.vhd +++ /dev/null @@ -1,34 +0,0 @@ -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; diff --git a/hw/dff2.vhd b/hw/dff2.vhd index c0d62dd..be894d6 100644 --- a/hw/dff2.vhd +++ b/hw/dff2.vhd @@ -3,6 +3,7 @@ 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; -- D circuit (filtered) @@ -23,20 +24,19 @@ begin 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; diff --git a/hw/irc_proc_inc.vhd b/hw/irc_proc_inc.vhd index 8c9875b..f415984 100644 --- a/hw/irc_proc_inc.vhd +++ b/hw/irc_proc_inc.vhd @@ -31,15 +31,15 @@ begin 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; diff --git a/hw/irc_proc_main.vhd b/hw/irc_proc_main.vhd index ad4a7e8..45f898a 100644 --- a/hw/irc_proc_main.vhd +++ b/hw/irc_proc_main.vhd @@ -2,10 +2,12 @@ library ieee; 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 ( @@ -13,13 +15,10 @@ entity irc_proc_main is 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); @@ -31,22 +30,17 @@ end irc_proc_main; 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 @@ -88,101 +82,97 @@ 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; diff --git a/hw/irc_reader.vhd b/hw/irc_reader.vhd index 3689787..e5cf207 100644 --- a/hw/irc_reader.vhd +++ b/hw/irc_reader.vhd @@ -23,19 +23,18 @@ entity irc_reader is 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, @@ -45,11 +44,11 @@ architecture rtl of irc_reader is 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, diff --git a/hw/lx-rocon.ucf b/hw/lx-rocon.ucf index 73ed939..95a4d01 100644 --- a/hw/lx-rocon.ucf +++ b/hw/lx-rocon.ucf @@ -6,13 +6,13 @@ CONFIG VCCAUX = 3.3; # ==================================================================== # 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; @@ -75,53 +75,30 @@ NET DATA<30> LOC = P138 | 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; diff --git a/hw/lx-rocon_firmware/firmware.c b/hw/lx-rocon_firmware/firmware.c index e12a76a..655fa6f 100644 --- a/hw/lx-rocon_firmware/firmware.c +++ b/hw/lx-rocon_firmware/firmware.c @@ -41,6 +41,12 @@ void init_defvals() 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; @@ -74,10 +80,10 @@ void main() { 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++; } } - diff --git a/hw/lx-rocon_firmware/start.S b/hw/lx-rocon_firmware/start.S index 136809f..3f7a81b 100644 --- a/hw/lx-rocon_firmware/start.S +++ b/hw/lx-rocon_firmware/start.S @@ -44,12 +44,12 @@ _main: 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 diff --git a/hw/lx-rocon_tumbl/lx_rocon_dmem.vhd b/hw/lx-rocon_tumbl/lx_rocon_dmem.vhd index 2315529..cccc34e 100644 --- a/hw/lx-rocon_tumbl/lx_rocon_dmem.vhd +++ b/hw/lx-rocon_tumbl/lx_rocon_dmem.vhd @@ -4,7 +4,7 @@ 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.mbl_Pkg.all; +use work.mbl_pkg.all; use work.lx_rocon_pkg.all; -- 4 kB data memory for Thumbl core @@ -16,9 +16,8 @@ entity lx_rocon_dmem is -- 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 @@ -32,14 +31,9 @@ entity lx_rocon_dmem is 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, @@ -52,8 +46,8 @@ begin 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, diff --git a/hw/lx-rocon_tumbl/lx_rocon_gprf_abd.vhd b/hw/lx-rocon_tumbl/lx_rocon_gprf_abd.vhd index 7c1613a..550655c 100644 --- a/hw/lx-rocon_tumbl/lx_rocon_gprf_abd.vhd +++ b/hw/lx-rocon_tumbl/lx_rocon_gprf_abd.vhd @@ -4,7 +4,7 @@ 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.mbl_Pkg.all; +use work.mbl_pkg.all; use work.lx_rocon_pkg.all; -- 32x32b General Puprose Registers for Tumbl Core @@ -72,89 +72,89 @@ begin 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; diff --git a/hw/lx-rocon_tumbl/lx_rocon_imem.vhd b/hw/lx-rocon_tumbl/lx_rocon_imem.vhd index 6d3135b..69f9772 100644 --- a/hw/lx-rocon_tumbl/lx_rocon_imem.vhd +++ b/hw/lx-rocon_tumbl/lx_rocon_imem.vhd @@ -4,7 +4,7 @@ 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.mbl_Pkg.all; +use work.mbl_pkg.all; use work.lx_rocon_pkg.all; -- 2 kB instruction memory for Thumbl core @@ -16,7 +16,7 @@ entity lx_rocon_imem is -- 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; @@ -31,7 +31,7 @@ end lx_rocon_imem; 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, @@ -45,7 +45,7 @@ begin rsta => '0', ena => cs_i, wea => "0000", - addra => adr_i(10 downto 2), + addra => adr_i, dina => C_32_ZEROS, douta => dat_o, diff --git a/hw/lx-rocon_tumbl/lx_rocon_tumbl.vhd b/hw/lx-rocon_tumbl/lx_rocon_tumbl.vhd index 49ed8cd..122e1b3 100644 --- a/hw/lx-rocon_tumbl/lx_rocon_tumbl.vhd +++ b/hw/lx-rocon_tumbl/lx_rocon_tumbl.vhd @@ -4,17 +4,18 @@ 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.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; @@ -56,10 +57,10 @@ end entity lx_rocon_tumbl; 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; @@ -95,10 +96,11 @@ architecture rtl of lx_rocon_tumbl is 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; @@ -111,12 +113,12 @@ begin 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, @@ -127,14 +129,13 @@ begin 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, @@ -146,7 +147,7 @@ begin dout_m => dmem_data_o ); - I_FETCH: fetch +I_FETCH: fetch port map ( prog_cntr_i => IF2ID_r.program_counter, @@ -155,7 +156,7 @@ begin IF2ID_o => IF2ID_s ); - I_DECODE: decode +I_DECODE: decode generic map(USE_HW_MUL_g, USE_BARREL_g, COMPATIBILITY_MODE_g) port map ( @@ -169,7 +170,7 @@ begin ID2CTRL_o => ID2CTRL_s ); - I_GPRF: lx_rocon_gprf_abd +I_GPRF: lx_rocon_gprf_abd port map ( clk_i => clk_i, @@ -181,7 +182,7 @@ begin GPRF2EX_o => GPRF2EX_s ); - I_EXEQ: exeq +I_EXEQ: exeq generic map(USE_HW_MUL_g, USE_BARREL_g, COMPATIBILITY_MODE_g) port map ( @@ -212,11 +213,11 @@ begin -- 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, @@ -231,8 +232,8 @@ begin 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, @@ -286,15 +287,15 @@ begin 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; diff --git a/hw/lx_rocon_pkg.vhd b/hw/lx_rocon_pkg.vhd index 547349b..deea826 100644 --- a/hw/lx_rocon_pkg.vhd +++ b/hw/lx_rocon_pkg.vhd @@ -16,20 +16,28 @@ package lx_rocon_pkg is 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 @@ -38,13 +46,10 @@ package lx_rocon_pkg is 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); @@ -96,8 +101,8 @@ package lx_rocon_pkg is 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; @@ -128,6 +133,36 @@ package lx_rocon_pkg is ); 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 -------------------------------------------------------------------------------- @@ -201,8 +236,7 @@ package lx_rocon_pkg is 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 @@ -232,19 +266,27 @@ package lx_rocon_pkg is -- 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; @@ -254,53 +296,20 @@ package lx_rocon_pkg is ( 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 @@ -315,9 +324,7 @@ package lx_rocon_pkg is 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; @@ -326,26 +333,71 @@ package lx_rocon_pkg is 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 -------------------------------------------------------------------------------- diff --git a/hw/lx_rocon_top.prj b/hw/lx_rocon_top.prj index 1d260df..8ed8bbe 100644 --- a/hw/lx_rocon_top.prj +++ b/hw/lx_rocon_top.prj @@ -1,8 +1,9 @@ -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" @@ -13,12 +14,14 @@ vhdl work "lx-rocon_tumbl/lx_rocon_imem.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" diff --git a/hw/lx_rocon_top.vhd b/hw/lx_rocon_top.vhd index 987e402..4e27660 100644 --- a/hw/lx_rocon_top.vhd +++ b/hw/lx_rocon_top.vhd @@ -7,7 +7,7 @@ use ieee.numeric_std.all; 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 @@ -18,97 +18,102 @@ use work.lx_rocon_pkg.all; -- -- 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 @@ -118,261 +123,253 @@ architecture Behavioral of lx_rocon_top is 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'); @@ -382,57 +379,71 @@ memory_bus_out: 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; diff --git a/hw/lxmaster.vhd b/hw/lxmaster.vhd new file mode 100644 index 0000000..262a4e6 --- /dev/null +++ b/hw/lxmaster.vhd @@ -0,0 +1,260 @@ +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; diff --git a/hw/measurement_register.vhd b/hw/measurement_register.vhd new file mode 100644 index 0000000..5192694 --- /dev/null +++ b/hw/measurement_register.vhd @@ -0,0 +1,71 @@ +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; + diff --git a/hw/qcounter.vhd b/hw/qcounter.vhd index 8eef2f0..8dcbe5c 100644 --- a/hw/qcounter.vhd +++ b/hw/qcounter.vhd @@ -45,7 +45,7 @@ architecture behavioral of qcounter is signal count_index_s : std_logic_vector (7 downto 0); begin - dff_a: dff2 +dff_a: dff2 port map ( clk_i => clk_i, @@ -54,7 +54,7 @@ begin q_o => a_s ); - dff_b: dff2 + dff_b: dff2 port map ( clk_i => clk_i, @@ -63,7 +63,7 @@ begin q_o => b_s ); - dff_index: dff2 +dff_index: dff2 port map ( clk_i => clk_i, @@ -153,36 +153,36 @@ comb_count: 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; diff --git a/hw/util_pkg.vhd b/hw/util_pkg.vhd new file mode 100644 index 0000000..a9b7048 --- /dev/null +++ b/hw/util_pkg.vhd @@ -0,0 +1,51 @@ +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; diff --git a/hw/xilinx_dualport_bram_no_change.vhd b/hw/xilinx_dualport_bram_no_change.vhd index 55cdfb9..10a9d95 100644 --- a/hw/xilinx_dualport_bram_no_change.vhd +++ b/hw/xilinx_dualport_bram_no_change.vhd @@ -39,58 +39,56 @@ architecture Behavioral of xilinx_dualport_bram_no_change is 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; diff --git a/hw/xilinx_dualport_bram_write_first.vhd b/hw/xilinx_dualport_bram_write_first.vhd index 50e05ec..7e0e618 100644 --- a/hw/xilinx_dualport_bram_write_first.vhd +++ b/hw/xilinx_dualport_bram_write_first.vhd @@ -39,54 +39,50 @@ architecture Behavioral of xilinx_dualport_bram_write_first is 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; diff --git a/submodule/ulan-app b/submodule/ulan-app index 225b899..a3fc941 160000 --- a/submodule/ulan-app +++ b/submodule/ulan-app @@ -1 +1 @@ -Subproject commit 225b899f1e904128ed4794041dc625751c08fc3f +Subproject commit a3fc9411ccca6a85ea488c51699523610369ff53 diff --git a/sw/app/rocon/appl_fpga.c b/sw/app/rocon/appl_fpga.c index 67ed35b..1d4d92d 100644 --- a/sw/app/rocon/appl_fpga.c +++ b/sw/app/rocon/appl_fpga.c @@ -25,21 +25,26 @@ volatile struct irc_register *irc2 = (volatile struct irc_register *)FPGA_IRC2_B 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() { @@ -55,7 +60,7 @@ 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 @@ -72,9 +77,7 @@ void appl_fpga_init() } int appl_fpga_tumbl_set_reset(int reset) -{ - int i; - +{ if (reset) *tumbl_control |= FPGA_TUMBL_CONTROL_REG_RESET_BIT; else @@ -128,10 +131,10 @@ void appl_fpga_tumbl_write(unsigned int offset, unsigned char *ptr, int len) } /* - * 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 @@ -141,7 +144,7 @@ void appl_fpga_tumbl_write(unsigned int offset, unsigned char *ptr, int len) /* 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; @@ -160,18 +163,18 @@ int appl_fpga_calibrate_bus_read() /* 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) { @@ -200,7 +203,7 @@ int appl_fpga_calibrate_bus_read() return 0; } -int appl_fpga_calibrate_bus_write() +int appl_fpga_measure_bus_write() { int i; @@ -213,8 +216,8 @@ int appl_fpga_calibrate_bus_write() { /* 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; @@ -222,25 +225,25 @@ int appl_fpga_calibrate_bus_write() /* 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) { @@ -406,9 +409,9 @@ int appl_fpga_configure() 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); diff --git a/sw/app/rocon/appl_fpga.h b/sw/app/rocon/appl_fpga.h index 738c577..e98bc0a 100644 --- a/sw/app/rocon/appl_fpga.h +++ b/sw/app/rocon/appl_fpga.h @@ -20,21 +20,21 @@ 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; @@ -42,7 +42,11 @@ extern volatile struct irc_register *irc2; 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 */ @@ -63,8 +67,8 @@ void appl_fpga_tumbl_write(unsigned int offset, unsigned char *ptr, int len); 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(); diff --git a/sw/app/rocon/appl_usb.c b/sw/app/rocon/appl_usb.c index b3bb8a0..76af960 100644 --- a/sw/app/rocon/appl_usb.c +++ b/sw/app/rocon/appl_usb.c @@ -30,23 +30,23 @@ #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]; @@ -178,11 +178,11 @@ uint16_t appl_usb_vendor_call(uint16_t command, uint16_t argument) 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); @@ -202,6 +202,10 @@ uint16_t appl_usb_vendor_call(uint16_t command, uint16_t argument) 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");