EmbDev.net

Forum: FPGA, VHDL & Verilog Enhanced Tiger Single Board Computer


von Myron P. (myron_plichota)


Attached files:

Rate this post
useful
not useful
<html><head><title>TigerSBC overview</title></head><body>
Welcome to the user-defined TigerSBC DDE (Disintegrated Design 
Environment).<br>
TigerSBC is fun to program, and if you like being in the driver's seat, 
this machine might be for you.
<br><br>
TigerSBC_yyyy_mm_dd.zip is a snapshot of experimentally verified 
hardware and software source files,
for free use at one's own risk.
<br><br>
Many Python3 and Verilog source iterations led to this snapshot. 
Mistakes were made along the way, and corrected.
(See doc/koans.txt.)<br>
It is hoped that users will enjoy making and correcting their own 
mistakes, and sharing their successes.
<br><br>
This DDE implements a 12-bit 36 MHz lab/maker computer on a Lattice 
iCE40-HX8K FPGA Breakout Board, and its assembler.
<br><br>
Why 12 bits versus industry norms?<br>
1) more powerful than 8 bits<br>
2) simpler and faster than 16/32/64 bits<br>
3) object code is compact, minimizing memory overhead<br>
4) naturally matches popular 12-bit SPI ADCs and DACs for the lab/maker 
computer mission
<br><br>
TigerSBC's performance and code-density apparently rivals commodity 
MCUs.
The entire 4Kx12 code/data/io memory space is on-chip.
All reads and writes complete in one (1) clock cycle.
<br><br>
5V0 power and the host interface are provided via USB.
Memory-mapped io includes a 28-bit signed multiplier/accumulator and a 
48-bit timer.
Efficient 12-bit bit-banging parallel io, and an 8-bit mode 0 master SPI 
interface are also provided for 3V3 user io.
doc/EB85_pins.txt summarizes user io on the J2 and J4 2x20 0.1 inch 
(2.54 mm) pitch connectors.
<br><br>
Software libs and apps include Fast Fourier Transform and convolution 
DSP amenities.
A 512-point complex FFT takes ~13 ms.
An 8-point complex FFT takes ~78 us.
<br><br>
Tigerasm is written in Python3, providing a powerful syntax and 
interactive user interface.
New users should first learn how to program their own Tigerasm libs and 
apps for the existing hardware implementation.
Experienced users who speak Verilog might mutate the hardware as they 
see fit.
<br><br>
The Tiger CPU executes all (16) instructions in one (1) clock cycle. See 
Verilog/Tiger_opcodes.v for the summary.
The data and program counter stacks are register arrays with RPN 
arguments and results (smells like, but is not Forth).
Unique instruction fetch logic frequently saves clock cycles. See 
doc/instruction_fetch.txt for the commentary.
<br><br>
Tigerasm macros and procedures provide additional (multi-clock) 
operators.
Flagship examples are in lib/fft.py and apps/fft_test.py.
A simple example is in apps/hello.py.
<br><br>
A minimal DDE to use TigerSBC as-is requires:<br>
* TigerSBC_yyyy_mm_dd.zip<br>
* a Lattice iCE40-HX8K Breakout Board and included USB cable, and a 
reset switch (see doc/reset.txt)<br>
* a text editor (e.g. Notepad++)<br>
* Python3 for the Tiger assembler<br>
* a serial terminal emulator with raw file send capability for 
communication via USB/UART at 115200,8,n,1 (e.g. Tera Term)<br>
* Lattice Semiconductors Diamond to burn the existing FPGA configuration 
(pre-generated by iCEcube2 on the author's host)
<br><br>
A full DDE to create your own hardware mutations also requires:<br>
* Lattice Semiconductors iCEcube2 for FPGA design<br>
* Icarus Verilog for new module design and simulation
<br><br>
Getting started (Win10 example, Linux translations are 
straightforward):<br>
0) Unzip TigerSBC_yyyy_mm_dd.zip to your desktop and study 
doc/overview.html (this file).<br>
1) Obtain the requisite hardware and install the requisite software 
(punt to vendor doc).<br>
2) Rename asm.cmd.txt to asm.cmd.<br>
3) Rename sim/ivsim.cmd.txt to sim/ivsim.cmd.<br>
4) Connect your board (with closed reset switch connected on J2) via 
USB. Be curious about which COMx the OS decided to assign.<br>
5) Launch Diamond to burn your board as a TigerSBC with the USB/UART app 
loader:<pre>
     select Create a new blank project, click OK
     under the Device Family heading, select iCE40
     under the Device heading, select iCE40HX8K
     under the Operation heading
       select Access mode: SPI Flash Programming
       select Programming file: FPGAburn/TigerSBC_bitmap.bin
       click OK
     click the Program icon
       if failure, try hot-switching to another USB physical connection 
and retry (this happens if you have more than 1 board)
       on success, quit Diamond without saving the configuration</pre>
6) Launch a command prompt and enter these lines to test the 
assembler:<pre>
     cd Desktop/TigerSBC
     asm apps/hello.py
     save_app('apps/hello.app')
     (optional: investigate the suggested Python3 amenities)
     exit()</pre>
7) Launch the serial terminal emulator, configured 115200,8,n,1 on the 
currently-assigned COM port:<pre>
     close the reset switch
     open the reset switch, you should see
       Tiger is ready to load...
     raw file send apps/hello.app
     you should now see:
       Tiger is ready to load...done
       Hello, world!
     the red led D7 on the board should be blinking</pre>

For hints on writing your own apps, see FPGAburn/appload.py, lib/*.py, 
apps/*.py, and Tigerasm.py.
<br><br>
Tigerasm.py defines a 2-pass assembler that reads in source scripts via 
the include('filename') core procedure.
In the first pass, new symbols and (explicit) forward references are 
collected.
In the second pass, the final object code image is generated, ready to 
be saved to disk as an app (or a hex) file.
<br><br>
Although based on Python3, indentation in Tigerasm source is purely 
cosmetic.
The examples in this snapshot reflect the author's preferred style.
<br><br>
All Tigerasm symbols are global and must be unique. The order of 
encounter in source is important.
If an error occurs, inspect includes to see the list of included 
source files.
The last file in includes is where the error was detected, but not 
necessarily the root cause.
Python3 dir() and globals() list the known symbols for further 
inspection.
Tigerasm dump_ram(start_adr, end_adr) shows raw hexadecimal object code 
and data.
<br><br>
Typical Tigerasm libs and apps inherit the following host interface 
procedures from FPGAburn/appload.py:<pre>
  lbl('rx') # -> d
  # await zero-extended 8 lsbs from USB/UART

  lbl('tx') # d ->
  # transmit 8 lsbs of d to USB/UART

  lbl('tx_ascii') # adr ->
  # transmit a zero-terminated ascii string to USB/UART</pre>

Those interested in Verilog will find hints in Verilog/*.v.
Edit ram.v to correct the absolute reference to FPGAburn/ram.hex (the 
USB/UART app loader initial memory image).
iCEcube2 might then be used to build a new TigerSBC project for the 
board.
(Arcana: this snapshot required using the <right-click>Synthesis Tool: 
Synplify Pro option.)
Hardware mutations require followup changes to Verilog/TigerSBC.pcf and 
the io addresses defined in Tigerasm.py.
<br><br>
To try the Icarus Verilog simulator, launch a command prompt and enter 
these lines:<pre>
  cd Desktop/TigerSBC/sim
  ivsim spi</pre>
The simulation display was also saved to spi.log for posterity, 
try:<pre>
  copy spi.log con</pre>

For further consideration:<br>
This single-core implementation left most of the iCE40-HX8K FPGA 
resources available.<br>
Future mutations might explore parallel execution of multiple cpu+ram 
cores and their io interfaces.
<br><br>
Have fun being in the driver's seat!<br>
Myron!Plichota@at#gmail$dot%com
</body></html>

von repo? (Guest)


Rate this post
useful
not useful
well, just this ZipArchive out of nowhere?
No Code repository (git or the like) yet?
How would you deal with contributions?

Publicly accessible search engines do Not (yet) Know about this... (or 
it's my lack of SE-mojo)
But at least it's a start :-)

von myron_p (Guest)


Rate this post
useful
not useful
No wonder that search engines do not know about this since it was 
published just hours ago out of "nowhere".

For the time being, new users should evaluate the existing publication.

In the event of an active TigerSBC community emerging, we can discuss 
via email (as was done prior to github and sourceforge) how and where to 
host a "better" collection of resources.

von Myron P. (myron_plichota)


Attached files:

Rate this post
useful
not useful
Here is a spectrum analyzer app (spectrum.py) that uses the release 
libraries.
1
include('FPGAburn/appload.py') # must be on the first line
2
3
# text mode spectrum analyzer
4
# 64-point FFT
5
# harmonics 1..31 are shown as real (red) and imaginary (blue) horizontal bargraph pairs
6
# terminal should be at least 80x64
7
8
  ljmp(fwd('init'))
9
10
def12('passes', 6) # 3..9
11
def12('points', 1 << passes) # 8..512
12
include('lib/fft.py')
13
14
include('lib/spi.py')
15
include('lib/mcp3208.py')
16
17
defnum('h1', 60) # fft first harmonic Hz
18
defnum('fs', h1 * points) # adc sampling rate
19
defnum('ticks', fclk / fs) # clock ticks per sample
20
def12('kt11', int(ticks) & ALLBITS)
21
def12('kt23', int(ticks) >> 12)
22
23
lbl('wakeup'); data([0,0]) # next tl11,tl23 trigger
24
25
lbl('resync') # ->
26
# set wakeup (after inattention)
27
  lld(tl11); lit(kt11); adx(); lld(tl23); add(); lit(kt23); add()
28
  lst(wakeup+1); lst(wakeup); ret()
29
30
lbl('sync_x'); data([0])
31
#
32
lbl('sync') # ->
33
# await next wakeup, reschedule
34
    lld(wakeup); lld(tl11); neg(); adx(); lld(wakeup+1); add(); lld(tl23); inv(); add()
35
    lband(SIGNBIT); lst(sync_x); drop(); lld(sync_x); ljz(sync)
36
  lld(wakeup); lit(kt11); adx(); lld(wakeup+1); add(); lit(kt23); add()
37
  lst(wakeup+1); lst(wakeup); ret()
38
39
lbl('samples'); data([0 for n in range(points)])
40
41
lbl('capture_i'); data([0])
42
#
43
lbl('capture') # ->
44
# fill the sample buffer at nominal fs from adc1 channel 3
45
  lit(0); lst(capture_i)
46
  lcall(resync)
47
lbl('capture_again')
48
    lld(capture_i); lbxor(points); ljz(fwd('capture_done'))
49
      lcall(sync)
50
      lit(3); lit(spi_adc1); lcall(mcp3208_acquire); lbxor(SIGNBIT); lld(capture_i); last(samples)
51
      lld(capture_i); inc(); lst(capture_i)
52
      ljmp(capture_again)
53
lbl('capture_done')
54
  ret()
55
56
lbl('real_in_adr'); data ([0])
57
lbl('real_in_i'); data ([0])
58
#
59
lbl('real_in') # adr ->
60
# copy array at adr to real in bit-reversed order, imag is zeroed
61
  lst(real_in_adr); lit(0); lst(real_in_i) # ->
62
lbl('real_in_loop')
63
    lld(real_in_i); lbxor(points); ljz(fwd('real_in_done'))
64
      lld(real_in_adr); lld(real_in_i); ald() # -> d
65
      lld(real_in_i); lald(brev); last(real) # ->
66
      lit(0); lld(real_in_i); last(imag)
67
      lld(real_in_i); inc(); lst(real_in_i)
68
      ljmp(real_in_loop)
69
lbl('real_in_done')
70
  ret()
71
72
lbl('abs') # +-d -> +d
73
# absolute value of anything but SIGNBIT (the most-negative value)
74
  tt(); lband(SIGNBIT); ljz(fwd('abs_pos'))
75
    neg() # singularity: abs(SIGNBIT) == SIGNBIT, which is the wrong sign!
76
lbl('abs_pos')
77
  ret()
78
79
lbl('glyph'); data([ord('0')]) # '-'|'0'|'+'
80
81
lbl('pick_glyph') # d -> d
82
# determine hbar* plot character
83
  tt(); ljz(fwd('pick_glyph_zero'))
84
    tt(); lband(SIGNBIT); ljz(fwd('pick_glyph_pos'))
85
      lit(ord('-')); lst(glyph); ret()
86
lbl('pick_glyph_pos')
87
  lit(ord('+')); lst(glyph); ret()
88
lbl('pick_glyph_zero')
89
  lit(ord('0')); lst(glyph); ret()
90
91
lbl('hbar128') # d ->
92
# print a horizontal bar of up to 128 glyphs
93
# misbehaves if d == SIGNBIT because of the absolute value singularity
94
  lcall(pick_glyph); lcall(abs); asr(); asr(); asr(); asr(); inv() # -> lc # loop control
95
  lit(ord('\r')); lcall(tx); lit(ord('\n')); lcall(tx) # newline
96
lbl('hbar128_loop')
97
    tt(); ljz(fwd('hbar128_done'))
98
      lld(glyph); lcall(tx)
99
      inc() # -> lc'
100
      ljmp(hbar128_loop)
101
lbl('hbar128_done')
102
  drop(); ret() # ->
103
104
lbl('ansi_clear'); ascii('\x1b[2J\x1b[H')
105
lbl('ansi_red'); ascii('\x1b[31m')
106
lbl('ansi_blue'); ascii('\x1b[34m')
107
lbl('ansi_default'); ascii('\x1b[0m')
108
109
lbl('plot_spectrum') # ->
110
# plot real (red) and imaginary (blue) horizontal bars for each unexceptional fft harmonic
111
  lit(ansi_clear); lcall(tx_ascii) # clear screen, home cursor top left
112
  lit(1) # -> harmonic
113
lbl('plot_spectrum_loop')
114
    tt(); lbxor(points >> 1); ljz(fwd('plot_spectrum_done'))
115
      lit(ansi_red); lcall(tx_ascii); tt(); lald(real); lcall(hbar128)
116
      lit(ansi_blue); lcall(tx_ascii); tt(); lald(imag); lcall(hbar128)
117
      inc() # -> harmonic'
118
      ljmp(plot_spectrum_loop)
119
lbl('plot_spectrum_done')
120
  drop(); lit(ansi_default); ljmp(tx_ascii) # ->
121
122
lbl('init')
123
  lcall(set_brev)
124
lbl('doit')
125
    lcall(rx); drop() # await a keystroke
126
#    lit(cos); lcall(real_in);
127
#    lit(sin); lcall(real_in);
128
    lcall(capture); lit(samples); lcall(real_in);
129
    lcall(fft); lcall(plot_spectrum)
130
    ljmp(doit)
131
132
lbl('app_end') # must be on the last line

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.