VHDL görüşme sorusu - bir sayının geri kalanı olmadan 5'e bölünüp bölünmeyeceğini saptamak


24

VHDL için güzel bir röportaj sorusu gördüm - sayı alan ve geri kalanı olmadan 5'e bölünebilecek olup olmadığını tespit eden bir sistem inşa ettim. Bunu bir durum makinesiyle çözmeye çalıştım (sanırım mod veya rem kullanmanızı istemiyorlardı ) ve ilk başarımı elde ederken (5, 10, 15 gibi sayılar ve 20, 40, 80 gibi sayılar çalıştı. ), 130, 75 vb. gibi diğer numaralar benim için başarısız oldu.

Durum makinemi gösterirdim ama bu tamamen karışık bir durum (bir kod değil, çizim) ve dediğim gibi, çalışma bile.

Temel olarak yapmaya çalıştığım, 5 ile bölünebilen ikili sayılarla yazmak ve onlar için çalışacak bir durum makinesi oluşturmak.

Bana bu sorunu nasıl çözeceğimi ve bunun gibi bir şeyle karşı karşıya kalırken nasıl düşüneceğinizi gösterebilirseniz sevinirim.

Teşekkür ederim!


Bir (sentezlenebilir) donanım uygulaması demek istiyorsun, sadece bir tamsayının hazır değerinin 5 ile bölünebilir olup olmadığını test etmek için kod değil (örneğin, test tezgahı için).
smci

@smci Aslında bir devlet makinesinin şematik / çizimini istiyordum, ama bu durum makinesinin bir kodu zarar görmezdi. Dave Tweed soruyu mükemmel bir şekilde cevapladı.
Eran

sonra onu geri alırdım * "VHDL mülakat sorusu - eğer tespit etmek için cct ..."
smci

Buraya cevap egreg math.stackexchange.com/a/2569882/213607 , daha fazla paralellik yaklaşımı için ilham verebilir.
mathreadler

Yanıtlar:


37

Seri moda kalan bir işlem yapmak aslında oldukça kolaydır. Temel varsayım, verilerin seri olması halinde ilk önce MSB'de gelmesidir. Kalan bir modulo N'yi hesaplamak için yalnızca N durumuna ihtiyacınız var. sıfır.

şematik

bu devreyi simüle et - CircuitLab kullanılarak oluşturulan şematik

Kalanları takip etmek için gereken tek şey kalanı ise, uzun bölünmeyi nasıl yapacağınızı düşünün:

process (clk)
begin
  if rising_edge(clk) then
    if reset = 1 then
      state <= 0;
    else
      if (state & din) >= N then
        state <= (state & din) - N;
      else
        state <= state & din;
      end if;
    end if;
  end if;
end process;

6
Vay canına, bunun işe yaradığını gördüm ama durum makinesini nasıl bulduğunuzu açıklayabilir misiniz? Başlangıç ​​noktası neydi? Bunu daha önce hiç görmedim, sadece mantığın nasıl ortaya çıkacağını merak ediyorum mu?
zoder

7
Durum şeması, N = 5'in özel durumu için VHDL kodundan tam olarak ne elde ettiğinizi gösterir. Başka bir deyişle, eğer durum mevcut kalanı temsil ediyorsa, bir sonraki durum, durumu bir bit sola kaydırdığınızda ne elde edeceğinizdir, giriş bitini ona ekleyin ve gerekirse 5'i çıkarın.
Dave Tweed

3
Bu güzel olursa, röportajda biri kendi başına gelirse, gerçekten etkilenirdim. Ve sonra mutlu bir şekilde onlardan sentez sonuçlarının her saat döngüsünde tam bir vektörü işlemek için rem operatörü kullanmaya göre nasıl farklılık göstereceklerini açıklamalarını isterim.
Casperrw

8
@zoder Durumlar, mod 5 kalıntılarıdır; 0 oku işaret eder 2n mod 5ve 1 oku işaret eder (2n + 1) mod 5.
hobbs

2
Eğer bildirimleri eklemek Could state, dinve Nkodunuzu?
mkrieger1

15

Veriler önce LSB gelirse bir durum makinesi de tasarlayabilirsiniz:

Ekte bu cevabın sonunda açıklanan DFA'nın bir grafik gösterimi.

Böyle bir deterministik sonlu otomatın (DFA) varlığı, MSB-ilk için DFA'yı tanımlayan diğer cevaptan doğrudan gelir . DFA'lar tarafından kabul edilen dillerin düzenli olması ve normal dillerin ters çevrilmesiyle kapatıldığı biliniyor (örneğin , buraya bakınız ), aşağıdaki dili kabul eden bir DFA olmalıdır:

.L={w{0,1}| reverse(w)10 is divisible by 5}

İnşaat

  1. MSB'nin ilk DFA'sını Dave Tweed'in cevabından kopyalayın . Bunun için JFLAP otomasyon aracını kullandım .

  2. Açık dönüşüm algoritmasını DFA ters çevrmeleri için uygulayın, örneğin CS.SE: Bir DFA tasarlanması ve bunun tersi .
    Bu adımın (küçültülmemiş) sonucunu bu cevabın eski sürümünde görebilirsiniz .

  3. Elde edilen DFA'yı en aza indirin. Ne yazık ki, bu özellik en son JFLAP versiyonunda küçük bir sorun, bu yüzden elle küçültmek için kendimi istifa ettim.
    Yine, onlar için birçok algoritma ve kaynak var, tutorialspoint.com'da “DFA Minimizasyon” da açıklananı kullandım .

    (Aslında, gözleriniz DFA'lara bakacak şekilde yeterince iyi eğitilmişse, doğrudan q 0 ve q 1'in DFA'da 2. maddede elde edildiği gibi eşdeğer durum olduğunu doğrudan görebilirsiniz . !)q0q1

Aslında, ortaya çıkan otomat doğru cevapları verir:

"Girdi" ve "Sonuç" şeklinde iki sütunlu tablo, çeşitli numaraların "Kabul Et" veya "Reddet" ile sonuçlanıp sonuçlanmadığını listeler.


Arev5=(Q,Σ,δ,q0,F)Q={q0,q1,q2,q3,q4}Σ={0,1}F={q0}δ

δ(q0,0)=q0,δ(q0,1)=q1δ(q1,0)=q4,δ(q1,1)=q3δ(q2,0)=q1,δ(q2,1)=q2δ(q3,0)=q2,δ(q3,1)=q4δ(q4,0)=q3,δ(q4,1)=q0


DFA'yı geri çevirmekte zorlanıyorsanız, denklemi de tersine çevirebilirsiniz: new_state = state * 2 + input yerine, (new_state - input) / 2 = state komutunu, ardından durumu ve new_state komutunu kullanabilirsiniz. Yeni denklem için DFA, LSB-ilk problemini çözmelidir.
Eyal

Neden q3 ve q4 bu şekilde etiketlenmiştir ve tam tersi değildir? Q3 ve q4 etiketlerini değiştirin ve makine algo "yarım (mod 5) ve giriş bitini ekle" yi uygular.
Rosie F,

2
@RosieF: "yarım (mod 5)" ifadesi, ayrık matematiğe aşina olmayanlar için belki biraz daha açıklama kullanabilir. Bu bağlamda takım eşit, bu nedenle 3/2 (mod 5) (3 + 5) / 2, örneğin 4 olabilir sayısı bölme yapmak için gerekli olacaktır baz ne olursa olsun çok eklenmesini içerir
SuperCat

7

(Önce MSB) durum makinesini ortaya çıkarmanın bir yolu şöyledir:

  1. Şimdiye kadar alınan numara N. Kalanı bildiğini varsayalım M = N mod 5.

  2. Yeni bir bit geliyor ve şimdi yeni bir değer var N' = N*2 + b.

  3. Yeni kalanlar o zaman M' = (N*2 + b) mod 5 = (M*2 + b) mod 5.

Bu, elle tablo oluşturmak için yeterince kolaydır:

    M b | M'
------------------
    0 0 | 0
    1 0 | 2
    2 0 | 4
    3 0 | 1
    4 0 | 3
    0 1 | 1
    1 1 | 3
    2 1 | 0
    3 1 | 2
    4 1 | 4

Dave Tweed'in cevabındaki durum makinesiyle aynı.


5

Mülakat sorusu, VHDL veya Verilog'un giriş ve çıkışlarından ziyade problemi nasıl çözeceğinizi umuyor. Bir algoritmaya sahip olduğunuzda dil detayları açıktır.

S=0S(2S+d) mod 5 SS,dS=0,,4

S=0,k=0S(S+2kd) şık 5,kk+1k24=1 şık 5S(S+2kd) şık 5,k(k+1) şık 4S,k,d(S,k)S=0,,4k=0,,3


3

VHDL'nin ne için yazıldığına bağlı olarak, doğrudan, birleşik hesaplama olarak tanımlayan bir yaklaşım benimsemek isteyebilirsiniz. Sayı almak, tüm sayının bir saat döngüsü için kayıtta olacağı anlamına gelebilir.

Örneğin, bitlerin her birinin temsil ettiği değerin mod 5'ini not alabilir, bunları birlikte ekleyebilir ve ardından işlemi 5'ten küçük bir değere bırakılana kadar tekrarlayabilirsiniz. veya mantığı, az sayıda döngü için tekrar kullanın.

Ancak VHDL rem operatörünü kullanırsanız, bu doğru cevap olabilir. Şirketin iyi bir sentezleme aracı olduğunu varsayarsak, bu size oldukça verimli bir uygulama sağlayacaktır - devlet makinelerinin çözümlerinden biraz daha fazla alan, ancak tam kapasite ve dolayısıyla hesaplama başına muhtemelen iyi enerji. İşveren için uygulanması en az zaman ve bu nedenle muhtemelen en az paraya mal olacak bir seçenektir!

Adil olmak gerekirse, muhtemelen böyle bir soruyla aradıkları cevap değil - aynı zamanda herhangi bir gerçek tasarım deneyimini göstermek için de bir fırsattır.


3

Sayı, bir bitten büyük parçalar halinde sunulursa, kalıntı mod 15'i hesaplamak için bazı paralel hesaplamaları kullanmak faydalı olabilir, ancak hesaplamanın tam olarak sıfır olduğu takdirde hesap 15'in verebilmesi şarttır. Mod-15 tortusunu hesaplamanın basit bir yolu, N> = 1'in herhangi bir değeri için, en soldaki 4N bitinin, bir sayıdaki kısmına, orjinal mod 15 ile uyumlu bir değer vereceğini gözlemlemektir. mevcut kaynaklara bağlı olarak sorunun farklı şekillerde alt bölümlere ayrılmasını sağlar.

Örneğin, biri 32 bitlik bir değerle başlarsa, sekiz adet 4 bitlik değer olarak değerlendirilebilir. Bunlar, iki adet 6-bitlik değer veya bir adet 7-bitlik değerde birleştirilebilen dört adet 5-bitlik değer elde etmek için birlikte eklenebilir. Bu 7 bitlik değerin üst üç bitini düşük 4 bit'e eklemek, en fazla 21 olan 5 bitlik bir değer verecektir. Böylece, son değerin olup olmadığını gözlemleyerek orijinal değerin 5 katı olup olmadığını belirleyebilirsiniz. 0, 5, 10, 15 veya 20'den biri.


... ya da 4-bit eklentileri kullanabiliyordunuz ve her bir uygulamanın devrede daha sonra bir toplayıcı için bir taşıma haline geldiğinden emin olmalısınız. Üç katmanın eklenmesinden sonra, 4 bitlik tek bir sonuç elde edersiniz ve henüz kullanılmamış dört taşıyıcı kullanırsınız. Son 4-bit ilaveye paralel olarak taşıyıcılardan üçünü toplayın ve son taramayı olduğu gibi sonuçlarına toplamlarını ekleyin. Bu, en fazla 19 elde edilir, bu yüzden 20'den sonra eşleşmeniz gerekmez.
Henning Makholm

@HenningMakholm: İstenilen sonucu elde etmek için ekleyicileri düzenlemenin birçok yolu vardır. Belirli bir durumda hangi yaklaşımın daha iyi olacağı muhtemelen projeye özgü yönlendirme veya kaynak kullanımı sorunlarına bağlı olacaktır. Diğer bir püf noktası ise bir taşıma tasarruflu ekleyici kullanmak olacaktır, ancak kaydırılan çıktının üst kısmının dibe kaydırılabileceği gerçeğinden yararlanın. Böylece, bir katman 8 girişi 6'ya, ardından 6'yı 4'e, ardından 4'ü 3'e ve 3'e 2'ye döndürebilir. Her katmanın bir çıkışı basitçe AND geçitleri ve diğeri XOR geçitleri olacaktır, bu nedenle yayılma süresi bir 4-bitlik değer çifti ...
supercat

... bir ve sadece taşıma zinciri, dört xor kapısına ait olacaktır. Çıktıyı 19'un altına düşürmenin daha iyi olup olmadığı ya da 20'nin olası bir kalıntı olarak kontrol edilmesinin daha iyi olup olmadığı konusunda, bu muhtemelen kaynak mevcudiyetine ve kullanımına bağlıdır. 30'dan fazla olmayan bir sayı verildiğinde, üst ve alt naylonların eklenmesi en çok 15 (ya 16 + 14-> 1 + 14 ya da 0 + 15-> 0 + 15) olan, ancak açık olan bir değer verir. (20, 25, 30) 'dan bazıları veya tümü için kontroller daha ucuz olabilir.
Süperkat

2

VHDL'mi hatırlayamıyorum, ama işte ilk akla gelen fikrin bir taslağı:

İlk ikisinin ilk basamağının son basamağı (10 bazında) 1, 2, 4, 8, 6, 2, ... ve döngü tekrar eder. Bu nedenle, ikisinin güçlerinin 5 mod 1, 2, 4, 3, ....

Bunu kullanarak, bitlerde LSB'den kayabilir ve bir 1bit görüldüğü zaman pozisyona karşılık gelen kalan modları (5) biriktirebiliriz . Biriktirme modu 5 de yapın ve sonunda toplamın sıfır olup olmadığını kontrol etmek yeterlidir.


1

Buradaki cevabı kullanarak düşünceyi kullanabiliriz, 4 numaralı temelde, bir rakamın 5 rakamıyla bölünebildiğini ancak alternatif basamak toplamı ise elde edilebilir. Biz bu yüzden

  1. basamakları 2'ye 2 göre gruplayın,
  2. tekleri toplayın ve çift 2 bitlik blokları çıkarın.
  3. Sonuç birkaç bitin iki tamamlayıcı bölgesinde ise, örneğin [-4,3] (iki tamamlayıcı kullandığımızı varsaymak kolaydır) o zaman bittik ve orijinal sayıyı yalnızca 5 sonuçta bölebiliriz. toplamı kontrol etmek için çok basit bir mantıksal ifade olan 0'dır (temelde sadece ne büyük ne de sonuçta elde edilen bitlerde, hayır?)
  4. Aksi takdirde, yeni olanı yineleriz (çok daha kısa sayı).

166 = (10) (10) (01) (10): 2,2,1,2 sayısını deneyelim.

2-2 + 1-2 = -1

bu, mutlak değerde <= 3'tür ve 0 değil, neden sadece bir yinelemede 166'ın eşit olarak bölünmediği sonucuna varabiliriz.

Küçük bir hafızanın, kapıların hızı / sayısı bakımından yinelemekten daha ucuz / daha iyi olabileceği olabilir. Elbette bir kişi en kötü olanı önceden hesaplayabilir (izin verilen girdiler göz önüne alındığında mümkün olan en büyük sonuç) ve tasarımı buna göre planlayın.


1

MSB yaklaşımı kesinlikle daha kolay, ancak MSB çözümünü oluşturmaya gerek duymadan LSB durum diyagramını yapmayı başardım ... sadece birkaç saatimi aldı. @ComFreek tarafından gösterilene eşdeğer olduğu ortaya çıktı, sadece farklı şekilde açıklamalı.

İki numara izleyeceğiz. İlk önce, çalışan toplamı izleyeceğiz, modulo 5 ("SUM"). İkincisi, modulo 5 ("NEXT") olarak değiştirilecek bir sonraki 2 değerinin değerini izleyeceğiz. Her durumu, üstte "SUM" ve olası "NEXT" değerleri için altta gösterecekler.

"SUM" modulo 5'in 0 olduğu durumla başlayalım:

ilk


Şuna benzeyen bir durum olduğuna dikkat edin: 3,2,4,1
1,4,3,2

eşittir:
1,3,4,2
2,1,3,4

Çünkü her iki durum da şunları temsil eder:
SUM = 1 ve NEXT = 4 VEYA
SUM = 2 ve NEXT = 3 VEYA
SUM = 3 ve NEXT = 2 VEYA
SUM = 4 ve NEXT = 1.

Tamam, öyleyse, şimdi görüşmelere katılanların çoğu yalnızca bir devlet durumundaki bir durum diyagramından etkilenmeyeceğinden, şimdi ekstra devletler geliştirmemiz gerekiyor. Her devletin iki geçişi olduğunda işimiz bitti.

Ne zaman yeni bir duruma geçerseniz, "SONRAKİ" içindeki her sayı iki katına çıkar, daha sonra 5 modulo'lanır. "TOPLA" için şu kuralları izleyin:

  • 0 boyunca geçiş yaptıysanız, üst satır değerlerini korur.
  • 1 boyunca geçiş yaptıysanız, her sütun eski durumun "SUM" + "SONRAKİ" modülo 5'tir.

Öyleyse, gelen bit 1 olduğunda geçişleri doldurarak başlayalım.

Tüm 1'ler

Tamam, şimdi sıfırları dolduruyoruz. Sadece bir devlet eklendi, devam edeceğiz ve geçişlerini de dolduracağız.

Tamamlayınız

Ve işte! MSB çözümünü oluşturmak zorunda olmadan önce LSB'yi kabul eden bir devlet makinemiz var.


1

Yukarıdakilerin hepsi çok karmaşık görünüyor! İkili bir tamsayı beşe bölünebilir olup olmadığını algılamak için kolay bir matematik yolu var. Başlamak için, sıradan ondalık aritmetikte "dokuzları dökmek" nasıl yapılır hatırlıyor musunuz? Ondalık bir tamsayıdaki kalıntı modulo 9, rakamlarının toplamının kalıntı modulo 9 ile aynıdır. Bu işe yarıyor, çünkü 9 sayı tabanından az.

Alternatif basamakların işaretlerinin negatif olduğu “yükselme” gibi benzer bir süreç var. Bu işe yarıyor, çünkü on biri sayı tabanından büyük.

Dolayısıyla, beşlik dağıtmak istiyorsak, tamsayımızı dördüncü sayı olarak gösterebiliriz. Daha sonra ilk toplam olarak en düşük basamak çiftiyle başlar ve bir sonraki toplamı elde etmek için bir sonraki basamak çiftinden çıkarırız. Aday tamsayımız bu şekilde geçtikten sonra, asıl tamsayımız 5 ile bölünebiliyorsa, nihai toplam sıfır olur veya 5 ile bölünebilir.

Örnek 70: 01 00 01 10 -> 01 00 -1 -> 01 01 -> 00, 5 ile bölünebilir. Örnek 49: 11 00 01 -> 11 -1 -> 1 00 -> 1, DEĞİL 5 ile bölünebilir

Birikmiş farkın işareti ve taşırken ortaya çıkan durumlar için ekstra bir bit taşımanız gerektiğini unutmayın.

Gitmenin bir başka yolu, kalıntı modülo 15'i elde etmek için sadece altıgen rakamları eklemektir. Elbette sıfır, beş ve on kabul edilebilir üç sonucu tanımlamak için son bir mantık adımına ihtiyacınız var.

Örnek 70: 4 6 -> A, yani 70, 5 ile bölünebilir (ancak 15 ile değil). Örnek 49: 3 1 -> 4, yani 70, 5 ile bölünemez.

Çok sayıda bölünebilirlik testi oluşturmak için farklı sayı tabanları kullanabileceğinizi unutmayın, ancak bilgisayar mantığında 2 +/- 1 güçlerinin uygulanması en kolay olanıdır.

Ondalık aritmetikte, favorilerimden biri artık mod 7 için testim. 100'ün 7'nin ikiden büyük olduğunu not edin, bu yüzden rakamları çiftler halinde gruplandırın (100 numaralı sayıdaki çalışma) birimlerden yüzlerce TWICE ekleyin. Burada soldan sağa çalışıyoruz ...

Örnek: 98 76 -> 2 72 -> 76, bu yüzden 9876 7 ile bölünemez. 6 mod 7'dir. Örnek: 03 45 67 -> 51 67 -> 1 69 -> 71 1 mod 7.

Tabii ki, ikili olarak, sadece sekizlik basamakların toplamını alın (3 bitlik gruplar).

Üzgünüm, keşke bir Verilog gurusu olsaydım, ama aritmetik hayatın bu aşamasında sunabileceğim tek şey. Bunun gibi birçok püf noktası için Ron Doerfler'in "Ölü Hesaplaşma" bölümüne bakın.


Kanadalı kuzenlerimizin bazı özel algoritmaları olup olmadığını merak ediyorum. Kanada kuruşunu yasa dışı bıraktıklarından, tüm fiyatlar en yakın 0,05 dolara yuvarlandı.
richard1941,

1

Bir VHDL görüşme sorusu, bazı VHDL kodlarıyla sonuçlanmalıdır.

Dave Tweed'in devlet geçiş tablosunun bir uygulamasıyla bir ghdl llvm arka uç hatası bulma fırsatım oldu ;

type remains is (r0, r1, r2, r3, r4); -- remainder values

    function mod5 (dividend: bit_vector) return boolean is
        type remain_array is array (NBITS downto 0) of remains;
        type branch is array (remains, bit) of remains;
        constant br_table:  branch := ( r0 => ('0' => r0, '1' => r1),
                                        r1 => ('0' => r2, '1' => r3),
                                        r2 => ('0' => r4, '1' => r0),
                                        r3 => ('0' => r1, '1' => r2),
                                        r4 => ('0' => r3, '1' => r4)
                                      );
        variable  remaind:    remains := r0;
        variable tbit:        bit_vector (NBITS - 1 downto 0) := dividend;
    begin
        for i in dividend'length - 1 downto 0 loop
            remaind := br_table(remaind,tbit(i));
        end loop;
        return remaind = r0;
end function;

İlişkili test durumu oldukça küçüktür ve hata ayıklamanın daha kolay olmasını sağlar ve numaralandırılmış tipte kalıntılar için VHDL ile uyumlu durum adlarını kullanır:

dave_tweed.png (Dia ile yaratıldı)

Buradaki fikir, işlevin (hatta 27 satırlık bir VHDL programının bile) bir görüşme sırasında VHDL cevabı yazabilecek kadar kısa olmasıdır. Hem bilgi hem de beceri gösterilmesini gerektiren bir görüşme sorusunu bozma konusunda endişelenmenize gerek yok, bir görüşmecinin sorgulandığında bir uygulamayı savunması beklenir.

(Llvm arka uç hatası, bugün erken saatlerde 1f5df6e olarak düzeltildi .)

Dikkat edilecek hususlardan biri, devlet geçiş tablosunun ayrıca bir bölüm bitinin, 5'i temettüden çıkarırken düşük kalan değere sahip bir duruma (veya her ikisi için r4 için geçişler) gösterilen bir '1' olacağını gösterir. Bu ayrı bir tabloda (veya hantal gibi görünen bir kayıt türünde bir tabloda) kodlanabilir. Bunu tarihsel olarak 5 pikselin katları olan yatay ekran çözünürlükleriyle ilgilenen grafik donanımında yapıyoruz.

Bunu yapmak bize bir bölüm ve geri kalanı üreten bir div / mod5 verir:

library ieee;
use ieee.std_logic_1164.all;

entity divmod5 is
    generic (
        NBITS:  natural := 13 
    );
    port (
        clk:        in  std_logic;
        dividend:   in  std_logic_vector (NBITS - 1 downto 0);
        load:       in  std_logic;
        quotient:   out std_logic_vector (NBITS - 3 downto 0);
        remainder:  out std_logic_vector (2 downto 0);
        remzero:    out std_logic
    );
end entity;

architecture foo of divmod5 is
    type remains is (r0, r1, r2, r3, r4); -- remainder values
    type remain_array is array (NBITS downto 0) of remains;
    signal remaindr:    remain_array := (others => r0);
    signal dividendreg: std_logic_vector (NBITS - 1 downto 0);
    signal quot:        std_logic_vector (NBITS - 3 downto 0);
begin

parallel:
    for i in NBITS - 1 downto 0 generate
        type branch is array (remains, bit) of remains;
        -- Dave Tweeds state transition table:
        constant br_table:  branch := ( r0 => ('0' => r0, '1' => r1),
                                        r1 => ('0' => r2, '1' => r3),
                                        r2 => ('0' => r4, '1' => r0),
                                        r3 => ('0' => r1, '1' => r2),
                                        r4 => ('0' => r3, '1' => r4)
                                      );

        type qt is array (remains, bit) of std_ulogic;
    -- Generate quotient bits from Dave Tweeds state machine using q_table.
    -- A '1' when a remainder goes to a lower remainder or for both branches
    -- of r4. A '0' for all other branches.

        constant q_table:   qt :=     ( r0 => (others => '0'),
                                        r1 => (others => '0'),
                                        r2 => ('0' => '0', '1' => '1'),
                                        r3 => (others => '1'),
                                        r4 => (others => '1')
                                      );
        signal tbit:    bit;
    begin
        tbit <= to_bit(dividendreg(i));
        remaindr(i) <= br_table(remaindr(i + 1),tbit);
do_quotient:
        if i < quot'length generate   
            quot(i) <= q_table(remaindr(i + 1),tbit);
        end generate;
    end generate;

dividend_reg:
    process (clk)
    begin
        if rising_edge(clk) then
            if load = '1' then
                dividendreg <= dividend;
            end if;
        end if;
    end process;

quotient_reg:
    process (clk)
    begin
        if rising_edge (clk) then
            quotient <=  quot;
        end if;
    end process;

remainders:
    process (clk)
    begin
        if rising_edge(clk) then 
            remzero <= '0';
            case remaindr(0) is
                when r0 =>
                    remainder <= "000";
                    remzero <= '1';
                when r1 =>
                    remainder <= "001";
                when r2 =>
                    remainder <= "010";
                when r3 =>
                    remainder <= "011";
                when r4 =>
                    remainder <= "100";
            end case;
        end if;
    end process;

end architecture;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity divmod5_tb is
end entity;

architecture foo of divmod5_tb is
    constant NBITS:    integer range 0 to 13 := 8;
    signal clk:        std_logic := '0';
    signal dividend:   std_logic_vector (NBITS - 1 downto 0);
    signal load:       std_logic := '0';

    signal quotient:   std_logic_vector (NBITS - 3 downto 0);
    signal remainder:  std_logic_vector (2 downto 0);
    signal remzero:    std_logic;
    signal psample:    std_ulogic;
    signal sample:     std_ulogic;
    signal done:       boolean;
begin
DUT:
    entity work.divmod5
        generic map  (NBITS)
        port map (
            clk => clk,
            dividend => dividend,
            load => load,
            quotient => quotient,
            remainder => remainder,
            remzero => remzero
        );
CLOCK:
    process
    begin
        wait for 5 ns;
        clk <= not clk;
        if done'delayed(30 ns) then
            wait;
        end if;
    end process;
STIMULI:
    process
    begin
        for i in 0 to 2 ** NBITS - 1 loop
            wait for 10 ns;
            dividend <= std_logic_vector(to_unsigned(i,NBITS));
            wait for 10 ns;
            load <= '1';
            wait for 10 ns;
            load <= '0';
        end loop;
        wait for 15 ns;
        done <= true;
        wait;
    end process;

SAMPLER:
    process (clk)
    begin
        if rising_edge(clk) then
            psample <= load;
            sample <= psample after 4 ns;
        end if;
    end process;

MONITOR:
    process (sample)
        variable i:     integer;
        variable div5:  integer;
        variable rem5:  integer;
    begin
        if rising_edge (sample) then
            i := to_integer(unsigned(dividend));
            div5 := i / 5;
            assert div5 = unsigned(quotient)
                report LF & HT &
                    "i = " & integer'image(i) &
                    " div 5 expected " & integer'image(div5) & 
                    " got " & integer'image(to_integer(unsigned(quotient)))
                SEVERITY ERROR;
            rem5 := i mod 5;
            assert rem5 = unsigned(remainder)
                report LF & HT &
                    "i = " & integer'image(i) &
                    " rem 5 expected " & integer'image(rem5) & 
                    " got " & integer'image(to_integer(unsigned(remainder)))
                SEVERITY ERROR;
        end if;
    end process;

end architecture;

Burada bir Oluşturuş ifadesi ile uygulanır, bölüm bitleri üreten bir iç üreteç ifadesi kullanılır. Remaindr dizisi, bir durum geçişi izlemesi sağlar:

divmod5_tb.png

Hepsi aritmetik işlem yapmadan.

Ayrıca, modsuz olan parametrelerden faydalanan tüm kayıtlar olmadan bir prosedür uygulamak da mümkündür. Bu bir röportaj için minimum hatta yaklaşır.

Saatli bir sıralı uygulama bir bit sayacı ve akış kontrolü gerektirecektir (bir JK flip flop ve birkaç kapı).

Bir röportajda savunmanızın gerekebileceği temettü büyüklüğüne bağlı olarak zaman / karmaşıklık değişebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.