Eksperimen pertama menggunakan protokol streaming pada contoh CPU dan komunikasi prosesor di Redd FPGA



Pada artikel sebelumnya, kami sudah bertemu dengan bus Avalon-MM , di mana MM adalah singkatan dari Memory Mapped, yang diproyeksikan ke memori. Ban ini cukup serbaguna. Beberapa master (Master) dan beberapa perangkat slave dapat dihubungkan ke sana. Kami sudah menghubungkan dua perangkat terkemuka sekaligus (Master Instruksi dan Data Master), karena prosesor NIOS II memiliki arsitektur Harvard, sehingga perintah dan bus data berbeda, tetapi banyak penulis menghubungkannya ke perangkat yang sama untuk menyederhanakan pengembangan perangkat lunak dari luar. ke bus.

Jika sebuah blok di bus memiliki fungsi akses memori langsung (DMA), itu juga akan berisi master untuk bus.

Sebenarnya, ketidaknyamanan utama ban ini didasarkan pada fakta ini (banyak pengikut terkemuka, banyak pengikut). Ketika kami merancang budak kami, kami harus memecahkan kode alamatnya. Ketika saya kebetulan menjadi pemimpin saya, ada lebih banyak keributan dengan arbitrasi. Tetapi benang merah melalui seluruh seri artikel adalah pernyataan bahwa pengembangan untuk Redd adalah bagian tambahan dari proyek, seharusnya tidak memerlukan terlalu banyak pekerjaan. Dan jika kita dapat membebaskan diri kita dari rutinitas, kita harus membebaskan diri dari itu.



Semua artikel siklus:

  1. Pengembangan "firmware" paling sederhana untuk FPGA yang dipasang di Redd, dan debugging menggunakan tes memori sebagai contoh
  2. Pengembangan "firmware" paling sederhana untuk FPGA yang dipasang di Redd. Bagian 2. Kode program
  3. Pengembangan intinya sendiri untuk ditanamkan dalam sistem prosesor berbasis FPGA
  4. Pengembangan program untuk prosesor pusat Redd pada contoh akses ke FPGA

Dokumen Spesifikasi Antarmuka Avalon sudah diketahui oleh kami (secara umum, saya tidak memberikan tautan langsung, karena selalu berubah, sehingga seluruh jaringan dipenuhi artikel dengan tautan mati, lebih mudah untuk menemukan posisi saat ini dengan mengarahkan nama ke mesin pencari) melaporkan bahwa selain bus Avalon-MM , ada juga bus Avalon-ST , di mana ST adalah singkatan dari Stream, yaitu streaming. Faktanya adalah bahwa sangat sering data yang dikirimkan memiliki struktur aliran. Ya, bahkan sektor klasik hard drive. Ini memiliki ukuran tetap. Itu harus diteruskan dari awal sampai akhir. Bahkan jika kita mempertimbangkannya di area yang bisa dialamatkan, maka alamat akan meningkat secara linear. Dan jika Anda menggunakan blok FIFO untuk penyimpanan, maka alamat di dalamnya sepenuhnya tersembunyi dari kami. Memang, tapi bekerja dengan mereka bukan urusan kita.

Hal yang sama berlaku untuk banyak data streaming lainnya: mereka selalu pergi dari awal hingga akhir, ditempatkan dalam repositori berurutan. Inilah yang digunakan protokol streaming untuk mentransfer data tersebut. Selain kurangnya pengalamatan eksplisit, bus Avalon-ST menarik karena selalu menghubungkan dua perangkat: sumber dan penerima. Selalu ada dua dari mereka. Satu perangkat selalu sumber, yang kedua selalu penerima. Karena itu, masalah dengan arbitrase bus ini tidak menjadi perhatian. Ini adalah pasangan perangkat yang terhubung ke bus ini:



Dan inilah sinyal khas dari bus ini:



Selain itu, garis kesalahan adalah opsional, mereka mengirimkan kode kesalahan biner yang diberikan oleh kami, dan kita dapat mengatakan bahwa tidak ada kode kesalahan. Dan garis nomor saluran, seperti yang kita lihat di atas, diperlukan hanya jika demultiplex dilakukan lebih lanjut. Jika tidak, nomor saluran tidak diperlukan. Kami akan melakukannya tanpanya untuk saat ini. Tiga baris tetap: pada kenyataannya, data, sinyal siap dan sinyal konfirmasi data (strobo). Sinyal jam lain, karena bus itu sinkron.

Dari dokumentasi itu juga berikut bahwa tiga sinyal lebih mungkin, menambah bus sifat transmisi paket yang jelas:



Secara umum, bannya sangat menarik, dan hari ini kita akan mulai bereksperimen dengannya. Seperti yang telah kita ketahui, FPGA terhubung ke bus USB dari kompleks Redd melalui jembatan FT2232H yang beroperasi dalam mode FT245-SYNC . Sebenarnya, data yang melewati antarmuka ini sepenuhnya streaming data. Hari ini kita akan belajar bagaimana mentransfer data ini ke sistem prosesor kami berdasarkan NIOS II. Sangat disayangkan bahwa protokol FT245-SYNC , meskipun streaming, tidak sepenuhnya mematuhi bus Avalon-ST . Untuk menghemat kaki chip, ia memiliki bus data dua arah, dan bus Avalon-ST searah. Jadi, kita harus membuat blok yang mengkoordinasikan tutup tetapi tidak cocok protokol.

Kami sudah berkenalan dengan protokol FT245-SYNC di salah satu artikel sebelumnya . Biarkan saya mengingatkan Anda bahwa deskripsinya dapat ditemukan di dokumen AN_130 FT2232H Digunakan dalam Mode FIFO Sinkron Gaya FT245 . Berikut ini adalah diagram waktu khas dari transmisi dari jembatan ke FPGA



Secara umum, sebagai seorang programmer, saya sangat tertarik pada kenyataan bahwa paket yang dikirimkan akan ditandai dengan jelas mulai dan berakhir. Nah, untuk membuatnya lebih logis dalam logika protokol UDP, karena jika transfer menggunakan gaya TCP, Anda harus menambahkan data benchmark khusus ke stream, yang akan dihabiskan untuk pemrograman, upaya, dan siklus prosesor ... Sepertinya garis RXF dapat membantu kami dengan ini. Kami memeriksa ... Kami mengisi "firmware" di FPGA untuk mengukur kinerja, yang dibuat pada artikel sebelumnya , dan menghubungkan probe osiloskop ke jalur RXF. Sebagai program uji untuk prosesor pusat Redd, kami menggunakan basis, juga digunakan untuk mengukur kinerja, alih-alih mengirim sejumlah besar data, kami mengirim blok monolitik 0x400 byte.

uint8_t temp [maxBlockSize]; memset (temp,0,sizeof (temp)); uint32_t dwWritten; FT_Write(ftHandle0, temp, 0x400, &dwWritten); 

Kami mendapatkan gambar berikut di jalur RXF:



Jelas bahwa microcircuit menerima 0x200 byte buffer (yaitu berapa banyak yang bisa datang dalam satu paket USB2.0 HS), kemudian mengirimkannya ke saluran. Secara umum, ini aneh, karena dokumentasi menyatakan bahwa dua buffer digunakan di setiap arah. Selama transmisi, buffer kedua seharusnya memiliki waktu untuk diisi. Sayang Akhir pengisiannya jelas terlambat. Sebenarnya, ini menunjukkan mengapa kinerja tidak mencapai teoritis 52 megabyte per detik: sebagian besar waktu (walaupun tidak 50%) tidak ditransmisikan.

Tetapi dengan satu atau lain cara, dan kami menemukan bahwa mungkin untuk mendeteksi permulaan paket pada tepi RXF negatif hanya jika ukuran paket tidak melebihi 0x200 byte. Jika kami hanya mengirim perintah dengan sejumlah kecil data ke perangkat, ini cukup dapat dicapai. Tetapi jika kita mengirim aliran data yang besar, kita harus menggunakan saluran kontinu, serupa dalam logikanya dengan UART (atau, katakanlah, ke saluran TCP), dengan menyoroti batas-batas paket secara murni secara terprogram.

Secara umum, untuk kesederhanaan presentasi, kami menggunakan versi streaming sebagai dasarnya. Kami tidak akan mempertimbangkan paket hari ini. Nah, versi bis Avalon-ST yang kami ambil sebagai dasar sudah jelas. Kami mulai merancang blok kami. Seperti disebutkan di atas, kita harus membuat tidak hanya jembatan, tetapi saklar, karena bus FT245FIFO adalah dua arah, dan bus Avalon-ST adalah searah. Artinya, perlu membuat dua bus Avalon-ST sekaligus: output dan input.



Kami mulai perlahan mengembangkan otomat yang akan mengimplementasikan logika yang kita butuhkan. Tentu saja, dalam artikel ini, logika ini akan disederhanakan secara maksimal. Mari kita mulai dengan mentransfer data dari FPGA ke PC, karena proses ini sedikit lebih sederhana (Anda tidak perlu mengubah status jalur OE, yang telah kita bicarakan di artikel terakhir ). Artinya, kami menerapkan port Sink.

Dari sisi bus Avalon-ST , saya memilih mode operasi berikut (ada banyak sekali di dokumen, tapi yang ini paling dekat dengan antarmuka dengan FT245-SYNC ):



Biarkan saya mengingatkan Anda arah sinyal:



Artinya, kita tinggal menunggu konfirmasi pada bus ( valid ), klik pada data dan gerbang fakta ini dengan garis ready .

Dari sisi FT245_FIFO, protokolnya terlihat seperti ini:



Ternyata kita harus menunggu sinyal TXE dan gerbang data dengan sinyal WR # (polaritasnya terbalik untuk kedua sinyal ini).

TXE # sangat mirip fungsinya dengan ready , dan WR # valid . Detailnya sedikit berbeda, tetapi logikanya serupa.

Ternyata kita dapat memilih satu status tunggal toPC, di mana pergantian paling sederhana dari beberapa baris akan dilakukan. Kondisi untuk memasuki kondisi ini adalah kesiapan kedua belah pihak untuk transmisi, yaitu (TXE # == 0) AND (valid == 1). Segera setelah beberapa kesiapan hilang, kami keluar kembali ke siaga.

Grafik transisi automaton masih sederhana:



Dan tabel switching adalah seperti ini (di mana nama-nama sinyalnya ambigu, indeks ditambahkan padanya, di mana namanya unik - tidak ada indeks):

SinyalStatus ToPCKondisi lainnya
WR #TIDAK (validSink)1
readySinkBUKAN (TXE #)0
DATAFT245_FIFODataSinkZ


Pindah ke transfer yang sedikit lebih kompleks dari Source ke FT245_FIFO. Seperti yang kita lihat di artikel sebelumnya , komplikasinya adalah beralih arah dengan sinyal OE #:



Untuk bus Avalon_ST, semuanya sama seperti sebelumnya, sehingga gambar tidak ditampilkan untuk kedua kalinya, tetapi sekarang kita berada di posisi Sumber.

Di sini, baris RXF # sesuai dengan baris yang valid , dan baris RD # sesuai dengan baris siap . Baiklah, tambahkan beberapa status ke mesin:



dan logika berikut untuk sinyal yang aktif di negara ini:

Sinyaljatuhkandari PCKondisi lainnya
OE #001
RD #1BUKAN (readySource)1
sumber dataNilai apa punDATAFT245_FIFONilai apa pun
sumber yang valid0BUKAN (RXF #)0

Jelas bahwa skema itu bukan yang paling ideal. Ada berbagai nuansa yang terkait dengan buffer overruns atau underruns. Tetapi tidak boleh ada kehilangan data apa pun, tetapi untuk optimalitas, Anda harus memulai suatu tempat!

Kami mulai mentransfer teori yang dikembangkan ke kode SystemVerilog. Benar, kami tidak dapat menggunakan semua fitur SystemVerilog. Ada sebuah kasus, saya menulis sebuah artikel besar , di mana saya menguji kemampuan praktis dari fitur yang indah dari bahasa ini dengan lingkungan pengembangan yang nyata. Di sini kita hanya meminta penggunaan antarmuka, karena sistem akan memiliki dua contoh tipe Avalon-ST . Alas dan ah. Ini adalah kode tes:
 interface AvalonST #(parameter width=8)(input clk); logic [width-1:0] data; logic ready; logic valid; modport source (input clk, ready, output data,valid); modport sink (input clk, data, valid, output ready); endinterface module FT245toAvalonST ( AvalonST.source source, AvalonST.sink sink ); //assign source.ready = sink.valid; assign sink.ready = source.valid; endmodule 

Itu sempurna disintesis dalam kompiler utama (baris komentar ketika menghapus komentar memprovokasi kesalahan untuk memastikan bahwa synthesizer menginterpretasikan semuanya dengan benar), tetapi ketika memeriksa tombol Menganalisis File Sintesis untuk komponen untuk kode ini, kesalahan dihasilkan bahwa tipe AvalonST tidak diketahui. Artinya, analisis tidak ada pada SystemVerilog, tetapi pada Verilog murni. Sayang sekali.



Selain itu, bahasa ditentukan dengan benar, hanya alat analisa tidak mengerti antarmuka antar port.



Secara umum, Anda harus menggunakan sintaks tua yang jelek.

Dengan sintaks ini kita mendapatkan antarmuka modul berikut:
 module FT245toAvalonST ( input clk, input reset, inout [7:0] ft245_data, input logic ft245_rxf, input logic ft245_txe, output logic ft245_rd, output logic ft245_wr, output logic ft245_oe, output logic ft245_siwu, input logic source_ready, output logic source_valid, output logic[7:0] source_data, output logic sink_ready, input logic sink_valid, input logic[7:0] sink_data ); 


Kasar, vintage, tetapi apa yang bisa Anda lakukan.

Kami menyadari grafik transisi otomat tanpa embel-embel:
 //    enum {idle, toPC, dropOE, fromPC} state = idle; //     always_ff @(posedge clk,posedge reset) begin if (reset == 1) begin state <= idle; end else begin case (state) idle: begin if ((ft245_txe == 0) && (sink_valid == 1)) state <= toPC; else if ((ft245_rxf == 0)&&(source_ready == 1)) state <= dropOE; end toPC: begin if (!((ft245_txe == 0) && (sink_valid == 1))) state <= idle; end dropOE: begin state <= fromPC; end fromPC: begin if (!((ft245_rxf == 0)&&(source_ready == 1))) state <= idle; end endcase end end 


Kontrol output, bagaimanapun, memerlukan beberapa penjelasan.

Bagian dari instalasi dilakukan "di dahi":
 //    //   ,        , //  -    . always_comb begin ft245_oe <= 1; ft245_rd <= 1; ft245_wr <= 1; source_valid <= 0; sink_ready <= 0; //     , //     assign- case (state) idle: begin end toPC: begin ft245_wr <= !(sink_valid); sink_ready <= !(ft245_txe); end dropOE: begin ft245_oe <= 0; end fromPC: begin ft245_oe <= 0; ft245_rd <= !(source_ready); source_valid <= !(ft245_rxf); end endcase end 


Tetapi, katakanlah, untuk bus data dua arah, solusi tipikal harus diterapkan. Seperti yang kita ingat, itu dinyatakan di bagian antarmuka sebagai berikut:

  inout [7:0] ft245_data, 

dan membaca darinya bisa dilakukan dengan cara biasa. Untuk kasus kami, kami cukup membungkus semua data pada data bus Avalon-ST yang keluar:

 //          assign source_data = ft245_data; 

Tetapi secara umum, Anda selalu dapat membaca dari bus dan dengan cara apa pun yang Anda suka. Tetapi Anda harus menulis untuk itu menggunakan multiplexer. Ketika kami menulis data ke bus, data ini harus berasal dari bus lain yang sudah disiapkan sebelumnya. Biasanya, variabel tipe reg (atau logika bermodel) berakhir di modul. Dalam kasus kami, bus semacam itu sudah ada. Ini adalah bus sink_data . Dalam kasus lain, negara Z adalah output. Jika Anda terbiasa dengan sirkuit, Anda sangat menyadari buffer output khas. Entah melewatkan data input apa pun, atau masuk ke Z-state. Dalam kode kami, multiplexer ini terlihat seperti ini:

 //      inout- assign ft245_data = (state == toPC) ? sink_data : 8'hzz; 

Dan ft245_siwu sinyal lain. Kami tidak pernah menggunakannya, jadi menurut dokumentasi di FT2232H, tarik ke persatuan:

 //   FTDI : // Tie this pin to VCCIO if not used. assign ft245_siwu = 1; 

Sebenarnya itu saja.

Seluruh modul terlihat seperti ini:
 module FT245toAvalonST ( input clk, input reset, inout [7:0] ft245_data, input logic ft245_rxf, input logic ft245_txe, output logic ft245_rd, output logic ft245_wr, output logic ft245_oe, output logic ft245_siwu, input logic source_ready, output logic source_valid, output logic[7:0] source_data, output logic sink_ready, input logic sink_valid, input logic[7:0] sink_data ); //    enum {idle, toPC, dropOE, fromPC} state = idle; //     always_ff @(posedge clk,posedge reset) begin if (reset == 1) begin state <= idle; end else begin case (state) idle: begin if ((ft245_txe == 0) && (sink_valid == 1)) state <= toPC; else if ((ft245_rxf == 0)&&(source_ready == 1)) state <= dropOE; end toPC: begin if (!((ft245_txe == 0) && (sink_valid == 1))) state <= idle; end dropOE: begin state <= fromPC; end fromPC: begin if (!((ft245_rxf == 0)&&(source_ready == 1))) state <= idle; end endcase end end //    //   ,        , //  -    . always_comb begin ft245_oe <= 1; ft245_rd <= 1; ft245_wr <= 1; source_valid <= 0; sink_ready <= 0; //     , //     assign- case (state) idle: begin end toPC: begin ft245_wr <= !(sink_valid); sink_ready <= !(ft245_txe); end dropOE: begin ft245_oe <= 0; end fromPC: begin ft245_oe <= 0; ft245_rd <= !(source_ready); source_valid <= !(ft245_rxf); end endcase end // -  c  ,   ... //   FTDI : // Tie this pin to VCCIO if not used. assign ft245_siwu = 1; //      inout- assign ft245_data = (state == toPC) ? sink_data : 8'hzz; //          assign source_data = ft245_data; endmodule 


Cara memasukkan modul dalam daftar yang tersedia untuk digunakan dalam sistem prosesor, kami memeriksa secara rinci di salah satu artikel sebelumnya , jadi saya hanya menunjukkan hasilnya pada gambar. Saya ingat bahwa untuk mencapainya, saya harus menambahkan dua bus AVALON-ST , satu bus Conduit , menarik sinyal dari bus AVALON-MM yang didefinisikan secara keliru, dan ketika tidak ada satu sinyal pun yang tersisa di bus itu, hapus saja. Sepanjang jalan, gambar menunjukkan pengaturan yang saya pilih untuk bus AVALON-ST (8 bit per simbol, tidak ada kesalahan, saluran maksimum adalah nol, latensi adalah nol).



Dengan pengembangan modul untuk docking ban - itu saja. Tapi sayang sekali, ah. Berkembang hanyalah awal dari pekerjaan. Implementasi jauh lebih sulit. Seperti yang bisa dilihat dari posisi scroller di layar, akhir artikel masih jauh. Jadi, kami mulai membuat proyek sederhana yang menggunakan bus FT245-SYNC bersama dengan bus AVALON-ST . Itu yang paling sederhana. Sebuah proyek serius tidak cocok dengan kerangka kerja satu artikel dengan ukuran yang masuk akal. Saya sekarang akan membuat penyederhanaan setelah penyederhanaan hanya agar perhatian pembaca cukup untuk sisa teks sehingga mereka tidak berhenti membaca dalam sepatah kata pun. Penyederhanaan pertama adalah bahwa 60 MHz clock untuk FT245_SYNC dihasilkan oleh chip FT2232H itu sendiri . Saya bisa menambahkan dua garis jam ke sistem, tetapi begitu semua orang melihatnya, kita akan memiliki jaring laba-laba sedemikian rupa sehingga ibu saya tidak berduka. Jika saya masih memperhatikan garis jam yang berbeda, kita semua akan bingung. Oleh karena itu, saya hanya mengumumkan bahwa hari ini sistem prosesor kami akan clock dari chip FT2232H , dan bukan dari generator biasa.

Kenapa kamu tidak bisa selalu melakukan itu? Sangat sederhana: selama FT2232H tidak dalam mode 245_SYNC, ia tidak memiliki pulsa ini pada output. Artinya, Anda harus terlebih dahulu menjalankan program untuk prosesor sentral, dan hanya kemudian memuat semuanya ke dalam FPGA. Jika kita membuat sistem untuk pelanggan eksternal, solusi seperti itu akan menciptakan banyak masalah. Saya tahu dari pengalaman bahwa mereka akan secara teratur menghubungi kami dan mengatakan bahwa tidak ada yang berhasil, kami akan mengingatkan tentang bar, tetapi itu akan membantu untuk sementara waktu. Tetapi kami sedang melakukan hal internal, dan kami hanya akan menggunakannya dalam kondisi laboratorium. Artinya, dalam kerangka tugas ini, ini diizinkan.

Tapi ini membawa tantangan baru. Kami memiliki frekuensi 60 MHz, dan blok jam SDRAM yang saat ini kami gunakan terkait erat dengan frekuensi 50 MHz. Ya, saya telah memeriksa, 60 dapat dikirimkan, tetapi mari kita berpura-pura bahwa kita mencoba untuk tidak melampaui mode yang diizinkan. Dalam artikel selanjutnya saya akan mencoba menunjukkan bagaimana cara mengganti blok keras ini, tetapi hari ini kami hanya mengatakan bahwa karena unit jam kami dari SDRAM tidak dapat bekerja pada frekuensi yang digunakan, kami mengecualikannya dari sistem prosesor SDRAM. Program dan datanya akan sepenuhnya terletak di memori internal FPGA. Secara eksperimental ditemukan bahwa dalam konfigurasi hari ini, FPGA dapat mengambil maksimum 28 kilobyte RAM untuk bisnis ini. Ternyata Anda dapat mengambil volume dan bukan kekuatan ganda dari dua ...

Selain itu, kami akan menggunakan jam standar dan unit reset. Ini diatur ulang sedikit berbeda dari yang kami gunakan untuk SDRAM. Agar tidak menyulitkan artikel, saya akan mengambil keuntungan dari kenyataan bahwa sistem yang sedang dikembangkan akan selalu bekerja di bawah kendali debugger, jadi saya akan memulai reset dari subsistem JTAG untuk debugging.

Secara total, kami mendapatkan sketsa sistem prosesor basis (garis Reset paling sulit disorot saat ini, penanda biru ada pada sumber sinyal):



di mana frekuensi telah disesuaikan untuk jam dan setel ulang blok:



dan untuk RAM - volumenya:



Hari ini kita perlu menampilkan teks di terminal. Karena itu, kami akan menambahkan blok yang menarik ke sistem:



Dengan blok ini, kita akan dapat memanggil fungsi yang mirip dengan printf. Selain bus AVALON_MM, itu juga harus menghubungkan output permintaan interupsi.



Itu saja, pengadaan untuk sistem prosesor selesai. Saatnya menanamkan unit kami. Di mana dia akan mengirim data? Di antara blok yang tersedia untuk kita, ada memori FIFO dua port yang sangat menarik. Pesonanya terletak pada kenyataan bahwa satu port dapat dikonfigurasi ke mode AVALON-ST dan menghubungkannya ke unit kami, dan yang kedua ke mode AVALON_MM dan bekerja dengannya menggunakan prosesor NIOS II. Blok indah ini terletak di sini:



Kami memiliki dua bus Avalon-ST (satu untuk membaca, yang lain untuk menulis), jadi kami juga membutuhkan dua blok FIFO. Sekarang saya akan membahas salah satu dari mereka dengan sangat terperinci, kami memutar beberapa kilometer web (dan banyak layar teks dengan gambar), dan tentang yang kedua kami mengatakan bahwa "itu dapat dilakukan dengan analogi", hanya menunjukkan perbedaan. Karena itu, untuk saat ini, kami hanya menambahkan satu blok ke sistem dan melihat-lihat pengaturannya. Ada banyak pengaturan. Adalah mungkin untuk hanya menunjukkan nilai-nilai yang diperlukan sehingga semua orang merujuk ke artikel sebagai referensi, tetapi tiba-tiba seseorang masuk ke situasi yang perlu dikonfigurasi, tetapi tidak ada akses ke jaringan (dan, karena itu, artikel). Oleh karena itu, saya akan menambahkan pengaturan secara iteratif. Pertama jelas, kemudian - sesuai tuntutan sistem, jalankan melalui dialog lagi dan lagi. Jadi setiap orang akan merasakan prosesnya dan akan dapat mengulanginya kapan saja. Jadi Secara default, kami diberi pengaturan berikut:



Sekarang saya akan melakukan FIFO, yang mengumpulkan data dari Avalon-ST , dan mengunggahnya ke Avalon-MM . Ternyata hasil edit pertama akan seperti ini:



Saya mendapat peringatan yang menarik ini:



Ternyata ketika setidaknya satu port diproyeksikan ke memori, lebar bus Avalon-ST harus benar-benar 32 bit. Dan kami memiliki bus 8-bit. Bagaimana menyepakati kedalaman bit, saya akan memberi tahu Anda sedikit lebih rendah, tetapi untuk sekarang kami melakukan bus 32-bit dengan karakter delapan-bit di sini. Nah, nonaktifkan mode batch, seperti yang diputuskan di bagian teoretis.



Berikutnya adalah kapasitas. Misalkan saya mengantri 256 kata (mis., 1024 byte):



Sekarang statusnya. Pada awalnya, saya tidak mementingkan itu, dan saya membekukan program dengan ketat. Jadi sekarang saya tahu status itu diperlukan. Karena kami akan bekerja dengan port keluaran secara terprogram, kami menambahkan status untuk itu.



dan tangkap kesalahan:



Baiklah kalau begitu. Tambahkan pencatatan jam kerja ganda. Cukup sambungkan kedua input ke saluran jam yang sama, karena kami memiliki satu.
Uhhhh Total yang kami miliki:



Tetapi masih terlalu dini untuk menghubungkan bisnis ini ke sistem umum. Seperti yang kami ketahui, bus Avalon-ST 8-bit meninggalkan blok yang kami kembangkan, dan ini harus termasuk yang 32-bit. Bagaimana kita? Merombak blok Anda? Tidak! Semuanya sudah dilakukan sebelum kita. Inilah yang akan membantu kami:



Tambahkan ke sistem. Selain itu, karena ini adalah lapisan, murni untuk kecantikan, kami menempatkannya di antara blok kami dan FIFO, menggunakan panah yang sesuai:



Kami melakukan pengaturan berikut: pada input kami memiliki bus 8-bit, pada output 32-bit. Sinyal paket tidak digunakan, sinyal siap dan valid digunakan.



Saatnya menenun web. Pertama, saya akan meletakkan garis streaming (pada gambar keduanya disorot, penanda ada pada penerima data):



Artinya, sinyal dari Sumber blok kami menuju ke input adaptor. Dan dari output adaptor ke input FIFO. Seperti yang saya katakan, semua koneksi dalam protokol streaming berjalan secara point-to-point.
Nah, sekarang kita menggantung garis reset, garis jam, dan juga menghubungkan semuanya ke bus sistem dan untuk mengganggu ...



Yah ... Dan sekarang, dengan prinsip yang sama, kami menambahkan FIFO untuk mengeluarkan data ke FT245SYNC . Hanya di sana, data masuk ke FIFO dari Avalon-MM dalam bentuk 32-bit. Mereka melewati adaptor 32-in-8 dan kemudian mendapatkan input SINK dari blok kami, yang tidak terhubung di sirkuit saat ini ... Kami mendapatkan bagian berikut dari rangkaian terakhir (memori di sana ternyata dengan satu jam):



Formalitas lebih lanjut yang telah kami lakukan dengan baik dalam percobaan yang dijelaskan dalam artikel sebelumnya ( sebagian besar - di sini ). Kami menetapkan vektor ke prosesor. Untuk sistem, kami menyebut penetapan angka dan alamat interupsi secara otomatis. Kami menyimpan sistem ... Semua orang ingat bahwa nama sistem yang disimpan harus cocok dengan nama proyek sehingga sistem berada di tingkat atas hierarki? Tambahkan sistem ke proyek, buat konsep kasar proyek, tetapkan kaki. Secara pribadi, saya curang: Saya menyalin tugas dari file * .qsf dari proyek draft ke proyek finishing saat ini (dan Anda dapat mengambil proyek saya dan menyalin baris * .qsf yang sesuai dengan Anda, tetapi Anda dapat dengan mudah menetapkan semua kaki melalui GUI). Saya menaruh perhatian khusus pada fakta bahwa sinyal CLK terhubung ke leg 23, bukan 25, seperti dalam proyek-proyek sebelumnya. Saya mengingatkan Anda bahwa di sini kita berdetak dari output FT2232.



Hebat! Perangkat keras sudah siap. Kami lolos ke perangkat lunak. Di mana kita mulai? Hari ini pertanyaan ini tidak sepadan. Jika kita mulai dengan program yang berjalan pada prosesor NIOS II, tidak ada yang berhasil bagi kita. Pertama, kita harus meletakkan FT2232 ke mode 245-SYNC, hanya kemudian sistem prosesor kami akan menerima pulsa clock. Oleh karena itu, kita mulai dengan kode untuk prosesor pusat.

Kami mendapatkan sesuatu seperti ini:
 #include <cstdio> #include <sys/time.h> #include <unistd.h> #include "ftd2xx.h" FT_HANDLE OpenFT2232H() { FT_HANDLE ftHandle0; static FT_DEVICE ftDevice; //      int nDevice = 0; while (true) { //     if (FT_Open(nDevice, &ftHandle0) != FT_OK) { printf("No FT2232 found\n"); //  ,      return 0; } //     ? if (FT_GetDeviceInfo(ftHandle0, &ftDevice, NULL, NULL, NULL, NULL) == FT_OK) { // ,    if (ftDevice == FT_DEVICE_2232H) { // ,     AN130 FT_SetBitMode(ftHandle0, 0xff, 0x00); usleep(1000000); //Sync FIFO mode FT_SetBitMode(ftHandle0, 0xff, 0x40); FT_SetLatencyTimer(ftHandle0, 2); FT_SetUSBParameters(ftHandle0, 0x10000, 0x10000); return ftHandle0; } } //    FT_Close(ftHandle0); //    nDevice += 1; } printf("No FT2232 found\n"); } int main() { FT_HANDLE ftHandle0 = OpenFT2232H(); if (ftHandle0 == 0) { printf("Cannot open device\n"); return -1; } int item; bool bWork = true; while (bWork) { printf("1 - Send 16 bytes\n"); printf("2 - Send 256 bytes\n"); printf("3 - Receive loop\n"); printf("0 - Exit\n"); scanf("%d", &item); switch (item) { case 0: bWork = false; break; case 1: { static const unsigned char data[0x10] = { 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; DWORD dwWritten; FT_Write(ftHandle0, (void*)data, sizeof(data), &dwWritten); } break; case 2: { unsigned char data[0x100]; for (size_t i = 0; i < sizeof(data); i++) { data[i] = (unsigned char)i; } DWORD dwWritten; FT_Write(ftHandle0, (void*)data, sizeof(data), &dwWritten); } break; case 3: { DWORD dwRxBytes; DWORD dwRead; DWORD buf[0x100]; while (true) { FT_GetQueueStatus(ftHandle0, &dwRxBytes); if (dwRxBytes != 0) { printf("Received %d bytes (%d DWORDs)\n", dwRxBytes, dwRxBytes / sizeof(buf[0])); if (dwRxBytes > sizeof(buf)) { dwRxBytes = sizeof(buf); } FT_Read(ftHandle0, buf, dwRxBytes, &dwRead); for (DWORD i = 0; i < dwRxBytes / sizeof(buf[0]);i++) { printf("0x%X, ",buf[i]); } printf("\n"); } } } break; } } // ,    FT_Close(ftHandle0); return 0; } 


Fungsi OpenFT2232H () tidak asing bagi kita dari artikel terakhir . Dialah yang membuka perangkat FT2232 dan menempatkannya dalam mode yang kita butuhkan. Segera setelah peluncuran program yang sukses, kami mendapatkan pulsa clock, dan dengan mereka kemampuan untuk debug program untuk NIOS II. Nah, fungsi dari fungsi utama sesederhana bangku. Kirim beberapa data (1), kirim banyak data (2), terima data (3). Harap dicatat bahwa semua data dikirim dalam blok yang kelipatan empat byte. Ini semua karena kami memiliki adaptor 8-in-32. Di pintu keluar dari itu, data harus dalam kata-kata ganda. Kalau tidak, semuanya jelas.

NIOS II BSP. , Hello World Small. BSP ( BSP, ). , , , Settings, .



Generate BSP , , hello_world_small.c hello_world_small.cpp , , .

( , FIFO, โ€” , , ). . โ€” NIOS II. :

 extern "C" { #include "sys/alt_stdio.h" #include <system.h> #include <altera_avalon_fifo_util.h> } #include <stdint.h> int main() { while (1) { int level = IORD_ALTERA_AVALON_FIFO_LEVEL(FIFO_0_OUT_CSR_BASE); if (level != 0) { alt_printf("0x%x words received:\n",level); for (int i=0;i<level;i++) { alt_printf("0x%x,",IORD_ALTERA_AVALON_FIFO_DATA (FIFO_0_OUT_BASE)); } alt_printf("\n"); } } /* Event loop never exits. */ while (1); return 0; } 

FIFO. , .
. , . Redd ยซยป , NIOS II. :



, . , . , , . FT2232, , . . : FT245-SYNC .

1. , :

0x2 words received:
0x3020100,0x7060504,
0x2 words received:
0xb0a0908,0xf0e0d0c,


:

0x3 words received:
0x3020100,0x7060504,0xb0a0908,
0x1 words received:
0xf0e0d0c,


, 1, 3 , . , , . , , JTAG โ€” . , . , ( , ? ), (FIFO โ€” , , ).

Little Endian. , :

 static const unsigned char data[0x10] = { 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; 

Benar juga. 2, ( , ):

 0x3 words received: 0x3020100,0x7060504,0xb0a0908, 0x3d words received: 0xf0e0d0c, 0x13121110,0x17161514,0x1b1a1918,0x1f1e1d1c, 0x23222120,0x27262524,0x2b2a2928,0x2f2e2d2c, 0x33323130,0x37363534,0x3b3a3938,0x3f3e3d3c, 0x43424140,0x47464544,0x4b4a4948,0x4f4e4d4c, 0x53525150,0x57565554,0x5b5a5958,0x5f5e5d5c, 0x63626160,0x67666564,0x6b6a6968,0x6f6e6d6c, 0x73727170,0x77767574,0x7b7a7978,0x7f7e7d7c, 0x83828180,0x87868584,0x8b8a8988,0x8f8e8d8c, 0x93929190,0x97969594,0x9b9a9998,0x9f9e9d9c, 0xa3a2a1a0,0xa7a6a5a4,0xabaaa9a8,0xafaeadac, 0xb3b2b1b0,0xb7b6b5b4,0xbbbab9b8,0xbfbebdbc, 0xc3c2c1c0,0xc7c6c5c4,0xcbcac9c8,0xcfcecdcc, 0xd3d2d1d0,0xd7d6d5d4,0xdbdad9d8,0xdfdedddc, 0xe3e2e1e0,0xe7e6e5e4,0xebeae9e8,0xefeeedec, 0xf3f2f1f0,0xf7f6f5f4,0xfbfaf9f8,0xfffefdfc, 

. . NIOS II :

  /*  -  2 */ uint32_t buf[] = {0x11223344,0x55667788,0x99aabbcc,0xddeeff00}; for (uint32_t i=0;i<sizeof(buf)/sizeof(buf[0]);i++) { IOWR_ALTERA_AVALON_FIFO_DATA (FIFO_1_IN_BASE,buf[i]); } 

3 NIOS II. :

Received 16 bytes (4 DWORDs)

0x11223344, 0x55667788, 0x99AABBCC, 0xDDEEFF00,


. - .

Kesimpulan


Avalon-ST . Redd , . . .

. , , Redd.

Source: https://habr.com/ru/post/id462253/


All Articles