55 / 63 · Konsep
Memori sinkron dan kontrak konflik baca/tulis
Tentukan respons berregister dan mode konflik, dengan memisahkan validitas dari inisialisasi alamat.
Pelajaran dapat dibaca gratis. Daftar untuk menyimpan progres.
Sebelum alamat, tentukan waktu respons
Memori memerlukan ketentuan kapasitas, latensi baca, dan konflik. Bangun 16 kata delapan bit yang menerima satu baca dan satu tulis pada tepi naik sama. Keduanya berbagi clock, tetapi alamat independen. Kapasitas 16×8=128 bit; lebar alamat bit.
Stabilkan alamat dan rd_en sebelum tepi: rd_data serta rd_valid dari register muncul sesudahnya. Ini satu tahap baca dengan keluaran berregister. always_ff lain yang membacanya pada tepi sama melihat nilai lama; registerRegister Rangkaian penyimpan beberapa bit keadaan. Register sinkron mata kuliah ini menangkap masukan yang ditentukan pada tepi clock. Selengkapnya konsumen menerima pada tepi berikutnya. Tandai permintaan dan pengamatan respons terpisah. Permintaan baru dapat diterima tiap siklus, sehingga latensi satu tahap tidak berarti throughputThroughput Jumlah pekerjaan diterima atau selesai per satuan waktu. Pipeline dapat meningkatkannya tanpa mengurangi latensi satu pekerjaan. Selengkapnya setengah.
Membaca dan menulis alamat sama
Misalkan sebelum tepi M[3]=8'h25, lalu alamat 3 dibaca sambil ditulis 8'h9A. read-first merespons 25 lalu menyimpan 9A; write-first merespons 9A; no-change mempertahankan register keluaran yang belum tentu berisi nilai lama alamat 3. Ini tiga kontrak normal berbeda, juga dijelaskan dalam mode RAM AMD.
Kita memilih read-first. Dengan sebelum dan sesudah tepi, untuk alamat pada tepi tanpa reset:
Walaupun konflik, baca memakai , bukan . Tanpa permintaan baca, rd_data dipertahankan.
module sync_mem16x8 (
input logic clk, rst,
input logic wr_en, rd_en,
input logic [3:0] wr_addr, rd_addr,
input logic [7:0] wr_data,
output logic [7:0] rd_data,
output logic rd_valid
);
timeunit 1ns;
timeprecision 1ps;
logic [7:0] mem [0:15];
always_ff @(posedge clk) begin
if (rst) begin
rd_valid <= 1'b0;
end else begin
rd_valid <= rd_en;
if (wr_en)
mem[wr_addr] <= wr_data;
if (rd_en)
rd_data <= mem[rd_addr];
end
end
endmoduleSisi kanan membaca nilai lama sebelum pembaruan nonblockingNonblocking Penugasan <= pada RTL sekuensial: sisi kanan dievaluasi lalu pembaruan dijadwalkan, sehingga register pada tepi sama menghitung dari keadaan lama. Selengkapnya. Menulis pernyataan tulis sebelum baca tidak mengubahnya menjadi write-first. Untuk write-first, gunakan eksplisit (wr_en && wr_addr==rd_addr) ? wr_data : mem[rd_addr]. Bypass ini tetap mempertahankan register keluaran.
Validitas dan inisialisasi adalah kontrak berbeda
rst sinkron active-high. Jika rst=1 pada tepi, kedua permintaan diabaikan dan hanya rd_valid dihapus ke 0; array dan rd_data tidak dihapus. Alamat yang belum pernah ditulis sejak daya menyala tidak didefinisikan: simulator dapat menunjukkan X dan nilai fisik tertentu tidak boleh diasumsikan.
rd_valid=1 menandai periode respons, bukan alamat yang telah diinisialisasi. Pengguna harus membaca alamat yang sudah ditulis atau memelihara tabel inisialisasi. Baca read-first pada tepi penulisan pertama tetap mengembalikan isi lama tidak terdefinisi. rd_data juga harus diabaikan ketika valid=0. Guard valid dan inisialisasi alamat tidak saling menggantikan.
Reset tidak menghapus penyimpanan: nilai tertulis tetap ada menurut RTL. Jika sistem membuang isi lama setelah reset, tabel inisialisasi luar juga harus dikelola. Penghapusan informasi sensitif adalah kebutuhan terpisah dari reset kontrol.
Setiap kolom mengamati tepi naikTepi naik Saat clock berubah 0 ke 1, berbeda dari tingkat yang mencakup seluruh interval CLK=1. Selengkapnya: masukan sebelum, keadaan after sesudah. Penjajaran bukan tundaan fisikTundaan propagasi Waktu sejak masukan berubah hingga keluaran stabil pada nilai benar. Kesetaraan logika berbeda dari karakteristik waktu. Selengkapnya. Semua alamat 3: E0 menulis 25, E1 menggantinya dengan 9A sambil membaca. Tanda hubung berarti tidak terdefinisi; valid=0 bukan respons. Data ditulis heksadesimal.
Lihat data gelombang
| Sinyal | Gelombang | Nilai bus |
|---|---|---|
| edge | 2345 | E0 → E1 → E2 → E3 |
| wr_en | 1.0. | |
| wr_data | 23.. | 25 → 9A |
| rd_en | 01.0 | |
| M[3] sesudah | 23.. | 25 → 9A |
| rd_data sesudah | 234. | - → 25 → 9A |
| rd_valid sesudah | 01.0 |
Menelusuri empat tepi secara manual
E0 menulis 25 ke alamat 3 dengan rd_en=0. E1 menulis 9A dan membaca 3: sesudah E1 valid=1,data=25. E2 membaca lagi tanpa menulis: data=9A. E3 dengan rd_en=0 memberi valid=0 dan mempertahankan data=9A. Menghitung nilai terakhir ini sebagai respons baru memproses data sama dua kali.
Untuk alamat berbeda, baca dan tulis independen: membaca 7 sambil menulis 3 mengembalikan isi lama 7. Pada FPGA nyata, periksa sumber RAM hasil sintesis dan kebijakan konflik melalui laporan serta dokumentasi komponen. Menentukan makna RTL dan memvalidasi perangkat tertentu adalah tahap berbeda.
Coba sendiri
M[6]=8'h10 telah disimpan. E0 membaca 6 dan menulis 8'h20; E1 membaca lagi tanpa menulis; E2 rd_en=0. Tentukan data/valid tiap tepi untuk read-first. Apa perubahan write-first? Apakah konflik pertama pada alamat belum pernah ditulis memiliki nilai pasti?
Baca penjelasan
E0: data=10,valid=1, array diperbarui ke 20. E1: data=20,valid=1. E2 mempertahankan data=20 tetapi valid=0, bukan respons. Pada write-first, hanya E0 menjadi data=20. Konflik read-first saat penulisan pertama mengembalikan isi lama belum diinisialisasi: tidak ada nilai pasti sebagai jawaban. valid=1 tidak menjamin inisialisasi.