aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2017-06-18 14:38:03 +0200
committerDimitri Sokolyuk <demon@dim13.org>2017-06-18 14:38:03 +0200
commitcf01b391440fc9de43597b907acfc22dba1aa15e (patch)
tree5cef95c1fd6556af1f9b67360fdc8f02eaf8e2cd
parentb468c5579f42134da43d1dccf828300f5c8fb4c3 (diff)
Add j1
m---------j10
-rw-r--r--j1/.gitignore2
-rw-r--r--j1/Makefile14
-rw-r--r--j1/README.md4
-rw-r--r--j1/build/.empty0
-rw-r--r--j1/build/.gitignore2
-rw-r--r--j1/go5
-rw-r--r--j1/sim_main.cpp76
-rw-r--r--j1/toolchain/basewords.fs92
-rw-r--r--j1/toolchain/cross.fs321
-rw-r--r--j1/toolchain/demo1.fs7
-rw-r--r--j1/toolchain/dump.py36
-rw-r--r--j1/toolchain/go3
-rw-r--r--j1/toolchain/nuc.fs604
-rw-r--r--j1/toolchain/strings.fs25
-rw-r--r--j1/verilog/common.h3
-rw-r--r--j1/verilog/j1.v123
-rw-r--r--j1/verilog/stack.v22
-rw-r--r--j1/verilog/testbench.v30
-rw-r--r--j1/verilog/top.v9
-rw-r--r--j1/verilog/uart.v180
-rw-r--r--j1/verilog/xilinx-top.v215
-rw-r--r--j1/xilinx/.gitignore44
-rw-r--r--j1/xilinx/Makefile11
-rw-r--r--j1/xilinx/go22
-rw-r--r--j1/xilinx/j1-papilioduo.bmm24
-rw-r--r--j1/xilinx/j1-papilioduo.ucf183
-rw-r--r--j1/xilinx/shell.py78
-rw-r--r--j1/xilinx/xilinx.mk176
-rw-r--r--j1/xilinx/xilinx.opt42
30 files changed, 2353 insertions, 0 deletions
diff --git a/j1 b/j1
deleted file mode 160000
-Subproject 911439641c002a8f7a6e306ce1b1d3fd4b389fd
diff --git a/j1/.gitignore b/j1/.gitignore
new file mode 100644
index 0000000..f169042
--- /dev/null
+++ b/j1/.gitignore
@@ -0,0 +1,2 @@
+a.out
+test.vcd
diff --git a/j1/Makefile b/j1/Makefile
new file mode 100644
index 0000000..34f0dae
--- /dev/null
+++ b/j1/Makefile
@@ -0,0 +1,14 @@
+
+$(SUBDIRS):
+ $(MAKE) -C $@
+
+all: obj_dir/Vj1 $(SUBDIRS)
+
+VERILOGS=verilog/j1.v verilog/stack.v
+
+obj_dir/Vj1: $(VERILOGS) sim_main.cpp Makefile
+ verilator -Wall --cc --trace -Iverilog/ $(VERILOGS) --top-module j1 --exe sim_main.cpp
+ # verilator --cc --trace $(VERILOGS) --top-module j1 --exe sim_main.cpp
+ $(MAKE) -C obj_dir OPT_FAST="-O2" -f Vj1.mk Vj1
+
+.PHONY: all
diff --git a/j1/README.md b/j1/README.md
new file mode 100644
index 0000000..9a419f5
--- /dev/null
+++ b/j1/README.md
@@ -0,0 +1,4 @@
+j1
+==
+
+The J1 CPU
diff --git a/j1/build/.empty b/j1/build/.empty
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/j1/build/.empty
diff --git a/j1/build/.gitignore b/j1/build/.gitignore
new file mode 100644
index 0000000..ebc3c15
--- /dev/null
+++ b/j1/build/.gitignore
@@ -0,0 +1,2 @@
+firmware
+quartus
diff --git a/j1/go b/j1/go
new file mode 100644
index 0000000..c0740cb
--- /dev/null
+++ b/j1/go
@@ -0,0 +1,5 @@
+(cd toolchain && sh go) || exit
+iverilog -I verilog/ -g2 -s testbench verilog/testbench.v verilog/top.v verilog/j1.v verilog/stack.v || exit
+./a.out
+
+make && obj_dir/Vj1 build/firmware/demo0.hex
diff --git a/j1/sim_main.cpp b/j1/sim_main.cpp
new file mode 100644
index 0000000..ee075ac
--- /dev/null
+++ b/j1/sim_main.cpp
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include "Vj1.h"
+#include "verilated_vcd_c.h"
+
+int main(int argc, char **argv)
+{
+ Verilated::commandArgs(argc, argv);
+ Vj1* top = new Vj1;
+ int i;
+
+ // Verilated::traceEverOn(true);
+ // VerilatedVcdC* tfp = new VerilatedVcdC;
+ // top->trace (tfp, 99);
+ // tfp->open ("simx.vcd");
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: sim <hex-file>\n");
+ exit(1);
+ }
+
+ union {
+ uint32_t ram32[4096];
+ uint16_t ram16[8192];
+ };
+
+ FILE *hex = fopen(argv[1], "r");
+ for (i = 0; i < 4096; i++) {
+ unsigned int v;
+ if (fscanf(hex, "%x\n", &v) != 1) {
+ fprintf(stderr, "invalid hex value at line %d\n", i + 1);
+ exit(1);
+ }
+ ram32[i] = v;
+ }
+
+ FILE *log = fopen("log", "w");
+ int t = 0;
+
+ top->resetq = 0;
+ top->eval();
+ top->resetq = 1;
+ top->eval();
+
+ for (i = 0; i < 100000000; i++) {
+ uint16_t a = top->mem_addr;
+ uint16_t b = top->code_addr;
+ if (top->mem_wr)
+ ram32[(a & 16383) / 4] = top->dout;
+ top->clk = 1;
+ top->eval();
+ t += 20;
+
+ top->mem_din = ram32[(a & 16383) / 4];
+ top->insn = ram16[b];
+ top->clk = 0;
+ top->eval();
+ t += 20;
+ if (top->io_wr) {
+ putchar(top->dout);
+ putc(top->dout, log);
+ if (top->dout == '#')
+ break;
+ }
+#if 0
+ if (top->io_inp && (top->io_n == 2)) {
+ top->io_din = getchar();
+ }
+#endif
+ }
+ printf("\nSimulation ended after %d cycles\n", i);
+ delete top;
+ // tfp->close();
+ fclose(log);
+
+ exit(0);
+}
diff --git a/j1/toolchain/basewords.fs b/j1/toolchain/basewords.fs
new file mode 100644
index 0000000..6534d2b
--- /dev/null
+++ b/j1/toolchain/basewords.fs
@@ -0,0 +1,92 @@
+( J1 base words implemented in assembler JCB 17:27 12/31/11)
+
+: T h# 0000 ;
+: N h# 0100 ;
+: T+N h# 0200 ;
+: T&N h# 0300 ;
+: T|N h# 0400 ;
+: T^N h# 0500 ;
+: ~T h# 0600 ;
+: N==T h# 0700 ;
+: N<T h# 0800 ;
+: N>>T h# 0900 ;
+: N<<T h# 0a00 ;
+: rT h# 0b00 ;
+: [T] h# 0c00 ;
+: io[T] h# 0d00 ;
+: status h# 0e00 ;
+: Nu<T h# 0f00 ;
+
+: T->N h# 0010 or ;
+: T->R h# 0020 or ;
+: N->[T] h# 0030 or ;
+: N->io[T] h# 0040 or ;
+: RET h# 0080 or ;
+
+: d-1 h# 0003 or ;
+: d+1 h# 0001 or ;
+: r-1 h# 000c or ;
+: r-2 h# 0008 or ;
+: r+1 h# 0004 or ;
+
+: imm h# 8000 or tw, ;
+: alu h# 6000 or tw, ;
+: ubranch h# 0000 or tw, ;
+: 0branch h# 2000 or tw, ;
+: scall h# 4000 or tw, ;
+
+
+:: noop T alu ;
+:: + T+N d-1 alu ;
+:: xor T^N d-1 alu ;
+:: and T&N d-1 alu ;
+:: or T|N d-1 alu ;
+:: invert ~T alu ;
+:: = N==T d-1 alu ;
+:: < N<T d-1 alu ;
+:: u< Nu<T d-1 alu ;
+:: swap N T->N alu ;
+:: dup T T->N d+1 alu ;
+:: drop N d-1 alu ;
+:: over N T->N d+1 alu ;
+:: nip T d-1 alu ;
+:: >r N T->R r+1 d-1 alu ;
+:: r> rT T->N r-1 d+1 alu ;
+:: r@ rT T->N d+1 alu ;
+:: @ [T] alu ;
+:: io@ io[T] alu ;
+:: ! T N->[T] d-1 alu
+ N d-1 alu ;
+:: io! T N->io[T] d-1 alu
+ N d-1 alu ;
+:: rshift N>>T d-1 alu ;
+:: lshift N<<T d-1 alu ;
+:: depths status T->N d+1 alu ;
+:: exit T RET r-1 alu ;
+
+\ Elided words
+\ These words are supported by the hardware but are not
+\ part of ANS Forth. They are named after the word-pair
+\ that matches their effect
+\ Using these elided words instead of
+\ the pair saves one cycle and one instruction.
+
+:: 2dupand T&N T->N d+1 alu ;
+:: 2dup< N<T T->N d+1 alu ;
+:: 2dup= N==T T->N d+1 alu ;
+:: 2dupor T|N T->N d+1 alu ;
+:: 2duprshift N>>T T->N d+1 alu ;
+:: 2dup+ T+N T->N d+1 alu ;
+:: 2dupu< Nu<T T->N d+1 alu ;
+:: 2dupxor T^N T->N d+1 alu ;
+:: dup>r T T->R r+1 alu ;
+:: dup@ [T] T->N d+1 alu ;
+:: overand T&N alu ;
+:: over> N<T alu ;
+:: over= N==T alu ;
+:: overor T|N alu ;
+:: over+ T+N alu ;
+:: overu> Nu<T alu ;
+:: overxor T^N alu ;
+:: rdrop T r-1 alu ;
+:: tuck! T N->[T] d-1 alu ;
diff --git a/j1/toolchain/cross.fs b/j1/toolchain/cross.fs
new file mode 100644
index 0000000..56c0025
--- /dev/null
+++ b/j1/toolchain/cross.fs
@@ -0,0 +1,321 @@
+( J1 Cross Compiler JCB 16:55 05/02/12)
+
+\ Usage gforth cross.fs <machine.fs> <program.fs>
+\
+\ Where machine.fs defines the target machine
+\ and program.fs is the target program
+\
+
+variable lst \ .lst output file handle
+
+: h#
+ base @ >r 16 base !
+ 0. bl parse >number throw 2drop postpone literal
+ r> base ! ; immediate
+
+: tcell 2 ;
+: tcells tcell * ;
+: tcell+ tcell + ;
+
+131072 allocate throw constant tflash \ bytes, target flash
+131072 allocate throw constant _tbranches \ branch targets, cells
+tflash 31072 0 fill
+_tbranches 131072 0 fill
+: tbranches cells _tbranches + ;
+
+variable tdp 0 tdp !
+: there tdp @ ;
+: islegal ;
+: tc! islegal tflash + c! ;
+: tc@ islegal tflash + c@ ;
+: tw! islegal tflash + w! ;
+: t! islegal tflash + l! ;
+: t@ islegal tflash + uw@ ;
+: twalign tdp @ 1+ -2 and tdp ! ;
+: talign tdp @ 3 + -4 and tdp ! ;
+: tc, there tc! 1 tdp +! ;
+: t, there t! 4 tdp +! ;
+: tw, there tw! tcell tdp +! ;
+: org tdp ! ;
+
+wordlist constant target-wordlist
+: add-order ( wid -- ) >r get-order r> swap 1+ set-order ;
+: :: get-current >r target-wordlist set-current : r> set-current ;
+
+next-arg included \ include the machine.fs
+
+( Language basics for target JCB 19:08 05/02/12)
+
+warnings off
+:: ( postpone ( ;
+:: \ postpone \ ;
+
+:: org org ;
+:: include include ;
+:: included included ;
+:: marker marker ;
+:: [if] postpone [if] ;
+:: [else] postpone [else] ;
+:: [then] postpone [then] ;
+
+: literal
+ \ dup $f rshift over $e rshift xor 1 and throw
+ dup h# 8000 and if
+ h# ffff xor recurse
+ ~T alu
+ else
+ h# 8000 or tw,
+ then
+;
+
+: literal
+ dup $80000000 and if
+ invert recurse
+ ~T alu
+ else
+ dup $ffff8000 and if
+ dup $F rshift recurse
+ $f recurse
+ N<<T d-1 alu
+ $7fff and recurse
+ T|N d-1 alu
+ else
+ $8000 or tw,
+ then
+ then
+;
+
+( Defining words for target JCB 19:04 05/02/12)
+
+: codeptr tdp @ 2/ ; \ target data pointer as a jump address
+
+: wordstr ( "name" -- c-addr u )
+ >in @ >r bl word count r> >in !
+;
+
+variable link 0 link !
+
+:: header
+ twalign there
+ \ cr ." link is " link @ .
+ link @ tw,
+ link !
+ bl parse
+ dup tc,
+ bounds do
+ i c@ tc,
+ loop
+ twalign
+;
+
+:: :
+ hex
+ codeptr s>d
+ <# bl hold # # # # #>
+ lst @ write-file throw
+ wordstr lst @ write-line throw
+
+ create codeptr ,
+ does> @ scall
+;
+
+:: :noname
+;
+
+:: ,
+ talign
+ t,
+;
+
+:: allot
+ 0 ?do
+ 0 tc,
+ loop
+;
+
+: shortcut ( orig -- f ) \ insn @orig precedes ;. Shortcut it.
+ \ call becomes jump
+ dup t@ h# e000 and h# 4000 = if
+ dup t@ h# 1fff and over tw!
+ true
+ else
+ dup t@ h# e00c and h# 6000 = if
+ dup t@ h# 0080 or r-1 over tw!
+ true
+ else
+ false
+ then
+ then
+ nip
+;
+
+:: ;
+ there 2 - shortcut \ true if shortcut applied
+ there 0 do
+ i tbranches @ there = if
+ i tbranches @ shortcut and
+ then
+ loop
+ 0= if \ not all shortcuts worked
+ s" exit" evaluate
+ then
+;
+:: ;fallthru ;
+
+:: jmp
+ ' >body @ ubranch
+;
+
+:: constant
+ create ,
+ does> @ literal
+;
+
+:: create
+ talign
+ create there ,
+ does> @ literal
+;
+
+( Switching between target and meta JCB 19:08 05/02/12)
+
+: target only target-wordlist add-order definitions ;
+: ] target ;
+:: meta forth definitions ;
+:: [ forth definitions ;
+
+: t' bl parse target-wordlist search-wordlist 0= throw >body @ ;
+
+( eforth's way of handling constants JCB 13:12 09/03/10)
+
+: sign>number ( c-addr1 u1 -- ud2 c-addr2 u2 )
+ 0. 2swap
+ over c@ [char] - = if
+ 1 /string
+ >number
+ 2swap dnegate 2swap
+ else
+ >number
+ then
+;
+
+: base>number ( caddr u base -- )
+ base @ >r base !
+ sign>number
+ r> base !
+ dup 0= if
+ 2drop drop literal
+ else
+ 1 = swap c@ [char] . = and if
+ drop dup literal 32 rshift literal
+ else
+ -1 abort" bad number"
+ then
+ then ;
+warnings on
+
+:: d# bl parse 10 base>number ;
+:: h# bl parse 16 base>number ;
+:: ['] ' >body @ 2* literal ;
+:: [char] char literal ;
+
+:: asm-0branch
+ ' >body @
+ 0branch
+;
+
+( Conditionals JCB 13:12 09/03/10)
+
+: resolve ( orig -- )
+ there over tbranches ! \ forward reference from orig to this loc
+ dup t@ there 2/ or swap tw!
+;
+
+:: if
+ there
+ 0 0branch
+;
+
+:: then
+ resolve
+;
+
+:: else
+ there
+ 0 ubranch
+ swap resolve
+;
+
+:: begin there ;
+
+:: again ( dest -- )
+ 2/ ubranch
+;
+:: until
+ 2/ 0branch
+;
+:: while
+ there
+ 0 0branch
+;
+:: repeat
+ swap 2/ ubranch
+ resolve
+;
+
+4 org
+: .trim ( a-addr u ) \ shorten string until it ends with '.'
+ begin
+ 2dup + 1- c@ [char] . <>
+ while
+ 1-
+ repeat
+;
+include strings.fs
+next-arg 2dup .trim >str constant prefix.
+: .suffix ( c-addr u -- c-addr u ) \ e.g. "bar" -> "foo.bar"
+ >str prefix. +str str@
+;
+: create-output-file w/o create-file throw ;
+: out-suffix ( s -- h ) \ Create an output file h with suffix s
+ >str
+ prefix. +str
+ s" ../build/firmware/" >str +str str@
+ create-output-file
+;
+:noname
+ s" lst" out-suffix lst !
+; execute
+
+
+target included \ include the program.fs
+
+[ tdp @ 0 org ] bootloader main [ org ]
+meta
+
+decimal
+0 value file
+: dumpall.16
+ s" hex" out-suffix to file
+
+ hex
+ 1024 0 do
+ tflash i 2* + w@
+ s>d <# # # # # #> file write-line throw
+ loop
+ file close-file
+;
+: dumpall.32
+ s" hex" out-suffix to file
+
+ hex
+ 4096 0 do
+ tflash i 4 * + @
+ s>d <# # # # # # # # # #> file write-line throw
+ loop
+ file close-file
+;
+
+dumpall.32
+
+bye
diff --git a/j1/toolchain/demo1.fs b/j1/toolchain/demo1.fs
new file mode 100644
index 0000000..7c49af4
--- /dev/null
+++ b/j1/toolchain/demo1.fs
@@ -0,0 +1,7 @@
+: main
+ begin
+ h# 0 io@
+ d# 1 +
+ h# 0 io!
+ again
+;
diff --git a/j1/toolchain/dump.py b/j1/toolchain/dump.py
new file mode 100644
index 0000000..283916b
--- /dev/null
+++ b/j1/toolchain/dump.py
@@ -0,0 +1,36 @@
+import sys
+import array
+
+def hexdump(s):
+ def toprint(c):
+ if 32 <= ord(c) < 127:
+ return c
+ else:
+ return "."
+ def hexline(i, s):
+ return ("%04x: " % i + " ".join(["%02x" % ord(c) for c in s]).ljust(52) +
+ "|" +
+ "".join([toprint(c) for c in s]).ljust(16) +
+ "|")
+ return "\n".join([hexline(i, s[i:i+16]) for i in range(0, len(s), 16)])
+
+pgm = array.array('H', [int(l, 16) for l in open(sys.argv[1])])
+
+while pgm[-1] == 0:
+ pgm = pgm[:-1]
+s = pgm.tostring()
+print
+print hexdump(s)
+
+link = [w for w in pgm[::-1] if w][0]
+words = []
+while link:
+ name = s[link + 2:]
+ c = ord(name[0])
+ name = name[1:1+c]
+ print "%04x %s" % (link, name)
+ assert not name in words
+ words.append(name)
+ link = pgm[link / 2]
+print len(words), " ".join(words)
+print "program size %d/%d" % (len(pgm), 1024)
diff --git a/j1/toolchain/go b/j1/toolchain/go
new file mode 100644
index 0000000..6570942
--- /dev/null
+++ b/j1/toolchain/go
@@ -0,0 +1,3 @@
+set -e
+gforth cross.fs basewords.fs nuc.fs
+# python dump.py ../build/firmware/demo0.hex
diff --git a/j1/toolchain/nuc.fs b/j1/toolchain/nuc.fs
new file mode 100644
index 0000000..846db05
--- /dev/null
+++ b/j1/toolchain/nuc.fs
@@ -0,0 +1,604 @@
+header 1+ : 1+ d# 1 + ;
+header 1- : 1- d# -1 + ;
+header 0= : 0= d# 0 = ;
+header cell+ : cell+ d# 2 + ;
+
+header <> : <> = invert ;
+header > : > swap < ;
+header 0< : 0< d# 0 < ;
+header 0> : 0> d# 0 > ;
+header 0<> : 0<> d# 0 <> ;
+header u> : u> swap u< ;
+
+: eol ( u -- u' false | true )
+ d# -1 +
+ dup 0= dup if
+ ( 0 true -- )
+ nip
+ then
+;
+
+header ms
+: ms
+ begin
+ d# 15000 begin
+ eol until
+ eol until
+;
+
+
+header key?
+: key?
+ d# 0 io@
+ d# 4 and
+ 0<>
+;
+
+header key
+: key
+ begin
+ key?
+ until
+ d# 0 io@ d# 8 rshift
+ d# 0 d# 2 io!
+;
+
+: ready
+ d# 0 io@
+ d# 2 and
+ 0=
+;
+
+header emit
+: emit
+ begin ready until
+ h# 0 io!
+;
+
+header cr
+: cr
+ d# 13 emit
+ d# 10 emit
+;
+
+header space
+: space
+ d# 32 emit
+;
+
+header bl
+: bl
+ d# 32
+;
+
+: hex1
+ h# f and
+ dup d# 10 < if
+ [char] 0
+ else
+ d# 55
+ then
+ +
+ emit
+;
+
+: hex2
+ dup d# 4 rshift hex1 hex1
+;
+
+: hex4
+ dup d# 8 rshift hex2 hex2
+;
+
+: hex8
+ dup d# 16 rshift hex4 hex4
+;
+
+header .
+: . hex8 space ;
+
+header false : false d# 0 ;
+header true : true d# -1 ;
+header rot : rot >r swap r> swap ;
+header -rot : -rot swap >r swap r> ;
+header tuck : tuck swap over ;
+header 2drop : 2drop drop drop ;
+header ?dup : ?dup dup if dup then ;
+
+header 2dup : 2dup over over ;
+header +! : +! tuck @ + swap ! ;
+header 2swap : 2swap rot >r rot r> ;
+
+header min : min 2dup< if drop else nip then ;
+header max : max 2dup< if nip else drop then ;
+
+header c@
+: c@
+ dup @ swap
+ d# 3 and d# 3 lshift rshift
+ d# 255 and
+;
+
+: hi16
+ d# 16 rshift d# 16 lshift
+;
+
+: lo16
+ d# 16 lshift d# 16 rshift
+;
+
+header uw@
+: uw@
+ dup @ swap
+ d# 2 and d# 3 lshift rshift
+ lo16
+;
+
+header w!
+: w! ( u c-addr -- )
+ dup>r d# 2 and if
+ d# 16 lshift
+ r@ @ lo16
+ else
+ lo16
+ r@ @ hi16
+ then
+ or r> !
+;
+
+header c!
+: c! ( u c-addr -- )
+ dup>r d# 1 and if
+ d# 8 lshift
+ h# 00ff
+ else
+ h# 00ff and
+ h# ff00
+ then
+ r@ uw@ and
+ or r> w!
+;
+
+header count
+: count
+ dup 1+ swap c@
+;
+
+: bounds ( a n -- a+n a )
+ over + swap
+;
+
+header type
+: type
+ bounds
+ begin
+ 2dupxor
+ while
+ dup c@ emit
+ 1+
+ repeat
+ 2drop
+;
+
+create base $a ,
+create ll 0 ,
+create dp 0 ,
+create tib# 0 ,
+create >in 0 ,
+create tib 80 allot
+
+header words : words
+ ll uw@
+ begin
+ dup
+ while
+ cr
+ dup .
+ dup cell+
+ count type
+ space
+ uw@
+ repeat
+ drop
+;
+
+header dump : dump ( addr u -- )
+ cr over hex4
+ begin ( addr u )
+ ?dup
+ while
+ over c@ space hex2
+ 1- swap 1+ ( u' addr' )
+ dup h# f and 0= if ( next line? )
+ cr dup hex4
+ then
+ swap
+ repeat
+ drop cr
+;
+
+header negate : negate invert 1+ ;
+header - : - negate + ;
+header abs : abs dup 0< if negate then ;
+header 2* : 2* d# 1 lshift ;
+header 2/ : 2/ d# 1 rshift ;
+header here : here dp @ ;
+header depth : depth depths h# f and ;
+
+: /string
+ dup >r - swap r> + swap
+;
+
+header aligned
+: aligned
+ d# 3 + d# -4 and
+;
+
+: d+ ( augend . addend . -- sum . )
+ rot + >r ( augend addend)
+ over + ( augend sum)
+ dup rot ( sum sum augend)
+ u< if ( sum)
+ r> 1+
+ else
+ r>
+ then ( sum . )
+;
+
+: d1+ d# 1. d+ ;
+
+: dnegate
+ invert swap invert swap
+ d1+
+;
+
+: dabs ( d -- ud )
+ dup 0< if dnegate then
+;
+
+: s>d dup 0< ;
+: m+
+ s>d d+
+;
+
+: snap
+ cr depth hex2 space
+ begin
+ depth
+ while
+ .
+ repeat
+ cr
+ [char] # emit
+ begin again
+;
+
+create scratch 0 ,
+
+header um*
+: um* ( u1 u2 -- ud )
+ scratch !
+ d# 0.
+ d# 32 begin
+ >r
+ 2dup d+
+ rot dup 0< if
+ 2* -rot
+ scratch @ d# 0 d+
+ else
+ 2* -rot
+ then
+ r> eol
+ until
+ rot drop
+;
+: *
+ um* drop
+;
+
+header accept
+: accept
+ d# 30 emit
+ drop dup
+ begin
+ key
+ dup h# 0d xor
+ while
+ dup h# 0a = if
+ drop
+ else
+ over c! 1+
+ then
+ repeat
+ drop swap -
+;
+
+: 3rd >r over r> swap ;
+: 3dup 3rd 3rd 3rd ;
+
+: sameword ( c-addr u wp -- c-addr u wp flag )
+ 2dup d# 2 + c@ = if
+ 3dup
+ d# 3 + >r
+ bounds
+ begin
+ 2dupxor
+ while
+ dup c@ r@ c@ <> if
+ 2drop rdrop false exit
+ then
+ 1+
+ r> 1+ >r
+ repeat
+ 2drop rdrop true
+ else
+ false
+ then
+;
+
+\ lsb 0 means non-immediate, return -1
+\ 1 means immediate, return 1
+: isimmediate ( wp -- -1 | 1 )
+ uw@ d# 1 and 2* 1-
+;
+
+: sfind
+ ll uw@
+ begin
+ dup
+ while
+ sameword
+ if
+ nip nip
+ dup
+ d# 2 +
+ count +
+ d# 1 + d# -2 and
+ swap isimmediate
+ exit
+ then
+ uw@
+ repeat
+;
+
+: digit? ( c -- u f )
+ dup h# 39 > h# 100 and +
+ dup h# 140 > h# 107 and - h# 30 -
+ dup base @ u<
+;
+
+: ud* ( ud1 u -- ud2 ) \ ud2 is the product of ud1 and u
+ tuck * >r
+ um* r> +
+;
+
+: >number ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 )
+ begin
+ dup
+ while
+ over c@ digit?
+ 0= if drop exit then
+ >r 2swap base @ ud*
+ r> m+ 2swap
+ d# 1 /string
+ repeat
+;
+
+header fill
+: fill ( c-addr u char -- ) ( 6.1.1540 )
+ >r bounds
+ begin
+ 2dupxor
+ while
+ r@ over c! 1+
+ repeat
+ r> drop 2drop
+;
+
+header erase
+: erase
+ d# 0 fill
+;
+
+header execute
+: execute
+ >r
+;
+
+header source
+: source
+ tib tib# @
+;
+
+\ From Forth200x - public domain
+
+: isspace? ( c -- f )
+ bl 1+ u< ;
+
+: isnotspace? ( c -- f )
+ isspace? 0= ;
+
+: xt-skip ( addr1 n1 xt -- addr2 n2 ) \ gforth
+ \ skip all characters satisfying xt ( c -- f )
+ >r
+ BEGIN
+ over c@ r@ execute
+ over 0<> and
+ WHILE
+ d# 1 /string
+ REPEAT
+ r> drop ;
+
+: parse-name ( "name" -- c-addr u )
+ source >in @ /string
+ ['] isspace? xt-skip over >r
+ ['] isnotspace? xt-skip ( end-word restlen r: start-word )
+ 2dup d# 1 min + source drop - >in !
+ drop r> tuck - ;
+
+header ! :noname ! ;
+header + :noname + ;
+header xor :noname xor ;
+header and :noname and ;
+header or :noname or ;
+header invert :noname invert ;
+header = :noname = ;
+header < :noname < ;
+header u< :noname u< ;
+header swap :noname swap ;
+header dup :noname dup ;
+header drop :noname drop ;
+header over :noname over ;
+header nip :noname nip ;
+header @ :noname @ ;
+header io! :noname io! ;
+header rshift :noname rshift ;
+header lshift :noname lshift ;
+\
+\ \ >r
+\ \ r>
+\ \ r@
+\ \ exit
+\
+
+: xmain
+ cr d# 1 ms cr
+ d# 60 begin
+ [char] - emit
+ eol until
+ begin key? while key drop repeat
+
+ cr h# ffff hex8
+
+ d# 0 d# 100 dump
+ words cr cr
+
+ begin again
+
+ begin
+ cr
+ tib d# 30 accept >r
+ d# 0. tib r> >number
+ 2drop hex4 space hex4
+ again
+
+ snap
+;
+
+: route
+ r> + >r ;
+
+\ (doubleAlso) ( c-addr u -- x 1 | x x 2 )
+\ If the string is legal, leave a single or double cell number
+\ and size of the number.
+
+: isvoid ( caddr u -- ) \ any char remains, throw -13
+ nip 0<>
+ if [char] x emit snap then
+;
+
+: consume1 ( caddr u ch -- caddr' u' f )
+ >r over c@ r> =
+ over 0<> and
+ dup>r d# 1 and /string r>
+;
+
+: (doubleAlso)
+ h# 0. 2swap
+ [char] - consume1 >r
+ >number
+ [char] . consume1 if
+ isvoid \ double number
+ r> if dnegate then
+ d# 2 exit
+ then
+ \ single number
+ isvoid drop
+ r> if negate then
+ d# 1
+;
+
+: doubleAlso
+ (doubleAlso) drop
+;
+
+
+: dispatch
+ route ;fallthru
+ jmp execute \ -1 0 non-immediate
+ jmp doubleAlso \ 0 0 number
+ jmp execute \ 1 0 immediate
+
+\ jmp compile_comma \ -1 2 non-immediate
+\ jmp doubleAlso_comma \ 0 2 number
+\ jmp execute \ 1 2 immediate
+
+: interpret
+ begin
+ parse-name dup
+ while
+ sfind
+ 1+ 2* dispatch
+ repeat
+ 2drop
+;
+
+: main
+ 2drop
+ begin
+ tib d# 80 accept
+ tib# !
+ \ h# 40 emit
+ d# 0 >in !
+ source dump
+ \ cr parse-name sfind
+ \ if
+ \ execute
+ \ then
+ interpret
+ again
+;
+
+meta
+ $3f80 org
+target
+
+: b.key
+ begin
+ d# 0 io@
+ d# 4 and
+ until
+ d# 0 io@ d# 8 rshift
+ d# 0 d# 2 io!
+;
+
+: b.32
+ b.key
+ b.key d# 8 lshift or
+ b.key d# 16 lshift or
+ b.key d# 24 lshift or
+;
+
+meta
+ $3fc0 org
+target
+
+: bootloader
+ begin
+ b.key d# 27 =
+ until
+
+ b.32 d# 0
+ begin
+ 2dupxor
+ while
+ b.32 over !
+ d# 4 +
+ repeat
+;
+
+meta
+ link @ t,
+ link @ t' ll tw!
+ there t' dp tw!
+target
diff --git a/j1/toolchain/strings.fs b/j1/toolchain/strings.fs
new file mode 100644
index 0000000..cbd9b0e
--- /dev/null
+++ b/j1/toolchain/strings.fs
@@ -0,0 +1,25 @@
+( Strings JCB 11:57 05/18/12)
+
+: >str ( c-addr u -- str ) \ a new u char string from c-addr
+ dup cell+ allocate throw dup >r
+ 2dup ! cell+ \ write size into first cell
+ ( c-addr u saddr )
+ swap cmove r>
+;
+: str@ dup cell+ swap @ ;
+: str! ( str c-addr -- c-addr' ) \ copy str to c-addr
+ >r str@ r>
+ 2dup + >r swap
+ cmove r>
+;
+: +str ( str2 str1 -- str3 )
+ over @ over @ + cell+ allocate throw >r
+ over @ over @ + r@ !
+ r@ cell+ str! str! drop r>
+;
+
+: example
+ s" sailor" >str
+ s" hello" >str
+ +str str@ type
+;
diff --git a/j1/verilog/common.h b/j1/verilog/common.h
new file mode 100644
index 0000000..03da65d
--- /dev/null
+++ b/j1/verilog/common.h
@@ -0,0 +1,3 @@
+`default_nettype none
+`define WIDTH 32
+`define DEPTH 4
diff --git a/j1/verilog/j1.v b/j1/verilog/j1.v
new file mode 100644
index 0000000..d69ca20
--- /dev/null
+++ b/j1/verilog/j1.v
@@ -0,0 +1,123 @@
+`include "common.h"
+
+module j1(
+ input wire clk,
+ input wire resetq,
+
+ output wire io_wr,
+ output wire [15:0] mem_addr,
+ output wire mem_wr,
+ output wire [`WIDTH-1:0] dout,
+ input wire [`WIDTH-1:0] mem_din,
+
+ input wire [`WIDTH-1:0] io_din,
+
+ output wire [12:0] code_addr,
+ input wire [15:0] insn
+ );
+ reg [`DEPTH-1:0] dsp; // Data stack pointer
+ reg [`DEPTH-1:0] dspN;
+ reg [`WIDTH-1:0] st0; // Top of data stack
+ reg [`WIDTH-1:0] st0N;
+ reg dstkW; // D stack write
+
+ reg [12:0] pc, pcN;
+ reg [`DEPTH-1:0] rsp, rspN;
+ reg rstkW; // R stack write
+ wire [`WIDTH-1:0] rstkD; // R stack write value
+ reg reboot = 1;
+ wire [12:0] pc_plus_1 = pc + 1;
+
+ assign mem_addr = st0N[15:0];
+ assign code_addr = {pcN};
+
+ // The D and R stacks
+ wire [`WIDTH-1:0] st1, rst0;
+ stack #(.DEPTH(`DEPTH))
+ dstack(.clk(clk), .resetq(resetq), .ra(dsp), .rd(st1), .we(dstkW), .wa(dspN), .wd(st0));
+ stack #(.DEPTH(`DEPTH))rstack(.clk(clk), .resetq(resetq), .ra(rsp), .rd(rst0), .we(rstkW), .wa(rspN), .wd(rstkD));
+
+ always @*
+ begin
+ // Compute the new value of st0
+ casez ({insn[15:8]})
+ 8'b1??_?????: st0N = { {(`WIDTH - 15){1'b0}}, insn[14:0] }; // literal
+ 8'b000_?????: st0N = st0; // jump
+ 8'b010_?????: st0N = st0; // call
+ 8'b001_?????: st0N = st1; // conditional jump
+ 8'b011_?0000: st0N = st0; // ALU operations...
+ 8'b011_?0001: st0N = st1;
+ 8'b011_?0010: st0N = st0 + st1;
+ 8'b011_?0011: st0N = st0 & st1;
+ 8'b011_?0100: st0N = st0 | st1;
+ 8'b011_?0101: st0N = st0 ^ st1;
+ 8'b011_?0110: st0N = ~st0;
+ 8'b011_?0111: st0N = {`WIDTH{(st1 == st0)}};
+ 8'b011_?1000: st0N = {`WIDTH{($signed(st1) < $signed(st0))}};
+`ifdef NOSHIFTER // `define NOSHIFTER in common.h to cut slice usage in half and shift by 1 only
+ 8'b011_?1001: st0N = st1 >> 1;
+ 8'b011_?1010: st0N = st1 << 1;
+`else // otherwise shift by 1-any number of bits
+ 8'b011_?1001: st0N = st1 >> st0[4:0];
+ 8'b011_?1010: st0N = st1 << st0[4:0];
+`endif
+ 8'b011_?1011: st0N = rst0;
+ 8'b011_?1100: st0N = mem_din;
+ 8'b011_?1101: st0N = io_din;
+ 8'b011_?1110: st0N = {{(`WIDTH - 8){1'b0}}, rsp, dsp};
+ 8'b011_?1111: st0N = {`WIDTH{(st1 < st0)}};
+ default: st0N = {`WIDTH{1'bx}};
+ endcase
+ end
+
+ wire func_T_N = (insn[6:4] == 1);
+ wire func_T_R = (insn[6:4] == 2);
+ wire func_write = (insn[6:4] == 3);
+ wire func_iow = (insn[6:4] == 4);
+
+ wire is_alu = (insn[15:13] == 3'b011);
+ assign mem_wr = !reboot & is_alu & func_write;
+ assign dout = st1;
+ assign io_wr = !reboot & is_alu & func_iow;
+
+ assign rstkD = (insn[13] == 1'b0) ? {{(`WIDTH - 14){1'b0}}, pc_plus_1, 1'b0} : st0;
+
+ reg [`DEPTH-1:0] dspI, rspI;
+ always @*
+ begin
+ casez ({insn[15:13]})
+ 3'b1??: {dstkW, dspI} = {1'b1, 4'b0001};
+ 3'b001: {dstkW, dspI} = {1'b0, 4'b1111};
+ 3'b011: {dstkW, dspI} = {func_T_N, {insn[1], insn[1], insn[1:0]}};
+ default: {dstkW, dspI} = {1'b0, 4'b0000};
+ endcase
+ dspN = dsp + dspI;
+
+ casez ({insn[15:13]})
+ 3'b010: {rstkW, rspI} = {1'b1, 4'b0001};
+ 3'b011: {rstkW, rspI} = {func_T_R, {insn[3], insn[3], insn[3:2]}};
+ default: {rstkW, rspI} = {1'b0, 4'b0000};
+ endcase
+ rspN = rsp + rspI;
+
+ casez ({reboot, insn[15:13], insn[7], |st0})
+ 6'b1_???_?_?: pcN = 0;
+ 6'b0_000_?_?,
+ 6'b0_010_?_?,
+ 6'b0_001_?_0: pcN = insn[12:0];
+ 6'b0_011_1_?: pcN = rst0[13:1];
+ default: pcN = pc_plus_1;
+ endcase
+ end
+
+ always @(negedge resetq or posedge clk)
+ begin
+ if (!resetq) begin
+ reboot <= 1'b1;
+ { pc, dsp, st0, rsp } <= 0;
+ end else begin
+ reboot <= 0;
+ { pc, dsp, st0, rsp } <= { pcN, dspN, st0N, rspN };
+ end
+ end
+endmodule
diff --git a/j1/verilog/stack.v b/j1/verilog/stack.v
new file mode 100644
index 0000000..e5cee8a
--- /dev/null
+++ b/j1/verilog/stack.v
@@ -0,0 +1,22 @@
+`include "common.h"
+
+module stack
+ #(parameter DEPTH=4)
+ (input wire clk,
+ /* verilator lint_off UNUSED */
+ input wire resetq,
+ /* verilator lint_on UNUSED */
+ input wire [DEPTH-1:0] ra,
+ output wire [`WIDTH-1:0] rd,
+ input wire we,
+ input wire [DEPTH-1:0] wa,
+ input wire [`WIDTH-1:0] wd);
+
+ reg [`WIDTH-1:0] store[0:(2**DEPTH)-1];
+
+ always @(posedge clk)
+ if (we)
+ store[wa] <= wd;
+
+ assign rd = store[ra];
+endmodule
diff --git a/j1/verilog/testbench.v b/j1/verilog/testbench.v
new file mode 100644
index 0000000..2ec2b5e
--- /dev/null
+++ b/j1/verilog/testbench.v
@@ -0,0 +1,30 @@
+`timescale 1ns/1ps
+`default_nettype none
+
+module testbench();
+
+ reg clk;
+ reg resetq;
+ integer t;
+
+ top #(.FIRMWARE("build/firmware/")) dut(.clk(clk), .resetq(resetq));
+
+ initial begin
+ clk = 1;
+ t = 0;
+ resetq = 0;
+ #1;
+ resetq = 1;
+
+ $dumpfile("test.vcd");
+ $dumpvars(0, dut);
+ end
+
+ always #5.0 clk = ~clk;
+
+ always @(posedge clk) begin
+ t <= t + 1;
+ if (t == 300)
+ $finish;
+ end
+endmodule
diff --git a/j1/verilog/top.v b/j1/verilog/top.v
new file mode 100644
index 0000000..efcf297
--- /dev/null
+++ b/j1/verilog/top.v
@@ -0,0 +1,9 @@
+module top(
+ input clk,
+ input resetq,
+ output [15:0] tail);
+ parameter FIRMWARE = "<firmware>";
+
+ j1 _j1 (.clk(clk), .resetq(resetq));
+
+endmodule
diff --git a/j1/verilog/uart.v b/j1/verilog/uart.v
new file mode 100644
index 0000000..4daac0f
--- /dev/null
+++ b/j1/verilog/uart.v
@@ -0,0 +1,180 @@
+`default_nettype none
+
+module baudgen(
+ input wire clk,
+ input wire resetq,
+ input wire [31:0] baud,
+ input wire restart,
+ output wire ser_clk);
+ parameter CLKFREQ = 1000000;
+
+ wire [38:0] aclkfreq = CLKFREQ;
+ reg [38:0] d;
+ wire [38:0] dInc = d[38] ? ({4'd0, baud}) : (({4'd0, baud}) - aclkfreq);
+ wire [38:0] dN = restart ? 0 : (d + dInc);
+ wire fastclk = ~d[38];
+ assign ser_clk = fastclk;
+
+ always @(negedge resetq or posedge clk)
+ begin
+ if (!resetq) begin
+ d <= 0;
+ end else begin
+ d <= dN;
+ end
+ end
+endmodule
+
+/*
+
+-----+ +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+ | | | | | | | | | | | |
+ |start| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |stop1|stop2|
+ | | | | | | | | | | | ? |
+ +-----+-----+-----+-----+-----+-----+-----+-----+-----+ +
+
+*/
+
+module uart(
+ input wire clk, // System clock
+ input wire resetq,
+
+ // Outputs
+ output wire uart_busy, // High means UART is transmitting
+ output reg uart_tx, // UART transmit wire
+ // Inputs
+ input wire [31:0] baud,
+ input wire uart_wr_i, // Raise to transmit byte
+ input wire [7:0] uart_dat_i // 8-bit data
+);
+ parameter CLKFREQ = 1000000;
+
+ reg [3:0] bitcount;
+ reg [8:0] shifter;
+
+ assign uart_busy = |bitcount;
+ wire sending = |bitcount;
+
+ wire ser_clk;
+
+ wire starting = uart_wr_i & ~uart_busy;
+ baudgen #(.CLKFREQ(CLKFREQ)) _baudgen(
+ .clk(clk),
+ .resetq(resetq),
+ .baud(baud),
+ .restart(1'b0),
+ .ser_clk(ser_clk));
+
+ always @(negedge resetq or posedge clk)
+ begin
+ if (!resetq) begin
+ uart_tx <= 1;
+ bitcount <= 0;
+ shifter <= 0;
+ end else begin
+ if (starting) begin
+ shifter <= { uart_dat_i[7:0], 1'b0 };
+ bitcount <= 1 + 8 + 1;
+ end
+
+ if (sending & ser_clk) begin
+ { shifter, uart_tx } <= { 1'b1, shifter };
+ bitcount <= bitcount - 4'd1;
+ end
+ end
+ end
+
+endmodule
+
+module rxuart(
+ input wire clk,
+ input wire resetq,
+ input wire [31:0] baud,
+ input wire uart_rx, // UART recv wire
+ input wire rd, // read strobe
+ output wire valid, // has data
+ output wire [7:0] data); // data
+ parameter CLKFREQ = 1000000;
+
+ reg [4:0] bitcount;
+ reg [7:0] shifter;
+
+ // On starting edge, wait 3 half-bits then sample, and sample every 2 bits thereafter
+
+ wire idle = &bitcount;
+ wire sample;
+ reg [2:0] hh = 3'b111;
+ wire [2:0] hhN = {hh[1:0], uart_rx};
+ wire startbit = idle & (hhN[2:1] == 2'b10);
+ wire [7:0] shifterN = sample ? {hh[1], shifter[7:1]} : shifter;
+
+ wire ser_clk;
+ baudgen #(.CLKFREQ(CLKFREQ)) _baudgen(
+ .clk(clk),
+ .baud({baud[30:0], 1'b0}),
+ .resetq(resetq),
+ .restart(startbit),
+ .ser_clk(ser_clk));
+
+ assign valid = (bitcount == 18);
+ reg [4:0] bitcountN;
+ always @*
+ if (startbit)
+ bitcountN = 0;
+ else if (!idle & !valid & ser_clk)
+ bitcountN = bitcount + 5'd1;
+ else if (valid & rd)
+ bitcountN = 5'b11111;
+ else
+ bitcountN = bitcount;
+
+ // 3,5,7,9,11,13,15,17
+ assign sample = (bitcount > 2) & bitcount[0] & !valid & ser_clk;
+ assign data = shifter;
+
+ always @(negedge resetq or posedge clk)
+ begin
+ if (!resetq) begin
+ hh <= 3'b111;
+ bitcount <= 5'b11111;
+ shifter <= 0;
+ end else begin
+ hh <= hhN;
+ bitcount <= bitcountN;
+ shifter <= shifterN;
+ end
+ end
+endmodule
+
+module buart(
+ input wire clk,
+ input wire resetq,
+ input wire [31:0] baud,
+ input wire rx, // recv wire
+ output wire tx, // xmit wire
+ input wire rd, // read strobe
+ input wire wr, // write strobe
+ output wire valid, // has recv data
+ output wire busy, // is transmitting
+ input wire [7:0] tx_data,
+ output wire [7:0] rx_data // data
+);
+ parameter CLKFREQ = 1000000;
+
+ rxuart #(.CLKFREQ(CLKFREQ)) _rx (
+ .clk(clk),
+ .resetq(resetq),
+ .baud(baud),
+ .uart_rx(rx),
+ .rd(rd),
+ .valid(valid),
+ .data(rx_data));
+ uart #(.CLKFREQ(CLKFREQ)) _tx (
+ .clk(clk),
+ .resetq(resetq),
+ .baud(baud),
+ .uart_busy(busy),
+ .uart_tx(tx),
+ .uart_wr_i(wr),
+ .uart_dat_i(tx_data));
+endmodule
diff --git a/j1/verilog/xilinx-top.v b/j1/verilog/xilinx-top.v
new file mode 100644
index 0000000..6695d77
--- /dev/null
+++ b/j1/verilog/xilinx-top.v
@@ -0,0 +1,215 @@
+`default_nettype none
+
+
+module bram_tdp #(
+ parameter DATA = 72,
+ parameter ADDR = 10
+) (
+ // Port A
+ input wire a_clk,
+ input wire a_wr,
+ input wire [ADDR-1:0] a_addr,
+ input wire [DATA-1:0] a_din,
+ output reg [DATA-1:0] a_dout,
+
+ // Port B
+ input wire b_clk,
+ input wire b_wr,
+ input wire [ADDR-1:0] b_addr,
+ input wire [DATA-1:0] b_din,
+ output reg [DATA-1:0] b_dout
+);
+
+// Shared memory
+reg [DATA-1:0] mem [(2**ADDR)-1:0];
+ initial begin
+ $readmemh("../build/firmware/demo0.hex", mem);
+ end
+
+// Port A
+always @(posedge a_clk) begin
+ a_dout <= mem[a_addr];
+ if(a_wr) begin
+ a_dout <= a_din;
+ mem[a_addr] <= a_din;
+ end
+end
+
+// Port B
+always @(posedge b_clk) begin
+ b_dout <= mem[b_addr];
+ if(b_wr) begin
+ b_dout <= b_din;
+ mem[b_addr] <= b_din;
+ end
+end
+
+endmodule
+
+// A 16Kbyte RAM (4096x32) with one write port and one read port
+module ram16k0(
+ input wire clk,
+
+ input wire[15:0] a_addr,
+ output wire[31:0] a_q,
+ input wire[31:0] a_d,
+ input wire a_wr,
+
+ input wire[12:0] b_addr,
+ output wire[15:0] b_q);
+
+ //synthesis attribute ram_style of mem is block
+ reg [31:0] mem[0:4095]; //pragma attribute mem ram_block TRUE
+ initial begin
+ $readmemh("../build/firmware/demo0.hex", mem);
+ end
+
+ always @ (posedge clk)
+ if (a_wr)
+ mem[a_addr[13:2]] <= a_d;
+
+ reg [15:0] a_addr_;
+ always @ (posedge clk)
+ a_addr_ <= a_addr;
+ assign a_q = mem[a_addr_[13:2]];
+
+ reg [12:0] raddr_reg;
+ always @ (posedge clk)
+ raddr_reg <= b_addr;
+ wire [31:0] insn32 = mem[raddr_reg[12:1]];
+ assign b_q = raddr_reg[0] ? insn32[31:16] : insn32[15:0];
+endmodule
+
+module ram16k(
+ input wire clk,
+
+ input wire[15:0] a_addr,
+ output wire[31:0] a_q,
+ input wire[31:0] a_d,
+ input wire a_wr,
+
+ input wire[12:0] b_addr,
+ output wire[15:0] b_q);
+
+ wire [31:0] insn32;
+
+ bram_tdp #(.DATA(32), .ADDR(12)) nram (
+ .a_clk(clk),
+ .a_wr(a_wr),
+ .a_addr(a_addr[13:2]),
+ .a_din(a_d),
+ .a_dout(a_q),
+
+ .b_clk(clk),
+ .b_wr(1'b0),
+ .b_addr(b_addr[12:1]),
+ .b_din(32'd0),
+ .b_dout(insn32));
+
+ reg ba_;
+ always @(posedge clk)
+ ba_ <= b_addr[0];
+ assign b_q = ba_ ? insn32[31:16] : insn32[15:0];
+
+endmodule
+
+
+module top(
+ input wire CLK,
+ output wire DUO_LED,
+ input wire DUO_SW1,
+ input wire RXD,
+ output wire TXD,
+ input wire DTR
+ );
+ localparam MHZ = 40;
+
+ wire fclk;
+
+ DCM_CLKGEN #(
+ .CLKFX_MD_MAX(0.0), // Specify maximum M/D ratio for timing anlysis
+ .CLKFX_DIVIDE(32), // Divide value - D - (1-256)
+ .CLKFX_MULTIPLY(MHZ), // Multiply value - M - (2-256)
+ .CLKIN_PERIOD(31.25), // Input clock period specified in nS
+ .STARTUP_WAIT("FALSE") // Delay config DONE until DCM_CLKGEN LOCKED (TRUE/FALSE)
+ )
+ DCM_CLKGEN_inst (
+ .CLKFX(fclk), // 1-bit output: Generated clock output
+ .CLKIN(CLK), // 1-bit input: Input clock
+ .FREEZEDCM(0), // 1-bit input: Prevents frequency adjustments to input clock
+ .PROGCLK(0), // 1-bit input: Clock input for M/D reconfiguration
+ .PROGDATA(0), // 1-bit input: Serial data input for M/D reconfiguration
+ .PROGEN(0), // 1-bit input: Active high program enable
+ .RST(0) // 1-bit input: Reset input pin
+ );
+
+ reg [25:0] counter;
+ always @(posedge fclk)
+ counter <= counter + 26'd1;
+ assign DUO_LED = counter[25];
+
+ // ------------------------------------------------------------------------
+
+ wire uart0_valid, uart0_busy;
+ wire [7:0] uart0_data;
+ wire uart0_rd, uart0_wr;
+ reg [31:0] baud = 32'd115200;
+ wire UART0_RX;
+ buart #(.CLKFREQ(MHZ * 1000000)) _uart0 (
+ .clk(fclk),
+ .resetq(1'b1),
+ .baud(baud),
+ .rx(RXD),
+ .tx(TXD),
+ .rd(uart0_rd),
+ .wr(uart0_wr),
+ .valid(uart0_valid),
+ .busy(uart0_busy),
+ .tx_data(dout_[7:0]),
+ .rx_data(uart0_data));
+
+ wire [15:0] mem_addr;
+ wire [31:0] mem_din;
+ wire mem_wr;
+ wire [31:0] dout;
+
+ wire [12:0] code_addr;
+ wire [15:0] insn;
+
+ wire io_wr;
+
+ wire resetq = DTR;
+
+ j1 _j1 (
+ .clk(fclk),
+ .resetq(resetq),
+
+ .io_wr(io_wr),
+ .mem_addr(mem_addr),
+ .mem_wr(mem_wr),
+ .mem_din(mem_din),
+ .dout(dout),
+ .io_din({16'd0, uart0_data, 4'd0, DTR, uart0_valid, uart0_busy, DUO_SW1}),
+
+ .code_addr(code_addr),
+ .insn(insn)
+ );
+
+ ram16k ram(.clk(fclk),
+ .a_addr(mem_addr),
+ .a_q(mem_din),
+ .a_wr(mem_wr),
+ .a_d(dout),
+ .b_addr(code_addr),
+ .b_q(insn));
+
+ reg io_wr_;
+ reg [15:0] mem_addr_;
+ reg [31:0] dout_;
+ always @(posedge fclk)
+ {io_wr_, mem_addr_, dout_} <= {io_wr, mem_addr, dout};
+
+ assign uart0_wr = io_wr_ & (mem_addr_ == 16'h0000);
+ assign uart0_rd = io_wr_ & (mem_addr_ == 16'h0002);
+
+endmodule
diff --git a/j1/xilinx/.gitignore b/j1/xilinx/.gitignore
new file mode 100644
index 0000000..e138931
--- /dev/null
+++ b/j1/xilinx/.gitignore
@@ -0,0 +1,44 @@
+*.bgn
+*.bit
+*_bitgen.xwbt
+*.bld
+*.cfi
+*.drc
+*.map
+*.mcs
+*.mrp
+*.ncd
+*.ngc
+*.ngc_xst.xrpt
+*.ngd
+*_ngdbuild.xrpt
+*.ngm
+*_par.grf
+*_par.ncd
+*_par.pad
+*_par_pad.csv
+*_par_pad.txt
+*_par.par
+*_par.ptwx
+*_par.unroutes
+*_par.xpi
+*.pcf
+*.prj
+*.prm
+*.psr
+*.scr
+*.srp
+*.xml
+*.html
+_impactbatch.log
+netlist.lst
+smartguide.ncd
+top.lso
+top_map.xrpt
+top_par.xrpt
+usage_statistics_webtalk.html
+webtalk.log
+xlnx_auto_0_xdb
+_xmsgs
+xst
+unused/
diff --git a/j1/xilinx/Makefile b/j1/xilinx/Makefile
new file mode 100644
index 0000000..481513b
--- /dev/null
+++ b/j1/xilinx/Makefile
@@ -0,0 +1,11 @@
+project = j1-papilioduo
+vendor = xilinx
+family = spartan3s
+part = xc6slx9-2-tqg144
+# part = xc3s200an-4ftg256
+top_module = top
+flashsize = 2048
+
+vfiles = ../verilog/xilinx-top.v ../verilog/uart.v ../verilog/j1.v ../verilog/stack.v
+
+include xilinx.mk
diff --git a/j1/xilinx/go b/j1/xilinx/go
new file mode 100644
index 0000000..c527f4c
--- /dev/null
+++ b/j1/xilinx/go
@@ -0,0 +1,22 @@
+set -e
+cd ../toolchain
+sh go
+cd ../xilinx
+
+$HOME/Downloads/DesignLab-1.0.5/tools/Papilio_Loader/programmer/linux32/papilio-prog -v -f j1-papilioduo.bit
+python shell.py -h /dev/ttyUSB2 -i ../build/firmware/nuc.hex ; exit
+
+make clean
+make
+if false
+then
+ cp ../build/firmware/nuc.hex ../build/firmware/nuc.mem
+ data2mem -bm j1-papilioduo_bd.bmm -bd ../build/firmware/nuc.mem -bt j1-papilioduo.bit
+ trce -v 10 j1-papilioduo.ncd j1-papilioduo.pcf -o j1-papilioduo.twr
+ DL=j1-papilioduo_rp.bit
+else
+ DL=j1-papilioduo.bit
+fi
+$HOME/Downloads/DesignLab-1.0.5/tools/Papilio_Loader/programmer/linux32/papilio-prog -v -f $DL
+python shell.py -h /dev/ttyUSB2 -i ../build/firmware/nuc.hex ; exit
+# miniterm.py /dev/ttyUSB0 115200
diff --git a/j1/xilinx/j1-papilioduo.bmm b/j1/xilinx/j1-papilioduo.bmm
new file mode 100644
index 0000000..3dea0be
--- /dev/null
+++ b/j1/xilinx/j1-papilioduo.bmm
@@ -0,0 +1,24 @@
+// BMM LOC annotation file.
+//
+// Release 14.6 - P.20131013, build 3.0.10 Apr 3, 2013
+// Copyright (c) 1995-2015 Xilinx, Inc. All rights reserved.
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Address space 'j1' 0x00000000:0x000007FF (2 KBytes).
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// ADDRESS_SPACE j1 RAMB16 [0xffff0000:0xffff3FFF]
+// BUS_BLOCK
+// ram/nram/Mram_mem7 RAMB16 [3:0] [0:4095];
+// ram/nram/Mram_mem6 RAMB16 [7:4] [0:4095];
+// ram/nram/Mram_mem5 RAMB16 [11:8] [0:4095];
+// ram/nram/Mram_mem4 RAMB16 [15:12] [0:4095];
+// ram/nram/Mram_mem3 RAMB16 [19:16] [0:4095];
+// ram/nram/Mram_mem2 RAMB16 [23:20] [0:4095];
+// ram/nram/Mram_mem1 RAMB16 [27:24] [0:4095];
+// ram/nram/Mram_mem0 RAMB16 [31:28] [0:4095];
+// END_BUS_BLOCK;
+// END_ADDRESS_SPACE;
diff --git a/j1/xilinx/j1-papilioduo.ucf b/j1/xilinx/j1-papilioduo.ucf
new file mode 100644
index 0000000..e06e002
--- /dev/null
+++ b/j1/xilinx/j1-papilioduo.ucf
@@ -0,0 +1,183 @@
+# UCF file for the Papilio DUO board
+# Generated by pin_converter, written by Kevin Lindsey
+# https://github.com/thelonious/papilio_pins/tree/development/pin_converter
+
+# Main board wing pin [] to FPGA pin Pxx map
+# -------C------- -------B------- -------A-------
+# [GND] [C00] P114 [GND] [B00] P99 P100 [A15]
+# [2V5] [C01] P115 [2V5] [B01] P97 P98 [A14]
+# [3V3] [C02] P116 [3V3] [B02] P92 P93 [A13]
+# [5V0] [C03] P117 [5V0] [B03] P87 P88 [A12]
+# [C04] P118 [B04] P84 P85 [A11] [5V0]
+# [C05] P119 [B05] P82 P83 [A10] [3V3]
+# [C06] P120 [B06] P80 P81 [A09] [2V5]
+# [C07] P121 [B07] P78 P79 [A08] [GND]
+# [GND] [C08] P123 [GND] [B08] P74 P75 [A07]
+# [2V5] [C09] P124 [2V5] [B09] P95 P67 [A06]
+# [3V3] [C10] P126 [3V3] [B10] P62 P66 [A05]
+# [5V0] [C11] P127 [5V0] [B11] P59 P61 [A04]
+# [C12] P131 [B12] P57 P58 [A03] [5V0]
+# [C13] P132 [B13] P55 P56 [A02] [3V3]
+# [C14] P133 [B14] P50 P51 [A01] [2V5]
+# [C15] P134 [B15] P47 P48 [A00] [GND]
+
+## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
+CONFIG PROHIBIT=P144;
+CONFIG PROHIBIT=P69;
+CONFIG PROHIBIT=P60;
+
+#NET "*" IOSTANDARD = LVTTL;
+
+NET CLK LOC="P94" | IOSTANDARD=LVTTL; # CLK
+TIMESPEC TS_Period_1 = PERIOD "CLK" 31.25 ns HIGH 50%;
+NET TXD LOC="P141" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;
+NET RXD LOC="P46" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;
+NET DTR LOC="P137" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+
+// NET "fclk" PERIOD = 6 ns HIGH 50%;
+
+#
+# NET Arduino_0 LOC="P116" | IOSTANDARD=LVTTL; # A0
+# NET Arduino_1 LOC="P117" | IOSTANDARD=LVTTL; # A1
+# NET Arduino_2 LOC="P118" | IOSTANDARD=LVTTL; # A2
+# NET Arduino_3 LOC="P119" | IOSTANDARD=LVTTL; # A3
+# NET Arduino_4 LOC="P120" | IOSTANDARD=LVTTL; # A4
+# NET Arduino_5 LOC="P121" | IOSTANDARD=LVTTL; # A5
+# NET Arduino_6 LOC="P123" | IOSTANDARD=LVTTL; # A6
+# NET Arduino_7 LOC="P124" | IOSTANDARD=LVTTL; # A7
+# NET Arduino_8 LOC="P126" | IOSTANDARD=LVTTL; # A8
+# NET Arduino_9 LOC="P127" | IOSTANDARD=LVTTL; # A9
+# NET Arduino_10 LOC="P131" | IOSTANDARD=LVTTL; # A10
+# NET Arduino_11 LOC="P132" | IOSTANDARD=LVTTL; # A11
+# NET Arduino_12 LOC="P133" | IOSTANDARD=LVTTL; # A12
+# NET Arduino_13 LOC="P134" | IOSTANDARD=LVTTL; # A13
+#
+# NET Arduino_14 LOC="P115" | IOSTANDARD=LVTTL; # B0
+# NET Arduino_15 LOC="P114" | IOSTANDARD=LVTTL; # B1
+# NET Arduino_16 LOC="P112" | IOSTANDARD=LVTTL; # B2
+# NET Arduino_17 LOC="P111" | IOSTANDARD=LVTTL; # B3
+# NET Arduino_18 LOC="P105" | IOSTANDARD=LVTTL; # B4
+# NET Arduino_19 LOC="P102" | IOSTANDARD=LVTTL; # B5
+# NET Arduino_20 LOC="P101" | IOSTANDARD=LVTTL; # B6
+# NET Arduino_21 LOC="P100" | IOSTANDARD=LVTTL; # B7
+#
+# NET Arduino_22 LOC="P99" | IOSTANDARD=LVTTL; # C0
+# NET Arduino_24 LOC="P97" | IOSTANDARD=LVTTL; # C1
+# NET Arduino_26 LOC="P93" | IOSTANDARD=LVTTL; # C2
+# NET Arduino_28 LOC="P88" | IOSTANDARD=LVTTL; # C3
+# NET Arduino_30 LOC="P85" | IOSTANDARD=LVTTL; # C4
+# NET Arduino_32 LOC="P83" | IOSTANDARD=LVTTL; # C5
+# NET Arduino_34 LOC="P81" | IOSTANDARD=LVTTL; # C6
+# NET Arduino_36 LOC="P79" | IOSTANDARD=LVTTL; # C7
+# NET Arduino_38 LOC="P75" | IOSTANDARD=LVTTL; # C8
+# NET Arduino_40 LOC="P67" | IOSTANDARD=LVTTL; # C9
+# NET Arduino_42 LOC="P62" | IOSTANDARD=LVTTL; # C10
+# NET Arduino_44 LOC="P59" | IOSTANDARD=LVTTL; # C11
+# NET Arduino_46 LOC="P57" | IOSTANDARD=LVTTL; # C12
+# NET Arduino_48 LOC="P55" | IOSTANDARD=LVTTL; # C13
+# NET Arduino_50 LOC="P50" | IOSTANDARD=LVTTL; # C14
+# NET Arduino_52 LOC="P47" | IOSTANDARD=LVTTL; # C15
+#
+# NET Arduino_23 LOC="P98" | IOSTANDARD=LVTTL ;
+# NET Arduino_25 LOC="P95" | IOSTANDARD=LVTTL ;
+# NET Arduino_27 LOC="P92" | IOSTANDARD=LVTTL ;
+# NET Arduino_29 LOC="P87" | IOSTANDARD=LVTTL ;
+# NET Arduino_31 LOC="P84" | IOSTANDARD=LVTTL ;
+# NET Arduino_33 LOC="P82" | IOSTANDARD=LVTTL ;
+# NET Arduino_35 LOC="P80" | IOSTANDARD=LVTTL ;
+# NET Arduino_37 LOC="P78" | IOSTANDARD=LVTTL ;
+# NET Arduino_39 LOC="P74" | IOSTANDARD=LVTTL ;
+# NET Arduino_41 LOC="P66" | IOSTANDARD=LVTTL ;
+# NET Arduino_43 LOC="P61" | IOSTANDARD=LVTTL ;
+# NET Arduino_45 LOC="P58" | IOSTANDARD=LVTTL ;
+# NET Arduino_47 LOC="P56" | IOSTANDARD=LVTTL ;
+# NET Arduino_49 LOC="P51" | IOSTANDARD=LVTTL ;
+# NET Arduino_51 LOC="P48" | IOSTANDARD=LVTTL ;
+# NET Arduino_53 LOC="P39" | IOSTANDARD=LVTTL ;
+#
+# # SRAM
+#
+# NET "sram_addr<0>" LOC = "P7" | IOSTANDARD=LVTTL | SLEW=FAST;
+# NET "sram_addr<1>" LOC = "P8" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<2>" LOC = "P9" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<3>" LOC = "P10" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<4>" LOC = "P11" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<5>" LOC = "P5" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<6>" LOC = "P2" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<7>" LOC = "P1" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<8>" LOC = "P143" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<9>" LOC = "P142" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<10>" LOC = "P43" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<11>" LOC = "P41" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<12>" LOC = "P40" | IOSTANDARD=LVTTL | SLEW=FAST;
+# NET "sram_addr<13>" LOC = "P35" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<14>" LOC = "P34" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<15>" LOC = "P27" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<16>" LOC = "P29" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<17>" LOC = "P33" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_addr<18>" LOC = "P32" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# #NET "sram_addr<19>" LOC = "P44" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# #NET "sram_addr<20>" LOC = "P30" | IOSTANDARD=LVTTL | SLEW=FAST ;
+#
+# # Data lines
+# NET "sram_data<0>" LOC = "P14" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_data<1>" LOC = "P15" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_data<2>" LOC = "P16" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_data<3>" LOC = "P17" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_data<4>" LOC = "P21" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_data<5>" LOC = "P22" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_data<6>" LOC = "P23" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_data<7>" LOC = "P24" | IOSTANDARD=LVTTL | SLEW=FAST ;
+#
+# # Control lines
+# NET "sram_ce" LOC = "P12" | IOSTANDARD=LVTTL | SLEW=FAST;
+# NET "sram_we" LOC = "P6" | IOSTANDARD=LVTTL | SLEW=FAST ;
+# NET "sram_oe" LOC = "P26" | IOSTANDARD=LVTTL | SLEW=FAST;
+#
+# NET SPI_CS LOC="P38" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CS OK
+# NET SPI_SCK LOC="P70" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CK OK
+# NET SPI_MOSI LOC="P64" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_SI OK
+# NET SPI_MISO LOC="P65" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_SO OK
+#
+# #Dragon MPSSE
+# NET BD0_MPSSE_TCK LOC="P46" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET BD1_MPSSE_TDI LOC="P141" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET BD2_MPSSE_TDO LOC="P140" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET BD3_MPSSE_TMS LOC="P138" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET BD4_MPSSE_DTR LOC="P137" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+#
+# #Arduino JTAG
+# NET ARD_JTAG_TDI LOC="P88" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET ARD_JTAG_TDO LOC="P85" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET ARD_JTAG_TMS LOC="P83" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET ARD_JTAG_TCK LOC="P81" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+#
+# #Arduino SPI
+# NET ARD_SPI_MISO LOC="P133" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET ARD_SPI_MOSI LOC="P132" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET ARD_SPI_SCLK LOC="P134" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+#
+# #Dragon SPI
+# NET DRAGON_SPI_GND LOC="P78" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET DRAGON_SPI_RESET LOC="P79" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# #NET DRAGON_SPI_RESET LOC="P79" | IOSTANDARD=LVTTL | DRIVE=8 | PULLUP | SLEW=SLOW;
+# NET DRAGON_SPI_MOSI LOC="P74" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET DRAGON_SPI_SCK LOC="P75" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET DRAGON_SPI_VTG LOC="P66" | IOSTANDARD=LVTTL | DRIVE=24 | SLEW=SLOW;
+# NET DRAGON_SPI_MISO LOC="P67" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+#
+# #Dragon JTAG
+# NET DRAGON_JTAG_TCK LOC="P47" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET DRAGON_JTAG_GND LOC="P39" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET DRAGON_JTAG_TDO LOC="P50" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET DRAGON_JTAG_VTG LOC="P48" | IOSTANDARD=LVTTL | DRIVE=24 | SLEW=SLOW;
+# NET DRAGON_JTAG_TMS LOC="P55" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET DRAGON_JTAG_RESET LOC="P51" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# #NET DRAGON_JTAG_RESET LOC="P51" | IOSTANDARD=LVTTL | DRIVE=8 | PULLUP | SLEW=SLOW;
+# NET DRAGON_JTAG_TDI LOC="P59" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET DRAGON_JTAG_GND2 LOC="P58" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+#
+# #Dragon Misc
+NET DUO_SW1 LOC="P104" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
+# NET ARD_RESET LOC="P139" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; # ARD_RESET
+NET DUO_LED LOC="P134" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
diff --git a/j1/xilinx/shell.py b/j1/xilinx/shell.py
new file mode 100644
index 0000000..814e6a2
--- /dev/null
+++ b/j1/xilinx/shell.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+
+import sys
+from datetime import datetime
+import time
+import array
+import struct
+import os
+
+try:
+ import serial
+except:
+ print "This tool needs PySerial, but it was not found"
+ sys.exit(1)
+
+import swapforth as sf
+
+class TetheredJ1b(sf.TetheredFT900):
+ def __init__(self, port):
+ ser = serial.Serial(port, 115200, timeout=None, rtscts=0)
+ self.ser = ser
+ self.searchpath = ['.']
+ self.log = open("log", "w")
+
+ def boot(self, bootfile = None):
+ ser = self.ser
+ ser.setDTR(1)
+ ser.setDTR(0)
+ boot = array.array('I', [int(l, 16) for l in open(bootfile)])
+ boot = boot[:0x3f80 / 4] # remove bootloader itself (top 128 bytes)
+ while boot[-1] == 0: # remove any unused words
+ boot = boot[:-1]
+ boot = boot.tostring()
+ ser.write(chr(27))
+ print 'wrote 27'
+ # print repr(ser.read(1))
+
+ ser.write(struct.pack('I', len(boot)))
+ ser.write(boot)
+ print 'completed load of %d bytes' % len(boot)
+ # print repr(ser.read(1))
+
+if __name__ == '__main__':
+ port = '/dev/ttyUSB0'
+ image = None
+
+ r = None
+
+ args = sys.argv[1:]
+ while args:
+ a = args[0]
+ if a.startswith('-i'):
+ image = args[1]
+ args = args[2:]
+ elif a.startswith('-h'):
+ port = args[1]
+ args = args[2:]
+ else:
+ if not r:
+ r = TetheredJ1b(port)
+ r.boot(image)
+ if a.startswith('-e'):
+ print r.shellcmd(args[1])
+ args = args[2:]
+ else:
+ try:
+ r.include(a)
+ except sf.Bye:
+ pass
+ args = args[1:]
+ if not r:
+ r = TetheredJ1b(port)
+ r.boot(image)
+
+ print repr(r.ser.read(1))
+ # r.interactive_command(None)
+ r.shell(False)
+ # r.listen()
diff --git a/j1/xilinx/xilinx.mk b/j1/xilinx/xilinx.mk
new file mode 100644
index 0000000..f71dede
--- /dev/null
+++ b/j1/xilinx/xilinx.mk
@@ -0,0 +1,176 @@
+# The top level module should define the variables below then include
+# this file. The files listed should be in the same directory as the
+# Makefile.
+#
+# variable description
+# ---------- -------------
+# project project name (top level module should match this name)
+# top_module top level module of the project
+# libdir path to library directory
+# libs library modules used
+# vfiles all local .v files
+# xilinx_cores all local .xco files
+# vendor vendor of FPGA (xilinx, altera, etc.)
+# family FPGA device family (spartan3e)
+# part FPGA part name (xc4vfx12-10-sf363)
+# flashsize size of flash for mcs file (16384)
+# optfile (optional) xst extra opttions file to put in .scr
+# map_opts (optional) options to give to map
+# par_opts (optional) options to give to par
+# intstyle (optional) intstyle option to all tools
+#
+# files description
+# ---------- ------------
+# $(project).ucf ucf file
+#
+# Library modules should have a modules.mk in their root directory,
+# namely $(libdir)/<libname>/module.mk, that simply adds to the vfiles
+# and xilinx_cores variable.
+#
+# all the .xco files listed in xilinx_cores will be generated with core, with
+# the resulting .v and .ngc files placed back in the same directory as
+# the .xco file.
+#
+# TODO: .xco files are device dependant, should use a template based system
+
+coregen_work_dir ?= ./coregen-tmp
+map_opts ?= -timing -ol high -detail -pr b -register_duplication -w
+par_opts ?= -ol high
+isedir ?= /data/Xilinx/14.7/ISE_DS
+xil_env ?= . $(isedir)/settings64.sh
+flashsize ?= 8192
+
+libmks = $(patsubst %,$(libdir)/%/module.mk,$(libs))
+mkfiles = Makefile $(libmks) xilinx.mk
+include $(libmks)
+
+corengcs = $(foreach core,$(xilinx_cores),$(core:.xco=.ngc))
+local_corengcs = $(foreach ngc,$(corengcs),$(notdir $(ngc)))
+vfiles += $(foreach core,$(xilinx_cores),$(core:.xco=.v))
+junk += $(local_corengcs)
+
+.PHONY: default xilinx_cores clean twr etwr
+default: $(project).bit $(project).mcs
+xilinx_cores: $(corengcs)
+twr: $(project).twr
+etwr: $(project)_err.twr
+
+define cp_template
+$(2): $(1)
+ cp $(1) $(2)
+endef
+$(foreach ngc,$(corengcs),$(eval $(call cp_template,$(ngc),$(notdir $(ngc)))))
+
+%.ngc %.v: %.xco
+ @echo "=== rebuilding $@"
+ if [ -d $(coregen_work_dir) ]; then \
+ rm -rf $(coregen_work_dir)/*; \
+ else \
+ mkdir -p $(coregen_work_dir); \
+ fi
+ cd $(coregen_work_dir); \
+ $(xil_env); \
+ coregen -b $$OLDPWD/$<; \
+ cd -
+ xcodir=`dirname $<`; \
+ basename=`basename $< .xco`; \
+ if [ ! -r $(coregen_work_dir/$$basename.ngc) ]; then \
+ echo "'$@' wasn't created."; \
+ exit 1; \
+ else \
+ cp $(coregen_work_dir)/$$basename.v $(coregen_work_dir)/$$basename.ngc $$xcodir; \
+ fi
+junk += $(coregen_work_dir)
+
+date = $(shell date +%F-%H-%M)
+
+# some common junk
+junk += *.xrpt
+
+programming_files: $(project).bit $(project).mcs
+ mkdir -p $@/$(date)
+ mkdir -p $@/latest
+ for x in .bit .mcs .cfi _bd.bmm; do cp $(project)$$x $@/$(date)/$(project)$$x; cp $(project)$$x $@/latest/$(project)$$x; done
+ $(xil_env); xst -help | head -1 | sed 's/^/#/' | cat - $(project).scr > $@/$(date)/$(project).scr
+
+$(project).mcs: $(project).bit
+ $(xil_env); \
+ promgen -w -s $(flashsize) -p mcs -o $@ -u 0 $^
+junk += $(project).mcs $(project).cfi $(project).prm
+
+$(project).bit: $(project)_par.ncd
+ $(xil_env); \
+ bitgen $(intstyle) -g UserID:0x09470947 -g DriveDone:yes -g StartupClk:Cclk -w $(project)_par.ncd $(project).bit
+ # bitgen $(intstyle) -g compress -g UserID:0x09470947 -g DriveDone:yes -g StartupClk:Cclk -w $(project)_par.ncd $(project).bit
+ # bitgen $(intstyle) -g UserID:0x09470947 -g DriveDone:yes -g StartupClk:Cclk -w $(project)_par.ncd $(project).bit
+junk += $(project).bgn $(project).bit $(project).drc $(project)_bd.bmm
+
+
+$(project)_par.ncd: $(project).ncd
+ $(xil_env); \
+ if par $(intstyle) $(par_opts) -w $(project).ncd $(project)_par.ncd; then \
+ :; \
+ else \
+ $(MAKE) etwr; \
+ fi
+junk += $(project)_par.ncd $(project)_par.par $(project)_par.pad
+junk += $(project)_par_pad.csv $(project)_par_pad.txt
+junk += $(project)_par.grf $(project)_par.ptwx
+junk += $(project)_par.unroutes $(project)_par.xpi
+
+$(project).ncd: $(project).ngd
+ if [ -r $(project)_par.ncd ]; then \
+ cp $(project)_par.ncd smartguide.ncd; \
+ smartguide="-smartguide smartguide.ncd"; \
+ else \
+ smartguide=""; \
+ fi; \
+ $(xil_env); \
+ map $(intstyle) $(map_opts) $$smartguide $<
+junk += $(project).ncd $(project).pcf $(project).ngm $(project).mrp $(project).map
+junk += smartguide.ncd $(project).psr
+junk += $(project)_summary.xml $(project)_usage.xml
+
+$(project).ngd: $(project).ngc $(project).ucf $(project).bmm
+ $(xil_env); ngdbuild $(intstyle) $(project).ngc -bm $(project).bmm
+junk += $(project).ngd $(project).bld
+
+$(project).ngc: $(vfiles) $(local_corengcs) $(project).scr $(project).prj
+ $(xil_env); xst $(intstyle) -ifn $(project).scr
+junk += xlnx_auto* $(top_module).lso $(project).srp
+junk += netlist.lst xst $(project).ngc
+
+$(project).prj: $(vfiles) $(mkfiles)
+ for src in $(vfiles); do echo "verilog work $$src" >> $(project).tmpprj; done
+ sort -u $(project).tmpprj > $(project).prj
+ rm -f $(project).tmpprj
+junk += $(project).prj
+
+optfile += $(wildcard $(project).opt)
+top_module ?= $(project)
+$(project).scr: $(optfile) $(mkfiles) ./xilinx.opt
+ echo "run" > $@
+ echo "-p $(part)" >> $@
+ echo "-top $(top_module)" >> $@
+ echo "-ifn $(project).prj" >> $@
+ echo "-ofn $(project).ngc" >> $@
+ cat ./xilinx.opt $(optfile) >> $@
+junk += $(project).scr
+
+$(project).post_map.twr: $(project).ncd
+ $(xil_env); trce -e 10 $< $(project).pcf -o $@
+junk += $(project).post_map.twr $(project).post_map.twx smartpreview.twr
+
+$(project).twr: $(project)_par.ncd
+ $(xil_env); trce $< $(project).pcf -o $(project).twr
+junk += $(project).twr $(project).twx smartpreview.twr
+
+$(project)_err.twr: $(project)_par.ncd
+ $(xil_env); trce -e 10 $< $(project).pcf -o $(project)_err.twr
+junk += $(project)_err.twr $(project)_err.twx
+
+.gitignore: $(mkfiles)
+ echo programming_files $(junk) | sed 's, ,\n,g' > .gitignore
+
+clean::
+ rm -rf $(junk)
diff --git a/j1/xilinx/xilinx.opt b/j1/xilinx/xilinx.opt
new file mode 100644
index 0000000..c9e5ab7
--- /dev/null
+++ b/j1/xilinx/xilinx.opt
@@ -0,0 +1,42 @@
+-ifmt mixed
+-ofmt NGC
+-opt_mode speed
+-opt_level 1
+-iuc NO
+-keep_hierarchy no
+-netlist_hierarchy as_optimized
+-rtlview no
+-glob_opt AllClockNets
+-read_cores yes
+-write_timing_constraints NO
+-cross_clock_analysis NO
+-hierarchy_separator /
+-bus_delimiter <>
+-case maintain
+-slice_utilization_ratio 100
+-bram_utilization_ratio 100
+#-dsp_utilization_ratio 100
+-safe_implementation No
+-fsm_extract YES
+-fsm_encoding Auto
+-fsm_style lut
+-ram_extract Yes
+-ram_style Auto
+-rom_extract Yes
+-rom_style Auto
+-shreg_extract YES
+-auto_bram_packing NO
+-resource_sharing NO
+-async_to_sync NO
+#-use_dsp48 auto
+-iobuf YES
+-max_fanout 500
+-register_duplication YES
+-register_balancing No
+-optimize_primitives NO
+-use_clock_enable Auto
+-use_sync_set Auto
+-use_sync_reset Auto
+-iob auto
+-equivalent_register_removal YES
+-slice_utilization_ratio_maxmargin 5