Proyek | SoC keempat ditulis dalam VHDL |
---|---|
Pengarang | Richard James Howe |
Hak cipta | 2013-2019 Richard Howe |
Lisensi | MIT/LGPL |
[email protected] |
Proyek ini mengimplementasikan komputer tumpukan kecil yang dirancang untuk mengeksekusi Forth berdasarkan CPU J1. Prosesor telah ditulis ulang dalam VHDL dari Verilog, dan sedikit diperluas.
Tujuan dari proyek ini adalah sebagai berikut:
Ketiganya telah selesai.
Prosesor H2, seperti J1, adalah prosesor berbasis tumpukan yang menjalankan set instruksi yang khususnya cocok untuk FORTH.
Target saat ini adalah papan Nexys3, dengan Xilinx Spartan-6 XC6LX16-CS324 FPGA, papan baru akan ditargetkan di masa depan karena papan ini mencapai akhir masa pakainya. VHDL ditulis dengan cara yang umum, dengan komponen perangkat keras disimpulkan dan bukan dibuat secara eksplisit, hal ini akan membuat kode tersebut cukup portabel, meskipun antarmuka ke komponen papan Nexys3 khusus untuk periferal pada papan tersebut.
Video pelaksanaan proyek, pada perangkat keras, dapat dilihat di sini:
SoC juga dapat disimulasikan dengan simulator yang ditulis dalam C, seperti yang ditunjukkan di bawah ini:
Arsitektur Sistemnya adalah sebagai berikut:
Lisensi yang digunakan oleh proyek ini beragam dan berdasarkan per file. Untuk kode saya, saya menggunakan lisensi MIT - jadi silakan gunakan sesuai keinginan. Lisensi lain yang digunakan adalah LGPL dan lisensi Apache 2.0, lisensi tersebut terbatas pada modul tunggal sehingga dapat dihapus jika Anda tidak menyukai kode LGPL.
Satu-satunya papan target yang tersedia saat ini adalah Nexys3, hal ini akan berubah di masa depan karena papan tersebut saat ini berada pada Akhir Masa Pakainya. Papan berikutnya yang ingin saya dukung adalah penerusnya, Nexys 4, dan myStorm BlackIce (https://mystorm.uk/). Papan myStorm menggunakan rantai alat sumber terbuka sepenuhnya untuk sintesis, tempat dan rute, serta pembuatan file bit.
Build telah diuji pada Debian Linux, versi 8.
Anda akan membutuhkan:
Perangkat keras:
Xilinx ISE dapat (atau bisa saja) diunduh secara gratis, tetapi memerlukan registrasi. ISE harus berada di jalur Anda:
PATH=$PATH:/opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64;
PATH=$PATH:/opt/Xilinx/14.7/ISE_DS/ISE/lib/lin64;
Untuk membuat rantai alat berbasis C:
make embed.hex
Untuk membuat file bit yang dapat di-flash ke papan target:
make simulation synthesis implementation bitfile
Untuk mengunggah bitfile ke papan target:
make upload
Untuk melihat bentuk gelombang yang dihasilkan oleh "make simulasi":
make viewer
Simulator CLI berbasis C dapat dipanggil dengan:
make run
Yang akan merakit file sumber H2 Forth embed.fth, dan menjalankan file objek yang dirakit di bawah simulator H2 dengan debugger diaktifkan. Simulator grafis dapat dijalankan dengan:
make gui-run
Yang membutuhkan freeglut serta kompiler C.
Proyek J1 asli tersedia di:
Proyek ini menargetkan inti J1 asli dan menyediakan implementasi eForth (ditulis menggunakan Gforth untuk kompilasi meta/kompilasi silang ke inti J1). Ini juga menyediakan simulator untuk sistem yang ditulis dalam C.
Interpreter eForth yang menjadi dasar pembuatan meta-compiler dapat ditemukan di:
Prosesor H2 dan periferal terkait sekarang cukup stabil, namun sumbernya selalu menjadi panduan pasti mengenai bagaimana instruksi dan periferal berperilaku, serta peta register.
Ada beberapa modifikasi pada CPU J1 yang antara lain:
CPU H2 berperilaku sangat mirip dengan CPU J1, dan PDF J1 dapat dibaca untuk lebih memahami prosesor ini. Prosesornya 16-bit dengan instruksi yang mengambil satu siklus clock. Sebagian besar kata Forth primitif juga dapat dieksekusi dalam satu siklus, satu pengecualian adalah store ("!"), yang dibagi menjadi dua instruksi.
CPU memiliki status berikut di dalamnya:
Memuat dan menyimpan ke dalam blok RAM yang menampung program H2 membuang bit terendah, setiap operasi memori lainnya menggunakan bit yang lebih rendah (seperti lompatan dan memuat serta menyimpan ke periferal Input/Output). Hal ini agar aplikasi dapat menggunakan bit terendah untuk operasi karakter ketika mengakses RAM program.
Set instruksi diterjemahkan dengan cara berikut:
+---------------------------------------------------------------+
| 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 | ALU OPERATION |T2N|T2R|N2A|R2P| 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)
Semua operasi ALU menggantikan T:
Nilai | Operasi | Keterangan |
---|---|---|
0 | T | Bagian Atas Tumpukan |
1 | N | Salin T ke N |
2 | T+N | Tambahan |
3 | T & N | Sedikit demi sedikit DAN |
4 | Robek | Sedikit demi sedikit ATAU |
5 | T ^ N | XOR sedikit demi sedikit |
6 | ~T | Inversi Bitwise |
7 | T = N | Tes kesetaraan |
8 | N < T | Perbandingan yang ditandatangani |
9 | N >> T | Pergeseran Kanan yang Logis |
10 | T - 1 | Pengurangan |
11 | R | Tumpukan pengembalian teratas |
12 | [T] | Muat dari alamat |
13 | N << T | Pergeseran Kiri Logis |
14 | kedalaman | Kedalaman tumpukan |
15 | Tidak kamu< T | Perbandingan tanpa tanda tangan |
16 | Atur Status CPU | Aktifkan interupsi |
17 | Dapatkan Status CPU | Apakah interupsi aktif? |
18 | kedalaman | Kedalaman stk kembali |
19 | 0= | T == 0? |
20 | ID CPU | Pengenal CPU |
21 | HARFIAH | Instruksi Internal |
Register yang diberi awalan 'o' adalah register keluaran, sedangkan register yang diberi awalan 'i' adalah register masukan. Register dibagi menjadi bagian register masukan dan keluaran dan alamat register masukan dan keluaran tidak bersesuaian satu sama lain dalam semua kasus.
Periferal berikut telah diimplementasikan dalam SoC VHDL untuk berinteraksi dengan perangkat di papan Nexys3:
SoC juga dilengkapi serangkaian interupsi terbatas yang dapat diaktifkan atau dinonaktifkan.
Peta register keluaran:
Daftar | Alamat | Keterangan |
---|---|---|
oUart | 0x4000 | Daftar UART |
oVT100 | 0x4002 | Tulis Terminal VT100 |
oLED | 0x4004 | keluaran LED |
oTimerCtrl | 0x4006 | Kontrol pengatur waktu |
oMemDout | 0x4008 | Keluaran Data Memori |
oMemControl | 0x400A | Kontrol Memori / Alamat Hai |
oMemAddrRendah | 0x400C | Alamat Memori Lo |
o7SegLED | 0x400E | 4 x LED 7 Tampilan segmen |
oIrcMask | 0x4010 | Masker Interupsi CPU |
oUartBaudTx | 0x4012 | Pengaturan Jam UART Tx Baud |
oUartBaudRx | 0x4014 | Pengaturan Jam UART Rx Baud |
Register masukan:
Daftar | Alamat | Keterangan |
---|---|---|
iUart | 0x4000 | Daftar UART |
iVT100 | 0x4002 | Status terminal & Papan Ketik PS/2 |
iSwitch | 0x4004 | Tombol dan sakelar |
iTimerDin | 0x4006 | Nilai Pengatur Waktu Saat Ini |
iMemDin | 0x4008 | Masukan Data Memori |
Deskripsi register berikut harus dibaca secara berurutan dan menjelaskan cara kerja periferal juga.
UART dengan baud rate dan format tetap (115200, 8 bit, 1 stop bit) ada di SoC. UART memiliki FIFO kedalaman 8 pada saluran RX dan TX. Kontrol UART dibagi menjadi oUart dan iUart.
Untuk menulis nilai ke UART, tegaskan TXWE bersama dengan memasukkan data ke dalam TXDO. Status FIFO dapat dianalisis dengan melihat register iUart.
Untuk membaca suatu nilai dari UART: iUart dapat dicek apakah ada data di FIFO, jika diassert RXRE di register oUart, pada siklus clock berikutnya data akan ada di register iUart.
Baud rate UART dapat diubah dengan membangun kembali proyek VHDL, panjang bit, bit paritas dan bit stop hanya dapat diubah dengan modifikasi uart.vhd
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| X | X |TXWE| X | X |RXRE| X | X | TXDO |
+-------------------------------------------------------------------------------+
TXWE: UART TX Write Enable
RXRE: UART RX Read Enable
TXDO: UART TX Data Output
Perangkat Teks VGA mengemulasi terminal dimana pengguna dapat berbicara dengan menulis ke register oVT100. Ini mendukung subset dari fungsionalitas terminal VT100. Antarmuka berperilaku seperti menulis ke UART dengan sinyal sibuk dan sinyal kontrol yang sama. Input diambil dari keyboard PS/2 yang tersedia di board, ini berperilaku seperti mekanisme RX pada UART.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| X | X |TXWE| X | X |RXRE| X | X | TXDO |
+-------------------------------------------------------------------------------+
TXWE: VT100 TX Write Enable
RXRE: UART RX Read Enable
TXDO: UART TX Data Output
Pada board Nexys3 terdapat kumpulan LED yang terletak di sebelah sakelar, LED ini dapat dinyalakan (1) atau dimatikan (0) dengan menulis ke LEDO. Setiap LED di sini berhubungan dengan sakelar di sebelahnya.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| X | X | X | X | X | X | X | X | LEDO |
+-------------------------------------------------------------------------------+
LEDO: LED Output
Timer dapat dikontrol oleh register oTimerCtrl, ini adalah timer 13-bit yang berjalan pada 100MHz, secara opsional dapat menghasilkan interupsi dan hitungan internal timer saat ini dapat dibaca kembali dengan register iTimerDin.
Pengatur waktu dihitung setelah bit TE ditetapkan, setelah pengatur waktu mencapai nilai TCMP, pengatur waktu akan membungkusnya dan secara opsional dapat menghasilkan interupsi dengan menyatakan INTE. Ini juga mengaktifkan garis Q dan NQ yang keluar dari pengatur waktu dan diarahkan ke pin di papan (lihat file batasan top.ucf untuk pinnya).
Timer dapat direset dengan menulis ke RST.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| TE | RST|INTE| TCMP |
+-------------------------------------------------------------------------------+
TE: Timer Enable
RST: Timer Reset
INTE: Interrupt Enable
TCMP: Timer Compare Value
Inti H2 memiliki mekanisme interupsi, interupsi harus diaktifkan atau dinonaktifkan dengan instruksi. Setiap interupsi dapat ditutup dengan sedikit di IMSK untuk mengaktifkan interupsi spesifik tersebut. Angka '1' dalam sedikit IMSK mengaktifkan interupsi spesifik tersebut, yang akan dikirimkan ke CPU jika interupsi diaktifkan di dalamnya.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| X | X | X | X | X | X | X | X | IMSK |
+-------------------------------------------------------------------------------+
IMSK: Interrupt Mask
Register ini digunakan untuk mengatur baud dan frekuensi jam sampel untuk transmisi saja.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| BTXC |
+-------------------------------------------------------------------------------+
BTXC: Baud Clock Settings
Register ini digunakan untuk mengatur baud dan frekuensi jam sampel untuk penerimaan saja.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| BRXC |
+-------------------------------------------------------------------------------+
BRXC: Baud Clock Settings
Data yang akan dikeluarkan ke alamat yang dipilih ketika write aktifkan (WE) dikeluarkan di oMemControl.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| Data Ouput |
+-------------------------------------------------------------------------------+
Register ini berisi register kontrol untuk memori onboard pada board Nexys3. Papan tersebut berisi tiga perangkat memori, dua perangkat memori non-volatil, dan satu perangkat berbasis RAM yang mudah menguap. Dua perangkat yang dapat diakses melalui antarmuka SRAM sederhana (satu M45W8MW16 yang mudah menguap, satu yang non-volatil - NP8P128A13T1760E) keduanya dapat diakses, yang ketiga adalah perangkat memori berbasis SPI, NP5Q128A13ESFC0E) dan saat ini tidak dapat diakses.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| OE | WE | RST|WAIT| RCS| FCS| Address Hi |
+-------------------------------------------------------------------------------+
OE: Output Enable - enable reading from current address into iMemDin
WE: Write Enable - enable writing oMemDout into ram at current address
RST: Reset the Flash memory controller
RCS: RAM Chip Select, Enable Volatile Memory
FCS: Flash Chip Select, Enable Non-Volatile Memory
Address Hi: High Bits of RAM address
OE dan WE saling lepas, jika keduanya diatur maka tidak ada pengaruhnya.
Pengontrol memori sedang dalam pengembangan aktif, dan antarmukanya mungkin berubah.
Ini adalah bit alamat yang lebih rendah dari RAM.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| Address Lo |
+-------------------------------------------------------------------------------+
Pada papan Nexys3 terdapat kumpulan tampilan 7 segmen, dengan titik desimal (sebenarnya 8 segmen), yang dapat digunakan untuk keluaran numerik. Segmen LED tidak dapat ditangani secara langsung. Sebaliknya nilai yang disimpan di L8SD dipetakan ke nilai tampilan heksadesimal (atau nilai BCD, tetapi ini memerlukan regenerasi SoC dan modifikasi generik di VHDL).
Nilai '0' sesuai dengan angka nol yang ditampilkan pada segmen LED, '15' dengan 'F', dan sebagainya.
Ada 4 tampilan berturut-turut.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| L7SD0 | L7SD1 | L7SD2 | L7SD3 |
+-------------------------------------------------------------------------------+
L7SD0: LED 7 Segment Display (leftmost display)
L7SD1: LED 7 Segment Display
L7SD2: LED 7 Segment Display
L7SD3: LED 7 Segment Display (right most display)
Register iUart bekerja sama dengan register oUart. Status FIFO yang menyangga transmisi dan penerimaan byte tersedia di register iUart, serta byte apa pun yang diterima.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| X | X | X |TFFL|TFEM| X |RFFL|RFEM| RXDI |
+-------------------------------------------------------------------------------+
TFFL: UART TX FIFO Full
TFEM: UART TX FIFO Empty
RFFL: UART RX FIFO Full
RFEM: UART RX FIFO Empty
RXDI: UART RX Data Input
Register iVT100 bekerja bersama dengan register oVT100. Status FIFO yang menyangga transmisi dan penerimaan byte tersedia di register iVT100, serta byte apa pun yang diterima. Ia bekerja sama dengan register iUart/oUart.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| X | X | X |TFFL|TFEM| X |RFFL|RFEM| 0 | ACHR |
+-------------------------------------------------------------------------------+
TFFL: VGA VT100 TX FIFO Full
TFEM: VGA VT100 TX FIFO Empty
RFFL: PS2 VT100 RX FIFO Full
RFEM: PS2 VT100 RX FIFO Empty
ACHR: New character available on PS2 Keyboard
Register ini berisi nilai penghitung waktu saat ini.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| X | X | X | TCNT |
+-------------------------------------------------------------------------------+
TCNT: Timer Counter Value
iSwitches berisi jalur input dari berbagai sumber. Tombol-tombolnya (BUP, BDWN, BLFT, BRGH, dan BCNT) berhubungan dengan D-Pad pada board Nexys3. Sakelar (TSWI) adalah yang disebutkan di oLed, masing-masing memiliki LED di sebelahnya.
Sakelar dan tombol sudah di-debounce di perangkat keras sehingga tidak perlu diproses lebih lanjut setelah dibaca dari register ini.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| X | X | X | BUP|BDWN|BLFT|BRGH|BCNT| TSWI |
+-------------------------------------------------------------------------------+
BUP: Button Up
BDWN: Button Down
BLFT: Button Left
BRGH: Button Right
BCNT: Button Center
TSWI: Two Position Switches
Input memori, baik dari SRAM atau Flash, diindeks oleh oMemControl dan oMemAddrLow. Saat membaca dari flash, ini mungkin sebenarnya informasi status atau informasi dari tabel kueri.
+-------------------------------------------------------------------------------+
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------------------------------------------------------+
| Data Input |
+-------------------------------------------------------------------------------+
Rutinitas layanan interupsi berikut ditentukan:
Nama | Nomor | Keterangan |
---|---|---|
isrTidak Ada | 0 | Tidak digunakan |
isrRxFifoTidakKosong | 1 | UART RX FIFO Tidak Kosong |
isrRxFifoPenuh | 2 | UART RX FIFI Penuh |
isrTxFifoTidakKosong | 3 | UART TX FIFO Tidak Kosong |
isrTxFifoFull | 4 | UART TX FIFO Penuh |
isrKbdBaru | 5 | Karakter Keyboard PS/2 Baru |
isrTimer | 6 | Penghitung Waktu |
isrDPadButton | 7 | Status Perubahan Tombol D-Pad Apa Pun |
Ketika interupsi terjadi, dan interupsi diaktifkan di dalam prosesor, maka panggilan ke lokasi di memori dilakukan - lokasi tersebut sama dengan nomor ISR. ISR dengan nomor '4' akan melakukan panggilan (bukan lompatan) ke lokasi '4' dalam memori, misalnya.
Interupsi memiliki latensi minimal 4-5 siklus sebelum ditindaklanjuti, terdapat penundaan dua hingga tiga siklus pada penangan permintaan interupsi, maka pemanggilan ke lokasi ISR di memori harus dilakukan, kemudian pemanggilan ke lokasi ISR di memori harus dilakukan. kata yang mengimplementasikan ISR itu sendiri.
Jika dua interupsi terjadi secara bersamaan, maka diproses dari nomor interupsi terendah hingga tertinggi.
Interupsi hilang ketika terjadi interupsi dengan nomor yang sama namun belum diproses.
Simulator berbasis Disassembler dan C untuk H2 ada dalam satu program (lihat h2.c). Simulator ini melengkapi bangku tes VHDL tb.vhd dan bukan penggantinya. Kompiler meta berjalan di atas penerjemah eForth dan terkandung dalam file embed.c dan embed.blk. Meta-compiler (bahasa Forth untuk cross-compiler) adalah program Forth yang digunakan untuk membuat image eForth yang berjalan pada target.
Rantai alat saat ini sedang mengalami perubahan, ke depan kemungkinan akan ada lebih banyak integrasi antara h2.c dan embed.c, serta mengubah Mesin Virtual Tersemat menjadi mesin yang lebih mirip dengan CPU H2 dengan tujuan jangka panjang untuk membuat hosting mandiri sistem.
Untuk membangun keduanya, diperlukan compiler C, target build "h2" akan membuat executable, h2, dan "embed" akan membuat meta-compiler:
make h2 embed
Dan itu dapat dijalankan pada file sumber embed.fth dengan target make:
make run
File make tidak diperlukan:
Linux:
cc -std=c99 h2.c -o h2 # To build the h2 executable
cc -std=c99 embed.c -o embed # To build the embed VM executable
./embed embed.blk embed.hex embed.fth # Create the target eForth image
./h2 -h # For a list of options
./h2 -r embed.hex # Run the assembled file
Windows:
gcc -std=c99 h2.c -o h2.exe # Builds the h2.exe executable
gcc -std=c99 embed.c -o embed.exe # Builds the embed.exe executable
embed.exe embed.blk embed.hex embed.fth # Create the target eForth iamge
h2.exe -h # For a list of options
h2.exe -r embed.hex # Run the assembled file
Daftar opsi baris perintah yang tersedia:
- stop processing options, following arguments are files
-h print a help message and exit
-v increase logging level
-d disassemble input files (default)
-D full disassembly of input files
-T Enter debug mode when running simulation
-r run hex file
-L # load symbol file
-s # number of steps to run simulation (0 = forever)
-n # specify NVRAM block file (default is nvram.blk)
file* file to process
Program ini dirilis di bawah lisensi MIT, silakan gunakan dan modifikasi sesuka Anda. Dengan sedikit modifikasi seharusnya dapat merakit program untuk inti J1 asli.
Kompiler meta berjalan di atas mesin virtual yang disematkan, ini adalah mesin virtual 16-bit yang awalnya diturunkan dari CPU H2. Proyek ini mencakup skema kompilasi meta yang memungkinkan gambar eForth menghasilkan gambar eForth baru dengan modifikasi. Sistem tersebut telah diadaptasi untuk digunakan dengan H2, yang menggantikan kompiler silang yang ditulis dalam C, yang memungkinkan gambar pertama untuk H2 dibuat.
Meta-compiler adalah program Forth biasa, yang terdapat di dalam embed.fth. Program meta-compiler Forth kemudian digunakan untuk membangun image eForth yang mampu berjalan pada target H2.
Untuk informasi lebih lanjut tentang kompilasi meta di Forth, lihat:
Pembongkaran mengambil file teks yang berisi program rakitan, yang terdiri dari angka heksadesimal 16-bit. Ia kemudian mencoba membongkar instruksinya. Itu juga dapat dimasukkan ke dalam file simbol yang dapat dihasilkan oleh assembler dan mencoba menemukan lokasi lompatan dan panggilan yang dituju.
Disassembler digunakan oleh skrip tcl yang disebut GTKwave, yang mengubah jejak instruksi H2 dari serangkaian angka menjadi instruksi dan tujuan cabang yang diwakilinya. Ini membuat proses debug VHDL menjadi lebih mudah.
Jejak ungu menunjukkan instruksi yang telah dibongkar.
Simulator di C mengimplementasikan inti H2 dan sebagian besar SoC. IO untuk simulator tidak akurat dalam siklus, namun dapat digunakan untuk menjalankan dan men-debug program dengan hasil yang sangat mirip dengan perilaku perangkat keras. Ini jauh lebih cepat daripada membangun kembali file bit yang digunakan untuk mem-flash FPGA.
Simulator ini juga menyertakan debugger, yang dirancang serupa dengan program DEBUG.COM yang tersedia di DOS. Debugger dapat digunakan untuk membongkar bagian memori, memeriksa status periferal, dan membuang bagian memori ke layar. Ini juga dapat digunakan untuk menyetel breakpoint, satu langkah, dan menjalankan kode hingga breakpoint tercapai.
Untuk menjalankan debugger, file hex atau file sumber harus diberikan:
# -T turns debugging mode on
./h2 -T -r file.hex # Run simulator
Kedua mode operasi dapat ditambah dengan file simbol, yang mencantumkan lokasi variabel, label, dan fungsi dengan inti yang dirakit.
Ketika opsi "-T" diberikan, mode debug akan dimasukkan sebelum simulasi dijalankan. Sebuah prompt akan muncul dan baris perintah akan terlihat seperti ini:
$ ./h2 -T -R h2.fth
Debugger running, type 'h' for a list of command
debug>
Break point dapat diatur secara simbolis atau berdasarkan lokasi program, perintah 'b' digunakan untuk mengatur breakpoint:
Angka dapat dimasukkan dalam oktal (diawali angka dengan '0'), heksadesimal (diawali dengan '0x') atau dalam desimal. Sebagai contoh, tiga perintah debug berikut semuanya menyetel breakpoint di lokasi yang sama:
debug> b 16
debug> b 0x10
debug> b 020
'k' dapat digunakan untuk membuat daftar break point saat ini yang ditetapkan:
debug> k
0x0010
Ini menetapkan breakpoint ketika fungsi "kunci?" disebut:
debug> b key?
Fungsi dan label dapat dihentikan, hal ini memerlukan file simbol untuk ditentukan pada baris perintah atau dirakit dan dijalankan untuk digunakan pada file sumber, bukan file hex. File simbol dapat digunakan pada file sumber atau hex.
Untuk satu langkah perintah 's' dapat diberikan, meskipun tidak banyak yang akan terjadi jika tracing dimatikan (tracing dinonaktifkan secara default). Pelacakan dapat diaktifkan atau dinonaktifkan dengan perintah 't':
debug> s
debug> s
debug> t
trace on
debug> s
0001: pc(089a) inst(4889) sp(0) rp(0) tos(0000) r(0000) call 889 init
debug> s
0002: pc(0889) inst(807a) sp(0) rp(1) tos(0000) r(089b) 7a
debug> s
0003: pc(088a) inst(e004) sp(1) rp(1) tos(007a) r(089b) 6004
Dianjurkan untuk mematikan penelusuran saat menjalankan perintah 'c', atau lanjutkan.
'.' perintah dapat digunakan untuk menampilkan keadaan internal inti H2:
debug> .
Return Stack:
0000: 0000 08aa 0883 017b 0000 031b 0000 ffb0 0000 02eb ffb5 0210 0167 0167
0167 0167
0010: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000
Variable Stack:
tos: 0000
0001: 0000 0000 0000 0001 0004 0005 0000 ffb0 0000 0000 0000 0000 0000 0000
0000 0000
0011: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000
pc: 0538
rp: 0001
dp: 0000
ie: false
Dan perintah 'p' dapat digunakan untuk menampilkan keadaan periferal yang disimulasikan:
debug> p
LEDS: 00
VGA Cursor: 0005
VGA Control: 007a
Timer Control: 8032
Timer: 001b
IRC Mask: 0000
UART Input: 6c
LED 7seg: 0005
Switches: 00
LFSR: 40ba
Waiting: false
Untuk daftar perintah lengkap, gunakan perintah 'h'.
Cara lain untuk memasuki mode debug termasuk memasukkan direktif assembler ".break" ke dalam kode sumber (ini hanya berfungsi jika perintah assemble dan run digunakan pada file sumber, bukan pada file hex), dan menekan karakter escape saat simulator berada mencoba membaca data melalui simulasi keyboard UART atau PS/2 (pelarian akan tetap diteruskan ke simulator, tetapi juga mengaktifkan mode debug).
Sebuah program terpisah dapat dikompilasi, diuji di Linux dan Windows. Ini mensimulasikan periferal papan Nexys3 yang berinteraksi dengan SoC, tetapi menyediakan lingkungan grafis, tidak seperti utilitas baris perintah. Lebih mudah untuk berinteraksi dengan perangkat dan melihat apa yang dilakukannya, namun sesi debugging kurang terkontrol. Itu membutuhkan kekenyangan gratis.
Di bawah ini adalah gambar sesi yang sedang berjalan di simulator GUI:
Bangunan dapat dilakukan dengan
make gui
Dan berjalan:
make gui-run
Atau:
./gui h2.hex (on Linux)
gui.exe h2.hex (on Windows)
Build Linux seharusnya berfungsi ketika paket pengembangan gratis glut diinstal pada sistem Anda, build Windows mungkin memerlukan perubahan pada sistem build dan/atau instalasi manual kompiler, pustaka, dan header.
Peta kunci saat ini adalah:
Up Activate Up D-Pad Button, Release turns off
Down Activate Down D-Pad Button, Release turns off
Left Activate Left D-Pad Button, Release turns off
Right Activate Right D-Pad Button, Release turns off
F1 - F8 Toggle Switch On/Off, F1 is left most, F8 Right Most
F11 Toggle UART/PS2 Keyboard Input
F12 Toggle Debugging Information
Escape Quit simulator
Semua tombol keyboard lainnya dialihkan ke input Keyboard UART atau PS/2.
Tombol Switch dan D-Pad dapat diklik untuk menyalakannya, switch menyala dengan klik kiri dan mati dengan klik kanan. Tombol D-Pads menyala dengan satu klik di atasnya dan mati dengan melepaskan tombol di mana saja di layar.
Komponen VHDL yang digunakan dalam sistem ini dirancang agar dapat digunakan kembali dan portabel di berbagai rantai alat dan vendor. Komponen perangkat keras, seperti blok RAM, disimpulkan dan tidak dipakai secara eksplisit. Komponennya juga dibuat seumum mungkin, dengan sebagian besar memiliki lebar yang dapat dipilih. Hal ini akan dilakukan secara ekstrim, namun sayangnya banyak vendor masih belum mendukung standar VHDL-2008.
Mengajukan | Lisensi | Pengarang | Keterangan |
---|---|---|---|
util.vhd | MIT | Richard J Howe | Kumpulan komponen generik |
h2.vhd | MIT | Richard J Howe | Inti CPU H2 Keempat |
uart.vhd | MIT | Richard J Howe | UART TX/RX (Waktu pengoperasian dapat disesuaikan) |
vga.vhd | LGPL 3.0 | Javier V Garcia | Mode Teks Tampilan VGA 80x40 |
Richard J Howe | (dan emulator terminal VT100) | ||
kbd.vhd | ??? | Scott Larson | Papan Ketik PS/2 |
Bahasa seperti Forth semu yang digunakan sebagai assembler dijelaskan di atas, aplikasi yang benar-benar berjalan pada inti Forth itu sendiri merupakan penerjemah Forth. Bagian ini menjelaskan juru bahasa Keempat yang berjalan pada H2 Core, yang terdapat dalam embed.fth.
YANG HARUS DILAKUKAN:
Ada beberapa bahasa yang digunakan dalam proyek ini, semuanya sangat berbeda satu sama lain dan memerlukan standar pengkodean dan panduan gaya tersendiri.
Nama sinyal umum:
clk - The system clock
rst - A reset signal for the module
we - Write Enable
re - Read Enable
di - Data In
din - Data In
do - Data Out
dout - Data Out
control - Generally an input to a register, the documentation
for the module will need to be consulted to find out
what each bit means
signal_we - The write enable for 'signal'
signal_i - This is an input signal
signal_o - This is an output signal
Umumnya penggunaan akhiran "_i" dan "_o" tidak digunakan, modul dibuat pendek dan nama dipilih sehingga maknanya jelas. Aturan ini mungkin akan ditinjau kembali setelah proyek berkembang.
Komponen harus:
constant N: positive := 4;
signal a: std_logic_vector(N - 1 downto 0) := (others => '1');
Alih-alih:
signal a: std_logic_vector(3 downto 0) := x"F";
Aturan gayanya adalah sebagai berikut:
Contoh pedoman pemformatan, ini menjelaskan register lebar sembarang sederhana:
-- Lots of comments about what the unit does should go
-- here. Describe the waveforms, states and use ASCII
-- art where possible.
library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all; -- numeric_std not std_logic_arith
entity reg is -- generic and port indented one tab, their parameters two
generic (
N: positive); -- Generic parameters make for a generic component
port (
clk: in std_logic; -- standard signal names
rst: in std_logic; --
we: in std_logic;
di: in std_logic_vector(N - 1 downto 0);
do: out std_logic_vector(N - 1 downto 0)); -- note the position of ");
end entity; -- "end entity", not "end reg"
architecture rtl of reg is
signal r_c, r_n: std_logic_vector(N - 1 downto 0) := (others => '0');
begin
do <= r_c;
process(rst, clk)
begin
if rst = '1' then -- asynchronous reset
r_c <= (others => '0');
elsif rising_edge(clk) then -- rising edge, not "clk'event and clk = '1'"
r_c <= r_n;
end if;
end process;
process(r_c, di, we)
begin
r_n <= r_c;
if we = '1' then
r_n <= di;
end if;
end process;
end; -- "end" or "end architecture"
Ada cukup banyak kode C yang digunakan dalam proyek ini, digunakan untuk membuat rantai alat untuk inti H2 dan untuk mensimulasikan sistem.
Tidak ada yang terlalu mengejutkan tentang kode C di sini, jadi beberapa pengecualian harus ditangani.
static const char *alu_op_to_string(uint16_t instruction) {
/* notice also that the 'case' clauses are inline with the
* switch selector */
switch (ALU_OP(instruction)) {
case ALU_OP_T: return "T";
case ALU_OP_N: return "N";
case ALU_OP_T_PLUS_N: return "T+N";
case ALU_OP_T_AND_N: return "T&N";
case ALU_OP_T_OR_N: return "T|N";
case ALU_OP_T_XOR_N: return "T^N";
case ALU_OP_T_INVERT: return "~T";
case ALU_OP_T_EQUAL_N: return "N=T";
case ALU_OP_N_LESS_T: return "T>N";
case ALU_OP_N_RSHIFT_T: return "N>>T";
case ALU_OP_T_DECREMENT: return "T-1";
case ALU_OP_R: return "R";
case ALU_OP_T_LOAD: return "[T]";
case ALU_OP_N_LSHIFT_T: return "N<N";
case ALU_OP_ENABLE_INTERRUPTS: return "seti";
case ALU_OP_INTERRUPTS_ENABLED: return "iset?";
case ALU_OP_RDEPTH: return "rdepth";
case ALU_OP_T_EQUAL_0: return "0=";
case ALU_OP_CPU_ID: return "cpu-id";
default: return "unknown";
}
}
if (foo)
bar();
else
baz();
picocom --omap delbs -b 115200 -e b /dev/ttyUSB1