Implementace čítačů v číslicových systémech Jakub Šťastný
1 Úvod Čítač je fundamentálním obvodovým blokem nezbytným pro návrh většiny číslicových systémů. Blok čítače je v číslicových obvodech používán v řadě aplikací; nejtypičtějším použitím je čítač užitý jako časovač – blok, který počítá události (například náběžné hrany hodin) na svém vstupu. S čítačem se můžeme setkat ovšem i v jiných podobách, například jako s řadičem pro generování určité sekvence řídících signálů, s generátorem adresy pro paměť, či čítačem instrukcí programu v procesoru (Program Counter). Blok čítače můžeme chápat i jako zjednodušený stavový automat, je-li doplněn o převodník stavu čítače na požadované výstupní signály automatu. Vlastní převodník přitom může degenerovat i na jednoduché „dráty“ mezi výstupem čítače a řídicími signály, je-li stav čítače vhodně kódován. Příklad užití čítače jako generátoru sekvence signálů lze nalézt na obrázku 1.
Obrázek 1: Čítač užitý jako stavový automat pro generování sekvence signálů. V levé části obrázku vidíme příklady časových průběhů hodnot logických signálů na vstupu čítače a na jeho výstupu (hodinový signál clk, resetovací vstup res a výstupy čítače cnt(0) a cnt(1)) spolu s požadovanými průběhy generovaných signálů – ctrl1,2 a 3. V pravé části je pak rozkresleno schéma čítače spolu s dekodérem pro generování příslušných signálů. Soubor cnt_fsm.png. Základní podoba binárního čítače je velmi dobře známá a probíraná ve všech kurzech číslicového návrhu a zmiňovaná i každou knihou zaměřenou na návrh číslicových obvodů, viz například [1], kapitola 2. Už méně známé a zmiňované jsou alternativní možnosti implementace čítače spolu s jeho vlastnostmi; to je překvapivé vzhledem k fundamentálnímu významu bloku čítače pro číslicové systémy. Potřebujeme-li navrhnout čítač pro konkrétní aplikaci, základní vlastnost kterou je třeba vzít v úvahu je kódování stavu čítače. Kódování stavu ovlivňuje téměř všechny parametry výsledného návrhu (velikost, maximální pracovní hodinovou frekvenci, spotřebu elektrické energie a počet současně se měnících bitů na sběrnici na výstupu čítače – maximální Hammingovu vzdálenost [2] dvou sousedních stavů čítače MHVS). Vhodná volba kódování je klíčovým rozhodnutím a právě jí je věnován náš příspěvek. Dalším důležitým kriteriem pro návrh čítače je volba mezi synchronním čítačem (synchronous counter, všechny registry klopí ve stejný okamžik), nebo asynchronním čítačem (ripple counter, registry klopí postupně). Základní rozdíly mezi oběma čítači a argumenty pro volbu jednoho či druhého postupu budou také diskutovány v textu. Jako příklad je v textu užit jednoduchý blok čítače procházejícího osmi stavy; pro jednotlivé alternativy je prezentován i VHDL kód návrhu a implementační parametry. Ty jsou pak v závěru článku shrnuty a vzájemně srovnány. Pro simulaci i implementaci bylo použito volně dostupné návrhové prostředí ISE Webpack [3]; jednotlivé bloky byly implementovány do obvodu xc5vlx30-3ff324. Začínající návrháři mohou nalézt detailní návod jak pracovat s návrhovým prostředím v knize [1], kapitola 2. V celém textu označujeme počet registrů udržujících stav čítače jako N, počet stavů jako Ns. Jako fclk_max označujeme maximální dosažitelnou pracovní frekvenci čítače, Tclk_min=1/fclk_max je pak minimální perioda hodinového cyklu. Řešení popsaná v textu jsou použitelná jak při návrhu číslicových obvodů na programovatelných hradlových polích, tak při návrhu zákaznických integrovaných obvodů. Pro jednotlivé možnosti implementace číslicové logiky uvádíme v závěru seriálu kromě odhadů velikosti vlastní logiky a délky kritické cesty v čítači i méně často diskutovanou vlastnost – stručnou analýzu možností „ruční editace“ návrhu čítače v případě nutnosti provedení tzv. ECO úpravy (Engineering Change Order, viz [4]) už vyráběného integrovaného obvodu. Příspěvek je z prostorových důvodů rozdělen do několika dílů; v tomto příspěvku bude prezentována plná implementace binárního čítače spolu se synchronním binárním a Johnsonovým čítačem. V dalším příspěvku potom ukážeme implementaci Grayova čítače, čítače v kódu 1 z N a binárního asynchronního čítače spolu se závěrečným
1
shrnutím jejich vlastností.
2 Základní implementace Před rozborem jednotlivých alternativ implementace čítačů nejprve shrňme základní funkce, které může čítač mít; spolu s výkladem nechť čtenář sleduje výpis v příkladu 1: •
Asynchronní a synchronní reset (asynchronous/synchronous reset) – reset aktivní buď vždy, nebo jen v okamžiku příchodu náběžné hrany hodin; čítač je většinou nastaven do stavu 00...000 (je-li binární vzestupný), nebo do stavu např. 11...111 (binární čítající sestupně), případně ve speciálních případech může být obvod resetován i do jiného stavu. Poznamenejme zde, že reset je nezbytnou součástí implementace a není rozumné ho vynechávat, více viz [1], kapitola 5. V případě použití asynchronního resetu se na signálu nesmí vyskytovat žádné hazardní stavy ( glitche), nesmí být tedy generován přímo z obecné kombinační logiky. V příkladu 1 je funkce asynchronního resetu ovládána vstupem async_res, synchronního sync_res.
•
Synchronní a asynchronní přednastavení (synchronous/asynchronous preload) – stavový registr čítače je nastaven na hodnotu přivedenou na k tomu určenou vstupní sběrnici obvodu a aktivuje se příslušným řídicím signálem. Tím se také liší přednastavení od resetu. Reset čítač nastavuje vždy do stejného počátečního stavu. Synchronní přednastavení je v příkladu 1 řízeno signálem sync_ld, asynchronní async_ld. Hodnota, do které má být čítač přednastaven, je přivedena na sběrnici ld_val. Ani na signálu pro řízení asynchronního přednastavení se nesmí vyskytovat žádné hazardní stavy, jejich přítomnost by porušila stav čítače.
Čítání (counting) – stav čítače je u binárního čítače inkrementován, nebo dekrementován s daným krokem (většinou 1, ale může být jiný), případně u jiného kódování je realizován přechod na následující/předchozí stav. Při čítání můžeme procházet jak úplnou sekvencí stavů čítače (pro N bitový binární čítač je počet stavů Ns=2N), tak sekvencí redukovanou. O Ns-stavovém čítači často hovoříme jako o „čítači modulo Ns“. Demonstrační čítač má vstupní signály cnt_en – povolení čítání, cnt_up – směr čítání (nahoru/dolů), cnt_step – krok čítání. Počet stavů, kterými čítač může procházet, je definován vstupní sběrnicí cnt_limit, dosažení daného počtu stavů je pak indikováno pulzem na výstupním signálu cnt_over. Všimněte si také implementace detekce podtečení čítače – přechodu přes nulu v případě čítání dolů. Je zde využito vlastností binárního kódu a podtečení detekován pomocí detekce situace, kdy je požadovaný příští stav „negativní“ (nejvyšší bit je v log. 1) a současný stav „pozitivní“ (nejvyšší bit je v log. 0). Všimněte si v příkladu 1 implementace vynulování čítače po dosažení posledního stavu; reset je implementován jako synchronní. Bylo by hrubou chybou čítač nulovat pomocí asynchronního resetu, například takto: reg_cnt : PROCESS (clk, async_res, cnt_over_i, async_ld, ld_val) BEGIN IF async_res='1' OR cnt_over_i='1' THEN cnt_q <= (OTHERS => '0'); ELSIF async_ld='1' THEN cnt_q <= unsigned(ld_val); ELSIF clk'EVENT AND clk='1' THEN cnt_q <= cnt_d; END IF; END PROCESS reg_cnt; Komparátor stavu čítače proti hodnotě cnt_limit bude téměř jistě na svém výstupu produkovat statické a dynamické hazardy a zákmit typu 0-1-0 by s jistotou vedl k poruše správné funkce čítače (stavový registr čítače by byl vynulován, případně by mohly být vynulovány jen některé registry ze stavového registru). •
2
LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.numeric_std.ALL; ENTITY binary_counter IS GENERIC ( N : natural := 16 ); PORT ( async_res : IN std_logic; async_ld : IN std_logic; clk : IN std_logic; sync_res sync_ld ld_val
: IN : IN : IN
std_logic; std_logic; std_logic_vector (N-1 DOWNTO 0);
cnt_en cnt_up cnt_step cnt_limit
: : : :
std_logic; std_logic; std_logic_vector (N-1 DOWNTO 0); std_logic_vector (N-1 DOWNTO 0);
cnt_over cnt_unde cnt_out
: OUT std_logic; : OUT std_logic; : OUT std_logic_vector (N-1 DOWNTO 0)
IN IN IN IN
); END ENTITY binary_counter; ARCHITECTURE rtl OF SIGNAL cnt_nx SIGNAL cnt_d SIGNAL cnt_q SIGNAL cnt_over_i SIGNAL cnt_unde_i BEGIN
binary_counter IS : unsigned (N-1 DOWNTO 0); : unsigned (N-1 DOWNTO 0); : unsigned (N-1 DOWNTO 0); : std_logic; : std_logic;
reg_cnt : PROCESS (clk, async_res, async_ld, ld_val) BEGIN IF async_res='1' THEN cnt_q <= (OTHERS => '0'); ELSIF async_ld='1' THEN cnt_q <= unsigned(ld_val); ELSIF clk'EVENT AND clk='1' THEN cnt_q <= cnt_d; END IF; END PROCESS reg_cnt; cnt_nx
<= cnt_q+unsigned(cnt_step) WHEN cnt_en = '1' AND cnt_up = '1' ELSE cnt_q-unsigned(cnt_step) WHEN cnt_en = '1' AND cnt_up = '0' ELSE cnt_q; cnt_over_i <= '1' WHEN cnt_nx >= unsigned(cnt_limit) ELSE '0'; cnt_unde_i <= '1' WHEN cnt_nx(N-1) = '1' AND cnt_q(N-1) = '0' ELSE '0'; cnt_d <= cnt_nx WHEN sync_res = '0' AND sync_ld = '0' AND cnt_over_i = '0' ELSE (OTHERS => '0') WHEN sync_res = '1' ELSE unsigned(ld_val) WHEN sync_ld = '1' ELSE unsigned(cnt_limit) WHEN cnt_unde_i = '1' ELSE -- underflow (OTHERS => '0'); -- overflow cnt_over <= cnt_over_i; cnt_unde <= cnt_unde_i; cnt_out <= std_logic_vector(cnt_q); END ARCHITECTURE rtl;
Příklad 1: Maximalistická verze binárního čítače se všemi běžnými funkcemi.
3 Synchronní binární čítač Binární kód je všem návrhářům dobře známý. Jeho výhodou je minimální počet registrů nutných pro implementaci čítače procházejícího Ns stavy, N=ceil(log2(Ns)), kde ceil je funkce zaokrouhlující svůj argument nahoru na celé jednotky. Dále je snadné provádět nad výstupem binárního čítače nejrůznější aritmetické operace (např. porovnávání – >,< atd.), jejich implementace v binárním kódu je velmi intuitivní a běžně používaná. Výhodou je i to, že čítač čítající v
3
binárním kódu může mít libovolný počet stavů. Nevýhodou synchronního binárního čítače je potřeba většího množství kombinační logiky pro implementaci sčítačky pro generování dalšího stavu a větší zpoždění v této logice, které omezuje fclk_max. Poslední významnější nevýhodou je skutečnost, že sousední stavy binárního čítače se mohou lišit až v N bitech (MHVS je N); kombinační logická funkce, která by dekódovala stavy čítače a generovala podle nich příslušné výstupy jako např. blok decoder na obrázku 1, pak bude téměř jistě produkovat statické či dynamické hazardy (glitche) na svém výstupu. Pokud bychom chtěli upravovat čítač pomocí ECO změny, můžeme chtít buď jen zvýšit počet stavů (přidat další stavy na konec sekvence), nebo sekvenci „rozšířit“ vložením nových stavů „doprostřed“. Kombinační logická funkce binárního čítače patří mezi složitější z pohledu ECO změn; většinou lze prodloužit sekvenci přidáním dalších stavů, ale není možné vložit stavy dovnitř do sekvence čítače (čítač by pak už nečítal v binárním kódu). Příklad 2 uvedený níže demonstruje už jen zjednodušenou verzi čítače z příkladu 1, sekvenci stavů demonstruje obrázek 2.
Obrázek 2: Příklad běhu čítače, sekvence stavů 000, 001, 010, 011, 100, 101, 110, 111. Soubor cnt_binary.png LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.numeric_std.ALL; ENTITY cnt IS GENERIC ( N : natural := 4 ); PORT ( res : IN std_logic; clk : IN std_logic; cnt_out : OUT std_logic_vector (N-1 DOWNTO 0) ); END ENTITY cnt; ARCHITECTURE rtl_bin OF cnt IS SIGNAL cnt_d : unsigned (N-1 DOWNTO 0); SIGNAL cnt_q : unsigned (N-1 DOWNTO 0); BEGIN reg_cnt : PROCESS (clk, res) BEGIN IF res='1' THEN cnt_q <= (OTHERS => '0'); ELSIF clk'EVENT AND clk='1' THEN cnt_q <= cnt_d; END IF; END PROCESS reg_cnt; cnt_d <= cnt_q + 1; cnt_out <= std_logic_vector(cnt_q); END ARCHITECTURE rtl_bin;
Soubor cnt_binary_sch.png
Příklad 2: Binární čítač - RTL kód a příklad funkce.
4 Synchronní Johnsonův čítač Stav a výstup Johnsonova čítače je kódován v Johnsonově, nebo tzv. plazivém, kódu. Kód se konstruuje jednoduše – první stav je zakódován samými nulami; pro další stavy se stavový registr posouvá vlevo a zprava nasouvá jednička až do okamžiku, kdy jsou všechny registry nastavené do log. 1. Potom se celý proces opakuje s tím rozdílem, že zprava nasouváme log. 0 až do okamžiku, kdy jsou všechny registry stavu čítače nastavené do log. 0. Pak celý postup opakujeme. Příklad sekvence v Johnsonově kódu je uveden níže, v obrázku 3. Výhodou Johnsonova kódu je to, že MHVS je jen 1, proto je Johnsonův čítač často používán například v generátorech hodinových signálů (navazující kombinační logika bloku decoder generující vlastní hodinové signály má za dodržení dalších dodatečných podmínek výstup bez statických i dynamických hazardů). Nevýhodou je, že počet registrů udržujících stav čítače je zde N=Ns/2; dále je možná jen implementace čítače o sudém počtu stavů. Všimněme si zde, že
4
mezi registry čítače v podstatě není žádná kombinační logika, jen jeden invertorm který invertuje výstup z posledního registru a vytváří „plazivou“ sekvenci nul a jedniček. To umožňuje dosáhnout vysoké hodnoty fclk_max. Do čítače implementovaného jako Johnsonův lze proto snadno vložit pomocí ECO změny další stavy a prodloužit tak sekvenci čítání.
Obrázek 3: Příklad běhu čítače, sekvence stavů je 0000, 0001, 0011, 0111, 1111, 1110, 1100, 1000. Soubor cnt_johnson.png ARCHITECTURE rtl_johnson OF cnt IS SIGNAL cnt_d : std_logic_vector (N-1 DOWNTO 0); SIGNAL cnt_q : std_logic_vector (N-1 DOWNTO 0); BEGIN reg_cnt : PROCESS (clk, res) BEGIN IF res='1' THEN cnt_q <= (OTHERS => '0'); ELSIF clk'EVENT AND clk='1' THEN cnt_q <= cnt_d; END IF; END PROCESS reg_cnt; cnt_d <= cnt_q(N-2 DOWNTO 0)&NOT(cnt_q(N-1)); cnt_out <= cnt_q; END ARCHITECTURE rtl_johnson;
Soubor cnt_johnson_sch.png
Příklad 3: Johnsonův čítač - RTL kód a schéma.
5 Literatura [1] Jakub Šťastný. FPGA Prakticky, BEN Praha 2011. [2] Hamming Distance. http://en.eikipedia.org/wiki/Hamming_distance [3] ISE WebPack. http://www.xilinx.com/tools/webpack.htm [4] Engineering Change Order. http://en.wikipedia.org/wiki/Engineering_Change_Order [5] Steve Golson. One-hot state machine design for FPGAs, 3rd PLD Design conference, Santa Clara, 1993. [6] Steve Golson. State machine design techniques for Verilog and VHDL, 1994.
5
Implementace čítačů v číslicových systémech 2 Jakub Šťastný
1 Úvod V předchozím článku byly shrnuty základní vlastnosti čítačů, implementace a výhody a nevýhody binárního a Johnsonova čítače. V tomto příspěvku se budeme dále zabývat synchronní implementací čítače v Grayově kódu, kódu 1 z N a LFSR čítače. Poslední část, připravovaná do příštího čísla, bude potom věnována implementaci asynchronního čítače (ripple counteru) a shrnutí parametrů předvedených konstrukcí. V celém textu označujeme počet registrů udržujících stav čítače jako N, počet stavů jako Ns. Jako fclk_max označujeme maximální dosažitelnou pracovní frekvenci čítače, Tclk_min=1/fclk_max je pak minimální perioda hodinového cyklu. Zkratkou MHVS budeme označovat maximální počet současně se měnících bitů na sběrnici na výstupu čítače – maximální Hammingovu vzdálenost dvou sousedních stavů čítače.
2 Grayův čítač Binární čítač nemůžeme užít, potřebujeme-li vzorkovat jeho výstup hodinovým signálem asynchronním k hodinovému signálu, ze kterého běží čítač. V takovém případě by způsobilo vážné problémy to, že u binárního čítače se mohou dva sousední stavy lišit v podstatě v libovolném počtu bitů, viz obrázek 4. V levé části obrázku je zjednodušené schéma celé obvodové konfigurace. Binární čítač je řízen hodinami clk1, vzorkování je prováděno náběžnou hranou hodin clk2. Přitom hodiny clk2 jsou plně asynchronní k hodinám clk1. Vidíme, že při naznačeném přechodu výstupu čítače mezi hodnotami 011 a 100 můžeme navzorkovat hodnoty 011, 110 i 100. Skutečné chování přitom závisí na konkrétních vzájemných časových posunech mezi signály cnt1(0), cnt1(1) a cnt1(2). Abychom se podobným problémům vyhnuli, je nezbytné zajistit, aby se na výstupu čítače měnil vždy jen jeden bit. Právě tuto vlastnost splňuje Grayův čítač, speciální konstrukce stavové sekvence u něj zajišťuje MHVS 1. Tato vlastnost navíc umožňuje (za dodržení dalších dodatečných podmínek) navrhnout případný následný dekodér (blok decoder v obrázku 1 z prvního dílu seriálu [1]) tak, aby na jeho výstupech nebyly žádné statické ani dynamické hazardy. Stejně jako u binárního čítače – a oproti Johnsonovu čítači – je i zde výhodou minimální počet registrů nutných pro implementaci čítače procházejícího Ns stavy, N=ceil(log2(Ns)). RTL schéma Grayova čítače lze nalézt v obrázku v příkladu 4, spolu s RTL VHDL implementací, stavová sekvence je potom v obrázku 5. Z důvodu úspory místa vynecháváme konstrukci ENTITY definující porty a generické parametry čítače. Použitá konstrukce je totožná s tou, kterou lze nalézt v příkladu 2 v předchozím dílu [1].
Obrázek 4: Vzorkování výstupu binárního čítače asynchronním signálem. Soubor sync_1.png. Zřejmou nevýhodou Grayova čítače je větší plocha zabraná kombinační logikou pro generování následujícího stavu čítače; s tím souvisí i větší zpoždění v kritické cestě. Dlouhou kritickou cestu částečně odstraňuje řešení na obrázku 6 [2], ovšem za cenu většího množství registrů potřebných pro implementaci. A jako u binárního čítače, je i u Grayova čítače změna počtu stavů pomocí ECO úpravy obtížná. Použití Grayova kódu dále přináší omezení na délku stavové sekvence čítače; ta musí vždy obsahovat sudý počet stavů. V každém textu zabývajícím se kódy naleznete popis konstrukce Grayova kódu pro počet stavů Ns=2l; nicméně je možné zkonstruovat Grayův kód pro obecný sudý počet stavů, viz [3]. Všimněte si, že v čítači je použita binární sčítačka obklopená převodníky z a do Grayova kódu. Stavový registr nicméně obsahuje hodnotu v Grayově kódu. Výstup Grayova čítače musí být řízen přímo z registru, aby se předešlo zákmitům na výstupech jež by mohly být posléze navzorkovány jako legitimní hodnoty, více viz [4], kapitola 11.
6
Obrázek 5: Příklad běhu čítače, sekvence stavů je 000, 001, 011, 010, 110, 111, 101, 100. Soubor cnt_gray.png. LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.numeric_std.ALL; ARCHITECTURE rtl_gray OF cnt IS SIGNAL cnt_d : std_logic_vector SIGNAL cnt_q : std_logic_vector SIGNAL cnt_b : std_logic_vector SIGNAL cnt_b_nxt : std_logic_vector
LIBRARY IEEE; USE IEEE.std_logic_1164.ALL;
(N-1 (N-1 (N-1 (N-1
DOWNTO DOWNTO DOWNTO DOWNTO
0); 0); 0); 0);
COMPONENT gray2bin IS GENERIC ( N : natural := 4 ); PORT ( gray : IN std_logic_vector (N-1 DOWNTO 0); bin : OUT std_logic_vector (N-1 DOWNTO 0) ); END COMPONENT gray2bin; COMPONENT bin2gray IS GENERIC ( N : natural := 4 ); PORT ( bin : IN std_logic_vector (N-1 DOWNTO 0); gray : OUT std_logic_vector (N-1 DOWNTO 0) ); END COMPONENT bin2gray; BEGIN reg_cnt : PROCESS (clk, res) BEGIN IF res='1' THEN cnt_q <= (OTHERS => '0'); ELSIF clk'EVENT AND clk='1' THEN cnt_q <= cnt_d; END IF; END PROCESS reg_cnt; i_gray2bin:gray2bin GENERIC MAP (N => N) PORT MAP ( gray => cnt_q, bin => cnt_b );
ENTITY gray2bin IS GENERIC (N : natural := 4); PORT ( gray : IN std_logic_vector (N-1 DOWNTO 0); bin : OUT std_logic_vector (N-1 DOWNTO 0) ); END ENTITY gray2bin; ARCHITECTURE rtl OF gray2bin IS SIGNAL bin_i : std_logic_vector (N-1 DOWNTO 0); BEGIN bin_i(N-1) <= gray(N-1); g2b:FOR index IN N-2 DOWNTO 0 GENERATE bin_i(index) <= gray(index) XOR bin_i(index+1); END GENERATE g2b; bin <= bin_i; END ARCHITECTURE rtl; LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; ENTITY bin2gray IS GENERIC ( N : natural := 4 ); PORT ( bin : IN std_logic_vector (N-1 DOWNTO 0); gray : OUT std_logic_vector (N-1 DOWNTO 0) ); END ENTITY bin2gray; ARCHITECTURE rtl OF bin2gray IS BEGIN gray <= bin XOR ('0'&bin((N-1) DOWNTO 1)); END ARCHITECTURE rtl;
cnt_b_nxt <= std_logic_vector(unsigned(cnt_b)+1); i_bin2gray:bin2gray GENERIC MAP (N => N) PORT MAP ( bin => cnt_b_nxt, gray => cnt_d ); cnt_out <= cnt_q; END ARCHITECTURE rtl_gray;
Soubor cnt_gray_sch.png. Příklad 4: Grayův čítač - RTL kód a schéma.
7
Obrázek 6: Implementace Grayova čítače s kratšími kritickými cestami. Soubor cnt_gray2_sch.png
3 Čítač v kódu 1 z N Čítač v kódu „1 z N“ (one-hot encoding) je implementován jak je uvedeno v příkladu 5, v obrázku 7 je potom příklad stavové sekvence. Vidíme, že je každý stav zakódovaný jako binární řetězec složený ze samých nul jen s jednou jedničkou. Délka stavu čítače je rovná počtu stavů, potřebujeme tedy N=Ns registrů. Mezi registry zde není žádná kombinační logická funkce, počáteční nastavení je zajištěno resetem obvodu a jednička pak „samovolně“ obíhá posuvným registrem. Jednoznačnou nevýhodou čítače je velké množství registrů potřebných pro jeho implementaci; to může vést ke zvýšené spotřebě elektrické energie v hodinovém stromu čítače. Kódování „1 z N“ má ale i řadu výhod. Stejně jako u Johnsonova čítače je i zde velmi redukovaná kombinační logická funkce pro generování následujícího stavu, to umožňuje čítači pracovat na vyšší hodinové frekvenci, než v případě binárního, či Grayova čítače. I zde jsou omezeny hazardy na výstupu případného navazujícího kombinačního detektoru, potlačení nicméně – na rozdíl od Johnsonova kódování – není absolutní, MHVS je 2. Dále je zde jednoduše možné pomocí ECO úpravy vložit do čítače další stav.
Obrázek 7: Příklad běhu čítače, sekvence stavů:00000001, 00000010, 00000100, 00001000, 00010000, 00100000, 01000000, 10000000. Soubor cnt_one_hot.png ARCHITECTURE rtl_one_hot OF cnt IS SIGNAL cnt_d : std_logic_vector (N-1 DOWNTO 0); SIGNAL cnt_q : std_logic_vector (N-1 DOWNTO 0); BEGIN reg_cnt : PROCESS (clk, res) BEGIN IF res='1' THEN cnt_q <= (0=>'1', OTHERS => '0'); ELSIF clk'EVENT AND clk='1' THEN cnt_q <= cnt_d; END IF; END PROCESS reg_cnt; cnt_d <= cnt_q(N-2 DOWNTO 0)&cnt_q(N-1); cnt_out <= cnt_q; END ARCHITECTURE rtl_one_hot;
Příklad 5: „1 z N“ čítač - RTL kód a schéma.
8
Soubor cnt_onehot_sch.png
4 LFSR LFSR čítač (Linear Feedback Shift Register) patří mezi poněkud exotičtější konstrukce, kterým se návrháři spíše vyhýbají (autor textu si pamatuje na několik vášnivých diskuzí o vhodnosti jeho použití i z vlastní praxe). LFSR čítače mají nicméně velké množství aplikací a jsou naprosto nepostradatelné v mnoha aplikacích počínaje kryptografií, přes vysílání v rozptýleném spektru až po obyčejné čítače. LFSR je v principu posuvný registr doplněný o jedno/několik hradel XOR ve zpětné vazbě sloužících pro generování sekvence stavů. Na rozdíl od binárního čítače LFSR o délce N bitů prochází jen Ns=2N-1 stavy, jeden stav je vždy zakázaný (00....000 pro konstrukci užívající hradel XOR, případně 11...111 pro konstrukci s hradlem XNOR). Pohledem na schéma v příkladu 6 lze snadno zjistit, že ze zakázaného stavu (zde 000) se čítač nedostane, dojde k jeho zaseknutí (lockup). U LFSR čítačů je tak nezbytné zajistit pomocí resetu vhodné počáteční podmínky (zde tedy resetovat čítač do libovolného nenulového stavu, například 111). Příklad 6 ukazuje VHDL kód a schéma LFSR čítače procházejícího sedmi stavy, sekvence stavů je přitom zachycena v obrázku 8. Je zřejmé, že za extrémní jednoduchost bloku platíme cenu v podobě zdánlivě chaotické stavové sekvence. Poznamenejme zde, že stavová sekvence má skutečně některé vlastnosti náhodného procesu a proto jsou LFSR čítače často užívány v aplikacích, kde je třeba používat pseudonáhodná čísla. O statistických vlastnostech je možné se dozvědět více v české knize [6]. Stejně jako u Johnsonova čítače, nebo čítače v kódu 1 z N je i zde kombinační logická funkce pro generování dalšího stavu velmi redukovaná. Čítač je tak relativně malý a může pracovat s vyšší fclk_max. Teorie vlastní konstrukce LFSR čítačů je poměrně komplexní, zájemce o detaily odkazujeme na texty [6,7,8], mnoho informací lze také získat prostým hledáním hesla „LFSR counter“ na vyhledávači Google. Méně zřejmou nevýhodou konstrukce LFSR čítače je o něco větší obtížnost návrhu obecného bloku čítače. Pro jeho správnou funkci je třeba správné konfigurace zpětných vazeb v posuvném registru (vyjádřené pomocí tzv. generujícího polynomu, více viz např. [6]), přitom konfigurace je pro každou délku čítače unikátní. Tabulka 1 (převzatá z [9]) obsahuje konfigurace LFSR čítačů pro různé šířky stavového registru. Podíváme-li se na zvýrazněný řádek a srovnámeli ho se schématem v obrázku v příkladu 6, můžeme snadno nahlédnout na to, jak je čítač navržen. Závěrem poznamenejme, že případná modifikace čítače pomocí ECO úpravy nebývá obtížná.
Obrázek 8: Příklad běhu čítače, sekvence stavů 111, 011, 001, 100, 010, 101, 110. Všimněte si, že stavů je jen sedm, ne osm. Soubor cnt_lfsr.png. ARCHITECTURE rtl_lfsr OF cnt IS SIGNAL cnt_d : std_logic_vector (N-1 DOWNTO 0); SIGNAL cnt_q : std_logic_vector (N-1 DOWNTO 0); SIGNAL cnt_xor : std_logic; BEGIN reg_cnt : PROCESS (clk, res) BEGIN IF res='1' THEN cnt_q <= (OTHERS => '1'); ELSIF clk'EVENT AND clk='1' THEN cnt_q <= cnt_d; END IF; END PROCESS reg_cnt; cnt_xor <= cnt_q(1) XOR cnt_q(0); cnt_d <= cnt_xor&cnt_q(N-1 DOWNTO 1); cnt_out <= cnt_q; END ARCHITECTURE rtl_lfsr;
Příklad 6: LFSR čítač - RTL kód a schéma.
9
soubor cnt_lfsr_sch.png
N
Registry pro zpětnou vazbu
1 0 2 1,0 3 1,0 4 1,0 5 2,0 6 1,0 7 1,0 8 6,5,1,0 9 4,0 10 3,0 11 2,0 12 7,4,3,0 13 4,3,1,0 14 12,11,1,0 15 1,0 16 5,3,2,0 Tabulka 1: Zpětné vazby v LFSR čítačích pro různé šířky stavového registru.
5 Literatura [1] Jakub Šťastný. Implementace čítačů v číslicových systémech. DPS Plošné spoje od A do Z, XXXX, str. XXX-XXX. [2] Clifford Cummings. Simulation and synthesis techniques for asynchronous FIFO designs. SNUG San Jose 2002. [3] Clive Maxfield. Yet another Gray code conundrum, July 19, 2007 http://www.pldesignline.com/201002340;jsessionid=SEEHOQLT04WKZQE1GHPSKHWATMY32JVN? printableArticle=true (kontrolováno 1.5.2011) [4] Jakub Šťastný. FPGA Prakticky, BEN Praha 2011. [5] Steve Golson. State machine design techniques for Verilog and VHDL, 1994. [6] Jiří Adámek. Kódování. Sešit XXXI, matematika pro vysoké školy technické, SNTL 1989. [7] Xilinx. Linear Feedback Shift Registers in Virtex Devices: XAPP 210. [8] Xilinx. Efficient Shift Registers, LFSR Counters, and Long Pseudo-Random Sequence Generators: XAPP 052. [9] Tom Balph. LFSR counters implement binary polynomial generators. EDN Design feature, http://www.edn.com/archives/1998/052198/11df_06.htm (kontrolováno 1.5.2011)
10
Implementace čítačů v číslicových systémech 3 Jakub Šťastný
1 Úvod V předchozích článcích byly shrnuty základní vlastnosti čítačů, implementace a výhody a nevýhody všech běžně používaných synchronních čítačů. Poslední část je věnována implementaci asynchronního čítače (ripple counteru) a shrnutí parametrů předvedených konstrukcí. V celém textu označujeme počet registrů udržujících stav čítače jako N, počet stavů jako Ns. Jako fclk_max označujeme maximální dosažitelnou pracovní frekvenci čítače, Tclk_min=1/fclk_max je pak minimální perioda hodinového cyklu. Zkratkou MHVS budeme označovat počet současně se měnících bitů na sběrnici na výstupu čítače – maximální Hammingovu vzdálenost [2] dvou sousedních stavů čítače.
2 Asynchronní binární čítač Doposud jsme prezentovali jen synchronní řešení obvodu čítače. U synchronního čítače se – zjednodušeně řečeno – překlápí všechny registry současně, všechny registry udržující stav čítače mají jednotný zdroj hodin. V asynchronním čítači se oproti tomu mění stavy jednotlivých registrů „jeden po druhém“. Asynchronní binární čítač (ripple counter) je ze všech prezentovaných typů čítačů nejmenší pro daný počet stavů. Také dosahuje nejmenší spotřeby a je schopen pracovat na nejvyšší možné fclk_max. Jednoduše ho lze zkonstruovat jako čítající nahoru, či dolů, problematičtější je ale čítání s jiným krokem, než 1. Výhoda malé spotřeby a plochy zabrané obvodem je nicméně vyvážena asynchronním klopením registrů v čítači a složitějším zkracováním čítaného cyklu. Obtížnější je i detekce stavů. Příklad 7 ukazuje asynchronní čítač čítající nahoru, sekvence stavů je uvedena v obrázku 9. Všimněte si, že každý registr užívá jako zdroj hodin předchozí registr v čítači. To posléze vede na zpoždění v překlápění jedotlivých registrů, jak je možné vidět v obrázku 10. Mezi překlopením registrů 0 a 2 zde uplyne cca 1,5 ns a na výstupu čítače se vystřídají stavy 011, 010, 000 a 100. Popsaný jev se v angličtině nazývá ripple (česky bychom řekli řetězová reakce, nebo dominový efekt) a dal čítači jméno. Pro větší počet registrů čítače a vyšší hodinové frekvence se snadno může stát, že ustálení celého čítače nestihne proběhnout do konce hodinové periody. S popsaným chováním je potřeba počítat a skutečné chování asynchronního čítače po implementaci zkontrolovat. Na druhou stranu je ale kritická cesta v asynchronním čítači velmi krátká a tak čítač může typicky pracovat na velmi vysokých hodinových frekvencích bez ohledu na počet jeho registrů. Proto ho bývá užitečné užít například pro čítání událostí s velmi vysokou frekvencí. Zde nám nemusí vadit delší doba ustálení než je perioda hodin, jen je potřeba správně implementovat vzorkování čítače (např. stav čítače číst jen je-li zastaven). Implementace asynchronního čítače čítajícího dolů by byla obdobná s tím rozdílem, že jednotlivé registry musí klopit na náběžnou a nikoliv spádovou hranu výstupu předchozího registru. Asynchronní čítače nejsou příliš vhodné pro programovatelná hradlová pole právě kvůli generování vlastních hodinových signálů; díky obtížnějšímu nastavovaní čítače (preload), které se musí dělat asynchronně a složitější detekci stavů v případě potřeby zkrácení čítacího cyklu ani nejsou doporučenými konstrukcemi pro začínající návrháře. Naopak, při návrhu číslicových obvodů pro zákaznické integrované obvody jsou výhody asynchronního čítače (malá plocha a malá spotřeba) naprosto nedocenitelné. Případná modifikace asynchronního čítače pomocí ECO změny může být dosti obtížná kvůli časovému chování obvodu.
11
ARCHITECTURE rtl_ripple OF cnt IS SIGNAL cnt_d : std_logic_vector (N-1 DOWNTO 0); SIGNAL cnt_q : std_logic_vector (N-1 DOWNTO 0); SIGNAL clk_i : std_logic_vector (N-1 DOWNTO 0); BEGIN g_rp:FOR index IN 0 TO N-1 GENERATE reg_cnt : PROCESS (clk_i(index), res) BEGIN IF res='1' THEN cnt_q(index) <= '0'; ELSIF clk_i(index)'EVENT AND clk_i(index)='0' THEN cnt_q(index) <= cnt_d(index); END IF; END PROCESS reg_cnt; END GENERATE g_rp;
Soubor cnt_ripple_sch.png
clk_i <= cnt_q(N-2 DOWNTO 0)&NOT(clk); cnt_d <= NOT(cnt_q); cnt_out <= cnt_q; END ARCHITECTURE rtl_ripple;
Příklad 7: Asynchronní čítač - RTL kód a schéma.
Obrázek 9: Příklad běhu čítače, sekvence stavů 000, 001, 010, 011, 100, 101, 110, 111. Soubor cnt_ripple_rtl.png.
Obrázek 10: Příklad běhu čítače, simulace na hradlové úrovni, detail přechodu mezi stavy 011 a 100. Soubor cnt_ripple_gate.png.
3 Shrnutí a závěr Tabulka 2 obsahuje teoretické odhady implementačních parametrů jednotlivých typů čítačů; kvantitativní srovnání parametrů jednotlivých čítačů po implementaci na programovatelném hradlovém poli xc5vlx30-3ff324 je uvedeno v tabulce 3. Z tabulky můžeme učinit následující závěry: •
U malých čítačů (zde příklad pro 8 stavů) téměř nehraje roli, jaký typ čítače zvolíme. Sčítačky v binárním a Grayově čítači jsou natolik optimalizované a redukované, že jejich zpoždění jsou zanedbatelná proti zpožděním na spojích v obvodu. Johnsonův čítač má proti čítači 1 z N handicap v nutnosti vložit invertor do cesty mezi výstupem druhého a vstupem nultého stavového registru čítače; tato cesta je omezující pro jeho maximální hodinovou frekvenci.
•
Pro středně velké čítače (zde příklad pro 64 stavů) platí celkem dobře to, co jsme uvedli výše. Johnsonův čítač a čítač 1 z N mají téměř shodné maximální hodinové frekvence (minimální perioda se liší jen o 100 ps, vyšší rychlost Johnsonova čítače je zde zjevně způsobena lepším rozmístěním a propojením jeho logických prvků). Oba jsou rychlejší než binární a Grayův čítač. Mírně abnormální vyšší rychlost Grayova čítače proti binárnímu je způsobena dobrou optimalizací kombinační logiky generující příští stav a šikovnějším rozmístěním a propojením. Rozdíl mezi oběma bloky je tak také v řádu 100 ps v délce kritické cesty.
•
U velkých čítačů (1024 stavů pro binární, Grayův, 200 pro 1 z N a 400 pro Johnsonův) se stává použití
12
Johnsonova čítače a čítače 1 z N nevýhodné. Zabírají příliš mnoho logických prvků, nicméně jsou oba schopny pracovat na nejvyšší hodinové frekvenci. Grayův čítač vidíme, že je nyní mnohem pomalejší, než binární díky komplexnější logické funkci pro generování příštího stavu. Asynchronní čítač je na první pohled světem sám pro sebe. Musíme rozlišit dva možné způsoby jeho užití. Užijeme-li ho pro čítání událostí, není při správném návrhu třeba vyžadovat jeho ustálení do příchodu další hrany na hodinovém signálu. Pak můžeme čítač ve všech případech provozovat až na frekvenci cca 1,4GHz. Budeme-li chtít asynchronní čítač užít jako náhradu běžného čítače, je nezbytné aby došlo k ustálení čítače před příchodem další hrany hodin; odpovídající perioda a frekvence hodin je uvedena v tabulce v závorce. Zde je patrný lineární nárůst zpoždění s rostoucím počtem registrů v čítači; zpoždění na registr je zhruba 0,6 ns. Závěrem bychom čtenáře rádi upozornili na internetovou stránku [4], na které je k dispozici balíček s přílohou k článku se všemi zdrojovými kódy čítačů. •
Čítač
LUTů
DFF
Délka kritické cesty
Binární
O(log2 Ns)
log2 Ns
O(log2 Ns)
Johnsonův
1
Ns/2
1
Grayův
O(log2 Ns)
log2 Ns
O(log2 Ns)
1zN
0
Ns
1
LFSR
O(1)
log2 Ns
O(1)
Asynchronní
0
log2 Ns
1
Tabulka 2: Srovnání parametrů jednotlivých čítačů. Zápis O(n) znamená "řádově n", délka kritické cesty je v počtech obecných kombinačních hradel v cestě. Čítač Binární
Grayův
Johnsonův
1zN
Asynchronní
Ns
LUT
DFF
fclk_max [MHz]/Tclk_min [ns]
8
3
3
1470 MHz/0,68 ns
64
6
6
934 MHz/1,07 ns
1024
10
10
843 MHz/1,186 ns
8
3
3
1282 MHz/0,78 ns
64
6
6
961 MHz/1,04 ns
1024
17
10
534 MHz/1,87 ns
8
1
4
1010 MHz/0,99 ns
64
1
32
1123 MHz/0,89 ns
400
1
200
877 MHz/1,14 ns
8
0
8
1351 MHz/0,74 ns
64
0
64
1010 MHz/0,99 ns
200
0
200
800 MHz/1,25 ns
8
3
3
1470 MHz/0,68 ns (608 MHz/1,64 ns)
64
6
6
1492 MHz/0,67 ns (284 MHz/3,52 ns)
1024
10
10
1470 MHz/0,68 ns (158 MHz/6,31 ns)
Tabulka 3: Parametry jednotlivých typů čítačů.
4 Cvičení 1. Implementujte v prostředí ISE univerzální binární čítač z příkladu 1, použijte stejné FPGA jako v našich příkladech. Jak závisí maximální hodinová frekvence na N? Spusťte statickou časovou analýzu pro N=16, zjistěte maximální hodinovou frekvenci, na které čítač může pracovat. Upravte generování signálu pro detekci přetečení následujícím způsobem: 13
cnt_ofl <= '1'
WHEN signed('0'&cnt_q) >= signed('0'&cnt_limit)- signed('0'&cnt_step) ELSE'0';
Jak se změní po úpravě maximální dosažitelná hodinová frekvence? Jaký má úprava vliv na velikost čítače? 2. Navrhněte generátor sekvence z obrázku 11 podle schématu uvedeného v obrázku 1 s použitím binárního, Johnsonova, 1 z N, LFSR i Grayova čítače a binárního asynchronního čítače. Srovnejte velikosti implementací a dosažitelné fclk_max, pozorujte v simulaci na hradlové úrovni chování výstupů ctrl1 a 2 bloku. Pro který čítač je na nich nejvíce a pro který nejméně zákmitů?
Obrázek 11: Sekvence generovaných stavů čítačem. Soubor cviceni.eps.
3. Implementujte asynchronní binární čítač čítající dolů.
5 Doporučená literatura [1] Jakub Šťastný. FPGA prakticky, BEN Praha 2011. [2] Hamming Distance. http://en.eikipedia.org/wiki/Hamming_distance [3] Milan Křemeček. Implementace základních logických funkcí na FPGA, bakalářská práce, FPGA Laboratoř, Katedra teorie obvodů FEL ČVUT v Praze, 2006. http://amber.feld.cvut.cz/fpga/publications/BP_Kremecek_2006.pdf (kontrolováno 1.5.2011). [4] Jakub Šťastný. FPGA návrh. http://amber.feld.cvut.cz/fpga/prednasky/FPGA_navrh/fpga_navrh.html
14