├── .gitignore ├── README.md ├── verilog ├── common.h ├── top.v ├── stack.v ├── testbench.v ├── j1.v ├── uart.v └── xilinx-top.v ├── toolchain ├── demo1.fs ├── go ├── strings.fs ├── dump.py ├── basewords.fs ├── cross.fs └── nuc.fs ├── go ├── xilinx ├── Makefile ├── .gitignore ├── go ├── j1-papilioduo.bmm ├── xilinx.opt ├── shell.py ├── xilinx.mk └── j1-papilioduo.ucf ├── Makefile ├── LICENSE └── sim_main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | a.out 2 | test.vcd 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | j1 2 | == 3 | 4 | The J1 CPU 5 | -------------------------------------------------------------------------------- /verilog/common.h: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | `define WIDTH 32 3 | `define DEPTH 4 4 | -------------------------------------------------------------------------------- /toolchain/demo1.fs: -------------------------------------------------------------------------------- 1 | : main 2 | begin 3 | h# 0 io@ 4 | d# 1 + 5 | h# 0 io! 6 | again 7 | ; 8 | -------------------------------------------------------------------------------- /toolchain/go: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | mkdir -p ../build/firmware/ 4 | gforth cross.fs basewords.fs nuc.fs 5 | # python dump.py ../build/firmware/demo0.hex 6 | -------------------------------------------------------------------------------- /verilog/top.v: -------------------------------------------------------------------------------- 1 | module top( 2 | input clk, 3 | input resetq, 4 | output [15:0] tail); 5 | parameter FIRMWARE = ""; 6 | 7 | j1 _j1 (.clk(clk), .resetq(resetq)); 8 | 9 | endmodule 10 | -------------------------------------------------------------------------------- /go: -------------------------------------------------------------------------------- 1 | (cd toolchain && sh go) || exit 2 | iverilog -I verilog/ -g2 -s testbench verilog/testbench.v verilog/top.v verilog/j1.v verilog/stack.v || exit 3 | ./a.out 4 | 5 | make && obj_dir/Vj1 build/firmware/demo0.hex 6 | -------------------------------------------------------------------------------- /xilinx/Makefile: -------------------------------------------------------------------------------- 1 | project = j1-papilioduo 2 | vendor = xilinx 3 | family = spartan3s 4 | part = xc6slx9-2-tqg144 5 | # part = xc3s200an-4ftg256 6 | top_module = top 7 | flashsize = 2048 8 | 9 | vfiles = ../verilog/xilinx-top.v ../verilog/uart.v ../verilog/j1.v ../verilog/stack.v 10 | 11 | include xilinx.mk 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | $(SUBDIRS): 3 | $(MAKE) -C $@ 4 | 5 | all: obj_dir/Vj1 $(SUBDIRS) 6 | 7 | VERILOGS=verilog/j1.v verilog/stack.v 8 | 9 | obj_dir/Vj1: $(VERILOGS) sim_main.cpp Makefile 10 | verilator -Wall --cc --trace -Iverilog/ $(VERILOGS) --top-module j1 --exe sim_main.cpp 11 | # verilator --cc --trace $(VERILOGS) --top-module j1 --exe sim_main.cpp 12 | $(MAKE) -C obj_dir OPT_FAST="-O2" -f Vj1.mk Vj1 13 | 14 | .PHONY: all 15 | -------------------------------------------------------------------------------- /verilog/stack.v: -------------------------------------------------------------------------------- 1 | `include "common.h" 2 | 3 | module stack 4 | #(parameter DEPTH=4) 5 | (input wire clk, 6 | /* verilator lint_off UNUSED */ 7 | input wire resetq, 8 | /* verilator lint_on UNUSED */ 9 | input wire [DEPTH-1:0] ra, 10 | output wire [`WIDTH-1:0] rd, 11 | input wire we, 12 | input wire [DEPTH-1:0] wa, 13 | input wire [`WIDTH-1:0] wd); 14 | 15 | reg [`WIDTH-1:0] store[0:(2**DEPTH)-1]; 16 | 17 | always @(posedge clk) 18 | if (we) 19 | store[wa] <= wd; 20 | 21 | assign rd = store[ra]; 22 | endmodule 23 | -------------------------------------------------------------------------------- /verilog/testbench.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | `default_nettype none 3 | 4 | module testbench(); 5 | 6 | reg clk; 7 | reg resetq; 8 | integer t; 9 | 10 | top #(.FIRMWARE("build/firmware/")) dut(.clk(clk), .resetq(resetq)); 11 | 12 | initial begin 13 | clk = 1; 14 | t = 0; 15 | resetq = 0; 16 | #1; 17 | resetq = 1; 18 | 19 | $dumpfile("test.vcd"); 20 | $dumpvars(0, dut); 21 | end 22 | 23 | always #5.0 clk = ~clk; 24 | 25 | always @(posedge clk) begin 26 | t <= t + 1; 27 | if (t == 300) 28 | $finish; 29 | end 30 | endmodule 31 | -------------------------------------------------------------------------------- /xilinx/.gitignore: -------------------------------------------------------------------------------- 1 | *.bgn 2 | *.bit 3 | *_bitgen.xwbt 4 | *.bld 5 | *.cfi 6 | *.drc 7 | *.map 8 | *.mcs 9 | *.mrp 10 | *.ncd 11 | *.ngc 12 | *.ngc_xst.xrpt 13 | *.ngd 14 | *_ngdbuild.xrpt 15 | *.ngm 16 | *_par.grf 17 | *_par.ncd 18 | *_par.pad 19 | *_par_pad.csv 20 | *_par_pad.txt 21 | *_par.par 22 | *_par.ptwx 23 | *_par.unroutes 24 | *_par.xpi 25 | *.pcf 26 | *.prj 27 | *.prm 28 | *.psr 29 | *.scr 30 | *.srp 31 | *.xml 32 | *.html 33 | _impactbatch.log 34 | netlist.lst 35 | smartguide.ncd 36 | top.lso 37 | top_map.xrpt 38 | top_par.xrpt 39 | usage_statistics_webtalk.html 40 | webtalk.log 41 | xlnx_auto_0_xdb 42 | _xmsgs 43 | xst 44 | unused/ 45 | -------------------------------------------------------------------------------- /toolchain/strings.fs: -------------------------------------------------------------------------------- 1 | ( Strings JCB 11:57 05/18/12) 2 | 3 | : >str ( c-addr u -- str ) \ a new u char string from c-addr 4 | dup cell+ allocate throw dup >r 5 | 2dup ! cell+ \ write size into first cell 6 | ( c-addr u saddr ) 7 | swap cmove r> 8 | ; 9 | : str@ dup cell+ swap @ ; 10 | : str! ( str c-addr -- c-addr' ) \ copy str to c-addr 11 | >r str@ r> 12 | 2dup + >r swap 13 | cmove r> 14 | ; 15 | : +str ( str2 str1 -- str3 ) 16 | over @ over @ + cell+ allocate throw >r 17 | over @ over @ + r@ ! 18 | r@ cell+ str! str! drop r> 19 | ; 20 | 21 | : example 22 | s" sailor" >str 23 | s" hello" >str 24 | +str str@ type 25 | ; 26 | -------------------------------------------------------------------------------- /xilinx/go: -------------------------------------------------------------------------------- 1 | set -e 2 | cd ../toolchain 3 | sh go 4 | cd ../xilinx 5 | 6 | $HOME/Downloads/DesignLab-1.0.5/tools/Papilio_Loader/programmer/linux32/papilio-prog -v -f j1-papilioduo.bit 7 | python shell.py -h /dev/ttyUSB2 -i ../build/firmware/nuc.hex ; exit 8 | 9 | make clean 10 | make 11 | if false 12 | then 13 | cp ../build/firmware/nuc.hex ../build/firmware/nuc.mem 14 | data2mem -bm j1-papilioduo_bd.bmm -bd ../build/firmware/nuc.mem -bt j1-papilioduo.bit 15 | trce -v 10 j1-papilioduo.ncd j1-papilioduo.pcf -o j1-papilioduo.twr 16 | DL=j1-papilioduo_rp.bit 17 | else 18 | DL=j1-papilioduo.bit 19 | fi 20 | $HOME/Downloads/DesignLab-1.0.5/tools/Papilio_Loader/programmer/linux32/papilio-prog -v -f $DL 21 | python shell.py -h /dev/ttyUSB2 -i ../build/firmware/nuc.hex ; exit 22 | # miniterm.py /dev/ttyUSB0 115200 23 | -------------------------------------------------------------------------------- /xilinx/j1-papilioduo.bmm: -------------------------------------------------------------------------------- 1 | // BMM LOC annotation file. 2 | // 3 | // Release 14.6 - P.20131013, build 3.0.10 Apr 3, 2013 4 | // Copyright (c) 1995-2015 Xilinx, Inc. All rights reserved. 5 | 6 | 7 | /////////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Address space 'j1' 0x00000000:0x000007FF (2 KBytes). 10 | // 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | // ADDRESS_SPACE j1 RAMB16 [0xffff0000:0xffff3FFF] 14 | // BUS_BLOCK 15 | // ram/nram/Mram_mem7 RAMB16 [3:0] [0:4095]; 16 | // ram/nram/Mram_mem6 RAMB16 [7:4] [0:4095]; 17 | // ram/nram/Mram_mem5 RAMB16 [11:8] [0:4095]; 18 | // ram/nram/Mram_mem4 RAMB16 [15:12] [0:4095]; 19 | // ram/nram/Mram_mem3 RAMB16 [19:16] [0:4095]; 20 | // ram/nram/Mram_mem2 RAMB16 [23:20] [0:4095]; 21 | // ram/nram/Mram_mem1 RAMB16 [27:24] [0:4095]; 22 | // ram/nram/Mram_mem0 RAMB16 [31:28] [0:4095]; 23 | // END_BUS_BLOCK; 24 | // END_ADDRESS_SPACE; 25 | -------------------------------------------------------------------------------- /xilinx/xilinx.opt: -------------------------------------------------------------------------------- 1 | -ifmt mixed 2 | -ofmt NGC 3 | -opt_mode speed 4 | -opt_level 1 5 | -iuc NO 6 | -keep_hierarchy no 7 | -netlist_hierarchy as_optimized 8 | -rtlview no 9 | -glob_opt AllClockNets 10 | -read_cores yes 11 | -write_timing_constraints NO 12 | -cross_clock_analysis NO 13 | -hierarchy_separator / 14 | -bus_delimiter <> 15 | -case maintain 16 | -slice_utilization_ratio 100 17 | -bram_utilization_ratio 100 18 | #-dsp_utilization_ratio 100 19 | -safe_implementation No 20 | -fsm_extract YES 21 | -fsm_encoding Auto 22 | -fsm_style lut 23 | -ram_extract Yes 24 | -ram_style Auto 25 | -rom_extract Yes 26 | -rom_style Auto 27 | -shreg_extract YES 28 | -auto_bram_packing NO 29 | -resource_sharing NO 30 | -async_to_sync NO 31 | #-use_dsp48 auto 32 | -iobuf YES 33 | -max_fanout 500 34 | -register_duplication YES 35 | -register_balancing No 36 | -optimize_primitives NO 37 | -use_clock_enable Auto 38 | -use_sync_set Auto 39 | -use_sync_reset Auto 40 | -iob auto 41 | -equivalent_register_removal YES 42 | -slice_utilization_ratio_maxmargin 5 43 | -------------------------------------------------------------------------------- /toolchain/dump.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import array 3 | 4 | def hexdump(s): 5 | def toprint(c): 6 | if 32 <= ord(c) < 127: 7 | return c 8 | else: 9 | return "." 10 | def hexline(i, s): 11 | return ("%04x: " % i + " ".join(["%02x" % ord(c) for c in s]).ljust(52) + 12 | "|" + 13 | "".join([toprint(c) for c in s]).ljust(16) + 14 | "|") 15 | return "\n".join([hexline(i, s[i:i+16]) for i in range(0, len(s), 16)]) 16 | 17 | pgm = array.array('H', [int(l, 16) for l in open(sys.argv[1])]) 18 | 19 | while pgm[-1] == 0: 20 | pgm = pgm[:-1] 21 | s = pgm.tostring() 22 | print 23 | print hexdump(s) 24 | 25 | link = [w for w in pgm[::-1] if w][0] 26 | words = [] 27 | while link: 28 | name = s[link + 2:] 29 | c = ord(name[0]) 30 | name = name[1:1+c] 31 | print "%04x %s" % (link, name) 32 | assert not name in words 33 | words.append(name) 34 | link = pgm[link / 2] 35 | print len(words), " ".join(words) 36 | print "program size %d/%d" % (len(pgm), 1024) 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2020, James Bowman 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of swapforth nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /sim_main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Vj1.h" 3 | #include "verilated_vcd_c.h" 4 | 5 | int main(int argc, char **argv) 6 | { 7 | Verilated::commandArgs(argc, argv); 8 | Vj1* top = new Vj1; 9 | int i; 10 | 11 | // Verilated::traceEverOn(true); 12 | // VerilatedVcdC* tfp = new VerilatedVcdC; 13 | // top->trace (tfp, 99); 14 | // tfp->open ("simx.vcd"); 15 | 16 | if (argc != 2) { 17 | fprintf(stderr, "usage: sim \n"); 18 | exit(1); 19 | } 20 | 21 | union { 22 | uint32_t ram32[4096]; 23 | uint16_t ram16[8192]; 24 | }; 25 | 26 | FILE *hex = fopen(argv[1], "r"); 27 | for (i = 0; i < 4096; i++) { 28 | unsigned int v; 29 | if (fscanf(hex, "%x\n", &v) != 1) { 30 | fprintf(stderr, "invalid hex value at line %d\n", i + 1); 31 | exit(1); 32 | } 33 | ram32[i] = v; 34 | } 35 | 36 | FILE *log = fopen("log", "w"); 37 | int t = 0; 38 | 39 | top->resetq = 0; 40 | top->eval(); 41 | top->resetq = 1; 42 | top->eval(); 43 | 44 | for (i = 0; i < 100000000; i++) { 45 | uint16_t a = top->mem_addr; 46 | uint16_t b = top->code_addr; 47 | if (top->mem_wr) 48 | ram32[(a & 16383) / 4] = top->dout; 49 | top->clk = 1; 50 | top->eval(); 51 | t += 20; 52 | 53 | top->mem_din = ram32[(a & 16383) / 4]; 54 | top->insn = ram16[b]; 55 | top->clk = 0; 56 | top->eval(); 57 | t += 20; 58 | if (top->io_wr) { 59 | putchar(top->dout); 60 | putc(top->dout, log); 61 | if (top->dout == '#') 62 | break; 63 | } 64 | #if 0 65 | if (top->io_inp && (top->io_n == 2)) { 66 | top->io_din = getchar(); 67 | } 68 | #endif 69 | } 70 | printf("\nSimulation ended after %d cycles\n", i); 71 | delete top; 72 | // tfp->close(); 73 | fclose(log); 74 | 75 | exit(0); 76 | } 77 | -------------------------------------------------------------------------------- /xilinx/shell.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from datetime import datetime 5 | import time 6 | import array 7 | import struct 8 | import os 9 | 10 | try: 11 | import serial 12 | except: 13 | print "This tool needs PySerial, but it was not found" 14 | sys.exit(1) 15 | 16 | import swapforth as sf 17 | 18 | class TetheredJ1b(sf.TetheredFT900): 19 | def __init__(self, port): 20 | ser = serial.Serial(port, 115200, timeout=None, rtscts=0) 21 | self.ser = ser 22 | self.searchpath = ['.'] 23 | self.log = open("log", "w") 24 | 25 | def boot(self, bootfile = None): 26 | ser = self.ser 27 | ser.setDTR(1) 28 | ser.setDTR(0) 29 | boot = array.array('I', [int(l, 16) for l in open(bootfile)]) 30 | boot = boot[:0x3f80 / 4] # remove bootloader itself (top 128 bytes) 31 | while boot[-1] == 0: # remove any unused words 32 | boot = boot[:-1] 33 | boot = boot.tostring() 34 | ser.write(chr(27)) 35 | print 'wrote 27' 36 | # print repr(ser.read(1)) 37 | 38 | ser.write(struct.pack('I', len(boot))) 39 | ser.write(boot) 40 | print 'completed load of %d bytes' % len(boot) 41 | # print repr(ser.read(1)) 42 | 43 | if __name__ == '__main__': 44 | port = '/dev/ttyUSB0' 45 | image = None 46 | 47 | r = None 48 | 49 | args = sys.argv[1:] 50 | while args: 51 | a = args[0] 52 | if a.startswith('-i'): 53 | image = args[1] 54 | args = args[2:] 55 | elif a.startswith('-h'): 56 | port = args[1] 57 | args = args[2:] 58 | else: 59 | if not r: 60 | r = TetheredJ1b(port) 61 | r.boot(image) 62 | if a.startswith('-e'): 63 | print r.shellcmd(args[1]) 64 | args = args[2:] 65 | else: 66 | try: 67 | r.include(a) 68 | except sf.Bye: 69 | pass 70 | args = args[1:] 71 | if not r: 72 | r = TetheredJ1b(port) 73 | r.boot(image) 74 | 75 | print repr(r.ser.read(1)) 76 | # r.interactive_command(None) 77 | r.shell(False) 78 | # r.listen() 79 | -------------------------------------------------------------------------------- /toolchain/basewords.fs: -------------------------------------------------------------------------------- 1 | ( J1 base words implemented in assembler JCB 17:27 12/31/11) 2 | 3 | : T h# 0000 ; 4 | : N h# 0100 ; 5 | : T+N h# 0200 ; 6 | : T&N h# 0300 ; 7 | : T|N h# 0400 ; 8 | : T^N h# 0500 ; 9 | : ~T h# 0600 ; 10 | : N==T h# 0700 ; 11 | : N>T h# 0900 ; 13 | : N<N h# 0010 or ; 21 | : T->R h# 0020 or ; 22 | : N->[T] h# 0030 or ; 23 | : N->io[T] h# 0040 or ; 24 | : RET h# 0080 or ; 25 | 26 | : d-1 h# 0003 or ; 27 | : d+1 h# 0001 or ; 28 | : r-1 h# 000c or ; 29 | : r-2 h# 0008 or ; 30 | : r+1 h# 0004 or ; 31 | 32 | : imm h# 8000 or tw, ; 33 | : alu h# 6000 or tw, ; 34 | : ubranch h# 0000 or tw, ; 35 | : 0branch h# 2000 or tw, ; 36 | : scall h# 4000 or tw, ; 37 | 38 | 39 | :: noop T alu ; 40 | :: + T+N d-1 alu ; 41 | :: xor T^N d-1 alu ; 42 | :: and T&N d-1 alu ; 43 | :: or T|N d-1 alu ; 44 | :: invert ~T alu ; 45 | :: = N==T d-1 alu ; 46 | :: < NN alu ; 49 | :: dup T T->N d+1 alu ; 50 | :: drop N d-1 alu ; 51 | :: over N T->N d+1 alu ; 52 | :: nip T d-1 alu ; 53 | :: >r N T->R r+1 d-1 alu ; 54 | :: r> rT T->N r-1 d+1 alu ; 55 | :: r@ rT T->N d+1 alu ; 56 | :: @ [T] alu ; 57 | :: io@ io[T] alu ; 58 | :: ! T N->[T] d-1 alu 59 | N d-1 alu ; 60 | :: io! T N->io[T] d-1 alu 61 | N d-1 alu ; 62 | :: rshift N>>T d-1 alu ; 63 | :: lshift N<N d+1 alu ; 65 | :: exit T RET r-1 alu ; 66 | 67 | \ Elided words 68 | \ These words are supported by the hardware but are not 69 | \ part of ANS Forth. They are named after the word-pair 70 | \ that matches their effect 71 | \ Using these elided words instead of 72 | \ the pair saves one cycle and one instruction. 73 | 74 | :: 2dupand T&N T->N d+1 alu ; 75 | :: 2dup< NN d+1 alu ; 76 | :: 2dup= N==T T->N d+1 alu ; 77 | :: 2dupor T|N T->N d+1 alu ; 78 | :: 2duprshift N>>T T->N d+1 alu ; 79 | :: 2dup+ T+N T->N d+1 alu ; 80 | :: 2dupu< NuN d+1 alu ; 81 | :: 2dupxor T^N T->N d+1 alu ; 82 | :: dup>r T T->R r+1 alu ; 83 | :: dup@ [T] T->N d+1 alu ; 84 | :: overand T&N alu ; 85 | :: over> N Nu[T] d-1 alu ; 93 | -------------------------------------------------------------------------------- /verilog/j1.v: -------------------------------------------------------------------------------- 1 | `include "common.h" 2 | 3 | module j1( 4 | input wire clk, 5 | input wire resetq, 6 | 7 | output wire io_wr, 8 | output wire [15:0] mem_addr, 9 | output wire mem_wr, 10 | output wire [`WIDTH-1:0] dout, 11 | input wire [`WIDTH-1:0] mem_din, 12 | 13 | input wire [`WIDTH-1:0] io_din, 14 | 15 | output wire [12:0] code_addr, 16 | input wire [15:0] insn 17 | ); 18 | reg [`DEPTH-1:0] dsp; // Data stack pointer 19 | reg [`DEPTH-1:0] dspN; 20 | reg [`WIDTH-1:0] st0; // Top of data stack 21 | reg [`WIDTH-1:0] st0N; 22 | reg dstkW; // D stack write 23 | 24 | reg [12:0] pc, pcN; 25 | reg [`DEPTH-1:0] rsp, rspN; 26 | reg rstkW; // R stack write 27 | wire [`WIDTH-1:0] rstkD; // R stack write value 28 | reg reboot = 1; 29 | wire [12:0] pc_plus_1 = pc + 1; 30 | 31 | assign mem_addr = st0N[15:0]; 32 | assign code_addr = {pcN}; 33 | 34 | // The D and R stacks 35 | wire [`WIDTH-1:0] st1, rst0; 36 | stack #(.DEPTH(`DEPTH)) 37 | dstack(.clk(clk), .resetq(resetq), .ra(dsp), .rd(st1), .we(dstkW), .wa(dspN), .wd(st0)); 38 | stack #(.DEPTH(`DEPTH))rstack(.clk(clk), .resetq(resetq), .ra(rsp), .rd(rst0), .we(rstkW), .wa(rspN), .wd(rstkD)); 39 | 40 | always @* 41 | begin 42 | // Compute the new value of st0 43 | casez ({insn[15:8]}) 44 | 8'b1??_?????: st0N = { {(`WIDTH - 15){1'b0}}, insn[14:0] }; // literal 45 | 8'b000_?????: st0N = st0; // jump 46 | 8'b010_?????: st0N = st0; // call 47 | 8'b001_?????: st0N = st1; // conditional jump 48 | 8'b011_?0000: st0N = st0; // ALU operations... 49 | 8'b011_?0001: st0N = st1; 50 | 8'b011_?0010: st0N = st0 + st1; 51 | 8'b011_?0011: st0N = st0 & st1; 52 | 8'b011_?0100: st0N = st0 | st1; 53 | 8'b011_?0101: st0N = st0 ^ st1; 54 | 8'b011_?0110: st0N = ~st0; 55 | 8'b011_?0111: st0N = {`WIDTH{(st1 == st0)}}; 56 | 8'b011_?1000: st0N = {`WIDTH{($signed(st1) < $signed(st0))}}; 57 | `ifdef NOSHIFTER // `define NOSHIFTER in common.h to cut slice usage in half and shift by 1 only 58 | 8'b011_?1001: st0N = st1 >> 1; 59 | 8'b011_?1010: st0N = st1 << 1; 60 | `else // otherwise shift by 1-any number of bits 61 | 8'b011_?1001: st0N = st1 >> st0[4:0]; 62 | 8'b011_?1010: st0N = st1 << st0[4:0]; 63 | `endif 64 | 8'b011_?1011: st0N = rst0; 65 | 8'b011_?1100: st0N = mem_din; 66 | 8'b011_?1101: st0N = io_din; 67 | 8'b011_?1110: st0N = {{(`WIDTH - 8){1'b0}}, rsp, dsp}; 68 | 8'b011_?1111: st0N = {`WIDTH{(st1 < st0)}}; 69 | default: st0N = {`WIDTH{1'bx}}; 70 | endcase 71 | end 72 | 73 | wire func_T_N = (insn[6:4] == 1); 74 | wire func_T_R = (insn[6:4] == 2); 75 | wire func_write = (insn[6:4] == 3); 76 | wire func_iow = (insn[6:4] == 4); 77 | 78 | wire is_alu = (insn[15:13] == 3'b011); 79 | assign mem_wr = !reboot & is_alu & func_write; 80 | assign dout = st1; 81 | assign io_wr = !reboot & is_alu & func_iow; 82 | 83 | assign rstkD = (insn[13] == 1'b0) ? {{(`WIDTH - 14){1'b0}}, pc_plus_1, 1'b0} : st0; 84 | 85 | reg [`DEPTH-1:0] dspI, rspI; 86 | always @* 87 | begin 88 | casez ({insn[15:13]}) 89 | 3'b1??: {dstkW, dspI} = {1'b1, 4'b0001}; 90 | 3'b001: {dstkW, dspI} = {1'b0, 4'b1111}; 91 | 3'b011: {dstkW, dspI} = {func_T_N, {insn[1], insn[1], insn[1:0]}}; 92 | default: {dstkW, dspI} = {1'b0, 4'b0000}; 93 | endcase 94 | dspN = dsp + dspI; 95 | 96 | casez ({insn[15:13]}) 97 | 3'b010: {rstkW, rspI} = {1'b1, 4'b0001}; 98 | 3'b011: {rstkW, rspI} = {func_T_R, {insn[3], insn[3], insn[3:2]}}; 99 | default: {rstkW, rspI} = {1'b0, 4'b0000}; 100 | endcase 101 | rspN = rsp + rspI; 102 | 103 | casez ({reboot, insn[15:13], insn[7], |st0}) 104 | 6'b1_???_?_?: pcN = 0; 105 | 6'b0_000_?_?, 106 | 6'b0_010_?_?, 107 | 6'b0_001_?_0: pcN = insn[12:0]; 108 | 6'b0_011_1_?: pcN = rst0[13:1]; 109 | default: pcN = pc_plus_1; 110 | endcase 111 | end 112 | 113 | always @(negedge resetq or posedge clk) 114 | begin 115 | if (!resetq) begin 116 | reboot <= 1'b1; 117 | { pc, dsp, st0, rsp } <= 0; 118 | end else begin 119 | reboot <= 0; 120 | { pc, dsp, st0, rsp } <= { pcN, dspN, st0N, rspN }; 121 | end 122 | end 123 | endmodule 124 | -------------------------------------------------------------------------------- /verilog/uart.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module baudgen( 4 | input wire clk, 5 | input wire resetq, 6 | input wire [31:0] baud, 7 | input wire restart, 8 | output wire ser_clk); 9 | parameter CLKFREQ = 1000000; 10 | 11 | wire [38:0] aclkfreq = CLKFREQ; 12 | reg [38:0] d; 13 | wire [38:0] dInc = d[38] ? ({4'd0, baud}) : (({4'd0, baud}) - aclkfreq); 14 | wire [38:0] dN = restart ? 0 : (d + dInc); 15 | wire fastclk = ~d[38]; 16 | assign ser_clk = fastclk; 17 | 18 | always @(negedge resetq or posedge clk) 19 | begin 20 | if (!resetq) begin 21 | d <= 0; 22 | end else begin 23 | d <= dN; 24 | end 25 | end 26 | endmodule 27 | 28 | /* 29 | 30 | -----+ +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- 31 | | | | | | | | | | | | | 32 | |start| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |stop1|stop2| 33 | | | | | | | | | | | | ? | 34 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+ + 35 | 36 | */ 37 | 38 | module uart( 39 | input wire clk, // System clock 40 | input wire resetq, 41 | 42 | // Outputs 43 | output wire uart_busy, // High means UART is transmitting 44 | output reg uart_tx, // UART transmit wire 45 | // Inputs 46 | input wire [31:0] baud, 47 | input wire uart_wr_i, // Raise to transmit byte 48 | input wire [7:0] uart_dat_i // 8-bit data 49 | ); 50 | parameter CLKFREQ = 1000000; 51 | 52 | reg [3:0] bitcount; 53 | reg [8:0] shifter; 54 | 55 | assign uart_busy = |bitcount; 56 | wire sending = |bitcount; 57 | 58 | wire ser_clk; 59 | 60 | wire starting = uart_wr_i & ~uart_busy; 61 | baudgen #(.CLKFREQ(CLKFREQ)) _baudgen( 62 | .clk(clk), 63 | .resetq(resetq), 64 | .baud(baud), 65 | .restart(1'b0), 66 | .ser_clk(ser_clk)); 67 | 68 | always @(negedge resetq or posedge clk) 69 | begin 70 | if (!resetq) begin 71 | uart_tx <= 1; 72 | bitcount <= 0; 73 | shifter <= 0; 74 | end else begin 75 | if (starting) begin 76 | shifter <= { uart_dat_i[7:0], 1'b0 }; 77 | bitcount <= 1 + 8 + 1; 78 | end 79 | 80 | if (sending & ser_clk) begin 81 | { shifter, uart_tx } <= { 1'b1, shifter }; 82 | bitcount <= bitcount - 4'd1; 83 | end 84 | end 85 | end 86 | 87 | endmodule 88 | 89 | module rxuart( 90 | input wire clk, 91 | input wire resetq, 92 | input wire [31:0] baud, 93 | input wire uart_rx, // UART recv wire 94 | input wire rd, // read strobe 95 | output wire valid, // has data 96 | output wire [7:0] data); // data 97 | parameter CLKFREQ = 1000000; 98 | 99 | reg [4:0] bitcount; 100 | reg [7:0] shifter; 101 | 102 | // On starting edge, wait 3 half-bits then sample, and sample every 2 bits thereafter 103 | 104 | wire idle = &bitcount; 105 | wire sample; 106 | reg [2:0] hh = 3'b111; 107 | wire [2:0] hhN = {hh[1:0], uart_rx}; 108 | wire startbit = idle & (hhN[2:1] == 2'b10); 109 | wire [7:0] shifterN = sample ? {hh[1], shifter[7:1]} : shifter; 110 | 111 | wire ser_clk; 112 | baudgen #(.CLKFREQ(CLKFREQ)) _baudgen( 113 | .clk(clk), 114 | .baud({baud[30:0], 1'b0}), 115 | .resetq(resetq), 116 | .restart(startbit), 117 | .ser_clk(ser_clk)); 118 | 119 | assign valid = (bitcount == 18); 120 | reg [4:0] bitcountN; 121 | always @* 122 | if (startbit) 123 | bitcountN = 0; 124 | else if (!idle & !valid & ser_clk) 125 | bitcountN = bitcount + 5'd1; 126 | else if (valid & rd) 127 | bitcountN = 5'b11111; 128 | else 129 | bitcountN = bitcount; 130 | 131 | // 3,5,7,9,11,13,15,17 132 | assign sample = (bitcount > 2) & bitcount[0] & !valid & ser_clk; 133 | assign data = shifter; 134 | 135 | always @(negedge resetq or posedge clk) 136 | begin 137 | if (!resetq) begin 138 | hh <= 3'b111; 139 | bitcount <= 5'b11111; 140 | shifter <= 0; 141 | end else begin 142 | hh <= hhN; 143 | bitcount <= bitcountN; 144 | shifter <= shifterN; 145 | end 146 | end 147 | endmodule 148 | 149 | module buart( 150 | input wire clk, 151 | input wire resetq, 152 | input wire [31:0] baud, 153 | input wire rx, // recv wire 154 | output wire tx, // xmit wire 155 | input wire rd, // read strobe 156 | input wire wr, // write strobe 157 | output wire valid, // has recv data 158 | output wire busy, // is transmitting 159 | input wire [7:0] tx_data, 160 | output wire [7:0] rx_data // data 161 | ); 162 | parameter CLKFREQ = 1000000; 163 | 164 | rxuart #(.CLKFREQ(CLKFREQ)) _rx ( 165 | .clk(clk), 166 | .resetq(resetq), 167 | .baud(baud), 168 | .uart_rx(rx), 169 | .rd(rd), 170 | .valid(valid), 171 | .data(rx_data)); 172 | uart #(.CLKFREQ(CLKFREQ)) _tx ( 173 | .clk(clk), 174 | .resetq(resetq), 175 | .baud(baud), 176 | .uart_busy(busy), 177 | .uart_tx(tx), 178 | .uart_wr_i(wr), 179 | .uart_dat_i(tx_data)); 180 | endmodule 181 | -------------------------------------------------------------------------------- /verilog/xilinx-top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | 4 | module bram_tdp #( 5 | parameter DATA = 72, 6 | parameter ADDR = 10 7 | ) ( 8 | // Port A 9 | input wire a_clk, 10 | input wire a_wr, 11 | input wire [ADDR-1:0] a_addr, 12 | input wire [DATA-1:0] a_din, 13 | output reg [DATA-1:0] a_dout, 14 | 15 | // Port B 16 | input wire b_clk, 17 | input wire b_wr, 18 | input wire [ADDR-1:0] b_addr, 19 | input wire [DATA-1:0] b_din, 20 | output reg [DATA-1:0] b_dout 21 | ); 22 | 23 | // Shared memory 24 | reg [DATA-1:0] mem [(2**ADDR)-1:0]; 25 | initial begin 26 | $readmemh("../build/firmware/demo0.hex", mem); 27 | end 28 | 29 | // Port A 30 | always @(posedge a_clk) begin 31 | a_dout <= mem[a_addr]; 32 | if(a_wr) begin 33 | a_dout <= a_din; 34 | mem[a_addr] <= a_din; 35 | end 36 | end 37 | 38 | // Port B 39 | always @(posedge b_clk) begin 40 | b_dout <= mem[b_addr]; 41 | if(b_wr) begin 42 | b_dout <= b_din; 43 | mem[b_addr] <= b_din; 44 | end 45 | end 46 | 47 | endmodule 48 | 49 | // A 16Kbyte RAM (4096x32) with one write port and one read port 50 | module ram16k0( 51 | input wire clk, 52 | 53 | input wire[15:0] a_addr, 54 | output wire[31:0] a_q, 55 | input wire[31:0] a_d, 56 | input wire a_wr, 57 | 58 | input wire[12:0] b_addr, 59 | output wire[15:0] b_q); 60 | 61 | //synthesis attribute ram_style of mem is block 62 | reg [31:0] mem[0:4095]; //pragma attribute mem ram_block TRUE 63 | initial begin 64 | $readmemh("../build/firmware/demo0.hex", mem); 65 | end 66 | 67 | always @ (posedge clk) 68 | if (a_wr) 69 | mem[a_addr[13:2]] <= a_d; 70 | 71 | reg [15:0] a_addr_; 72 | always @ (posedge clk) 73 | a_addr_ <= a_addr; 74 | assign a_q = mem[a_addr_[13:2]]; 75 | 76 | reg [12:0] raddr_reg; 77 | always @ (posedge clk) 78 | raddr_reg <= b_addr; 79 | wire [31:0] insn32 = mem[raddr_reg[12:1]]; 80 | assign b_q = raddr_reg[0] ? insn32[31:16] : insn32[15:0]; 81 | endmodule 82 | 83 | module ram16k( 84 | input wire clk, 85 | 86 | input wire[15:0] a_addr, 87 | output wire[31:0] a_q, 88 | input wire[31:0] a_d, 89 | input wire a_wr, 90 | 91 | input wire[12:0] b_addr, 92 | output wire[15:0] b_q); 93 | 94 | wire [31:0] insn32; 95 | 96 | bram_tdp #(.DATA(32), .ADDR(12)) nram ( 97 | .a_clk(clk), 98 | .a_wr(a_wr), 99 | .a_addr(a_addr[13:2]), 100 | .a_din(a_d), 101 | .a_dout(a_q), 102 | 103 | .b_clk(clk), 104 | .b_wr(1'b0), 105 | .b_addr(b_addr[12:1]), 106 | .b_din(32'd0), 107 | .b_dout(insn32)); 108 | 109 | reg ba_; 110 | always @(posedge clk) 111 | ba_ <= b_addr[0]; 112 | assign b_q = ba_ ? insn32[31:16] : insn32[15:0]; 113 | 114 | endmodule 115 | 116 | 117 | module top( 118 | input wire CLK, 119 | output wire DUO_LED, 120 | input wire DUO_SW1, 121 | input wire RXD, 122 | output wire TXD, 123 | input wire DTR 124 | ); 125 | localparam MHZ = 40; 126 | 127 | wire fclk; 128 | 129 | DCM_CLKGEN #( 130 | .CLKFX_MD_MAX(0.0), // Specify maximum M/D ratio for timing anlysis 131 | .CLKFX_DIVIDE(32), // Divide value - D - (1-256) 132 | .CLKFX_MULTIPLY(MHZ), // Multiply value - M - (2-256) 133 | .CLKIN_PERIOD(31.25), // Input clock period specified in nS 134 | .STARTUP_WAIT("FALSE") // Delay config DONE until DCM_CLKGEN LOCKED (TRUE/FALSE) 135 | ) 136 | DCM_CLKGEN_inst ( 137 | .CLKFX(fclk), // 1-bit output: Generated clock output 138 | .CLKIN(CLK), // 1-bit input: Input clock 139 | .FREEZEDCM(0), // 1-bit input: Prevents frequency adjustments to input clock 140 | .PROGCLK(0), // 1-bit input: Clock input for M/D reconfiguration 141 | .PROGDATA(0), // 1-bit input: Serial data input for M/D reconfiguration 142 | .PROGEN(0), // 1-bit input: Active high program enable 143 | .RST(0) // 1-bit input: Reset input pin 144 | ); 145 | 146 | reg [25:0] counter; 147 | always @(posedge fclk) 148 | counter <= counter + 26'd1; 149 | assign DUO_LED = counter[25]; 150 | 151 | // ------------------------------------------------------------------------ 152 | 153 | wire uart0_valid, uart0_busy; 154 | wire [7:0] uart0_data; 155 | wire uart0_rd, uart0_wr; 156 | reg [31:0] baud = 32'd115200; 157 | wire UART0_RX; 158 | buart #(.CLKFREQ(MHZ * 1000000)) _uart0 ( 159 | .clk(fclk), 160 | .resetq(1'b1), 161 | .baud(baud), 162 | .rx(RXD), 163 | .tx(TXD), 164 | .rd(uart0_rd), 165 | .wr(uart0_wr), 166 | .valid(uart0_valid), 167 | .busy(uart0_busy), 168 | .tx_data(dout_[7:0]), 169 | .rx_data(uart0_data)); 170 | 171 | wire [15:0] mem_addr; 172 | wire [31:0] mem_din; 173 | wire mem_wr; 174 | wire [31:0] dout; 175 | 176 | wire [12:0] code_addr; 177 | wire [15:0] insn; 178 | 179 | wire io_wr; 180 | 181 | wire resetq = DTR; 182 | 183 | j1 _j1 ( 184 | .clk(fclk), 185 | .resetq(resetq), 186 | 187 | .io_wr(io_wr), 188 | .mem_addr(mem_addr), 189 | .mem_wr(mem_wr), 190 | .mem_din(mem_din), 191 | .dout(dout), 192 | .io_din({16'd0, uart0_data, 4'd0, DTR, uart0_valid, uart0_busy, DUO_SW1}), 193 | 194 | .code_addr(code_addr), 195 | .insn(insn) 196 | ); 197 | 198 | ram16k ram(.clk(fclk), 199 | .a_addr(mem_addr), 200 | .a_q(mem_din), 201 | .a_wr(mem_wr), 202 | .a_d(dout), 203 | .b_addr(code_addr), 204 | .b_q(insn)); 205 | 206 | reg io_wr_; 207 | reg [15:0] mem_addr_; 208 | reg [31:0] dout_; 209 | always @(posedge fclk) 210 | {io_wr_, mem_addr_, dout_} <= {io_wr, mem_addr, dout}; 211 | 212 | assign uart0_wr = io_wr_ & (mem_addr_ == 16'h0000); 213 | assign uart0_rd = io_wr_ & (mem_addr_ == 16'h0002); 214 | 215 | endmodule 216 | -------------------------------------------------------------------------------- /xilinx/xilinx.mk: -------------------------------------------------------------------------------- 1 | # The top level module should define the variables below then include 2 | # this file. The files listed should be in the same directory as the 3 | # Makefile. 4 | # 5 | # variable description 6 | # ---------- ------------- 7 | # project project name (top level module should match this name) 8 | # top_module top level module of the project 9 | # libdir path to library directory 10 | # libs library modules used 11 | # vfiles all local .v files 12 | # xilinx_cores all local .xco files 13 | # vendor vendor of FPGA (xilinx, altera, etc.) 14 | # family FPGA device family (spartan3e) 15 | # part FPGA part name (xc4vfx12-10-sf363) 16 | # flashsize size of flash for mcs file (16384) 17 | # optfile (optional) xst extra opttions file to put in .scr 18 | # map_opts (optional) options to give to map 19 | # par_opts (optional) options to give to par 20 | # intstyle (optional) intstyle option to all tools 21 | # 22 | # files description 23 | # ---------- ------------ 24 | # $(project).ucf ucf file 25 | # 26 | # Library modules should have a modules.mk in their root directory, 27 | # namely $(libdir)//module.mk, that simply adds to the vfiles 28 | # and xilinx_cores variable. 29 | # 30 | # all the .xco files listed in xilinx_cores will be generated with core, with 31 | # the resulting .v and .ngc files placed back in the same directory as 32 | # the .xco file. 33 | # 34 | # TODO: .xco files are device dependant, should use a template based system 35 | 36 | coregen_work_dir ?= ./coregen-tmp 37 | map_opts ?= -timing -ol high -detail -pr b -register_duplication -w 38 | par_opts ?= -ol high 39 | isedir ?= /data/Xilinx/14.7/ISE_DS 40 | xil_env ?= . $(isedir)/settings64.sh 41 | flashsize ?= 8192 42 | 43 | libmks = $(patsubst %,$(libdir)/%/module.mk,$(libs)) 44 | mkfiles = Makefile $(libmks) xilinx.mk 45 | include $(libmks) 46 | 47 | corengcs = $(foreach core,$(xilinx_cores),$(core:.xco=.ngc)) 48 | local_corengcs = $(foreach ngc,$(corengcs),$(notdir $(ngc))) 49 | vfiles += $(foreach core,$(xilinx_cores),$(core:.xco=.v)) 50 | junk += $(local_corengcs) 51 | 52 | .PHONY: default xilinx_cores clean twr etwr 53 | default: $(project).bit $(project).mcs 54 | xilinx_cores: $(corengcs) 55 | twr: $(project).twr 56 | etwr: $(project)_err.twr 57 | 58 | define cp_template 59 | $(2): $(1) 60 | cp $(1) $(2) 61 | endef 62 | $(foreach ngc,$(corengcs),$(eval $(call cp_template,$(ngc),$(notdir $(ngc))))) 63 | 64 | %.ngc %.v: %.xco 65 | @echo "=== rebuilding $@" 66 | if [ -d $(coregen_work_dir) ]; then \ 67 | rm -rf $(coregen_work_dir)/*; \ 68 | else \ 69 | mkdir -p $(coregen_work_dir); \ 70 | fi 71 | cd $(coregen_work_dir); \ 72 | $(xil_env); \ 73 | coregen -b $$OLDPWD/$<; \ 74 | cd - 75 | xcodir=`dirname $<`; \ 76 | basename=`basename $< .xco`; \ 77 | if [ ! -r $(coregen_work_dir/$$basename.ngc) ]; then \ 78 | echo "'$@' wasn't created."; \ 79 | exit 1; \ 80 | else \ 81 | cp $(coregen_work_dir)/$$basename.v $(coregen_work_dir)/$$basename.ngc $$xcodir; \ 82 | fi 83 | junk += $(coregen_work_dir) 84 | 85 | date = $(shell date +%F-%H-%M) 86 | 87 | # some common junk 88 | junk += *.xrpt 89 | 90 | programming_files: $(project).bit $(project).mcs 91 | mkdir -p $@/$(date) 92 | mkdir -p $@/latest 93 | for x in .bit .mcs .cfi _bd.bmm; do cp $(project)$$x $@/$(date)/$(project)$$x; cp $(project)$$x $@/latest/$(project)$$x; done 94 | $(xil_env); xst -help | head -1 | sed 's/^/#/' | cat - $(project).scr > $@/$(date)/$(project).scr 95 | 96 | $(project).mcs: $(project).bit 97 | $(xil_env); \ 98 | promgen -w -s $(flashsize) -p mcs -o $@ -u 0 $^ 99 | junk += $(project).mcs $(project).cfi $(project).prm 100 | 101 | $(project).bit: $(project)_par.ncd 102 | $(xil_env); \ 103 | bitgen $(intstyle) -g UserID:0x09470947 -g DriveDone:yes -g StartupClk:Cclk -w $(project)_par.ncd $(project).bit 104 | # bitgen $(intstyle) -g compress -g UserID:0x09470947 -g DriveDone:yes -g StartupClk:Cclk -w $(project)_par.ncd $(project).bit 105 | # bitgen $(intstyle) -g UserID:0x09470947 -g DriveDone:yes -g StartupClk:Cclk -w $(project)_par.ncd $(project).bit 106 | junk += $(project).bgn $(project).bit $(project).drc $(project)_bd.bmm 107 | 108 | 109 | $(project)_par.ncd: $(project).ncd 110 | $(xil_env); \ 111 | if par $(intstyle) $(par_opts) -w $(project).ncd $(project)_par.ncd; then \ 112 | :; \ 113 | else \ 114 | $(MAKE) etwr; \ 115 | fi 116 | junk += $(project)_par.ncd $(project)_par.par $(project)_par.pad 117 | junk += $(project)_par_pad.csv $(project)_par_pad.txt 118 | junk += $(project)_par.grf $(project)_par.ptwx 119 | junk += $(project)_par.unroutes $(project)_par.xpi 120 | 121 | $(project).ncd: $(project).ngd 122 | if [ -r $(project)_par.ncd ]; then \ 123 | cp $(project)_par.ncd smartguide.ncd; \ 124 | smartguide="-smartguide smartguide.ncd"; \ 125 | else \ 126 | smartguide=""; \ 127 | fi; \ 128 | $(xil_env); \ 129 | map $(intstyle) $(map_opts) $$smartguide $< 130 | junk += $(project).ncd $(project).pcf $(project).ngm $(project).mrp $(project).map 131 | junk += smartguide.ncd $(project).psr 132 | junk += $(project)_summary.xml $(project)_usage.xml 133 | 134 | $(project).ngd: $(project).ngc $(project).ucf $(project).bmm 135 | $(xil_env); ngdbuild $(intstyle) $(project).ngc -bm $(project).bmm 136 | junk += $(project).ngd $(project).bld 137 | 138 | $(project).ngc: $(vfiles) $(local_corengcs) $(project).scr $(project).prj 139 | $(xil_env); xst $(intstyle) -ifn $(project).scr 140 | junk += xlnx_auto* $(top_module).lso $(project).srp 141 | junk += netlist.lst xst $(project).ngc 142 | 143 | $(project).prj: $(vfiles) $(mkfiles) 144 | for src in $(vfiles); do echo "verilog work $$src" >> $(project).tmpprj; done 145 | sort -u $(project).tmpprj > $(project).prj 146 | rm -f $(project).tmpprj 147 | junk += $(project).prj 148 | 149 | optfile += $(wildcard $(project).opt) 150 | top_module ?= $(project) 151 | $(project).scr: $(optfile) $(mkfiles) ./xilinx.opt 152 | echo "run" > $@ 153 | echo "-p $(part)" >> $@ 154 | echo "-top $(top_module)" >> $@ 155 | echo "-ifn $(project).prj" >> $@ 156 | echo "-ofn $(project).ngc" >> $@ 157 | cat ./xilinx.opt $(optfile) >> $@ 158 | junk += $(project).scr 159 | 160 | $(project).post_map.twr: $(project).ncd 161 | $(xil_env); trce -e 10 $< $(project).pcf -o $@ 162 | junk += $(project).post_map.twr $(project).post_map.twx smartpreview.twr 163 | 164 | $(project).twr: $(project)_par.ncd 165 | $(xil_env); trce $< $(project).pcf -o $(project).twr 166 | junk += $(project).twr $(project).twx smartpreview.twr 167 | 168 | $(project)_err.twr: $(project)_par.ncd 169 | $(xil_env); trce -e 10 $< $(project).pcf -o $(project)_err.twr 170 | junk += $(project)_err.twr $(project)_err.twx 171 | 172 | .gitignore: $(mkfiles) 173 | echo programming_files $(junk) | sed 's, ,\n,g' > .gitignore 174 | 175 | clean:: 176 | rm -rf $(junk) 177 | -------------------------------------------------------------------------------- /toolchain/cross.fs: -------------------------------------------------------------------------------- 1 | ( J1 Cross Compiler JCB 16:55 05/02/12) 2 | 3 | \ Usage gforth cross.fs 4 | \ 5 | \ Where machine.fs defines the target machine 6 | \ and program.fs is the target program 7 | \ 8 | 9 | variable lst \ .lst output file handle 10 | 11 | : h# 12 | base @ >r 16 base ! 13 | 0. bl parse >number throw 2drop postpone literal 14 | r> base ! ; immediate 15 | 16 | : tcell 2 ; 17 | : tcells tcell * ; 18 | : tcell+ tcell + ; 19 | 20 | 131072 allocate throw constant tflash \ bytes, target flash 21 | 131072 allocate throw constant _tbranches \ branch targets, cells 22 | tflash 131072 0 fill 23 | _tbranches 131072 0 fill 24 | : tbranches cells _tbranches + ; 25 | 26 | variable tdp 0 tdp ! 27 | : there tdp @ ; 28 | : islegal ; 29 | : tc! islegal tflash + c! ; 30 | : tc@ islegal tflash + c@ ; 31 | : tw! islegal tflash + w! ; 32 | : t! islegal tflash + l! ; 33 | : t@ islegal tflash + uw@ ; 34 | : twalign tdp @ 1+ -2 and tdp ! ; 35 | : talign tdp @ 3 + -4 and tdp ! ; 36 | : tc, there tc! 1 tdp +! ; 37 | : t, there t! 4 tdp +! ; 38 | : tw, there tw! tcell tdp +! ; 39 | : org tdp ! ; 40 | 41 | wordlist constant target-wordlist 42 | : add-order ( wid -- ) >r get-order r> swap 1+ set-order ; 43 | : :: get-current >r target-wordlist set-current : r> set-current ; 44 | 45 | next-arg included \ include the machine.fs 46 | 47 | ( Language basics for target JCB 19:08 05/02/12) 48 | 49 | warnings off 50 | :: ( postpone ( ; 51 | :: \ postpone \ ; 52 | 53 | :: org org ; 54 | :: include include ; 55 | :: included included ; 56 | :: marker marker ; 57 | :: [if] postpone [if] ; 58 | :: [else] postpone [else] ; 59 | :: [then] postpone [then] ; 60 | 61 | : literal 62 | \ dup $f rshift over $e rshift xor 1 and throw 63 | dup h# 8000 and if 64 | h# ffff xor recurse 65 | ~T alu 66 | else 67 | h# 8000 or tw, 68 | then 69 | ; 70 | 71 | : literal 72 | dup $80000000 and if 73 | invert recurse 74 | ~T alu 75 | else 76 | dup $ffff8000 and if 77 | dup $F rshift recurse 78 | $f recurse 79 | N<in @ >r bl word count r> >in ! 94 | ; 95 | 96 | variable link 0 link ! 97 | 98 | :: header 99 | twalign there 100 | \ cr ." link is " link @ . 101 | link @ tw, 102 | link ! 103 | bl parse 104 | dup tc, 105 | bounds do 106 | i c@ tc, 107 | loop 108 | twalign 109 | ; 110 | 111 | :: header-imm 112 | twalign there 113 | link @ 1+ tw, 114 | link ! 115 | bl parse 116 | dup tc, 117 | bounds do 118 | i c@ tc, 119 | loop 120 | twalign 121 | ; 122 | 123 | variable wordstart 124 | 125 | :: : 126 | hex 127 | there s>d 128 | <# bl hold # # # # #> 129 | lst @ write-file throw 130 | wordstr lst @ write-line throw 131 | 132 | there wordstart ! 133 | create codeptr , 134 | does> @ scall 135 | 136 | ; 137 | 138 | :: :noname 139 | ; 140 | 141 | :: , 142 | talign 143 | t, 144 | ; 145 | 146 | :: allot 147 | 0 ?do 148 | 0 tc, 149 | loop 150 | ; 151 | 152 | : shortcut ( orig -- f ) \ insn @orig precedes ;. Shortcut it. 153 | \ call becomes jump 154 | dup t@ h# e000 and h# 4000 = if 155 | dup t@ h# 1fff and over tw! 156 | true 157 | else 158 | dup t@ h# e00c and h# 6000 = if 159 | dup t@ h# 0080 or r-1 over tw! 160 | true 161 | else 162 | false 163 | then 164 | then 165 | nip 166 | ; 167 | 168 | :: ; 169 | there wordstart @ = if 170 | s" exit" evaluate 171 | else 172 | there 2 - shortcut \ true if shortcut applied 173 | there 0 do 174 | i tbranches @ there = if 175 | i tbranches @ shortcut and 176 | then 177 | loop 178 | 0= if \ not all shortcuts worked 179 | s" exit" evaluate 180 | then 181 | then 182 | ; 183 | 184 | :: ;fallthru ; 185 | 186 | :: jmp 187 | ' >body @ ubranch 188 | ; 189 | 190 | :: constant 191 | create , 192 | does> @ literal 193 | ; 194 | 195 | :: create 196 | talign 197 | create there , 198 | does> @ literal 199 | ; 200 | 201 | ( Switching between target and meta JCB 19:08 05/02/12) 202 | 203 | : target only target-wordlist add-order definitions ; 204 | : ] target ; 205 | :: meta forth definitions ; 206 | :: [ forth definitions ; 207 | 208 | : t' bl parse target-wordlist search-wordlist 0= throw >body @ ; 209 | 210 | ( eforth's way of handling constants JCB 13:12 09/03/10) 211 | 212 | : sign>number ( c-addr1 u1 -- ud2 c-addr2 u2 ) 213 | 0. 2swap 214 | over c@ [char] - = if 215 | 1 /string 216 | >number 217 | 2swap dnegate 2swap 218 | else 219 | >number 220 | then 221 | ; 222 | 223 | : base>number ( caddr u base -- ) 224 | base @ >r base ! 225 | sign>number 226 | r> base ! 227 | dup 0= if 228 | 2drop drop literal 229 | else 230 | 1 = swap c@ [char] . = and if 231 | drop dup literal 32 rshift literal 232 | else 233 | -1 abort" bad number" 234 | then 235 | then ; 236 | warnings on 237 | 238 | :: d# bl parse 10 base>number ; 239 | :: h# bl parse 16 base>number ; 240 | :: ['] ' >body @ 2* literal ; 241 | :: [char] char literal ; 242 | 243 | :: asm-0branch 244 | ' >body @ 245 | 0branch 246 | ; 247 | 248 | ( Conditionals JCB 13:12 09/03/10) 249 | 250 | : resolve ( orig -- ) 251 | there over tbranches ! \ forward reference from orig to this loc 252 | dup t@ there 2/ or swap tw! 253 | ; 254 | 255 | :: if 256 | there 257 | 0 0branch 258 | ; 259 | 260 | :: then 261 | resolve 262 | ; 263 | 264 | :: else 265 | there 266 | 0 ubranch 267 | swap resolve 268 | ; 269 | 270 | :: begin there ; 271 | 272 | :: again ( dest -- ) 273 | 2/ ubranch 274 | ; 275 | :: until 276 | 2/ 0branch 277 | ; 278 | :: while 279 | there 280 | 0 0branch 281 | ; 282 | :: repeat 283 | swap 2/ ubranch 284 | resolve 285 | ; 286 | 287 | 4 org 288 | : .trim ( a-addr u ) \ shorten string until it ends with '.' 289 | begin 290 | 2dup + 1- c@ [char] . <> 291 | while 292 | 1- 293 | repeat 294 | ; 295 | include strings.fs 296 | next-arg 2dup .trim >str constant prefix. 297 | : .suffix ( c-addr u -- c-addr u ) \ e.g. "bar" -> "foo.bar" 298 | >str prefix. +str str@ 299 | ; 300 | : create-output-file w/o create-file throw ; 301 | : out-suffix ( s -- h ) \ Create an output file h with suffix s 302 | >str 303 | prefix. +str 304 | s" ../build/firmware/" >str +str str@ 305 | create-output-file 306 | ; 307 | :noname 308 | s" lst" out-suffix lst ! 309 | ; execute 310 | 311 | 312 | target included \ include the program.fs 313 | 314 | [ tdp @ 0 org ] bootloader main [ org ] 315 | meta 316 | 317 | decimal 318 | 0 value file 319 | : dumpall.16 320 | s" hex" out-suffix to file 321 | 322 | hex 323 | 1024 0 do 324 | tflash i 2* + w@ 325 | s>d <# # # # # #> file write-line throw 326 | loop 327 | file close-file 328 | ; 329 | : dumpall.32 330 | s" hex" out-suffix to file 331 | 332 | hex 333 | 4096 0 do 334 | tflash i 4 * + @ 335 | s>d <# # # # # # # # # #> file write-line throw 336 | loop 337 | file close-file 338 | ; 339 | 340 | dumpall.32 341 | 342 | bye 343 | -------------------------------------------------------------------------------- /xilinx/j1-papilioduo.ucf: -------------------------------------------------------------------------------- 1 | # UCF file for the Papilio DUO board 2 | # Generated by pin_converter, written by Kevin Lindsey 3 | # https://github.com/thelonious/papilio_pins/tree/development/pin_converter 4 | 5 | # Main board wing pin [] to FPGA pin Pxx map 6 | # -------C------- -------B------- -------A------- 7 | # [GND] [C00] P114 [GND] [B00] P99 P100 [A15] 8 | # [2V5] [C01] P115 [2V5] [B01] P97 P98 [A14] 9 | # [3V3] [C02] P116 [3V3] [B02] P92 P93 [A13] 10 | # [5V0] [C03] P117 [5V0] [B03] P87 P88 [A12] 11 | # [C04] P118 [B04] P84 P85 [A11] [5V0] 12 | # [C05] P119 [B05] P82 P83 [A10] [3V3] 13 | # [C06] P120 [B06] P80 P81 [A09] [2V5] 14 | # [C07] P121 [B07] P78 P79 [A08] [GND] 15 | # [GND] [C08] P123 [GND] [B08] P74 P75 [A07] 16 | # [2V5] [C09] P124 [2V5] [B09] P95 P67 [A06] 17 | # [3V3] [C10] P126 [3V3] [B10] P62 P66 [A05] 18 | # [5V0] [C11] P127 [5V0] [B11] P59 P61 [A04] 19 | # [C12] P131 [B12] P57 P58 [A03] [5V0] 20 | # [C13] P132 [B13] P55 P56 [A02] [3V3] 21 | # [C14] P133 [B14] P50 P51 [A01] [2V5] 22 | # [C15] P134 [B15] P47 P48 [A00] [GND] 23 | 24 | ## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration. 25 | CONFIG PROHIBIT=P144; 26 | CONFIG PROHIBIT=P69; 27 | CONFIG PROHIBIT=P60; 28 | 29 | #NET "*" IOSTANDARD = LVTTL; 30 | 31 | NET CLK LOC="P94" | IOSTANDARD=LVTTL; # CLK 32 | TIMESPEC TS_Period_1 = PERIOD "CLK" 31.25 ns HIGH 50%; 33 | NET TXD LOC="P141" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; 34 | NET RXD LOC="P46" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; 35 | NET DTR LOC="P137" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 36 | 37 | // NET "fclk" PERIOD = 6 ns HIGH 50%; 38 | 39 | # 40 | # NET Arduino_0 LOC="P116" | IOSTANDARD=LVTTL; # A0 41 | # NET Arduino_1 LOC="P117" | IOSTANDARD=LVTTL; # A1 42 | # NET Arduino_2 LOC="P118" | IOSTANDARD=LVTTL; # A2 43 | # NET Arduino_3 LOC="P119" | IOSTANDARD=LVTTL; # A3 44 | # NET Arduino_4 LOC="P120" | IOSTANDARD=LVTTL; # A4 45 | # NET Arduino_5 LOC="P121" | IOSTANDARD=LVTTL; # A5 46 | # NET Arduino_6 LOC="P123" | IOSTANDARD=LVTTL; # A6 47 | # NET Arduino_7 LOC="P124" | IOSTANDARD=LVTTL; # A7 48 | # NET Arduino_8 LOC="P126" | IOSTANDARD=LVTTL; # A8 49 | # NET Arduino_9 LOC="P127" | IOSTANDARD=LVTTL; # A9 50 | # NET Arduino_10 LOC="P131" | IOSTANDARD=LVTTL; # A10 51 | # NET Arduino_11 LOC="P132" | IOSTANDARD=LVTTL; # A11 52 | # NET Arduino_12 LOC="P133" | IOSTANDARD=LVTTL; # A12 53 | # NET Arduino_13 LOC="P134" | IOSTANDARD=LVTTL; # A13 54 | # 55 | # NET Arduino_14 LOC="P115" | IOSTANDARD=LVTTL; # B0 56 | # NET Arduino_15 LOC="P114" | IOSTANDARD=LVTTL; # B1 57 | # NET Arduino_16 LOC="P112" | IOSTANDARD=LVTTL; # B2 58 | # NET Arduino_17 LOC="P111" | IOSTANDARD=LVTTL; # B3 59 | # NET Arduino_18 LOC="P105" | IOSTANDARD=LVTTL; # B4 60 | # NET Arduino_19 LOC="P102" | IOSTANDARD=LVTTL; # B5 61 | # NET Arduino_20 LOC="P101" | IOSTANDARD=LVTTL; # B6 62 | # NET Arduino_21 LOC="P100" | IOSTANDARD=LVTTL; # B7 63 | # 64 | # NET Arduino_22 LOC="P99" | IOSTANDARD=LVTTL; # C0 65 | # NET Arduino_24 LOC="P97" | IOSTANDARD=LVTTL; # C1 66 | # NET Arduino_26 LOC="P93" | IOSTANDARD=LVTTL; # C2 67 | # NET Arduino_28 LOC="P88" | IOSTANDARD=LVTTL; # C3 68 | # NET Arduino_30 LOC="P85" | IOSTANDARD=LVTTL; # C4 69 | # NET Arduino_32 LOC="P83" | IOSTANDARD=LVTTL; # C5 70 | # NET Arduino_34 LOC="P81" | IOSTANDARD=LVTTL; # C6 71 | # NET Arduino_36 LOC="P79" | IOSTANDARD=LVTTL; # C7 72 | # NET Arduino_38 LOC="P75" | IOSTANDARD=LVTTL; # C8 73 | # NET Arduino_40 LOC="P67" | IOSTANDARD=LVTTL; # C9 74 | # NET Arduino_42 LOC="P62" | IOSTANDARD=LVTTL; # C10 75 | # NET Arduino_44 LOC="P59" | IOSTANDARD=LVTTL; # C11 76 | # NET Arduino_46 LOC="P57" | IOSTANDARD=LVTTL; # C12 77 | # NET Arduino_48 LOC="P55" | IOSTANDARD=LVTTL; # C13 78 | # NET Arduino_50 LOC="P50" | IOSTANDARD=LVTTL; # C14 79 | # NET Arduino_52 LOC="P47" | IOSTANDARD=LVTTL; # C15 80 | # 81 | # NET Arduino_23 LOC="P98" | IOSTANDARD=LVTTL ; 82 | # NET Arduino_25 LOC="P95" | IOSTANDARD=LVTTL ; 83 | # NET Arduino_27 LOC="P92" | IOSTANDARD=LVTTL ; 84 | # NET Arduino_29 LOC="P87" | IOSTANDARD=LVTTL ; 85 | # NET Arduino_31 LOC="P84" | IOSTANDARD=LVTTL ; 86 | # NET Arduino_33 LOC="P82" | IOSTANDARD=LVTTL ; 87 | # NET Arduino_35 LOC="P80" | IOSTANDARD=LVTTL ; 88 | # NET Arduino_37 LOC="P78" | IOSTANDARD=LVTTL ; 89 | # NET Arduino_39 LOC="P74" | IOSTANDARD=LVTTL ; 90 | # NET Arduino_41 LOC="P66" | IOSTANDARD=LVTTL ; 91 | # NET Arduino_43 LOC="P61" | IOSTANDARD=LVTTL ; 92 | # NET Arduino_45 LOC="P58" | IOSTANDARD=LVTTL ; 93 | # NET Arduino_47 LOC="P56" | IOSTANDARD=LVTTL ; 94 | # NET Arduino_49 LOC="P51" | IOSTANDARD=LVTTL ; 95 | # NET Arduino_51 LOC="P48" | IOSTANDARD=LVTTL ; 96 | # NET Arduino_53 LOC="P39" | IOSTANDARD=LVTTL ; 97 | # 98 | # # SRAM 99 | # 100 | # NET "sram_addr<0>" LOC = "P7" | IOSTANDARD=LVTTL | SLEW=FAST; 101 | # NET "sram_addr<1>" LOC = "P8" | IOSTANDARD=LVTTL | SLEW=FAST ; 102 | # NET "sram_addr<2>" LOC = "P9" | IOSTANDARD=LVTTL | SLEW=FAST ; 103 | # NET "sram_addr<3>" LOC = "P10" | IOSTANDARD=LVTTL | SLEW=FAST ; 104 | # NET "sram_addr<4>" LOC = "P11" | IOSTANDARD=LVTTL | SLEW=FAST ; 105 | # NET "sram_addr<5>" LOC = "P5" | IOSTANDARD=LVTTL | SLEW=FAST ; 106 | # NET "sram_addr<6>" LOC = "P2" | IOSTANDARD=LVTTL | SLEW=FAST ; 107 | # NET "sram_addr<7>" LOC = "P1" | IOSTANDARD=LVTTL | SLEW=FAST ; 108 | # NET "sram_addr<8>" LOC = "P143" | IOSTANDARD=LVTTL | SLEW=FAST ; 109 | # NET "sram_addr<9>" LOC = "P142" | IOSTANDARD=LVTTL | SLEW=FAST ; 110 | # NET "sram_addr<10>" LOC = "P43" | IOSTANDARD=LVTTL | SLEW=FAST ; 111 | # NET "sram_addr<11>" LOC = "P41" | IOSTANDARD=LVTTL | SLEW=FAST ; 112 | # NET "sram_addr<12>" LOC = "P40" | IOSTANDARD=LVTTL | SLEW=FAST; 113 | # NET "sram_addr<13>" LOC = "P35" | IOSTANDARD=LVTTL | SLEW=FAST ; 114 | # NET "sram_addr<14>" LOC = "P34" | IOSTANDARD=LVTTL | SLEW=FAST ; 115 | # NET "sram_addr<15>" LOC = "P27" | IOSTANDARD=LVTTL | SLEW=FAST ; 116 | # NET "sram_addr<16>" LOC = "P29" | IOSTANDARD=LVTTL | SLEW=FAST ; 117 | # NET "sram_addr<17>" LOC = "P33" | IOSTANDARD=LVTTL | SLEW=FAST ; 118 | # NET "sram_addr<18>" LOC = "P32" | IOSTANDARD=LVTTL | SLEW=FAST ; 119 | # #NET "sram_addr<19>" LOC = "P44" | IOSTANDARD=LVTTL | SLEW=FAST ; 120 | # #NET "sram_addr<20>" LOC = "P30" | IOSTANDARD=LVTTL | SLEW=FAST ; 121 | # 122 | # # Data lines 123 | # NET "sram_data<0>" LOC = "P14" | IOSTANDARD=LVTTL | SLEW=FAST ; 124 | # NET "sram_data<1>" LOC = "P15" | IOSTANDARD=LVTTL | SLEW=FAST ; 125 | # NET "sram_data<2>" LOC = "P16" | IOSTANDARD=LVTTL | SLEW=FAST ; 126 | # NET "sram_data<3>" LOC = "P17" | IOSTANDARD=LVTTL | SLEW=FAST ; 127 | # NET "sram_data<4>" LOC = "P21" | IOSTANDARD=LVTTL | SLEW=FAST ; 128 | # NET "sram_data<5>" LOC = "P22" | IOSTANDARD=LVTTL | SLEW=FAST ; 129 | # NET "sram_data<6>" LOC = "P23" | IOSTANDARD=LVTTL | SLEW=FAST ; 130 | # NET "sram_data<7>" LOC = "P24" | IOSTANDARD=LVTTL | SLEW=FAST ; 131 | # 132 | # # Control lines 133 | # NET "sram_ce" LOC = "P12" | IOSTANDARD=LVTTL | SLEW=FAST; 134 | # NET "sram_we" LOC = "P6" | IOSTANDARD=LVTTL | SLEW=FAST ; 135 | # NET "sram_oe" LOC = "P26" | IOSTANDARD=LVTTL | SLEW=FAST; 136 | # 137 | # NET SPI_CS LOC="P38" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CS OK 138 | # NET SPI_SCK LOC="P70" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CK OK 139 | # NET SPI_MOSI LOC="P64" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_SI OK 140 | # NET SPI_MISO LOC="P65" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_SO OK 141 | # 142 | # #Dragon MPSSE 143 | # NET BD0_MPSSE_TCK LOC="P46" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 144 | # NET BD1_MPSSE_TDI LOC="P141" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 145 | # NET BD2_MPSSE_TDO LOC="P140" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 146 | # NET BD3_MPSSE_TMS LOC="P138" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 147 | # NET BD4_MPSSE_DTR LOC="P137" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 148 | # 149 | # #Arduino JTAG 150 | # NET ARD_JTAG_TDI LOC="P88" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 151 | # NET ARD_JTAG_TDO LOC="P85" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 152 | # NET ARD_JTAG_TMS LOC="P83" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 153 | # NET ARD_JTAG_TCK LOC="P81" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 154 | # 155 | # #Arduino SPI 156 | # NET ARD_SPI_MISO LOC="P133" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 157 | # NET ARD_SPI_MOSI LOC="P132" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 158 | # NET ARD_SPI_SCLK LOC="P134" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 159 | # 160 | # #Dragon SPI 161 | # NET DRAGON_SPI_GND LOC="P78" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 162 | # NET DRAGON_SPI_RESET LOC="P79" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 163 | # #NET DRAGON_SPI_RESET LOC="P79" | IOSTANDARD=LVTTL | DRIVE=8 | PULLUP | SLEW=SLOW; 164 | # NET DRAGON_SPI_MOSI LOC="P74" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 165 | # NET DRAGON_SPI_SCK LOC="P75" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 166 | # NET DRAGON_SPI_VTG LOC="P66" | IOSTANDARD=LVTTL | DRIVE=24 | SLEW=SLOW; 167 | # NET DRAGON_SPI_MISO LOC="P67" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 168 | # 169 | # #Dragon JTAG 170 | # NET DRAGON_JTAG_TCK LOC="P47" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 171 | # NET DRAGON_JTAG_GND LOC="P39" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 172 | # NET DRAGON_JTAG_TDO LOC="P50" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 173 | # NET DRAGON_JTAG_VTG LOC="P48" | IOSTANDARD=LVTTL | DRIVE=24 | SLEW=SLOW; 174 | # NET DRAGON_JTAG_TMS LOC="P55" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 175 | # NET DRAGON_JTAG_RESET LOC="P51" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 176 | # #NET DRAGON_JTAG_RESET LOC="P51" | IOSTANDARD=LVTTL | DRIVE=8 | PULLUP | SLEW=SLOW; 177 | # NET DRAGON_JTAG_TDI LOC="P59" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 178 | # NET DRAGON_JTAG_GND2 LOC="P58" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 179 | # 180 | # #Dragon Misc 181 | NET DUO_SW1 LOC="P104" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 182 | # NET ARD_RESET LOC="P139" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; # ARD_RESET 183 | NET DUO_LED LOC="P134" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; 184 | -------------------------------------------------------------------------------- /toolchain/nuc.fs: -------------------------------------------------------------------------------- 1 | header 1+ : 1+ d# 1 + ; 2 | header 1- : 1- d# -1 + ; 3 | header 0= : 0= d# 0 = ; 4 | header cell+ : cell+ d# 2 + ; 5 | 6 | header <> : <> = invert ; 7 | header > : > swap < ; 8 | header 0< : 0< d# 0 < ; 9 | header 0> : 0> d# 0 > ; 10 | header 0<> : 0<> d# 0 <> ; 11 | header u> : u> swap u< ; 12 | 13 | : eol ( u -- u' false | true ) 14 | d# -1 + 15 | dup 0= dup if 16 | ( 0 true -- ) 17 | nip 18 | then 19 | ; 20 | 21 | header ms 22 | : ms 23 | begin 24 | d# 15000 begin 25 | eol until 26 | eol until 27 | ; 28 | 29 | 30 | header key? 31 | : key? 32 | d# 0 io@ 33 | d# 4 and 34 | 0<> 35 | ; 36 | 37 | header key 38 | : key 39 | begin 40 | key? 41 | until 42 | d# 0 io@ d# 8 rshift 43 | d# 0 d# 2 io! 44 | ; 45 | 46 | : ready 47 | d# 0 io@ 48 | d# 2 and 49 | 0= 50 | ; 51 | 52 | header emit 53 | : emit 54 | begin ready until 55 | h# 0 io! 56 | ; 57 | 58 | header cr 59 | : cr 60 | d# 13 emit 61 | d# 10 emit 62 | ; 63 | 64 | header space 65 | : space 66 | d# 32 emit 67 | ; 68 | 69 | header bl 70 | : bl 71 | d# 32 72 | ; 73 | 74 | : hex1 75 | h# f and 76 | dup d# 10 < if 77 | [char] 0 78 | else 79 | d# 55 80 | then 81 | + 82 | emit 83 | ; 84 | 85 | : hex2 86 | dup d# 4 rshift hex1 hex1 87 | ; 88 | 89 | : hex4 90 | dup d# 8 rshift hex2 hex2 91 | ; 92 | 93 | : hex8 94 | dup d# 16 rshift hex4 hex4 95 | ; 96 | 97 | header . 98 | : . hex8 space ; 99 | 100 | header false : false d# 0 ; 101 | header true : true d# -1 ; 102 | header rot : rot >r swap r> swap ; 103 | header -rot : -rot swap >r swap r> ; 104 | header tuck : tuck swap over ; 105 | header 2drop : 2drop drop drop ; 106 | header ?dup : ?dup dup if dup then ; 107 | 108 | header 2dup : 2dup over over ; 109 | header +! : +! tuck @ + swap ! ; 110 | header 2swap : 2swap rot >r rot r> ; 111 | 112 | header min : min 2dup< if drop else nip then ; 113 | header max : max 2dup< if nip else drop then ; 114 | 115 | header c@ 116 | : c@ 117 | dup @ swap 118 | d# 3 and d# 3 lshift rshift 119 | d# 255 and 120 | ; 121 | 122 | : hi16 123 | d# 16 rshift d# 16 lshift 124 | ; 125 | 126 | : lo16 127 | d# 16 lshift d# 16 rshift 128 | ; 129 | 130 | header uw@ 131 | : uw@ 132 | dup @ swap 133 | d# 2 and d# 3 lshift rshift 134 | lo16 135 | ; 136 | 137 | header w! 138 | : w! ( u c-addr -- ) 139 | dup>r d# 2 and if 140 | d# 16 lshift 141 | r@ @ lo16 142 | else 143 | lo16 144 | r@ @ hi16 145 | then 146 | or r> ! 147 | ; 148 | 149 | header c! 150 | : c! ( u c-addr -- ) 151 | dup>r d# 1 and if 152 | d# 8 lshift 153 | h# 00ff 154 | else 155 | h# 00ff and 156 | h# ff00 157 | then 158 | r@ uw@ and 159 | or r> w! 160 | ; 161 | 162 | header count 163 | : count 164 | dup 1+ swap c@ 165 | ; 166 | 167 | : bounds ( a n -- a+n a ) 168 | over + swap 169 | ; 170 | 171 | header type 172 | : type 173 | bounds 174 | begin 175 | 2dupxor 176 | while 177 | dup c@ emit 178 | 1+ 179 | repeat 180 | 2drop 181 | ; 182 | 183 | create base $a , 184 | create ll 0 , 185 | create dp 0 , 186 | create tib# 0 , 187 | create >in 0 , 188 | create tib 80 allot 189 | 190 | header words : words 191 | ll uw@ 192 | begin 193 | dup 194 | while 195 | cr 196 | dup . 197 | dup cell+ 198 | count type 199 | space 200 | uw@ 201 | repeat 202 | drop 203 | ; 204 | 205 | header dump : dump ( addr u -- ) 206 | cr over hex4 207 | begin ( addr u ) 208 | ?dup 209 | while 210 | over c@ space hex2 211 | 1- swap 1+ ( u' addr' ) 212 | dup h# f and 0= if ( next line? ) 213 | cr dup hex4 214 | then 215 | swap 216 | repeat 217 | drop cr 218 | ; 219 | 220 | header negate : negate invert 1+ ; 221 | header - : - negate + ; 222 | header abs : abs dup 0< if negate then ; 223 | header 2* : 2* d# 1 lshift ; 224 | header 2/ : 2/ d# 1 rshift ; 225 | header here : here dp @ ; 226 | header depth : depth depths h# f and ; 227 | 228 | : /string 229 | dup >r - swap r> + swap 230 | ; 231 | 232 | header aligned 233 | : aligned 234 | d# 3 + d# -4 and 235 | ; 236 | 237 | : d+ ( augend . addend . -- sum . ) 238 | rot + >r ( augend addend) 239 | over + ( augend sum) 240 | dup rot ( sum sum augend) 241 | u< if ( sum) 242 | r> 1+ 243 | else 244 | r> 245 | then ( sum . ) 246 | ; 247 | 248 | : d1+ d# 1. d+ ; 249 | 250 | : dnegate 251 | invert swap invert swap 252 | d1+ 253 | ; 254 | 255 | : dabs ( d -- ud ) 256 | dup 0< if dnegate then 257 | ; 258 | 259 | : s>d dup 0< ; 260 | : m+ 261 | s>d d+ 262 | ; 263 | 264 | : snap 265 | cr depth hex2 space 266 | begin 267 | depth 268 | while 269 | . 270 | repeat 271 | cr 272 | [char] # emit 273 | begin again 274 | ; 275 | 276 | create scratch 0 , 277 | 278 | header um* 279 | : um* ( u1 u2 -- ud ) 280 | scratch ! 281 | d# 0. 282 | d# 32 begin 283 | >r 284 | 2dup d+ 285 | rot dup 0< if 286 | 2* -rot 287 | scratch @ d# 0 d+ 288 | else 289 | 2* -rot 290 | then 291 | r> eol 292 | until 293 | rot drop 294 | ; 295 | : * 296 | um* drop 297 | ; 298 | 299 | header accept 300 | : accept 301 | d# 30 emit 302 | drop dup 303 | begin 304 | key 305 | dup h# 0d xor 306 | while 307 | dup h# 0a = if 308 | drop 309 | else 310 | over c! 1+ 311 | then 312 | repeat 313 | drop swap - 314 | ; 315 | 316 | : 3rd >r over r> swap ; 317 | : 3dup 3rd 3rd 3rd ; 318 | 319 | : sameword ( c-addr u wp -- c-addr u wp flag ) 320 | 2dup d# 2 + c@ = if 321 | 3dup 322 | d# 3 + >r 323 | bounds 324 | begin 325 | 2dupxor 326 | while 327 | dup c@ r@ c@ <> if 328 | 2drop rdrop false exit 329 | then 330 | 1+ 331 | r> 1+ >r 332 | repeat 333 | 2drop rdrop true 334 | else 335 | false 336 | then 337 | ; 338 | 339 | \ lsb 0 means non-immediate, return -1 340 | \ 1 means immediate, return 1 341 | : isimmediate ( wp -- -1 | 1 ) 342 | uw@ d# 1 and 2* 1- 343 | ; 344 | 345 | : sfind 346 | ll uw@ 347 | begin 348 | dup 349 | while 350 | sameword 351 | if 352 | nip nip 353 | dup 354 | d# 2 + 355 | count + 356 | d# 1 + d# -2 and 357 | swap isimmediate 358 | exit 359 | then 360 | uw@ 361 | repeat 362 | ; 363 | 364 | : digit? ( c -- u f ) 365 | dup h# 39 > h# 100 and + 366 | dup h# 140 > h# 107 and - h# 30 - 367 | dup base @ u< 368 | ; 369 | 370 | : ud* ( ud1 u -- ud2 ) \ ud2 is the product of ud1 and u 371 | tuck * >r 372 | um* r> + 373 | ; 374 | 375 | : >number ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 ) 376 | begin 377 | dup 378 | while 379 | over c@ digit? 380 | 0= if drop exit then 381 | >r 2swap base @ ud* 382 | r> m+ 2swap 383 | d# 1 /string 384 | repeat 385 | ; 386 | 387 | header fill 388 | : fill ( c-addr u char -- ) ( 6.1.1540 ) 389 | >r bounds 390 | begin 391 | 2dupxor 392 | while 393 | r@ over c! 1+ 394 | repeat 395 | r> drop 2drop 396 | ; 397 | 398 | header erase 399 | : erase 400 | d# 0 fill 401 | ; 402 | 403 | header execute 404 | : execute 405 | >r 406 | ; 407 | 408 | header source 409 | : source 410 | tib tib# @ 411 | ; 412 | 413 | \ From Forth200x - public domain 414 | 415 | : isspace? ( c -- f ) 416 | bl 1+ u< ; 417 | 418 | : isnotspace? ( c -- f ) 419 | isspace? 0= ; 420 | 421 | : xt-skip ( addr1 n1 xt -- addr2 n2 ) \ gforth 422 | \ skip all characters satisfying xt ( c -- f ) 423 | >r 424 | BEGIN 425 | over c@ r@ execute 426 | over 0<> and 427 | WHILE 428 | d# 1 /string 429 | REPEAT 430 | r> drop ; 431 | 432 | : parse-name ( "name" -- c-addr u ) 433 | source >in @ /string 434 | ['] isspace? xt-skip over >r 435 | ['] isnotspace? xt-skip ( end-word restlen r: start-word ) 436 | 2dup d# 1 min + source drop - >in ! 437 | drop r> tuck - ; 438 | 439 | header ! :noname ! ; 440 | header + :noname + ; 441 | header xor :noname xor ; 442 | header and :noname and ; 443 | header or :noname or ; 444 | header invert :noname invert ; 445 | header = :noname = ; 446 | header < :noname < ; 447 | header u< :noname u< ; 448 | header swap :noname swap ; 449 | header dup :noname dup ; 450 | header drop :noname drop ; 451 | header over :noname over ; 452 | header nip :noname nip ; 453 | header @ :noname @ ; 454 | header io! :noname io! ; 455 | header rshift :noname rshift ; 456 | header lshift :noname lshift ; 457 | \ 458 | \ \ >r 459 | \ \ r> 460 | \ \ r@ 461 | \ \ exit 462 | \ 463 | 464 | : xmain 465 | cr d# 1 ms cr 466 | d# 60 begin 467 | [char] - emit 468 | eol until 469 | begin key? while key drop repeat 470 | 471 | cr h# ffff hex8 472 | 473 | d# 0 d# 100 dump 474 | words cr cr 475 | 476 | begin again 477 | 478 | begin 479 | cr 480 | tib d# 30 accept >r 481 | d# 0. tib r> >number 482 | 2drop hex4 space hex4 483 | again 484 | 485 | snap 486 | ; 487 | 488 | : route 489 | r> + >r ; 490 | 491 | \ (doubleAlso) ( c-addr u -- x 1 | x x 2 ) 492 | \ If the string is legal, leave a single or double cell number 493 | \ and size of the number. 494 | 495 | : isvoid ( caddr u -- ) \ any char remains, throw -13 496 | nip 0<> 497 | if [char] x emit snap then 498 | ; 499 | 500 | : consume1 ( caddr u ch -- caddr' u' f ) 501 | >r over c@ r> = 502 | over 0<> and 503 | dup>r d# 1 and /string r> 504 | ; 505 | 506 | : (doubleAlso) 507 | h# 0. 2swap 508 | [char] - consume1 >r 509 | >number 510 | [char] . consume1 if 511 | isvoid \ double number 512 | r> if dnegate then 513 | d# 2 exit 514 | then 515 | \ single number 516 | isvoid drop 517 | r> if negate then 518 | d# 1 519 | ; 520 | 521 | : doubleAlso 522 | (doubleAlso) drop 523 | ; 524 | 525 | 526 | : dispatch 527 | route ;fallthru 528 | jmp execute \ -1 0 non-immediate 529 | jmp doubleAlso \ 0 0 number 530 | jmp execute \ 1 0 immediate 531 | 532 | \ jmp compile_comma \ -1 2 non-immediate 533 | \ jmp doubleAlso_comma \ 0 2 number 534 | \ jmp execute \ 1 2 immediate 535 | 536 | : interpret 537 | begin 538 | parse-name dup 539 | while 540 | sfind 541 | 1+ 2* dispatch 542 | repeat 543 | 2drop 544 | ; 545 | 546 | : main 547 | 2drop 548 | begin 549 | tib d# 80 accept 550 | tib# ! 551 | \ h# 40 emit 552 | d# 0 >in ! 553 | source dump 554 | \ cr parse-name sfind 555 | \ if 556 | \ execute 557 | \ then 558 | interpret 559 | again 560 | ; 561 | 562 | meta 563 | $3f80 org 564 | target 565 | 566 | : b.key 567 | begin 568 | d# 0 io@ 569 | d# 4 and 570 | until 571 | d# 0 io@ d# 8 rshift 572 | d# 0 d# 2 io! 573 | ; 574 | 575 | : b.32 576 | b.key 577 | b.key d# 8 lshift or 578 | b.key d# 16 lshift or 579 | b.key d# 24 lshift or 580 | ; 581 | 582 | meta 583 | $3fc0 org 584 | target 585 | 586 | : bootloader 587 | begin 588 | b.key d# 27 = 589 | until 590 | 591 | b.32 d# 0 592 | begin 593 | 2dupxor 594 | while 595 | b.32 over ! 596 | d# 4 + 597 | repeat 598 | ; 599 | 600 | meta 601 | link @ t, 602 | link @ t' ll tw! 603 | there t' dp tw! 604 | target 605 | --------------------------------------------------------------------------------