VHDL'de “umurumda değil” sinyallerini nasıl belirleyebilirim?


11

Mantık Tasarımı derslerinde hepimiz, örneğin bir Karnaugh haritası veya Quine – McCluskey algoritması kullanarak bir mantık işlevini en aza indirmenin mümkün olduğunu öğrendik . Ayrıca "Umurumda Değil" değerlerinin minimizasyon potansiyelini artırdığını öğrendik .

Örneğin bir kayıt dosyası alın. write_addressVe write_datane zaman sinyalleri gerçekten önemli değil write_enablesinyaldir '0'. Bu nedenle, bu sinyalleri yönlendiren mantıkta daha fazla optimizasyon sağlamak için bir "Umurumda Olma" değeri atanmalıdır (yani kayıt dosyasının kendisinde değil).

Sentez aracının olası optimizasyonlara daha fazla yer vermesini sağlamak için VHDL'de bu tür "Umursamayın" değerlerini belirtmenin doğru yolu nedir?


Şimdiye kadar uygun olabilecek aşağıdaki şeyleri buldum. Ama her bir yaklaşımın artıları ve eksileri neler olduğundan emin değilim:

  • Sadece sinyali atamamak. Bu işe yarayabilir gibi görünüyor. Ancak record, kayıt sabitlerinin tam olarak belirtilmesi gerektiğinden (en azından Modelsim bana söyler) bazı tür "sabit bir şey yapma" tanımlamak istediğinizde işe yaramadı buldum .
  • std_logic_1164Paket değerini tanımlar '-' -- Don't careiçin std_ulogic. Bu, açık bir "umrumda değil" için anlamsal olarak doğru bir seçim gibi görünüyor, ancak daha önce hiçbir yerde kullanıldığını görmedim (ilgisiz VHDL-2008 case?yapıları hariç ).
  • Modelsim bu değeri 'X'tanımsız sinyalleri görüntülemek için kullanır . Ancak sentez araçlarının açık bir 'X'atamayı "umursamadıkları" olarak anlayıp anlamadıklarından emin değilim .

Burada, önemsiz sinyalleri başlattığım açıklama için basitleştirilmiş bir kod snippet'i var '-'.

Gördüğünüz gibi, sinyal control.reg_write_address3 farklı değerlere sahip olabilir: "----", instruction(11 downto 8);ve instruction(3 downto 0);. Şimdi '-'"umurumda değil" olarak yorumlanırsa, bunun 2 girişli bir çoklayıcıya sentezlenmesini beklerdim . Birlikte sinyal başlatılır vardı (others => '0')yerine '-', araç yerine 3-giriş çoklayıcıyı oluşturmak gerekir.

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

package mytypes is
    type control_signals_t is record
        write_enable  : std_logic;
        write_address : std_ulogic_vector(3 downto 0);
        read_address  : std_ulogic_vector(3 downto 0);
    end record;

    -- All members of this constant must be fully specified.
    -- So it's not possible to simply not assign a value.
    constant CONTROL_NOP : control_signals_t := (
        write_enable  => '0',
        write_address => (others => '-'),
        read_address  => (others => '-')
    );
end package;

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

entity control_unit is
    port(
        instruction : in  std_ulogic_vector(15 downto 0);
        write_data  : out std_ulogic_vector(15 downto 0);
        ctrl        : out control_signals_t
    );
end entity;

architecture rtl of control_unit is
begin
    decode_instruction : process(instruction) is
    begin
        -- Set sensible default values that do nothing.
        -- Especially all "write_enable" signals should be '0'.
        -- Everything else is mostly irrelevant (don't care).
        ctrl       <= CONTROL_NOP;
        write_data <= (others => '-');

        if instruction(15 downto 12) = "1100" then
            -- Load 8 bit of data into the register file
            ctrl.write_enable  <= '1';
            write_data         <= std_ulogic_vector(resize(signed(instruction(7 downto 0)), 16));
            ctrl.write_address <= instruction(11 downto 8);
        elsif instruction(15 downto 8) = "11111001" then
            -- Load 4 bit of data into the register file
            write_data         <= std_ulogic_vector(resize(signed(instruction(7 downto 4)), 16));
            ctrl.write_address <= instruction(3 downto 0);
        elsif instruction(15 downto 8) = "10110101" then
            -- Read from the register file. Don't use the write signals at all.
            ctrl.read_address <= instruction(3 downto 0);
        end if;
    end process;
end architecture;

Eğer yapmak istediğiniz şeyi daha açar mısın söylediğini write_addressve write_data? Hangi optimizasyonun gerçekleşmesini bekliyorsunuz?
fru1tbat

Umarım örnek neyi başarmak istediğimi daha açık hale getirir.
Fritz

Yanıtlar:


9

Daha ayrıntılı bir cevap vermek için bunu bir LRM uzmanına bırakacağım, ancak kısacası yaklaşımınız geçerli olmalı - Quartus'un son bir sürümü ile hızlı bir test yaptım ve '-'olması gerektiği gibi işliyor - oluşturulan mantık azaltıldı Çıktı varsayılan olarak ayarlandığında beklendiği gibi '-'( 'X'bu arada da çalışır). Listelediğiniz yaklaşımlar hakkında daha fazla bilgi:

  • Sinyali atamamak, mandal istemiyorsanız, elbette örneğin bir seçenek değildir. Saatli bir işlemse, biraz daha iyi durumdasınız, ancak yine de onlara ihtiyacınız olmayacak yerlerde etkinleştirirsiniz. Belki burada niyetini özlüyorum.

  • '-', daha önce de belirtildiği gibi, hem semantik hem de pratik nedenlerle muhtemelen en iyi seçenektir.

  • "Undefined" ile ne demek istediğinize bağlı. 'X'teknik olarak "bilinmiyor". 'U'ModelSim'in "X"onaltılık gösterimde görüntülediği başlatılmamış sinyaller içindir . 'X'yine de, yukarıda da belirttiğim gibi çalışıyor.

Başka bir alternatif, optimizasyonu kendiniz yapmak ve bir vakayı açıkça test edilmekten kaldırmak olabilir:

if instruction(15 downto 8) = "11111001" then
  write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 4)), 16));
else
  write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 0)), 16));
end if;

Bu önemli dezavantajları (çoğunlukla kod netliği ile ilgili) olsa da, ve muhtemelen daha ideal bir çözüm tercih ediyorum.

Bu arada, '-'std_match() kod çözme için kullanmayı düşüneceğim yaygın olarak da kullanılır , örneğin:

if std_match(instruction(15 downto 8), "1100----") then

Bu noktada, muhtemelen sadece kullanmaktan daha iyi olursunuz case?.


6

Kısacası: Yasal VHDL'dir ve genellikle sentez araçlarıyla desteklenir.

Ancak kullanıldığını görmek oldukça nadirdir. Nedenini gerçekten bilmiyorum. Kodunuz bana bunu kullanmanın ne zaman anlamlı olacağını gösteren iyi bir örnek gibi görünüyor.

Bununla birlikte, bilinmesi gereken bir dezavantaj vardır: sentezde, umursamayanların dahil olduğu çıktıları tahrik eden fonksiyonlar sentez çalışmaları arasında farklı olabilir . Bu, sentezi daha az belirleyici yapar. Umurumda değil olarak tanımlanan çıkışlar kullanılırsa (yanlışlıkla), bu, hatanın bulunmasını zorlaştırabilir.

Araç desteği

En azından aşağıdaki araçlar, umursamaz ve optimizasyon olanaklarından yararlanır:

  • Xilinx (ref .: "XST Kullanım Kılavuzu")
  • Altera (ref .: "Önerilen HDL Kodlama Stilleri")
  • Synplify (ref .: "Referans kılavuzu synplify")

Xilinx ve Altera, umursamadıkları gibi davranacaklar '-'ve 'X'Synplify bunlara ve dahası 'U've 'W'(zayıf) umursamadıkları gibi davranacaklar .


1
Bu dezavantajın başka bir uygulaması daha vardı. Benim kod benziyordu çünkü kod, FPGA üzerindeki simülasyonunda işlenmiş fakat: if signal = '1' then a; else b; end if;. Ne yazık ki signaldeğildi 1ya da 0ama -. Simülasyonda, elseşube idam edildi, ancak donanımda bir olduğu -ortaya çıktı 1, bu yüzden gerçek şube idam edildi ...
Fritz

Evet, benzer hatalar simülasyonu geçirdim, ancak çoğu zaman benim durumumda 'U', bazı elsekod bloklarının yürütülmesine yol açan simülasyonların başlangıcında yaygın olan s'ler var . 'U'Eşzamanlı boole ifadelerinin davranışına benzer şekilde koşulların bir şekilde yayılması için harika bir şey yapılabilir .
Carl

Bu hatayı buldum sonra hep böyle bir şey yazmak emin oldum if signal = '1' then output <= '1'; elsif signal='0' then output <= '0'; else output <= '-'; end if;. Ve tüm kayıtlara ve anılara aşağıdakileri ekledim: assert not is_X(write_enable) report "we=" & str(A_write_enable) severity ERROR;ve if write_enable = '1' then assert not is_X(write_addr) report "write_addr=str(write_addr) severity ERROR; end if;. Artı aynı write_data. Birlikte, bu neredeyse tüm bu hataları yakalamalıdır.
Fritz

Bu bir yol, ama bu benim için çok ayrıntılı. Bu olasılığı VHDL dilinde diliyorum.
Carl

1
Evet, VHDL biraz ayrıntılı, ama bu sadece VHDL yolu. : D Öte yandan, aynı zamanda çok açık ve arkamda "kara büyü" yapmaz, ki oldukça hoş buluyorum (bkz. Python Zen "Açık" örtük daha iyidir ").
Fritz
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.