mirror of
https://github.com/im-tomu/fomu-workshop.git
synced 2024-09-20 03:10:12 +00:00
Upload of completed j1eforth for FOMU in verilog
This commit is contained in:
parent
d7119d0719
commit
cccaf76e71
BIN
docs/j1eforth-verilog.png
Normal file
BIN
docs/j1eforth-verilog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 77 KiB |
351
docs/j1eforth.rst
Normal file
351
docs/j1eforth.rst
Normal file
@ -0,0 +1,351 @@
|
||||
Verilog-Playground
|
||||
==================
|
||||
|
||||
My Verilog Coding Experimental Area
|
||||
|
||||
j1eforth-verilog for FOMU
|
||||
-------------------------
|
||||
|
||||
Translation of the j1eforth interactive Forth environment for FOMU
|
||||
(https://www.crowdsupply.com/sutajio-kosagi/fomu with documentation at
|
||||
https://workshop.fomu.im/en/latest/) translated from Silice to Verilog.
|
||||
|
||||
The original J1 CPU (https://www.excamera.com/sphinx/fpga-j1.html with a
|
||||
very clear explanatory paper at https://www.excamera.com/files/j1.pdf)
|
||||
along with the j1eforth interactive Forth environment
|
||||
(https://github.com/samawati/j1eforth) was written for an FPGA with
|
||||
access to 16384 x 16bit (256kbit) dual port single cycle block ram,
|
||||
whereas the FOMU has 120kbit of block ram. It does however have 1024kbit
|
||||
of single port ram (65536 x 16bit), which is more than sufficient for
|
||||
j1eforth, but it has 2 cycle latency.
|
||||
|
||||
j1eforth for FOMU was originally coded in Silice
|
||||
(https://github.com/sylefeb/Silice) due to my limited (i.e. NO) FPGA
|
||||
programming experience. Silice provides a nice introduction to FPGA
|
||||
programming for those coming from more tradition software coding. Once
|
||||
this design was working, especially the timings to access the single
|
||||
port ram, I translated it back to verilog, as an educational experience
|
||||
for myself.
|
||||
|
||||
I’ve, in my opinion, tidied up the code, to make the variables more
|
||||
explanatory, and to aid my coding.
|
||||
|
||||
For communicating via a terminal the tinyfpga_bx_usbserial
|
||||
(https://github.com/stef/nb-fomu-hw) was implemented to provide a 115200
|
||||
baud UART. A 32 character input and output buffer was added.
|
||||
|
||||
Using j1eforth-verilog on the FOMU
|
||||
----------------------------------
|
||||
|
||||
Download the source code from this repository. Ensure that you have the
|
||||
required toolchain installed. Compile (on Linux) with
|
||||
``./fomu_hacker_USB_SPRAM.sh`` within the source directory.
|
||||
|
||||
Or download the precompiled ``j1eforth-verilog-FOMU.dfu`` file from this repository.
|
||||
|
||||
Upload the compiled, or downloaded bitstream to your FOMU with
|
||||
``dfu-util -D build.dfu`` or ``dfu-util -D j1eforth-verilog-FOMU.dfu`` and connect via your chosen terminal, for
|
||||
minicom ``minicom -D /dev/ttyACM0`` (ACM0 may need replacing with an
|
||||
appropriate number on your machine).
|
||||
|
||||
Resources on the FOMU
|
||||
---------------------
|
||||
|
||||
Resource usage:
|
||||
|
||||
::
|
||||
|
||||
Info: Device utilisation:
|
||||
Info: ICESTORM_LC: 2612/ 5280 49%
|
||||
Info: ICESTORM_RAM: 19/ 30 63%
|
||||
Info: SB_IO: 12/ 96 12%
|
||||
Info: SB_GB: 8/ 8 100%
|
||||
Info: ICESTORM_PLL: 0/ 1 0%
|
||||
Info: SB_WARMBOOT: 0/ 1 0%
|
||||
Info: ICESTORM_DSP: 0/ 8 0%
|
||||
Info: ICESTORM_HFOSC: 0/ 1 0%
|
||||
Info: ICESTORM_LFOSC: 0/ 1 0%
|
||||
Info: SB_I2C: 0/ 2 0%
|
||||
Info: SB_SPI: 0/ 2 0%
|
||||
Info: IO_I3C: 0/ 2 0%
|
||||
Info: SB_LEDDA_IP: 0/ 1 0%
|
||||
Info: SB_RGBA_DRV: 1/ 1 100%
|
||||
Info: ICESTORM_SPRAM: 4/ 4 100%
|
||||
|
||||
// Timing estimate: 36.89 ns (27.11 MHz)
|
||||
|
||||
The original J1 CPU has this instruction encoding:
|
||||
|
||||
::
|
||||
|
||||
+---------------------------------------------------------------+
|
||||
| F | E | D | C | B | A | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
+---------------------------------------------------------------+
|
||||
| 1 | LITERAL VALUE |
|
||||
+---------------------------------------------------------------+
|
||||
| 0 | 0 | 0 | BRANCH TARGET ADDRESS |
|
||||
+---------------------------------------------------------------+
|
||||
| 0 | 0 | 1 | CONDITIONAL BRANCH TARGET ADDRESS |
|
||||
+---------------------------------------------------------------+
|
||||
| 0 | 1 | 0 | CALL TARGET ADDRESS |
|
||||
+---------------------------------------------------------------+
|
||||
| 0 | 1 | 1 |R2P| ALU OPERATION |T2N|T2R|N2A| | RSTACK| DSTACK|
|
||||
+---------------------------------------------------------------+
|
||||
| F | E | D | C | B | A | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
+---------------------------------------------------------------+
|
||||
|
||||
T : Top of data stack
|
||||
N : Next on data stack
|
||||
PC : Program Counter
|
||||
|
||||
LITERAL VALUES : push a value onto the data stack
|
||||
CONDITIONAL : BRANCHS pop and test the T
|
||||
CALLS : PC+1 onto the return stack
|
||||
|
||||
T2N : Move T to N
|
||||
T2R : Move T to top of return stack
|
||||
N2A : STORE T to memory location addressed by N
|
||||
R2P : Move top of return stack to PC
|
||||
|
||||
RSTACK and DSTACK are signed values (twos compliment) that are
|
||||
the stack delta (the amount to increment or decrement the stack
|
||||
by for their respective stacks: return and data)
|
||||
|
||||
The J1+ CPU adds up to 16 new alu operations, by assigning new alu
|
||||
operations by using ALU bit 4 to determine if J1 or J1+ alu operations,
|
||||
with the ALU instruction encoding:
|
||||
|
||||
::
|
||||
|
||||
+---------------------------------------------------------------+
|
||||
| 0 | 1 | 1 |R2P| ALU OPERATION |T2N|T2R|N2A|J1+| RSTACK| DSTACK|
|
||||
+---------------------------------------------------------------+
|
||||
| F | E | D | C | B | A | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
+---------------------------------------------------------------+
|
||||
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| Binary | J1 CPU | J1+ CPU | J1 CPU | J1+ CPU | J1+ |
|
||||
| ALU | | | Forth | Forth | Im |
|
||||
| Operation | | | Word | Word | plemented |
|
||||
| Code | | | (notes) | | in |
|
||||
| | | | | | j1eforth |
|
||||
+===========+===========+===========+===========+===========+===========+
|
||||
| 0000 | T | T==0 | (top of | 0= | X |
|
||||
| | | | stack) | | |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 0001 | N | T<>0 | (next on | 0<> | X |
|
||||
| | | | stack) | | |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 0010 | T+N | N<>T | + | <> | X |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 0011 | T&N | T+1 | and | 1+ | X |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 0100 | T|N | T<<1 | or | 2\* | X |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 0101 | T^N | T>>1 | xor | 2/ | (stops |
|
||||
| | | | | | ROM |
|
||||
| | | | | | working) |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 0110 | ~T | N>T | invert | > | X |
|
||||
| | | | | (signed) | |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 0111 | N==T | NU>T | = | > | X |
|
||||
| | | | | ( | |
|
||||
| | | | | unsigned) | |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 1000 | N<T | T<0 | < | 0< | X |
|
||||
| | | | (signed) | | |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 1001 | N>>T | T>0 | rshift | 0> | X |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 1010 | T-1 | ABST | 1- | abs | X |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 1011 | rt | MXNT | (push top | max | X |
|
||||
| | | | of return | | |
|
||||
| | | | stack to | | |
|
||||
| | | | data | | |
|
||||
| | | | stack) | | |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 1100 | [T] | MNNT | @ (read | min | X |
|
||||
| | | | from | | |
|
||||
| | | | memory) | | |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 1101 | N<<T | -T | lshift | negate | X |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 1110 | dsp | N-T | (depth of | - | (stops |
|
||||
| | | | stacks) | | ROM |
|
||||
| | | | | | working) |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 1111 | NU<T | N>=T | < | >= | X |
|
||||
| | | | ( | (signed) | |
|
||||
| | | | unsigned) | | |
|
||||
+-----------+-----------+-----------+-----------+-----------+-----------+
|
||||
|
||||
*I am presently unable to add the 2/ or - to the j1eforth ROM, as the
|
||||
compiled ROM is no longer functional. Some assistance to add these
|
||||
instructions would be appreciated.*
|
||||
|
||||
Memory Map
|
||||
~~~~~~~~~~
|
||||
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| Hexadecimal Address | Usage |
|
||||
+===================================+===================================+
|
||||
| 0000 - 3fff | Program code and data |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 4000 - 7fff | RAM (written to with |
|
||||
| | ``value addr !``, read by |
|
||||
| | ``addr @`` |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| f000 | UART input/output (best to leave |
|
||||
| | to j1eforth to operate via IN/OUT |
|
||||
| | buffers) |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| f001 | UART Status (bit 1 = TX buffer |
|
||||
| | full, bit 0 = RX character |
|
||||
| | available, best to leave to |
|
||||
| | j1eforth to operate via IN/OUT |
|
||||
| | buffers) |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| f002 | RGB LED input/output bitfield { |
|
||||
| | 13b0, red, green, blue } |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| f003 | BUTTONS input bitfield { 12b0, |
|
||||
| | button 4, button 3, button 2, |
|
||||
| | button 1 } |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
|
||||
INIT stages
|
||||
~~~~~~~~~~~
|
||||
|
||||
Due to the size of the block ram on the FOMU (120kbit or 7680 x 16bit)
|
||||
and the J1+ CPU requiring 256kbit (16384 x 16bit) of RAM, the J1+ CPU on
|
||||
the FOMU copies the j1eforth code from an initialised block ram to
|
||||
SPRAM, and uses the SPRAM for the J1+ CPU.
|
||||
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| INIT | Action |
|
||||
+===================================+===================================+
|
||||
| 0 | 0 the SPRAM. Due to the latency, |
|
||||
| | this is controlled by CYCLE |
|
||||
| | (pipeline). |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 1 | COPY the j1eforth ROM to SPRAM. |
|
||||
| | Due to latency, this is |
|
||||
| | controoled by CYCLE (pipeline). |
|
||||
| | The block ram at address |
|
||||
| | [copaddress] is read in a |
|
||||
| | separate always block. This |
|
||||
| | allows the block ram to inferred |
|
||||
| | by yosys. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 2 | SPARE (not used in the J1+ CPU). |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 3 | Start the J1+ CPU at pc==0 from |
|
||||
| | SPRAM. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
|
||||
Pipeline / CYCLE logic
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Due to blockram and SPRAM latency, there needs to be a pipeline for the
|
||||
J1+ CPU on the FOMU, which is set to 0 to 12 stages. These are used as
|
||||
follows:
|
||||
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| CYCLE | Action |
|
||||
+===================================+===================================+
|
||||
| ALL (at entry to INIT==3 loop) | Check for input from the UART, |
|
||||
| | put into buffer. Check if output |
|
||||
| | in the UART buffer and send to |
|
||||
| | UART. **NOTE:** To stop a race |
|
||||
| | condition, uartOutBufferTop = |
|
||||
| | newuartOutBufferTop is updated |
|
||||
| | after output. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 0 | blockram: Read data stackNext and |
|
||||
| | rstackTop, started in CYCLE==9. |
|
||||
| | SPRAM: Start the read of memory |
|
||||
| | position [stackTop] by setting |
|
||||
| | the SPRAM sram_address and |
|
||||
| | sram_readwrite flag. This is done |
|
||||
| | speculatively in case the ALU |
|
||||
| | needs this memory later in the |
|
||||
| | pipeline. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 3 | Complete read of memory position |
|
||||
| | [stackTop] from SPRAM by reading |
|
||||
| | sram_data_read. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 4 | Start read of the instruction at |
|
||||
| | memory position [pc] by setting |
|
||||
| | sram_address and sram_readwrite |
|
||||
| | flag. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 7 | Complete read of the instruction |
|
||||
| | at memory position [pc] by |
|
||||
| | reading sram_data_read. *The |
|
||||
| | instruction is decoded |
|
||||
| | automatically by the continuos |
|
||||
| | assigns := block at the top of |
|
||||
| | the code.* |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 8 | Instruction Execution Determine |
|
||||
| | if LITERAL, BRANCH, BRANCH, CALL |
|
||||
| | or ALU. In the ALU (J1 CPU block) |
|
||||
| | the UART input buffer, UART |
|
||||
| | status register, RGB LED status, |
|
||||
| | input buttons or memory is |
|
||||
| | selected as appropriate. The UART |
|
||||
| | buffers and the speculative |
|
||||
| | memory read of [stackTop] are |
|
||||
| | used to allow **ALL** ALU |
|
||||
| | operations to execute in one |
|
||||
| | cycle. At the end of the ALU if a |
|
||||
| | write to memory is required, this |
|
||||
| | is initiated by setting the |
|
||||
| | sram_address, sram_data_write and |
|
||||
| | sram_readwrite flag. This will be |
|
||||
| | completed by CYCLE==12. Output to |
|
||||
| | UART output buffer or the RGB LED |
|
||||
| | is performed here if a write to |
|
||||
| | an I/O address, not memory, is |
|
||||
| | requested. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 9 | Start the writing to the block |
|
||||
| | ram for the data and return |
|
||||
| | stacks. This will be completed by |
|
||||
| | CYCLE==10. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 10 | Update all of the J1+ CPU |
|
||||
| | pointers for the data and return |
|
||||
| | stacks, the program counter, and |
|
||||
| | stackTop. Start the reading of |
|
||||
| | the data and return stacks. This |
|
||||
| | will be completed by CYCLE==11, |
|
||||
| | but not actually read until the |
|
||||
| | return to CYCLE==0. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| 12 | Reset the sram_readwrite flag, to |
|
||||
| | complete any memory write started |
|
||||
| | in CYCLE==8 in the ALU. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
| ALL (at end of INIT==3 loop) | Reset the UART output if any |
|
||||
| | character was transmitted. Move |
|
||||
| | to the next CYCLE. |
|
||||
+-----------------------------------+-----------------------------------+
|
||||
|
||||
Forth Words to try
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- ``cold`` reset
|
||||
- ``words`` list known Forth words
|
||||
- ``cr`` output a carriage return
|
||||
- ``2a emit`` output a \* (character 2a (hex) 42 (decimal)
|
||||
- ``decimal`` use decimal notation
|
||||
- ``hex`` use hexadecimal notation
|
||||
|
||||
.. figure:: j1eforth-verilog.png
|
||||
:alt: j1eforth on FOMU
|
||||
|
||||
j1eforth on FOMU
|
26
verilog/j1eforth/fomu_hacker_USB_SPRAM.sh
Normal file
26
verilog/j1eforth/fomu_hacker_USB_SPRAM.sh
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
rm build*
|
||||
|
||||
yosys -D HACKER=1 -p 'synth_ice40 -top top -json build.json' \
|
||||
tinyfpga_bx_usbserial/usb/edge_detect.v \
|
||||
tinyfpga_bx_usbserial/usb/serial.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_fs_in_arb.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_fs_in_pe.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_fs_out_arb.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_fs_out_pe.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_fs_pe.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_fs_rx.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_fs_tx_mux.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_fs_tx.v\
|
||||
tinyfpga_bx_usbserial/usb/usb_reset_det.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_serial_ctrl_ep.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_uart_bridge_ep.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_uart_core.v \
|
||||
tinyfpga_bx_usbserial/usb/usb_uart_i40.v \
|
||||
j1eforth.v
|
||||
|
||||
nextpnr-ice40 --up5k --freq 12 --opt-timing --package uwg30 --pcf pcf/fomu-hacker.pcf --json build.json --asc build.asc
|
||||
icepack build.asc build.bit
|
||||
icetime -d up5k -mtr build.rpt build.asc
|
||||
cp build.bit build.dfu
|
||||
dfu-suffix -v 1209 -p 70b1 -a build.dfu
|
13
verilog/j1eforth/j1eforth-plus/Makefile
Normal file
13
verilog/j1eforth/j1eforth-plus/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
all: j1 j1.bin j1.hex
|
||||
|
||||
j1: j1.c
|
||||
gcc -o j1 j1.c -lwpcap
|
||||
strip -s j1
|
||||
j1.bin j1.hex: j1.4th
|
||||
gforth ./j1.4th
|
||||
run: all
|
||||
./j1
|
||||
core: all
|
||||
./j1 core.4th
|
||||
clean:
|
||||
rm -rf j1 j1.bin j1.hex
|
99
verilog/j1eforth/j1eforth-plus/README.md
Normal file
99
verilog/j1eforth/j1eforth-plus/README.md
Normal file
@ -0,0 +1,99 @@
|
||||
eForth for the J1 Simulator and actual J1 FPGAs
|
||||
-------------
|
||||
|
||||
J1 eForth is an interactive work-in-progress Forth designed to run on the [James Bowman's J1 FPGA soft core][j1]
|
||||
(see also [J1 on Github][J1github]). There is a Forth cross compiler written in Forth to
|
||||
generate the interactice J1 eForth system, and a J1 simulator written in C to run J1 eForth simulated
|
||||
on a PC.
|
||||
|
||||
J1 eForth also runs on actual J1 FPGAs. It has been ported to the [Papilio Pro][pappro] FPGA board,
|
||||
where it executes Forth program at 66 MHz. It communicates with a host system using a serial line at a
|
||||
default speed of 115200 Bits/s.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- [GNU make][gmake] (optional) for job control
|
||||
- [gforth][gforth] for cross compiling / generating the J1 eForth image
|
||||
- [WpdPack][pcap] for network simulation
|
||||
|
||||
If you want to run J1 eForth simulated on a PC:
|
||||
|
||||
- [gcc][gcc] to compile the J1 simulator
|
||||
|
||||
If you want to run J1 eForth on a J1 in an FPGA:
|
||||
|
||||
- [Xilinx ISE][xilinxise] to generate the FPGA bit stream (ISE 14.7)
|
||||
- [Papilio-Loader][paploader] to download the bitstream to the FPGA
|
||||
|
||||
### Directry Structure
|
||||
|
||||
j1eforth
|
||||
├── README.MD
|
||||
├── j1.4th cross compiler with J1 eForth
|
||||
├── j1.c J1 simulator
|
||||
└── fpga
|
||||
├── src Verilog projects for J1 and UART (miniuart2) for Papilio Pro
|
||||
└── test testbenches
|
||||
|
||||
### Building and running the j1 Simulator
|
||||
#### Compiling using gcc Mingw (Windows)
|
||||
|
||||
gcc j1.c -o -lwpcap j1.exe
|
||||
|
||||
#### Creating flash image j1.bin (and j1.hex)
|
||||
|
||||
gforth j1.4th
|
||||
#### Running the Simulator
|
||||
|
||||
j1.exe [optional argument]
|
||||
|
||||
The argument to the simulator is an optional forth file that can be used to extend the dictionary
|
||||
and is passed to the simulator as the first argument during startup
|
||||
|
||||
Words to test in the simulator :
|
||||
|
||||
[ see , ' , compile , [compile] , ?branch , branch , call, .. and many more ]
|
||||
|
||||
Have fun , modify and pass on
|
||||
|
||||
### Running on Real Hardware
|
||||
|
||||
J1 eForth can run on an actual j1 FPGA. It has been ported to the [Papilio Pro][pappro] FPGA board.
|
||||
|
||||
#### Create the J1 bit stream:
|
||||
|
||||
Start Xilinx ise on project `vhdl/papiolo-pro-j1.xise`
|
||||
choose `Generate Programming File` on the `papilio_pro_j1` component. This generates `papilio_pro_j1.bit`
|
||||
including the Forth image (`j1.hex`) as initial memory (built before when generating the flash image).
|
||||
|
||||
#### Load the complete bit stream (J1 and memory) into the FPGA:
|
||||
|
||||
sudo papilio-prog -v -f papilio_pro_j1.bit
|
||||
|
||||
You might want to use the pre-built `pipilio_pro_j1.bit` for a quick start.
|
||||
|
||||
#### Connect to J1 eForth:
|
||||
|
||||
screen /dev/tty.usbserial 115200
|
||||
|
||||
or similar. J1 eForth should show the prompt
|
||||
|
||||
eForth j1 v1.04
|
||||
ok
|
||||
|
||||
If you only see the **`ok`** prompts issue a **`cold`** and press the enter key to reboot the system.
|
||||
|
||||
|
||||
### May the Forth be with you.
|
||||
|
||||
[pappro]: http://papilio.cc/index.php?n=Papilio.PapilioPro
|
||||
[paploader]: http://papilio.cc/index.php?n=Papilio.PapilioLoaderV2
|
||||
[pcap]: http://www.winpcap.org/archive/4.1.1-WpdPack.zip
|
||||
[j1]: http://www.excamera.com/sphinx/fpga-j1.html
|
||||
[j1github]: https://github.com/jamesbowman/j1
|
||||
|
||||
[gmake]: https://www.gnu.org/software/make/
|
||||
[gcc]: https://gcc.gnu.org/
|
||||
[gforth]: https://www.gnu.org/software/gforth/
|
||||
|
||||
[xilinxise]: http://www.xilinx.com/products/design-tools/ise-design-suite/ise-webpack.html
|
422
verilog/j1eforth/j1eforth-plus/fpga/papilio-pro-j1.xise
Normal file
422
verilog/j1eforth/j1eforth-plus/fpga/papilio-pro-j1.xise
Normal file
@ -0,0 +1,422 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<project xmlns="http://www.xilinx.com/XMLSchema" xmlns:xil_pn="http://www.xilinx.com/XMLSchema">
|
||||
|
||||
<header>
|
||||
<!-- ISE source project file created by Project Navigator. -->
|
||||
<!-- -->
|
||||
<!-- This file contains project source information including a list of -->
|
||||
<!-- project source files, project and process properties. This file, -->
|
||||
<!-- along with the project source files, is sufficient to open and -->
|
||||
<!-- implement in ISE Project Navigator. -->
|
||||
<!-- -->
|
||||
<!-- Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved. -->
|
||||
</header>
|
||||
|
||||
<version xil_pn:ise_version="14.7" xil_pn:schema_version="2"/>
|
||||
|
||||
<files>
|
||||
<file xil_pn:name="src/papilio-pro.ucf" xil_pn:type="FILE_UCF">
|
||||
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
|
||||
</file>
|
||||
<file xil_pn:name="src/miniuart.vhd" xil_pn:type="FILE_VHDL">
|
||||
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="4"/>
|
||||
<association xil_pn:name="Implementation" xil_pn:seqID="4"/>
|
||||
</file>
|
||||
<file xil_pn:name="src/Rxunit.vhd" xil_pn:type="FILE_VHDL">
|
||||
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="3"/>
|
||||
<association xil_pn:name="Implementation" xil_pn:seqID="3"/>
|
||||
</file>
|
||||
<file xil_pn:name="src/Txunit.vhd" xil_pn:type="FILE_VHDL">
|
||||
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="2"/>
|
||||
<association xil_pn:name="Implementation" xil_pn:seqID="2"/>
|
||||
</file>
|
||||
<file xil_pn:name="src/utils.vhd" xil_pn:type="FILE_VHDL">
|
||||
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="1"/>
|
||||
<association xil_pn:name="Implementation" xil_pn:seqID="1"/>
|
||||
</file>
|
||||
<file xil_pn:name="test/miniuart2_tb.vhd" xil_pn:type="FILE_VHDL">
|
||||
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="5"/>
|
||||
<association xil_pn:name="PostMapSimulation" xil_pn:seqID="231"/>
|
||||
<association xil_pn:name="PostRouteSimulation" xil_pn:seqID="231"/>
|
||||
<association xil_pn:name="PostTranslateSimulation" xil_pn:seqID="231"/>
|
||||
</file>
|
||||
<file xil_pn:name="test/papilio_pro_j1_tb.vhd" xil_pn:type="FILE_VHDL">
|
||||
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
|
||||
<association xil_pn:name="PostMapSimulation" xil_pn:seqID="15"/>
|
||||
<association xil_pn:name="PostRouteSimulation" xil_pn:seqID="15"/>
|
||||
<association xil_pn:name="PostTranslateSimulation" xil_pn:seqID="15"/>
|
||||
</file>
|
||||
<file xil_pn:name="src/papilio-pro-j1.vhd" xil_pn:type="FILE_VHDL">
|
||||
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
|
||||
<association xil_pn:name="Implementation" xil_pn:seqID="7"/>
|
||||
</file>
|
||||
<file xil_pn:name="src/j1.v" xil_pn:type="FILE_VERILOG">
|
||||
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
|
||||
<association xil_pn:name="Implementation" xil_pn:seqID="5"/>
|
||||
</file>
|
||||
<file xil_pn:name="src/clock.vhd" xil_pn:type="FILE_VHDL">
|
||||
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="0"/>
|
||||
<association xil_pn:name="Implementation" xil_pn:seqID="6"/>
|
||||
</file>
|
||||
</files>
|
||||
|
||||
<properties>
|
||||
<property xil_pn:name="AES Initial Vector spartan6" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="AES Key (Hex String) spartan6" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Add I/O Buffers" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Allow Logic Optimization Across Hierarchy" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Allow SelectMAP Pins to Persist" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Allow Unexpanded Blocks" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Allow Unmatched LOC Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Allow Unmatched Timing Group Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Analysis Effort Level" xil_pn:value="Standard" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Asynchronous To Synchronous" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Auto Implementation Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Auto Implementation Top" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Automatic BRAM Packing" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Automatically Insert glbl Module in the Netlist" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Automatically Run Generate Target PROM/ACE File" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="BRAM Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Bring Out Global Set/Reset Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Bring Out Global Tristate Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Bus Delimiter" xil_pn:value="<>" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="CLB Pack Factor Percentage" xil_pn:value="100" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Case" xil_pn:value="Maintain" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Case Implementation Style" xil_pn:value="None" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Change Device Speed To" xil_pn:value="-2" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Change Device Speed To Post Trace" xil_pn:value="-2" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Combinatorial Logic Optimization" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Compile EDK Simulation Library" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Compile SIMPRIM (Timing) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Compile UNISIM (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Compile XilinxCoreLib (CORE Generator) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Compile for HDL Debugging" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Configuration Clk (Configuration Pins)" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Configuration Pin Done" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Configuration Pin M0" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Configuration Pin M1" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Configuration Pin M2" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Configuration Pin Program" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Configuration Rate" xil_pn:value="4" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Configuration Rate spartan6" xil_pn:value="2" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Correlate Output to Input Design" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Create ASCII Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Create Binary Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Create Bit File" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Create I/O Pads from Ports" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Create IEEE 1532 Configuration File spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Create Logic Allocation File" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Create Mask File" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Create ReadBack Data Files" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Cross Clock Analysis" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="DSP Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Decoder Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Delay Values To Be Read from SDF" xil_pn:value="Setup Time" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Device" xil_pn:value="xc6slx9" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Device Family" xil_pn:value="Spartan6" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Device Speed Grade/Select ABS Minimum" xil_pn:value="-2" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Disable Detailed Package Model Insertion" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Do Not Escape Signal and Instance Names in Netlist" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Done (Output Events)" xil_pn:value="Default (4)" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Drive Awake Pin During Suspend/Wake Sequence spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Drive Done Pin High" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable BitStream Compression" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable Cyclic Redundancy Checking (CRC) spartan6" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable Debugging of Serial Mode BitStream" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable External Master Clock spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable Hardware Co-Simulation" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable Internal Done Pipe" xil_pn:value="true" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Enable Message Filtering" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable Multi-Pin Wake-Up Suspend Mode spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable Multi-Threading" xil_pn:value="Off" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable Multi-Threading par spartan6" xil_pn:value="Off" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable Outputs (Output Events)" xil_pn:value="Default (5)" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Enable Suspend/Wake Global Set/Reset spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Encrypt Bitstream spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Encrypt Key Select spartan6" xil_pn:value="BBRAM" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Equivalent Register Removal Map" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Equivalent Register Removal XST" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Essential Bits" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Evaluation Development Board" xil_pn:value="None Specified" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Exclude Compilation of Deprecated EDK Cores" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Exclude Compilation of EDK Sub-Libraries" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Extra Cost Tables Map" xil_pn:value="0" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Extra Effort (Highest PAR level only)" xil_pn:value="None" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="FPGA Start-Up Clock" xil_pn:value="CCLK" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="FSM Encoding Algorithm" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="FSM Style" xil_pn:value="LUT" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Filter Files From Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Flatten Output Netlist" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Functional Model Target Language ArchWiz" xil_pn:value="Verilog" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Functional Model Target Language Coregen" xil_pn:value="Verilog" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Functional Model Target Language Schematic" xil_pn:value="Verilog" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="GTS Cycle During Suspend/Wakeup Sequence spartan6" xil_pn:value="4" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="GWE Cycle During Suspend/Wakeup Sequence spartan6" xil_pn:value="5" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Architecture Only (No Entity Declaration)" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Asynchronous Delay Report" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Clock Region Report" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Constraints Interaction Report" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Constraints Interaction Report Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Datasheet Section" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Datasheet Section Post Trace" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Detailed MAP Report" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Multiple Hierarchical Netlist Files" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Post-Place & Route Power Report" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Post-Place & Route Simulation Model" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate RTL Schematic" xil_pn:value="Yes" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate SAIF File for Power Optimization/Estimation Par" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Testbench File" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Timegroups Section" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generate Timegroups Section Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Generics, Parameters" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Global Optimization Goal" xil_pn:value="AllClockNets" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Global Optimization map spartan6" xil_pn:value="Off" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Global Set/Reset Port Name" xil_pn:value="GSR_PORT" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Global Tristate Port Name" xil_pn:value="GTS_PORT" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Hierarchy Separator" xil_pn:value="/" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="ISim UUT Instance Name" xil_pn:value="UUT" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Ignore User Timing Constraints Map" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Ignore User Timing Constraints Par" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Implementation Top" xil_pn:value="Architecture|papilio_pro_j1|Behavioral" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Implementation Top File" xil_pn:value="src/papilio-pro-j1.vhd" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Implementation Top Instance Path" xil_pn:value="/papilio_pro_j1" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Include 'uselib Directive in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Include SIMPRIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Include UNISIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Include sdf_annotate task in Verilog File" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Incremental Compilation" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Insert Buffers to Prevent Pulse Swallowing" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Instantiation Template Target Language Xps" xil_pn:value="Verilog" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="JTAG Pin TCK" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="JTAG Pin TDI" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="JTAG Pin TDO" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="JTAG Pin TMS" xil_pn:value="Pull Up" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Keep Hierarchy" xil_pn:value="No" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="LUT Combining Map" xil_pn:value="Off" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="LUT Combining Xst" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Language" xil_pn:value="VHDL" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Last Applied Goal" xil_pn:value="Balanced" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Last Applied Strategy" xil_pn:value="Xilinx Default (unlocked)" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Last Unlock Status" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Launch SDK after Export" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Library for Verilog Sources" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Load glbl" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Logical Shifter Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Manual Implementation Compile Order" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Map Slice Logic into Unused Block RAMs" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Mask Pins for Multi-Pin Wake-Up Suspend Mode spartan6" xil_pn:value="0x00" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Max Fanout" xil_pn:value="100000" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Maximum Compression" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Maximum Number of Lines in Report" xil_pn:value="1000" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Maximum Signal Name Length" xil_pn:value="20" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Move First Flip-Flop Stage" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Move Last Flip-Flop Stage" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="MultiBoot: Insert IPROG CMD in the Bitfile spartan6" xil_pn:value="Enable" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="MultiBoot: Next Configuration Mode spartan6" xil_pn:value="001" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="MultiBoot: Starting Address for Golden Configuration spartan6" xil_pn:value="0x00000000" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="MultiBoot: Starting Address for Next Configuration spartan6" xil_pn:value="0x00000000" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="MultiBoot: Use New Mode for Next Configuration spartan6" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="MultiBoot: User-Defined Register for Failsafe Scheme spartan6" xil_pn:value="0x0000" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Multiplier Style" xil_pn:value="LUT" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Mux Extraction" xil_pn:value="Yes" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Mux Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Netlist Hierarchy" xil_pn:value="As Optimized" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Netlist Translation Type" xil_pn:value="Timestamp" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Number of Clock Buffers" xil_pn:value="16" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Number of Paths in Error/Verbose Report" xil_pn:value="3" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Number of Paths in Error/Verbose Report Post Trace" xil_pn:value="3" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Optimization Effort" xil_pn:value="Normal" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Optimization Effort spartan6" xil_pn:value="Normal" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Optimization Goal" xil_pn:value="Speed" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Optimization Strategy (Cover Mode)" xil_pn:value="Area" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Optimize Instantiated Primitives" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Bitgen Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Bitgen Command Line Options spartan6" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Compiler Options" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Compiler Options Map" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Compiler Options Par" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Compiler Options Translate" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Compxlib Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Map Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other NETGEN Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Ngdbuild Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Place & Route Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Simulator Commands Behavioral" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Simulator Commands Post-Map" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Simulator Commands Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other Simulator Commands Post-Translate" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other XPWR Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Other XST Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Output Extended Identifiers" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Output File Name" xil_pn:value="papilio_pro_forth" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Overwrite Compiled Libraries" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Pack I/O Registers into IOBs" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Pack I/O Registers/Latches into IOBs" xil_pn:value="Off" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Package" xil_pn:value="tqg144" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Perform Advanced Analysis" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Perform Advanced Analysis Post Trace" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Perform Timing-Driven Packing and Placement" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Place & Route Effort Level (Overall)" xil_pn:value="High" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Place And Route Mode" xil_pn:value="Normal Place and Route" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Place MultiBoot Settings into Bitstream spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Placer Effort Level (Overrides Overall Level)" xil_pn:value="None" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Placer Effort Level Map" xil_pn:value="High" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Placer Extra Effort Map" xil_pn:value="None" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Port to be used" xil_pn:value="Auto - default" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Post Map Simulation Model Name" xil_pn:value="papilio_pro_forth_map.v" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Post Place & Route Simulation Model Name" xil_pn:value="papilio_pro_forth_timesim.v" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Post Synthesis Simulation Model Name" xil_pn:value="papilio_pro_forth_synthesis.v" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Post Translate Simulation Model Name" xil_pn:value="papilio_pro_forth_translate.v" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Power Reduction Map" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Power Reduction Map spartan6" xil_pn:value="Off" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Power Reduction Par" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Power Reduction Xst" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Preferred Language" xil_pn:value="Verilog" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Priority Encoder Extraction" xil_pn:value="Yes" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Produce Verbose Report" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Project Description" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Project Generator" xil_pn:value="ProjNav" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Property Specification in Project File" xil_pn:value="Store all values" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="RAM Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="RAM Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="ROM Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="ROM Style" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Read Cores" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Reduce Control Sets" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Regenerate Core" xil_pn:value="Under Current Project Setting" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Register Balancing" xil_pn:value="No" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Register Duplication Map" xil_pn:value="Off" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Register Duplication Xst" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Register Ordering spartan6" xil_pn:value="4" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Release Write Enable (Output Events)" xil_pn:value="Default (6)" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Rename Design Instance in Testbench File to" xil_pn:value="UUT" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Rename Top Level Architecture To" xil_pn:value="Structure" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Rename Top Level Entity to" xil_pn:value="main" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Rename Top Level Module To" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Report Fastest Path(s) in Each Constraint" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Report Fastest Path(s) in Each Constraint Post Trace" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Report Paths by Endpoint" xil_pn:value="3" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Report Paths by Endpoint Post Trace" xil_pn:value="3" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Report Type" xil_pn:value="Verbose Report" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Report Type Post Trace" xil_pn:value="Verbose Report" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Report Unconstrained Paths" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Report Unconstrained Paths Post Trace" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Reset On Configuration Pulse Width" xil_pn:value="100" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Resource Sharing" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Retain Hierarchy" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Retry Configuration if CRC Error Occurs spartan6" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Revision Select" xil_pn:value="00" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Revision Select Tristate" xil_pn:value="Disable" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Router Effort Level (Overrides Overall Level)" xil_pn:value="None" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Run Design Rules Checker (DRC)" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Run for Specified Time" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Run for Specified Time Map" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Run for Specified Time Par" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Run for Specified Time Translate" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Safe Implementation" xil_pn:value="No" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Security" xil_pn:value="Enable Readback and Reconfiguration" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Selected Module Instance Name" xil_pn:value="/miniuart2_tb" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Selected Simulation Root Source Node Behavioral" xil_pn:value="work.miniuart2_tb" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Selected Simulation Root Source Node Post-Map" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Selected Simulation Root Source Node Post-Translate" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Selected Simulation Source Node" xil_pn:value="UUT" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Set SPI Configuration Bus Width spartan6" xil_pn:value="1" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Setup External Master Clock Division spartan6" xil_pn:value="1" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Shift Register Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Shift Register Minimum Size spartan6" xil_pn:value="2" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Show All Models" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Simulation Model Target" xil_pn:value="Verilog" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Simulation Run Time ISim" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Simulation Run Time Map" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Simulation Run Time Par" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Simulation Run Time Translate" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Simulator" xil_pn:value="ISim (VHDL/Verilog)" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Slice Packing" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Slice Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Specify 'define Macro Name and Value" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Specify Top Level Instance Names Behavioral" xil_pn:value="work.miniuart2_tb" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Specify Top Level Instance Names Post-Map" xil_pn:value="Default" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Specify Top Level Instance Names Post-Route" xil_pn:value="Default" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Specify Top Level Instance Names Post-Translate" xil_pn:value="Default" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Speed Grade" xil_pn:value="-2" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Starting Placer Cost Table (1-100) Map" xil_pn:value="1" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Starting Placer Cost Table (1-100) Map spartan6" xil_pn:value="1" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Starting Placer Cost Table (1-100) Par" xil_pn:value="1" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Synthesis Tool" xil_pn:value="XST (VHDL/Verilog)" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Target Simulator" xil_pn:value="Please Specify" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Target UCF File Name" xil_pn:value="src/papilio-one.ucf" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Timing Mode Map" xil_pn:value="Non Timing Driven" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Timing Mode Par" xil_pn:value="Performance Evaluation" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Top-Level Module Name in Output Netlist" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Top-Level Source Type" xil_pn:value="HDL" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Trim Unconnected Signals" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Tristate On Configuration Pulse Width" xil_pn:value="0" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Unused IOB Pins" xil_pn:value="Pull Down" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use 64-bit PlanAhead on 64-bit Systems" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Clock Enable" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Project File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Project File Post-Map" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Project File Post-Route" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Project File Post-Translate" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Simulation Command File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Simulation Command File Map" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Simulation Command File Par" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Simulation Command File Translate" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Waveform Configuration File Behav" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Waveform Configuration File Map" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Waveform Configuration File Par" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Custom Waveform Configuration File Translate" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use DSP Block spartan6" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use LOC Constraints" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use RLOC Constraints" xil_pn:value="Yes" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Smart Guide" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Synchronous Reset" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Synchronous Set" xil_pn:value="Auto" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Use Synthesis Constraints File" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="User Browsed Strategy Files" xil_pn:value="/opt/Xilinx/14.7/ISE_DS/ISE/data/default.xds" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="UserID Code (8 Digit Hexadecimal)" xil_pn:value="0xFFFFFFFF" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="VCCAUX Voltage Level spartan6" xil_pn:value="2.5V" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="VHDL Source Analysis Standard" xil_pn:value="VHDL-93" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Value Range Check" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Verilog 2001 Xst" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Verilog Macros" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Wait for DCM and PLL Lock (Output Events) spartan6" xil_pn:value="Default (NoWait)" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Wait for DLL Lock (Output Events)" xil_pn:value="Default (NoWait)" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Wakeup Clock spartan6" xil_pn:value="Startup Clock" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Watchdog Timer Value spartan6" xil_pn:value="0xFFFF" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="Working Directory" xil_pn:value="." xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="Write Timing Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="XOR Collapsing" xil_pn:value="true" xil_pn:valueState="default"/>
|
||||
<!-- -->
|
||||
<!-- The following properties are for internal use only. These should not be modified.-->
|
||||
<!-- -->
|
||||
<property xil_pn:name="PROP_BehavioralSimTop" xil_pn:value="Architecture|miniuart2_tb|behavior" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="PROP_DesignName" xil_pn:value="forth" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="PROP_DevFamilyPMName" xil_pn:value="spartan6" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="PROP_FPGAConfiguration" xil_pn:value="FPGAConfiguration" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="PROP_PostMapSimTop" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="PROP_PostParSimTop" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="PROP_PostSynthSimTop" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="PROP_PostXlateSimTop" xil_pn:value="" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="PROP_PreSynthesis" xil_pn:value="PreSynthesis" xil_pn:valueState="default"/>
|
||||
<property xil_pn:name="PROP_intProjectCreationTimestamp" xil_pn:value="2012-03-04T11:05:19" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="PROP_intWbtProjectID" xil_pn:value="2646B868CC6AC035FC694292A405C58C" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="PROP_intWorkingDirLocWRTProjDir" xil_pn:value="Same" xil_pn:valueState="non-default"/>
|
||||
<property xil_pn:name="PROP_intWorkingDirUsed" xil_pn:value="No" xil_pn:valueState="non-default"/>
|
||||
</properties>
|
||||
|
||||
<bindings/>
|
||||
|
||||
<libraries/>
|
||||
|
||||
<autoManagedFiles>
|
||||
<!-- The following files are identified by `include statements in verilog -->
|
||||
<!-- source files and are automatically managed by Project Navigator. -->
|
||||
<!-- -->
|
||||
<!-- Do not hand-edit this section, as it will be overwritten when the -->
|
||||
<!-- project is analyzed based on files automatically identified as -->
|
||||
<!-- include files. -->
|
||||
</autoManagedFiles>
|
||||
|
||||
</project>
|
BIN
verilog/j1eforth/j1eforth-plus/fpga/papilio_pro_j1.bit
Normal file
BIN
verilog/j1eforth/j1eforth-plus/fpga/papilio_pro_j1.bit
Normal file
Binary file not shown.
97
verilog/j1eforth/j1eforth-plus/fpga/src/Rxunit.vhd
Normal file
97
verilog/j1eforth/j1eforth-plus/fpga/src/Rxunit.vhd
Normal file
@ -0,0 +1,97 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- Title : UART
|
||||
-- Project : UART
|
||||
-------------------------------------------------------------------------------
|
||||
-- File : Rxunit.vhd
|
||||
-- Author : Philippe CARTON
|
||||
-- (philippe.carton2@libertysurf.fr)
|
||||
-- Organization:
|
||||
-- Created : 15/12/2001
|
||||
-- Last update : 8/1/2003
|
||||
-- Platform : Foundation 3.1i
|
||||
-- Simulators : ModelSim 5.5b
|
||||
-- Synthesizers: Xilinx Synthesis
|
||||
-- Targets : Xilinx Spartan
|
||||
-- Dependency : IEEE std_logic_1164
|
||||
-------------------------------------------------------------------------------
|
||||
-- Description: RxUnit is a serial to parallel unit Receiver.
|
||||
-------------------------------------------------------------------------------
|
||||
-- Copyright (c) notice
|
||||
-- This core adheres to the GNU public license
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
-- Revisions :
|
||||
-- Revision Number :
|
||||
-- Version :
|
||||
-- Date :
|
||||
-- Modifier : name <email>
|
||||
-- Description :
|
||||
--
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
entity RxUnit is
|
||||
port (
|
||||
Clk : in std_logic; -- system clock signal
|
||||
Reset : in std_logic; -- Reset input
|
||||
Enable : in std_logic; -- Enable input
|
||||
ReadA : in Std_logic; -- Async Read Received Byte
|
||||
RxD : in std_logic; -- RS-232 data input
|
||||
RxAv : out std_logic; -- Byte available
|
||||
DataO : out std_logic_vector(7 downto 0)); -- Byte received
|
||||
end RxUnit;
|
||||
|
||||
architecture Behaviour of RxUnit is
|
||||
signal RReg : std_logic_vector(7 downto 0); -- receive register
|
||||
signal RRegL : std_logic; -- Byte received
|
||||
begin
|
||||
-- RxAv process
|
||||
RxAvProc : process(RRegL,Reset,ReadA)
|
||||
begin
|
||||
if ReadA = '1' or Reset = '1' then
|
||||
RxAv <= '0'; -- Negate RxAv when RReg read
|
||||
elsif Rising_Edge(RRegL) then
|
||||
RxAv <= '1'; -- Assert RxAv when RReg written
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Rx Process
|
||||
RxProc : process(Clk,Reset,Enable,RxD,RReg)
|
||||
variable BitPos : INTEGER range 0 to 10; -- Position of the bit in the frame
|
||||
variable SampleCnt : INTEGER range 0 to 3; -- Count from 0 to 3 in each bit
|
||||
begin
|
||||
if Reset = '1' then -- Reset
|
||||
RRegL <= '0';
|
||||
BitPos := 0;
|
||||
elsif Rising_Edge(Clk) then
|
||||
if Enable = '1' then
|
||||
case BitPos is
|
||||
when 0 => -- idle
|
||||
RRegL <= '0';
|
||||
if RxD = '0' then -- Start Bit
|
||||
SampleCnt := 0;
|
||||
BitPos := 1;
|
||||
end if;
|
||||
when 10 => -- Stop Bit
|
||||
BitPos := 0; -- next is idle
|
||||
RRegL <= '1'; -- Indicate byte received
|
||||
DataO <= RReg; -- Store received byte
|
||||
when others =>
|
||||
if (SampleCnt = 1 and BitPos >= 2) then -- Sample RxD on 1
|
||||
RReg(BitPos-2) <= RxD; -- Deserialisation
|
||||
end if;
|
||||
if SampleCnt = 3 then -- Increment BitPos on 3
|
||||
BitPos := BitPos + 1;
|
||||
end if;
|
||||
end case;
|
||||
if SampleCnt = 3 then
|
||||
SampleCnt := 0;
|
||||
else
|
||||
sampleCnt := SampleCnt + 1;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end Behaviour;
|
100
verilog/j1eforth/j1eforth-plus/fpga/src/Txunit.vhd
Normal file
100
verilog/j1eforth/j1eforth-plus/fpga/src/Txunit.vhd
Normal file
@ -0,0 +1,100 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- Title : UART
|
||||
-- Project : UART
|
||||
-------------------------------------------------------------------------------
|
||||
-- File : Txunit.vhd
|
||||
-- Author : Philippe CARTON
|
||||
-- (philippe.carton2@libertysurf.fr)
|
||||
-- Organization:
|
||||
-- Created : 15/12/2001
|
||||
-- Last update : 8/1/2003
|
||||
-- Platform : Foundation 3.1i
|
||||
-- Simulators : ModelSim 5.5b
|
||||
-- Synthesizers: Xilinx Synthesis
|
||||
-- Targets : Xilinx Spartan
|
||||
-- Dependency : IEEE std_logic_1164
|
||||
-------------------------------------------------------------------------------
|
||||
-- Description: Txunit is a parallel to serial unit transmitter.
|
||||
-------------------------------------------------------------------------------
|
||||
-- Copyright (c) notice
|
||||
-- This core adheres to the GNU public license
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
-- Revisions :
|
||||
-- Revision Number :
|
||||
-- Version :
|
||||
-- Date :
|
||||
-- Modifier : name <email>
|
||||
-- Description :
|
||||
--
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
entity TxUnit is
|
||||
port (
|
||||
Clk : in std_logic; -- Clock signal
|
||||
Reset : in std_logic; -- Reset input
|
||||
Enable : in std_logic; -- Enable input
|
||||
LoadA : in std_logic; -- Asynchronous Load
|
||||
TxD : out std_logic; -- RS-232 data output
|
||||
Busy : out std_logic; -- Tx Busy
|
||||
DataI : in std_logic_vector(7 downto 0)); -- Byte to transmit
|
||||
end TxUnit;
|
||||
|
||||
architecture Behaviour of TxUnit is
|
||||
|
||||
component synchroniser
|
||||
port (
|
||||
C1 : in std_logic; -- Asynchronous signal
|
||||
C : in std_logic; -- Clock
|
||||
O : out Std_logic);-- Synchronised signal
|
||||
end component;
|
||||
|
||||
signal TBuff : std_logic_vector(7 downto 0); -- transmit buffer
|
||||
signal TReg : std_logic_vector(7 downto 0); -- transmit register
|
||||
signal TBufL : std_logic; -- Buffer loaded
|
||||
signal LoadS : std_logic; -- Synchronised load signal
|
||||
|
||||
begin
|
||||
-- Synchronise Load on Clk
|
||||
SyncLoad : Synchroniser port map (LoadA, Clk, LoadS);
|
||||
Busy <= LoadS or TBufL;
|
||||
|
||||
-- Tx process
|
||||
TxProc : process(Clk, Reset, Enable, DataI, TBuff, TReg, TBufL)
|
||||
variable BitPos : INTEGER range 0 to 10; -- Bit position in the frame
|
||||
begin
|
||||
if Reset = '1' then
|
||||
TBufL <= '0';
|
||||
BitPos := 0;
|
||||
TxD <= '1';
|
||||
elsif Rising_Edge(Clk) then
|
||||
if LoadS = '1' then
|
||||
TBuff <= DataI;
|
||||
TBufL <= '1';
|
||||
end if;
|
||||
if Enable = '1' then
|
||||
case BitPos is
|
||||
when 0 => -- idle or stop bit
|
||||
TxD <= '1';
|
||||
if TBufL = '1' then -- start transmit. next is start bit
|
||||
TReg <= TBuff;
|
||||
TBufL <= '0';
|
||||
BitPos := 1;
|
||||
end if;
|
||||
when 1 => -- Start bit
|
||||
TxD <= '0';
|
||||
BitPos := 2;
|
||||
when others =>
|
||||
TxD <= TReg(BitPos-2); -- Serialisation of TReg
|
||||
BitPos := BitPos + 1;
|
||||
end case;
|
||||
if BitPos = 10 then -- bit8. next is stop bit
|
||||
BitPos := 0;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end Behaviour;
|
78
verilog/j1eforth/j1eforth-plus/fpga/src/clock.vhd
Normal file
78
verilog/j1eforth/j1eforth-plus/fpga/src/clock.vhd
Normal file
@ -0,0 +1,78 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.ALL;
|
||||
use ieee.numeric_std.ALL;
|
||||
library UNISIM;
|
||||
use UNISIM.Vcomponents.ALL;
|
||||
|
||||
entity clock is
|
||||
port ( clk_in : in std_logic;
|
||||
clk : out std_logic;
|
||||
clk180 : out std_logic);
|
||||
end clock;
|
||||
|
||||
architecture BEHAVIORAL of clock is
|
||||
|
||||
signal CLKFB_IN : std_logic;
|
||||
signal CLKFX_BUF : std_logic;
|
||||
signal CLKFX180_BUF : std_logic;
|
||||
signal CLKIN_IBUFG : std_logic;
|
||||
signal CLK2X_BUF : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
CLKFX_BUFG_INST : BUFG
|
||||
port map (I=>CLKFX_BUF,
|
||||
O=>clk);
|
||||
|
||||
CLKFX180_BUFG_INST : BUFG
|
||||
port map (I=>CLKFX180_BUF,
|
||||
O=>clk180);
|
||||
|
||||
CLKIN_IBUFG_INST : IBUFG
|
||||
port map (I=>clk_in,
|
||||
O=>CLKIN_IBUFG);
|
||||
|
||||
CLK2X_BUFG_INST : BUFG
|
||||
port map (I=>CLK2X_BUF,
|
||||
O=>CLKFB_IN);
|
||||
|
||||
DCM_SP_INST : DCM_SP
|
||||
generic map(
|
||||
CLK_FEEDBACK => "2X",
|
||||
CLKDV_DIVIDE => 4.0,
|
||||
CLKFX_DIVIDE => 1,
|
||||
CLKFX_MULTIPLY => 2,
|
||||
CLKIN_DIVIDE_BY_2 => FALSE,
|
||||
CLKIN_PERIOD => 31.250,
|
||||
CLKOUT_PHASE_SHIFT => "NONE",
|
||||
DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
|
||||
DFS_FREQUENCY_MODE => "LOW",
|
||||
DLL_FREQUENCY_MODE => "LOW",
|
||||
DUTY_CYCLE_CORRECTION=> TRUE,
|
||||
FACTORY_JF => x"C080",
|
||||
PHASE_SHIFT => 0,
|
||||
STARTUP_WAIT => TRUE)
|
||||
port map (
|
||||
CLKIN => CLKIN_IBUFG,
|
||||
CLKFB => CLKFB_IN,
|
||||
DSSEN => '0',
|
||||
PSCLK => '0',
|
||||
PSEN => '0',
|
||||
PSINCDEC => '0',
|
||||
RST => '0',
|
||||
CLKDV => open,
|
||||
CLKFX => CLKFX_BUF,
|
||||
CLKFX180 => CLKFX180_BUF,
|
||||
CLK2X => CLK2X_BUF,
|
||||
CLK2X180 => open,
|
||||
CLK0 => open,
|
||||
CLK90 => open,
|
||||
CLK180 => open,
|
||||
CLK270 => open,
|
||||
LOCKED => open,
|
||||
PSDONE => open,
|
||||
STATUS => open);
|
||||
|
||||
end BEHAVIORAL;
|
||||
|
||||
|
199
verilog/j1eforth/j1eforth-plus/fpga/src/j1.v
Normal file
199
verilog/j1eforth/j1eforth-plus/fpga/src/j1.v
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
Copyright (c) 2011
|
||||
James Bowman All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of James Bowman nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
module j1(
|
||||
input sys_clk_i, input sys_rst_i, input [15:0] io_din,
|
||||
output io_rd, output io_wr, output [15:0] io_addr, output [15:0] io_dout);
|
||||
|
||||
reg [15:0] insn;
|
||||
wire [15:0] immediate = { 1'b0, insn[14:0] };
|
||||
|
||||
reg [4:0] dsp; // Data stack pointer
|
||||
reg [4:0] _dsp;
|
||||
reg [15:0] st0; // Return stack pointer
|
||||
reg [15:0] _st0;
|
||||
wire _dstkW; // D stack write
|
||||
|
||||
reg [12:0] pc;
|
||||
reg [12:0] _pc;
|
||||
reg [4:0] rsp;
|
||||
reg [4:0] _rsp;
|
||||
reg _rstkW; // R stack write
|
||||
reg [15:0] _rstkD;
|
||||
wire _ramWE; // RAM write enable
|
||||
|
||||
wire [15:0] pc_plus_1;
|
||||
assign pc_plus_1 = pc + 1;
|
||||
|
||||
// The D and R stacks
|
||||
reg [15:0] dstack[0:31];
|
||||
reg [15:0] rstack[0:31];
|
||||
always @(posedge sys_clk_i)
|
||||
begin
|
||||
if (_dstkW)
|
||||
dstack[_dsp] = st0;
|
||||
if (_rstkW)
|
||||
rstack[_rsp] = _rstkD;
|
||||
end
|
||||
wire [15:0] st1 = dstack[dsp];
|
||||
wire [15:0] rst0 = rstack[rsp];
|
||||
|
||||
// st0sel is the ALU operation. For branch and call the operation
|
||||
// is T, for 0branch it is N. For ALU ops it is loaded from the instruction
|
||||
// field.
|
||||
reg [3:0] st0sel;
|
||||
always @*
|
||||
begin
|
||||
case (insn[14:13])
|
||||
2'b00: st0sel = 0; // ubranch
|
||||
2'b10: st0sel = 0; // call
|
||||
2'b01: st0sel = 1; // 0branch
|
||||
2'b11: st0sel = insn[11:8]; // ALU
|
||||
default: st0sel = 4'bxxxx;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
// Papilio Pro: main memory to be infered instead of specified explitely.
|
||||
reg [15:0] ram[0:16383]; initial $readmemh("../j1.hex", ram);
|
||||
|
||||
reg [15:0] mem_din;
|
||||
always @(posedge sys_clk_i) begin
|
||||
// $monitor("insn_addr= %h, insn = %h, sp=%h, rp=%h, S=%h %h", pc, insn, dsp, rsp, st1, st0);
|
||||
insn <= ram[_pc];
|
||||
mem_din <= ram[_st0[15:1]];
|
||||
if (_ramWE & (_st0[15:14] ==0))
|
||||
ram[_st0[15:1]] <= st1[15:0];
|
||||
end
|
||||
|
||||
|
||||
// Compute the new value of T.
|
||||
always @*
|
||||
begin
|
||||
if (insn[15])
|
||||
_st0 = immediate;
|
||||
else
|
||||
case (st0sel)
|
||||
4'b0000: _st0 = st0;
|
||||
4'b0001: _st0 = st1;
|
||||
4'b0010: _st0 = st0 + st1;
|
||||
4'b0011: _st0 = st0 & st1;
|
||||
4'b0100: _st0 = st0 | st1;
|
||||
4'b0101: _st0 = st0 ^ st1;
|
||||
4'b0110: _st0 = ~st0;
|
||||
4'b0111: _st0 = {16{(st1 == st0)}};
|
||||
4'b1000: _st0 = {16{($signed(st1) < $signed(st0))}};
|
||||
4'b1001: _st0 = st1 >> st0[3:0];
|
||||
4'b1010: _st0 = st0 - 1;
|
||||
4'b1011: _st0 = rst0;
|
||||
4'b1100: _st0 = |st0[15:14] ? io_din : mem_din;
|
||||
4'b1101: _st0 = st1 << st0[3:0];
|
||||
4'b1110: _st0 = {rsp, 3'b000, dsp};
|
||||
4'b1111: _st0 = {16{(st1 < st0)}};
|
||||
default: _st0 = 16'hxxxx;
|
||||
endcase
|
||||
end
|
||||
|
||||
wire is_alu = (insn[15:13] == 3'b011);
|
||||
wire is_lit = (insn[15]);
|
||||
|
||||
assign io_rd = (is_alu & (insn[11:8] == 4'hc));
|
||||
assign io_wr = _ramWE;
|
||||
assign io_addr = st0;
|
||||
assign io_dout = st1;
|
||||
|
||||
assign _ramWE = is_alu & insn[5];
|
||||
assign _dstkW = is_lit | (is_alu & insn[7]);
|
||||
|
||||
wire [1:0] dd = insn[1:0]; // D stack delta
|
||||
wire [1:0] rd = insn[3:2]; // R stack delta
|
||||
|
||||
always @*
|
||||
begin
|
||||
if (is_lit) begin // literal
|
||||
_dsp = dsp + 1;
|
||||
_rsp = rsp;
|
||||
_rstkW = 0;
|
||||
_rstkD = _pc;
|
||||
end else if (is_alu) begin
|
||||
_dsp = dsp + {dd[1], dd[1], dd[1], dd};
|
||||
_rsp = rsp + {rd[1], rd[1], rd[1], rd};
|
||||
_rstkW = insn[6];
|
||||
_rstkD = st0;
|
||||
end else begin // jump/call
|
||||
// predicated jump is like DROP
|
||||
if (insn[15:13] == 3'b001) begin
|
||||
_dsp = dsp - 1;
|
||||
end else begin
|
||||
_dsp = dsp;
|
||||
end
|
||||
if (insn[15:13] == 3'b010) begin // call
|
||||
_rsp = rsp + 1;
|
||||
_rstkW = 1;
|
||||
_rstkD = {pc_plus_1[14:0], 1'b0};
|
||||
end else begin
|
||||
_rsp = rsp;
|
||||
_rstkW = 0;
|
||||
_rstkD = _pc;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @*
|
||||
begin
|
||||
if (sys_rst_i)
|
||||
_pc = pc;
|
||||
else
|
||||
if ((insn[15:13] == 3'b000) |
|
||||
((insn[15:13] == 3'b001) & (|st0 == 0)) |
|
||||
(insn[15:13] == 3'b010))
|
||||
_pc = insn[12:0];
|
||||
else if (is_alu & insn[12])
|
||||
_pc = rst0[15:1];
|
||||
else
|
||||
_pc = pc_plus_1;
|
||||
end
|
||||
|
||||
always @(posedge sys_clk_i)
|
||||
begin
|
||||
if (sys_rst_i) begin
|
||||
pc <= 0;
|
||||
dsp <= 0;
|
||||
st0 <= 0;
|
||||
rsp <= 0;
|
||||
end else begin
|
||||
dsp <= _dsp;
|
||||
pc <= _pc;
|
||||
st0 <= _st0;
|
||||
rsp <= _rsp;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule // j1
|
146
verilog/j1eforth/j1eforth-plus/fpga/src/miniuart.vhd
Normal file
146
verilog/j1eforth/j1eforth-plus/fpga/src/miniuart.vhd
Normal file
@ -0,0 +1,146 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- Title : MINIUART2 -- this is a modified version without Wishbone interface
|
||||
-- Project : MINIUART2
|
||||
-------------------------------------------------------------------------------
|
||||
-- File : MiniUart.vhd
|
||||
-- Author : Philippe CARTON
|
||||
-- (philippe.carton2@libertysurf.fr)
|
||||
-- Organization:
|
||||
-- Created : 15/12/2001
|
||||
-- Last update : 8/1/2003
|
||||
-- Platform : Foundation 3.1i
|
||||
-- Simulators : ModelSim 5.5b
|
||||
-- Synthesizers: Xilinx Synthesis
|
||||
-- Targets : Xilinx Spartan
|
||||
-- Dependency : IEEE std_logic_1164, Rxunit.vhd, Txunit.vhd, utils.vhd
|
||||
-------------------------------------------------------------------------------
|
||||
-- Description: Uart (Universal Asynchronous Receiver Transmitter) for SoC.
|
||||
-- Wishbone compatable.
|
||||
-------------------------------------------------------------------------------
|
||||
-- Copyright (c) notice
|
||||
-- This core adheres to the GNU public license
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
-- Revisions :
|
||||
-- Revision Number :
|
||||
-- Version :
|
||||
-- Date :
|
||||
-- Modifier : name <email>
|
||||
-- Description :
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
-- Revision History:
|
||||
-- 2014-12-19: removed wishbone interface (uh@xlerb.de)
|
||||
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
entity MINIUART2 is
|
||||
generic(BRDIVISOR: INTEGER range 0 to 65535 := 143); -- Baud rate divisor 143 = 115200 at 66 Mhz
|
||||
port (
|
||||
clk: in STD_LOGIC;
|
||||
rst: in STD_LOGIC;
|
||||
rx: in STD_LOGIC;
|
||||
tx: out STD_LOGIC;
|
||||
io_rd: in STD_LOGIC;
|
||||
io_wr: in STD_LOGIC;
|
||||
io_addr: in STD_LOGIC;
|
||||
io_din: in STD_LOGIC_VECTOR (15 downto 0);
|
||||
io_dout: out STD_LOGIC_VECTOR (15 downto 0));
|
||||
end MINIUART2;
|
||||
|
||||
-- Architecture for UART for synthesis
|
||||
architecture Behaviour of MINIUART2 is
|
||||
|
||||
component Counter
|
||||
generic(COUNT: INTEGER range 0 to 65535); -- Count revolution
|
||||
port (
|
||||
Clk : in std_logic; -- Clock
|
||||
Reset : in std_logic; -- Reset input
|
||||
CE : in std_logic; -- Chip Enable
|
||||
O : out std_logic); -- Output
|
||||
end component;
|
||||
|
||||
component RxUnit
|
||||
port (
|
||||
Clk : in std_logic; -- system clock signal
|
||||
Reset : in std_logic; -- Reset input
|
||||
Enable : in std_logic; -- Enable input
|
||||
ReadA : in Std_logic; -- Async Read Received Byte
|
||||
RxD : in std_logic; -- RS-232 data input
|
||||
RxAv : out std_logic; -- Byte available
|
||||
DataO : out std_logic_vector(7 downto 0)); -- Byte received
|
||||
end component;
|
||||
|
||||
component TxUnit
|
||||
port (
|
||||
Clk : in std_logic; -- Clock signal
|
||||
Reset : in std_logic; -- Reset input
|
||||
Enable : in std_logic; -- Enable input
|
||||
LoadA : in std_logic; -- Asynchronous Load
|
||||
TxD : out std_logic; -- RS-232 data output
|
||||
Busy : out std_logic; -- Tx Busy
|
||||
DataI : in std_logic_vector(7 downto 0)); -- Byte to transmit
|
||||
end component;
|
||||
|
||||
signal RxData : std_logic_vector(7 downto 0); -- Last Byte received
|
||||
signal TxData : std_logic_vector(7 downto 0); -- Last bytes transmitted
|
||||
signal SReg : std_logic_vector(7 downto 0); -- Status register
|
||||
signal EnabRx : std_logic; -- Enable RX unit
|
||||
signal EnabTx : std_logic; -- Enable TX unit
|
||||
signal RxAv : std_logic; -- Data Received
|
||||
signal TxBusy : std_logic; -- Transmiter Busy
|
||||
signal ReadA : std_logic; -- Async Read receive buffer
|
||||
signal LoadA : std_logic; -- Async Load transmit buffer
|
||||
signal Sig0 : std_logic; -- gnd signal
|
||||
signal Sig1 : std_logic; -- vcc signal
|
||||
|
||||
|
||||
begin
|
||||
sig0 <= '0';
|
||||
sig1 <= '1';
|
||||
Uart_Rxrate : Counter -- Baud Rate adjust
|
||||
generic map (COUNT => BRDIVISOR)
|
||||
port map (clk, rst, sig1, EnabRx);
|
||||
Uart_Txrate : Counter -- 4 Divider for Tx
|
||||
generic map (COUNT => 4)
|
||||
port map (clk, rst, EnabRx, EnabTx);
|
||||
Uart_TxUnit : TxUnit port map (clk, rst, EnabTX, LoadA, tx, TxBusy, TxData);
|
||||
Uart_RxUnit : RxUnit port map (clk, rst, EnabRX, ReadA, rx, RxAv, RxData);
|
||||
|
||||
-- status register
|
||||
SReg(0) <= RxAv;
|
||||
SReg(1) <= TxBusy;
|
||||
SReg(7 downto 2) <= (others => '0'); -- the rest is silence
|
||||
|
||||
process (clk, rst, io_addr, io_wr, io_din)
|
||||
begin
|
||||
if Rising_Edge(clk) then
|
||||
if rst='1' then
|
||||
LoadA <= '0';
|
||||
elsif io_wr='1' and io_addr='0' then -- write byte to tx
|
||||
TxData <= io_din(7 downto 0);
|
||||
LoadA <= '1';
|
||||
else
|
||||
LoadA <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (clk, rst, io_addr, io_rd, RxData, TxBusy, RxAv)
|
||||
begin
|
||||
if Rising_Edge(clk) then
|
||||
if rst='1' then
|
||||
ReadA <= '0';
|
||||
elsif io_rd='1' and io_addr='0' then
|
||||
ReadA <= '1';
|
||||
else
|
||||
ReadA <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
io_dout(7 downto 0) <= RxData when io_addr='0' else SReg;
|
||||
io_dout(15 downto 8) <= (others => '0');
|
||||
|
||||
end Behaviour;
|
117
verilog/j1eforth/j1eforth-plus/fpga/src/papilio-pro-j1.vhd
Normal file
117
verilog/j1eforth/j1eforth-plus/fpga/src/papilio-pro-j1.vhd
Normal file
@ -0,0 +1,117 @@
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
entity papilio_pro_j1 is
|
||||
port (
|
||||
clk_in: in std_logic;
|
||||
rx: in std_logic;
|
||||
tx: out std_logic;
|
||||
wing: out std_logic_vector(15 downto 0));
|
||||
end papilio_pro_j1;
|
||||
|
||||
architecture Behavioral of papilio_pro_j1 is
|
||||
|
||||
component clock is
|
||||
port (
|
||||
clk_in: in std_logic;
|
||||
clk: out std_logic;
|
||||
clk180: out std_logic);
|
||||
end component;
|
||||
|
||||
component j1 is
|
||||
port (
|
||||
sys_clk_i: in std_logic;
|
||||
sys_rst_i: in std_logic;
|
||||
io_rd: out std_logic;
|
||||
io_wr: out std_logic;
|
||||
io_addr: out std_logic_vector (15 downto 0);
|
||||
io_din: in std_logic_vector (15 downto 0);
|
||||
io_dout: out std_logic_vector (15 downto 0));
|
||||
end component;
|
||||
|
||||
component miniuart2 is
|
||||
port (
|
||||
clk: in STD_LOGIC;
|
||||
rst: in STD_LOGIC;
|
||||
rx: in STD_LOGIC;
|
||||
tx: out STD_LOGIC;
|
||||
io_rd: in STD_LOGIC;
|
||||
io_wr: in STD_LOGIC;
|
||||
io_addr: in STD_LOGIC;
|
||||
io_din: in STD_LOGIC_VECTOR (15 downto 0);
|
||||
io_dout: out STD_LOGIC_VECTOR (15 downto 0));
|
||||
end component;
|
||||
|
||||
|
||||
signal clk: std_logic;
|
||||
signal clk180: std_logic;
|
||||
|
||||
signal rst_counter: integer range 0 to 15 := 15;
|
||||
signal sys_rst: std_logic := '1';
|
||||
|
||||
signal io_rd: std_logic;
|
||||
signal io_wr: std_logic;
|
||||
signal io_addr: std_logic_vector (15 downto 0);
|
||||
signal io_din: std_logic_vector (15 downto 0);
|
||||
signal io_dout: std_logic_vector (15 downto 0);
|
||||
|
||||
signal uart_en: std_logic;
|
||||
signal uart_rd: std_logic;
|
||||
signal uart_wr: std_logic;
|
||||
signal uart_dout: std_logic_vector (15 downto 0);
|
||||
begin
|
||||
|
||||
clock_inst: clock
|
||||
port map (
|
||||
clk_in => clk_in,
|
||||
clk => clk,
|
||||
clk180 => clk180);
|
||||
|
||||
j1_inst: j1
|
||||
port map (
|
||||
sys_clk_i => clk,
|
||||
sys_rst_i => sys_rst,
|
||||
io_rd => io_rd,
|
||||
io_wr => io_wr,
|
||||
io_addr => io_addr,
|
||||
io_din => io_din,
|
||||
io_dout => io_dout);
|
||||
|
||||
uart_inst: miniuart2
|
||||
port map(
|
||||
clk => clk180,
|
||||
rst => sys_rst,
|
||||
rx => rx,
|
||||
tx => tx,
|
||||
io_rd => uart_rd,
|
||||
io_wr => uart_wr,
|
||||
io_addr => io_addr(0),
|
||||
io_din => io_dout,
|
||||
io_dout => uart_dout);
|
||||
|
||||
process (clk, rst_counter)
|
||||
begin
|
||||
if rising_edge(clk) and rst_counter>0 then
|
||||
rst_counter <= rst_counter-1;
|
||||
end if;
|
||||
end process;
|
||||
sys_rst <= '1' when rst_counter>0 else '0';
|
||||
|
||||
uart_en <= '1' when io_addr(15 downto 1)="111100000000000" else '0';
|
||||
uart_rd <= io_rd and uart_en;
|
||||
uart_wr <= io_wr and uart_en;
|
||||
|
||||
process (io_addr, uart_dout)
|
||||
begin
|
||||
case io_addr(15 downto 1) is
|
||||
when "111100000000000" =>
|
||||
io_din <= uart_dout;
|
||||
when others =>
|
||||
io_din <= (others=>'0');
|
||||
end case;
|
||||
end process;
|
||||
|
||||
wing <= (others=>'0');
|
||||
|
||||
end Behavioral;
|
143
verilog/j1eforth/j1eforth-plus/fpga/src/papilio-pro.ucf
Normal file
143
verilog/j1eforth/j1eforth-plus/fpga/src/papilio-pro.ucf
Normal file
@ -0,0 +1,143 @@
|
||||
# UCF file for the Papilio Pro 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 CLK_IN LOC="P94" | IOSTANDARD=LVTTL | PERIOD=31.25ns; # CLK
|
||||
NET RX LOC="P101" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # RX
|
||||
NET TX LOC="P105" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # TX
|
||||
NET WING(0) LOC="P48" | IOSTANDARD=LVTTL; # A0
|
||||
NET WING(1) LOC="P51" | IOSTANDARD=LVTTL; # A1
|
||||
NET WING(2) LOC="P56" | IOSTANDARD=LVTTL; # A2
|
||||
NET WING(3) LOC="P58" | IOSTANDARD=LVTTL; # A3
|
||||
NET WING(4) LOC="P61" | IOSTANDARD=LVTTL; # A4
|
||||
NET WING(5) LOC="P66" | IOSTANDARD=LVTTL; # A5
|
||||
NET WING(6) LOC="P67" | IOSTANDARD=LVTTL; # A6
|
||||
NET WING(7) LOC="P75" | IOSTANDARD=LVTTL; # A7
|
||||
NET WING(8) LOC="P79" | IOSTANDARD=LVTTL; # A8
|
||||
NET WING(9) LOC="P81" | IOSTANDARD=LVTTL; # A9
|
||||
NET WING(10) LOC="P83" | IOSTANDARD=LVTTL; # A10
|
||||
NET WING(11) LOC="P85" | IOSTANDARD=LVTTL; # A11
|
||||
NET WING(12) LOC="P88" | IOSTANDARD=LVTTL; # A12
|
||||
NET WING(13) LOC="P93" | IOSTANDARD=LVTTL; # A13
|
||||
NET WING(14) LOC="P98" | IOSTANDARD=LVTTL; # A14
|
||||
NET WING(15) LOC="P100" | IOSTANDARD=LVTTL; # A15
|
||||
#NET A(0) LOC="P48" | IOSTANDARD=LVTTL; # A0
|
||||
#NET A(1) LOC="P51" | IOSTANDARD=LVTTL; # A1
|
||||
#NET A(2) LOC="P56" | IOSTANDARD=LVTTL; # A2
|
||||
#NET A(3) LOC="P58" | IOSTANDARD=LVTTL; # A3
|
||||
#NET A(4) LOC="P61" | IOSTANDARD=LVTTL; # A4
|
||||
#NET A(5) LOC="P66" | IOSTANDARD=LVTTL; # A5
|
||||
#NET A(6) LOC="P67" | IOSTANDARD=LVTTL; # A6
|
||||
#NET A(7) LOC="P75" | IOSTANDARD=LVTTL; # A7
|
||||
#NET A(8) LOC="P79" | IOSTANDARD=LVTTL; # A8
|
||||
#NET A(9) LOC="P81" | IOSTANDARD=LVTTL; # A9
|
||||
#NET A(10) LOC="P83" | IOSTANDARD=LVTTL; # A10
|
||||
#NET A(11) LOC="P85" | IOSTANDARD=LVTTL; # A11
|
||||
#NET A(12) LOC="P88" | IOSTANDARD=LVTTL; # A12
|
||||
#NET A(13) LOC="P93" | IOSTANDARD=LVTTL; # A13
|
||||
#NET A(14) LOC="P98" | IOSTANDARD=LVTTL; # A14
|
||||
#NET A(15) LOC="P100" | IOSTANDARD=LVTTL; # A15
|
||||
#NET B(0) LOC="P99" | IOSTANDARD=LVTTL; # B0
|
||||
#NET B(1) LOC="P97" | IOSTANDARD=LVTTL; # B1
|
||||
#NET B(2) LOC="P92" | IOSTANDARD=LVTTL; # B2
|
||||
#NET B(3) LOC="P87" | IOSTANDARD=LVTTL; # B3
|
||||
#NET B(4) LOC="P84" | IOSTANDARD=LVTTL; # B4
|
||||
#NET B(5) LOC="P82" | IOSTANDARD=LVTTL; # B5
|
||||
#NET B(6) LOC="P80" | IOSTANDARD=LVTTL; # B6
|
||||
#NET B(7) LOC="P78" | IOSTANDARD=LVTTL; # B7
|
||||
#NET B(8) LOC="P74" | IOSTANDARD=LVTTL; # B8
|
||||
#NET B(9) LOC="P95" | IOSTANDARD=LVTTL; # B9
|
||||
#NET B(10) LOC="P62" | IOSTANDARD=LVTTL; # B10
|
||||
#NET B(11) LOC="P59" | IOSTANDARD=LVTTL; # B11
|
||||
#NET B(12) LOC="P57" | IOSTANDARD=LVTTL; # B12
|
||||
#NET B(13) LOC="P55" | IOSTANDARD=LVTTL; # B13
|
||||
#NET B(14) LOC="P50" | IOSTANDARD=LVTTL; # B14
|
||||
#NET B(15) LOC="P47" | IOSTANDARD=LVTTL; # B15
|
||||
#NET C(0) LOC="P114" | IOSTANDARD=LVTTL; # C0
|
||||
#NET C(1) LOC="P115" | IOSTANDARD=LVTTL; # C1
|
||||
#NET C(2) LOC="P116" | IOSTANDARD=LVTTL; # C2
|
||||
#NET C(3) LOC="P117" | IOSTANDARD=LVTTL; # C3
|
||||
#NET C(4) LOC="P118" | IOSTANDARD=LVTTL; # C4
|
||||
#NET C(5) LOC="P119" | IOSTANDARD=LVTTL; # C5
|
||||
#NET C(6) LOC="P120" | IOSTANDARD=LVTTL; # C6
|
||||
#NET C(7) LOC="P121" | IOSTANDARD=LVTTL; # C7
|
||||
#NET C(8) LOC="P123" | IOSTANDARD=LVTTL; # C8
|
||||
#NET C(9) LOC="P124" | IOSTANDARD=LVTTL; # C9
|
||||
#NET C(10) LOC="P126" | IOSTANDARD=LVTTL; # C10
|
||||
#NET C(11) LOC="P127" | IOSTANDARD=LVTTL; # C11
|
||||
#NET C(12) LOC="P131" | IOSTANDARD=LVTTL; # C12
|
||||
#NET C(13) LOC="P132" | IOSTANDARD=LVTTL; # C13
|
||||
#NET C(14) LOC="P133" | IOSTANDARD=LVTTL; # C14
|
||||
#NET C(15) LOC="P134" | IOSTANDARD=LVTTL; # C15
|
||||
#NET SDRAM_ADDR(0) LOC="P140" | IOSTANDARD=LVTTL; # SDRAM_ADDR0
|
||||
#NET SDRAM_ADDR(1) LOC="P139" | IOSTANDARD=LVTTL; # SDRAM_ADDR1
|
||||
#NET SDRAM_ADDR(2) LOC="P138" | IOSTANDARD=LVTTL; # SDRAM_ADDR2
|
||||
#NET SDRAM_ADDR(3) LOC="P137" | IOSTANDARD=LVTTL; # SDRAM_ADDR3
|
||||
#NET SDRAM_ADDR(4) LOC="P46" | IOSTANDARD=LVTTL; # SDRAM_ADDR4
|
||||
#NET SDRAM_ADDR(5) LOC="P45" | IOSTANDARD=LVTTL; # SDRAM_ADDR5
|
||||
#NET SDRAM_ADDR(6) LOC="P44" | IOSTANDARD=LVTTL; # SDRAM_ADDR6
|
||||
#NET SDRAM_ADDR(7) LOC="P43" | IOSTANDARD=LVTTL; # SDRAM_ADDR7
|
||||
#NET SDRAM_ADDR(8) LOC="P41" | IOSTANDARD=LVTTL; # SDRAM_ADDR8
|
||||
#NET SDRAM_ADDR(9) LOC="P40" | IOSTANDARD=LVTTL; # SDRAM_ADDR9
|
||||
#NET SDRAM_ADDR(10) LOC="P141" | IOSTANDARD=LVTTL; # SDRAM_ADDR10
|
||||
#NET SDRAM_ADDR(11) LOC="P35" | IOSTANDARD=LVTTL; # SDRAM_ADDR11
|
||||
#NET SDRAM_ADDR(12) LOC="P34" | IOSTANDARD=LVTTL; # SDRAM_ADDR12
|
||||
#NET SDRAM_DATA(0) LOC="P9" | IOSTANDARD=LVTTL; # SDRAM_DATA0
|
||||
#NET SDRAM_DATA(1) LOC="P10" | IOSTANDARD=LVTTL; # SDRAM_DATA1
|
||||
#NET SDRAM_DATA(2) LOC="P11" | IOSTANDARD=LVTTL; # SDRAM_DATA2
|
||||
#NET SDRAM_DATA(3) LOC="P12" | IOSTANDARD=LVTTL; # SDRAM_DATA3
|
||||
#NET SDRAM_DATA(4) LOC="P14" | IOSTANDARD=LVTTL; # SDRAM_DATA4
|
||||
#NET SDRAM_DATA(5) LOC="P15" | IOSTANDARD=LVTTL; # SDRAM_DATA5
|
||||
#NET SDRAM_DATA(6) LOC="P16" | IOSTANDARD=LVTTL; # SDRAM_DATA6
|
||||
#NET SDRAM_DATA(7) LOC="P8" | IOSTANDARD=LVTTL; # SDRAM_DATA7
|
||||
#NET SDRAM_DATA(8) LOC="P21" | IOSTANDARD=LVTTL; # SDRAM_DATA8
|
||||
#NET SDRAM_DATA(9) LOC="P22" | IOSTANDARD=LVTTL; # SDRAM_DATA9
|
||||
#NET SDRAM_DATA(10) LOC="P23" | IOSTANDARD=LVTTL; # SDRAM_DATA10
|
||||
#NET SDRAM_DATA(11) LOC="P24" | IOSTANDARD=LVTTL; # SDRAM_DATA11
|
||||
#NET SDRAM_DATA(12) LOC="P26" | IOSTANDARD=LVTTL; # SDRAM_DATA12
|
||||
#NET SDRAM_DATA(13) LOC="P27" | IOSTANDARD=LVTTL; # SDRAM_DATA13
|
||||
#NET SDRAM_DATA(14) LOC="P29" | IOSTANDARD=LVTTL; # SDRAM_DATA14
|
||||
#NET SDRAM_DATA(15) LOC="P30" | IOSTANDARD=LVTTL; # SDRAM_DATA15
|
||||
#NET SDRAM_DQML LOC="P7" | IOSTANDARD=LVTTL; # SDRAM_DQML
|
||||
#NET SDRAM_DQMH LOC="P17" | IOSTANDARD=LVTTL; # SDRAM_DQMH
|
||||
#NET SDRAM_BA(0) LOC="P143" | IOSTANDARD=LVTTL; # SDRAM_BA0
|
||||
#NET SDRAM_BA(1) LOC="P142" | IOSTANDARD=LVTTL; # SDRAM_BA1
|
||||
#NET SDRAM_nWE LOC="P6" | IOSTANDARD=LVTTL; # SDRAM_nWE
|
||||
#NET SDRAM_nCAS LOC="P5" | IOSTANDARD=LVTTL; # SDRAM_nCAS
|
||||
#NET SDRAM_nRAS LOC="P2" | IOSTANDARD=LVTTL; # SDRAM_nRAS
|
||||
#NET SDRAM_CS LOC="P1" | IOSTANDARD=LVTTL; # SDRAM_CS
|
||||
#NET SDRAM_CLK LOC="P32" | IOSTANDARD=LVTTL; # SDRAM_CLK
|
||||
#NET SDRAM_CKE LOC="P33" | IOSTANDARD=LVTTL; # SDRAM_CKE
|
||||
#NET LED1 LOC="P112" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; # LED1
|
||||
#NET JTAG_TMS LOC="P107" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TMS
|
||||
#NET JTAG_TCK LOC="P109" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TCK
|
||||
#NET JTAG_TDI LOC="P110" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TDI
|
||||
#NET JTAG_TDO LOC="P106" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TDO
|
||||
#NET FLASH_CS LOC="P38" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CS
|
||||
#NET FLASH_CK LOC="P70" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CK
|
||||
#NET FLASH_SI LOC="P64" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_SI
|
||||
#NET FLASH_SO LOC="P65" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # FLASH_SO
|
132
verilog/j1eforth/j1eforth-plus/fpga/src/utils.vhd
Normal file
132
verilog/j1eforth/j1eforth-plus/fpga/src/utils.vhd
Normal file
@ -0,0 +1,132 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- Title : UART
|
||||
-- Project : UART
|
||||
-------------------------------------------------------------------------------
|
||||
-- File : utils.vhd
|
||||
-- Author : Philippe CARTON
|
||||
-- (philippe.carton2@libertysurf.fr)
|
||||
-- Organization:
|
||||
-- Created : 15/12/2001
|
||||
-- Last update : 8/1/2003
|
||||
-- Platform : Foundation 3.1i
|
||||
-- Simulators : ModelSim 5.5b
|
||||
-- Synthesizers: Xilinx Synthesis
|
||||
-- Targets : Xilinx Spartan
|
||||
-- Dependency : IEEE std_logic_1164
|
||||
-------------------------------------------------------------------------------
|
||||
-- Description: VHDL utility file
|
||||
-------------------------------------------------------------------------------
|
||||
-- Copyright (c) notice
|
||||
-- This core adheres to the GNU public license
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
-- Revisions :
|
||||
-- Revision Number :
|
||||
-- Version :
|
||||
-- Date :
|
||||
-- Modifier : name <email>
|
||||
-- Description :
|
||||
--
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Revision list
|
||||
-- Version Author Date Changes
|
||||
--
|
||||
-- 1.0 Philippe CARTON 19 December 2001 New model
|
||||
-- philippe.carton2@libertysurf.fr
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Synchroniser:
|
||||
-- Synchronize an input signal (C1) with an input clock (C).
|
||||
-- The result is the O signal which is synchronous of C, and persist for
|
||||
-- one C clock period.
|
||||
--------------------------------------------------------------------------------
|
||||
library IEEE,STD;
|
||||
use IEEE.std_logic_1164.all;
|
||||
|
||||
entity synchroniser is
|
||||
port (
|
||||
C1 : in std_logic;-- Asynchronous signal
|
||||
C : in std_logic;-- Clock
|
||||
O : out std_logic);-- Synchronised signal
|
||||
end synchroniser;
|
||||
|
||||
architecture Behaviour of synchroniser is
|
||||
signal C1A : std_logic;
|
||||
signal C1S : std_logic;
|
||||
signal R : std_logic;
|
||||
begin
|
||||
RiseC1A : process(C1,R)
|
||||
begin
|
||||
if Rising_Edge(C1) then
|
||||
C1A <= '1';
|
||||
end if;
|
||||
if (R = '1') then
|
||||
C1A <= '0';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
SyncP : process(C,R)
|
||||
begin
|
||||
if Rising_Edge(C) then
|
||||
if (C1A = '1') then
|
||||
C1S <= '1';
|
||||
else C1S <= '0';
|
||||
end if;
|
||||
if (C1S = '1') then
|
||||
R <= '1';
|
||||
else R <= '0';
|
||||
end if;
|
||||
end if;
|
||||
if (R = '1') then
|
||||
C1S <= '0';
|
||||
end if;
|
||||
end process;
|
||||
O <= C1S;
|
||||
end Behaviour;
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Counter
|
||||
-- This counter is a parametrizable clock divider.
|
||||
-- The count value is the generic parameter Count.
|
||||
-- It is CE enabled. (it will count only if CE is high).
|
||||
-- When it overflow, it will emit a pulse on O.
|
||||
-- It can be reseted to 0.
|
||||
-------------------------------------------------------------------------------
|
||||
library IEEE,STD;
|
||||
use IEEE.std_logic_1164.all;
|
||||
|
||||
entity Counter is
|
||||
generic(Count: INTEGER range 0 to 65535); -- Count revolution
|
||||
port (
|
||||
Clk : in std_logic; -- Clock
|
||||
Reset : in std_logic; -- Reset input
|
||||
CE : in std_logic; -- Chip Enable
|
||||
O : out std_logic); -- Output
|
||||
end Counter;
|
||||
|
||||
architecture Behaviour of Counter is
|
||||
begin
|
||||
counter : process(Clk,Reset)
|
||||
variable Cnt : INTEGER range 0 to Count-1;
|
||||
begin
|
||||
if Reset = '1' then
|
||||
Cnt := Count - 1;
|
||||
O <= '0';
|
||||
elsif Rising_Edge(Clk) then
|
||||
if CE = '1' then
|
||||
if Cnt = 0 then
|
||||
O <= '1';
|
||||
Cnt := Count - 1;
|
||||
else
|
||||
O <= '0';
|
||||
Cnt := Cnt - 1;
|
||||
end if;
|
||||
else O <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end Behaviour;
|
249
verilog/j1eforth/j1eforth-plus/ipv4.4th
Normal file
249
verilog/j1eforth/j1eforth-plus/ipv4.4th
Normal file
@ -0,0 +1,249 @@
|
||||
(
|
||||
I feel that the Kernel is at it's best for now and that I can proceed
|
||||
to do some other things. Note that version 1 is just to make the whole
|
||||
thing work, later on I might look at optimisation where I might have to move
|
||||
some stuff around so that memory utilization and execution speed efficiency is
|
||||
achieved.So far the Kernel works without needing tweaks.
|
||||
|
||||
Work in progress: Implementing simple ipv4 for the j1eforth model
|
||||
|
||||
7 project targets:
|
||||
|
||||
1. Add multi-tasking support to the Kernel - 0%
|
||||
2. Modify j1 sim to use pcap interface for network tx and rx - 0%
|
||||
3. ARP - 0%
|
||||
4. ICMP - 0%
|
||||
5. IP - 0%
|
||||
6. UDP - 0%
|
||||
7. TCP - 0%
|
||||
|
||||
Hopefully I will get time to do all this and also document the design of
|
||||
the j1eforth Kernel for those who are starting out with forth and also those
|
||||
who wish to tinker with the Kernel for fun.
|
||||
)
|
||||
|
||||
hex
|
||||
|
||||
forth-wordlist >voc forth
|
||||
|
||||
vocabulary ipv4.1
|
||||
only forth also ipv4.1
|
||||
|
||||
ipv4.1 definitions
|
||||
|
||||
variable active_struct
|
||||
|
||||
: field
|
||||
create over , +
|
||||
does>
|
||||
@ active_struct @ + ;
|
||||
|
||||
( ethernet frame )
|
||||
|
||||
0
|
||||
6 field eth_dest ( 48 bit source address )
|
||||
6 field eth_src ( 48 bit destination address )
|
||||
2 field eth_type ( 16 bit type )
|
||||
constant eth_frame%
|
||||
|
||||
( arp message )
|
||||
|
||||
0
|
||||
2 field arp_hw ( 16 bit hw type )
|
||||
2 field arp_proto ( 16 bit protocol )
|
||||
1 field arp_hlen ( 8 bit hw address length )
|
||||
1 field arp_plen ( 8 bit protocol address length )
|
||||
2 field arp_op ( 16 bit operation )
|
||||
6 field arp_shw ( 48 bit sender hw address )
|
||||
4 field arp_sp ( 32 bit sender ipv4 address )
|
||||
6 field arp_thw ( 48 bit target hw address )
|
||||
4 field arp_tp ( 32 bit target ipv4 address )
|
||||
constant arp_message%
|
||||
|
||||
( arp cache )
|
||||
|
||||
0
|
||||
4 field ac_ip ( 32 bit protocol address )
|
||||
6 field ac_hw ( 48 bit hw address )
|
||||
constant arp_cache%
|
||||
|
||||
( ipv4 datagram header )
|
||||
|
||||
0
|
||||
1 field ip_vhl ( 4 bit version and 4 bit header length )
|
||||
1 field ip_tos ( 8 bit type of service )
|
||||
2 field ip_len ( 16 bit length )
|
||||
2 field ip_id ( 16 bit identification )
|
||||
2 field ip_frags ( 3 bit flags 13 bit fragment offset )
|
||||
1 field ip_ttl ( 8 bit time to live )
|
||||
1 field ip_proto ( 8 bit protocol number )
|
||||
2 field ip_checksum ( 16 bit checksum )
|
||||
4 field ip_source ( 32 bit source address )
|
||||
4 field ip_dest ( 32 bit destination address )
|
||||
constant ip_header%
|
||||
|
||||
( icmp header )
|
||||
|
||||
0
|
||||
1 field icmp_type ( 8 bits type )
|
||||
1 field icmp_code ( 8 bits code )
|
||||
2 field icmp_checksum ( 16 bits checksum )
|
||||
constant icmp_header%
|
||||
|
||||
( udp datagram )
|
||||
|
||||
0
|
||||
2 field udp_source ( 16 bit source port )
|
||||
2 field udp_dest ( 16 bit destination port )
|
||||
2 field udp_len ( 16 bit length )
|
||||
2 field udp_checksum ( 16 bit checksum )
|
||||
constant udp_datagram%
|
||||
|
||||
( tcp header )
|
||||
|
||||
0
|
||||
2 field tcp_source ( 16 bit source port )
|
||||
2 field tcp_dest ( 16 bit destination port )
|
||||
4 field tcp_seq ( 32 bit sequence number )
|
||||
4 field tcp_ack ( 32 bit acknowledgement )
|
||||
1 field tcp_offset ( 8 bit offset )
|
||||
2 field tcp_flags ( 16 bit flags )
|
||||
1 field tcp_window ( 8 bit window size )
|
||||
2 field tcp_checksum ( 16 bit checksum )
|
||||
2 field tcp_urgent ( 16 bit urgent pointer )
|
||||
constant tcp_header%
|
||||
|
||||
4000 constant eth_rx_buf
|
||||
|
||||
: htons ( n -- n )
|
||||
dup ff and 8 lshift swap ff00 and 8 rshift or ;
|
||||
|
||||
create ip_addr a8c0 , fe0b ,
|
||||
create ip_netmask ffff , 00ff ,
|
||||
create hw_addr bd00 , 333b , 7f05 ,
|
||||
|
||||
8 constant eth_ip_type
|
||||
608 constant eth_arp_type
|
||||
3580 constant eth_rarp_type
|
||||
|
||||
100 constant arp_request_type
|
||||
200 constant arp_reply_type
|
||||
|
||||
0 constant icmp_echo_reply
|
||||
8 constant icmp_echo
|
||||
|
||||
0 constant arp_action
|
||||
|
||||
: arp_lookup 0 to arp_action ;
|
||||
: arp_update 1 to arp_action ;
|
||||
: arp_insert 2 to arp_action ;
|
||||
: arp_delete 3 to arp_action ;
|
||||
: +arp_age 4 to arp_action ;
|
||||
|
||||
: (arp_lookup) cr ." compare" . . ;
|
||||
: (arp_update) cr ." update" . . ;
|
||||
: (arp_insert) cr ." insert" ;
|
||||
: (arp_delete) cr ." delete" ;
|
||||
: (+arp_age) cr ." age" ;
|
||||
|
||||
: arp_table ( u -- )
|
||||
create here over allot swap erase
|
||||
does>
|
||||
swap arp_cache% * +
|
||||
arp_action 0 to arp_action
|
||||
case
|
||||
0 of (arp_lookup) endof
|
||||
1 of (arp_update) endof
|
||||
2 of (arp_insert) endof
|
||||
3 of (arp_delete) endof
|
||||
4 of (+arp_age) endof
|
||||
." unknown cache option"
|
||||
endcase ;
|
||||
|
||||
arp_cache% 8 * arp_table arp_cache
|
||||
|
||||
: eth_rx f008 @ ;
|
||||
: eth_tx f008 ! ;
|
||||
|
||||
: checksum ( address count -- checksum)
|
||||
over + 0 -rot
|
||||
do
|
||||
i @ + i @ over u> if 1+ then
|
||||
-2 +loop
|
||||
dup 10 rshift swap ffff and +
|
||||
dup 10 rshift +
|
||||
ffff xor ;
|
||||
: arp_in ( -- )
|
||||
eth_frame% active_struct +!
|
||||
arp_op @ arp_request_type = if
|
||||
100 arp_hw !
|
||||
eth_ip_type arp_proto !
|
||||
6 arp_hlen c!
|
||||
4 arp_plen c!
|
||||
arp_reply_type arp_op !
|
||||
arp_shw arp_thw 6 cmove
|
||||
hw_addr arp_shw 6 cmove
|
||||
arp_sp arp_tp 4 cmove
|
||||
ip_addr arp_sp 4 cmove
|
||||
arp_thw
|
||||
eth_rx_buf active_struct !
|
||||
eth_dest 6 cmove
|
||||
hw_addr eth_src 6 cmove
|
||||
eth_arp_type eth_type !
|
||||
eth_tx
|
||||
else
|
||||
( arp_update )
|
||||
then ;
|
||||
: icmp_in
|
||||
ip_len @ htons
|
||||
ip_header% active_struct +!
|
||||
icmp_type c@ 8 = if
|
||||
0 icmp_type c!
|
||||
icmp_checksum @ fff7 = if
|
||||
9 icmp_checksum +!
|
||||
else 8 icmp_checksum +! then
|
||||
else
|
||||
cr ." weird icmp packet"
|
||||
then eth_tx ;
|
||||
: udp_in cr ." got udp packet." ;
|
||||
: tcp_in cr ." got tcp packet." ;
|
||||
: ip_in ( -- )
|
||||
eth_frame% active_struct +!
|
||||
ip_vhl @ 45 = if
|
||||
ip_proto c@ case
|
||||
1 of
|
||||
ip_source dup ip_dest 4 cmove
|
||||
ip_addr swap 4 cmove
|
||||
icmp_in
|
||||
endof
|
||||
6 of tcp_in endof
|
||||
17 of udp_in endof
|
||||
cr ." unknown ip protocol:"
|
||||
endcase
|
||||
else
|
||||
cr ." unsupported ip version detected"
|
||||
then ;
|
||||
: process ( -- )
|
||||
eth_type @ case
|
||||
eth_arp_type of arp_in endof
|
||||
eth_ip_type of ip_in endof
|
||||
cr ." unknown ethernet protocol"
|
||||
endcase ;
|
||||
: pcap_poll
|
||||
eth_rx_buf active_struct !
|
||||
active_struct @ 5dc erase
|
||||
eth_rx ;
|
||||
: round
|
||||
pcap_poll 0 <> if
|
||||
process
|
||||
then ;
|
||||
: main
|
||||
begin
|
||||
round
|
||||
again
|
||||
;
|
||||
|
||||
( main )
|
||||
|
||||
forth definitions
|
||||
ipv4.1 definitions
|
946
verilog/j1eforth/j1eforth-plus/j1.4th
Normal file
946
verilog/j1eforth/j1eforth-plus/j1.4th
Normal file
@ -0,0 +1,946 @@
|
||||
(
|
||||
eForth 1.04 for j1 Simulator by Edward A., July 2014
|
||||
Much of the code is derived from the following sources:
|
||||
j1 Cross-compiler by James Bowman August 2010
|
||||
8086 eForth 1.0 by Bill Muench and C. H. Ting, 1990
|
||||
)
|
||||
|
||||
only forth definitions hex
|
||||
|
||||
wordlist constant meta.1
|
||||
wordlist constant target.1
|
||||
wordlist constant assembler.1
|
||||
|
||||
: (order) ( w wid*n n -- wid*n w n )
|
||||
dup if
|
||||
1- swap >r recurse over r@ xor if
|
||||
1+ r> -rot exit then r> drop then ;
|
||||
: -order ( wid -- ) get-order (order) nip set-order ;
|
||||
: +order ( wid -- ) dup >r -order get-order r> swap 1+ set-order ;
|
||||
|
||||
: ]asm ( -- ) assembler.1 +order ; immediate
|
||||
|
||||
get-current meta.1 set-current
|
||||
|
||||
: [a] ( "name" -- )
|
||||
parse-word assembler.1 search-wordlist 0=
|
||||
abort" [a]?" compile, ; immediate
|
||||
: a: ( "name" -- )
|
||||
get-current >r assembler.1 set-current
|
||||
: r> set-current ;
|
||||
|
||||
target.1 +order meta.1 +order
|
||||
|
||||
a: asm[ ( -- ) assembler.1 -order ; immediate
|
||||
|
||||
create tflash 1000 cells here over erase allot
|
||||
|
||||
variable tdp
|
||||
|
||||
: there tdp @ ;
|
||||
: tc! tflash + c! ;
|
||||
: tc@ tflash + c@ ;
|
||||
: t! over ff and over tc! swap 8 rshift swap 1+ tc! ;
|
||||
: t@ dup tc@ swap 1+ tc@ 8 lshift or ;
|
||||
: talign there 1 and tdp +! ;
|
||||
: tc, there tc! 1 tdp +! ;
|
||||
: t, there t! 2 tdp +! ;
|
||||
: $literal [char] " word count dup tc, 0 ?do
|
||||
count tc, loop drop talign ;
|
||||
: tallot tdp +! ;
|
||||
: org tdp ! ;
|
||||
|
||||
a: t 0000 ;
|
||||
a: n 0100 ;
|
||||
a: t+n 0200 ;
|
||||
a: t&n 0300 ;
|
||||
a: t|n 0400 ;
|
||||
a: t^n 0500 ;
|
||||
a: ~t 0600 ;
|
||||
a: n==t 0700 ;
|
||||
a: n<t 0800 ;
|
||||
a: n>>t 0900 ;
|
||||
a: t-1 0a00 ;
|
||||
a: rt 0b00 ;
|
||||
a: [t] 0c00 ;
|
||||
a: n<<t 0d00 ;
|
||||
a: dsp 0e00 ;
|
||||
a: nu<t 0f00 ;
|
||||
|
||||
a: t==0 0010 ;
|
||||
a: t<>0 0110 ;
|
||||
a: n<>t 0210 ;
|
||||
a: t+1 0310 ;
|
||||
a: t<<1 0410 ;
|
||||
a: t>>1 0510 ;
|
||||
a: n>t 0610 ;
|
||||
a: nu>t 0710 ;
|
||||
a: t<0 0810 ;
|
||||
a: t>0 0910 ;
|
||||
a: abst 0a10 ;
|
||||
a: mxnt 0b10 ;
|
||||
a: mnnt 0c10 ;
|
||||
a: negt 0d10 ;
|
||||
a: n-t 0e10 ;
|
||||
a: n>=t 0f10 ;
|
||||
|
||||
a: t->n 0080 or ;
|
||||
a: t->r 0040 or ;
|
||||
a: n->[t] 0020 or ;
|
||||
a: d-1 0003 or ;
|
||||
a: d+1 0001 or ;
|
||||
a: r-1 000c or ;
|
||||
a: r-2 0008 or ;
|
||||
a: r+1 0004 or ;
|
||||
|
||||
a: alu 6000 or t, ;
|
||||
|
||||
a: return [a] t 1000 or [a] r-1 [a] alu ;
|
||||
a: branch 2/ 0000 or t, ;
|
||||
a: ?branch 2/ 2000 or t, ;
|
||||
a: call 2/ 4000 or t, ;
|
||||
|
||||
a: literal
|
||||
dup 8000 and if
|
||||
ffff xor recurse
|
||||
[a] ~t [a] alu
|
||||
else
|
||||
8000 or t,
|
||||
then ;
|
||||
|
||||
variable tlast
|
||||
variable tuser
|
||||
|
||||
0001 constant =ver
|
||||
0002 constant =ext
|
||||
0040 constant =comp
|
||||
0080 constant =imed
|
||||
7f1f constant =mask
|
||||
0002 constant =cell
|
||||
0010 constant =base
|
||||
0008 constant =bksp
|
||||
000a constant =lf
|
||||
000d constant =cr
|
||||
|
||||
4000 constant =em
|
||||
0000 constant =cold
|
||||
|
||||
8 constant =vocs
|
||||
80 constant =us
|
||||
|
||||
=em 100 - constant =tib
|
||||
=tib =us - constant =up
|
||||
=cold =us + constant =pick
|
||||
=pick 100 + constant =code
|
||||
|
||||
: thead
|
||||
talign
|
||||
tlast @ t, there tlast !
|
||||
parse-word dup tc, 0 ?do count tc, loop drop talign ;
|
||||
: twords
|
||||
cr tlast @
|
||||
begin
|
||||
dup tflash + count 1f and type space =cell - t@
|
||||
?dup 0= until ;
|
||||
: [t]
|
||||
parse-word target.1 search-wordlist 0=
|
||||
abort" [t]?" >body @ ; immediate
|
||||
: [last] tlast @ ; immediate
|
||||
: ( [char] ) parse 2drop ; immediate
|
||||
: literal [a] literal ;
|
||||
: lookback there =cell - t@ ;
|
||||
: call? lookback e000 and 4000 = ;
|
||||
: call>goto there =cell - dup t@ 1fff and swap t! ;
|
||||
: safe? lookback e000 and 6000 = lookback 004c and 0= and ;
|
||||
: alu>return there =cell - dup t@ 1000 or [a] r-1 swap t! ;
|
||||
: t:
|
||||
>in @ thead >in !
|
||||
get-current >r target.1 set-current create
|
||||
r> set-current 947947 talign there , does> @ [a] call ;
|
||||
: exit
|
||||
call? if
|
||||
call>goto else safe? if
|
||||
alu>return else
|
||||
[a] return
|
||||
then
|
||||
then ;
|
||||
: t;
|
||||
947947 <> if
|
||||
abort" unstructured" then true if
|
||||
exit else [a] return then ;
|
||||
: u:
|
||||
>in @ thead >in !
|
||||
get-current >r target.1 set-current create
|
||||
r> set-current talign tuser @ dup ,
|
||||
[a] literal exit =cell tuser +! does> @ [a] literal ;
|
||||
: [u]
|
||||
parse-word target.1 search-wordlist 0=
|
||||
abort" [t]?" >body @ =up - =cell + ; immediate
|
||||
: immediate tlast @ tflash + dup c@ =imed or swap c! ;
|
||||
: compile-only tlast @ tflash + dup c@ =comp or swap c! ;
|
||||
|
||||
0 tlast !
|
||||
=up tuser !
|
||||
|
||||
: hex# ( u -- addr len ) 0 <# base @ >r hex =lf hold # # # # r> base ! #> ;
|
||||
: save-hex ( <name> -- )
|
||||
parse-word w/o create-file throw
|
||||
there 0 do i t@ over >r hex# r> write-file throw 2 +loop
|
||||
close-file throw ;
|
||||
: save-target ( <name> -- )
|
||||
parse-word w/o create-file throw >r
|
||||
tflash there r@ write-file throw r> close-file ;
|
||||
|
||||
: begin there ;
|
||||
: until [a] ?branch ;
|
||||
|
||||
: if there 0 [a] ?branch ;
|
||||
: skip there 0 [a] branch ;
|
||||
: then begin 2/ over t@ or swap t! ;
|
||||
: else skip swap then ;
|
||||
: while if swap ;
|
||||
: repeat [a] branch then ;
|
||||
: again [a] branch ;
|
||||
: aft drop skip begin swap ;
|
||||
|
||||
: noop ]asm t alu asm[ ;
|
||||
: + ]asm t+n d-1 alu asm[ ;
|
||||
: xor ]asm t^n d-1 alu asm[ ;
|
||||
: and ]asm t&n d-1 alu asm[ ;
|
||||
: or ]asm t|n d-1 alu asm[ ;
|
||||
: invert ]asm ~t alu asm[ ;
|
||||
: = ]asm n==t d-1 alu asm[ ;
|
||||
: < ]asm n<t d-1 alu asm[ ;
|
||||
: u< ]asm nu<t d-1 alu asm[ ;
|
||||
: swap ]asm n t->n alu asm[ ;
|
||||
: dup ]asm t t->n d+1 alu asm[ ;
|
||||
: drop ]asm n d-1 alu asm[ ;
|
||||
: over ]asm n t->n d+1 alu asm[ ;
|
||||
: nip ]asm t d-1 alu asm[ ;
|
||||
: >r ]asm n t->r r+1 d-1 alu asm[ ;
|
||||
: r> ]asm rt t->n r-1 d+1 alu asm[ ;
|
||||
: r@ ]asm rt t->n d+1 alu asm[ ;
|
||||
: @ ]asm [t] alu asm[ ;
|
||||
: ! ]asm t n->[t] d-1 alu
|
||||
n d-1 alu asm[ ;
|
||||
: dsp ]asm dsp t->n d+1 alu asm[ ;
|
||||
: lshift ]asm n<<t d-1 alu asm[ ;
|
||||
: rshift ]asm n>>t d-1 alu asm[ ;
|
||||
: 1- ]asm t-1 alu asm[ ;
|
||||
: 2r> ]asm rt t->n r-1 d+1 alu
|
||||
rt t->n r-1 d+1 alu
|
||||
n t->n alu asm[ ;
|
||||
: 2>r ]asm n t->n alu
|
||||
n t->r r+1 d-1 alu
|
||||
n t->r r+1 d-1 alu asm[ ;
|
||||
: 2r@ ]asm rt t->n r-1 d+1 alu
|
||||
rt t->n r-1 d+1 alu
|
||||
n t->n d+1 alu
|
||||
n t->n d+1 alu
|
||||
n t->r r+1 d-1 alu
|
||||
n t->r r+1 d-1 alu
|
||||
n t->n alu asm[ ;
|
||||
: unloop
|
||||
]asm t r-1 alu
|
||||
t r-1 alu asm[ ;
|
||||
|
||||
( new J1+ ALU operations )
|
||||
: 0= ]asm t==0 alu asm[ ;
|
||||
: 0<> ]asm t<>0 alu asm[ ;
|
||||
: <> ]asm n<>t d-1 alu asm[ ;
|
||||
: 1+ ]asm t+1 alu asm[ ;
|
||||
: 2* ]asm t<<1 alu asm[ ;
|
||||
( : 2/ ]asm t>>1 alu asm[ ; ) ( uncommenting causes error )
|
||||
: > ]asm n>t d-1 alu asm[ ;
|
||||
: u> ]asm nu>t d-1 alu asm[ ;
|
||||
: 0< ]asm t<0 alu asm[ ;
|
||||
: 0> ]asm t>0 alu asm[ ;
|
||||
: abs ]asm abst alu asm[ ;
|
||||
: max ]asm mxnt d-1 alu asm[ ;
|
||||
: min ]asm mnnt d-1 alu asm[ ;
|
||||
: negate ]asm negt alu asm[ ;
|
||||
( : - ]asm n-t d-1 alu asm[ ; ) ( uncommenting causes error )
|
||||
: >= ]asm n>=t d-1 alu asm[ ;
|
||||
|
||||
: dup@ ]asm [t] t->n d+1 alu asm[ ;
|
||||
: dup>r ]asm t t->r r+1 alu asm[ ;
|
||||
: 2dupxor ]asm t^n t->n d+1 alu asm[ ;
|
||||
: 2dup= ]asm n==t t->n d+1 alu asm[ ;
|
||||
: !nip ]asm t n->[t] d-1 alu asm[ ;
|
||||
: 2dup! ]asm t n->[t] alu asm[ ;
|
||||
|
||||
: up1 ]asm t d+1 alu asm[ ;
|
||||
: down1 ]asm t d-1 alu asm[ ;
|
||||
: copy ]asm n alu asm[ ;
|
||||
|
||||
a: down e for down1 next copy exit ;
|
||||
a: up e for up1 next noop exit ;
|
||||
|
||||
: for >r begin ;
|
||||
: next r@ while r> 1- >r repeat r> drop ;
|
||||
|
||||
=pick org
|
||||
|
||||
]asm down up asm[
|
||||
|
||||
there constant =pickbody
|
||||
|
||||
copy ]asm return asm[
|
||||
9c ]asm call asm[ bc ]asm branch asm[
|
||||
9a ]asm call asm[ ba ]asm branch asm[
|
||||
98 ]asm call asm[ b8 ]asm branch asm[
|
||||
96 ]asm call asm[ b6 ]asm branch asm[
|
||||
94 ]asm call asm[ b4 ]asm branch asm[
|
||||
92 ]asm call asm[ b2 ]asm branch asm[
|
||||
90 ]asm call asm[ b0 ]asm branch asm[
|
||||
8e ]asm call asm[ ae ]asm branch asm[
|
||||
8c ]asm call asm[ ac ]asm branch asm[
|
||||
8a ]asm call asm[ aa ]asm branch asm[
|
||||
88 ]asm call asm[ a8 ]asm branch asm[
|
||||
86 ]asm call asm[ a6 ]asm branch asm[
|
||||
84 ]asm call asm[ a4 ]asm branch asm[
|
||||
82 ]asm call asm[ a2 ]asm branch asm[
|
||||
80 ]asm call asm[ a0 ]asm branch asm[
|
||||
]asm return asm[
|
||||
|
||||
=cold org
|
||||
|
||||
0 t,
|
||||
|
||||
there constant =uzero
|
||||
=base t, ( base )
|
||||
0 t, ( temp )
|
||||
0 t, ( >in )
|
||||
0 t, ( #tib )
|
||||
=tib t, ( tib )
|
||||
0 t, ( 'eval )
|
||||
0 t, ( 'abort )
|
||||
0 t, ( hld )
|
||||
|
||||
( context )
|
||||
|
||||
0 t, 0 t, 0 t, 0 t, 0 t, 0 t, 0 t, 0 t, 0 t,
|
||||
|
||||
( forth-wordlist )
|
||||
|
||||
0 t, ( na, of last definition, linked )
|
||||
0 t, ( wid|0, next or last wordlist in chain )
|
||||
0 t, ( na, wordlist name pointer )
|
||||
|
||||
( current )
|
||||
|
||||
0 t, ( wid, new definitions )
|
||||
0 t, ( wid, head of chain )
|
||||
|
||||
0 t, ( dp )
|
||||
0 t, ( last )
|
||||
0 t, ( '?key )
|
||||
0 t, ( 'emit )
|
||||
0 t, ( 'boot )
|
||||
0 t, ( '\ )
|
||||
0 t, ( '?name )
|
||||
0 t, ( '$,n )
|
||||
0 t, ( 'overt )
|
||||
0 t, ( '; )
|
||||
0 t, ( 'create )
|
||||
there constant =ulast
|
||||
=ulast =uzero - constant =udiff
|
||||
|
||||
=code org
|
||||
|
||||
t: noop noop t;
|
||||
t: + + t;
|
||||
t: xor xor t;
|
||||
t: and and t;
|
||||
t: or or t;
|
||||
t: invert invert t;
|
||||
t: = = t;
|
||||
t: < < t;
|
||||
t: u< u< t;
|
||||
t: swap swap t;
|
||||
t: u> u> t;
|
||||
t: dup dup t;
|
||||
t: drop drop t;
|
||||
t: over over t;
|
||||
t: nip nip t;
|
||||
t: lshift lshift t;
|
||||
t: rshift rshift t;
|
||||
t: 1- 1- t;
|
||||
t: >r r> swap >r >r t; compile-only
|
||||
t: r> r> r> swap >r t; compile-only
|
||||
t: r@ r> r> dup >r swap >r t; compile-only
|
||||
t: @ ( a -- w ) @ t;
|
||||
t: ! ( w a -- ) ! t;
|
||||
|
||||
t: <> <> t;
|
||||
t: 0< 0< t;
|
||||
t: 0= 0= t;
|
||||
t: 0<> 0<> t;
|
||||
t: > > t;
|
||||
t: 0> 0> t;
|
||||
t: >= >= t;
|
||||
t: tuck swap over t;
|
||||
t: -rot swap >r swap r> t;
|
||||
t: 2/ 1 literal rshift t;
|
||||
t: 2* 2* t;
|
||||
t: 1+ 1+ t;
|
||||
t: sp@ dsp ff literal and t;
|
||||
t: execute ( ca -- ) >r t;
|
||||
t: bye ( -- ) f002 literal ! t;
|
||||
t: c@ ( b -- c )
|
||||
dup @ swap 1 literal and if
|
||||
8 literal rshift else ff literal and then exit t;
|
||||
t: c! ( c b -- )
|
||||
swap ff literal and dup 8 literal lshift or swap
|
||||
tuck dup @ swap 1 literal and 0 literal = ff literal xor
|
||||
>r over xor r> and xor swap ! t;
|
||||
t: um+ ( w w -- w cy )
|
||||
over over + >r
|
||||
r@ 0 literal >= >r
|
||||
over over and
|
||||
0< r> or >r
|
||||
or 0< r> and invert 1+
|
||||
r> swap t;
|
||||
t: dovar ( -- a ) r> t; compile-only
|
||||
t: up dovar =up t, t;
|
||||
t: douser ( -- a ) up @ r> @ + t; compile-only
|
||||
|
||||
u: base
|
||||
u: temp
|
||||
u: >in
|
||||
u: #tib
|
||||
u: tib
|
||||
u: 'eval
|
||||
u: 'abort
|
||||
u: hld
|
||||
u: context
|
||||
=vocs =cell * tuser +!
|
||||
u: forth-wordlist
|
||||
=cell tuser +!
|
||||
=cell tuser +!
|
||||
u: current
|
||||
=cell tuser +!
|
||||
u: dp
|
||||
u: last
|
||||
u: '?key
|
||||
u: 'emit
|
||||
u: 'boot
|
||||
u: '\
|
||||
u: 'name?
|
||||
u: '$,n
|
||||
u: 'overt
|
||||
u: ';
|
||||
u: 'create
|
||||
|
||||
t: ?dup ( w -- w w | 0 ) dup if dup then exit t;
|
||||
t: rot ( w1 w2 w3 -- w2 w3 w1 ) >r swap r> swap t;
|
||||
t: 2drop ( w w -- ) drop drop t;
|
||||
t: 2dup ( w1 w2 -- w1 w2 w1 w2 ) over over t;
|
||||
t: negate ( n -- -n ) negate t;
|
||||
t: dnegate ( d -- -d )
|
||||
invert >r invert 1 literal um+ r> + t;
|
||||
t: - ( n1 n2 -- n1-n2 ) negate + t;
|
||||
t: abs ( n -- n ) abs t;
|
||||
t: max ( n n -- n ) max t;
|
||||
t: min ( n n -- n ) min t;
|
||||
t: within ( u ul uh -- t ) over - >r - r> u< t;
|
||||
t: um/mod ( udl udh u -- ur uq )
|
||||
2dup u< if
|
||||
negate f literal
|
||||
for >r dup um+ >r >r dup um+ r> + dup
|
||||
r> r@ swap >r um+ r> or if
|
||||
>r drop 1+ r>
|
||||
else
|
||||
drop
|
||||
then r>
|
||||
next drop swap exit
|
||||
then drop 2drop -1 literal dup t;
|
||||
t: m/mod ( d n -- r q )
|
||||
dup 0< dup >r if
|
||||
negate >r dnegate r>
|
||||
then >r dup 0< if
|
||||
r@ +
|
||||
then r> um/mod r> if
|
||||
swap negate swap then exit t;
|
||||
t: /mod ( n n -- r q ) over 0< swap m/mod t;
|
||||
t: mod ( n n -- r ) /mod drop t;
|
||||
t: / ( n n -- q ) /mod nip t;
|
||||
t: um* ( u u -- ud )
|
||||
0 literal swap f literal
|
||||
for dup um+ >r >r dup um+ r> + r> if
|
||||
>r over um+ r> + then
|
||||
next rot drop t;
|
||||
t: * ( n n -- n ) um* drop t;
|
||||
t: m* ( n n -- d )
|
||||
2dup xor 0< >r abs swap abs um* r> if
|
||||
dnegate then exit t;
|
||||
t: */mod ( n1 n2 n3 -- r q ) >r m* r> m/mod t;
|
||||
t: */ ( n1 n2 n3 -- q ) */mod nip t;
|
||||
t: cell+ ( a -- a ) =cell literal + t;
|
||||
t: cell- ( a -- a ) =cell literal - t;
|
||||
t: cells ( n -- n ) 1 literal lshift t;
|
||||
t: bl ( -- 32 ) 20 literal t;
|
||||
t: >char ( c -- c )
|
||||
7f literal and dup 7f literal bl within if
|
||||
drop 5f literal then exit t;
|
||||
t: +! ( n a -- ) tuck @ + swap ! t;
|
||||
t: 2! ( d a -- ) swap over ! cell+ ! t;
|
||||
t: 2@ ( a -- d ) dup cell+ @ swap @ t;
|
||||
t: count ( b -- b +n ) dup 1+ swap c@ t;
|
||||
t: here ( -- a ) dp @ t;
|
||||
t: aligned ( b -- a )
|
||||
dup 0 literal =cell literal um/mod drop dup if
|
||||
=cell literal swap - then + t;
|
||||
t: align ( -- ) here aligned dp ! t;
|
||||
t: pad ( -- a ) here 50 literal + aligned t;
|
||||
t: @execute ( a -- ) @ ?dup if execute then exit t;
|
||||
t: fill ( b u c -- )
|
||||
swap for swap aft 2dup c! 1+ then next 2drop t;
|
||||
t: erase 0 literal fill t;
|
||||
t: digit ( u -- c ) 9 literal over < 7 literal and + 30 literal + t;
|
||||
t: extract ( n base -- n c ) 0 literal swap um/mod swap digit t;
|
||||
t: <# ( -- ) pad hld ! t;
|
||||
t: hold ( c -- ) hld @ 1- dup hld ! c! t;
|
||||
t: # ( u -- u ) base @ extract hold t;
|
||||
t: #s ( u -- 0 ) begin # dup while repeat t;
|
||||
t: sign ( n -- ) 0< if 2d literal hold then exit t;
|
||||
t: #> ( w -- b u ) drop hld @ pad over - t;
|
||||
t: str ( n -- b u ) dup >r abs <# #s r> sign #> t;
|
||||
t: hex ( -- ) 10 literal base ! t;
|
||||
t: decimal ( -- ) a literal base ! t;
|
||||
t: digit? ( c base -- u t )
|
||||
>r 30 literal - 9 literal over < if
|
||||
dup 20 literal > if
|
||||
20 literal -
|
||||
then
|
||||
7 literal - dup a literal < or
|
||||
then dup r> u< t;
|
||||
t: number? ( a -- n t | a f )
|
||||
base @ >r 0 literal over count
|
||||
over c@ 24 literal = if
|
||||
hex swap 1+ swap 1- then
|
||||
over c@ 2d literal = >r
|
||||
swap r@ - swap r@ + ?dup if
|
||||
1-
|
||||
for dup >r c@ base @ digit?
|
||||
while swap base @ * + r> 1+
|
||||
next r@ nip if
|
||||
negate then swap
|
||||
else r> r> 2drop 2drop 0 literal
|
||||
then dup
|
||||
then r> 2drop r> base ! t;
|
||||
t: ?rx ( -- c t | f ) f001 literal @ 1 literal and 0<> t;
|
||||
t: tx! ( c -- )
|
||||
begin
|
||||
f001 literal @ 2 literal and 0=
|
||||
until f000 literal ! t;
|
||||
t: ?key ( -- c ) '?key @execute t;
|
||||
t: emit ( c -- ) 'emit @execute t;
|
||||
t: key ( -- c )
|
||||
begin
|
||||
?key
|
||||
until f000 literal @ t;
|
||||
t: nuf? ( -- t ) ?key dup if drop key =cr literal = then exit t;
|
||||
t: space ( -- ) bl emit t;
|
||||
t: spaces ( +n -- ) 0 literal max for aft space then next t;
|
||||
t: type ( b u -- ) for aft count emit then next drop t;
|
||||
t: cr ( -- ) =cr literal emit =lf literal emit t;
|
||||
t: do$ ( -- a ) r> r@ r> count + aligned >r swap >r t; compile-only
|
||||
t: $"| ( -- a ) do$ noop t; compile-only
|
||||
t: .$ ( a -- ) count type t;
|
||||
t: ."| ( -- ) do$ .$ t; compile-only
|
||||
t: .r ( n +n -- ) >r str r> over - spaces type t;
|
||||
t: u.r ( u +n -- ) >r <# #s #> r> over - spaces type t;
|
||||
t: u. ( u -- ) <# #s #> space type t;
|
||||
t: . ( w -- ) base @ a literal xor if u. exit then str space type t;
|
||||
t: cmove ( b1 b2 u -- ) for aft >r dup c@ r@ c! 1+ r> 1+ then next 2drop t;
|
||||
t: pack$ ( b u a -- a ) dup >r 2dup ! 1+ swap cmove r> t;
|
||||
t: ? ( a -- ) @ . t;
|
||||
t: (parse) ( b u c -- b u delta ; <string> )
|
||||
temp ! over >r dup if
|
||||
1- temp @ bl = if
|
||||
for
|
||||
count temp @ swap - 0< invert r@ 0> and
|
||||
while next r> drop 0 literal dup exit
|
||||
then 1- r>
|
||||
then over swap
|
||||
for
|
||||
count temp @ swap - temp @ bl = if
|
||||
0< then
|
||||
while next dup >r else r> drop dup >r 1-
|
||||
then over - r> r> - exit
|
||||
then over r> - t;
|
||||
t: parse ( c -- b u ; <string> )
|
||||
>r
|
||||
tib @ >in @ +
|
||||
#tib @ >in @ - r>
|
||||
(parse)
|
||||
>in +! t;
|
||||
t: .( ( -- ) 29 literal parse type t; immediate
|
||||
t: ( ( -- ) 29 literal parse 2drop t; immediate
|
||||
t: <\> ( -- ) #tib @ >in ! t; immediate
|
||||
t: \ ( -- ) '\ @execute t; immediate
|
||||
t: word ( c -- a ; <string> ) parse here cell+ pack$ t;
|
||||
t: token ( -- a ; <string> ) bl word t;
|
||||
t: name> ( na -- ca ) count 1f literal and + aligned t;
|
||||
t: same? ( a a u -- a a f \ -0+ )
|
||||
1-
|
||||
for aft over r@ + c@
|
||||
over r@ + c@ - ?dup
|
||||
if r> drop exit then then
|
||||
next 0 literal t;
|
||||
t: find ( a va -- ca na | a f )
|
||||
swap
|
||||
dup c@ temp !
|
||||
dup @ >r
|
||||
cell+ swap
|
||||
begin @ dup
|
||||
if dup @ =mask literal and r@ xor
|
||||
if cell+ -1 literal else cell+ temp @ same? then
|
||||
else r> drop swap cell- swap exit
|
||||
then
|
||||
while 2 literal cells -
|
||||
repeat r> drop nip cell- dup name> swap t;
|
||||
t: <name?> ( a -- ca na | a f )
|
||||
context dup 2@ xor if cell- then >r
|
||||
begin
|
||||
r> cell+ dup >r @ ?dup
|
||||
while
|
||||
find ?dup
|
||||
until r> drop exit then r> drop 0 literal t;
|
||||
t: name? ( a -- ca na | a f ) 'name? @execute t;
|
||||
t: ^h ( bot eot cur -- bot eot cur )
|
||||
>r over r@ < dup if
|
||||
=bksp literal dup emit space
|
||||
emit then r> + t;
|
||||
t: tap ( bot eot cur c -- bot eot cur )
|
||||
dup emit over c! 1+ t;
|
||||
t: ktap ( bot eot cur c -- bot eot cur )
|
||||
dup =cr literal xor if
|
||||
=bksp literal xor if
|
||||
bl tap exit
|
||||
then ^h exit
|
||||
then drop nip dup t;
|
||||
t: accept ( b u -- b u )
|
||||
over + over
|
||||
begin
|
||||
2dup xor
|
||||
while
|
||||
key dup bl - 7f literal u< if tap else ktap then
|
||||
repeat drop over - t;
|
||||
t: query ( -- ) tib @ 50 literal accept #tib ! drop 0 literal >in ! t;
|
||||
t: abort2 do$ drop t;
|
||||
t: abort1 space .$ 3f literal emit cr 'abort @execute abort2 t;
|
||||
t: <?abort"> if do$ abort1 exit then abort2 t; compile-only
|
||||
t: forget ( -- )
|
||||
token name? ?dup if
|
||||
cell- dup dp !
|
||||
@ dup context ! last !
|
||||
drop exit
|
||||
then abort1 t;
|
||||
t: $interpret ( a -- )
|
||||
name? ?dup if
|
||||
@ =comp literal and
|
||||
<?abort"> $literal compile-only" execute exit
|
||||
else number? if
|
||||
exit then abort1 then t;
|
||||
t: [ ( -- ) [t] $interpret literal 'eval ! t; immediate
|
||||
t: .ok ( -- )
|
||||
[t] $interpret literal 'eval @ = if
|
||||
."| $literal ok"
|
||||
then cr t;
|
||||
t: eval ( -- )
|
||||
begin
|
||||
token dup c@
|
||||
while
|
||||
'eval @execute
|
||||
repeat drop .ok t;
|
||||
t: $eval ( a u -- )
|
||||
>in @ >r #tib @ >r tib @ >r
|
||||
[t] >in literal 0 literal swap !
|
||||
#tib ! tib ! eval r> tib ! r> #tib ! r> >in ! t; compile-only
|
||||
t: preset ( -- ) =tib literal #tib cell+ ! t;
|
||||
t: quit ( -- )
|
||||
[ begin
|
||||
query eval
|
||||
again t;
|
||||
t: abort drop preset .ok quit t;
|
||||
t: ' ( -- ca ) token name? if exit then abort1 t;
|
||||
t: allot ( n -- ) aligned dp +! t;
|
||||
t: , ( w -- ) here dup cell+ dp ! ! t;
|
||||
t: call, ( ca -- ) 1 literal rshift 4000 literal or , t; compile-only
|
||||
t: ?branch ( ca -- ) 1 literal rshift 2000 literal or , t; compile-only
|
||||
t: branch ( ca -- ) 1 literal rshift 0000 literal or , t; compile-only
|
||||
t: [compile] ( -- ; <string> ) ' call, t; immediate
|
||||
t: compile ( -- ) r> dup @ , cell+ >r t; compile-only
|
||||
t: recurse last @ name> call, t; immediate
|
||||
t: pick dup 2* 2* =pickbody literal + >r t;
|
||||
t: literal ( w -- )
|
||||
dup 8000 literal and if
|
||||
ffff literal xor [t] literal ]asm call asm[ compile invert
|
||||
else
|
||||
8000 literal or ,
|
||||
then exit t; immediate
|
||||
t: ['] ' [t] literal ]asm call asm[ t; immediate
|
||||
t: $," ( -- ) 22 literal parse here pack$ count + aligned dp ! t;
|
||||
t: for ( -- a ) compile [t] >r ]asm call asm[ here t; compile-only immediate
|
||||
t: begin ( -- a ) here t; compile-only immediate
|
||||
t: (next) ( n -- ) r> r> ?dup if 1- >r @ >r exit then cell+ >r t; compile-only
|
||||
t: next ( -- ) compile (next) , t; compile-only immediate
|
||||
t: (do) ( limit index -- index ) r> dup >r swap rot >r >r cell+ >r t; compile-only
|
||||
t: do ( limit index -- ) compile (do) 0 literal , here t; compile-only immediate
|
||||
t: (leave) r> drop r> drop r> drop t; compile-only
|
||||
t: leave compile (leave) noop t; compile-only immediate
|
||||
t: (loop)
|
||||
r> r> 1+ r> 2dup <> if
|
||||
>r >r @ >r exit
|
||||
then >r 1- >r cell+ >r t; compile-only
|
||||
t: (unloop) r> r> drop r> drop r> drop >r t; compile-only
|
||||
t: unloop compile (unloop) noop t; compile-only immediate
|
||||
t: (?do)
|
||||
2dup <> if
|
||||
r> dup >r swap rot >r >r cell+ >r exit
|
||||
then 2drop exit t; compile-only
|
||||
t: ?do ( limit index -- ) compile (?do) 0 literal , here t; compile-only immediate
|
||||
t: loop ( -- ) compile (loop) dup , compile (unloop) cell- here 1 literal rshift swap ! t; compile-only immediate
|
||||
t: (+loop)
|
||||
r> swap r> r> 2dup - >r
|
||||
2 literal pick r@ + r@ xor 0< 0=
|
||||
3 literal pick r> xor 0< 0= or if
|
||||
>r + >r @ >r exit
|
||||
then >r >r drop cell+ >r t; compile-only
|
||||
t: +loop ( n -- ) compile (+loop) dup , compile (unloop) cell- here 1 literal rshift swap ! t; compile-only immediate
|
||||
t: (i) ( -- index ) r> r> tuck >r >r t; compile-only
|
||||
t: i ( -- index ) compile (i) noop t; compile-only immediate
|
||||
t: until ( a -- ) ?branch t; compile-only immediate
|
||||
t: again ( a -- ) branch t; compile-only immediate
|
||||
t: if ( -- a ) here 0 literal ?branch t; compile-only immediate
|
||||
t: then ( a -- ) here 1 literal rshift over @ or swap ! t; compile-only immediate
|
||||
t: repeat ( a a -- ) branch [t] then ]asm call asm[ t; compile-only immediate
|
||||
t: skip here 0 literal branch t; compile-only immediate
|
||||
t: aft ( a -- a a ) drop [t] skip ]asm call asm[ [t] begin ]asm call asm[ swap t; compile-only immediate
|
||||
t: else ( a -- a ) [t] skip ]asm call asm[ swap [t] then ]asm call asm[ t; compile-only immediate
|
||||
t: while ( a -- a a ) [t] if ]asm call asm[ swap t; compile-only immediate
|
||||
t: (case) r> swap >r >r t; compile-only
|
||||
t: case compile (case) 30 literal t; compile-only immediate
|
||||
t: (of) r> r@ swap >r = t; compile-only
|
||||
t: of compile (of) [t] if ]asm call asm[ t; compile-only immediate
|
||||
t: endof [t] else ]asm call asm[ 31 literal t; compile-only immediate
|
||||
t: (endcase) r> r> drop >r t;
|
||||
t: endcase
|
||||
begin
|
||||
dup 31 literal =
|
||||
while
|
||||
drop
|
||||
[t] then ]asm call asm[
|
||||
repeat
|
||||
30 literal <> <?abort"> $literal bad case construct."
|
||||
compile (endcase) noop t; compile-only immediate
|
||||
t: $" ( -- ; <string> ) compile $"| $," t; compile-only immediate
|
||||
t: ." ( -- ; <string> ) compile ."| $," t; compile-only immediate
|
||||
t: >body ( ca -- pa ) cell+ t;
|
||||
t: (to) ( n -- ) r> dup cell+ >r @ ! t; compile-only
|
||||
t: to ( n -- ) compile (to) ' >body , t; compile-only immediate
|
||||
t: (+to) ( n -- ) r> dup cell+ >r @ +! t; compile-only
|
||||
t: +to ( n -- ) compile (+to) ' >body , t; compile-only immediate
|
||||
t: get-current ( -- wid ) current @ t;
|
||||
t: set-current ( wid -- ) current ! t;
|
||||
t: definitions ( -- ) context @ set-current t;
|
||||
t: ?unique ( a -- a )
|
||||
dup get-current find if ."| $literal redef " over .$ then drop t;
|
||||
t: <$,n> ( na -- )
|
||||
dup c@ if
|
||||
?unique
|
||||
dup count + aligned
|
||||
dp !
|
||||
dup last !
|
||||
cell-
|
||||
get-current @
|
||||
swap ! exit
|
||||
then drop $"| $literal name" abort1 t;
|
||||
t: $,n ( na -- ) '$,n @execute t;
|
||||
t: $compile ( a -- )
|
||||
name? ?dup if
|
||||
@ =imed literal and if
|
||||
execute exit
|
||||
else call, exit
|
||||
then
|
||||
then
|
||||
number? if
|
||||
[t] literal ]asm call asm[ exit then abort1 t;
|
||||
t: abort" compile <?abort"> $," t; immediate
|
||||
t: <overt> ( -- ) last @ get-current ! t;
|
||||
t: overt ( -- ) 'overt @execute t;
|
||||
t: exit r> drop t;
|
||||
t: <;> ( -- )
|
||||
compile [t] exit ]asm call asm[
|
||||
[ overt 0 literal here ! t; compile-only immediate
|
||||
t: ; ( -- ) '; @execute t; compile-only immediate
|
||||
t: ] ( -- ) [t] $compile literal 'eval ! t;
|
||||
t: : ( -- ; <string> ) token $,n ] t;
|
||||
t: immediate ( -- ) =imed literal last @ @ or last @ ! t;
|
||||
t: user ( u -- ; <string> ) token $,n overt compile douser , t;
|
||||
t: <create> ( -- ; <string> ) token $,n overt [t] dovar ]asm literal asm[ call, t;
|
||||
t: create ( -- ; <string> ) 'create @execute t;
|
||||
t: variable ( -- ; <string> ) create 0 literal , t;
|
||||
t: (does>) ( -- )
|
||||
r> 1 literal rshift here 1 literal rshift
|
||||
last @ name> dup cell+ ]asm 8000 literal asm[ or , ! , t; compile-only
|
||||
t: compile-only ( -- ) =comp literal last @ @ or last @ ! t;
|
||||
t: does> ( -- ) compile (does>) noop t; immediate
|
||||
t: char ( <char> -- char ) ( -- c ) bl word 1+ c@ t;
|
||||
t: [char] char [t] literal ]asm call asm[ t; immediate
|
||||
t: constant create , (does>) @ t;
|
||||
t: defer create 0 literal ,
|
||||
(does>)
|
||||
@ ?dup 0 literal =
|
||||
<?abort"> $literal uninitialized" execute t;
|
||||
t: is ' >body ! t; immediate
|
||||
t: .id ( na -- )
|
||||
?dup if
|
||||
count 1f literal and type exit then
|
||||
cr ."| $literal {noname}" t;
|
||||
t: wordlist ( -- wid ) align here 0 literal , dup current cell+ dup @ , ! 0 literal , t;
|
||||
t: order@ ( a -- u*wid u ) dup @ dup if >r cell+ order@ r> swap 1+ exit then nip t;
|
||||
t: get-order ( -- u*wid u ) context order@ t;
|
||||
t: >wid ( wid -- ) cell+ t;
|
||||
t: .wid ( wid -- )
|
||||
space dup >wid cell+ @ ?dup if .id drop exit then 0 literal u.r t;
|
||||
t: !wid ( wid -- ) >wid cell+ last @ swap ! t;
|
||||
t: vocs ( -- ) ( list all wordlists )
|
||||
cr ."| $literal vocs:" current cell+
|
||||
begin
|
||||
@ ?dup
|
||||
while
|
||||
dup .wid >wid
|
||||
repeat t;
|
||||
t: order ( -- ) ( list search order )
|
||||
cr ."| $literal search:" get-order
|
||||
begin
|
||||
?dup
|
||||
while
|
||||
swap .wid 1-
|
||||
repeat
|
||||
cr ."| $literal define:" get-current .wid t;
|
||||
t: set-order ( u*wid n -- ) ( 16.6.1.2197 )
|
||||
dup -1 literal = if
|
||||
drop forth-wordlist 1 literal then
|
||||
=vocs literal over u< <?abort"> $literal over size of #vocs"
|
||||
context swap
|
||||
begin
|
||||
dup
|
||||
while
|
||||
>r swap over ! cell+ r>
|
||||
1-
|
||||
repeat swap ! t;
|
||||
t: only ( -- ) -1 literal set-order t;
|
||||
t: also ( -- ) get-order over swap 1+ set-order t;
|
||||
t: previous ( -- ) get-order swap drop 1- set-order t;
|
||||
t: >voc ( wid 'name' -- )
|
||||
create dup , !wid
|
||||
(does>)
|
||||
@ >r get-order swap drop r> swap set-order t;
|
||||
t: widof ( "vocabulary" -- wid ) ' >body @ t;
|
||||
t: vocabulary ( 'name' -- ) wordlist >voc t;
|
||||
t: _type ( b u -- ) for aft count >char emit then next drop t;
|
||||
t: dm+ ( a u -- a )
|
||||
over 4 literal u.r space
|
||||
for aft count 3 literal u.r then next t;
|
||||
t: dump ( a u -- )
|
||||
base @ >r hex 10 literal /
|
||||
for cr 10 literal 2dup dm+ -rot
|
||||
2 literal spaces _type
|
||||
next drop r> base ! t;
|
||||
t: .s ( ... -- ... ) cr sp@ 1- f literal and for r@ pick . next ."| $literal <tos" t;
|
||||
t: (>name) ( ca va -- na | f )
|
||||
begin
|
||||
@ ?dup
|
||||
while
|
||||
2dup name> xor
|
||||
while cell-
|
||||
repeat nip exit
|
||||
then drop 0 literal t;
|
||||
t: >name ( ca -- na | f )
|
||||
>r get-order
|
||||
begin
|
||||
?dup
|
||||
while
|
||||
swap
|
||||
r@ swap
|
||||
(>name)
|
||||
?dup if
|
||||
>r
|
||||
1- for aft drop then next
|
||||
r> r> drop
|
||||
exit
|
||||
then
|
||||
1-
|
||||
repeat
|
||||
r> drop 0 literal t;
|
||||
t: see ( -- ; <string> )
|
||||
' cr
|
||||
begin
|
||||
dup @ ?dup 700c literal xor
|
||||
while
|
||||
3fff literal and 1 literal lshift
|
||||
>name ?dup if
|
||||
space .id
|
||||
else
|
||||
dup @ 7fff literal and u.
|
||||
then
|
||||
cell+
|
||||
repeat 2drop t;
|
||||
t: (words) ( -- )
|
||||
cr
|
||||
begin
|
||||
@ ?dup
|
||||
while
|
||||
dup .id space cell-
|
||||
repeat t;
|
||||
t: words
|
||||
get-order
|
||||
begin
|
||||
?dup
|
||||
while
|
||||
swap
|
||||
cr cr ."| $literal :" dup .wid cr
|
||||
(words)
|
||||
1-
|
||||
repeat t;
|
||||
t: ver ( -- n ) =ver literal 100 literal * =ext literal + t;
|
||||
t: hi ( -- )
|
||||
cr ."| $literal eforth j1+ v"
|
||||
base @ hex
|
||||
ver <# # # 2e literal hold # #>
|
||||
type base ! cr t;
|
||||
t: cold ( -- )
|
||||
=uzero literal =up literal =udiff literal cmove
|
||||
preset forth-wordlist dup context ! dup current 2! overt
|
||||
4000 literal cell+ dup cell- @ $eval
|
||||
'boot @execute
|
||||
quit
|
||||
cold t;
|
||||
|
||||
target.1 -order set-current
|
||||
|
||||
there [u] dp t!
|
||||
[last] [u] last t!
|
||||
[t] ?rx [u] '?key t!
|
||||
[t] tx! [u] 'emit t!
|
||||
[t] <\> [u] '\ t!
|
||||
[t] $interpret [u] 'eval t!
|
||||
[t] abort [u] 'abort t!
|
||||
[t] hi [u] 'boot t!
|
||||
[t] <name?> [u] 'name? t!
|
||||
[t] <overt> [u] 'overt t!
|
||||
[t] <$,n> [u] '$,n t!
|
||||
[t] <;> [u] '; t!
|
||||
[t] <create> [u] 'create t!
|
||||
[t] cold 2/ =cold t!
|
||||
|
||||
save-target j1.bin
|
||||
save-hex j1.hex
|
||||
|
||||
meta.1 -order
|
||||
|
||||
bye
|
186
verilog/j1eforth/j1eforth-plus/j1.c
Normal file
186
verilog/j1eforth/j1eforth-plus/j1.c
Normal file
@ -0,0 +1,186 @@
|
||||
#include <pcap.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#if defined(unix) || defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
int getch(void) { /* reads from keypress, doesn't echo */
|
||||
struct termios oldattr, newattr;
|
||||
int ch;
|
||||
tcgetattr( STDIN_FILENO, &oldattr );
|
||||
newattr = oldattr;
|
||||
newattr.c_iflag &= ~( ICRNL );
|
||||
newattr.c_lflag &= ~( ICANON | ECHO );
|
||||
tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
|
||||
ch = getchar();
|
||||
tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
|
||||
// printf("%d\n", ch);
|
||||
if(ch==0x1b) exit(0);
|
||||
return ch==127 ? 8 : ch;
|
||||
}
|
||||
int putch(int c) { /* output character to sstdout & flush */
|
||||
int res=putchar(c);
|
||||
fflush(stdout);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
int len = 0;
|
||||
static pcap_t* handle = NULL;
|
||||
static void pcapdev_init(void) {
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
pcap_if_t* devices;
|
||||
if (pcap_findalldevs(&devices, errbuf) == -1) {
|
||||
fprintf(stderr, "error pcap_findalldevs: %s\n", errbuf);
|
||||
return;
|
||||
}
|
||||
pcap_if_t* device;
|
||||
for(device = devices; device; device = device->next) {
|
||||
if (device->description) {
|
||||
printf(" (%s)\n", device->description);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "no device\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
device = devices->next->next;
|
||||
if (NULL == (handle= pcap_open_live(device->name
|
||||
, 65536, 1, 10 , errbuf))) {
|
||||
fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n");
|
||||
pcap_freealldevs(devices);
|
||||
return;
|
||||
}
|
||||
pcap_freealldevs(devices);
|
||||
}
|
||||
static unsigned short t;
|
||||
static unsigned short s;
|
||||
static unsigned short d[0x20]; /* data stack */
|
||||
static unsigned short r[0x20]; /* return stack */
|
||||
static unsigned short pc; /* program counter, counts cells */
|
||||
static unsigned char dsp, rsp; /* point to top entry */
|
||||
static unsigned short* memory; /* ram */
|
||||
static int sx[4] = { 0, 1, -2, -1 }; /* 2-bit sign extension */
|
||||
|
||||
static void push(int v) // push v on the data stack
|
||||
{
|
||||
dsp = 0x1f & (dsp + 1);
|
||||
d[dsp] = t;
|
||||
t = v;
|
||||
}
|
||||
|
||||
static int pop(void) // pop value from the data stack and return it
|
||||
{
|
||||
int v = t;
|
||||
t = d[dsp];
|
||||
dsp = 0x1f & (dsp - 1);
|
||||
return v;
|
||||
}
|
||||
char eth_poll() {
|
||||
const u_char* packet;
|
||||
struct pcap_pkthdr* header;
|
||||
int res = 0;
|
||||
while (res == 0)
|
||||
{
|
||||
res = pcap_next_ex(handle, &header, &packet);
|
||||
}
|
||||
len = (int)header->len;
|
||||
memcpy(&memory[0x2000], packet, len);
|
||||
return len;
|
||||
}
|
||||
void eth_transmit(void) {
|
||||
if ((pcap_sendpacket(handle, (char *)(&memory[0x2000]), len) == -1))
|
||||
{
|
||||
printf("sorry send error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void execute(int entrypoint)
|
||||
{
|
||||
int _pc, _t;
|
||||
int insn = 0x4000 | entrypoint; // first insn: "call entrypoint"
|
||||
pcapdev_init();
|
||||
do {
|
||||
_pc = pc + 1;
|
||||
if (insn & 0x8000) { // literal
|
||||
push(insn & 0x7fff);
|
||||
} else {
|
||||
int target = insn & 0x1fff;
|
||||
switch (insn >> 13) {
|
||||
case 0: // jump
|
||||
_pc = target;
|
||||
break;
|
||||
case 1: // conditional jump
|
||||
if (pop() == 0)
|
||||
_pc = target;
|
||||
break;
|
||||
case 2: // call
|
||||
rsp = 31 & (rsp + 1);
|
||||
r[rsp] = _pc << 1;
|
||||
_pc = target;
|
||||
break;
|
||||
case 3: // alu
|
||||
if (insn & 0x1000) {/* r->pc */
|
||||
_pc = r[rsp] >> 1;
|
||||
}
|
||||
s = d[dsp];
|
||||
switch ((insn >> 8) & 0xf) {
|
||||
case 0: _t = t; break; /* noop */
|
||||
case 1: _t = s; break; /* copy */
|
||||
case 2: _t = t+s; break; /* + */
|
||||
case 3: _t = t&s; break; /* and */
|
||||
case 4: _t = t|s; break; /* or */
|
||||
case 5: _t = t^s; break; /* xor */
|
||||
case 6: _t = ~t; break; /* invert */
|
||||
case 7: _t = -(t==s); break; /* = */
|
||||
case 8: _t = -((signed short)s < (signed short)t); break; /* < */
|
||||
case 9: _t = s>>t; break; /* rshift */
|
||||
case 0xa: _t = t-1; break; /* 1- */
|
||||
case 0xb: _t = r[rsp]; break; /* r@ */
|
||||
case 0xc: _t = (t==0xf008)?eth_poll():(t==0xf001)?1:(t==0xf000)?getch():memory[t>>1]; break; /* @ */
|
||||
case 0xd: _t = s<<t; break; /* lshift */
|
||||
case 0xe: _t = (rsp<<8) + dsp; break; /* dsp */
|
||||
case 0xf: _t = -(s<t); break; /* u< */
|
||||
}
|
||||
dsp = 31 & (dsp + sx[insn & 3]); /* dstack+- */
|
||||
rsp = 31 & (rsp + sx[(insn >> 2) & 3]); /* rstack+- */
|
||||
if (insn & 0x80) /* t->s */
|
||||
d[dsp] = t;
|
||||
if (insn & 0x40) /* t->r */
|
||||
r[rsp] = t;
|
||||
if (insn & 0x20) /* s->[t] */
|
||||
(t==0xf008)?eth_transmit(): (t==0xf002)?(rsp=0):(t==0xf000)?putch(s):(memory[t>>1]=s); /* ! */
|
||||
t = _t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pc = _pc;
|
||||
insn = memory[pc];
|
||||
} while (1);
|
||||
}
|
||||
/* end of cpu */
|
||||
|
||||
/* start of i/o demo */
|
||||
|
||||
|
||||
int main(int argc , char *argv[])
|
||||
{
|
||||
unsigned short m[0x4000]; /* 32kb or RAM */
|
||||
FILE *f = fopen("j1.bin", "rb");
|
||||
fread(m, 0x2000, sizeof(m[0]), f); /* 0kb - 16kb data and code */
|
||||
fclose(f);
|
||||
if (argc>1) { // program name is counted as one
|
||||
struct stat st;
|
||||
f = fopen(argv[1], "r");
|
||||
stat(argv[1], &st);
|
||||
(&m[0x2000])[0] = st.st_size; /* 16kb - 32kb memory mapped i/o */
|
||||
fread(&m[0x2001], 0x2000, sizeof(m[0]), f);
|
||||
fclose(f);
|
||||
}
|
||||
memory = m;
|
||||
execute(0x00);
|
||||
return 0;
|
||||
}
|
3316
verilog/j1eforth/j1eforth-plus/j1.hex
Normal file
3316
verilog/j1eforth/j1eforth-plus/j1.hex
Normal file
File diff suppressed because it is too large
Load Diff
588
verilog/j1eforth/j1eforth.v
Normal file
588
verilog/j1eforth/j1eforth.v
Normal file
@ -0,0 +1,588 @@
|
||||
`define FOMU 1
|
||||
`default_nettype none
|
||||
// Correctly map pins for the iCE40UP5K SB_RGBA_DRV hard macro.
|
||||
// The variables EVT, PVT and HACKER are set from the yosys commandline e.g. yosys -D HACKER=1
|
||||
`ifdef EVT
|
||||
`define BLUEPWM RGB0PWM
|
||||
`define REDPWM RGB1PWM
|
||||
`define GREENPWM RGB2PWM
|
||||
`elsif HACKER
|
||||
`define BLUEPWM RGB0PWM
|
||||
`define GREENPWM RGB2PWM
|
||||
`define REDPWM RGB1PWM
|
||||
`elsif PVT
|
||||
`define GREENPWM RGB0PWM
|
||||
`define REDPWM RGB1PWM
|
||||
`define BLUEPWM RGB2PWM
|
||||
`else
|
||||
`error_board_not_supported
|
||||
`endif
|
||||
|
||||
module top(
|
||||
// 48MHz Clock Input
|
||||
input clki,
|
||||
// LED outputs
|
||||
output rgb0, // blue
|
||||
output rgb1, // green
|
||||
output rgb2, // red
|
||||
// USB Pins
|
||||
output usb_dp,
|
||||
output usb_dn,
|
||||
output usb_dp_pu,
|
||||
// SPI
|
||||
output spi_mosi,
|
||||
input spi_miso,
|
||||
output spi_clk,
|
||||
output spi_cs,
|
||||
// USER pads
|
||||
input user_1,
|
||||
input user_2,
|
||||
input user_3,
|
||||
input user_4
|
||||
);
|
||||
|
||||
// Connect to system clk_48mhz (with buffering)
|
||||
wire clk, clk_48mhz;
|
||||
SB_GB clk_gb (
|
||||
.USER_SIGNAL_TO_GLOBAL_BUFFER(clki),
|
||||
.GLOBAL_BUFFER_OUTPUT(clk)
|
||||
);
|
||||
assign clk_48mhz = clk;
|
||||
|
||||
// RGB LED Driver
|
||||
reg [2:0] setRGB;
|
||||
SB_RGBA_DRV #(
|
||||
.CURRENT_MODE("0b1"), // half current
|
||||
.RGB0_CURRENT("0b000011"), // 4 mA
|
||||
.RGB1_CURRENT("0b000011"), // 4 mA
|
||||
.RGB2_CURRENT("0b000011") // 4 mA
|
||||
) RGBA_DRIVER (
|
||||
.CURREN(1'b1),
|
||||
.RGBLEDEN(1'b1),
|
||||
.`BLUEPWM(setRGB[0]), // Blue
|
||||
.`REDPWM(setRGB[1]), // Red
|
||||
.`GREENPWM(setRGB[2]), // Green
|
||||
.RGB0(rgb0),
|
||||
.RGB1(rgb1),
|
||||
.RGB2(rgb2)
|
||||
);
|
||||
|
||||
// user buttons
|
||||
wire [3:0] buttons;
|
||||
assign buttons = { user_4, user_3, user_2, user_1 };
|
||||
|
||||
// SPRAM driver
|
||||
// https://github.com/damdoy/ice40_ultraplus_examples/blob/master/spram/top.v
|
||||
// 4 x 16384 x 16bit
|
||||
reg [15:0] sram_address; // 16bit 0-65535 address
|
||||
reg [15:0] sram_data_read; // data read from SPRAM after bank switching
|
||||
reg [15:0] sram_data_write; // data to write to SPRAM
|
||||
assign sram_data_in = sram_data_write;
|
||||
wire [15:0] sram_data_in; // to SB_SPRAM256KA
|
||||
wire [15:0] sram_data_out00; // from SB_SPRAM256KA bank 00
|
||||
wire [15:0] sram_data_out01; // from SB_SPRAM256KA bank 01
|
||||
wire [15:0] sram_data_out10; // from SB_SPRAM256KA bank 10
|
||||
wire [15:0] sram_data_out11; // from SB_SPRAM256KA bank 11
|
||||
wire sram_wren;
|
||||
reg sram_readwrite;
|
||||
assign sram_wren = sram_readwrite;
|
||||
|
||||
always @(posedge clk_48mhz) begin
|
||||
// SPRAM automatic bank switching for reading data from SB_SPRAM256KA banks
|
||||
case( sram_address[15:14])
|
||||
2'b00: sram_data_read = sram_data_out00;
|
||||
2'b01: sram_data_read = sram_data_out01;
|
||||
2'b10: sram_data_read = sram_data_out10;
|
||||
2'b11: sram_data_read = sram_data_out11;
|
||||
endcase
|
||||
end
|
||||
|
||||
SB_SPRAM256KA spram00 (
|
||||
.ADDRESS(sram_address),
|
||||
.DATAIN(sram_data_in),
|
||||
.MASKWREN(4'b1111),
|
||||
.WREN(sram_wren),
|
||||
.CHIPSELECT(sram_address[15:14]==2'b00),
|
||||
.CLOCK(clk_48mhz),
|
||||
.STANDBY(1'b0),
|
||||
.SLEEP(1'b0),
|
||||
.POWEROFF(1'b1),
|
||||
.DATAOUT(sram_data_out00)
|
||||
);
|
||||
SB_SPRAM256KA spram01 (
|
||||
.ADDRESS(sram_address),
|
||||
.DATAIN(sram_data_in),
|
||||
.MASKWREN(4'b1111),
|
||||
.WREN(sram_wren),
|
||||
.CHIPSELECT(sram_address[15:14]==2'b01),
|
||||
.CLOCK(clk_48mhz),
|
||||
.STANDBY(1'b0),
|
||||
.SLEEP(1'b0),
|
||||
.POWEROFF(1'b1),
|
||||
.DATAOUT(sram_data_out01)
|
||||
);
|
||||
SB_SPRAM256KA spram10 (
|
||||
.ADDRESS(sram_address),
|
||||
.DATAIN(sram_data_in),
|
||||
.MASKWREN(4'b1111),
|
||||
.WREN(sram_wren),
|
||||
.CHIPSELECT(sram_address[15:14]==2'b10),
|
||||
.CLOCK(clk_48mhz),
|
||||
.STANDBY(1'b0),
|
||||
.SLEEP(1'b0),
|
||||
.POWEROFF(1'b1),
|
||||
.DATAOUT(sram_data_out10)
|
||||
);
|
||||
SB_SPRAM256KA spram11 (
|
||||
.ADDRESS(sram_address),
|
||||
.DATAIN(sram_data_in),
|
||||
.MASKWREN(4'b1111),
|
||||
.WREN(sram_wren),
|
||||
.CHIPSELECT(sram_address[15:14]==2'b11),
|
||||
.CLOCK(clk_48mhz),
|
||||
.STANDBY(1'b0),
|
||||
.SLEEP(1'b0),
|
||||
.POWEROFF(1'b1),
|
||||
.DATAOUT(sram_data_out11)
|
||||
);
|
||||
|
||||
// Generate RESET
|
||||
reg [31:0] RST_d;
|
||||
reg [31:0] RST_q;
|
||||
|
||||
reg ready = 0;
|
||||
|
||||
always @* begin
|
||||
RST_d = RST_q >> 1;
|
||||
end
|
||||
|
||||
always @(posedge clk_48mhz) begin
|
||||
if (ready) begin
|
||||
RST_q <= RST_d;
|
||||
end else begin
|
||||
ready <= 1;
|
||||
RST_q <= 32'b111111111111111111111111111111;
|
||||
end
|
||||
end
|
||||
|
||||
wire reset_main;
|
||||
assign reset_main = RST_q[0];
|
||||
wire run_main;
|
||||
assign run_main = 1'b1;
|
||||
|
||||
|
||||
// USB_ACM UART CODE
|
||||
// Generate reset signal
|
||||
reg [5:0] reset_cnt = 0;
|
||||
wire reset = ~reset_cnt[5];
|
||||
always @(posedge clk_48mhz)
|
||||
reset_cnt <= reset_cnt + reset;
|
||||
|
||||
// uart pipeline in
|
||||
reg [7:0] uart_in_data;
|
||||
reg uart_in_valid;
|
||||
wire uart_in_ready;
|
||||
wire [7:0] uart_out_data;
|
||||
wire uart_out_valid;
|
||||
wire uart_out_ready;
|
||||
|
||||
// usb uart - this instanciates the entire USB device.
|
||||
usb_uart uart (
|
||||
.clk_48mhz (clk_48mhz),
|
||||
.reset (reset),
|
||||
|
||||
// pins
|
||||
.pin_usb_p( usb_dp ),
|
||||
.pin_usb_n( usb_dn ),
|
||||
|
||||
// uart pipeline in
|
||||
.uart_in_data( uart_in_data ),
|
||||
.uart_in_valid( uart_in_valid ),
|
||||
.uart_in_ready( uart_in_ready ),
|
||||
|
||||
.uart_out_data( uart_out_data ),
|
||||
.uart_out_valid( uart_out_valid ),
|
||||
.uart_out_ready( uart_out_ready )
|
||||
);
|
||||
|
||||
// USB Host Detect Pull Up
|
||||
assign usb_dp_pu = 1'b1;
|
||||
|
||||
// j1eforth ROM
|
||||
reg [15:0] rom[0:3336]; initial $readmemh("j1eforth-plus/j1.hex", rom);
|
||||
|
||||
// CYCLE to control each stage
|
||||
// CYCLE allows 1 clk_48mhz cycle for BRAM access and 3 clk_48mhz cycles for SPRAM access
|
||||
// INIT to determine if copying rom to ram or executing
|
||||
// INIT 0 SPRAM, INIT 1 ROM to SPRAM, INIT 2 J1 CPU
|
||||
reg [3:0] CYCLE = 0;
|
||||
reg [1:0] INIT = 0;
|
||||
|
||||
// Address for 0 to SPRAM, copying ROM, plus storage
|
||||
reg [15:0] copyaddress = 0;
|
||||
reg [15:0] bramREAD;
|
||||
reg bramENABLE = 0;
|
||||
|
||||
// instruction being executed with decoding information
|
||||
// +---------------------------------------------------------------+
|
||||
// | F | E | D | C | B | A | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
// +---------------------------------------------------------------+
|
||||
// | 1 | LITERAL VALUE |
|
||||
// +---------------------------------------------------------------+
|
||||
// | 0 | 0 | 0 | BRANCH TARGET ADDRESS |
|
||||
// +---------------------------------------------------------------+
|
||||
// | 0 | 0 | 1 | CONDITIONAL BRANCH TARGET ADDRESS |
|
||||
// +---------------------------------------------------------------+
|
||||
// | 0 | 1 | 0 | CALL TARGET ADDRESS |
|
||||
// +---------------------------------------------------------------+
|
||||
// | 0 | 1 | 1 |R2P| ALU OPERATION |T2N|T2R|N2A|J1+| RSTACK| DSTACK|
|
||||
// +---------------------------------------------------------------+
|
||||
// | F | E | D | C | B | A | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
// +---------------------------------------------------------------+
|
||||
reg [15:0] instruction;
|
||||
wire [15:0] immediate = { 1'b0, instruction[14:0] };
|
||||
wire is_lit = instruction[15];
|
||||
wire is_alu = ( instruction[15:13] == 3'b011 );
|
||||
wire is_call = ( instruction[15:13] == 3'b010 );
|
||||
wire dstackWrite = (is_lit | ( is_alu & instruction[7] ) );
|
||||
wire rstackWrite = (is_call | ( is_alu & instruction[6] ) );
|
||||
wire [4:0] ddelta = { instruction[1], instruction[1], instruction[1], instruction[1:0] };
|
||||
wire [4:0] rdelta = { instruction[3], instruction[3], instruction[3], instruction[3:2] };
|
||||
|
||||
// data and return stacks with pointers
|
||||
reg [15:0] dstack[0:31];
|
||||
reg [15:0] rstack[0:31];
|
||||
reg [15:0] stackTop = 0;
|
||||
reg [15:0] newStackTop;
|
||||
reg [4:0] dsp = 0;
|
||||
reg [4:0] newDSP;
|
||||
reg [15:0] stackNext;
|
||||
reg [15:0] rstackTop;
|
||||
reg [4:0] rsp = 0;
|
||||
reg [4:0] newRSP;
|
||||
reg [15:0] rStackTop;
|
||||
reg [15:0] rstackWData;
|
||||
|
||||
// program counter
|
||||
reg [12:0] pc = 0;
|
||||
reg [12:0] newPC;
|
||||
wire [12:0] pcPlusOne;
|
||||
assign pcPlusOne = pc + 1;
|
||||
|
||||
// value read from SPRAM
|
||||
reg [15:0] memoryInput;
|
||||
|
||||
// UART input and output buffers
|
||||
reg [7:0] uartInBuffer [0:31];
|
||||
reg [4:0] uartInBufferNext = 0;
|
||||
reg [4:0] uartInBufferTop = 0;
|
||||
reg [7:0] uartOutBuffer [0:31];
|
||||
reg [4:0] uartOutBufferNext = 0;
|
||||
reg [4:0] uartOutBufferTop = 0;
|
||||
reg [4:0] newUartOutBufferTop = 0;
|
||||
|
||||
// READ from BRAM ROM
|
||||
always @(posedge clk_48mhz) begin
|
||||
if( bramENABLE )
|
||||
bramREAD <= rom[copyaddress];
|
||||
end
|
||||
|
||||
// UART
|
||||
always @(posedge clk_48mhz) begin
|
||||
end
|
||||
|
||||
// MAIN LOOP
|
||||
always @(posedge clk_48mhz) begin
|
||||
|
||||
if( reset == 1 ) begin
|
||||
pc <= 0;
|
||||
dsp <= 0;
|
||||
stackTop <= 0;
|
||||
rsp <= 0;
|
||||
|
||||
CYCLE <= 0;
|
||||
INIT <= 0;
|
||||
copyaddress <= 0;
|
||||
|
||||
uartInBufferNext <= 0;
|
||||
uartInBufferTop <= 0;
|
||||
uartOutBufferNext <= 0;
|
||||
uartOutBufferTop <= 0;
|
||||
newUartOutBufferTop <= 0;
|
||||
end else begin
|
||||
|
||||
case( INIT )
|
||||
0: begin // 0 to SPRAM
|
||||
case( CYCLE )
|
||||
0: begin
|
||||
// SETUP WRITE of 0 to SPRAM[copyaddress]
|
||||
sram_address <= copyaddress;
|
||||
sram_data_write <= 0;
|
||||
sram_readwrite <= 1;
|
||||
end
|
||||
11: begin
|
||||
sram_readwrite <= 0;
|
||||
copyaddress = copyaddress + 1;
|
||||
end
|
||||
12: begin
|
||||
if( copyaddress == 16384 ) begin
|
||||
INIT <= 1;
|
||||
copyaddress <= 0;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
end
|
||||
endcase
|
||||
end // 0 to SPRAM
|
||||
|
||||
1: begin // COPY ROM to SPRAM
|
||||
bramENABLE = 1;
|
||||
case( CYCLE )
|
||||
2: begin
|
||||
// SETUP WRITE of 0 to SPRAM[copyaddress]
|
||||
sram_address <= copyaddress;
|
||||
sram_data_write <= bramREAD;
|
||||
sram_readwrite <= 1;
|
||||
end
|
||||
11: begin
|
||||
sram_readwrite <= 0;
|
||||
copyaddress = copyaddress + 1;
|
||||
end
|
||||
12: begin
|
||||
if( copyaddress == 4096 ) begin
|
||||
INIT <= 2;
|
||||
copyaddress <= 0;
|
||||
bramENABLE = 0;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
end
|
||||
endcase
|
||||
end // COPY ROM to SPRAM
|
||||
|
||||
2: begin // SPARE INIT
|
||||
bramENABLE = 1;
|
||||
case( CYCLE )
|
||||
12: begin
|
||||
INIT <= 3;
|
||||
end
|
||||
default: begin
|
||||
end
|
||||
endcase
|
||||
end // SPARE INIT
|
||||
|
||||
3: begin // MAIN J1 CPU LOOP
|
||||
// READ from UART if character available and store
|
||||
if( uart_out_valid ) begin
|
||||
uartInBuffer[uartInBufferTop] <= uart_out_data;
|
||||
uart_out_ready <= 1;
|
||||
uartInBufferTop <= uartInBufferTop + 1;
|
||||
end
|
||||
|
||||
// WRITE to UART if characters in buffer and UART is ready
|
||||
if( ~(uartOutBufferNext == uartOutBufferTop) & ~( uart_in_valid ) ) begin
|
||||
uart_in_data <= uartOutBuffer[uartOutBufferNext];
|
||||
uart_in_valid <= 1;
|
||||
uartOutBufferNext <= uartOutBufferNext + 1;
|
||||
end
|
||||
uartOutBufferTop = newUartOutBufferTop;
|
||||
|
||||
case( CYCLE )
|
||||
0: begin
|
||||
// Read stackNext and rStackTop
|
||||
stackNext <= dstack[dsp];
|
||||
rStackTop <= rstack[rsp];
|
||||
|
||||
// start READ memoryInput = [stackTop] result ready in 2 cycles
|
||||
sram_address <= stackTop >> 1;
|
||||
sram_readwrite <= 0;
|
||||
end
|
||||
|
||||
3: begin
|
||||
// wait then read the data from SPRAM
|
||||
memoryInput <= sram_data_read;
|
||||
end
|
||||
|
||||
4: begin
|
||||
// start READ instruction = [pc] result ready in 2 cycles
|
||||
sram_address <= pc;
|
||||
sram_readwrite <= 0;
|
||||
end
|
||||
|
||||
7: begin
|
||||
// wait then read the instruction from SPRAM
|
||||
instruction = sram_data_read;
|
||||
end
|
||||
|
||||
8: begin
|
||||
// J1 CPU instruction execute
|
||||
if( is_lit ) begin
|
||||
// LITERAL Push value onto stack
|
||||
newStackTop <= immediate;
|
||||
newPC <= pcPlusOne;
|
||||
newDSP <= dsp + 1;
|
||||
newRSP <= rsp;
|
||||
end else begin
|
||||
case( instruction[14:13] )
|
||||
2'b00: begin
|
||||
// BRANCH
|
||||
newStackTop <= stackTop;
|
||||
newPC <= instruction[12:0];
|
||||
newDSP <= dsp;
|
||||
newRSP <= rsp;
|
||||
end
|
||||
|
||||
2'b01: begin
|
||||
// 0BRANCH
|
||||
newStackTop <= stackNext;
|
||||
newPC <= ( stackTop == 0 ) ? instruction[12:0] : pcPlusOne;
|
||||
newDSP <= dsp - 1;
|
||||
newRSP <= rsp;
|
||||
end
|
||||
|
||||
2'b10: begin
|
||||
// CALL
|
||||
newStackTop <= stackTop;
|
||||
newPC <= instruction[12:0];
|
||||
newDSP <= dsp;
|
||||
newRSP <= rsp + 1;
|
||||
rstackWData <= pcPlusOne << 1;
|
||||
end
|
||||
|
||||
2'b11: begin
|
||||
case( instruction[4] )
|
||||
// ALU
|
||||
1'b0: begin
|
||||
// J1 ALUOP
|
||||
case( instruction[11:8] )
|
||||
4'b0000: newStackTop = stackTop;
|
||||
4'b0001: newStackTop = stackNext;
|
||||
4'b0010: newStackTop = stackTop + stackNext;
|
||||
4'b0011: newStackTop = stackTop & stackNext;
|
||||
4'b0100: newStackTop = stackTop | stackNext;
|
||||
4'b0101: newStackTop = stackTop ^ stackNext;
|
||||
4'b0110: newStackTop = ~stackTop;
|
||||
4'b0111: newStackTop = {16{(stackNext == stackTop)}};
|
||||
4'b1000: newStackTop = {16{($signed(stackNext) < $signed(stackTop))}};
|
||||
4'b1001: newStackTop = stackNext >> stackTop[3:0];
|
||||
4'b1010: newStackTop = stackTop - 1;
|
||||
4'b1011: newStackTop = rStackTop;
|
||||
4'b1100: begin
|
||||
case( stackTop)
|
||||
16'hf000: begin
|
||||
newStackTop = { 8'b0, uartInBuffer[uartInBufferNext] };
|
||||
uartInBufferNext = uartInBufferNext + 1;
|
||||
end
|
||||
16'hf001: newStackTop = {14'b0, ( uartOutBufferTop + 1 == uartOutBufferNext ), ~(uartInBufferNext == uartInBufferTop)}; // Read UART status
|
||||
16'hf002: newStackTop = setRGB; // Read to rgbLED status
|
||||
16'hf003: newStackTop = {12'b0, buttons}; // Read buttons status
|
||||
default: newStackTop = memoryInput; // memoryInput
|
||||
endcase
|
||||
end
|
||||
4'b1101: newStackTop = stackNext << stackTop[3:0];
|
||||
4'b1110: newStackTop = {rsp, 3'b000, dsp};
|
||||
4'b1111: newStackTop = {16{($unsigned(stackNext) < $unsigned(stackTop))}};
|
||||
endcase
|
||||
end
|
||||
|
||||
1'b1: begin
|
||||
// J1+ ALUOP
|
||||
case( instruction[11:8] )
|
||||
4'b0000: newStackTop = {16{(stackTop == 0)}};
|
||||
4'b0001: newStackTop = ~{16{(stackTop == 0)}};
|
||||
4'b0010: newStackTop = ~{16{(stackNext == stackTop)}};
|
||||
4'b0011: newStackTop = stackTop + 1;
|
||||
4'b0100: newStackTop = stackTop << 1;
|
||||
4'b0101: newStackTop = stackTop >> 1;
|
||||
4'b0110: newStackTop = {16{($signed(stackNext) > $signed(stackTop))}};
|
||||
4'b0111: newStackTop = {16{($unsigned(stackNext) > $unsigned(stackTop))}};
|
||||
4'b1000: newStackTop = {16{($signed(stackTop) < 0)}};
|
||||
4'b1001: newStackTop = {16{($signed(stackTop) > 0)}};
|
||||
4'b1010: newStackTop = ( $signed(stackTop) < 0 ) ? - stackTop : stackTop;
|
||||
4'b1011: newStackTop = ( $signed(stackNext) > $signed(stackTop) ) ? stackNext : stackTop;
|
||||
4'b1100: newStackTop = ( $signed(stackNext) < $signed(stackTop) ) ? stackNext : stackTop;
|
||||
4'b1101: newStackTop = -stackTop;
|
||||
4'b1110: newStackTop = stackNext - stackTop;
|
||||
4'b1111: newStackTop = {16{($signed(stackNext) >= $signed(stackTop))}};
|
||||
endcase
|
||||
end
|
||||
endcase // J1 / J1+
|
||||
|
||||
// UPDATE newDSP newRSP
|
||||
newDSP <= dsp + ddelta;
|
||||
newRSP <= rsp + rdelta;
|
||||
rstackWData <= stackTop;
|
||||
|
||||
// r2pc - return from call or next instruction
|
||||
newPC <= ( instruction[12] ) ? rStackTop >> 1 : pcPlusOne;
|
||||
|
||||
// n2memt mem[t] = n WRITE to SPRAM or UART/LED
|
||||
if( instruction[5] ) begin
|
||||
case( stackTop )
|
||||
16'hf000: begin
|
||||
// OUTPUT to UART via buffer
|
||||
uartOutBuffer[uartOutBufferTop] <= stackNext[7:0];
|
||||
newUartOutBufferTop <= uartOutBufferTop + 1;
|
||||
end
|
||||
|
||||
16'hf002: setRGB <= stackNext; // OUTPUT to rgbLED
|
||||
|
||||
default: begin
|
||||
// WRITE to SPRAM
|
||||
sram_address <= stackTop >> 1;
|
||||
sram_data_write <= stackNext;
|
||||
sram_readwrite <= 1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end // ALU
|
||||
|
||||
endcase // branch 0branch call alu
|
||||
end // not is_lit
|
||||
end // J1 CPU Instruction execute
|
||||
|
||||
9: begin
|
||||
// Write to dstack and rstack
|
||||
if( dstackWrite )
|
||||
dstack[newDSP] <= stackTop;
|
||||
if( rstackWrite )
|
||||
rstack[newRSP] <= rstackWData;
|
||||
end
|
||||
|
||||
10: begin
|
||||
// Update dsp, rsp, pc, stackTop
|
||||
dsp <= newDSP;
|
||||
pc <= newPC;
|
||||
stackTop <= newStackTop;
|
||||
rsp <= newRSP;
|
||||
end
|
||||
|
||||
|
||||
12: begin
|
||||
// reset sram_readwrite
|
||||
sram_readwrite <= 0;
|
||||
end
|
||||
|
||||
default: begin
|
||||
end
|
||||
|
||||
endcase
|
||||
end // MAIN J1 CPU LOOP
|
||||
|
||||
default: begin
|
||||
end
|
||||
|
||||
endcase // INIT
|
||||
|
||||
// Reset UART Output
|
||||
if(uart_in_ready & uart_in_valid)
|
||||
uart_in_valid <= 0;
|
||||
|
||||
// Move to next CYCLE ( 0 to 12 , then back to 0 )
|
||||
CYCLE = ( CYCLE == 12 ) ? 0 : CYCLE + 1;
|
||||
|
||||
|
||||
end // NOT RESET
|
||||
end // MAIN LOOP
|
||||
|
||||
endmodule
|
16
verilog/j1eforth/pcf/fomu-hacker.pcf
Normal file
16
verilog/j1eforth/pcf/fomu-hacker.pcf
Normal file
@ -0,0 +1,16 @@
|
||||
# Configuration for the Fomu hacker board.
|
||||
set_io rgb0 A5 # Blue LED
|
||||
set_io rgb1 B5 # Green LED
|
||||
set_io rgb2 C5 # Red LED
|
||||
set_io clki F5 # Clock input from 48MHz Oscillator
|
||||
set_io spi_mosi F1 # SPI Master Out, Slave In Pin
|
||||
set_io spi_miso E1 # SPI Master In, Slave Out Pin
|
||||
set_io spi_clk D1 # SPI Master Clock Output Pin
|
||||
set_io spi_cs C1 # SPI Chip Select
|
||||
set_io user_1 F4 # User touch pad 1
|
||||
set_io user_2 E5 # User touch pad 2
|
||||
set_io user_3 E4 # User touch pad 3
|
||||
set_io user_4 F2 # User touch pad 4
|
||||
set_io usb_dn A2 # USB D- pad
|
||||
set_io usb_dp A4 # USB D+ pad
|
||||
set_io usb_dp_pu D5 # USB D+ pull up (indicates device connected)
|
27
verilog/j1eforth/tinyfpga_bx_usbserial/usb/edge_detect.v
Normal file
27
verilog/j1eforth/tinyfpga_bx_usbserial/usb/edge_detect.v
Normal file
@ -0,0 +1,27 @@
|
||||
module rising_edge_detector (
|
||||
input clk,
|
||||
input in,
|
||||
output out
|
||||
);
|
||||
reg in_q;
|
||||
|
||||
always @(posedge clk) begin
|
||||
in_q <= in;
|
||||
end
|
||||
|
||||
assign out = !in_q && in;
|
||||
endmodule
|
||||
|
||||
module falling_edge_detector (
|
||||
input clk,
|
||||
input in,
|
||||
output out
|
||||
);
|
||||
reg in_q;
|
||||
|
||||
always @(posedge clk) begin
|
||||
in_q <= in;
|
||||
end
|
||||
|
||||
assign out = in_q && !in;
|
||||
endmodule
|
53
verilog/j1eforth/tinyfpga_bx_usbserial/usb/serial.v
Normal file
53
verilog/j1eforth/tinyfpga_bx_usbserial/usb/serial.v
Normal file
@ -0,0 +1,53 @@
|
||||
module width_adapter #(
|
||||
parameter [31:0] INPUT_WIDTH = 8,
|
||||
parameter [31:0] OUTPUT_WIDTH = 1
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
|
||||
input data_in_put,
|
||||
output data_in_free,
|
||||
input [INPUT_WIDTH-1:0] data_in,
|
||||
|
||||
output data_out_put,
|
||||
input data_out_free,
|
||||
output [OUTPUT_WIDTH-1:0] data_out
|
||||
);
|
||||
|
||||
generate
|
||||
if (INPUT_WIDTH > OUTPUT_WIDTH) begin
|
||||
// wide to narrow conversion
|
||||
reg [INPUT_WIDTH:0] data_in_q;
|
||||
reg has_data;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!has_data && data_in_put) begin
|
||||
data_in_q <= {1'b1, data_in};
|
||||
has_data <= 1;
|
||||
end
|
||||
|
||||
if (has_data && data_out_free) begin
|
||||
data_in_q <= data_in_q >> OUTPUT_WIDTH;
|
||||
end
|
||||
|
||||
if (data_in_q == 1'b1) begin
|
||||
has_data <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
assign data_out = data_in_q[OUTPUT_WIDTH:1];
|
||||
assign data_out_put = has_data;
|
||||
|
||||
|
||||
end else if (INPUT_WIDTH < OUTPUT_WIDTH) begin
|
||||
// narrow to wide conversion
|
||||
|
||||
|
||||
end else begin
|
||||
assign data_in_free = data_out_free;
|
||||
assign data_out_put = data_in_put;
|
||||
assign data_out = data_in;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
39
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_in_arb.v
Normal file
39
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_in_arb.v
Normal file
@ -0,0 +1,39 @@
|
||||
module usb_fs_in_arb #(
|
||||
parameter NUM_IN_EPS = 1
|
||||
) (
|
||||
////////////////////
|
||||
// endpoint interface
|
||||
////////////////////
|
||||
input [NUM_IN_EPS-1:0] in_ep_req,
|
||||
output reg [NUM_IN_EPS-1:0] in_ep_grant,
|
||||
input [(NUM_IN_EPS*8)-1:0] in_ep_data,
|
||||
|
||||
|
||||
////////////////////
|
||||
// protocol engine interface
|
||||
////////////////////
|
||||
output reg [7:0] arb_in_ep_data
|
||||
);
|
||||
integer i;
|
||||
reg grant;
|
||||
|
||||
always @* begin
|
||||
grant = 0;
|
||||
|
||||
arb_in_ep_data <= 0;
|
||||
|
||||
for (i = 0; i < NUM_IN_EPS; i = i + 1) begin
|
||||
in_ep_grant[i] <= 0;
|
||||
|
||||
if (in_ep_req[i] && !grant) begin
|
||||
in_ep_grant[i] <= 1;
|
||||
arb_in_ep_data <= in_ep_data[i * 8 +: 8];
|
||||
grant = 1;
|
||||
end
|
||||
end
|
||||
|
||||
// if (!grant) begin
|
||||
// arb_in_ep_data <= 0;
|
||||
// end
|
||||
end
|
||||
endmodule
|
421
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_in_pe.v
Normal file
421
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_in_pe.v
Normal file
@ -0,0 +1,421 @@
|
||||
// The IN Protocol Engine sends data to the host.
|
||||
module usb_fs_in_pe #(
|
||||
parameter NUM_IN_EPS = 11,
|
||||
parameter MAX_IN_PACKET_SIZE = 32
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
input [NUM_IN_EPS-1:0] reset_ep,
|
||||
input [6:0] dev_addr,
|
||||
|
||||
|
||||
////////////////////
|
||||
// endpoint interface
|
||||
////////////////////
|
||||
output reg [NUM_IN_EPS-1:0] in_ep_data_free = 0,
|
||||
input [NUM_IN_EPS-1:0] in_ep_data_put,
|
||||
input [7:0] in_ep_data,
|
||||
input [NUM_IN_EPS-1:0] in_ep_data_done,
|
||||
input [NUM_IN_EPS-1:0] in_ep_stall,
|
||||
output reg [NUM_IN_EPS-1:0] in_ep_acked = 0,
|
||||
|
||||
|
||||
////////////////////
|
||||
// rx path
|
||||
////////////////////
|
||||
|
||||
// Strobed on reception of packet.
|
||||
input rx_pkt_start,
|
||||
input rx_pkt_end,
|
||||
input rx_pkt_valid,
|
||||
|
||||
// Most recent packet received.
|
||||
input [3:0] rx_pid,
|
||||
input [6:0] rx_addr,
|
||||
input [3:0] rx_endp,
|
||||
input [10:0] rx_frame_num,
|
||||
|
||||
|
||||
////////////////////
|
||||
// tx path
|
||||
////////////////////
|
||||
|
||||
// Strobe to send new packet.
|
||||
output reg tx_pkt_start = 0,
|
||||
input tx_pkt_end,
|
||||
|
||||
|
||||
// Packet type to send
|
||||
output reg [3:0] tx_pid = 0,
|
||||
|
||||
// Data payload to send if any
|
||||
output tx_data_avail,
|
||||
input tx_data_get,
|
||||
output reg [7:0] tx_data,
|
||||
|
||||
output [7:0] debug
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// endpoint state machine
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
reg [1:0] ep_state [NUM_IN_EPS - 1:0];
|
||||
reg [1:0] ep_state_next [NUM_IN_EPS - 1:0];
|
||||
|
||||
// latched on valid IN token
|
||||
reg [3:0] current_endp = 0;
|
||||
|
||||
wire [1:0] current_ep_state = ep_state[current_endp][1:0];
|
||||
|
||||
localparam READY_FOR_PKT = 0;
|
||||
localparam PUTTING_PKT = 1;
|
||||
localparam GETTING_PKT = 2;
|
||||
localparam STALL = 3;
|
||||
|
||||
assign debug[1:0] = ( current_endp == 1 ) ? current_ep_state : 0;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// in transfer state machine
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
localparam IDLE = 0;
|
||||
localparam RCVD_IN = 1;
|
||||
localparam SEND_DATA = 2;
|
||||
localparam WAIT_ACK = 3;
|
||||
|
||||
reg [1:0] in_xfr_state = IDLE;
|
||||
reg [1:0] in_xfr_state_next;
|
||||
|
||||
assign debug[3:2] = ( current_endp == 1 ) ? in_xfr_state : 0;
|
||||
|
||||
reg in_xfr_start = 0;
|
||||
reg in_xfr_end = 0;
|
||||
|
||||
assign debug[4] = tx_data_avail;
|
||||
assign debug[5] = tx_data_get;
|
||||
|
||||
// data toggle state
|
||||
reg [NUM_IN_EPS - 1:0] data_toggle = 0;
|
||||
|
||||
// endpoint data buffer
|
||||
reg [7:0] in_data_buffer [(MAX_IN_PACKET_SIZE * NUM_IN_EPS) - 1:0];
|
||||
// Address registers - one bit longer (6) than required (5) to permit fullness != emptyness
|
||||
reg [5:0] ep_put_addr [NUM_IN_EPS - 1:0];
|
||||
reg [5:0] ep_get_addr [NUM_IN_EPS - 1:0];
|
||||
|
||||
integer i = 0;
|
||||
initial begin
|
||||
for (i = 0; i < NUM_IN_EPS; i = i + 1) begin
|
||||
ep_put_addr[i] = 0;
|
||||
ep_get_addr[i] = 0;
|
||||
ep_state[i] = 0;
|
||||
end
|
||||
end
|
||||
|
||||
reg [3:0] in_ep_num = 0;
|
||||
|
||||
// the actual address (note using only the real 5 bits of the incoming address + the high order buffer select)
|
||||
wire [8:0] buffer_put_addr = {in_ep_num[3:0], ep_put_addr[in_ep_num][4:0]};
|
||||
wire [8:0] buffer_get_addr = {current_endp[3:0], ep_get_addr[current_endp][4:0]};
|
||||
|
||||
// endpoint data packet buffer has a data packet ready to send
|
||||
reg [NUM_IN_EPS - 1:0] endp_ready_to_send = 0;
|
||||
|
||||
// endpoint has some space free in its buffer
|
||||
reg [NUM_IN_EPS - 1:0] endp_free = 0;
|
||||
|
||||
wire token_received =
|
||||
rx_pkt_end &&
|
||||
rx_pkt_valid &&
|
||||
rx_pid[1:0] == 2'b01 &&
|
||||
rx_addr == dev_addr &&
|
||||
rx_endp < NUM_IN_EPS;
|
||||
|
||||
wire setup_token_received =
|
||||
token_received &&
|
||||
rx_pid[3:2] == 2'b11;
|
||||
|
||||
wire in_token_received =
|
||||
token_received &&
|
||||
rx_pid[3:2] == 2'b10;
|
||||
|
||||
wire ack_received =
|
||||
rx_pkt_end &&
|
||||
rx_pkt_valid &&
|
||||
rx_pid == 4'b0010;
|
||||
|
||||
assign debug[ 6 ] = rx_pkt_start;
|
||||
assign debug[ 7 ] = rx_pkt_end;
|
||||
|
||||
|
||||
wire more_data_to_send =
|
||||
ep_get_addr[current_endp][5:0] < ep_put_addr[current_endp][5:0];
|
||||
|
||||
wire [5:0] current_ep_get_addr = ep_get_addr[current_endp][5:0];
|
||||
wire [5:0] current_ep_put_addr = ep_put_addr[current_endp][5:0];
|
||||
|
||||
|
||||
|
||||
|
||||
wire tx_data_avail_i =
|
||||
in_xfr_state == SEND_DATA &&
|
||||
more_data_to_send;
|
||||
|
||||
assign tx_data_avail = tx_data_avail_i;
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// endpoint state machine
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
genvar ep_num;
|
||||
generate
|
||||
for (ep_num = 0; ep_num < NUM_IN_EPS; ep_num = ep_num + 1) begin
|
||||
|
||||
// Manage next state
|
||||
always @* begin
|
||||
in_ep_acked[ep_num] <= 0;
|
||||
|
||||
ep_state_next[ep_num] <= ep_state[ep_num];
|
||||
|
||||
if (in_ep_stall[ep_num]) begin
|
||||
ep_state_next[ep_num] <= STALL;
|
||||
|
||||
end else begin
|
||||
case (ep_state[ep_num])
|
||||
READY_FOR_PKT : begin
|
||||
ep_state_next[ep_num] <= PUTTING_PKT;
|
||||
end
|
||||
|
||||
PUTTING_PKT : begin
|
||||
// if either the user says they're done or the buffer is full, move on to GETTING_PKT
|
||||
if ( ( in_ep_data_done[ep_num] ) || ( ep_put_addr[ep_num][5] ) ) begin
|
||||
ep_state_next[ep_num] <= GETTING_PKT;
|
||||
end else begin
|
||||
ep_state_next[ep_num] <= PUTTING_PKT;
|
||||
end
|
||||
end
|
||||
|
||||
GETTING_PKT : begin
|
||||
// here we're waiting to send the data out, and receive an ACK token back
|
||||
// No token, and we're here for a while.
|
||||
if (in_xfr_end && current_endp == ep_num) begin
|
||||
ep_state_next[ep_num] <= READY_FOR_PKT;
|
||||
in_ep_acked[ep_num] <= 1;
|
||||
|
||||
end else begin
|
||||
ep_state_next[ep_num] <= GETTING_PKT;
|
||||
end
|
||||
end
|
||||
|
||||
STALL : begin
|
||||
if (setup_token_received && rx_endp == ep_num) begin
|
||||
ep_state_next[ep_num] <= READY_FOR_PKT;
|
||||
|
||||
end else begin
|
||||
ep_state_next[ep_num] <= STALL;
|
||||
end
|
||||
end
|
||||
|
||||
default begin
|
||||
ep_state_next[ep_num] <= READY_FOR_PKT;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endp_free[ep_num] = !ep_put_addr[ep_num][5];
|
||||
in_ep_data_free[ep_num] = endp_free[ep_num] && ep_state[ep_num] == PUTTING_PKT;
|
||||
end
|
||||
|
||||
// Handle the data pointer (advancing and clearing)
|
||||
always @(posedge clk) begin
|
||||
if (reset || reset_ep[ep_num]) begin
|
||||
ep_state[ep_num] <= READY_FOR_PKT;
|
||||
|
||||
end else begin
|
||||
ep_state[ep_num] <= ep_state_next[ep_num];
|
||||
|
||||
case (ep_state[ep_num])
|
||||
READY_FOR_PKT : begin
|
||||
// make sure we start with a clear buffer (and the extra bit!)
|
||||
ep_put_addr[ep_num][5:0] <= 0;
|
||||
end
|
||||
|
||||
PUTTING_PKT : begin
|
||||
// each time we are putting, and there's a data_put signal, increment the address
|
||||
if (in_ep_data_put[ep_num] && ( ~ep_put_addr[ep_num][5] ) ) begin
|
||||
ep_put_addr[ep_num][5:0] <= ep_put_addr[ep_num][5:0] + 1;
|
||||
end
|
||||
end
|
||||
|
||||
GETTING_PKT : begin
|
||||
end
|
||||
|
||||
STALL : begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Decide which in_ep_num we're talking to
|
||||
// Using the data put register is OK here
|
||||
integer ep_num_decoder;
|
||||
always @* begin
|
||||
in_ep_num <= 0;
|
||||
|
||||
for (ep_num_decoder = 0; ep_num_decoder < NUM_IN_EPS; ep_num_decoder = ep_num_decoder + 1) begin
|
||||
if (in_ep_data_put[ep_num_decoder]) begin
|
||||
in_ep_num <= ep_num_decoder;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Handle putting the new data into the buffer
|
||||
always @(posedge clk) begin
|
||||
case (ep_state[in_ep_num])
|
||||
PUTTING_PKT : begin
|
||||
if (in_ep_data_put[in_ep_num] && !ep_put_addr[in_ep_num][5]) begin
|
||||
in_data_buffer[buffer_put_addr] <= in_ep_data;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// in transfer state machine
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
reg rollback_in_xfr;
|
||||
|
||||
always @* begin
|
||||
in_xfr_state_next <= in_xfr_state;
|
||||
in_xfr_start <= 0;
|
||||
in_xfr_end <= 0;
|
||||
tx_pkt_start <= 0;
|
||||
tx_pid <= 4'b0000;
|
||||
rollback_in_xfr <= 0;
|
||||
|
||||
case (in_xfr_state)
|
||||
IDLE : begin
|
||||
rollback_in_xfr <= 1;
|
||||
|
||||
if (in_token_received) begin
|
||||
in_xfr_state_next <= RCVD_IN;
|
||||
|
||||
end else begin
|
||||
in_xfr_state_next <= IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
// Got an IN token
|
||||
RCVD_IN : begin
|
||||
tx_pkt_start <= 1;
|
||||
|
||||
if (ep_state[current_endp] == STALL) begin
|
||||
in_xfr_state_next <= IDLE;
|
||||
tx_pid <= 4'b1110; // STALL
|
||||
|
||||
end else if (ep_state[current_endp] == GETTING_PKT) begin
|
||||
// if we were in GETTING_PKT (done getting data from the device), Send it!
|
||||
in_xfr_state_next <= SEND_DATA;
|
||||
tx_pid <= {data_toggle[current_endp], 3'b011}; // DATA0/1
|
||||
in_xfr_start <= 1;
|
||||
|
||||
end else begin
|
||||
in_xfr_state_next <= IDLE;
|
||||
tx_pid <= 4'b1010; // NAK
|
||||
end
|
||||
end
|
||||
|
||||
SEND_DATA : begin
|
||||
// Send the data from the buffer now (until the out (get) address = the in (put) address)
|
||||
if (!more_data_to_send) begin
|
||||
in_xfr_state_next <= WAIT_ACK;
|
||||
|
||||
end else begin
|
||||
in_xfr_state_next <= SEND_DATA;
|
||||
end
|
||||
end
|
||||
|
||||
WAIT_ACK : begin
|
||||
// FIXME: need to handle smash/timeout
|
||||
// Could wait here forever (although another token will come along)
|
||||
if (ack_received) begin
|
||||
in_xfr_state_next <= IDLE;
|
||||
in_xfr_end <= 1;
|
||||
|
||||
end else if (in_token_received) begin
|
||||
in_xfr_state_next <= RCVD_IN;
|
||||
rollback_in_xfr <= 1;
|
||||
|
||||
end else if (rx_pkt_end) begin
|
||||
in_xfr_state_next <= IDLE;
|
||||
rollback_in_xfr <= 1;
|
||||
|
||||
end else begin
|
||||
in_xfr_state_next <= WAIT_ACK;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
tx_data <= in_data_buffer[buffer_get_addr];
|
||||
|
||||
integer j;
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
in_xfr_state <= IDLE;
|
||||
|
||||
end else begin
|
||||
in_xfr_state <= in_xfr_state_next;
|
||||
|
||||
// tx_data <= in_data_buffer[buffer_get_addr];
|
||||
|
||||
if (setup_token_received) begin
|
||||
data_toggle[rx_endp] <= 1;
|
||||
end
|
||||
|
||||
if (in_token_received) begin
|
||||
current_endp <= rx_endp;
|
||||
end
|
||||
|
||||
if (rollback_in_xfr) begin
|
||||
ep_get_addr[current_endp][5:0] <= 0;
|
||||
end
|
||||
|
||||
case (in_xfr_state)
|
||||
IDLE : begin
|
||||
end
|
||||
|
||||
RCVD_IN : begin
|
||||
end
|
||||
|
||||
SEND_DATA : begin
|
||||
if (tx_data_get && tx_data_avail_i) begin
|
||||
ep_get_addr[current_endp][5:0] <= ep_get_addr[current_endp][5:0] + 1;
|
||||
end
|
||||
end
|
||||
|
||||
WAIT_ACK : begin
|
||||
if (ack_received) begin
|
||||
data_toggle[current_endp] <= !data_toggle[current_endp];
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
for (j = 0; j < NUM_IN_EPS; j = j + 1) begin
|
||||
if (reset || reset_ep[j]) begin
|
||||
data_toggle[j] <= 0;
|
||||
ep_get_addr[j][5:0] <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
25
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_out_arb.v
Normal file
25
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_out_arb.v
Normal file
@ -0,0 +1,25 @@
|
||||
module usb_fs_out_arb #(
|
||||
parameter NUM_OUT_EPS = 1
|
||||
) (
|
||||
////////////////////
|
||||
// endpoint interface
|
||||
////////////////////
|
||||
input [NUM_OUT_EPS-1:0] out_ep_req,
|
||||
output reg [NUM_OUT_EPS-1:0] out_ep_grant
|
||||
);
|
||||
integer i;
|
||||
reg grant;
|
||||
|
||||
always @* begin
|
||||
grant = 0;
|
||||
|
||||
for (i = 0; i < NUM_OUT_EPS; i = i + 1) begin
|
||||
out_ep_grant[i] <= 0;
|
||||
|
||||
if (out_ep_req[i] && !grant) begin
|
||||
out_ep_grant[i] <= 1;
|
||||
grant = 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
417
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_out_pe.v
Normal file
417
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_out_pe.v
Normal file
@ -0,0 +1,417 @@
|
||||
// The OUT Protocol Engine receives data from the host.
|
||||
module usb_fs_out_pe #(
|
||||
parameter NUM_OUT_EPS = 1,
|
||||
parameter MAX_OUT_PACKET_SIZE = 32
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
input [NUM_OUT_EPS-1:0] reset_ep,
|
||||
input [6:0] dev_addr,
|
||||
|
||||
////////////////////
|
||||
// endpoint interface
|
||||
////////////////////
|
||||
output [NUM_OUT_EPS-1:0] out_ep_data_avail,
|
||||
output reg [NUM_OUT_EPS-1:0] out_ep_setup = 0,
|
||||
input [NUM_OUT_EPS-1:0] out_ep_data_get,
|
||||
output reg [7:0] out_ep_data,
|
||||
input [NUM_OUT_EPS-1:0] out_ep_stall,
|
||||
output reg [NUM_OUT_EPS-1:0] out_ep_acked = 0,
|
||||
// Added to provide a more constant way of detecting the current OUT EP than data get
|
||||
input [NUM_OUT_EPS-1:0] out_ep_grant,
|
||||
|
||||
////////////////////
|
||||
// rx path
|
||||
////////////////////
|
||||
|
||||
// Strobed on reception of packet.
|
||||
input rx_pkt_start,
|
||||
input rx_pkt_end,
|
||||
input rx_pkt_valid,
|
||||
|
||||
// Most recent packet received.
|
||||
input [3:0] rx_pid,
|
||||
input [6:0] rx_addr,
|
||||
input [3:0] rx_endp,
|
||||
input [10:0] rx_frame_num,
|
||||
|
||||
// rx_data is pushed into endpoint controller.
|
||||
input rx_data_put,
|
||||
input [7:0] rx_data,
|
||||
|
||||
|
||||
////////////////////
|
||||
// tx path
|
||||
////////////////////
|
||||
|
||||
// Strobe to send new packet.
|
||||
output reg tx_pkt_start = 0,
|
||||
input tx_pkt_end,
|
||||
output reg [3:0] tx_pid = 0
|
||||
);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// endpoint state machine
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
localparam READY_FOR_PKT = 0;
|
||||
localparam PUTTING_PKT = 1;
|
||||
localparam GETTING_PKT = 2;
|
||||
localparam STALL = 3;
|
||||
|
||||
reg [1:0] ep_state [NUM_OUT_EPS - 1:0];
|
||||
reg [1:0] ep_state_next [NUM_OUT_EPS - 1:0];
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// out transfer state machine
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
localparam IDLE = 0;
|
||||
localparam RCVD_OUT = 1;
|
||||
localparam RCVD_DATA_START = 2;
|
||||
localparam RCVD_DATA_END = 3;
|
||||
|
||||
reg [1:0] out_xfr_state = IDLE;
|
||||
reg [1:0] out_xfr_state_next;
|
||||
|
||||
reg out_xfr_start = 0;
|
||||
reg new_pkt_end = 0;
|
||||
reg rollback_data = 0;
|
||||
|
||||
|
||||
reg [3:0] out_ep_num = 0;
|
||||
|
||||
|
||||
reg [NUM_OUT_EPS - 1:0] out_ep_data_avail_i = 0;
|
||||
reg [NUM_OUT_EPS - 1:0] out_ep_data_avail_j = 0;
|
||||
|
||||
// set when the endpoint buffer is unable to receive the out transfer
|
||||
reg nak_out_transfer = 0;
|
||||
|
||||
// data toggle state
|
||||
reg [NUM_OUT_EPS - 1:0] data_toggle = 0;
|
||||
|
||||
// latched on valid OUT/SETUP token
|
||||
reg [3:0] current_endp = 0;
|
||||
wire [1:0] current_ep_state = ep_state[current_endp];
|
||||
|
||||
// endpoint data buffer
|
||||
reg [7:0] out_data_buffer [(MAX_OUT_PACKET_SIZE * NUM_OUT_EPS) - 1:0];
|
||||
|
||||
// current get_addr when outputting a packet from the buffer
|
||||
reg [5:0] ep_get_addr [NUM_OUT_EPS - 1:0];
|
||||
reg [5:0] ep_get_addr_next [NUM_OUT_EPS - 1:0];
|
||||
|
||||
|
||||
// endpoint put_addrs when inputting a packet into the buffer
|
||||
reg [5:0] ep_put_addr [NUM_OUT_EPS - 1:0];
|
||||
|
||||
// total buffer put addr, uses endpoint number and that endpoints current
|
||||
// put address
|
||||
wire [8:0] buffer_put_addr = {current_endp[3:0], ep_put_addr[current_endp][4:0]};
|
||||
wire [8:0] buffer_get_addr = {out_ep_num[3:0], ep_get_addr[out_ep_num][4:0]};
|
||||
|
||||
wire token_received =
|
||||
rx_pkt_end &&
|
||||
rx_pkt_valid &&
|
||||
rx_pid[1:0] == 2'b01 &&
|
||||
rx_addr == dev_addr &&
|
||||
rx_endp < NUM_OUT_EPS;
|
||||
|
||||
wire out_token_received =
|
||||
token_received &&
|
||||
rx_pid[3:2] == 2'b00;
|
||||
|
||||
wire setup_token_received =
|
||||
token_received &&
|
||||
rx_pid[3:2] == 2'b11;
|
||||
|
||||
wire invalid_packet_received =
|
||||
rx_pkt_end &&
|
||||
!rx_pkt_valid;
|
||||
|
||||
wire data_packet_received =
|
||||
rx_pkt_end &&
|
||||
rx_pkt_valid &&
|
||||
rx_pid[2:0] == 3'b011;
|
||||
|
||||
wire non_data_packet_received =
|
||||
rx_pkt_end &&
|
||||
rx_pkt_valid &&
|
||||
rx_pid[2:0] != 3'b011;
|
||||
|
||||
//reg last_data_toggle = 0;
|
||||
|
||||
wire bad_data_toggle =
|
||||
data_packet_received &&
|
||||
rx_pid[3] != data_toggle[rx_endp];
|
||||
|
||||
//last_data_toggle == data_toggle[current_endp];
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// endpoint state machine
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
genvar ep_num;
|
||||
generate
|
||||
for (ep_num = 0; ep_num < NUM_OUT_EPS; ep_num = ep_num + 1) begin
|
||||
always @* begin
|
||||
|
||||
ep_state_next[ep_num] <= ep_state[ep_num];
|
||||
|
||||
if (out_ep_stall[ep_num]) begin
|
||||
ep_state_next[ep_num] <= STALL;
|
||||
|
||||
end else begin
|
||||
case (ep_state[ep_num])
|
||||
READY_FOR_PKT : begin
|
||||
if (out_xfr_start && rx_endp == ep_num) begin
|
||||
ep_state_next[ep_num] <= PUTTING_PKT;
|
||||
|
||||
end else begin
|
||||
ep_state_next[ep_num] <= READY_FOR_PKT;
|
||||
end
|
||||
end
|
||||
|
||||
PUTTING_PKT : begin
|
||||
if (new_pkt_end && current_endp == ep_num) begin
|
||||
ep_state_next[ep_num] <= GETTING_PKT;
|
||||
|
||||
end else if (rollback_data && current_endp == ep_num) begin
|
||||
ep_state_next[ep_num] <= READY_FOR_PKT;
|
||||
|
||||
end else begin
|
||||
ep_state_next[ep_num] <= PUTTING_PKT;
|
||||
end
|
||||
end
|
||||
|
||||
GETTING_PKT : begin
|
||||
|
||||
if (ep_get_addr[ep_num][5:0] >= (ep_put_addr[ep_num][5:0] - 6'H2)) begin
|
||||
ep_state_next[ep_num] <= READY_FOR_PKT;
|
||||
|
||||
end else begin
|
||||
ep_state_next[ep_num] <= GETTING_PKT;
|
||||
end
|
||||
end
|
||||
|
||||
STALL : begin
|
||||
if (setup_token_received && rx_endp == ep_num) begin
|
||||
ep_state_next[ep_num] <= READY_FOR_PKT;
|
||||
|
||||
end else begin
|
||||
ep_state_next[ep_num] <= STALL;
|
||||
end
|
||||
end
|
||||
|
||||
default begin
|
||||
ep_state_next[ep_num] <= READY_FOR_PKT;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// Determine the next get_address (init, inc, maintain)
|
||||
if (ep_state_next[ep_num][1:0] == READY_FOR_PKT) begin
|
||||
ep_get_addr_next[ep_num][5:0] <= 0;
|
||||
end else if (ep_state_next[ep_num][1:0] == GETTING_PKT && out_ep_data_get[ep_num]) begin
|
||||
ep_get_addr_next[ep_num][5:0] <= ep_get_addr[ep_num][5:0] + 6'H1;
|
||||
end else begin
|
||||
ep_get_addr_next[ep_num][5:0] <= ep_get_addr[ep_num][5:0];
|
||||
end
|
||||
|
||||
end // end of the always @*
|
||||
|
||||
// Advance the state to the next one.
|
||||
always @(posedge clk) begin
|
||||
if (reset || reset_ep[ep_num]) begin
|
||||
ep_state[ep_num] <= READY_FOR_PKT;
|
||||
end else begin
|
||||
ep_state[ep_num] <= ep_state_next[ep_num];
|
||||
end
|
||||
|
||||
ep_get_addr[ep_num][5:0] <= ep_get_addr_next[ep_num][5:0];
|
||||
end
|
||||
|
||||
|
||||
assign out_ep_data_avail[ep_num] =
|
||||
(ep_get_addr[ep_num][5:0] < (ep_put_addr[ep_num][5:0] - 6'H2)) &&
|
||||
(ep_state[ep_num][1:0] == GETTING_PKT);
|
||||
|
||||
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
integer i;
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
out_ep_setup <= 0;
|
||||
|
||||
end else begin
|
||||
if (setup_token_received) begin
|
||||
out_ep_setup[rx_endp] <= 1;
|
||||
end else if (out_token_received) begin
|
||||
out_ep_setup[rx_endp] <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
for (i = 0; i < NUM_OUT_EPS; i = i + 1) begin
|
||||
if (reset_ep[i]) begin
|
||||
out_ep_setup[i] <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) out_ep_data <= out_data_buffer[buffer_get_addr][7:0];
|
||||
// use the bus grant line to determine the out_ep_num (where the data is)
|
||||
integer ep_num_decoder;
|
||||
always @* begin
|
||||
out_ep_num <= 0;
|
||||
|
||||
for (ep_num_decoder = 0; ep_num_decoder < NUM_OUT_EPS; ep_num_decoder = ep_num_decoder + 1) begin
|
||||
if (out_ep_grant[ep_num_decoder]) begin
|
||||
out_ep_num <= ep_num_decoder;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// out transfer state machine
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
always @* begin
|
||||
out_ep_acked <= 0;
|
||||
out_xfr_start <= 0;
|
||||
out_xfr_state_next <= out_xfr_state;
|
||||
tx_pkt_start <= 0;
|
||||
tx_pid <= 0;
|
||||
new_pkt_end <= 0;
|
||||
rollback_data <= 0;
|
||||
|
||||
case (out_xfr_state)
|
||||
IDLE : begin
|
||||
if (out_token_received || setup_token_received) begin
|
||||
out_xfr_state_next <= RCVD_OUT;
|
||||
out_xfr_start <= 1;
|
||||
|
||||
end else begin
|
||||
out_xfr_state_next <= IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
RCVD_OUT : begin
|
||||
if (rx_pkt_start) begin
|
||||
out_xfr_state_next <= RCVD_DATA_START;
|
||||
|
||||
end else begin
|
||||
out_xfr_state_next <= RCVD_OUT;
|
||||
end
|
||||
end
|
||||
|
||||
RCVD_DATA_START : begin
|
||||
if (bad_data_toggle) begin
|
||||
out_xfr_state_next <= IDLE;
|
||||
rollback_data <= 1;
|
||||
tx_pkt_start <= 1;
|
||||
tx_pid <= 4'b0010; // ACK
|
||||
|
||||
end else if (invalid_packet_received || non_data_packet_received) begin
|
||||
out_xfr_state_next <= IDLE;
|
||||
rollback_data <= 1;
|
||||
|
||||
end else if (data_packet_received) begin
|
||||
out_xfr_state_next <= RCVD_DATA_END;
|
||||
|
||||
end else begin
|
||||
out_xfr_state_next <= RCVD_DATA_START;
|
||||
end
|
||||
end
|
||||
|
||||
RCVD_DATA_END : begin
|
||||
out_xfr_state_next <= IDLE;
|
||||
tx_pkt_start <= 1;
|
||||
|
||||
if (ep_state[current_endp] == STALL) begin
|
||||
tx_pid <= 4'b1110; // STALL
|
||||
|
||||
end else if (nak_out_transfer) begin
|
||||
tx_pid <= 4'b1010; // NAK
|
||||
rollback_data <= 1;
|
||||
|
||||
end else begin
|
||||
tx_pid <= 4'b0010; // ACK
|
||||
new_pkt_end <= 1;
|
||||
out_ep_acked[current_endp] <= 1;
|
||||
|
||||
//end else begin
|
||||
// tx_pid <= 4'b0010; // ACK
|
||||
// rollback_data <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
default begin
|
||||
out_xfr_state_next <= IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
wire current_ep_busy =
|
||||
(ep_state[current_endp] == GETTING_PKT) ||
|
||||
(ep_state[current_endp] == READY_FOR_PKT);
|
||||
|
||||
integer j;
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
out_xfr_state <= IDLE;
|
||||
end else begin
|
||||
out_xfr_state <= out_xfr_state_next;
|
||||
|
||||
if (out_xfr_start) begin
|
||||
current_endp <= rx_endp;
|
||||
//last_data_toggle <= setup_token_received ? 0 : data_toggle[rx_endp];
|
||||
end
|
||||
|
||||
if (new_pkt_end) begin
|
||||
data_toggle[current_endp] <= !data_toggle[current_endp];
|
||||
end
|
||||
|
||||
if (setup_token_received) begin
|
||||
data_toggle[rx_endp] <= 0;
|
||||
end
|
||||
|
||||
case (out_xfr_state)
|
||||
IDLE : begin
|
||||
end
|
||||
|
||||
RCVD_OUT : begin
|
||||
if (current_ep_busy) begin
|
||||
nak_out_transfer <= 1;
|
||||
end else begin
|
||||
nak_out_transfer <= 0;
|
||||
ep_put_addr[current_endp][5:0] <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
RCVD_DATA_START : begin
|
||||
if (!nak_out_transfer && rx_data_put && !ep_put_addr[current_endp][5]) begin
|
||||
out_data_buffer[buffer_put_addr][7:0] <= rx_data;
|
||||
end
|
||||
|
||||
if (!nak_out_transfer && rx_data_put) begin
|
||||
ep_put_addr[current_endp][5:0] <= ep_put_addr[current_endp][5:0] + 6'H1;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
RCVD_DATA_END : begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
for (j = 0; j < NUM_OUT_EPS; j = j + 1) begin
|
||||
if (reset || reset_ep[j]) begin
|
||||
data_toggle[j] <= 0;
|
||||
ep_put_addr[j][5:0] <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
239
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_pe.v
Normal file
239
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_pe.v
Normal file
@ -0,0 +1,239 @@
|
||||
module usb_fs_pe #(
|
||||
parameter [4:0] NUM_OUT_EPS = 1,
|
||||
parameter [4:0] NUM_IN_EPS = 1
|
||||
) (
|
||||
input clk,
|
||||
input [6:0] dev_addr,
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// USB Endpoint Interface
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////
|
||||
// global endpoint interface
|
||||
////////////////////
|
||||
input reset,
|
||||
|
||||
|
||||
////////////////////
|
||||
// out endpoint interfaces
|
||||
////////////////////
|
||||
input [NUM_OUT_EPS-1:0] out_ep_req,
|
||||
output [NUM_OUT_EPS-1:0] out_ep_grant,
|
||||
output [NUM_OUT_EPS-1:0] out_ep_data_avail,
|
||||
output [NUM_OUT_EPS-1:0] out_ep_setup,
|
||||
input [NUM_OUT_EPS-1:0] out_ep_data_get,
|
||||
output [7:0] out_ep_data,
|
||||
input [NUM_OUT_EPS-1:0] out_ep_stall,
|
||||
output [NUM_OUT_EPS-1:0] out_ep_acked,
|
||||
|
||||
|
||||
////////////////////
|
||||
// in endpoint interfaces
|
||||
////////////////////
|
||||
input [NUM_IN_EPS-1:0] in_ep_req,
|
||||
output [NUM_IN_EPS-1:0] in_ep_grant,
|
||||
output [NUM_IN_EPS-1:0] in_ep_data_free,
|
||||
input [NUM_IN_EPS-1:0] in_ep_data_put,
|
||||
input [(NUM_IN_EPS*8)-1:0] in_ep_data,
|
||||
input [NUM_IN_EPS-1:0] in_ep_data_done,
|
||||
input [NUM_IN_EPS-1:0] in_ep_stall,
|
||||
output [NUM_IN_EPS-1:0] in_ep_acked,
|
||||
|
||||
|
||||
////////////////////
|
||||
// sof interface
|
||||
////////////////////
|
||||
output sof_valid,
|
||||
output [10:0] frame_index,
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// USB TX/RX Interface
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
output usb_p_tx,
|
||||
output usb_n_tx,
|
||||
|
||||
input usb_p_rx,
|
||||
input usb_n_rx,
|
||||
|
||||
output usb_tx_en,
|
||||
|
||||
output [7:0] debug
|
||||
);
|
||||
// in pe interface
|
||||
wire [7:0] arb_in_ep_data;
|
||||
|
||||
// rx interface
|
||||
wire bit_strobe;
|
||||
wire rx_pkt_start;
|
||||
wire rx_pkt_end;
|
||||
wire [3:0] rx_pid;
|
||||
wire [6:0] rx_addr;
|
||||
wire [3:0] rx_endp;
|
||||
wire [10:0] rx_frame_num;
|
||||
wire rx_data_put;
|
||||
wire [7:0] rx_data;
|
||||
wire rx_pkt_valid;
|
||||
|
||||
// tx mux
|
||||
wire in_tx_pkt_start;
|
||||
wire [3:0] in_tx_pid;
|
||||
wire out_tx_pkt_start;
|
||||
wire [3:0] out_tx_pid;
|
||||
|
||||
// tx interface
|
||||
wire tx_pkt_start;
|
||||
wire tx_pkt_end;
|
||||
wire [3:0] tx_pid;
|
||||
wire tx_data_avail;
|
||||
wire tx_data_get;
|
||||
wire [7:0] tx_data;
|
||||
|
||||
// sof interface
|
||||
assign sof_valid = rx_pkt_end && rx_pkt_valid && rx_pid == 4'b0101;
|
||||
assign frame_index = rx_frame_num;
|
||||
|
||||
|
||||
usb_fs_in_arb #(
|
||||
.NUM_IN_EPS(NUM_IN_EPS)
|
||||
) usb_fs_in_arb_inst (
|
||||
// endpoint interface
|
||||
.in_ep_req(in_ep_req),
|
||||
.in_ep_grant(in_ep_grant),
|
||||
.in_ep_data(in_ep_data),
|
||||
|
||||
// protocol engine interface
|
||||
.arb_in_ep_data(arb_in_ep_data)
|
||||
);
|
||||
|
||||
usb_fs_out_arb #(
|
||||
.NUM_OUT_EPS(NUM_OUT_EPS)
|
||||
) usb_fs_out_arb_inst (
|
||||
// endpoint interface
|
||||
.out_ep_req(out_ep_req),
|
||||
.out_ep_grant(out_ep_grant)
|
||||
);
|
||||
|
||||
usb_fs_in_pe #(
|
||||
.NUM_IN_EPS(NUM_IN_EPS)
|
||||
) usb_fs_in_pe_inst (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.reset_ep({NUM_IN_EPS{1'b0}}),
|
||||
.dev_addr(dev_addr),
|
||||
|
||||
// endpoint interface
|
||||
.in_ep_data_free(in_ep_data_free),
|
||||
.in_ep_data_put(in_ep_data_put),
|
||||
.in_ep_data(arb_in_ep_data),
|
||||
.in_ep_data_done(in_ep_data_done),
|
||||
.in_ep_stall(in_ep_stall),
|
||||
.in_ep_acked(in_ep_acked),
|
||||
|
||||
// rx path
|
||||
.rx_pkt_start(rx_pkt_start),
|
||||
.rx_pkt_end(rx_pkt_end),
|
||||
.rx_pkt_valid(rx_pkt_valid),
|
||||
.rx_pid(rx_pid),
|
||||
.rx_addr(rx_addr),
|
||||
.rx_endp(rx_endp),
|
||||
.rx_frame_num(rx_frame_num),
|
||||
|
||||
// tx path
|
||||
.tx_pkt_start(in_tx_pkt_start),
|
||||
.tx_pkt_end(tx_pkt_end),
|
||||
.tx_pid(in_tx_pid),
|
||||
.tx_data_avail(tx_data_avail),
|
||||
.tx_data_get(tx_data_get),
|
||||
.tx_data(tx_data),
|
||||
|
||||
.debug(debug)
|
||||
);
|
||||
|
||||
usb_fs_out_pe #(
|
||||
.NUM_OUT_EPS(NUM_OUT_EPS)
|
||||
) usb_fs_out_pe_inst (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.reset_ep({NUM_OUT_EPS{1'b0}}),
|
||||
.dev_addr(dev_addr),
|
||||
|
||||
// endpoint interface
|
||||
.out_ep_data_avail(out_ep_data_avail),
|
||||
.out_ep_data_get(out_ep_data_get),
|
||||
.out_ep_data(out_ep_data),
|
||||
.out_ep_setup(out_ep_setup),
|
||||
.out_ep_stall(out_ep_stall),
|
||||
.out_ep_acked(out_ep_acked),
|
||||
.out_ep_grant(out_ep_grant),
|
||||
|
||||
// rx path
|
||||
.rx_pkt_start(rx_pkt_start),
|
||||
.rx_pkt_end(rx_pkt_end),
|
||||
.rx_pkt_valid(rx_pkt_valid),
|
||||
.rx_pid(rx_pid),
|
||||
.rx_addr(rx_addr),
|
||||
.rx_endp(rx_endp),
|
||||
.rx_frame_num(rx_frame_num),
|
||||
.rx_data_put(rx_data_put),
|
||||
.rx_data(rx_data),
|
||||
|
||||
// tx path
|
||||
.tx_pkt_start(out_tx_pkt_start),
|
||||
.tx_pkt_end(tx_pkt_end),
|
||||
.tx_pid(out_tx_pid)
|
||||
);
|
||||
|
||||
usb_fs_rx usb_fs_rx_inst (
|
||||
.clk_48mhz(clk),
|
||||
.reset(reset),
|
||||
.dp(usb_p_rx),
|
||||
.dn(usb_n_rx),
|
||||
.bit_strobe(bit_strobe),
|
||||
.pkt_start(rx_pkt_start),
|
||||
.pkt_end(rx_pkt_end),
|
||||
.pid(rx_pid),
|
||||
.addr(rx_addr),
|
||||
.endp(rx_endp),
|
||||
.frame_num(rx_frame_num),
|
||||
.rx_data_put(rx_data_put),
|
||||
.rx_data(rx_data),
|
||||
.valid_packet(rx_pkt_valid)
|
||||
);
|
||||
|
||||
usb_fs_tx_mux usb_fs_tx_mux_inst (
|
||||
// interface to IN Protocol Engine
|
||||
.in_tx_pkt_start(in_tx_pkt_start),
|
||||
.in_tx_pid(in_tx_pid),
|
||||
|
||||
// interface to OUT Protocol Engine
|
||||
.out_tx_pkt_start(out_tx_pkt_start),
|
||||
.out_tx_pid(out_tx_pid),
|
||||
|
||||
// interface to tx module
|
||||
.tx_pkt_start(tx_pkt_start),
|
||||
.tx_pid(tx_pid)
|
||||
);
|
||||
|
||||
usb_fs_tx usb_fs_tx_inst (
|
||||
.clk_48mhz(clk),
|
||||
.reset(reset),
|
||||
.bit_strobe(bit_strobe),
|
||||
.oe(usb_tx_en),
|
||||
.dp(usb_p_tx),
|
||||
.dn(usb_n_tx),
|
||||
.pkt_start(tx_pkt_start),
|
||||
.pkt_end(tx_pkt_end),
|
||||
.pid(tx_pid),
|
||||
.tx_data_avail(tx_data_avail),
|
||||
.tx_data_get(tx_data_get),
|
||||
.tx_data(tx_data)
|
||||
);
|
||||
endmodule
|
366
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_rx.v
Normal file
366
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_rx.v
Normal file
@ -0,0 +1,366 @@
|
||||
module usb_fs_rx (
|
||||
// A 48MHz clock is required to recover the clock from the incoming data.
|
||||
input clk_48mhz,
|
||||
input reset,
|
||||
|
||||
// USB data+ and data- lines.
|
||||
input dp,
|
||||
input dn,
|
||||
|
||||
// pulse on every bit transition.
|
||||
output bit_strobe,
|
||||
|
||||
// Pulse on beginning of new packet.
|
||||
output pkt_start,
|
||||
|
||||
// Pulse on end of current packet.
|
||||
output pkt_end,
|
||||
|
||||
// Most recent packet decoded.
|
||||
output [3:0] pid,
|
||||
output reg [6:0] addr = 0,
|
||||
output reg [3:0] endp = 0,
|
||||
output reg [10:0] frame_num = 0,
|
||||
|
||||
// Pulse on valid data on rx_data.
|
||||
output rx_data_put,
|
||||
output [7:0] rx_data,
|
||||
|
||||
// Most recent packet passes PID and CRC checks
|
||||
output valid_packet
|
||||
);
|
||||
wire clk = clk_48mhz;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////
|
||||
//////// usb receive path
|
||||
////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// double flop for metastability
|
||||
/*
|
||||
all asynchronous inputs into the RTL need to be double-flopped to protect
|
||||
against metastable scenarios. if the RTL clock samples an asynchronous signal
|
||||
at the same time the signal is transitioning the result is undefined. flopping
|
||||
the signal twice ensures it will be either 1 or 0 and nothing in between.
|
||||
*/
|
||||
|
||||
reg [3:0] dpair_q = 0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
dpair_q[3:0] <= {dpair_q[1:0], dp, dn};
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// line state recovery state machine
|
||||
/*
|
||||
the recieve path doesn't currently use a differential reciever. because of
|
||||
this there is a chance that one of the differential pairs will appear to have
|
||||
changed to the new state while the other is still in the old state. the
|
||||
following state machine detects transitions and waits an extra sampling clock
|
||||
before decoding the state on the differential pair. this transition period
|
||||
will only ever last for one clock as long as there is no noise on the line.
|
||||
if there is enough noise on the line then the data may be corrupted and the
|
||||
packet will fail the data integrity checks.
|
||||
*/
|
||||
|
||||
reg [2:0] line_state = 0;
|
||||
localparam DT = 3'b100;
|
||||
localparam DJ = 3'b010;
|
||||
localparam DK = 3'b001;
|
||||
localparam SE0 = 3'b000;
|
||||
localparam SE1 = 3'b011;
|
||||
|
||||
wire [1:0] dpair = dpair_q[3:2];
|
||||
|
||||
always @(posedge clk) begin
|
||||
case (line_state)
|
||||
// if we are in a transition state, then we can sample the pair and
|
||||
// move to the next corresponding line state
|
||||
DT : begin
|
||||
case (dpair)
|
||||
2'b10 : line_state <= DJ;
|
||||
2'b01 : line_state <= DK;
|
||||
2'b00 : line_state <= SE0;
|
||||
2'b11 : line_state <= SE1;
|
||||
endcase
|
||||
end
|
||||
|
||||
// if we are in a valid line state and the value of the pair changes,
|
||||
// then we need to move to the transition state
|
||||
DJ : if (dpair != 2'b10) line_state <= DT;
|
||||
DK : if (dpair != 2'b01) line_state <= DT;
|
||||
SE0 : if (dpair != 2'b00) line_state <= DT;
|
||||
SE1 : if (dpair != 2'b11) line_state <= DT;
|
||||
|
||||
// if we are in an invalid state we should move to the transition state
|
||||
default : line_state <= DT;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// clock recovery
|
||||
/*
|
||||
the DT state from the line state recovery state machine is used to align to
|
||||
transmit clock. the line state is sampled in the middle of the bit time.
|
||||
|
||||
example of signal relationships
|
||||
-------------------------------
|
||||
line_state DT DJ DJ DJ DT DK DK DK DK DK DK DT DJ DJ DJ
|
||||
line_state_valid ________----____________----____________----________----____
|
||||
bit_phase 0 0 1 2 3 0 1 2 3 0 1 2 0 1 2
|
||||
*/
|
||||
|
||||
reg [1:0] bit_phase = 0;
|
||||
|
||||
wire line_state_valid = (bit_phase == 1);
|
||||
assign bit_strobe = (bit_phase == 2);
|
||||
|
||||
always @(posedge clk) begin
|
||||
// keep track of phase within each bit
|
||||
if (line_state == DT) begin
|
||||
bit_phase <= 0;
|
||||
|
||||
end else begin
|
||||
bit_phase <= bit_phase + 1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// packet detection
|
||||
/*
|
||||
usb uses a sync to denote the beginning of a packet and two single-ended-0 to
|
||||
denote the end of a packet. this state machine recognizes the beginning and
|
||||
end of packets for subsequent layers to process.
|
||||
*/
|
||||
reg [5:0] line_history = 0;
|
||||
reg packet_valid = 0;
|
||||
reg next_packet_valid;
|
||||
wire packet_start = next_packet_valid && !packet_valid;
|
||||
wire packet_end = !next_packet_valid && packet_valid;
|
||||
|
||||
always @* begin
|
||||
if (line_state_valid) begin
|
||||
// check for packet start: KJKJKK
|
||||
if (!packet_valid && line_history[5:0] == 6'b100101) begin
|
||||
next_packet_valid <= 1;
|
||||
end
|
||||
|
||||
// check for packet end: SE0 SE0
|
||||
else if (packet_valid && line_history[3:0] == 4'b0000) begin
|
||||
next_packet_valid <= 0;
|
||||
|
||||
end else begin
|
||||
next_packet_valid <= packet_valid;
|
||||
end
|
||||
end else begin
|
||||
next_packet_valid <= packet_valid;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
line_history <= 6'b101010;
|
||||
packet_valid <= 0;
|
||||
end else begin
|
||||
// keep a history of the last two states on the line
|
||||
if (line_state_valid) begin
|
||||
line_history[5:0] <= {line_history[3:0], line_state[1:0]};
|
||||
end
|
||||
end
|
||||
packet_valid <= next_packet_valid;
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NRZI decode
|
||||
/*
|
||||
in order to ensure there are enough bit transitions for a receiver to recover
|
||||
the clock usb uses NRZI encoding.
|
||||
|
||||
https://en.wikipedia.org/wiki/Non-return-to-zero
|
||||
*/
|
||||
reg dvalid_raw;
|
||||
reg din;
|
||||
|
||||
always @* begin
|
||||
case (line_history[3:0])
|
||||
4'b0101 : din <= 1;
|
||||
4'b0110 : din <= 0;
|
||||
4'b1001 : din <= 0;
|
||||
4'b1010 : din <= 1;
|
||||
default : din <= 0;
|
||||
endcase
|
||||
|
||||
if (packet_valid && line_state_valid) begin
|
||||
case (line_history[3:0])
|
||||
4'b0101 : dvalid_raw <= 1;
|
||||
4'b0110 : dvalid_raw <= 1;
|
||||
4'b1001 : dvalid_raw <= 1;
|
||||
4'b1010 : dvalid_raw <= 1;
|
||||
default : dvalid_raw <= 0;
|
||||
endcase
|
||||
end else begin
|
||||
dvalid_raw <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
reg [5:0] bitstuff_history = 0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset || packet_end) begin
|
||||
bitstuff_history <= 6'b000000;
|
||||
end else begin
|
||||
if (dvalid_raw) begin
|
||||
bitstuff_history <= {bitstuff_history[4:0], din};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wire dvalid = dvalid_raw && !(bitstuff_history == 6'b111111);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// save and check pid
|
||||
/*
|
||||
shift in the entire 8-bit pid with an additional 9th bit used as a sentinal.
|
||||
*/
|
||||
|
||||
reg [8:0] full_pid = 0;
|
||||
wire pid_valid = full_pid[4:1] == ~full_pid[8:5];
|
||||
wire pid_complete = full_pid[0];
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (packet_start) begin
|
||||
full_pid <= 9'b100000000;
|
||||
end
|
||||
|
||||
if (dvalid && !pid_complete) begin
|
||||
full_pid <= {din, full_pid[8:1]};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// check crc5
|
||||
reg [4:0] crc5 = 0;
|
||||
wire crc5_valid = crc5 == 5'b01100;
|
||||
wire crc5_invert = din ^ crc5[4];
|
||||
always @(posedge clk) begin
|
||||
if (packet_start) begin
|
||||
crc5 <= 5'b11111;
|
||||
end
|
||||
|
||||
if (dvalid && pid_complete) begin
|
||||
crc5[4] <= crc5[3];
|
||||
crc5[3] <= crc5[2];
|
||||
crc5[2] <= crc5[1] ^ crc5_invert;
|
||||
crc5[1] <= crc5[0];
|
||||
crc5[0] <= crc5_invert;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// check crc16
|
||||
reg [15:0] crc16 = 0;
|
||||
wire crc16_valid = crc16 == 16'b1000000000001101;
|
||||
wire crc16_invert = din ^ crc16[15];
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (packet_start) begin
|
||||
crc16 <= 16'b1111111111111111;
|
||||
end
|
||||
|
||||
if (dvalid && pid_complete) begin
|
||||
crc16[15] <= crc16[14] ^ crc16_invert;
|
||||
crc16[14] <= crc16[13];
|
||||
crc16[13] <= crc16[12];
|
||||
crc16[12] <= crc16[11];
|
||||
crc16[11] <= crc16[10];
|
||||
crc16[10] <= crc16[9];
|
||||
crc16[9] <= crc16[8];
|
||||
crc16[8] <= crc16[7];
|
||||
crc16[7] <= crc16[6];
|
||||
crc16[6] <= crc16[5];
|
||||
crc16[5] <= crc16[4];
|
||||
crc16[4] <= crc16[3];
|
||||
crc16[3] <= crc16[2];
|
||||
crc16[2] <= crc16[1] ^ crc16_invert;
|
||||
crc16[1] <= crc16[0];
|
||||
crc16[0] <= crc16_invert;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// output control signals
|
||||
wire pkt_is_token = full_pid[2:1] == 2'b01;
|
||||
wire pkt_is_data = full_pid[2:1] == 2'b11;
|
||||
wire pkt_is_handshake = full_pid[2:1] == 2'b10;
|
||||
|
||||
|
||||
// TODO: need to check for data packet babble
|
||||
// TODO: do i need to check for bitstuff error?
|
||||
assign valid_packet = pid_valid && (
|
||||
(pkt_is_handshake) ||
|
||||
(pkt_is_data && crc16_valid) ||
|
||||
(pkt_is_token && crc5_valid)
|
||||
);
|
||||
|
||||
|
||||
reg [11:0] token_payload = 0;
|
||||
wire token_payload_done = token_payload[0];
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (packet_start) begin
|
||||
token_payload <= 12'b100000000000;
|
||||
end
|
||||
|
||||
if (dvalid && pid_complete && pkt_is_token && !token_payload_done) begin
|
||||
token_payload <= {din, token_payload[11:1]};
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (token_payload_done && pkt_is_token) begin
|
||||
addr <= token_payload[7:1];
|
||||
endp <= token_payload[11:8];
|
||||
frame_num <= token_payload[11:1];
|
||||
end
|
||||
end
|
||||
|
||||
assign pkt_start = packet_start;
|
||||
assign pkt_end = packet_end;
|
||||
assign pid = full_pid[4:1];
|
||||
//assign addr = token_payload[7:1];
|
||||
//assign endp = token_payload[11:8];
|
||||
//assign frame_num = token_payload[11:1];
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// deserialize and output data
|
||||
//assign rx_data_put = dvalid && pid_complete && pkt_is_data;
|
||||
reg [8:0] rx_data_buffer = 0;
|
||||
wire rx_data_buffer_full = rx_data_buffer[0];
|
||||
assign rx_data_put = rx_data_buffer_full;
|
||||
assign rx_data = rx_data_buffer[8:1];
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (packet_start || rx_data_buffer_full) begin
|
||||
rx_data_buffer <= 9'b100000000;
|
||||
end
|
||||
|
||||
if (dvalid && pid_complete && pkt_is_data) begin
|
||||
rx_data_buffer <= {din, rx_data_buffer[8:1]};
|
||||
end
|
||||
end
|
||||
|
||||
endmodule // usb_fs_rx
|
243
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_tx.v
Normal file
243
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_tx.v
Normal file
@ -0,0 +1,243 @@
|
||||
module usb_fs_tx (
|
||||
// A 48MHz clock is required to receive USB data at 12MHz
|
||||
// it's simpler to juse use 48MHz everywhere
|
||||
input clk_48mhz,
|
||||
input reset,
|
||||
|
||||
// bit strobe from rx to align with senders clock
|
||||
input bit_strobe,
|
||||
|
||||
// output enable to take ownership of bus and data out
|
||||
output reg oe = 0,
|
||||
output reg dp = 0,
|
||||
output reg dn = 0,
|
||||
|
||||
// pulse to initiate new packet transmission
|
||||
input pkt_start,
|
||||
output pkt_end,
|
||||
|
||||
// pid to send
|
||||
input [3:0] pid,
|
||||
|
||||
// tx logic pulls data until there is nothing available
|
||||
input tx_data_avail,
|
||||
output reg tx_data_get = 0,
|
||||
input [7:0] tx_data
|
||||
);
|
||||
wire clk = clk_48mhz;
|
||||
|
||||
// save packet parameters at pkt_start
|
||||
reg [3:0] pidq = 0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (pkt_start) begin
|
||||
pidq <= pid;
|
||||
end
|
||||
end
|
||||
|
||||
reg [7:0] data_shift_reg = 0;
|
||||
reg [7:0] oe_shift_reg = 0;
|
||||
reg [7:0] se0_shift_reg = 0;
|
||||
|
||||
|
||||
wire serial_tx_data = data_shift_reg[0];
|
||||
wire serial_tx_oe = oe_shift_reg[0];
|
||||
wire serial_tx_se0 = se0_shift_reg[0];
|
||||
|
||||
|
||||
// serialize sync, pid, data payload, and crc16
|
||||
reg byte_strobe = 0;
|
||||
reg [2:0] bit_count = 0;
|
||||
|
||||
reg [4:0] bit_history_q = 0;
|
||||
wire [5:0] bit_history = {serial_tx_data, bit_history_q};
|
||||
wire bitstuff = bit_history == 6'b111111;
|
||||
reg bitstuff_q = 0;
|
||||
reg bitstuff_qq = 0;
|
||||
reg bitstuff_qqq = 0;
|
||||
reg bitstuff_qqqq = 0;
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
bitstuff_q <= bitstuff;
|
||||
bitstuff_qq <= bitstuff_q;
|
||||
bitstuff_qqq <= bitstuff_qq;
|
||||
bitstuff_qqqq <= bitstuff_qqq;
|
||||
end
|
||||
|
||||
assign pkt_end = bit_strobe && se0_shift_reg[1:0] == 2'b01;
|
||||
|
||||
reg data_payload = 0;
|
||||
|
||||
reg [31:0] pkt_state = 0;
|
||||
localparam IDLE = 0;
|
||||
localparam SYNC = 1;
|
||||
localparam PID = 2;
|
||||
localparam DATA_OR_CRC16_0 = 3;
|
||||
localparam CRC16_1 = 4;
|
||||
localparam EOP = 5;
|
||||
|
||||
reg [15:0] crc16 = 0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
case (pkt_state)
|
||||
IDLE : begin
|
||||
if (pkt_start) begin
|
||||
pkt_state <= SYNC;
|
||||
end
|
||||
end
|
||||
|
||||
SYNC : begin
|
||||
if (byte_strobe) begin
|
||||
pkt_state <= PID;
|
||||
data_shift_reg <= 8'b10000000;
|
||||
oe_shift_reg <= 8'b11111111;
|
||||
se0_shift_reg <= 8'b00000000;
|
||||
end
|
||||
end
|
||||
|
||||
PID : begin
|
||||
if (byte_strobe) begin
|
||||
if (pidq[1:0] == 2'b11) begin
|
||||
pkt_state <= DATA_OR_CRC16_0;
|
||||
end else begin
|
||||
pkt_state <= EOP;
|
||||
end
|
||||
|
||||
data_shift_reg <= {~pidq, pidq};
|
||||
oe_shift_reg <= 8'b11111111;
|
||||
se0_shift_reg <= 8'b00000000;
|
||||
end
|
||||
end
|
||||
|
||||
DATA_OR_CRC16_0 : begin
|
||||
if (byte_strobe) begin
|
||||
if (tx_data_avail) begin
|
||||
pkt_state <= DATA_OR_CRC16_0;
|
||||
data_payload <= 1;
|
||||
tx_data_get <= 1;
|
||||
data_shift_reg <= tx_data;
|
||||
oe_shift_reg <= 8'b11111111;
|
||||
se0_shift_reg <= 8'b00000000;
|
||||
end else begin
|
||||
pkt_state <= CRC16_1;
|
||||
data_payload <= 0;
|
||||
tx_data_get <= 0;
|
||||
data_shift_reg <= ~{crc16[8], crc16[9], crc16[10], crc16[11], crc16[12], crc16[13], crc16[14], crc16[15]};
|
||||
oe_shift_reg <= 8'b11111111;
|
||||
se0_shift_reg <= 8'b00000000;
|
||||
end
|
||||
end else begin
|
||||
tx_data_get <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
CRC16_1 : begin
|
||||
if (byte_strobe) begin
|
||||
pkt_state <= EOP;
|
||||
data_shift_reg <= ~{crc16[0], crc16[1], crc16[2], crc16[3], crc16[4], crc16[5], crc16[6], crc16[7]};
|
||||
oe_shift_reg <= 8'b11111111;
|
||||
se0_shift_reg <= 8'b00000000;
|
||||
end
|
||||
end
|
||||
|
||||
EOP : begin
|
||||
if (byte_strobe) begin
|
||||
pkt_state <= IDLE;
|
||||
oe_shift_reg <= 8'b00000111;
|
||||
se0_shift_reg <= 8'b00000111;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
if (bit_strobe && !bitstuff) begin
|
||||
byte_strobe <= (bit_count == 3'b000);
|
||||
end else begin
|
||||
byte_strobe <= 0;
|
||||
end
|
||||
|
||||
if (pkt_start) begin
|
||||
bit_count <= 1;
|
||||
bit_history_q <= 0;
|
||||
|
||||
end else if (bit_strobe) begin
|
||||
// bitstuff
|
||||
if (bitstuff /* && !serial_tx_se0*/) begin
|
||||
bit_history_q <= bit_history[5:1];
|
||||
data_shift_reg[0] <= 0;
|
||||
|
||||
// normal deserialize
|
||||
end else begin
|
||||
bit_count <= bit_count + 1;
|
||||
|
||||
data_shift_reg <= (data_shift_reg >> 1);
|
||||
oe_shift_reg <= (oe_shift_reg >> 1);
|
||||
se0_shift_reg <= (se0_shift_reg >> 1);
|
||||
|
||||
bit_history_q <= bit_history[5:1];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
// calculate crc16
|
||||
wire crc16_invert = serial_tx_data ^ crc16[15];
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (pkt_start) begin
|
||||
crc16 <= 16'b1111111111111111;
|
||||
end
|
||||
|
||||
if (bit_strobe && data_payload && !bitstuff_qqqq && !pkt_start) begin
|
||||
crc16[15] <= crc16[14] ^ crc16_invert;
|
||||
crc16[14] <= crc16[13];
|
||||
crc16[13] <= crc16[12];
|
||||
crc16[12] <= crc16[11];
|
||||
crc16[11] <= crc16[10];
|
||||
crc16[10] <= crc16[9];
|
||||
crc16[9] <= crc16[8];
|
||||
crc16[8] <= crc16[7];
|
||||
crc16[7] <= crc16[6];
|
||||
crc16[6] <= crc16[5];
|
||||
crc16[5] <= crc16[4];
|
||||
crc16[4] <= crc16[3];
|
||||
crc16[3] <= crc16[2];
|
||||
crc16[2] <= crc16[1] ^ crc16_invert;
|
||||
crc16[1] <= crc16[0];
|
||||
crc16[0] <= crc16_invert;
|
||||
end
|
||||
end
|
||||
|
||||
reg [2:0] dp_eop = 0;
|
||||
|
||||
|
||||
// nrzi and differential driving
|
||||
always @(posedge clk) begin
|
||||
if (pkt_start) begin
|
||||
// J
|
||||
dp <= 1;
|
||||
dn <= 0;
|
||||
|
||||
dp_eop <= 3'b100;
|
||||
|
||||
end else if (bit_strobe) begin
|
||||
oe <= serial_tx_oe;
|
||||
|
||||
if (serial_tx_se0) begin
|
||||
dp <= dp_eop[0];
|
||||
dn <= 0;
|
||||
|
||||
dp_eop <= dp_eop >> 1;
|
||||
|
||||
end else if (serial_tx_data) begin
|
||||
// value should stay the same, do nothing
|
||||
|
||||
end else begin
|
||||
dp <= !dp;
|
||||
dn <= !dn;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
16
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_tx_mux.v
Normal file
16
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_fs_tx_mux.v
Normal file
@ -0,0 +1,16 @@
|
||||
module usb_fs_tx_mux (
|
||||
// interface to IN Protocol Engine
|
||||
input in_tx_pkt_start,
|
||||
input [3:0] in_tx_pid,
|
||||
|
||||
// interface to OUT Protocol Engine
|
||||
input out_tx_pkt_start,
|
||||
input [3:0] out_tx_pid,
|
||||
|
||||
// interface to tx module
|
||||
output tx_pkt_start,
|
||||
output [3:0] tx_pid
|
||||
);
|
||||
assign tx_pkt_start = in_tx_pkt_start | out_tx_pkt_start;
|
||||
assign tx_pid = out_tx_pkt_start ? out_tx_pid : in_tx_pid;
|
||||
endmodule
|
31
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_reset_det.v
Normal file
31
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_reset_det.v
Normal file
@ -0,0 +1,31 @@
|
||||
// detects USB port reset signal from host
|
||||
module usb_reset_det (
|
||||
input clk,
|
||||
output reset,
|
||||
|
||||
input usb_p_rx,
|
||||
input usb_n_rx
|
||||
);
|
||||
// reset detection
|
||||
reg [16:0] reset_timer = 0;
|
||||
reg reset_i = 0;
|
||||
|
||||
|
||||
wire timer_expired = reset_timer > 16'd30000;
|
||||
always @(posedge clk) reset_i <= timer_expired;
|
||||
assign reset = reset_i;
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (usb_p_rx || usb_n_rx) begin
|
||||
reset_timer <= 0;
|
||||
end else begin
|
||||
// SE0 detected from host
|
||||
if (!timer_expired) begin
|
||||
// timer not expired yet, keep counting
|
||||
reset_timer <= reset_timer + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
473
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_serial_ctrl_ep.v
Normal file
473
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_serial_ctrl_ep.v
Normal file
@ -0,0 +1,473 @@
|
||||
module usb_serial_ctrl_ep #(
|
||||
parameter MAX_IN_PACKET_SIZE = 32,
|
||||
parameter MAX_OUT_PACKET_SIZE = 32
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
output [6:0] dev_addr,
|
||||
|
||||
////////////////////
|
||||
// out endpoint interface
|
||||
////////////////////
|
||||
output out_ep_req,
|
||||
input out_ep_grant,
|
||||
input out_ep_data_avail,
|
||||
input out_ep_setup,
|
||||
output out_ep_data_get,
|
||||
input [7:0] out_ep_data,
|
||||
output out_ep_stall,
|
||||
input out_ep_acked,
|
||||
|
||||
|
||||
////////////////////
|
||||
// in endpoint interface
|
||||
////////////////////
|
||||
output in_ep_req,
|
||||
input in_ep_grant,
|
||||
input in_ep_data_free,
|
||||
output in_ep_data_put,
|
||||
output reg [7:0] in_ep_data = 0,
|
||||
output in_ep_data_done,
|
||||
output reg in_ep_stall,
|
||||
input in_ep_acked
|
||||
);
|
||||
|
||||
|
||||
localparam IDLE = 0;
|
||||
localparam SETUP = 1;
|
||||
localparam DATA_IN = 2;
|
||||
localparam DATA_OUT = 3;
|
||||
localparam STATUS_IN = 4;
|
||||
localparam STATUS_OUT = 5;
|
||||
|
||||
reg [5:0] ctrl_xfr_state = IDLE;
|
||||
reg [5:0] ctrl_xfr_state_next;
|
||||
|
||||
|
||||
|
||||
reg setup_stage_end = 0;
|
||||
reg data_stage_end = 0;
|
||||
reg status_stage_end = 0;
|
||||
reg send_zero_length_data_pkt = 0;
|
||||
|
||||
|
||||
|
||||
// the default control endpoint gets assigned the device address
|
||||
reg [6:0] dev_addr_i = 0;
|
||||
assign dev_addr = dev_addr_i;
|
||||
|
||||
assign out_ep_req = out_ep_data_avail;
|
||||
assign out_ep_data_get = out_ep_data_avail;
|
||||
reg out_ep_data_valid = 0;
|
||||
always @(posedge clk) out_ep_data_valid <= out_ep_data_avail && out_ep_grant;
|
||||
|
||||
// need to record the setup data
|
||||
reg [3:0] setup_data_addr = 0;
|
||||
reg [9:0] raw_setup_data [7:0];
|
||||
|
||||
wire [7:0] bmRequestType = raw_setup_data[0];
|
||||
wire [7:0] bRequest = raw_setup_data[1];
|
||||
wire [15:0] wValue = {raw_setup_data[3][7:0], raw_setup_data[2][7:0]};
|
||||
wire [15:0] wIndex = {raw_setup_data[5][7:0], raw_setup_data[4][7:0]};
|
||||
wire [15:0] wLength = {raw_setup_data[7][7:0], raw_setup_data[6][7:0]};
|
||||
|
||||
// keep track of new out data start and end
|
||||
wire pkt_start;
|
||||
wire pkt_end;
|
||||
|
||||
rising_edge_detector detect_pkt_start (
|
||||
.clk(clk),
|
||||
.in(out_ep_data_avail),
|
||||
.out(pkt_start)
|
||||
);
|
||||
|
||||
falling_edge_detector detect_pkt_end (
|
||||
.clk(clk),
|
||||
.in(out_ep_data_avail),
|
||||
.out(pkt_end)
|
||||
);
|
||||
|
||||
assign out_ep_stall = 1'b0;
|
||||
|
||||
wire setup_pkt_start = pkt_start && out_ep_setup;
|
||||
|
||||
// wire has_data_stage = wLength != 16'b0000000000000000; // this version for some reason causes a 16b carry which is slow
|
||||
wire has_data_stage = |wLength;
|
||||
|
||||
wire out_data_stage;
|
||||
assign out_data_stage = has_data_stage && !bmRequestType[7];
|
||||
|
||||
wire in_data_stage;
|
||||
assign in_data_stage = has_data_stage && bmRequestType[7];
|
||||
|
||||
reg [7:0] bytes_sent = 0;
|
||||
reg [6:0] rom_length = 0;
|
||||
|
||||
wire all_data_sent =
|
||||
(bytes_sent >= rom_length) ||
|
||||
(bytes_sent >= wLength[7:0]); // save it from the full 16b
|
||||
|
||||
wire more_data_to_send =
|
||||
!all_data_sent;
|
||||
|
||||
wire in_data_transfer_done;
|
||||
|
||||
rising_edge_detector detect_in_data_transfer_done (
|
||||
.clk(clk),
|
||||
.in(all_data_sent),
|
||||
.out(in_data_transfer_done)
|
||||
);
|
||||
|
||||
assign in_ep_data_done = (in_data_transfer_done && ctrl_xfr_state == DATA_IN) || send_zero_length_data_pkt;
|
||||
|
||||
assign in_ep_req = ctrl_xfr_state == DATA_IN && more_data_to_send;
|
||||
assign in_ep_data_put = ctrl_xfr_state == DATA_IN && more_data_to_send && in_ep_data_free;
|
||||
|
||||
|
||||
reg [6:0] rom_addr = 0;
|
||||
|
||||
reg save_dev_addr = 0;
|
||||
reg [6:0] new_dev_addr = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// control transfer state machine
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
always @* begin
|
||||
setup_stage_end <= 0;
|
||||
data_stage_end <= 0;
|
||||
status_stage_end <= 0;
|
||||
send_zero_length_data_pkt <= 0;
|
||||
|
||||
case (ctrl_xfr_state)
|
||||
IDLE : begin
|
||||
if (setup_pkt_start) begin
|
||||
ctrl_xfr_state_next <= SETUP;
|
||||
end else begin
|
||||
ctrl_xfr_state_next <= IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
SETUP : begin
|
||||
if (pkt_end) begin
|
||||
setup_stage_end <= 1;
|
||||
|
||||
if (in_data_stage) begin
|
||||
ctrl_xfr_state_next <= DATA_IN;
|
||||
|
||||
end else if (out_data_stage) begin
|
||||
ctrl_xfr_state_next <= DATA_OUT;
|
||||
|
||||
end else begin
|
||||
ctrl_xfr_state_next <= STATUS_IN;
|
||||
send_zero_length_data_pkt <= 1;
|
||||
end
|
||||
|
||||
end else begin
|
||||
ctrl_xfr_state_next <= SETUP;
|
||||
end
|
||||
end
|
||||
|
||||
DATA_IN : begin
|
||||
if (in_ep_stall) begin
|
||||
ctrl_xfr_state_next <= IDLE;
|
||||
data_stage_end <= 1;
|
||||
status_stage_end <= 1;
|
||||
|
||||
end else if (in_ep_acked && all_data_sent) begin
|
||||
ctrl_xfr_state_next <= STATUS_OUT;
|
||||
data_stage_end <= 1;
|
||||
|
||||
end else begin
|
||||
ctrl_xfr_state_next <= DATA_IN;
|
||||
end
|
||||
end
|
||||
|
||||
DATA_OUT : begin
|
||||
if (out_ep_acked) begin
|
||||
ctrl_xfr_state_next <= STATUS_IN;
|
||||
send_zero_length_data_pkt <= 1;
|
||||
data_stage_end <= 1;
|
||||
|
||||
end else begin
|
||||
ctrl_xfr_state_next <= DATA_OUT;
|
||||
end
|
||||
end
|
||||
|
||||
STATUS_IN : begin
|
||||
if (in_ep_acked) begin
|
||||
ctrl_xfr_state_next <= IDLE;
|
||||
status_stage_end <= 1;
|
||||
|
||||
end else begin
|
||||
ctrl_xfr_state_next <= STATUS_IN;
|
||||
end
|
||||
end
|
||||
|
||||
STATUS_OUT: begin
|
||||
if (out_ep_acked) begin
|
||||
ctrl_xfr_state_next <= IDLE;
|
||||
status_stage_end <= 1;
|
||||
|
||||
end else begin
|
||||
ctrl_xfr_state_next <= STATUS_OUT;
|
||||
end
|
||||
end
|
||||
|
||||
default begin
|
||||
ctrl_xfr_state_next <= IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
ctrl_xfr_state <= IDLE;
|
||||
end else begin
|
||||
ctrl_xfr_state <= ctrl_xfr_state_next;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
in_ep_stall <= 0;
|
||||
|
||||
if (out_ep_setup && out_ep_data_valid) begin
|
||||
raw_setup_data[setup_data_addr] <= out_ep_data;
|
||||
setup_data_addr <= setup_data_addr + 1;
|
||||
end
|
||||
|
||||
if (setup_stage_end) begin
|
||||
case (bRequest)
|
||||
'h06 : begin
|
||||
// GET_DESCRIPTOR
|
||||
case (wValue[15:8])
|
||||
1 : begin
|
||||
// DEVICE
|
||||
rom_addr <= 'h00;
|
||||
rom_length <= 'h12;
|
||||
end
|
||||
|
||||
2 : begin
|
||||
// CONFIGURATION
|
||||
rom_addr <= 'h12;
|
||||
rom_length <= 'h43;
|
||||
end
|
||||
|
||||
6 : begin
|
||||
// DEVICE_QUALIFIER
|
||||
in_ep_stall <= 1;
|
||||
rom_addr <= 'h00;
|
||||
rom_length <= 'h00;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
'h05 : begin
|
||||
// SET_ADDRESS
|
||||
rom_addr <= 'h00;
|
||||
rom_length <= 'h00;
|
||||
|
||||
// we need to save the address after the status stage ends
|
||||
// this is because the status stage token will still be using
|
||||
// the old device address
|
||||
save_dev_addr <= 1;
|
||||
new_dev_addr <= wValue[6:0];
|
||||
end
|
||||
|
||||
'h09 : begin
|
||||
// SET_CONFIGURATION
|
||||
rom_addr <= 'h00;
|
||||
rom_length <= 'h00;
|
||||
end
|
||||
|
||||
'h20 : begin
|
||||
// SET_LINE_CODING
|
||||
rom_addr <= 'h00;
|
||||
rom_length <= 'h00;
|
||||
end
|
||||
|
||||
'h21 : begin
|
||||
// GET_LINE_CODING
|
||||
rom_addr <= 'h55;
|
||||
rom_length <= 'h07;
|
||||
end
|
||||
|
||||
'h22 : begin
|
||||
// SET_CONTROL_LINE_STATE
|
||||
rom_addr <= 'h00;
|
||||
rom_length <= 'h00;
|
||||
end
|
||||
|
||||
'h23 : begin
|
||||
// SEND_BREAK
|
||||
rom_addr <= 'h00;
|
||||
rom_length <= 'h00;
|
||||
end
|
||||
|
||||
default begin
|
||||
rom_addr <= 'h00;
|
||||
rom_length <= 'h00;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (ctrl_xfr_state == DATA_IN && more_data_to_send && in_ep_grant && in_ep_data_free) begin
|
||||
rom_addr <= rom_addr + 1;
|
||||
bytes_sent <= bytes_sent + 1;
|
||||
end
|
||||
|
||||
if (status_stage_end) begin
|
||||
setup_data_addr <= 0;
|
||||
bytes_sent <= 0;
|
||||
rom_addr <= 0;
|
||||
rom_length <= 0;
|
||||
|
||||
if (save_dev_addr) begin
|
||||
save_dev_addr <= 0;
|
||||
dev_addr_i <= new_dev_addr;
|
||||
end
|
||||
end
|
||||
|
||||
if (reset) begin
|
||||
dev_addr_i <= 0;
|
||||
setup_data_addr <= 0;
|
||||
save_dev_addr <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
`define CDC_ACM_ENDPOINT 2
|
||||
`define CDC_RX_ENDPOINT 1
|
||||
`define CDC_TX_ENDPOINT 1
|
||||
|
||||
|
||||
always @* begin
|
||||
case (rom_addr)
|
||||
// device descriptor
|
||||
'h000 : in_ep_data <= 18; // bLength
|
||||
'h001 : in_ep_data <= 1; // bDescriptorType
|
||||
'h002 : in_ep_data <= 'h00; // bcdUSB[0]
|
||||
'h003 : in_ep_data <= 'h02; // bcdUSB[1]
|
||||
'h004 : in_ep_data <= 'h02; // bDeviceClass (Communications Device Class)
|
||||
'h005 : in_ep_data <= 'h00; // bDeviceSubClass (Abstract Control Model)
|
||||
'h006 : in_ep_data <= 'h00; // bDeviceProtocol (No class specific protocol required)
|
||||
'h007 : in_ep_data <= MAX_IN_PACKET_SIZE; // bMaxPacketSize0
|
||||
|
||||
'h008 : in_ep_data <= 'h50; // idVendor[0] http://wiki.openmoko.org/wiki/USB_Product_IDs
|
||||
'h009 : in_ep_data <= 'h1d; // idVendor[1]
|
||||
'h00A : in_ep_data <= 'h30; // idProduct[0]
|
||||
'h00B : in_ep_data <= 'h61; // idProduct[1]
|
||||
|
||||
'h00C : in_ep_data <= 0; // bcdDevice[0]
|
||||
'h00D : in_ep_data <= 0; // bcdDevice[1]
|
||||
'h00E : in_ep_data <= 0; // iManufacturer
|
||||
'h00F : in_ep_data <= 0; // iProduct
|
||||
'h010 : in_ep_data <= 0; // iSerialNumber
|
||||
'h011 : in_ep_data <= 1; // bNumConfigurations
|
||||
|
||||
// configuration descriptor
|
||||
'h012 : in_ep_data <= 9; // bLength
|
||||
'h013 : in_ep_data <= 2; // bDescriptorType
|
||||
'h014 : in_ep_data <= (9+9+5+5+4+5+7+9+7+7); // wTotalLength[0]
|
||||
'h015 : in_ep_data <= 0; // wTotalLength[1]
|
||||
'h016 : in_ep_data <= 2; // bNumInterfaces
|
||||
'h017 : in_ep_data <= 1; // bConfigurationValue
|
||||
'h018 : in_ep_data <= 0; // iConfiguration
|
||||
'h019 : in_ep_data <= 'hC0; // bmAttributes
|
||||
'h01A : in_ep_data <= 50; // bMaxPower
|
||||
|
||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||
'h01B : in_ep_data <= 9; // bLength
|
||||
'h01C : in_ep_data <= 4; // bDescriptorType
|
||||
'h01D : in_ep_data <= 0; // bInterfaceNumber
|
||||
'h01E : in_ep_data <= 0; // bAlternateSetting
|
||||
'h01F : in_ep_data <= 1; // bNumEndpoints
|
||||
'h020 : in_ep_data <= 2; // bInterfaceClass (Communications Device Class)
|
||||
'h021 : in_ep_data <= 2; // bInterfaceSubClass (Abstract Control Model)
|
||||
'h022 : in_ep_data <= 0; // bInterfaceProtocol (0 = ?, 1 = AT Commands: V.250 etc)
|
||||
'h023 : in_ep_data <= 0; // iInterface
|
||||
|
||||
// CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
|
||||
'h024 : in_ep_data <= 5; // bFunctionLength
|
||||
'h025 : in_ep_data <= 'h24; // bDescriptorType
|
||||
'h026 : in_ep_data <= 'h00; // bDescriptorSubtype
|
||||
'h027 : in_ep_data <= 'h10;
|
||||
'h028 : in_ep_data <= 'h01; // bcdCDC
|
||||
|
||||
// Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
|
||||
'h029 : in_ep_data <= 5; // bFunctionLength
|
||||
'h02A : in_ep_data <= 'h24; // bDescriptorType
|
||||
'h02B : in_ep_data <= 'h01; // bDescriptorSubtype
|
||||
'h02C : in_ep_data <= 'h00; // bmCapabilities
|
||||
'h02D : in_ep_data <= 1; // bDataInterface
|
||||
|
||||
// Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
|
||||
'h02E : in_ep_data <= 4; // bFunctionLength
|
||||
'h02F : in_ep_data <= 'h24; // bDescriptorType
|
||||
'h030 : in_ep_data <= 'h02; // bDescriptorSubtype
|
||||
'h031 : in_ep_data <= 'h06; // bmCapabilities
|
||||
|
||||
// Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
|
||||
'h032 : in_ep_data <= 5; // bFunctionLength
|
||||
'h033 : in_ep_data <= 'h24; // bDescriptorType
|
||||
'h034 : in_ep_data <= 'h06; // bDescriptorSubtype
|
||||
'h035 : in_ep_data <= 0; // bMasterInterface
|
||||
'h036 : in_ep_data <= 1; // bSlaveInterface0
|
||||
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
'h037 : in_ep_data <= 7; // bLength
|
||||
'h038 : in_ep_data <= 5; // bDescriptorType
|
||||
'h039 : in_ep_data <= `CDC_ACM_ENDPOINT | 'h80; // bEndpointAddress
|
||||
'h03A : in_ep_data <= 'h03; // bmAttributes (0x03=intr)
|
||||
'h03B : in_ep_data <= 8; // wMaxPacketSize[0]
|
||||
'h03C : in_ep_data <= 0; // wMaxPacketSize[1]
|
||||
'h03D : in_ep_data <= 64; // bInterval
|
||||
|
||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||
'h03E : in_ep_data <= 9; // bLength
|
||||
'h03F : in_ep_data <= 4; // bDescriptorType
|
||||
'h040 : in_ep_data <= 1; // bInterfaceNumber
|
||||
'h041 : in_ep_data <= 0; // bAlternateSetting
|
||||
'h042 : in_ep_data <= 2; // bNumEndpoints
|
||||
'h043 : in_ep_data <= 'h0A; // bInterfaceClass
|
||||
'h044 : in_ep_data <= 'h00; // bInterfaceSubClass
|
||||
'h045 : in_ep_data <= 'h00; // bInterfaceProtocol
|
||||
'h046 : in_ep_data <= 0; // iInterface
|
||||
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
'h047 : in_ep_data <= 7; // bLength
|
||||
'h048 : in_ep_data <= 5; // bDescriptorType
|
||||
'h049 : in_ep_data <= `CDC_RX_ENDPOINT; // bEndpointAddress
|
||||
'h04A : in_ep_data <= 'h02; // bmAttributes (0x02=bulk)
|
||||
'h04B : in_ep_data <= MAX_IN_PACKET_SIZE; // wMaxPacketSize[0]
|
||||
'h04C : in_ep_data <= 0; // wMaxPacketSize[1]
|
||||
'h04D : in_ep_data <= 0; // bInterval
|
||||
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
'h04E : in_ep_data <= 7; // bLength
|
||||
'h04F : in_ep_data <= 5; // bDescriptorType
|
||||
'h050 : in_ep_data <= `CDC_TX_ENDPOINT | 'h80; // bEndpointAddress
|
||||
'h051 : in_ep_data <= 'h02; // bmAttributes (0x02=bulk)
|
||||
|
||||
'h052 : in_ep_data <= MAX_OUT_PACKET_SIZE; // wMaxPacketSize[0]
|
||||
'h053 : in_ep_data <= 0; // wMaxPacketSize[1]
|
||||
'h054 : in_ep_data <= 0; // bInterval
|
||||
|
||||
// LINE_CODING
|
||||
'h055 : in_ep_data <= 'h80; // dwDTERate[0]
|
||||
'h056 : in_ep_data <= 'h25; // dwDTERate[1]
|
||||
'h057 : in_ep_data <= 'h00; // dwDTERate[2]
|
||||
'h058 : in_ep_data <= 'h00; // dwDTERate[3]
|
||||
'h059 : in_ep_data <= 1; // bCharFormat (1 stop bit)
|
||||
'h05A : in_ep_data <= 0; // bParityType (None)
|
||||
'h05B : in_ep_data <= 8; // bDataBits (8 bits)
|
||||
|
||||
default begin
|
||||
in_ep_data <= 0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
331
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_uart.v
Normal file
331
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_uart.v
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
usb_uart
|
||||
|
||||
Luke Valenti's USB module, as adapted by Lawrie Griffiths.
|
||||
|
||||
This module was originally tinyfpga_bootloader.v in Luke's code.
|
||||
|
||||
It creates the endpoint modules and the protocol engine to run things. Whereas
|
||||
the original creates a usb_spi_bridge, this one creates a usb_uart_bridge.
|
||||
|
||||
Instanciation template
|
||||
|
||||
----------------------------------------------------
|
||||
usb_uart uart (
|
||||
.clk_48mhz (clk_48mhz),
|
||||
.reset (reset),
|
||||
|
||||
// pins - these must be connected properly to the outside world. See below.
|
||||
.usb_p_tx(usb_p_tx),
|
||||
.usb_n_tx(usb_n_tx),
|
||||
.usb_p_rx(usb_p_rx),
|
||||
.usb_n_rx(usb_n_rx),
|
||||
.usb_tx_en(usb_tx_en),
|
||||
|
||||
// uart pipeline in
|
||||
.uart_in_data( uart_in_data ),
|
||||
.uart_in_valid( uart_in_valid ),
|
||||
.uart_in_ready( uart_in_ready ),
|
||||
|
||||
// uart pipeline out
|
||||
.uart_out_data( uart_out_data ),
|
||||
.uart_out_valid( uart_out_valid ),
|
||||
.uart_out_ready( uart_out_ready ),
|
||||
|
||||
.debug( debug )
|
||||
);
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
Then, the actual physical pins need some special handling. Get some
|
||||
help from the device.
|
||||
|
||||
----------------------------------------------------
|
||||
assign usb_p_rx = usb_tx_en ? 1'b1 : usb_p_in;
|
||||
assign usb_n_rx = usb_tx_en ? 1'b0 : usb_n_in;
|
||||
|
||||
SB_IO #(
|
||||
.PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
|
||||
.PULLUP(1'b 0)
|
||||
)
|
||||
iobuf_usbp
|
||||
(
|
||||
.PACKAGE_PIN(pin_usbp),
|
||||
.OUTPUT_ENABLE(usb_tx_en),
|
||||
.D_OUT_0(usb_p_tx),
|
||||
.D_IN_0(usb_p_in)
|
||||
);
|
||||
|
||||
SB_IO #(
|
||||
.PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
|
||||
.PULLUP(1'b 0)
|
||||
)
|
||||
iobuf_usbn
|
||||
(
|
||||
.PACKAGE_PIN(pin_usbn),
|
||||
.OUTPUT_ENABLE(usb_tx_en),
|
||||
.D_OUT_0(usb_n_tx),
|
||||
.D_IN_0(usb_n_in)
|
||||
);
|
||||
----------------------------------------------------
|
||||
|
||||
It should be noted that there are no other invocations of usb stuff other than
|
||||
usb_uart.v. Since it's the top, I'm going to put some doc in here.
|
||||
|
||||
General note: USB communications happen over endpoints. The OUT endpoints are out
|
||||
with respect to the HOST, and IN endpoints are in with respect to the HOST.
|
||||
|
||||
Files:
|
||||
|
||||
usb_uart.v - top level module creates the end points clusters, (usb_serial_ctrl_ep,
|
||||
usb_uart_bridge_ep) and the main protocol engine (usb_fs_pe - passing
|
||||
in the in (3) and out (2) count, along with the actual usb signal
|
||||
lines). Also, all the end point signals are connected to the protocol
|
||||
engine in its invocation. The serial end point cluster and the control
|
||||
end point cluster have two endpoints each - one in and one out.
|
||||
|
||||
usb_serial_ctrl_ep - serial control logic. Two end point interfaces are (one in one
|
||||
out) passed in with their various signal lines. Contains all the
|
||||
USB setup logic. Returns the configuration etc. Vendor 50 1D
|
||||
Product 30 61. Two interfaces. Descriptors. Obviously the main
|
||||
configuration file.
|
||||
|
||||
usb_uart_bridge.v - where the data action is for us. Is passed in the out endpoint
|
||||
and the in endpoint, and also the (strange) UART interface signals
|
||||
(uart_we, uart_re, uart_di, uart_do, uart_wait). So this translates
|
||||
between endpoint talk and UART talk.
|
||||
|
||||
usb_fs_pe.v - full speed protocol engine - instanciates all the endpoints, making
|
||||
arrays of in and out end point signals. Also is passed in are all
|
||||
the actual interfaces to the end points.
|
||||
|
||||
Creates the in and out arbitors (usb_fs_in_arb, usb_fs_out_arb)
|
||||
|
||||
Creates the in protocol engine (usb_fs_in_pe), and the out protocol
|
||||
engine (usb_fs_out_pe)
|
||||
|
||||
Creates the receiver and transmitter (usb_fs_rx, usb_fs_tx)
|
||||
|
||||
Creates the tx mux and the rx mux which permit the different engines
|
||||
to talk.
|
||||
|
||||
usb_fs_in_pe.v - in protocol engine
|
||||
|
||||
usb_fs_out_pe.v - out protocol engine
|
||||
|
||||
usb_fs_rx.v - Actual rx logic
|
||||
|
||||
usb_fs_tx.v - Actual tx logic
|
||||
|
||||
edge_detect.v - rising and falling edge detectors
|
||||
|
||||
serial.v - width adapter (x widths to y widths)
|
||||
|
||||
*/
|
||||
|
||||
module usb_uart (
|
||||
input clk_48mhz,
|
||||
input reset,
|
||||
|
||||
// USB lines. Split into input vs. output and oe control signal to maintain
|
||||
// highest level of compatibility with synthesis tools.
|
||||
output usb_p_tx,
|
||||
output usb_n_tx,
|
||||
input usb_p_rx,
|
||||
input usb_n_rx,
|
||||
output usb_tx_en,
|
||||
|
||||
// uart pipeline in (into the module, out of the device, into the host)
|
||||
input [7:0] uart_in_data,
|
||||
input uart_in_valid,
|
||||
output uart_in_ready,
|
||||
|
||||
// uart pipeline out (out of the host, into the device, out of the module)
|
||||
output [7:0] uart_out_data,
|
||||
output uart_out_valid,
|
||||
input uart_out_ready,
|
||||
|
||||
output [11:0] debug
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////
|
||||
//////// usb engine
|
||||
////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
wire [6:0] dev_addr;
|
||||
wire [7:0] out_ep_data;
|
||||
|
||||
wire ctrl_out_ep_req;
|
||||
wire ctrl_out_ep_grant;
|
||||
wire ctrl_out_ep_data_avail;
|
||||
wire ctrl_out_ep_setup;
|
||||
wire ctrl_out_ep_data_get;
|
||||
wire ctrl_out_ep_stall;
|
||||
wire ctrl_out_ep_acked;
|
||||
|
||||
wire ctrl_in_ep_req;
|
||||
wire ctrl_in_ep_grant;
|
||||
wire ctrl_in_ep_data_free;
|
||||
wire ctrl_in_ep_data_put;
|
||||
wire [7:0] ctrl_in_ep_data;
|
||||
wire ctrl_in_ep_data_done;
|
||||
wire ctrl_in_ep_stall;
|
||||
wire ctrl_in_ep_acked;
|
||||
|
||||
|
||||
wire serial_out_ep_req;
|
||||
wire serial_out_ep_grant;
|
||||
wire serial_out_ep_data_avail;
|
||||
wire serial_out_ep_setup;
|
||||
wire serial_out_ep_data_get;
|
||||
wire serial_out_ep_stall;
|
||||
wire serial_out_ep_acked;
|
||||
|
||||
wire serial_in_ep_req;
|
||||
wire serial_in_ep_grant;
|
||||
wire serial_in_ep_data_free;
|
||||
wire serial_in_ep_data_put;
|
||||
wire [7:0] serial_in_ep_data;
|
||||
wire serial_in_ep_data_done;
|
||||
wire serial_in_ep_stall;
|
||||
wire serial_in_ep_acked;
|
||||
|
||||
wire sof_valid;
|
||||
wire [10:0] frame_index;
|
||||
|
||||
reg [31:0] host_presence_timer = 0;
|
||||
reg host_presence_timeout = 0;
|
||||
|
||||
usb_serial_ctrl_ep ctrl_ep_inst (
|
||||
.clk(clk_48mhz),
|
||||
.reset(reset),
|
||||
.dev_addr(dev_addr),
|
||||
|
||||
// out endpoint interface
|
||||
.out_ep_req(ctrl_out_ep_req),
|
||||
.out_ep_grant(ctrl_out_ep_grant),
|
||||
.out_ep_data_avail(ctrl_out_ep_data_avail),
|
||||
.out_ep_setup(ctrl_out_ep_setup),
|
||||
.out_ep_data_get(ctrl_out_ep_data_get),
|
||||
.out_ep_data(out_ep_data),
|
||||
.out_ep_stall(ctrl_out_ep_stall),
|
||||
.out_ep_acked(ctrl_out_ep_acked),
|
||||
|
||||
|
||||
// in endpoint interface
|
||||
.in_ep_req(ctrl_in_ep_req),
|
||||
.in_ep_grant(ctrl_in_ep_grant),
|
||||
.in_ep_data_free(ctrl_in_ep_data_free),
|
||||
.in_ep_data_put(ctrl_in_ep_data_put),
|
||||
.in_ep_data(ctrl_in_ep_data),
|
||||
.in_ep_data_done(ctrl_in_ep_data_done),
|
||||
.in_ep_stall(ctrl_in_ep_stall),
|
||||
.in_ep_acked(ctrl_in_ep_acked)
|
||||
);
|
||||
|
||||
usb_uart_bridge_ep usb_uart_bridge_ep_inst (
|
||||
.clk(clk_48mhz),
|
||||
.reset(reset),
|
||||
|
||||
// out endpoint interface
|
||||
.out_ep_req(serial_out_ep_req),
|
||||
.out_ep_grant(serial_out_ep_grant),
|
||||
.out_ep_data_avail(serial_out_ep_data_avail),
|
||||
.out_ep_setup(serial_out_ep_setup),
|
||||
.out_ep_data_get(serial_out_ep_data_get),
|
||||
.out_ep_data(out_ep_data),
|
||||
.out_ep_stall(serial_out_ep_stall),
|
||||
.out_ep_acked(serial_out_ep_acked),
|
||||
|
||||
// in endpoint interface
|
||||
.in_ep_req(serial_in_ep_req),
|
||||
.in_ep_grant(serial_in_ep_grant),
|
||||
.in_ep_data_free(serial_in_ep_data_free),
|
||||
.in_ep_data_put(serial_in_ep_data_put),
|
||||
.in_ep_data(serial_in_ep_data),
|
||||
.in_ep_data_done(serial_in_ep_data_done),
|
||||
.in_ep_stall(serial_in_ep_stall),
|
||||
.in_ep_acked(serial_in_ep_acked),
|
||||
|
||||
// uart pipeline in
|
||||
.uart_in_data( uart_in_data ),
|
||||
.uart_in_valid( uart_in_valid ),
|
||||
.uart_in_ready( uart_in_ready ),
|
||||
|
||||
// uart pipeline out
|
||||
.uart_out_data( uart_out_data ),
|
||||
.uart_out_valid( uart_out_valid ),
|
||||
.uart_out_ready( uart_out_ready ),
|
||||
|
||||
.debug(debug[3:0])
|
||||
);
|
||||
|
||||
wire nak_in_ep_grant;
|
||||
wire nak_in_ep_data_free;
|
||||
wire nak_in_ep_acked;
|
||||
|
||||
usb_fs_pe #(
|
||||
.NUM_OUT_EPS(5'd2),
|
||||
.NUM_IN_EPS(5'd3)
|
||||
) usb_fs_pe_inst (
|
||||
.clk(clk_48mhz),
|
||||
.reset(reset),
|
||||
|
||||
.usb_p_tx(usb_p_tx),
|
||||
.usb_n_tx(usb_n_tx),
|
||||
.usb_p_rx(usb_p_rx),
|
||||
.usb_n_rx(usb_n_rx),
|
||||
.usb_tx_en(usb_tx_en),
|
||||
|
||||
.dev_addr(dev_addr),
|
||||
|
||||
// out endpoint interfaces
|
||||
.out_ep_req({serial_out_ep_req, ctrl_out_ep_req}),
|
||||
.out_ep_grant({serial_out_ep_grant, ctrl_out_ep_grant}),
|
||||
.out_ep_data_avail({serial_out_ep_data_avail, ctrl_out_ep_data_avail}),
|
||||
.out_ep_setup({serial_out_ep_setup, ctrl_out_ep_setup}),
|
||||
.out_ep_data_get({serial_out_ep_data_get, ctrl_out_ep_data_get}),
|
||||
.out_ep_data(out_ep_data),
|
||||
.out_ep_stall({serial_out_ep_stall, ctrl_out_ep_stall}),
|
||||
.out_ep_acked({serial_out_ep_acked, ctrl_out_ep_acked}),
|
||||
|
||||
// in endpoint interfaces
|
||||
.in_ep_req({1'b0, serial_in_ep_req, ctrl_in_ep_req}),
|
||||
.in_ep_grant({nak_in_ep_grant, serial_in_ep_grant, ctrl_in_ep_grant}),
|
||||
.in_ep_data_free({nak_in_ep_data_free, serial_in_ep_data_free, ctrl_in_ep_data_free}),
|
||||
.in_ep_data_put({1'b0, serial_in_ep_data_put, ctrl_in_ep_data_put}),
|
||||
.in_ep_data({8'b0, serial_in_ep_data[7:0], ctrl_in_ep_data[7:0]}),
|
||||
.in_ep_data_done({1'b0, serial_in_ep_data_done, ctrl_in_ep_data_done}),
|
||||
.in_ep_stall({1'b0, serial_in_ep_stall, ctrl_in_ep_stall}),
|
||||
.in_ep_acked({nak_in_ep_acked, serial_in_ep_acked, ctrl_in_ep_acked}),
|
||||
|
||||
// sof interface
|
||||
.sof_valid(sof_valid),
|
||||
.frame_index(frame_index),
|
||||
|
||||
// Debug
|
||||
.debug(debug[11:4])
|
||||
);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// host presence detection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
always @(posedge clk_48mhz) begin
|
||||
if (sof_valid) begin
|
||||
host_presence_timer <= 0;
|
||||
host_presence_timeout <= 0;
|
||||
end else begin
|
||||
host_presence_timer <= host_presence_timer + 1;
|
||||
end
|
||||
|
||||
if (host_presence_timer > 48000000) begin
|
||||
host_presence_timeout <= 1;
|
||||
end
|
||||
end
|
||||
endmodule
|
315
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_uart_bridge_ep.v
Normal file
315
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_uart_bridge_ep.v
Normal file
@ -0,0 +1,315 @@
|
||||
/*
|
||||
usb_uart_bridge_ep
|
||||
|
||||
This is the endpoint to uart translator. Two things to highlight: the directions
|
||||
IN and OUT are set with respect to the HOST, and also in USB, the HOST runs all
|
||||
endpoint interactions.
|
||||
|
||||
The out endpoint interface. This is the out w.r.t. the host, hence in to
|
||||
us. There are request grant, data available and data get signals, stall and
|
||||
acked signals. And the data itself.
|
||||
|
||||
The in endpoint interface. This is the in w.r.t. the host, hence out to us.
|
||||
This interface also has a req and grant. There's a put signal and a free
|
||||
signal. Stall and acked. And the data.
|
||||
|
||||
To get data in and out there are two pipeline interfaces - one in and one out.
|
||||
|
||||
OUT (or into this device)
|
||||
|
||||
Roughly, the USB innards signal that a packet has arrived by raising out_ep_data_available.
|
||||
The data multiplexor has to be switched, so the interface is requested. This is
|
||||
combinatorial logic so clever req and grant stuff can happen in the same line.
|
||||
|
||||
assign out_ep_req = ( out_ep_req_reg || out_ep_data_avail );
|
||||
|
||||
With the interface granted, the data is free to get. Every cycle that the out_ep_data_get
|
||||
signal is high, the input address is advanced. Inside the USB innards, when the
|
||||
read address pointer equals the address of the write pointer (when all the data is
|
||||
retreived, the out_ep_data_available flag is lowered and we withdraw our request for
|
||||
the interface and go back to idle.
|
||||
|
||||
Interestingly, if you stop taking data... you lose your buffer. So don't.
|
||||
|
||||
IN (or out of this device back to the host)
|
||||
|
||||
The IN EP works by providing a buffer and waiting for the local logic to fill it,
|
||||
or to say that it's done. When this happens the interface switches to a new state where
|
||||
it waits for a token from the host. When it get the token, it sends the data. When that
|
||||
is acknoledged, the buffer is released and returned ready to be filled again.
|
||||
|
||||
in_ep_data_free signals that there's a buffer waiting. And that signal goes low when
|
||||
the buffer is full and not available.
|
||||
|
||||
In the case where a buffer is not full - just sitting around with some data in it, a decision
|
||||
has to be made at some point just to send. This is handled by a timeout mechanism, which
|
||||
asserts in_ep_data_done and lets the buffer be sent.
|
||||
|
||||
In the case where the buffer fills to the top, in_ep_data_free goes low by itself.
|
||||
|
||||
*/
|
||||
|
||||
module usb_uart_bridge_ep (
|
||||
input clk,
|
||||
input reset,
|
||||
|
||||
////////////////////
|
||||
// out endpoint interface
|
||||
////////////////////
|
||||
output out_ep_req, // request the data interface for the out endpoint
|
||||
input out_ep_grant, // data interface granted
|
||||
input out_ep_data_avail, // flagging data available to get from the host - stays up until the cycle upon which it is empty
|
||||
input out_ep_setup, // [setup packet sent? - not used here]
|
||||
output out_ep_data_get, // request to get the data
|
||||
input [7:0] out_ep_data, // data from the host
|
||||
output out_ep_stall, // an output enabling the device to stop inputs (not used)
|
||||
input out_ep_acked, // indicating that the outgoing data was acked
|
||||
|
||||
////////////////////
|
||||
// in endpoint interface
|
||||
////////////////////
|
||||
output in_ep_req, // request the data interface for the in endpoint
|
||||
input in_ep_grant, // data interface granted
|
||||
input in_ep_data_free, // end point is ready for data - (specifically there is a buffer and it has space)
|
||||
// after going low it takes a while to get another back, but it does this automatically
|
||||
output in_ep_data_put, // forces end point to read our data
|
||||
output [7:0] in_ep_data, // data back to the host
|
||||
output in_ep_data_done, // signalling that we're done sending data
|
||||
output in_ep_stall, // an output enabling the device to stop outputs (not used)
|
||||
input in_ep_acked, // indicating that the outgoing data was acked
|
||||
|
||||
// uart pipeline in
|
||||
input [7:0] uart_in_data,
|
||||
input uart_in_valid,
|
||||
output uart_in_ready,
|
||||
|
||||
// uart pipeline out
|
||||
output [7:0] uart_out_data,
|
||||
output uart_out_valid,
|
||||
input uart_out_ready,
|
||||
|
||||
output [3:0] debug
|
||||
);
|
||||
|
||||
// Timeout counter width.
|
||||
localparam TimeoutWidth = 3;
|
||||
|
||||
// We don't stall
|
||||
assign out_ep_stall = 1'b0;
|
||||
assign in_ep_stall = 1'b0;
|
||||
|
||||
// Registers for the out pipeline (out of the module)
|
||||
reg [7:0] uart_out_data_reg;
|
||||
reg [7:0] uart_out_data_overflow_reg;
|
||||
reg uart_out_valid_reg;
|
||||
|
||||
// registers for the out end point (out of the host)
|
||||
reg out_ep_req_reg;
|
||||
reg out_ep_data_get_reg;
|
||||
|
||||
// out pipeline / out endpoint state machine state (6 states -> 3 bits)
|
||||
reg [1:0] pipeline_out_state;
|
||||
|
||||
localparam PipelineOutState_Idle = 0;
|
||||
localparam PipelineOutState_WaitData = 1;
|
||||
localparam PipelineOutState_PushData = 2;
|
||||
localparam PipelineOutState_WaitPipeline = 3;
|
||||
|
||||
// connect the pipeline registers to the outgoing ports
|
||||
assign uart_out_data = uart_out_data_reg;
|
||||
assign uart_out_valid = uart_out_valid_reg;
|
||||
|
||||
// automatically make the bus request from the data_available
|
||||
// latch it with out_ep_req_reg
|
||||
assign out_ep_req = ( out_ep_req_reg || out_ep_data_avail );
|
||||
|
||||
wire out_granted_data_available;
|
||||
|
||||
assign out_granted_data_available = out_ep_req && out_ep_grant;
|
||||
|
||||
assign out_ep_data_get = ( uart_out_ready || ~uart_out_valid_reg ) && out_ep_data_get_reg;
|
||||
|
||||
reg [7:0] out_stall_data;
|
||||
reg out_stall_valid;
|
||||
|
||||
// do HOST OUT, DEVICE IN, PIPELINE OUT (!)
|
||||
always @(posedge clk) begin
|
||||
if ( reset ) begin
|
||||
pipeline_out_state <= PipelineOutState_Idle;
|
||||
uart_out_data_reg <= 0;
|
||||
uart_out_valid_reg <= 0;
|
||||
out_ep_req_reg <= 0;
|
||||
out_ep_data_get_reg <= 0;
|
||||
out_stall_data <= 0;
|
||||
out_stall_valid <= 0;
|
||||
end else begin
|
||||
case( pipeline_out_state )
|
||||
PipelineOutState_Idle: begin
|
||||
// Waiting for the data_available signal indicating that a data packet has arrived
|
||||
if ( out_granted_data_available ) begin
|
||||
// indicate that we want the data
|
||||
out_ep_data_get_reg <= 1;
|
||||
// although the bus has been requested automatically, we latch the request so we control it
|
||||
out_ep_req_reg <= 1;
|
||||
// now wait for the data to set up
|
||||
pipeline_out_state <= PipelineOutState_WaitData;
|
||||
uart_out_valid_reg <= 0;
|
||||
out_stall_data <= 0;
|
||||
out_stall_valid <= 0;
|
||||
end
|
||||
end
|
||||
PipelineOutState_WaitData: begin
|
||||
// it takes one cycle for the juices to start flowing
|
||||
// we got here when we were starting or if the outgoing pipe stalled
|
||||
if ( uart_out_ready || ~uart_out_valid_reg ) begin
|
||||
//if we were stalled, we can send the byte we caught while we were stalled
|
||||
// the actual stalled byte now having been VALID & READY'ed
|
||||
if ( out_stall_valid ) begin
|
||||
uart_out_data_reg <= out_stall_data;
|
||||
uart_out_valid_reg <= 1;
|
||||
out_stall_data <= 0;
|
||||
out_stall_valid <= 0;
|
||||
if ( out_ep_data_avail )
|
||||
pipeline_out_state <= PipelineOutState_PushData;
|
||||
else begin
|
||||
pipeline_out_state <= PipelineOutState_WaitPipeline;
|
||||
end
|
||||
end else begin
|
||||
pipeline_out_state <= PipelineOutState_PushData;
|
||||
end
|
||||
end
|
||||
end
|
||||
PipelineOutState_PushData: begin
|
||||
// can grab a character if either the out was accepted or the out reg is empty
|
||||
if ( uart_out_ready || ~uart_out_valid_reg ) begin
|
||||
// now we really have got some data and a place to shove it
|
||||
uart_out_data_reg <= out_ep_data;
|
||||
uart_out_valid_reg <= 1;
|
||||
if ( ~out_ep_data_avail ) begin
|
||||
// stop streaming, now just going to wait until the character is accepted
|
||||
out_ep_data_get_reg <= 0;
|
||||
pipeline_out_state <= PipelineOutState_WaitPipeline;
|
||||
end
|
||||
end else begin
|
||||
// We're in push data so there is a character, but our pipeline has stalled
|
||||
// need to save the character and wait.
|
||||
out_stall_data <= out_ep_data;
|
||||
out_stall_valid <= 1;
|
||||
pipeline_out_state <= PipelineOutState_WaitData;
|
||||
if ( ~out_ep_data_avail )
|
||||
out_ep_data_get_reg <= 0;
|
||||
end
|
||||
end
|
||||
PipelineOutState_WaitPipeline: begin
|
||||
// unhand the bus (don't want to block potential incoming) - be careful, this works instantly!
|
||||
out_ep_req_reg <= 0;
|
||||
if ( uart_out_ready ) begin
|
||||
uart_out_valid_reg <= 0;
|
||||
uart_out_data_reg <= 0;
|
||||
pipeline_out_state <= PipelineOutState_Idle;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// in endpoint control registers
|
||||
reg in_ep_req_reg;
|
||||
reg in_ep_data_done_reg;
|
||||
|
||||
// in pipeline / in endpoint state machine state (4 states -> 2 bits)
|
||||
reg [1:0] pipeline_in_state;
|
||||
|
||||
localparam PipelineInState_Idle = 0;
|
||||
localparam PipelineInState_WaitData = 1;
|
||||
localparam PipelineInState_CycleData = 2;
|
||||
localparam PipelineInState_WaitEP = 3;
|
||||
|
||||
// connect the pipeline register to the outgoing port
|
||||
assign uart_in_ready = ( pipeline_in_state == PipelineInState_CycleData ) && in_ep_data_free;
|
||||
|
||||
// uart_in_valid and a buffer being ready is the request for the bus.
|
||||
// It is granted automatically if available, and latched on by the SM.
|
||||
// Note once requested, uart_in_valid may go on and off as data is available.
|
||||
// When requested, connect the end point registers to the outgoing ports
|
||||
assign in_ep_req = ( uart_in_valid && in_ep_data_free) || in_ep_req_reg;
|
||||
|
||||
// Confirmation that the bus was granted
|
||||
wire in_granted_in_valid = in_ep_grant && uart_in_valid;
|
||||
|
||||
// Here are the things we use to get data sent
|
||||
// ... put this word
|
||||
assign in_ep_data_put = ( pipeline_in_state == PipelineInState_CycleData ) && uart_in_valid && in_ep_data_free;
|
||||
// ... we're done putting - send the buffer
|
||||
assign in_ep_data_done = in_ep_data_done_reg;
|
||||
// ... the actual data, direct from the pipeline to the usb in buffer
|
||||
assign in_ep_data = uart_in_data;
|
||||
|
||||
// If we have a half filled buffer, send it after a while by using a timer
|
||||
// 4 bits of counter, we'll just count up until bit 3 is high... 8 clock cycles seems more than enough to wait
|
||||
// to send the packet
|
||||
reg [TimeoutWidth:0] in_ep_timeout;
|
||||
|
||||
// do PIPELINE IN, FPGA/Device OUT, Host IN
|
||||
always @(posedge clk) begin
|
||||
if ( reset ) begin
|
||||
pipeline_in_state <= PipelineInState_Idle;
|
||||
in_ep_req_reg <= 0;
|
||||
in_ep_data_done_reg <= 0;
|
||||
end else begin
|
||||
case( pipeline_in_state )
|
||||
PipelineInState_Idle: begin
|
||||
in_ep_data_done_reg <= 0;
|
||||
if ( in_granted_in_valid && in_ep_data_free ) begin
|
||||
// got the bus, there is free space, now do the data
|
||||
// confirm request bus - this will hold the request up until we're done with it
|
||||
in_ep_req_reg <= 1;
|
||||
pipeline_in_state <= PipelineInState_CycleData;
|
||||
end
|
||||
end
|
||||
PipelineInState_CycleData: begin
|
||||
if (uart_in_valid ) begin
|
||||
if ( ~in_ep_data_free ) begin
|
||||
// back to idle
|
||||
pipeline_in_state <= PipelineInState_Idle;
|
||||
// release the bus
|
||||
in_ep_req_reg <= 0;
|
||||
end
|
||||
end else begin
|
||||
// No valid character. Let's just pause for a second to see if any more are forthcoming.
|
||||
// clear the timeout counter
|
||||
in_ep_timeout <= 0;
|
||||
pipeline_in_state <= PipelineInState_WaitData;
|
||||
end
|
||||
end
|
||||
PipelineInState_WaitData: begin
|
||||
in_ep_timeout <= in_ep_timeout + 1;
|
||||
if ( uart_in_valid ) begin
|
||||
pipeline_in_state <= PipelineInState_CycleData;
|
||||
end else begin
|
||||
// check for a timeout
|
||||
if ( in_ep_timeout[ TimeoutWidth ] ) begin
|
||||
in_ep_data_done_reg <= 1;
|
||||
pipeline_in_state <= PipelineInState_WaitEP;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
PipelineInState_WaitEP: begin
|
||||
// maybe done is ignored if putting?
|
||||
in_ep_data_done_reg <= 0;
|
||||
|
||||
// back to idle
|
||||
pipeline_in_state <= PipelineInState_Idle;
|
||||
// release the bus
|
||||
in_ep_req_reg <= 0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
assign debug = { in_ep_data_free, in_ep_data_done, pipeline_in_state[ 1 ], pipeline_in_state[ 0 ] };
|
||||
|
||||
endmodule
|
332
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_uart_core.v
Normal file
332
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_uart_core.v
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
usb_uart
|
||||
|
||||
Luke Valenti's USB module, as adapted by Lawrie Griffiths.
|
||||
|
||||
This module was originally tinyfpga_bootloader.v in Luke's code.
|
||||
|
||||
It creates the endpoint modules and the protocol engine to run things. Whereas
|
||||
the original creates a usb_spi_bridge, this one creates a usb_uart_bridge.
|
||||
|
||||
Instanciation template with separate pipe signals
|
||||
|
||||
----------------------------------------------------
|
||||
usb_uart_core_np uart (
|
||||
.clk_48mhz (clk_48mhz),
|
||||
.reset (reset),
|
||||
|
||||
// pins - these must be connected properly to the outside world. See below.
|
||||
.usb_p_tx(usb_p_tx),
|
||||
.usb_n_tx(usb_n_tx),
|
||||
.usb_p_rx(usb_p_rx),
|
||||
.usb_n_rx(usb_n_rx),
|
||||
.usb_tx_en(usb_tx_en),
|
||||
|
||||
// uart pipeline in
|
||||
.uart_in_data( uart_in_data ),
|
||||
.uart_in_valid( uart_in_valid ),
|
||||
.uart_in_ready( uart_in_ready ),
|
||||
|
||||
// uart pipeline out
|
||||
.uart_out_data( uart_out_data ),
|
||||
.uart_out_valid( uart_out_valid ),
|
||||
.uart_out_ready( uart_out_ready ),
|
||||
|
||||
.debug( debug )
|
||||
);
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
Then, the actual physical pins need some special handling. Get some
|
||||
help from the device.
|
||||
|
||||
----------------------------------------------------
|
||||
assign usb_p_rx = usb_tx_en ? 1'b1 : usb_p_in;
|
||||
assign usb_n_rx = usb_tx_en ? 1'b0 : usb_n_in;
|
||||
|
||||
SB_IO #(
|
||||
.PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
|
||||
.PULLUP(1'b 0)
|
||||
)
|
||||
iobuf_usbp
|
||||
(
|
||||
.PACKAGE_PIN(pin_usbp),
|
||||
.OUTPUT_ENABLE(usb_tx_en),
|
||||
.D_OUT_0(usb_p_tx),
|
||||
.D_IN_0(usb_p_in)
|
||||
);
|
||||
|
||||
SB_IO #(
|
||||
.PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
|
||||
.PULLUP(1'b 0)
|
||||
)
|
||||
iobuf_usbn
|
||||
(
|
||||
.PACKAGE_PIN(pin_usbn),
|
||||
.OUTPUT_ENABLE(usb_tx_en),
|
||||
.D_OUT_0(usb_n_tx),
|
||||
.D_IN_0(usb_n_in)
|
||||
);
|
||||
----------------------------------------------------
|
||||
|
||||
It should be noted that there are no other invocations of usb stuff other than
|
||||
usb_uart.v. Since it's the top, I'm going to put some doc in here.
|
||||
|
||||
General note: USB communications happen over endpoints. The OUT endpoints are out
|
||||
with respect to the HOST, and IN endpoints are in with respect to the HOST.
|
||||
|
||||
Files:
|
||||
|
||||
usb_uart_core.v - top level module creates the end points clusters, (usb_serial_ctrl_ep,
|
||||
usb_uart_bridge_ep) and the main protocol engine (usb_fs_pe - passing
|
||||
in the in (3) and out (2) count, along with the actual usb signal
|
||||
lines). Also, all the end point signals are connected to the protocol
|
||||
engine in its invocation. The serial end point cluster and the control
|
||||
end point cluster have two endpoints each - one in and one out.
|
||||
|
||||
usb_serial_ctrl_ep - serial control logic. Two end point interfaces are (one in one
|
||||
out) passed in with their various signal lines. Contains all the
|
||||
USB setup logic. Returns the configuration etc. Vendor 50 1D
|
||||
Product 30 61. Two interfaces. Descriptors. Obviously the main
|
||||
configuration file.
|
||||
|
||||
usb_uart_bridge.v - where the data action is for us. Is passed in the out endpoint
|
||||
and the in endpoint, and also the (strange) UART interface signals
|
||||
(uart_we, uart_re, uart_di, uart_do, uart_wait). So this translates
|
||||
between endpoint talk and UART talk.
|
||||
|
||||
usb_fs_pe.v - full speed protocol engine - instanciates all the endpoints, making
|
||||
arrays of in and out end point signals. Also is passed in are all
|
||||
the actual interfaces to the end points.
|
||||
|
||||
Creates the in and out arbitors (usb_fs_in_arb, usb_fs_out_arb)
|
||||
|
||||
Creates the in protocol engine (usb_fs_in_pe), and the out protocol
|
||||
engine (usb_fs_out_pe)
|
||||
|
||||
Creates the receiver and transmitter (usb_fs_rx, usb_fs_tx)
|
||||
|
||||
Creates the tx mux and the rx mux which permit the different engines
|
||||
to talk.
|
||||
|
||||
usb_fs_in_pe.v - in protocol engine
|
||||
|
||||
usb_fs_out_pe.v - out protocol engine
|
||||
|
||||
usb_fs_rx.v - Actual rx logic
|
||||
|
||||
usb_fs_tx.v - Actual tx logic
|
||||
|
||||
edge_detect.v - rising and falling edge detectors
|
||||
|
||||
serial.v - width adapter (x widths to y widths)
|
||||
|
||||
*/
|
||||
|
||||
module usb_uart_core(
|
||||
input clk_48mhz,
|
||||
input reset,
|
||||
|
||||
// USB lines. Split into input vs. output and oe control signal to maintain
|
||||
// highest level of compatibility with synthesis tools.
|
||||
output usb_p_tx,
|
||||
output usb_n_tx,
|
||||
input usb_p_rx,
|
||||
input usb_n_rx,
|
||||
output usb_tx_en,
|
||||
|
||||
// uart pipeline in (into the module, out of the device, into the host)
|
||||
input [7:0] uart_in_data,
|
||||
input uart_in_valid,
|
||||
output uart_in_ready,
|
||||
|
||||
// uart pipeline out (out of the host, into the device, out of the module)
|
||||
output [7:0] uart_out_data,
|
||||
output uart_out_valid,
|
||||
input uart_out_ready,
|
||||
|
||||
output [11:0] debug
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////
|
||||
//////// usb engine
|
||||
////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
wire [6:0] dev_addr;
|
||||
wire [7:0] out_ep_data;
|
||||
|
||||
wire ctrl_out_ep_req;
|
||||
wire ctrl_out_ep_grant;
|
||||
wire ctrl_out_ep_data_avail;
|
||||
wire ctrl_out_ep_setup;
|
||||
wire ctrl_out_ep_data_get;
|
||||
wire ctrl_out_ep_stall;
|
||||
wire ctrl_out_ep_acked;
|
||||
|
||||
wire ctrl_in_ep_req;
|
||||
wire ctrl_in_ep_grant;
|
||||
wire ctrl_in_ep_data_free;
|
||||
wire ctrl_in_ep_data_put;
|
||||
wire [7:0] ctrl_in_ep_data;
|
||||
wire ctrl_in_ep_data_done;
|
||||
wire ctrl_in_ep_stall;
|
||||
wire ctrl_in_ep_acked;
|
||||
|
||||
|
||||
wire serial_out_ep_req;
|
||||
wire serial_out_ep_grant;
|
||||
wire serial_out_ep_data_avail;
|
||||
wire serial_out_ep_setup;
|
||||
wire serial_out_ep_data_get;
|
||||
wire serial_out_ep_stall;
|
||||
wire serial_out_ep_acked;
|
||||
|
||||
wire serial_in_ep_req;
|
||||
wire serial_in_ep_grant;
|
||||
wire serial_in_ep_data_free;
|
||||
wire serial_in_ep_data_put;
|
||||
wire [7:0] serial_in_ep_data;
|
||||
wire serial_in_ep_data_done;
|
||||
wire serial_in_ep_stall;
|
||||
wire serial_in_ep_acked;
|
||||
|
||||
wire sof_valid;
|
||||
wire [10:0] frame_index;
|
||||
|
||||
reg [31:0] host_presence_timer = 0;
|
||||
reg host_presence_timeout = 0;
|
||||
|
||||
usb_serial_ctrl_ep ctrl_ep_inst (
|
||||
.clk(clk_48mhz),
|
||||
.reset(reset),
|
||||
.dev_addr(dev_addr),
|
||||
|
||||
// out endpoint interface
|
||||
.out_ep_req(ctrl_out_ep_req),
|
||||
.out_ep_grant(ctrl_out_ep_grant),
|
||||
.out_ep_data_avail(ctrl_out_ep_data_avail),
|
||||
.out_ep_setup(ctrl_out_ep_setup),
|
||||
.out_ep_data_get(ctrl_out_ep_data_get),
|
||||
.out_ep_data(out_ep_data),
|
||||
.out_ep_stall(ctrl_out_ep_stall),
|
||||
.out_ep_acked(ctrl_out_ep_acked),
|
||||
|
||||
|
||||
// in endpoint interface
|
||||
.in_ep_req(ctrl_in_ep_req),
|
||||
.in_ep_grant(ctrl_in_ep_grant),
|
||||
.in_ep_data_free(ctrl_in_ep_data_free),
|
||||
.in_ep_data_put(ctrl_in_ep_data_put),
|
||||
.in_ep_data(ctrl_in_ep_data),
|
||||
.in_ep_data_done(ctrl_in_ep_data_done),
|
||||
.in_ep_stall(ctrl_in_ep_stall),
|
||||
.in_ep_acked(ctrl_in_ep_acked)
|
||||
);
|
||||
|
||||
usb_uart_bridge_ep usb_uart_bridge_ep_inst (
|
||||
.clk(clk_48mhz),
|
||||
.reset(reset),
|
||||
|
||||
// out endpoint interface
|
||||
.out_ep_req(serial_out_ep_req),
|
||||
.out_ep_grant(serial_out_ep_grant),
|
||||
.out_ep_data_avail(serial_out_ep_data_avail),
|
||||
.out_ep_setup(serial_out_ep_setup),
|
||||
.out_ep_data_get(serial_out_ep_data_get),
|
||||
.out_ep_data(out_ep_data),
|
||||
.out_ep_stall(serial_out_ep_stall),
|
||||
.out_ep_acked(serial_out_ep_acked),
|
||||
|
||||
// in endpoint interface
|
||||
.in_ep_req(serial_in_ep_req),
|
||||
.in_ep_grant(serial_in_ep_grant),
|
||||
.in_ep_data_free(serial_in_ep_data_free),
|
||||
.in_ep_data_put(serial_in_ep_data_put),
|
||||
.in_ep_data(serial_in_ep_data),
|
||||
.in_ep_data_done(serial_in_ep_data_done),
|
||||
.in_ep_stall(serial_in_ep_stall),
|
||||
.in_ep_acked(serial_in_ep_acked),
|
||||
|
||||
// uart pipeline in
|
||||
.uart_in_data( uart_in_data ),
|
||||
.uart_in_valid( uart_in_valid ),
|
||||
.uart_in_ready( uart_in_ready ),
|
||||
|
||||
// uart pipeline out
|
||||
.uart_out_data( uart_out_data ),
|
||||
.uart_out_valid( uart_out_valid ),
|
||||
.uart_out_ready( uart_out_ready ),
|
||||
|
||||
.debug(debug[3:0])
|
||||
);
|
||||
|
||||
wire nak_in_ep_grant;
|
||||
wire nak_in_ep_data_free;
|
||||
wire nak_in_ep_acked;
|
||||
|
||||
usb_fs_pe #(
|
||||
.NUM_OUT_EPS(5'd2),
|
||||
.NUM_IN_EPS(5'd3)
|
||||
) usb_fs_pe_inst (
|
||||
.clk(clk_48mhz),
|
||||
.reset(reset),
|
||||
|
||||
.usb_p_tx(usb_p_tx),
|
||||
.usb_n_tx(usb_n_tx),
|
||||
.usb_p_rx(usb_p_rx),
|
||||
.usb_n_rx(usb_n_rx),
|
||||
.usb_tx_en(usb_tx_en),
|
||||
|
||||
.dev_addr(dev_addr),
|
||||
|
||||
// out endpoint interfaces
|
||||
.out_ep_req({serial_out_ep_req, ctrl_out_ep_req}),
|
||||
.out_ep_grant({serial_out_ep_grant, ctrl_out_ep_grant}),
|
||||
.out_ep_data_avail({serial_out_ep_data_avail, ctrl_out_ep_data_avail}),
|
||||
.out_ep_setup({serial_out_ep_setup, ctrl_out_ep_setup}),
|
||||
.out_ep_data_get({serial_out_ep_data_get, ctrl_out_ep_data_get}),
|
||||
.out_ep_data(out_ep_data),
|
||||
.out_ep_stall({serial_out_ep_stall, ctrl_out_ep_stall}),
|
||||
.out_ep_acked({serial_out_ep_acked, ctrl_out_ep_acked}),
|
||||
|
||||
// in endpoint interfaces
|
||||
.in_ep_req({1'b0, serial_in_ep_req, ctrl_in_ep_req}),
|
||||
.in_ep_grant({nak_in_ep_grant, serial_in_ep_grant, ctrl_in_ep_grant}),
|
||||
.in_ep_data_free({nak_in_ep_data_free, serial_in_ep_data_free, ctrl_in_ep_data_free}),
|
||||
.in_ep_data_put({1'b0, serial_in_ep_data_put, ctrl_in_ep_data_put}),
|
||||
.in_ep_data({8'b0, serial_in_ep_data[7:0], ctrl_in_ep_data[7:0]}),
|
||||
.in_ep_data_done({1'b0, serial_in_ep_data_done, ctrl_in_ep_data_done}),
|
||||
.in_ep_stall({1'b0, serial_in_ep_stall, ctrl_in_ep_stall}),
|
||||
.in_ep_acked({nak_in_ep_acked, serial_in_ep_acked, ctrl_in_ep_acked}),
|
||||
|
||||
// sof interface
|
||||
.sof_valid(sof_valid),
|
||||
.frame_index(frame_index),
|
||||
|
||||
// Debug
|
||||
.debug(debug[11:4])
|
||||
);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// host presence detection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// always @(posedge clk_48mhz) begin
|
||||
// if (sof_valid) begin
|
||||
// host_presence_timer <= 0;
|
||||
// host_presence_timeout <= 0;
|
||||
// end else begin
|
||||
// host_presence_timer <= host_presence_timer + 1;
|
||||
// end
|
||||
|
||||
// if (host_presence_timer > 48000000) begin
|
||||
// host_presence_timeout <= 1;
|
||||
// end
|
||||
// end
|
||||
|
||||
endmodule
|
110
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_uart_i40.v
Normal file
110
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_uart_i40.v
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
usb_uart_i40
|
||||
|
||||
Simple wrapper around the usb_uart which incorporates the Pin driver logic
|
||||
so this doesn't clutter the top level circuit
|
||||
|
||||
The layer above has to assert the Host Pull Up line
|
||||
|
||||
----------------------------------------------------
|
||||
usb_uart_i40 u_u_i40 (
|
||||
.clk_48mhz (clk_48mhz),
|
||||
.reset (reset),
|
||||
|
||||
// pins
|
||||
.pin_usb_p( pin_usb_p ),
|
||||
.pin_usb_n( pin_usb_n ),
|
||||
|
||||
// uart pipeline in
|
||||
.uart_in_data( uart_in_data ),
|
||||
.uart_in_valid( uart_in_valid ),
|
||||
.uart_in_ready( uart_in_ready ),
|
||||
|
||||
// uart pipeline out
|
||||
.uart_out_data( uart_out_data ),
|
||||
.uart_out_valid( uart_out_valid ),
|
||||
.uart_out_ready( uart_out_ready ),
|
||||
);
|
||||
|
||||
*/
|
||||
|
||||
module usb_uart (
|
||||
input clk_48mhz,
|
||||
input reset,
|
||||
|
||||
// USB pins
|
||||
inout pin_usb_p,
|
||||
inout pin_usb_n,
|
||||
|
||||
// uart pipeline in (out of the device, into the host)
|
||||
input [7:0] uart_in_data,
|
||||
input uart_in_valid,
|
||||
output uart_in_ready,
|
||||
|
||||
// uart pipeline out (into the device, out of the host)
|
||||
output [7:0] uart_out_data,
|
||||
output uart_out_valid,
|
||||
input uart_out_ready,
|
||||
|
||||
output [11:0] debug
|
||||
);
|
||||
|
||||
wire usb_p_tx;
|
||||
wire usb_n_tx;
|
||||
wire usb_p_rx;
|
||||
wire usb_n_rx;
|
||||
wire usb_tx_en;
|
||||
|
||||
//wire [3:0] debug;
|
||||
|
||||
usb_uart_core uart (
|
||||
.clk_48mhz (clk_48mhz),
|
||||
.reset (reset),
|
||||
|
||||
// pins - these must be connected properly to the outside world. See below.
|
||||
.usb_p_tx(usb_p_tx),
|
||||
.usb_n_tx(usb_n_tx),
|
||||
.usb_p_rx(usb_p_rx),
|
||||
.usb_n_rx(usb_n_rx),
|
||||
.usb_tx_en(usb_tx_en),
|
||||
|
||||
// uart pipeline in
|
||||
.uart_in_data( uart_in_data ),
|
||||
.uart_in_valid( uart_in_valid ),
|
||||
.uart_in_ready( uart_in_ready ),
|
||||
|
||||
// uart pipeline out
|
||||
.uart_out_data( uart_out_data ),
|
||||
.uart_out_valid( uart_out_valid ),
|
||||
.uart_out_ready( uart_out_ready ),
|
||||
|
||||
.debug( debug )
|
||||
);
|
||||
|
||||
wire usb_p_in;
|
||||
wire usb_n_in;
|
||||
|
||||
assign usb_p_rx = usb_tx_en ? 1'b1 : usb_p_in;
|
||||
assign usb_n_rx = usb_tx_en ? 1'b0 : usb_n_in;
|
||||
|
||||
SB_IO #(
|
||||
.PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
|
||||
.PULLUP(1'b 0)
|
||||
) iobuf_usbp (
|
||||
.PACKAGE_PIN(pin_usb_p),
|
||||
.OUTPUT_ENABLE(usb_tx_en),
|
||||
.D_OUT_0(usb_p_tx),
|
||||
.D_IN_0(usb_p_in)
|
||||
);
|
||||
|
||||
SB_IO #(
|
||||
.PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
|
||||
.PULLUP(1'b 0)
|
||||
) iobuf_usbn (
|
||||
.PACKAGE_PIN(pin_usb_n),
|
||||
.OUTPUT_ENABLE(usb_tx_en),
|
||||
.D_OUT_0(usb_n_tx),
|
||||
.D_IN_0(usb_n_in)
|
||||
);
|
||||
|
||||
endmodule
|
118
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_uart_x7.v
Normal file
118
verilog/j1eforth/tinyfpga_bx_usbserial/usb/usb_uart_x7.v
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
usb_uart_x7
|
||||
|
||||
Simple wrapper around the usb_uart which incorporates the Pin driver logic
|
||||
so this doesn't clutter the top level circuit
|
||||
|
||||
Make the signature generic (usb_uart) and rely on the file inclusion process (makefile)
|
||||
to bring the correct architecture in
|
||||
|
||||
The layer above has to assert the Host Pull Up line
|
||||
|
||||
usb_uart u_u (
|
||||
.clk_48mhz (clk_48mhz),
|
||||
.reset (reset),
|
||||
|
||||
// pins
|
||||
.pin_usb_p( pin_usb_p ),
|
||||
.pin_usb_n( pin_usb_n ),
|
||||
|
||||
// uart pipeline in
|
||||
.uart_in_data( uart_in_data ),
|
||||
.uart_in_valid( uart_in_valid ),
|
||||
.uart_in_ready( uart_in_ready ),
|
||||
|
||||
// uart pipeline out
|
||||
.uart_out_data( uart_out_data ),
|
||||
.uart_out_valid( uart_out_valid ),
|
||||
.uart_out_ready( uart_out_ready ),
|
||||
);
|
||||
|
||||
*/
|
||||
|
||||
`include "../../pipe/rtl/pipe_defs.v"
|
||||
|
||||
module usb_uart (
|
||||
input clk_48mhz,
|
||||
input reset,
|
||||
|
||||
// USB pins
|
||||
inout pin_usb_p,
|
||||
inout pin_usb_n,
|
||||
|
||||
// uart pipeline in (out of the device, into the host)
|
||||
input [7:0] uart_in_data,
|
||||
input uart_in_valid,
|
||||
output uart_in_ready,
|
||||
|
||||
// uart pipeline out (into the device, out of the host)
|
||||
output [7:0] uart_out_data,
|
||||
output uart_out_valid,
|
||||
input uart_out_ready,
|
||||
|
||||
output [11:0] debug
|
||||
);
|
||||
|
||||
wire usb_p_tx;
|
||||
wire usb_n_tx;
|
||||
wire usb_p_rx;
|
||||
wire usb_n_rx;
|
||||
wire usb_tx_en;
|
||||
|
||||
//wire [3:0] debug;
|
||||
|
||||
usb_uart_core_np u_u_c_np (
|
||||
.clk_48mhz (clk_48mhz),
|
||||
.reset (reset),
|
||||
|
||||
// pins - these must be connected properly to the outside world. See below.
|
||||
.usb_p_tx(usb_p_tx),
|
||||
.usb_n_tx(usb_n_tx),
|
||||
.usb_p_rx(usb_p_rx),
|
||||
.usb_n_rx(usb_n_rx),
|
||||
.usb_tx_en(usb_tx_en),
|
||||
|
||||
// uart pipeline in
|
||||
.uart_in_data( uart_in_data ),
|
||||
.uart_in_valid( uart_in_valid ),
|
||||
.uart_in_ready( uart_in_ready ),
|
||||
|
||||
// uart pipeline out
|
||||
.uart_out_data( uart_out_data ),
|
||||
.uart_out_valid( uart_out_valid ),
|
||||
.uart_out_ready( uart_out_ready ),
|
||||
|
||||
.debug( debug )
|
||||
);
|
||||
|
||||
wire usb_p_in;
|
||||
wire usb_n_in;
|
||||
|
||||
assign usb_p_rx = usb_tx_en ? 1'b1 : usb_p_in;
|
||||
assign usb_n_rx = usb_tx_en ? 1'b0 : usb_n_in;
|
||||
|
||||
IOBUF #(
|
||||
.DRIVE(16), // Specify the output drive strength
|
||||
.IBUF_LOW_PWR("FALSE"), // Low Power - "TRUE", High Performance = "FALSE"
|
||||
.IOSTANDARD("DEFAULT"), // Specify the I/O standard
|
||||
.SLEW("FAST") // Specify the output slew rate
|
||||
) iobuf_p (
|
||||
.O( usb_p_in ), // Buffer output
|
||||
.I( usb_p_tx ), // Buffer input
|
||||
.IO( pin_usb_p ), // Buffer inout port (connect directly to top-level port)
|
||||
.T( !usb_tx_en ) // 3-state enable input, high=input, low=output
|
||||
);
|
||||
|
||||
IOBUF #(
|
||||
.DRIVE(16), // Specify the output drive strength
|
||||
.IBUF_LOW_PWR("FALSE"), // Low Power - "TRUE", High Performance = "FALSE"
|
||||
.IOSTANDARD("DEFAULT"), // Specify the I/O standard
|
||||
.SLEW("FAST") // Specify the output slew rate
|
||||
) iobuf_n (
|
||||
.O( usb_n_in ), // Buffer output
|
||||
.I( usb_n_tx ), // Buffer input
|
||||
.IO( pin_usb_n ), // Buffer inout port (connect directly to top-level port)
|
||||
.T( !usb_tx_en ) // 3-state enable input, high=input, low=output
|
||||
);
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user