Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Industrial programming >> VHDL

Cara menginisialisasi RAM dari file menggunakan TEXTIO

Cara mudah untuk mengisi blok RAM dengan nilai awal adalah dengan membaca literal biner atau heksadesimal dari file ASCII. Ini juga merupakan cara yang baik untuk membuat ROM (memori hanya-baca) di VHDL. Bagaimanapun, RAM dan ROM adalah hal yang sama di FPGA, ROM adalah RAM yang hanya Anda baca.

Contoh di seluruh artikel ini akan mengasumsikan bahwa konstanta dan tipe RAM berikut telah dideklarasikan di awal wilayah deklaratif file VHDL.

constant ram_depth : natural := 256;
constant ram_width : natural := 32;

type ram_type is array (0 to ram_depth - 1)
  of std_logic_vector(ram_width - 1 downto 0);

Posting blog ini adalah bagian dari seri tentang penggunaan perpustakaan TEXTIO di VHDL. Baca artikel lainnya di sini:

File stimulus dibaca di testbench menggunakan TEXTIO

Gambar bitmap file BMP dibaca menggunakan TEXTIO

BACA, GARIS, HREAD, OREAD, dan ROTI

Subprogram dan jenis yang diperlukan untuk membaca dan menulis file eksternal di VHDL terletak di TEXTIO kemasan. Paket ini adalah bagian dari std Perpustakaan. Pustaka standar selalu dimuat; oleh karena itu, kita tidak perlu mengimpornya secara eksplisit dengan kode library kata kunci.

Kita bisa melanjutkan dan menggunakan TEXTIO package di header file VHDL kita seperti ini:

use std.textio.all;

Kami akan menyimpan data RAM dalam file ASCII di mana satu baris teks sesuai dengan slot memori. Untuk membaca sebaris teks kita menggunakan READLINE prosedur dari TEXTIO kemasan. Prosedur ini membutuhkan dua argumen, nama file sebagai input konstan dan baris teks yang diurai sebagai inout variabel. Deklarasi prototipe READLINE prosedur dan LINE jenis yang diambil dari spesifikasi standar VHDL ditunjukkan di bawah ini.

procedure READLINE (file F: TEXT; L: inout LINE);

type LINE is access STRING; -- A LINE is a pointer
                            -- to a STRING value.

Meskipun kelas LINE parameter tidak secara eksplisit ditentukan dalam deklarasi prototipe READLINE , ini adalah variabel karena itu adalah kelas default untuk inout parameter. LINE type hanyalah tipe akses ke string, pointer ke objek string yang dialokasikan secara dinamis.

VHDL-2008 mendefinisikan OREAD , HREAD , dan BREAD prosedur untuk mengekstrak nilai oktal, heksadesimal, dan biner dari LINE obyek. Metode untuk membaca nilai oktal dan heksadesimal sangat mirip, nilai oktal hanyalah bagian dari heksadesimal. Untuk mempermudah, kita akan melewatkan pembacaan oktal dalam artikel ini dan fokus pada cara membaca nilai heksadesimal dan biner dari file teks.

Kode di bawah ini menunjukkan definisi prosedur yang relevan bagi kami, mereka hanya tersedia di VHDL-2008 dan revisi yang lebih baru. OREAD dan HREAD prosedur datang dalam dua rasa kelebihan beban untuk masing-masing jenis output yang didukung. GOOD opsional output dapat digunakan untuk mendeteksi kesalahan baca, meskipun, sebagian besar alat akan menghasilkan kesalahan atau peringatan terlepas dari apakah output ini digunakan atau tidak.

procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR;
                                 GOOD : out BOOLEAN);
procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);

procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR;
                                  GOOD : out BOOLEAN);
procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);

alias BREAD is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
alias BREAD is READ [LINE, STD_ULOGIC_VECTOR];
Klik di sini untuk melihat definisi prosedur input dari perpustakaan TEXTIO
procedure READLINE (file F: TEXT; L: inout LINE);

procedure READ (L: inout LINE; VALUE: out BIT;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out BIT);

procedure READ (L: inout LINE; VALUE: out BIT_VECTOR;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out BIT_VECTOR);

procedure READ (L: inout LINE; VALUE: out BOOLEAN;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out BOOLEAN);

procedure READ (L: inout LINE; VALUE: out CHARACTER;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out CHARACTER);

procedure READ (L: inout LINE; VALUE: out INTEGER;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out INTEGER);

procedure READ (L: inout LINE; VALUE: out REAL;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out REAL);

procedure READ (L: inout LINE; VALUE: out STRING;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out STRING);

procedure READ (L: inout LINE; VALUE: out TIME;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out TIME);

procedure SREAD (L: inout LINE; VALUE: out STRING;
                                STRLEN: out NATURAL);
alias STRING_READ is SREAD [LINE, STRING, NATURAL];

alias BREAD is READ [LINE, BIT_VECTOR, BOOLEAN];
alias BREAD is READ [LINE, BIT_VECTOR];
alias BINARY_READ is READ [LINE, BIT_VECTOR, BOOLEAN];
alias BINARY_READ is READ [LINE, BIT_VECTOR];

procedure OREAD (L: inout LINE; VALUE: out BIT_VECTOR;
                                GOOD: out BOOLEAN);
procedure OREAD (L: inout LINE; VALUE: out BIT_VECTOR);
alias OCTAL_READ is OREAD [LINE, BIT_VECTOR, BOOLEAN];
alias OCTAL_READ is OREAD [LINE, BIT_VECTOR];

procedure HREAD (L: inout LINE; VALUE: out BIT_VECTOR;
                                GOOD: out BOOLEAN);
procedure HREAD (L: inout LINE; VALUE: out BIT_VECTOR);
alias HEX_READ is HREAD [LINE, BIT_VECTOR, BOOLEAN];
alias HEX_READ is HREAD [LINE, BIT_VECTOR];
Klik di sini untuk melihat definisi prosedur input dari perpustakaan std_logic_1164
procedure READ (L : inout LINE; VALUE : out STD_ULOGIC; GOOD : out BOOLEAN);
procedure READ (L : inout LINE; VALUE : out STD_ULOGIC);

procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN);
procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);

alias BREAD is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
alias BREAD is READ [LINE, STD_ULOGIC_VECTOR];
alias BINARY_READ is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
alias BINARY_READ is READ [LINE, STD_ULOGIC_VECTOR];

procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN);
procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);
alias OCTAL_READ is OREAD [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
alias OCTAL_READ is OREAD [LINE, STD_ULOGIC_VECTOR];

procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN);
procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);
alias HEX_READ is HREAD [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
alias HEX_READ is HREAD [LINE, STD_ULOGIC_VECTOR];

Baca nilai hex dari file

Heksadesimal adalah format yang berguna untuk menggambarkan konten RAM karena dua karakter hex langsung diterjemahkan menjadi satu byte, delapan bit. Setiap karakter menggambarkan nibble (setengah byte) dan setiap baris dalam file teks menggambarkan isi dari satu slot RAM. Daftar di bawah ini menunjukkan kutipan dari ram_content_hex.txt mengajukan. Itu sudah diisi dengan contoh nilai mulai dari 1 sampai 256 desimal, ditulis sebagai hex.

12–255256 00000001 00000002 ... 000000FF 00000100

Untuk memuat data dari file teks, kami menggunakan fungsi tidak murni yang dideklarasikan di bawah ram_type , tetapi di atas deklarasi sinyal RAM. Kode di bawah ini menunjukkan init_ram_hex fungsi yang membaca data dari file teks dan mengembalikannya sebagai ram_type objek.

impure function init_ram_hex return ram_type is
  file text_file : text open read_mode is "ram_content_hex.txt";
  variable text_line : line;
  variable ram_content : ram_type;
begin
  for i in 0 to ram_depth - 1 loop
    readline(text_file, text_line);
    hread(text_line, ram_content(i));
  end loop;

  return ram_content;
end function;

readline prosedur di dalam for-loop membaca satu baris teks pada saat itu dan menetapkannya ke text_line variabel. Objek ini bertipe line , yang merupakan tipe akses ke objek string, penunjuk ke string yang dialokasikan secara dinamis. Pada baris berikutnya, hread prosedur membaca string dari line objek dan mengubahnya menjadi std_ulogic_vector . Jenis ini dapat ditetapkan langsung ke std_logic_vector dari mana setiap sel RAM dibuat.

Terakhir, kami mendeklarasikan sinyal RAM saat memanggil init_ram_hex berfungsi untuk memberikan nilai awal untuknya:

signal ram_hex : ram_type := init_ram_hex;

HREAD dalam VHDL-2002 dan VHDL-93

Sayangnya, HREAD prosedur ini hanya tersedia di VHDL-2008. Di semua versi VHDL sebelumnya, standar READ prosedur harus digunakan sebagai gantinya. READ prosedur kelebihan beban dengan banyak jenis keluaran yang berbeda, tetapi tidak ada opsi untuk membaca nilai heksadesimal.

Mari kita menulis algoritme khusus untuk mengonversi karakter ASCII heksadesimal ke std_logic_vector VHDL . Pertama, kita perlu membaca karakter satu per satu dari text_line objek, lalu kami mendekode nilainya dan menetapkannya ke irisan yang benar dari vektor slot RAM. Kode di bawah ini menunjukkan implementasi yang setara dari init_ram_hex fungsi yang juga berfungsi di versi VHDL lawas.

impure function init_ram_hex return ram_type is
  file text_file : text open read_mode is "ram_content_hex.txt";
  variable text_line : line;
  variable ram_content : ram_type;
  variable c : character;
  variable offset : integer;
  variable hex_val : std_logic_vector(3 downto 0);
begin
  for i in 0 to ram_depth - 1 loop
    readline(text_file, text_line);

    offset := 0;

    while offset < ram_content(i)'high loop
      read(text_line, c);

      case c is
        when '0' => hex_val := "0000";
        when '1' => hex_val := "0001";
        when '2' => hex_val := "0010";
        when '3' => hex_val := "0011";
        when '4' => hex_val := "0100";
        when '5' => hex_val := "0101";
        when '6' => hex_val := "0110";
        when '7' => hex_val := "0111";
        when '8' => hex_val := "1000";
        when '9' => hex_val := "1001";
        when 'A' | 'a' => hex_val := "1010";
        when 'B' | 'b' => hex_val := "1011";
        when 'C' | 'c' => hex_val := "1100";
        when 'D' | 'd' => hex_val := "1101";
        when 'E' | 'e' => hex_val := "1110";
        when 'F' | 'f' => hex_val := "1111";

        when others =>
          hex_val := "XXXX";
          assert false report "Found non-hex character '" & c & "'";
      end case;

      ram_content(i)(ram_content(i)'high - offset
        downto ram_content(i)'high - offset - 3) := hex_val;
      offset := offset + 4;

    end loop;
  end loop;

  return ram_content;
end function;

Algoritma hanya melewati setiap baris sambil melihat setiap karakter, mengubahnya menjadi nilai biner yang benar. Jika karakter yang tidak berada dalam rentang 0x0-0xF ditemukan, kegagalan penegasan akan muncul di when others cabang. offset variabel mengontrol posisi irisan dalam setiap sel memori untuk menetapkan nilai yang didekodekan.

Anda mungkin bertanya pada diri sendiri mengapa kami tidak membuat hread khusus prosedur alih-alih mengkodekannya di dalam init_ram_hex fungsi? Maka kita tidak perlu mengubah init_ram_hex fungsi sama sekali, kami hanya akan menggunakan hread khusus kami menggantikan prosedur standar yang hilang.

Itu akan bekerja di sebagian besar simulator dan beberapa synthesizer seperti Lattice iCEcube2, tetapi tidak akan disintesis di Xilinx Vivado. Pesan kesalahan di bawah ini dengan jelas menyatakan apa masalahnya.

Di Vivado:
[Synth 8-27] Argumen prosedur tipe 'baris' tidak didukung [init_ram_tb.vhd:15]

Klik di sini untuk melihat implementasi alternatif dari prosedur HREAD
procedure hread(l: inout line; value: out std_logic_vector) is
  variable c : character;
  variable ok : boolean;
  variable i : integer := 0;
  variable hex_val : std_logic_vector(3 downto 0);
begin
  while i < value'high loop
    read(l, c);
  
    case c is
      when '0' => hex_val := "0000";
      when '1' => hex_val := "0001";
      when '2' => hex_val := "0010";
      when '3' => hex_val := "0011";
      when '4' => hex_val := "0100";
      when '5' => hex_val := "0101";
      when '6' => hex_val := "0110";
      when '7' => hex_val := "0111";
      when '8' => hex_val := "1000";
      when '9' => hex_val := "1001";
      when 'A' | 'a' => hex_val := "1010";
      when 'B' | 'b' => hex_val := "1011";
      when 'C' | 'c' => hex_val := "1100";
      when 'D' | 'd' => hex_val := "1101";
      when 'E' | 'e' => hex_val := "1110";
      when 'F' | 'f' => hex_val := "1111";
  
      when others =>
        hex_val := "XXXX";
        assert false report "Found non-hex character '" & c & "'";
    end case;
  
    value(value'high - i downto value'high - i - 3) := hex_val;
    i := i + 4;
  end loop;
end procedure;

Baca nilai biner dari file

Anda mungkin ingin menyimpan nilai RAM sebagai literal biner alih-alih karakter hex jika lebar RAM bukan kelipatan 8. Daftar di bawah ini menunjukkan konten yang sama seperti sebelumnya, tetapi diwakili dalam format biner hanya menggunakan karakter 0 dan 1 .

12–255256 00000000000000000000000000000001 00000000000000000000000000000010 ... 00000000000000000000000011111111 00000000000000000000000100000000

Algoritma yang ditunjukkan di bawah ini adalah untuk membaca nilai biner dari file. Ini mirip dengan membaca heksadesimal, tetapi dalam VHDL-2008 Anda harus menggunakan BREAD panggilan prosedur alih-alih HREAD . Ini akan menerjemahkan satu karakter ASCII menjadi satu std_ulogic nilai, yang secara implisit dikonversi ke std_logic .

impure function init_ram_bin return ram_type is
  file text_file : text open read_mode is "ram_content_bin.txt";
  variable text_line : line;
  variable ram_content : ram_type;
begin
  for i in 0 to ram_depth - 1 loop
    readline(text_file, text_line);
    bread(text_line, ram_content(i));
  end loop;

  return ram_content;
end function;

Terakhir, kita menginisialisasi sinyal RAM dengan memanggil fungsi baru kita yang tidak murni seperti yang ditunjukkan pada kode di bawah ini.

signal ram_bin : ram_type := init_ram_bin;

ROTI dalam VHDL-2002 dan VHDL-93

Kami dapat dengan mudah membuat kode kami portabel ke versi VHDL lama dengan memanggil READ bukannya BREAD . Kutipan dari standar VHDL di bawah ini menunjukkan prototipe READ yang ingin kami gunakan.

procedure READ (L: inout LINE; VALUE: out BIT);

READ prosedur yang menghasilkan std_ulogic tidak ada sebelum VHDL-2008, oleh karena itu kita harus menggunakan bit versi dari TEXTIO Perpustakaan. Untungnya, tipe ini dapat dengan mudah diubah menjadi std_logic dengan menggunakan To_StdLogicVector standar fungsi.

Implementasi init_ram_bin yang ditunjukkan di bawah ini berfungsi di VHDL-2002 dan juga di VHDL-93.

impure function init_ram_bin return ram_type is
  file text_file : text open read_mode is "ram_content_bin.txt";
  variable text_line : line;
  variable ram_content : ram_type;
  variable bv : bit_vector(ram_content(0)'range);
begin
  for i in 0 to ram_depth - 1 loop
    readline(text_file, text_line);
    read(text_line, bv);
    ram_content(i) := To_StdLogicVector(bv);
  end loop;

  return ram_content;
end function;

Backport perpustakaan IEEE std_logic_1164

Alternatif untuk mengubah kode untuk versi VHDL lawas adalah dengan menggunakan paket pihak ketiga std_logic_1164_additions. Dengan mengunduh dan menambahkan pustaka ini ke proyek Anda, Anda akan dapat menggunakan prosedur baru juga di VHDL-2002 dan VHDL-93. Tentu saja, Anda akan mengimpor lebih banyak dan kode Anda akan selalu bergantung pada paket ini.


VHDL

  1. Bagaimana Melindungi Aluminium Dari Korosi
  2. Bagaimana Unsur Logam Berbeda Dari Unsur Bukan Logam
  3. Cara Membuat Template CloudFormation Menggunakan AWS
  4. Bagaimana komputasi awan berbeda dari komputasi tradisional?
  5. Cara menulis Komentar dalam Pemrograman C
  6. Java BufferedReader:Cara Membaca File di Java dengan Contoh
  7. Python Average:Cara Menemukan RATA-RATA dari Daftar dengan Python
  8. Apa itu Mikrometer? | Bagaimana Anda membaca Mikrometer?
  9. Cara memanggil Blok Fungsi dari Klien OPC UA menggunakan Model Informasi
  10. Cara Membaca Cetak Biru CNC