aboutsummaryrefslogtreecommitdiff
path: root/VexRiscv/doc/gcdPeripheral/src
diff options
context:
space:
mode:
authorFriedrich Beckmann <friedrich.beckmann@hs-augsburg.de>2022-07-25 17:55:39 +0200
committerFriedrich Beckmann <friedrich.beckmann@hs-augsburg.de>2022-07-25 17:55:39 +0200
commit3fff6023602822531efdae30bc8ebf862967f1ef (patch)
tree16028102b8d850f8ab3115d28a8539ca6bc5f51d /VexRiscv/doc/gcdPeripheral/src
Initial Commit
Diffstat (limited to 'VexRiscv/doc/gcdPeripheral/src')
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/makefile134
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/project/build.properties1
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/crt.S98
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gcd.h13
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gpio.h15
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/interrupt.h17
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/linker.ld110
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.c62
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.h78
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/murax.h20
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/prescaler.h16
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/timer.h20
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/uart.h42
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/demo/Murax.scala559
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/Apb3GCDCtrl.scala39
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDCtrl.scala68
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDData.scala54
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDTop.scala46
-rw-r--r--VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDTopSim.scala52
19 files changed, 1444 insertions, 0 deletions
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/makefile b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/makefile
new file mode 100644
index 0000000..0f4abd8
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/makefile
@@ -0,0 +1,134 @@
+PROJ_NAME=gcd_world
+DEBUG=no
+BENCH=no
+MULDIV=no
+
+SRCS = $(wildcard src/*.c) \
+ $(wildcard src/*.cpp) \
+ $(wildcard src/*.S)
+
+OBJDIR = build
+
+INC =
+LIBS =
+LIBSINC = -L$(OBJDIR)
+LDSCRIPT = ./src/linker.ld
+
+#include ../../../resources/gcc.mk
+# Set it to yes if you are using the sifive precompiled GCC pack
+SIFIVE_GCC_PACK ?= no
+
+ifeq ($(SIFIVE_GCC_PACK),yes)
+ RISCV_NAME ?= riscv64-unknown-elf
+ RISCV_PATH ?= /home/sallar/tools/riscv-64-newlib-dist/
+else
+ RISCV_NAME ?= riscv32-unknown-elf
+ ifeq ($(MULDIV),yes)
+ RISCV_PATH ?= /home/sallar/tools/riscv-32-imac-ilp32-newlib-dist/
+ else
+ RISCV_PATH ?= /home/sallar/tools/rv32i-ilp32-dist/
+ endif
+endif
+
+MABI=ilp32
+MARCH := rv32i
+ifeq ($(MULDIV),yes)
+ MARCH := $(MARCH)m
+endif
+ifeq ($(COMPRESSED),yes)
+ MARCH := $(MARCH)ac
+endif
+
+CFLAGS += -march=$(MARCH) -mabi=$(MABI) -DNDEBUG
+LDFLAGS += -march=$(MARCH) -mabi=$(MABI)
+
+
+
+#include ../../../resources/subproject.mk
+
+
+ifeq ($(DEBUG),yes)
+ CFLAGS += -g3 -O0
+endif
+
+ifeq ($(DEBUG),no)
+ CFLAGS += -g -Os
+endif
+
+ifeq ($(BENCH),yes)
+ CFLAGS += -fno-inline
+endif
+
+ifeq ($(SIFIVE_GCC_PACK),yes)
+ RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/$(MARCH)/$(MABI)/
+else
+ RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/
+endif
+
+
+
+
+
+RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
+RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
+RISCV_CC=$(RISCV_PATH)/bin/$(RISCV_NAME)-gcc
+
+CFLAGS += -MD -fstrict-volatile-bitfields -fno-strict-aliasing
+LDFLAGS += -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usage
+#LDFLAGS += -lgcc -lc -lg -nostdlib -lgcc -msave-restore --strip-debug,
+
+OBJS := $(SRCS)
+OBJS := $(OBJS:.c=.o)
+OBJS := $(OBJS:.cpp=.o)
+OBJS := $(OBJS:.S=.o)
+OBJS := $(OBJS:..=miaou)
+OBJS := $(addprefix $(OBJDIR)/,$(OBJS))
+
+
+all: $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v
+
+$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)
+ $(RISCV_CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBSINC) $(LIBS)
+
+%.hex: %.elf
+ $(RISCV_OBJCOPY) -O ihex $^ $@
+
+%.bin: %.elf
+ $(RISCV_OBJCOPY) -O binary $^ $@
+
+%.v: %.elf
+ $(RISCV_OBJCOPY) -O verilog $^ $@
+
+%.asm: %.elf
+ $(RISCV_OBJDUMP) -S -d $^ > $@
+
+$(OBJDIR)/%.o: %.c
+ mkdir -p $(dir $@)
+ $(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
+ $(RISCV_CC) -S $(CFLAGS) $(INC) -o $@.disasm $^
+
+$(OBJDIR)/%.o: %.cpp
+ mkdir -p $(dir $@)
+ $(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
+
+$(OBJDIR)/%.o: %.S
+ mkdir -p $(dir $@)
+ $(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1
+
+$(OBJDIR):
+ mkdir -p $@
+
+.PHONY: clean
+clean:
+ rm -rf $(OBJDIR)/src
+ rm -f $(OBJDIR)/$(PROJ_NAME).elf
+ rm -f $(OBJDIR)/$(PROJ_NAME).hex
+ rm -f $(OBJDIR)/$(PROJ_NAME).map
+ rm -f $(OBJDIR)/$(PROJ_NAME).v
+ rm -f $(OBJDIR)/$(PROJ_NAME).asm
+ find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm
+ find $(OBJDIR) -type f -name '*.d' -print0 | xargs -0 -r rm
+
+clean-all : clean
+
+.SECONDARY: $(OBJS)
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/project/build.properties b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/project/build.properties
new file mode 100644
index 0000000..dbae93b
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/project/build.properties
@@ -0,0 +1 @@
+sbt.version=1.4.9
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/crt.S b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/crt.S
new file mode 100644
index 0000000..62d67b9
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/crt.S
@@ -0,0 +1,98 @@
+.global crtStart
+.global main
+.global irqCallback
+
+ .section .start_jump,"ax",@progbits
+crtStart:
+ //long jump to allow crtInit to be anywhere
+ //do it always in 12 bytes
+ lui x2, %hi(crtInit)
+ addi x2, x2, %lo(crtInit)
+ jalr x1,x2
+ nop
+
+.section .text
+
+.global trap_entry
+.align 5
+trap_entry:
+ sw x1, - 1*4(sp)
+ sw x5, - 2*4(sp)
+ sw x6, - 3*4(sp)
+ sw x7, - 4*4(sp)
+ sw x10, - 5*4(sp)
+ sw x11, - 6*4(sp)
+ sw x12, - 7*4(sp)
+ sw x13, - 8*4(sp)
+ sw x14, - 9*4(sp)
+ sw x15, -10*4(sp)
+ sw x16, -11*4(sp)
+ sw x17, -12*4(sp)
+ sw x28, -13*4(sp)
+ sw x29, -14*4(sp)
+ sw x30, -15*4(sp)
+ sw x31, -16*4(sp)
+ addi sp,sp,-16*4
+ call irqCallback
+ lw x1 , 15*4(sp)
+ lw x5, 14*4(sp)
+ lw x6, 13*4(sp)
+ lw x7, 12*4(sp)
+ lw x10, 11*4(sp)
+ lw x11, 10*4(sp)
+ lw x12, 9*4(sp)
+ lw x13, 8*4(sp)
+ lw x14, 7*4(sp)
+ lw x15, 6*4(sp)
+ lw x16, 5*4(sp)
+ lw x17, 4*4(sp)
+ lw x28, 3*4(sp)
+ lw x29, 2*4(sp)
+ lw x30, 1*4(sp)
+ lw x31, 0*4(sp)
+ addi sp,sp,16*4
+ mret
+ .text
+
+
+crtInit:
+ .option push
+ .option norelax
+ la gp, __global_pointer$
+ .option pop
+ la sp, _stack_start
+
+bss_init:
+ la a0, _bss_start
+ la a1, _bss_end
+bss_loop:
+ beq a0,a1,bss_done
+ sw zero,0(a0)
+ add a0,a0,4
+ j bss_loop
+bss_done:
+
+ctors_init:
+ la a0, _ctors_start
+ addi sp,sp,-4
+ctors_loop:
+ la a1, _ctors_end
+ beq a0,a1,ctors_done
+ lw a3,0(a0)
+ add a0,a0,4
+ sw a0,0(sp)
+ jalr a3
+ lw a0,0(sp)
+ j ctors_loop
+ctors_done:
+ addi sp,sp,4
+
+
+ li a0, 0x880 //880 enable timer + external interrupts
+ csrw mie,a0
+ li a0, 0x1808 //1808 enable interrupts
+ csrw mstatus,a0
+
+ call main
+infinitLoop:
+ j infinitLoop
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gcd.h b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gcd.h
new file mode 100644
index 0000000..1d3ccb7
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gcd.h
@@ -0,0 +1,13 @@
+#ifndef GCD_H_
+#define GCD_H_
+
+typedef struct
+{
+ volatile uint32_t A;
+ volatile uint32_t B;
+ volatile uint32_t RES;
+ volatile uint32_t READY;
+ volatile uint32_t VALID;
+} Gcd_Reg;
+
+#endif /* GCD_H_ */
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gpio.h b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gpio.h
new file mode 100644
index 0000000..34348fe
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/gpio.h
@@ -0,0 +1,15 @@
+#ifndef GPIO_H_
+#define GPIO_H_
+
+
+typedef struct
+{
+ volatile uint32_t INPUT;
+ volatile uint32_t OUTPUT;
+ volatile uint32_t OUTPUT_ENABLE;
+} Gpio_Reg;
+
+
+#endif /* GPIO_H_ */
+
+
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/interrupt.h b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/interrupt.h
new file mode 100644
index 0000000..23b7d27
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/interrupt.h
@@ -0,0 +1,17 @@
+#ifndef INTERRUPTCTRL_H_
+#define INTERRUPTCTRL_H_
+
+#include <stdint.h>
+
+typedef struct
+{
+ volatile uint32_t PENDINGS;
+ volatile uint32_t MASKS;
+} InterruptCtrl_Reg;
+
+static void interruptCtrl_init(InterruptCtrl_Reg* reg){
+ reg->MASKS = 0;
+ reg->PENDINGS = 0xFFFFFFFF;
+}
+
+#endif /* INTERRUPTCTRL_H_ */
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/linker.ld b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/linker.ld
new file mode 100644
index 0000000..57bc2f7
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/linker.ld
@@ -0,0 +1,110 @@
+/*
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+*/
+OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
+OUTPUT_ARCH(riscv)
+ENTRY(crtStart)
+
+MEMORY {
+ RAM (rwx): ORIGIN = 0x80000000, LENGTH = 2k
+}
+
+_stack_size = DEFINED(_stack_size) ? _stack_size : 256;
+_heap_size = DEFINED(_heap_size) ? _heap_size : 0;
+
+SECTIONS {
+
+ ._vector ORIGIN(RAM): {
+ *crt.o(.start_jump);
+ *crt.o(.text);
+ } > RAM
+
+ ._user_heap (NOLOAD):
+ {
+ . = ALIGN(8);
+ PROVIDE ( end = . );
+ PROVIDE ( _end = . );
+ PROVIDE ( _heap_start = .);
+ . = . + _heap_size;
+ . = ALIGN(8);
+ PROVIDE ( _heap_end = .);
+ } > RAM
+
+._stack (NOLOAD):
+ {
+ . = ALIGN(16);
+ PROVIDE (_stack_end = .);
+ . = . + _stack_size;
+ . = ALIGN(16);
+ PROVIDE (_stack_start = .);
+ } > RAM
+
+ .data :
+ {
+ *(.rdata)
+ *(.rodata .rodata.*)
+ *(.gnu.linkonce.r.*)
+ *(.data .data.*)
+ *(.gnu.linkonce.d.*)
+ . = ALIGN(8);
+ PROVIDE( __global_pointer$ = . + 0x800 );
+ *(.sdata .sdata.*)
+ *(.gnu.linkonce.s.*)
+ . = ALIGN(8);
+ *(.srodata.cst16)
+ *(.srodata.cst8)
+ *(.srodata.cst4)
+ *(.srodata.cst2)
+ *(.srodata .srodata.*)
+ } > RAM
+
+ .bss (NOLOAD) : {
+ . = ALIGN(4);
+ /* This is used by the startup in order to initialize the .bss secion */
+ _bss_start = .;
+ *(.sbss*)
+ *(.gnu.linkonce.sb.*)
+ *(.bss .bss.*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(4);
+ _bss_end = .;
+ } > RAM
+
+
+ .rodata :
+ {
+ *(.rdata)
+ *(.rodata .rodata.*)
+ *(.gnu.linkonce.r.*)
+ } > RAM
+
+ .noinit (NOLOAD) : {
+ . = ALIGN(4);
+ *(.noinit .noinit.*)
+ . = ALIGN(4);
+ } > RAM
+
+ .memory : {
+ *(.text);
+ end = .;
+ } > RAM
+
+ .ctors :
+ {
+ . = ALIGN(4);
+ _ctors_start = .;
+ KEEP(*(.init_array*))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ . = ALIGN(4);
+ _ctors_end = .;
+ PROVIDE ( END_OF_SW_IMAGE = . );
+ } > RAM
+
+}
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.c b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.c
new file mode 100644
index 0000000..fccbcc2
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.c
@@ -0,0 +1,62 @@
+//#include "stddefs.h"
+#include <stdint.h>
+
+#include "murax.h"
+
+#include "main.h"
+
+#define DEBUG 0
+
+uint32_t gcd(uint32_t a, uint32_t b){
+ GCD->A = a;
+ GCD->B = b;
+ GCD->VALID = 0x00000001;
+ uint32_t rdyFlag = 0;
+ do{
+ rdyFlag = GCD->READY;
+ }while(!rdyFlag);
+ return GCD->RES;
+}
+
+void calcPrintGCD(uint32_t a, uint32_t b){
+ uint32_t myGCD = 0;
+ char buf[5] = { 0x00 };
+ char aBuf[11] = { 0x00 };
+ char bBuf[11] = { 0x00 };
+ itoa(a, aBuf, 10);
+ itoa(b, bBuf, 10);
+ print("gcd(");print(aBuf);print(",");print(bBuf);println("):");
+ myGCD = gcd(a,b);
+ itoa(myGCD, buf, 10);
+ println(buf);
+}
+
+void main() {
+ GPIO_A->OUTPUT_ENABLE = 0x0000000F;
+ GPIO_A->OUTPUT = 0x00000001;
+ println("hello gcd world");
+ const int nleds = 4;
+ const int nloops = 2000000;
+
+ GCD->VALID = 0x00000000;
+ while(GCD->READY);
+
+ calcPrintGCD(1, 123913);
+ calcPrintGCD(461952, 116298);
+ calcPrintGCD(461952, 116298);
+ calcPrintGCD(461952, 116298);
+
+ while(1){
+ for(unsigned int i=0;i<nleds-1;i++){
+ GPIO_A->OUTPUT = 1<<i;
+ delay(nloops);
+ }
+ for(unsigned int i=0;i<nleds-1;i++){
+ GPIO_A->OUTPUT = (1<<(nleds-1))>>i;
+ delay(nloops);
+ }
+ }
+}
+
+void irqCallback(){
+}
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.h b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.h
new file mode 100644
index 0000000..31cb9c0
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/main.h
@@ -0,0 +1,78 @@
+
+//----------------------------
+// integer to ascii (itoa) with util functions
+//----------------------------
+
+// function to swap two numbers
+void swap(char *x, char *y) {
+ char t = *x; *x = *y; *y = t;
+}
+
+// function to reverse buffer[i..j]
+char* reverse(char *buffer, int i, int j) {
+ while (i < j)
+ swap(&buffer[i++], &buffer[j--]);
+ return buffer;
+}
+
+// Iterative function to implement itoa() function in C
+char* itoa(int value, char* buffer, int base) {
+ // invalid input
+ if (base < 2 || base > 32)
+ return buffer;
+ // consider absolute value of number
+ int n = (value < 0) ? -value : value;
+ int i = 0;
+ while (n) {
+ int r = n % base;
+ if (r >= 10)
+ buffer[i++] = 65 + (r - 10);
+ else
+ buffer[i++] = 48 + r;
+ n = n / base;
+ }
+
+ // if number is 0
+ if (i == 0)
+ buffer[i++] = '0';
+
+ // If base is 10 and value is negative, the resulting string
+ // is preceded with a minus sign (-)
+ // With any other base, value is always considered unsigned
+ if (value < 0 && base == 10)
+ buffer[i++] = '-';
+
+ buffer[i] = '\0'; // null terminate string
+
+ // reverse the string and return it
+ return reverse(buffer, 0, i - 1);
+}
+
+//----------------------------
+// print, println, dbgprint
+//----------------------------
+
+void print(const char*str){
+ while(*str){
+ uart_write(UART,*str);
+ str++;
+ }
+}
+void println(const char*str){
+ print(str);
+ uart_write(UART,'\n');
+}
+
+void dbgPrintln(const char*str){
+ #if DEBUG == 1
+ println(str);
+ #else
+ void;
+ #endif
+}
+
+void delay(uint32_t loops){
+ for(int i=0;i<loops;i++){
+ int tmp = GPIO_A->OUTPUT;
+ }
+} \ No newline at end of file
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/murax.h b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/murax.h
new file mode 100644
index 0000000..9d7b7e7
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/murax.h
@@ -0,0 +1,20 @@
+#ifndef __MURAX_H__
+#define __MURAX_H__
+
+#include "timer.h"
+#include "prescaler.h"
+#include "interrupt.h"
+#include "gpio.h"
+#include "uart.h"
+#include "gcd.h"
+
+#define GPIO_A ((Gpio_Reg*)(0xF0000000))
+#define TIMER_PRESCALER ((Prescaler_Reg*)0xF0020000)
+#define TIMER_INTERRUPT ((InterruptCtrl_Reg*)0xF0020010)
+#define TIMER_A ((Timer_Reg*)0xF0020040)
+#define TIMER_B ((Timer_Reg*)0xF0020050)
+#define UART ((Uart_Reg*)(0xF0010000))
+#define GCD ((Gcd_Reg*)(0xF0030000))
+
+
+#endif /* __MURAX_H__ */
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/prescaler.h b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/prescaler.h
new file mode 100644
index 0000000..6bd9694
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/prescaler.h
@@ -0,0 +1,16 @@
+#ifndef PRESCALERCTRL_H_
+#define PRESCALERCTRL_H_
+
+#include <stdint.h>
+
+
+typedef struct
+{
+ volatile uint32_t LIMIT;
+} Prescaler_Reg;
+
+static void prescaler_init(Prescaler_Reg* reg){
+
+}
+
+#endif /* PRESCALERCTRL_H_ */
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/timer.h b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/timer.h
new file mode 100644
index 0000000..1577535
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/timer.h
@@ -0,0 +1,20 @@
+#ifndef TIMERCTRL_H_
+#define TIMERCTRL_H_
+
+#include <stdint.h>
+
+
+typedef struct
+{
+ volatile uint32_t CLEARS_TICKS;
+ volatile uint32_t LIMIT;
+ volatile uint32_t VALUE;
+} Timer_Reg;
+
+static void timer_init(Timer_Reg *reg){
+ reg->CLEARS_TICKS = 0;
+ reg->VALUE = 0;
+}
+
+
+#endif /* TIMERCTRL_H_ */
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/uart.h b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/uart.h
new file mode 100644
index 0000000..c3a30a5
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/c/murax/gcd_world/src/uart.h
@@ -0,0 +1,42 @@
+#ifndef UART_H_
+#define UART_H_
+
+
+typedef struct
+{
+ volatile uint32_t DATA;
+ volatile uint32_t STATUS;
+ volatile uint32_t CLOCK_DIVIDER;
+ volatile uint32_t FRAME_CONFIG;
+} Uart_Reg;
+
+enum UartParity {NONE = 0,EVEN = 1,ODD = 2};
+enum UartStop {ONE = 0,TWO = 1};
+
+typedef struct {
+ uint32_t dataLength;
+ enum UartParity parity;
+ enum UartStop stop;
+ uint32_t clockDivider;
+} Uart_Config;
+
+static uint32_t uart_writeAvailability(Uart_Reg *reg){
+ return (reg->STATUS >> 16) & 0xFF;
+}
+static uint32_t uart_readOccupancy(Uart_Reg *reg){
+ return reg->STATUS >> 24;
+}
+
+static void uart_write(Uart_Reg *reg, uint32_t data){
+ while(uart_writeAvailability(reg) == 0);
+ reg->DATA = data;
+}
+
+static void uart_applyConfig(Uart_Reg *reg, Uart_Config *config){
+ reg->CLOCK_DIVIDER = config->clockDivider;
+ reg->FRAME_CONFIG = ((config->dataLength-1) << 0) | (config->parity << 8) | (config->stop << 16);
+}
+
+#endif /* UART_H_ */
+
+
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/demo/Murax.scala b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/demo/Murax.scala
new file mode 100644
index 0000000..f3d4f6c
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/demo/Murax.scala
@@ -0,0 +1,559 @@
+package vexriscv.demo
+
+import spinal.core._
+import spinal.lib._
+import spinal.lib.bus.amba3.apb._
+import spinal.lib.bus.misc.SizeMapping
+import spinal.lib.bus.simple.PipelinedMemoryBus
+import spinal.lib.com.jtag.Jtag
+import spinal.lib.com.spi.ddr.SpiXdrMaster
+import spinal.lib.com.uart._
+import spinal.lib.io.{InOutWrapper, TriStateArray}
+import spinal.lib.misc.{InterruptCtrl, Prescaler, Timer}
+import spinal.lib.soc.pinsec.{PinsecTimerCtrl, PinsecTimerCtrlExternal}
+import vexriscv.plugin._
+import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
+import spinal.lib.com.spi.ddr._
+import spinal.lib.bus.simple._
+import scala.collection.mutable.ArrayBuffer
+import vexriscv.periph.gcd._
+import vexriscv.periph.tasks.gen._
+import vexriscv.periph.tasks.map._
+import vexriscv.periph.tasks.sort._
+import vexriscv.periph.tasks.max._
+import vexriscv.periph.tasks.sum._
+import vexriscv.periph.tasks.hash._
+
+/** Created by PIC32F_USER on 28/07/2017.
+ *
+ * Murax is a very light SoC which could work without any external component.
+ * - ICE40-hx8k + icestorm => 53 Mhz, 2142 LC
+ * - 0.37 DMIPS/Mhz
+ * - 8 kB of on-chip ram
+ * - JTAG debugger (eclipse/GDB/openocd ready)
+ * - Interrupt support
+ * - APB bus for peripherals
+ * - 32 GPIO pin
+ * - one 16 bits prescaler, two 16 bits timers
+ * - one UART with tx/rx fifo
+ */
+
+case class MuraxConfig(
+ coreFrequency: HertzNumber,
+ onChipRamSize: BigInt,
+ onChipRamHexFile: String,
+ pipelineDBus: Boolean,
+ pipelineMainBus: Boolean,
+ pipelineApbBridge: Boolean,
+ gpioWidth: Int,
+ uartCtrlConfig: UartCtrlMemoryMappedConfig,
+ xipConfig: SpiXdrMasterCtrl.MemoryMappingParameters,
+ hardwareBreakpointCount: Int,
+ cpuPlugins: ArrayBuffer[Plugin[VexRiscv]]
+) {
+ require(
+ pipelineApbBridge || pipelineMainBus,
+ "At least pipelineMainBus or pipelineApbBridge should be enable to avoid wipe transactions"
+ )
+ val genXip = xipConfig != null
+
+}
+
+object MuraxConfig {
+ def default: MuraxConfig = default(false, false)
+ def default(withXip: Boolean = false, bigEndian: Boolean = false) =
+ MuraxConfig(
+ coreFrequency = 12 MHz,
+ onChipRamSize = 8 kB,
+ onChipRamHexFile = null,
+ pipelineDBus = true,
+ pipelineMainBus = false,
+ pipelineApbBridge = true,
+ gpioWidth = 32,
+ xipConfig = ifGen(withXip)(
+ SpiXdrMasterCtrl.MemoryMappingParameters(
+ SpiXdrMasterCtrl
+ .Parameters(8, 12, SpiXdrParameter(2, 2, 1))
+ .addFullDuplex(0, 1, false),
+ cmdFifoDepth = 32,
+ rspFifoDepth = 32,
+ xip = SpiXdrMasterCtrl
+ .XipBusParameters(addressWidth = 24, lengthWidth = 2)
+ )
+ ),
+ hardwareBreakpointCount = if (withXip) 3 else 0,
+ cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel
+ new IBusSimplePlugin(
+ resetVector = if (withXip) 0xf001e000L else 0x80000000L,
+ cmdForkOnSecondStage = true,
+ cmdForkPersistence = withXip, //Required by the Xip controller
+ prediction = NONE,
+ catchAccessFault = false,
+ compressedGen = false,
+ bigEndian = bigEndian
+ ),
+ new DBusSimplePlugin(
+ catchAddressMisaligned = false,
+ catchAccessFault = false,
+ earlyInjection = false,
+ bigEndian = bigEndian
+ ),
+ new CsrPlugin(
+ CsrPluginConfig.smallest(mtvecInit =
+ if (withXip) 0xe0040020L else 0x80000020L
+ )
+ ),
+ new DecoderSimplePlugin(
+ catchIllegalInstruction = false
+ ),
+ new RegFilePlugin(
+ regFileReadyKind = plugin.SYNC,
+ zeroBoot = false
+ ),
+ new IntAluPlugin,
+ new SrcPlugin(
+ separatedAddSub = false,
+ executeInsertion = false
+ ),
+ new LightShifterPlugin,
+ new HazardSimplePlugin(
+ bypassExecute = false,
+ bypassMemory = false,
+ bypassWriteBack = false,
+ bypassWriteBackBuffer = false,
+ pessimisticUseSrc = false,
+ pessimisticWriteRegFile = false,
+ pessimisticAddressMatch = false
+ ),
+ new BranchPlugin(
+ earlyBranch = false,
+ catchAddressMisaligned = false
+ ),
+ new YamlPlugin("cpu0.yaml")
+ ),
+ uartCtrlConfig = UartCtrlMemoryMappedConfig(
+ uartCtrlConfig = UartCtrlGenerics(
+ dataWidthMax = 8,
+ clockDividerWidth = 20,
+ preSamplingSize = 1,
+ samplingSize = 3,
+ postSamplingSize = 1
+ ),
+ initConfig = UartCtrlInitConfig(
+ baudrate = 115200,
+ dataLength = 7, //7 => 8 bits
+ parity = UartParityType.NONE,
+ stop = UartStopType.ONE
+ ),
+ busCanWriteClockDividerConfig = false,
+ busCanWriteFrameConfig = false,
+ txFifoDepth = 16,
+ rxFifoDepth = 16
+ )
+ )
+
+ def fast = {
+ val config = default
+
+ //Replace HazardSimplePlugin to get datapath bypass
+ config.cpuPlugins(
+ config.cpuPlugins.indexWhere(_.isInstanceOf[HazardSimplePlugin])
+ ) = new HazardSimplePlugin(
+ bypassExecute = true,
+ bypassMemory = true,
+ bypassWriteBack = true,
+ bypassWriteBackBuffer = true
+ )
+// config.cpuPlugins(config.cpuPlugins.indexWhere(_.isInstanceOf[LightShifterPlugin])) = new FullBarrelShifterPlugin()
+
+ config
+ }
+}
+
+case class Murax(config: MuraxConfig) extends Component {
+ import config._
+
+ val io = new Bundle {
+ //Clocks / reset
+ val asyncReset = in Bool ()
+ val mainClk = in Bool ()
+
+ //Main components IO
+ val jtag = slave(Jtag())
+
+ //Peripherals IO
+ val gpioA = master(TriStateArray(gpioWidth bits))
+ val uart = master(Uart())
+
+ val xip = ifGen(genXip)(master(SpiXdrMaster(xipConfig.ctrl.spi)))
+ }
+
+ val resetCtrlClockDomain = ClockDomain(
+ clock = io.mainClk,
+ config = ClockDomainConfig(
+ resetKind = BOOT
+ )
+ )
+
+ val resetCtrl = new ClockingArea(resetCtrlClockDomain) {
+ val mainClkResetUnbuffered = False
+
+ //Implement an counter to keep the reset axiResetOrder high 64 cycles
+ // Also this counter will automatically do a reset when the system boot.
+ val systemClkResetCounter = Reg(UInt(6 bits)) init (0)
+ when(systemClkResetCounter =/= U(systemClkResetCounter.range -> true)) {
+ systemClkResetCounter := systemClkResetCounter + 1
+ mainClkResetUnbuffered := True
+ }
+ when(BufferCC(io.asyncReset)) {
+ systemClkResetCounter := 0
+ }
+
+ //Create all reset used later in the design
+ val mainClkReset = RegNext(mainClkResetUnbuffered)
+ val systemReset = RegNext(mainClkResetUnbuffered)
+ }
+
+ val systemClockDomain = ClockDomain(
+ clock = io.mainClk,
+ reset = resetCtrl.systemReset,
+ frequency = FixedFrequency(coreFrequency)
+ )
+
+ val debugClockDomain = ClockDomain(
+ clock = io.mainClk,
+ reset = resetCtrl.mainClkReset,
+ frequency = FixedFrequency(coreFrequency)
+ )
+
+ val system = new ClockingArea(systemClockDomain) {
+ val pipelinedMemoryBusConfig = PipelinedMemoryBusConfig(
+ addressWidth = 32,
+ dataWidth = 32
+ )
+
+ val bigEndianDBus = config.cpuPlugins.exists(_ match {
+ case plugin: DBusSimplePlugin => plugin.bigEndian
+ case _ => false
+ })
+
+ //Arbiter of the cpu dBus/iBus to drive the mainBus
+ //Priority to dBus, !! cmd transactions can change on the fly !!
+ val mainBusArbiter =
+ new MuraxMasterArbiter(pipelinedMemoryBusConfig, bigEndianDBus)
+
+ //Instanciate the CPU
+ val cpu = new VexRiscv(
+ config = VexRiscvConfig(
+ plugins = cpuPlugins += new DebugPlugin(
+ debugClockDomain,
+ hardwareBreakpointCount
+ )
+ )
+ )
+
+ //Checkout plugins used to instanciate the CPU to connect them to the SoC
+ val timerInterrupt = False
+ val externalInterrupt = False
+ for (plugin <- cpu.plugins) plugin match {
+ case plugin: IBusSimplePlugin =>
+ mainBusArbiter.io.iBus.cmd <> plugin.iBus.cmd
+ mainBusArbiter.io.iBus.rsp <> plugin.iBus.rsp
+ case plugin: DBusSimplePlugin => {
+ if (!pipelineDBus)
+ mainBusArbiter.io.dBus <> plugin.dBus
+ else {
+ mainBusArbiter.io.dBus.cmd << plugin.dBus.cmd.halfPipe()
+ mainBusArbiter.io.dBus.rsp <> plugin.dBus.rsp
+ }
+ }
+ case plugin: CsrPlugin => {
+ plugin.externalInterrupt := externalInterrupt
+ plugin.timerInterrupt := timerInterrupt
+ }
+ case plugin: DebugPlugin =>
+ plugin.debugClockDomain {
+ resetCtrl.systemReset setWhen (RegNext(plugin.io.resetOut))
+ io.jtag <> plugin.io.bus.fromJtag()
+ }
+ case _ =>
+ }
+
+ //****** MainBus slaves ********
+ val mainBusMapping = ArrayBuffer[(PipelinedMemoryBus, SizeMapping)]()
+ val ram = new MuraxPipelinedMemoryBusRam(
+ onChipRamSize = onChipRamSize,
+ onChipRamHexFile = onChipRamHexFile,
+ pipelinedMemoryBusConfig = pipelinedMemoryBusConfig,
+ bigEndian = bigEndianDBus
+ )
+ mainBusMapping += ram.io.bus -> (0x80000000L, onChipRamSize)
+
+ val apbBridge = new PipelinedMemoryBusToApbBridge(
+ apb3Config = Apb3Config(
+ addressWidth = 20,
+ dataWidth = 32
+ ),
+ pipelineBridge = pipelineApbBridge,
+ pipelinedMemoryBusConfig = pipelinedMemoryBusConfig
+ )
+ mainBusMapping += apbBridge.io.pipelinedMemoryBus -> (0xf0000000L, 1 MB)
+
+ //******** APB peripherals *********
+ val apbMapping = ArrayBuffer[(Apb3, SizeMapping)]()
+ val gpioACtrl = Apb3Gpio(gpioWidth = gpioWidth, withReadSync = true)
+ io.gpioA <> gpioACtrl.io.gpio
+ apbMapping += gpioACtrl.io.apb -> (0x00000, 4 kB)
+
+ val uartCtrl = Apb3UartCtrl(uartCtrlConfig)
+ uartCtrl.io.uart <> io.uart
+ externalInterrupt setWhen (uartCtrl.io.interrupt)
+ apbMapping += uartCtrl.io.apb -> (0x10000, 4 kB)
+
+ val timer = new MuraxApb3Timer()
+ timerInterrupt setWhen (timer.io.interrupt)
+ apbMapping += timer.io.apb -> (0x20000, 4 kB)
+
+ val gcd = new Apb3GCDCtrl(
+ apb3Config = Apb3Config(
+ addressWidth = 20,
+ dataWidth = 32
+ )
+ )
+ apbMapping += gcd.io.apb -> (0x30000, 1 kB)
+
+ val xip = ifGen(genXip)(new Area {
+ val ctrl = Apb3SpiXdrMasterCtrl(xipConfig)
+ ctrl.io.spi <> io.xip
+ externalInterrupt setWhen (ctrl.io.interrupt)
+ apbMapping += ctrl.io.apb -> (0x1f000, 4 kB)
+
+ val accessBus = new PipelinedMemoryBus(PipelinedMemoryBusConfig(24, 32))
+ mainBusMapping += accessBus -> (0xe0000000L, 16 MB)
+
+ ctrl.io.xip.fromPipelinedMemoryBus() << accessBus
+ val bootloader = Apb3Rom("src/main/c/murax/xipBootloader/crt.bin")
+ apbMapping += bootloader.io.apb -> (0x1e000, 4 kB)
+ })
+
+ //******** Memory mappings *********
+ val apbDecoder = Apb3Decoder(
+ master = apbBridge.io.apb,
+ slaves = apbMapping
+ )
+
+ val mainBusDecoder = new Area {
+ val logic = new MuraxPipelinedMemoryBusDecoder(
+ master = mainBusArbiter.io.masterBus,
+ specification = mainBusMapping,
+ pipelineMaster = pipelineMainBus
+ )
+ }
+ }
+}
+
+object Murax {
+ def main(args: Array[String]) {
+ SpinalVerilog(Murax(MuraxConfig.default))
+ }
+}
+
+object Murax_iCE40_hx8k_breakout_board_xip {
+
+ case class SB_GB() extends BlackBox {
+ val USER_SIGNAL_TO_GLOBAL_BUFFER = in Bool ()
+ val GLOBAL_BUFFER_OUTPUT = out Bool ()
+ }
+
+ case class SB_IO_SCLK() extends BlackBox {
+ addGeneric("PIN_TYPE", B"010000")
+ val PACKAGE_PIN = out Bool ()
+ val OUTPUT_CLK = in Bool ()
+ val CLOCK_ENABLE = in Bool ()
+ val D_OUT_0 = in Bool ()
+ val D_OUT_1 = in Bool ()
+ setDefinitionName("SB_IO")
+ }
+
+ case class SB_IO_DATA() extends BlackBox {
+ addGeneric("PIN_TYPE", B"110000")
+ val PACKAGE_PIN = inout(Analog(Bool))
+ val CLOCK_ENABLE = in Bool ()
+ val INPUT_CLK = in Bool ()
+ val OUTPUT_CLK = in Bool ()
+ val OUTPUT_ENABLE = in Bool ()
+ val D_OUT_0 = in Bool ()
+ val D_OUT_1 = in Bool ()
+ val D_IN_0 = out Bool ()
+ val D_IN_1 = out Bool ()
+ setDefinitionName("SB_IO")
+ }
+
+ case class Murax_iCE40_hx8k_breakout_board_xip() extends Component {
+ val io = new Bundle {
+ val mainClk = in Bool ()
+ val jtag_tck = in Bool ()
+ val jtag_tdi = in Bool ()
+ val jtag_tdo = out Bool ()
+ val jtag_tms = in Bool ()
+ val uart_txd = out Bool ()
+ val uart_rxd = in Bool ()
+
+ val mosi = inout(Analog(Bool))
+ val miso = inout(Analog(Bool))
+ val sclk = out Bool ()
+ val spis = out Bool ()
+
+ val led = out Bits (8 bits)
+ }
+ val murax = Murax(
+ MuraxConfig.default(withXip = true).copy(onChipRamSize = 8 kB)
+ )
+ murax.io.asyncReset := False
+
+ val mainClkBuffer = SB_GB()
+ mainClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.mainClk
+ mainClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.mainClk
+
+ val jtagClkBuffer = SB_GB()
+ jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.jtag_tck
+ jtagClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.jtag.tck
+
+ io.led <> murax.io.gpioA.write(7 downto 0)
+
+ murax.io.jtag.tdi <> io.jtag_tdi
+ murax.io.jtag.tdo <> io.jtag_tdo
+ murax.io.jtag.tms <> io.jtag_tms
+ murax.io.gpioA.read <> 0
+ murax.io.uart.txd <> io.uart_txd
+ murax.io.uart.rxd <> io.uart_rxd
+
+ val xip = new ClockingArea(murax.systemClockDomain) {
+ RegNext(murax.io.xip.ss.asBool) <> io.spis
+
+ val sclkIo = SB_IO_SCLK()
+ sclkIo.PACKAGE_PIN <> io.sclk
+ sclkIo.CLOCK_ENABLE := True
+
+ sclkIo.OUTPUT_CLK := ClockDomain.current.readClockWire
+ sclkIo.D_OUT_0 <> murax.io.xip.sclk.write(0)
+ sclkIo.D_OUT_1 <> RegNext(murax.io.xip.sclk.write(1))
+
+ val datas =
+ for ((data, pin) <- (murax.io.xip.data, List(io.mosi, io.miso)).zipped)
+ yield new Area {
+ val dataIo = SB_IO_DATA()
+ dataIo.PACKAGE_PIN := pin
+ dataIo.CLOCK_ENABLE := True
+
+ dataIo.OUTPUT_CLK := ClockDomain.current.readClockWire
+ dataIo.OUTPUT_ENABLE <> data.writeEnable
+ dataIo.D_OUT_0 <> data.write(0)
+ dataIo.D_OUT_1 <> RegNext(data.write(1))
+
+ dataIo.INPUT_CLK := ClockDomain.current.readClockWire
+ data.read(0) := dataIo.D_IN_0
+ data.read(1) := RegNext(dataIo.D_IN_1)
+ }
+ }
+
+ }
+
+ def main(args: Array[String]) {
+ SpinalVerilog(Murax_iCE40_hx8k_breakout_board_xip())
+ }
+}
+
+object MuraxDhrystoneReady {
+ def main(args: Array[String]) {
+ SpinalVerilog(Murax(MuraxConfig.fast.copy(onChipRamSize = 256 kB)))
+ }
+}
+
+object MuraxDhrystoneReadyMulDivStatic {
+ def main(args: Array[String]) {
+ SpinalVerilog({
+ val config = MuraxConfig.fast.copy(onChipRamSize = 256 kB)
+ config.cpuPlugins += new MulPlugin
+ config.cpuPlugins += new DivPlugin
+ config.cpuPlugins.remove(
+ config.cpuPlugins.indexWhere(_.isInstanceOf[BranchPlugin])
+ )
+ config.cpuPlugins += new BranchPlugin(
+ earlyBranch = false,
+ catchAddressMisaligned = false
+ )
+ config.cpuPlugins += new IBusSimplePlugin(
+ resetVector = 0x80000000L,
+ cmdForkOnSecondStage = true,
+ cmdForkPersistence = false,
+ prediction = STATIC,
+ catchAccessFault = false,
+ compressedGen = false
+ )
+ config.cpuPlugins.remove(
+ config.cpuPlugins.indexWhere(_.isInstanceOf[LightShifterPlugin])
+ )
+ config.cpuPlugins += new FullBarrelShifterPlugin
+ Murax(config)
+ })
+ }
+}
+
+//Will blink led and echo UART RX to UART TX (in the verilator sim, type some text and press enter to send UART frame to the Murax RX pin)
+object MuraxWithRamInit {
+ def main(args: Array[String]) {
+ SpinalVerilog(
+ Murax(
+ MuraxConfig.default.copy(
+ onChipRamSize = 4 kB,
+ onChipRamHexFile = "src/main/c/murax/gcd_world/build/gcd_world.hex"
+ )
+ )
+ )
+ .printPruned()
+ }
+}
+
+object MuraxWithRamInitSynth {
+ def main(args: Array[String]) {
+ val config = SpinalConfig(
+ targetDirectory = "synth",
+ defaultClockDomainFrequency = FixedFrequency(12 MHz)
+ )
+ config
+ .generateVerilog(
+ Murax(
+ MuraxConfig.default.copy(
+ onChipRamSize = 4 kB,
+ onChipRamHexFile = "src/main/c/murax/gcd_world/build/gcd_world.hex"
+ )
+ )
+ )
+ .printPruned()
+ }
+}
+
+object Murax_arty {
+ def main(args: Array[String]) {
+ val hex = "src/main/c/murax/hello_world/build/hello_world.hex"
+ SpinalVerilog(
+ Murax(
+ MuraxConfig
+ .default(false)
+ .copy(
+ coreFrequency = 100 MHz,
+ onChipRamSize = 32 kB,
+ onChipRamHexFile = hex
+ )
+ )
+ )
+ }
+}
+
+object MuraxAsicBlackBox extends App {
+ println("Warning this soc do not has any rom to boot on.")
+ val config = SpinalConfig()
+ config.addStandardMemBlackboxing(blackboxAll)
+ config.generateVerilog(Murax(MuraxConfig.default()))
+}
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/Apb3GCDCtrl.scala b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/Apb3GCDCtrl.scala
new file mode 100644
index 0000000..2ec7401
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/Apb3GCDCtrl.scala
@@ -0,0 +1,39 @@
+package vexriscv.periph.gcd
+
+import spinal.core._
+import spinal.lib._
+import spinal.lib.bus.amba3.apb.{Apb3, Apb3Config, Apb3SlaveFactory}
+import spinal.lib.eda.altera.QSysify
+import spinal.lib.slave
+
+object Apb3GCDCtrl {
+ def getApb3Config = Apb3Config(
+ addressWidth = 5,
+ dataWidth = 32,
+ selWidth = 1,
+ useSlaveError = false
+ )
+}
+
+class Apb3GCDCtrl(apb3Config : Apb3Config) extends Component {
+ val io = new Bundle {
+ val apb = slave(Apb3(Apb3GCDCtrl.getApb3Config))
+ // maybe later
+ // val interrupt = out Bool
+ }
+ val gcdCtrl = new GCDTop()
+ val apbCtrl = Apb3SlaveFactory(io.apb)
+ apbCtrl.driveAndRead(gcdCtrl.io.a, address=0)
+ apbCtrl.driveAndRead(gcdCtrl.io.b, address=4)
+ // when result of calculation ready, synchronize it into memory mapped register
+ val resSyncBuf = RegNextWhen(gcdCtrl.io.res, gcdCtrl.io.ready)
+ apbCtrl.read(resSyncBuf, address=8)
+ // if result is read, it will be consumed, set ready to 0
+ apbCtrl.onRead(8)(resSyncBuf := 0)
+ apbCtrl.onRead(8)(rdySyncBuf := False)
+ // synchronize ready signal into memory mapped register
+ val rdySyncBuf = RegNextWhen(gcdCtrl.io.ready, gcdCtrl.io.ready)
+ apbCtrl.read(rdySyncBuf, address=12)
+ // set valid based on memory mapped register but clear/consume it after 1 cycle <s
+ gcdCtrl.io.valid := apbCtrl.setOnSet(RegNext(False) init(False), address=16, 0)
+}
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDCtrl.scala b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDCtrl.scala
new file mode 100644
index 0000000..e4b814f
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDCtrl.scala
@@ -0,0 +1,68 @@
+package vexriscv.periph.gcd
+
+import spinal.core._
+import spinal.lib._
+import spinal.lib.master
+import spinal.lib.fsm._
+
+//Hardware definition
+class GCDCtrl() extends Component {
+ val io = new Bundle {
+ val valid = in Bool()
+ val ready = out Bool()
+ val dataCtrl = master(GCDDataControl())
+ }
+ val fsm = new StateMachine{
+ io.dataCtrl.loadA := False
+ io.dataCtrl.loadB := False
+ io.dataCtrl.init := False
+ io.dataCtrl.selL := False
+ io.dataCtrl.selR := False
+ io.ready := False
+ val idle : State = new State with EntryPoint{
+ whenIsActive{
+ when(io.valid){
+ io.dataCtrl.init := True
+ goto(calculate)
+ }
+ }
+ }
+ val calculate : State = new State{
+ whenIsActive{
+ when(io.dataCtrl.cmpAgtB){
+ goto(calcA)
+ }.elsewhen(io.dataCtrl.cmpAltB){
+ goto(calcB)
+ }.elsewhen(!io.dataCtrl.cmpAgtB & !io.dataCtrl.cmpAgtB){
+ goto(calcDone)
+ }
+ }
+ }
+ val calcA : State = new State{
+ whenIsActive{
+ io.dataCtrl.selR := True
+ io.dataCtrl.loadA := True
+ goto(calculate)
+ }
+ }
+ val calcB : State = new State{
+ whenIsActive{
+ io.dataCtrl.selL := True
+ io.dataCtrl.loadB := True
+ goto(calculate)
+ }
+ }
+ val calcDone : State = new State{
+ whenIsActive{
+ io.ready := True
+ goto(idle)
+ }
+ }
+ }
+}
+
+object GCDCtrlVerilog {
+ def main(args: Array[String]) {
+ SpinalVerilog(new GCDCtrl)
+ }
+} \ No newline at end of file
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDData.scala b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDData.scala
new file mode 100644
index 0000000..88e58ad
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDData.scala
@@ -0,0 +1,54 @@
+package vexriscv.periph.gcd
+
+import spinal.core._
+import spinal.lib._
+import spinal.lib.slave
+
+//Hardware definition
+class GCDData() extends Component {
+ val io = new Bundle {
+ val a = in(UInt(32 bits))
+ val b = in(UInt(32 bits))
+ val res = out(UInt(32 bits))
+ val dataCtrl = slave(GCDDataControl())
+ }
+ /*
+ *
+ * // Pseudocode of the Euclids algorithm for calculating the GCD
+ * inputs: [a, b, start]
+ * outputs: [done, a]
+ * done := False
+ * while(!done):
+ * if(a > b):
+ * a := a - b
+ * else if(b > a):
+ * b := b - a
+ * else:
+ * done := True
+ */
+ //registers
+ val regA = Reg(UInt(32 bits)) init(0)
+ val regB = Reg(UInt(32 bits)) init(0)
+ // compare
+ val xGTy = regA > regB
+ val xLTy = regA < regB
+ // mux
+ val chX = io.dataCtrl.selL ? regB | regA
+ val chY = io.dataCtrl.selR ? regB | regA
+ // subtract
+ val subXY = chX - chY
+ // load logic
+ when(io.dataCtrl.init){
+ regA := io.a
+ regB := io.b
+ }
+ when(io.dataCtrl.loadA){
+ regA := subXY
+ }
+ when(io.dataCtrl.loadB){
+ regB := subXY
+ }
+ io.dataCtrl.cmpAgtB := xGTy
+ io.dataCtrl.cmpAltB := xLTy
+ io.res := regA
+} \ No newline at end of file
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDTop.scala b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDTop.scala
new file mode 100644
index 0000000..654e9b8
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDTop.scala
@@ -0,0 +1,46 @@
+package vexriscv.periph.gcd
+
+import spinal.core._
+import spinal.lib._
+import spinal.lib.IMasterSlave
+
+case class GCDDataControl() extends Bundle with IMasterSlave{
+ val cmpAgtB = Bool
+ val cmpAltB = Bool
+ val loadA = Bool
+ val loadB = Bool
+ val init = Bool
+ val selL = Bool
+ val selR = Bool
+ // define <> semantic
+ override def asMaster(): Unit = {
+ // as controller: output, input
+ out(loadA, loadB, selL, selR, init)
+ in(cmpAgtB, cmpAltB)
+ }
+}
+
+//Hardware definition
+class GCDTop() extends Component {
+ val io = new Bundle {
+ val valid = in Bool()
+ val ready = out Bool()
+ val a = in(UInt(32 bits))
+ val b = in(UInt(32 bits))
+ val res = out(UInt(32 bits))
+ }
+ val gcdCtr = new GCDCtrl()
+ gcdCtr.io.valid := io.valid
+ io.ready := gcdCtr.io.ready
+ val gcdDat = new GCDData()
+ gcdDat.io.a := io.a
+ gcdDat.io.b := io.b
+ io.res := gcdDat.io.res
+ gcdCtr.io.dataCtrl <> gcdDat.io.dataCtrl
+}
+
+object GCDTopVerilog {
+ def main(args: Array[String]) {
+ SpinalVerilog(new GCDTop)
+ }
+} \ No newline at end of file
diff --git a/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDTopSim.scala b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDTopSim.scala
new file mode 100644
index 0000000..53ea8dc
--- /dev/null
+++ b/VexRiscv/doc/gcdPeripheral/src/main/scala/vexriscv/periph/gcd/GCDTopSim.scala
@@ -0,0 +1,52 @@
+package vexriscv.periph.gcd
+
+import spinal.core._
+import spinal.sim._
+import spinal.core.sim._
+
+//import scala.util.Random
+import java.util.concurrent.ThreadLocalRandom
+object GCDTopSim {
+ def main(args: Array[String]) {
+
+ SimConfig.withWave.doSim(new GCDTop()){dut =>
+ // SimConfig.doSim(new GCDTop()){dut =>
+ def gcd(a: Long,b: Long): Long = {
+ if(b==0) a else gcd(b, a%b)
+ }
+ def RndNextUInt32(): Long = {
+ ThreadLocalRandom.current().nextLong(Math.pow(2, 32).toLong - 1)
+ }
+ var a = 0L
+ var b = 0L
+ var model = 0L
+ dut.io.a #= 0
+ dut.io.b #= 0
+ dut.io.valid #= false
+
+ dut.clockDomain.forkStimulus(period = 10)
+ dut.clockDomain.waitRisingEdge()
+
+ for(idx <- 0 to 500){
+ // generate 2 random ints
+ a = RndNextUInt32()
+ b = RndNextUInt32()
+ // calculate the model value (software)
+ model = gcd(a,b)
+ // apply stimulus with random ints
+ dut.io.a #= a
+ dut.io.b #= b
+ dut.io.valid #= true
+ dut.clockDomain.waitRisingEdge()
+ dut.io.valid #= false
+ // wait until calculation of hardware is done
+ waitUntil(dut.io.ready.toBoolean)
+ assert(
+ assertion = (dut.io.res.toBigInt == model),
+ message = "test " + idx + " failed. Expected " + model + ", retrieved: " + dut.io.res.toBigInt
+ )
+ waitUntil(!dut.io.ready.toBoolean)
+ }
+ }
+ }
+}