
Beberapa waktu yang lalu, selama diskusi di perusahaan pengembang FPGA profesional, diskusi muncul tentang lulus wawancara. Pertanyaan apa yang diajukan di sana, dan apa yang bisa ditanyakan. Saya menyarankan dua pertanyaan:
- Berikan contoh kode sinkron tanpa menggunakan penundaan, yang akan memberikan hasil yang berbeda saat memodelkan dan ketika bekerja di peralatan nyata
- Perbaiki kode ini dengan penundaan.
Setelah pertanyaan ini, sebuah diskusi yang hidup terjadi, sebagai akibatnya saya memutuskan untuk mempertimbangkan masalah ini secara lebih rinci.
Saya sudah sedikit menyentuh masalah ini pada
artikel sebelumnya . Sekarang lebih detail. Berikut ini contoh teks:
library IEEE; use IEEE.STD_LOGIC_1164.all; entity delta_delay is end delta_delay; architecture delta_delay of delta_delay is signal clk1 : std_logic:='0'; signal clk2 : std_logic; alias clk3 : std_logic is clk1;
Untuk mempermudah, semua kode ditempatkan dalam satu komponen.
Sinyal
clk1 dan
a adalah sinyal paparan uji.
clk1 adalah frekuensi clock 100 MHz, Sinyal
a menahan dua siklus clock pada 0 dan empat clock cycle pada 1. Sinyal
a dihasilkan dengan penundaan 1 nc relatif terhadap kenaikan edge
clk1 . Kedua sinyal ini cukup untuk menggambarkan masalahnya.
Opsi kode sintetik yang berbeda dapat dibatalkan komentar dan dimodelkan.
Pertimbangkan opsi pertama, ini adalah kode yang disintesis tanpa penundaan dan menggunakan penugasan kembali frekuensi clock.
Berikut adalah hasil simulasi untuk opsi 1:

Diagram secara visual menunjukkan bahwa sinyal clock
clk1 dan
clk2 bertepatan, tetapi sebenarnya
clk2 tertunda relatif terhadap
clk1 oleh nilai delta delay. Sinyal
c memperlambat sinyal
b oleh satu siklus clock. Ini benar Tetapi sinyal
d harus bertepatan dengan sinyal
c , tetapi ini tidak terjadi. Ini bekerja lebih awal.
Mari kita ingat apa itu penundaan delta. Ini adalah konsep mendasar, didasarkan pada karya simulator acara, yang kami gunakan saat memodelkan sirkuit logika.
Simulator memiliki konsep waktu model. Semua peristiwa dalam sistem terlampir pada waktu model ini. Mari kita lihat pembentukan frekuensi jam:
clk1 <= not clk1 after 5 ns;
Misalkan sekarang kita hanya memodelkan
clk1 , tidak ada sinyal lain.
Pada saat awal waktu,
clk1 adalah 0, ini diatur ketika sinyal dinyatakan. Simulator melihat persyaratan untuk membalikkan sinyal. Kata kunci setelah memberikan instruksi untuk menetapkan nilai baru dalam 5 ns relatif terhadap waktu model saat ini. Simulator melihat ini dan membuat catatan bahwa pada waktu 5 ns nilai
clk1 akan menjadi 1. Meskipun ini adalah model masa depan, omong-omong itu masih dapat berubah. Selanjutnya, simulator memindai sinyal yang tersisa. Simulator akan melihat bahwa untuk momen tertentu dalam waktu model, semuanya dilakukan dan dia dapat menghitung momen berikutnya. Muncul pertanyaan - apa momen selanjutnya? Pada prinsipnya, berbagai opsi dimungkinkan. Misalnya, Simulink memiliki mode pitch-tetap. Dalam hal ini, waktu model akan bertambah dengan jumlah tertentu dan perhitungan berlanjut.
Sistem simulasi sirkuit digital melakukan hal yang berbeda. Mereka pindah ke acara berikutnya, yang telah mereka tempatkan di masa depan pada sumbu waktu model mereka. Dalam hal ini, akan menjadi 5 ns. Simulator akan melihat bahwa
clk1 telah berubah dan akan menghitung nilai baru untuk itu, itu akan menjadi 0 yang juga akan ditempatkan dengan penundaan 5 ns pada sumbu waktu. Yaitu itu akan menjadi 10 ns. Maka proses akan berlanjut sampai waktu simulasi yang ditentukan berakhir.
Sekarang mari kita tambahkan sinyal
a dan
b .
Sinyal
a ditugaskan dalam proses. Untuk sinyal
b , konstruksi bersyarat saat digunakan; Fungsi rising_edge (
clk1 ) mem-parsing
clk1 dan mengembalikan
true ketika bagian depan diperbaiki, mis. nilai sebelumnya adalah 0 dan nilai saat ini adalah 1.
Pada model waktu 5 ns,
clk1 akan berubah. Itu akan menjadi sama dengan 1 dan untuk saat 10 ns suatu acara akan dibuat dari pengaturan ke 0. Tapi ini nanti. Sementara kami masih dalam 5 ns dan kami terus perhitungan. Simulator menuju ke garis
b<=a when rising_edge(clk1);
Karena ada fungsi yang bergantung pada
clk1, simulator akan menghitung nilai fungsi, melihat bahwa ia mengembalikan true dan akan menetapkan
b<=a;
Di sini bagian yang paling menarik dimulai - ketika perlu untuk mengubah nilai
b . Tampaknya perlu untuk mengubahnya sekarang, pada saat ini. Tetapi kami memiliki proses paralel. Mungkin kita masih membutuhkan nilai
b untuk menghitung sinyal lain. Dan inilah konsep penundaan delta. Ini adalah nilai minimum dimana waktu model bergeser. Nilai ini bahkan tidak memiliki dimensi waktu. Ini hanya sebuah delta. Tetapi mungkin ada banyak dari mereka. Dan simulator itu berhenti karena kesalahan atau macet.
Jadi, nilai baru
b akan ditetapkan untuk momen 5 ns + 1 (1 adalah penundaan delta pertama). Simulator akan melihat bahwa tidak ada yang perlu dihitung untuk saat ini 5 ns dan akan pergi ke saat berikutnya, dan ini akan menjadi 5 ns + 1; Saat ini, rising_edge (ckl1) tidak berfungsi. Dan nilai b akan ditetapkan ke 1. Setelah itu, simulator akan menuju ke saat 10 nc.
Sekarang mari kita tambahkan sinyal
c ,
d dan lihat mengapa mereka berbeda.
Yang terbaik untuk mempertimbangkan saat model waktu 25 n dengan mempertimbangkan penundaan akun
delta | clk1 | clk2 | re (clk1) | re (clk2) | b | c | d |
---|
0 | 1 | 0 | benar | salah | 0 | 0 | 0 |
---|
1 | 1 | 1 | salah | benar | 1 | 0 | 0 |
---|
2 | 1 | 0 | salah | salah | 1 | 0 | 1 |
---|
Catatan: re - rise_edge
Tabel menunjukkan bahwa pada saat fungsi rising_edge (
clk2 ) dipicu, nilai
b sudah 1. Dan karenanya, ia akan ditugaskan ke sinyal
d .
Berdasarkan akal sehat, ini bukan perilaku yang kami harapkan dari kode. Setelah semua, kami cukup menetapkan kembali sinyal
clk1 ke
clk2 dan berharap bahwa sinyal
c dan
d akan sama. Tetapi mengikuti logika simulator, ini tidak benar. Ini adalah fitur
PRINCIPAL . Fitur ini, tentu saja, harus diketahui oleh pengembang proyek FPGA dan oleh karena itu ini adalah pertanyaan yang baik dan perlu untuk wawancara.
Apa yang akan terjadi selama sintesis? Tetapi synthesizer akan mengikuti akal sehat, itu akan membuat sinyal
clk2 dan
clk1 satu sinyal dan karena itu
c dan
d juga akan sama. Dan dengan pengaturan synthesizer tertentu, mereka juga akan digabungkan menjadi satu sinyal.
Ini hanya kasus ketika pemodelan dan bekerja di peralatan nyata akan menghasilkan hasil yang berbeda. Saya ingin mencatat bahwa alasan untuk hasil yang berbeda adalah logika simulator dan synthesizer yang berbeda. Ini adalah perbedaan DASAR. Ini tidak ada hubungannya dengan kendala waktu. Dan jika proyek Anda di model dan di besi menunjukkan hasil yang berbeda, maka periksa, mungkin desain seperti itu merayap di sana
clk2 <= clk1
Sekarang pertanyaan kedua adalah memperbaiki kode ini dengan penundaan.
Ini adalah opsi 2. Ini dapat dihapus dan dimodelkan.
Inilah hasilnya.

Hasilnya benar. Apa yang terjadi Mari kita membuat tabel lagi untuk interval 25 - 36 ns
waktu | delta | clk1 | clk2 | re (clk1) | re (clk2) | b | c | d |
---|
25 | 0 | 1 | 0 | benar | salah | 0 | 0 | 0 |
---|
25 | 1 | 1 | 1 | salah | benar | 0 | 0 | 0 |
---|
26 | 0 | 1 | 1 | salah | salah | 1 | 0 | 0 |
---|
35 | 0 | 1 | 0 | benar | salah | 1 | 0 | 0 |
---|
35 | 1 | 1 | 1 | salah | benar | 1 | 0 | 0 |
---|
36 | 0 | 1 | 1 | salah | salah | 1 | 1 | 1 |
---|
Dapat dilihat bahwa nilai
b tidak berubah pada saat front
clk1 ,
clk2 . Penundaan 1 ns membutuhkan waktu saat sinyal berubah di luar zona respons tepi. Kode ini semakin mendekati kenyataan. Dalam rangkaian nyata, ada beberapa waktu untuk memicu untuk memicu dan untuk menyebarkan sinyal. Waktu ini harus kurang dari periode frekuensi jam, pada kenyataannya, inilah yang dilakukan pelacak, dan inilah yang diperiksa oleh analisis waktu.
Penyebab kesalahan adalah penugasan kembali sinyal clock oleh penugasan biasa di mana penundaan delta muncul. Namun, bahasa VHDL memiliki alias alias. Ini memungkinkan Anda untuk mendapatkan nama yang berbeda untuk sinyal tersebut. Berikut pengumumannya:
alias clk3 : std_logic is clk1;
Dalam teks contoh, Anda dapat menghapus komentar opsi 3 - itu akan berfungsi dengan benar.
Contoh ini ditulis dalam VHDL. Mungkin ini masalahnya hanya dari bahasa ini? Tapi di sini ada opsi yang sama di Verilog.
Teks tersembunyi `timescale 1 ns / 1 ps module delta_delay_2 (); reg clk1 = 1'b0; reg clk2; wire clk3; reg a = 1'b0; reg b; reg c; reg d; initial begin forever clk1 = #5 ~clk1; end initial begin repeat(10) begin #20 a = 1'b1; #60 a = 1'b0; end end
- Opsi 1 - tidak ada penundaan. Itu tidak berfungsi dengan baik.
- Opsi 2 - dengan penundaan. Itu bekerja dengan benar.
- Opsi 3 - penugasan kembali melalui kawat. Itu bekerja dengan benar.
Verilog memiliki konsep reg dan kawat. Dalam hal ini, penugasan kembali sinyal clock melalui kawat terlihat lebih alami. Ini analog dengan penugasan alias dalam VHDL. Ini agak mengurangi ketegangan dari masalah, tetapi Anda masih perlu tahu ini.
Verilog juga memiliki konsep tugas pemblokiran dan non-pemblokiran. Penugasan sinyal
b dan
c dapat ditulis dengan cara lain:
always @(posedge clk1) begin c = b; b = a; end
Dan Anda dapat melakukan ini:
always @(posedge clk1) begin b = a; c = b; end
Bergantung pada urutan garis, hasilnya akan berbeda.
Kembali ke topik wawancara, saya ingin menekankan sekali lagi bahwa pertanyaan-pertanyaan ini adalah untuk memahami esensi masalah. Dan dari pemahaman masalah, orang dapat menarik berbagai kesimpulan, misalnya, gaya kode yang digunakan. Secara pribadi, saya selalu menggunakan tugas keterlambatan.
File sampel tersedia di sini.