Skocz do zawartości

Pomocna odpowiedź

Napisano

Witajcie.

W kodzie bardzo często używamy konstrukcji if oraz else. To podstawowy mechanizm wyboru — jeśli warunek jest spełniony, wykonujemy blok if, w przeciwnym razie else. W praktyce oznacza to, że pierwszy warunek ma najwyższy priorytet, a kolejne są sprawdzane dopiero wtedy, gdy poprzednie nie zostały spełnione.

To oczywiste dla programisty, ale nie każdy wie, jak układ programowalny realizuje taki wybór elektrycznie. W FPGA nie ma „instrukcji if”. Jest tylko logika kombinacyjna. A odpowiednikiem if/elsif/else jest dekoder priorytetowy.

Dekoder priorytetowy to układ bramek logicznych, który:

  1. przyjmuje wiele wejść,
  2. wybiera najwyższy ustawiony bit,
  3. ignoruje wszystkie niższe bity.

Przykład (logika pozytywna):

Kod

wejście = 0000 01010 wyjście = 0000 01000

Bit 3 jest najwyższym ustawionym bitem → więc tylko on przechodzi na wyjście.

Mój dekoder 1×8 — zoptymalizowany pod Spartan‑3 (LUT4)

To nie jest „książkowy” dekoder, ale jest zoptymalizowany pod LUT4 i działa bardzo dobrze.

Schemat w logisim:

image.thumb.png.7f7f71404dfb66471dd2695ec9a477fe.png

Kod VHDL:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity PriorityDecoder1x8 is
    Port ( Input : in  STD_LOGIC_VECTOR (7 downto 0);
           Output : out  STD_LOGIC_VECTOR (7 downto 0));
end PriorityDecoder1x8;

architecture Behavioral of PriorityDecoder1x8 is

   signal and1x8 : std_logic_vector(8 downto 0);

begin

   -- poziom górny(7,6,5,4)
   and1x8(8) <= not Input(7) and Input(6);
   and1x8(7) <= not Input(7) and not and1x8(8) and Input(5);
   and1x8(6) <= not Input(7) and not and1x8(8) and not and1x8(7) and Input(4);
   
   -- przeniesienie priorytetu do dolnego bloku
   and1x8(5) <= not Input(7) and not and1x8(8) and not and1x8(7) and not Input(4);
   
   -- poziom dolny (3,2,1,0)
   and1x8(4) <= and1x8(5) and Input(3);
   and1x8(3) <= and1x8(5) and not and1x8(4) and Input(2);
   and1x8(2) <= and1x8(5) and not and1x8(4) and not and1x8(3) and Input(1);
   
   -- przeniesienie priorytetu do najniższego poziomu
   and1x8(1) <= and1x8(5) and not and1x8(2);
   
   and1x8(0) <= and1x8(1) and not and1x8(4) and not and1x8(3) and Input(0);
   
   -- wyjście
   Output <= Input(7) & and1x8(8 downto 6) & and1x8(4 downto 2) & and1x8(0);


end Behavioral;

Kod symulacji układu w programie xilinx ise 14.6:

--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:   13:21:39 07/11/2026
-- Design Name:   
-- Module Name:   C:/xilinx_project/PriorityDecoder1x8/PriorityDecoder1x8_TB.vhd
-- Project Name:  PriorityDecoder1x8
-- Target Device:  
-- Tool versions:  
-- Description:   
-- 
-- VHDL Test Bench Created by ISE for module: PriorityDecoder1x8
-- 
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
-- Notes: 
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test.  Xilinx recommends
-- that these types always be used for the top-level I/O of a design in order
-- to guarantee that the testbench will bind correctly to the post-implementation 
-- simulation model.
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
 
ENTITY PriorityDecoder1x8_TB IS
END PriorityDecoder1x8_TB;
 
ARCHITECTURE behavior OF PriorityDecoder1x8_TB IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT PriorityDecoder1x8
    PORT(
         Input : IN  std_logic_vector(7 downto 0);
         Output : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal Input : std_logic_vector(7 downto 0) := (others => '0');

 	--Outputs
   signal Output : std_logic_vector(7 downto 0);
   -- No clocks detected in port list. Replace <clock> below with 
   -- appropriate port name 
 
--   constant <clock>_period : time := 10 ns;
 
BEGIN
 
	-- Instantiate the Unit Under Test (UUT)
   uut: PriorityDecoder1x8 PORT MAP (
          Input => Input,
          Output => Output
        );

   -- Clock process definitions
--   <clock>_process :process
--   begin
--		<clock> <= '0';
--		wait for <clock>_period/2;
--		<clock> <= '1';
--		wait for <clock>_period/2;
--   end process;
 

   -- Stimulus process
   stim_proc: process
   begin		
      -- hold reset state for 100 ns.
--      wait for 100 ns;	

--      wait for <clock>_period*10;

      -- insert stimulus here 
      Input <= "00000000";
      wait for 10 ns;	
      Input <= "00000001";
      wait for 10 ns;
      Input <= "00000011";
      wait for 10 ns;
      Input <= "00000111";
      wait for 10 ns;	
      Input <= "00001111";
      wait for 10 ns;	
      Input <= "00011111";
      wait for 10 ns;	
      Input <= "00111111";
      wait for 10 ns;	
      Input <= "01111111";
      wait for 10 ns;	
      Input <= "11111111";	

      wait;
   end process;

END;

Symulacja w xilinx ise 14.6:

image.thumb.png.536560d0492b885f5c274b439b29be46.png

Dlaczego dekoder priorytetowy jest ważny?

  1. Bo w sprzęcie nie istnieje „if”. Istnieje tylko logika, która musi zdecydować:
  2. który sygnał ma pierwszeństwo,
  3. który sygnał wygra konflikt,
  4. który sygnał zostanie zignorowany.

Właśnie dlatego dekodery priorytetowe są używane w:

  1. sterownikach pamięci,
  2. kontrolerach magistral,
  3. arbitrażach,
  4. dekoderach instrukcji,
  5. maszynach stanów,
  6. układach wejścia/wyjścia.

Przykład z praktyki — inicjacja IntelliMouse (PS/2)
Przykład z if/elsif/else jest świetny, bo pokazuje, że:

  1. pierwszy warunek ma najwyższy priorytet,
  2. kolejne mają niższy,
  3. a else jest najniższym priorytetem.

To jest dokładnie to samo, co robi dekoder priorytetowy — tylko w formie sprzętowej.

 

							if ((Init = "10000000000") and (Din = X"00")) then --inicjacja inellimouse F3 C8 F3 64 F3 50 E8 00 F4
								Init <= Init(0) & Init(10 downto 1);
								Din <= X"F3";
								PS2State <= rts;
						elsif ((Init = "01000000000") and (Din = X"FA")) then
								Init <= Init(0) & Init(10 downto 1);
								Din <= X"C8";
								PS2State <= rts;
						elsif ((Init = "00100000000") and (Din = X"FA")) then
								Init <= Init(0) & Init(10 downto 1);
								Din <= X"F3";
								PS2State <= rts;
						elsif ((Init = "00010000000") and (Din = X"FA")) then
								Init <= Init(0) & Init(10 downto 1);
								Din <= X"64";
								PS2State <= rts;
						elsif ((Init = "00001000000") and (Din = X"FA")) then
								Init <= Init(0) & Init(10 downto 1);
								Din <= X"F3";
								PS2State <= rts;
						elsif ((Init = "00000100000") and (Din = X"FA")) then
								Init <= Init(0) & Init(10 downto 1);
								Din <= X"50";
								PS2State <= rts;
						elsif ((Init = "00000010000") and (Din = X"FA")) then
								Init <= Init(0) & Init(10 downto 1);
								Din <= X"E8";
								PS2State <= rts;
						elsif ((Init = "00000001000") and (Din = X"FA")) then
								Init <= Init(0) & Init(10 downto 1);
								Din <= X"00";
								PS2State <= rts;
						elsif ((Init = "00000000100") and (Din = X"FA")) then
								Init <= Init(0) & Init(10 downto 1);
								Din <= X"F4";
								PS2State <= rts;
						elsif ((Init = "00000000010") and (Din = X"FA")) then
								Init <= Init(0) & Init(10 downto 1);
								SelB <= "1000";
								PS2State <= idle;
							else
								B3 <= Din;
								B2 <= B3;
								B1 <= B2;
								B0 <= B1;
								SelB <= SelB(0) & SelB(3 downto 1);
								PS2State <= we;
							end if;

Podsumowanie

Dekoder priorytetowy:

  1. nie jest magiczną skrzynką,
  2. jest prostą logiką bramek,
  3. realizuje to samo, co if/elsif/else,
  4. ma ogromne zastosowanie w FPGA

Pozdrawiam, i życzę wyboru najwyższego priorytetu.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...