Primer načrtovanja vmesnika

Prikazali bomo primer načrtovanja vezja vmesnika za paralelna vrata osebnega računalnika. Na primeru vezja si bomo pogledali postopek načrtovanja vezja od zgoraj navzdol, opis vezja z uporabo komponent, izvedbo tristanjskih vodil in priključitev signalov na paralelna vrata.

 Paralelni vmesnik

Paralelna vrata osebnega računalnika vsebujejo 8 podatkovnih izhodov in nekaj vhodnih ter izhodnih kontrolnih signalov. Vse signale lahko programsko nastavljamo ali beremo. Z vmesnikom želimo povečati število signalov, tako da bomo imeli na voljo štiri 8 bitna vhodna ali izhodna vrata (qa, qb, qc in qd), ki jih bomo programsko nastavljali in brali.

Načrtovanje od zgoraj navzdol poteka tako, da vezje razdelimo na posamezne bloke (manjše funkcionalne enote), ki jih nato načrtamo in povežemo med seboj. Paralelni vmesnik ima štiri vrata, zato bo sestavljen iz štirih podobnih sklopov. Poglejmo si zasnovo posameznega sklopa:

Izhodni izbiralnik

Vhode v izbiralnik smo razdelili na 4 bitne podvektorje, ki jih ob določeni kombinaciji kontrolnih signalov prenesemo na izhod. Ker imamo na voljo premalo kontrolnih signalov, smo kot dodatni pogoj uporabili tudi uro (clk).


 izhod <= qa(3 downto 0) when ctr="001" and clk='0' else
 qa(7 downto 4) when ctr="001" and clk='1' else
 qb(3 downto 0) when ctr="010" and clk='0' else
 qb(7 downto 4) when ctr="010" and clk='1' else
 qc(3 downto 0) when ctr="011" and clk='0' else
 qc(7 downto 4) when ctr="011" and clk='1' else
 qd(3 downto 0) when ctr="100" and clk='0' else
 qd(7 downto 4);

Tristanjski ojačevalniki

Tristanjske ojačevalnike opišemo v jeziku VHDL tako, da izhodnemu signalu priredimo stanje visoke impedance ("Z....") ob določenem pogoju:


 qa <= qa_int when ctr_reg(0)='1' else "ZZZZZZZZ";

Tristanjski ojačevalniki se uporabljajo za notranja dvosmerna vodila v vezju ali pa za zunanje signale, ki so definirani kot inout (vhodi ali izhodi). Če načrtujemo vezje na strukturnem nivoju (s komponentami), morajo biti zunanji tristanjski ojačevalniki opisani na najvišjem hierarhičnem nivoju. V tem primeru zna program za sintezo vezij pravilno uporabiti tristanjske ojačevalnike, ki so del vhodno-izhodnih blokov FPGA vezja. Če so tristanjski ojačevalniki znotraj komponente, pa bomo lahko imeli težave pri sintezi.

Klikni na komponento za VHDL opis posamezne komponente!

Na levi strani so podatkovni signali na paralelnih vratih računalnika, na desni pa so vrata qa našega vmesnika. Vrata qa se obnašajo kot izhod, kadar so tristanjski ojačevalniki odprti. Vrednost na vratih nastavimo z vpisom podatkov v 8 bitni register. Če so tristanjski ojačevalniki zaprti, lahko vrata uporabljamo kot paralelne vhode, ki jih beremo z osebnim računalnikom. Branje poteka preko multiplekserja, s katerim združimo vrednosti iz vseh vrat v 4 bitne bloke, ki jih zaporedoma preberemo preko kontrolnih signalov na paralelnih vratih osebnega računalnika.

Za krmlijenje vezja potrebujemo nekaj kontronih signalov:

Na paralelnih vratih računalnika imamo poleg osmih podatkovnih izhodov na voljo le še štiri kontrolne izhode, kar je občutno premalo za direktno krmiljenje vseh sklopov vmesnika. Problem rešimo s pametno razdelitvijo kontrolnih signalov in dodatno logiko v vmesniku.

Tristanjske ojačevalnike bomo bolj redko nastavljali, zato za njihovo krmiljenje uvedemo dodatni 4 bitni register, ki ga vpišemo ob določeni kombinaciji krmilnih signalov. Vpis podatkov v registre vmesnika naj se izvrši ob urinem signalu (1 kontrolni signal) in dodatnem pogoju, ki ga določa kombinacija ostalih treh kontrolnih signalov. S kombinacijo kontrolnih signalov in ure izvedemo tudi branje vhodov preko izhodnega multiplekserja.

ctr(2:0) Vpis v register Branje
001 qa qa(3:0) pri clk='0'
qa(7:4) pri clk='1'
010 qb qb(3:0) pri clk='0'
qb(7:4) pri clk='1'
011 qc qc(3:0) pri clk='0'
qc(7:4) pri clk='1'
100 qd qd(3:0) pri clk='0'
qd(7:4) pri clk='1'
111 kontrolni register  

Tule je opis celotnega vezja vmesnika, ki vsebuje kot komponento 8 bitni register. Komponento smo deklarirali samo enkrat, uporabili pa smo jo štirikrat (r1, r2, r3 in r4).

library IEEE;
use IEEE.std_logic_1164.all;

entity vmesnik is
  port ( clk: in std_logic;
         d: in std_logic_vector(7 downto 0);
         ctr: in std_logic_vector(2 downto 0);
         qa, qb, qc, qd: inout std_logic_vector(7 downto 0);
         izhod: out std_logic_vector(3 downto 0) );
end vmesnik;
architecture opis of dff is

architecture vmesnik of vmesnik is

 -- 8 bitni register s signalom ce (clock enable)
 component reg8
   port (
     clk: in STD_LOGIC;
     ce: in STD_LOGIC;
     d: in STD_LOGIC_VECTOR (7 downto 0);
     q: out STD_LOGIC_VECTOR (7 downto 0)
   );
 end component;

 -- kontrolni register, zacetno stanje je 0000
 signal ctr_reg: std_logic_vector(3 downto 0) := "0000";

 signal ce1, ce2, ce3, ce4: std_logic;
 signal qa_int, qb_int, qc_int, qd_int: std_logic_vector(7 downto 0);
 signal izhod_int: std_logic_vector(3 downto 0);

 begin

 -- 4 bitni kontrolni register (ctr_reg)
 p: process(clk)
   begin
   if clk'event and clk='1' then
     if ctr="111" then
       ctr_reg <= d(3 downto 0);
     end if;
   end if;
 end process;

 -- 1. izhodni register
 r1: reg8 port map (clk => clk, ce => ce1, d => d, q => qa_int);
 ce1 <= '1' when ctr="001" else '0'; -- pogoj za vpis v 1. izhodni register

 -- vrata qa
 qa <= qa_int when ctr_reg(0)='1' else "ZZZZZZZZ";

 -- 2. izhodni register
 r2: reg8 port map (clk => clk, ce => ce2, d => d, q => qb_int);
 ce2 <= '1' when ctr="010" else '0'; -- pogoj za vpis v 2. izhodni register

 -- vrata qb
 qb <= qb_int when ctr_reg(1)='1' else "ZZZZZZZZ";

 -- 3. izhodni register
 r3: reg8 port map (clk => clk, ce => ce3, d => d, q => qc_int);
 ce3 <= '1' when ctr="011" else '0'; -- pogoj za vpis v 3. izhodni register

 -- vrata qc
 qc <= qc_int when ctr_reg(2)='1' else "ZZZZZZZZ";

 -- 4. izhodni register
 r4: reg8 port map (clk => clk, ce => ce4, d => d, q => qd_int);
 ce4 <= '1' when ctr="100" else '0'; -- pogoj za vpis v 4. izhodni register

 -- vrata qd
 qd <= qd_int when ctr_reg(3)='1' else "ZZZZZZZZ";

 -- izhodni multiplekser

 izhod_int <= qa(3 downto 0) when ctr="001" and clk='0' else
 qa(7 downto 4) when ctr="001" and clk='1' else
 qb(3 downto 0) when ctr="010" and clk='0' else
 qb(7 downto 4) when ctr="010" and clk='1' else
 qc(3 downto 0) when ctr="011" and clk='0' else
 qc(7 downto 4) when ctr="011" and clk='1' else
 qd(3 downto 0) when ctr="100" and clk='0' else
 qd(7 downto 4);

 -- krmiljenje izhoda z 0 in visoko impedanco,
 -- tako da dobimo preko zunanjega pull-up upora 5V nivo

 izhod(0) <= '0' when izhod_int(0) = '0' else 'Z';
 izhod(1) <= '0' when izhod_int(1) = '0' else 'Z';
 izhod(2) <= '0' when izhod_int(2) = '0' else 'Z';
 izhod(3) <= '0' when izhod_int(3) = '0' else 'Z';
end vmesnik;

Na paralelnih vratih osebnega računalnika imamo 5V logične nivoje. Vhodi 3.3V FPGA vezja so združljivi s 5V nivoji, na izhodih pa moramo uporabiti pull-up upore in jih krmiliti z logično ničlo ali visoko impedanco. Ko je izhod v stanju visoke impedance, dobimo preko zunanjega upora napetost 5V.

Paralelni vmesnik v FPGA vezju priključimo na paralelna vrata osebnega računalnika, tako kot prikazuje shema. Za kontrolne signale uporabimo Auto-Linefeed, Initialize in Select-Printer, za uro pa signal Strobe. Ker so to dvosmerni signali (open drain), jih moramo priključiti preko 4k7 uporov na 5V. Še posebej kritičen je signal Strobe, ki ga uporabljamo za uro v našem vezju. Na tem signalu ne sme biti nobenih prenihavanj in imeti mora dovolj kratek dvižni čas, kajti FPGA vezja reagirajo zelo zelo hitro (bistveno hitreje kot običajni CMOS ali TTL gradniki). Najbolje je, če kontrolne signale filtriramo s pomočjo Schmitt trigerjev, ki nam popravijo dvižni čas in odstranijo motnje. Na izhodih vmesnika, ki so vezani na vhode paralelnih vrat, morajo biti prav tako upori proti napetosti 5V v velikosti nekaj kilo Ohmov.

Strukturni opis Pogosta vprašanja