Hlavní navigace

Mikrořadiče a DSP společnosti Infineon

21. 2. 2017
Doba čtení: 27 minut

Sdílet

Vývojem DSP se kromě společností TI a Motorola samozřejmě zabývají i další firmy. Dnes se seznámíme s některými zajímavými čipy určenými pro automobilové i průmyslové aplikace, které jsou vyvíjeny ve společnosti Infineon.

Obsah

1. Mikrořadiče a DSP společnosti Infineon

2. Osmibitové mikrořadiče založené na 8051

3. Řada XC800, rodina A a I

4. Moduly mikrořadičů řady XC800

5. Vylepšené jádro 8051

6. Paměťový subsystém

7. Multiplication/Division Unit (MDU)

8. Field Oriented Control (FOC)

9. Algoritmus CORDIC (COrdinate Rotation DIgital Computer)

10. Princip CORDICu: rotace vektoru r okolo počátku souřadného systému

11. Úprava vztahu rotace vektoru pro algoritmus CORDIC

12. Hodnoty úhlů, po kterých se provádí rotace

13. Ukázka: výpočet funkcí sin a cos algoritmem CORDIC

14. CORDIC a formát pevné řádové čárky

15. CORDIC na čipech XC800

16. Odkazy na Internetu

1. Mikrořadiče a DSP společnosti Infineon

Dalším výrobcem (nejenom) digitálních signálových procesorů je německá společnost Infineon, která se zaměřuje na čipy určené pro automobilový průmysl a taktéž pro různé řídicí systémy v průmyslu (průmyslová automatizace, diagnostika atd.). Spektrum čipů, které Infineon vyráběl či vyrábí, je poměrně široké: od osmibitových mikrořadičů (například řady C505, nověji XC800) založených na dnes již pravěké, ale stále používané architektuře 8051 přes čipy s některým ARMovským mikrořadičovým jádrem Cortex-M (řada XMC1000 používá Cortex-M0 a řada XMC4000 Cortex-M4) až po 32bitové čipy s architekturou TriCore, v nichž se kombinují možnosti RISCových procesorů, digitálních signálových procesorů a mikrořadičů. Vzhledem k tomu, pro jaké typy aplikací jsou čipy společnosti Infineon určeny, asi nepřekvapí, že jsou v naprosté většině případů vybaveny rozhraním pro sběrnici CAN (CAN Bus) popř. jednodušší sběrnice LIN a u mnoha mikrořadičů nalezneme i pomocné „koprocesory“ určené například pro řízení elektrických motorů apod.

Obrázek 1: Dobový vývojový kit s původním mikrořadičem Intel 8051 (MCS-51).

2. Osmibitové mikrořadiče založené na 8051

Některé významné čipy Infineon si v tomto seriálu postupně popíšeme. Začneme přitom těmi nejméně výkonnými osmibitovými mikrořadiči, které jsou postaveny na architektuře 8051. Aby byly tyto mikrořadiče použitelné i pro řídicí účely, jsou vybaveny pomocnými moduly, typicky samostatnou násobičkou a děličkou, modulem pro algoritmus CORDIC atd. (s velkou pravděpodobností tyto moduly zabírají větší plochu čipu, než samotné jádro 8051). Díky přidání pomocných modulů a taktéž navýšením kapacity pamětí pro programový kód a data je možné čipy s jádrem 8051 nasadit i v těch oblastech, kde by jinak byl vyžadován výkonnější mikrořadič, ať již osmibitový (H8, S08), šestnáctibitový (H8–300H, MSP430) či 32bitový (Cortex-M0, Cortex-M3, Cortex-M4, Cortex-M7, SuperH).

Obrázek 2: Připojení LCD s rozlišením 128×64 pixelů k mikrořadiči 8051.

Již na tomto místě si však musíme říct, že největší nevýhody 8051 vlastně vůbec nebyly odstraněny, což se týká jak omezeného adresního prostoru, tak i malého množství pracovních registrů (jedná se akumulátorovou architekturu, takže často musí docházet k přesunům dat, i když se další výrobci klonů 8051 snažili rozšířit instrukční soubor a toto omezení obejít), nízké kapacity zásobníku a jen velmi jednoduchých adresovacích režimů (zejména se to týká použití šestnáctibitových adres, kde lze použít jediný adresní registr). To vše se negativně projevuje především při programování v céčku či v dalších vyšších programovacích jazycích.

Obrázek 3: „Zbastlený“ video výstup založený na přímém programovém ovládání tří signálů – LUMINANCE (světlost), BLANK (interval v němž je obraz zatemněný – okraje a návrat paprsku) a SYNC (synchronizační impuls) mikrořadičem 8051 (resp. přesněji řečeno jeho rychlejší variantou). Všechny tři signály jsou pomocí čtveřice rezistorů smíchány a tvoří tak vstup (kompozitní video bez barvonosné složky) pro televizor pracující v normě PAL, SECAM či NTSC.

3. Řada XC800, rodina A a I

Mezi mikrořadiče s jádry založenými na 8051 patří především řada čipů nazvaná XC800. Tyto čipy jsou rozděleny do dvou velkých rodin: XC800 A-Family a XC800 I-Family. A-Family obsahuje mikrořadiče určené pro automobilový průmysl (A značí automotive), zatímco do I-Family patří čipy pro průmyslovou automatizaci (I značí industry). Jak jsme si již řekli v předchozí kapitole, jsou tyto mikrořadiče postaveny na jádru 8051, které ovšem bylo vylepšeno a při shodné hodinové frekvenci by bylo šestkrát výkonnější, než původní Intel 8051 (ve skutečnosti však čipy Infineon používají vyšší hodinové frekvence, typicky 24 až 27 MHz podle konkrétního typu čipu). Okolo vylepšeného jádra 8051 byly přidány další moduly, které na původních mikrořadičích Intel 8051 a Intel 8052 nenajdeme. Typicky se jedná o sériové sběrnice a porty SPI, I2C, většinou i CAN Bus (Controller Area Network) a/nebo poněkud jednodušší a levnější LIN (Local Interconnect Network). Dále většina čipů řady XC800 obsahuje i vícekanálový A/D převodník s rozlišením deseti bitů, větší kapacitu RAM i ROM a možnost použít paměť Flash jak pro program, tak i pro data (viz navazující kapitoly). Nesmíme zapomenout ani na „koprocesory“, jejichž popisu je věnována druhá polovina dnešního článku.

Čipy XC800 mohou být na jedné straně připojeny ke sběrnici CAN, na straně druhé pak mohou přímo ovládat k nim připojená zařízení, a to přes SPI, SSI, I2C a paralelní porty, číst stav čidel (jak digitálních, tak i analogových) apod.

4. Moduly mikrořadičů řady XC800

Na následujícím obrázku jsou zobrazeny všechny základní moduly mikrořadičů XC800 postavené okolo mikroprocesorového jádra založeného na 8051. Moduly jsou rozděleny podle své funkce, nikoli podle toho, jakým způsobem jsou interně zapojeny (interně čip obsahuje několik sběrnic atd.). Povšimněte si mnohých rozšíření oproti „klasickým“ starodávným mikrořadičům 8051. Nalezneme zde více bloků paměti (navíc s mnohem vyšší kapacitou), větší množství časovačů včetně šestnáctibitového watchdogu, sériové sběrnice a porty, A/D převodníky, dva paralelní porty navíc a taktéž koprocesory nazvané MDU a CORDIC:

Obrázek 4: Základní moduly mikrořadičů XC800.

Význam některých použitých zkratek:

  1. BootROM jediná skutečná ROM s uloženým programovým kódem pro inicializaci MCU, spuštění ladění atd. Zbylá část programu je uložena v paměti Flash. Typická velikost BootROM je 8KB.
  2. Flash je význačná tím, že se v ní používají ECC umožňující opravit jednobitovou chybu v každém bajtu a odhalit dva chybné bity. Typická kapacita dosahuje 52 až 64 KB.
  3. XRAM je běžný blok paměti RAM, která může být adresovaná buď jako programová paměť nebo jako externí datová paměť. Jedná se o jediný blok paměti, který je však dostupný jak přes instrukci MOVX, tak i instrukcí MOVC. Původní význam zkratky XRAM je External RAM, zde se však jedná o RAM umístěnou přímo na mikrořadiči.
  4. UART klasický sériový port s asynchronním přenosem dat a konfigurovatelným počtem datových bitů, délky stop bitu, výpočtu parity atd.
  5. SSP (Synchronous Serial Port) řadič podporující sběrnici SPI i sériové rozhraní SSI.
  6. SPI (Serial Peripheral Interface) standardní sériová sběrnice.
  7. SSI (Synchronous Serial Interface) jednodušší sériové rozhraní pro jednosměrný přenos dat.
  8. CAN (Controller Area Network) je průmyslová sběrnice často používaná v automotive i v průmyslových aplikacích.
  9. MDU (Multiplication/Division Unit) je koprocesor, který bude popsán v sedmé kapitole.
  10. CORDIC (COrdinate Rotation DIgital Computer) je koprocesor, který bude popsán v deváté kapitole.

5. Vylepšené jádro 8051

Vylepšené jádro použité v mikrořadičích XC800, které je označováno názvem „E-warp“, zachovává kompatibilitu s původními čipy Intel 8051/Intel 8052 jak na binární úrovni, tak i na úrovni zdrojových kódů. Došlo ovšem k vylepšení interní struktury, takže běžné instrukce se namísto dvanácti cyklů provedou jen ve dvou cyklech (šestinásobné urychlení při použití stejné hodinové frekvence). Existují ovšem i delší instrukce, konkrétně instrukce provedené za čtyři cykly (INC DPTR protože chybí 16bitová ALU) o dokonce i za osm cyklů (MUL AB a DIV AB, mimochodem tyto instrukce na původním 8051 trvaly 48 cyklů, takže se stále jedná o šestinásobné urychlení). Nová a tím pádem i zpětně nekompatibilní instrukce existuje jen jedna: MOVC @(DPTR++), A, která je mapována na kód 0×A5, který původně nebyl použit (v tabulce umístěné pod tímto odstavcem je tento kód reprezentován prázdnou červenou buňkou).

Obrázek 5: Instrukční sada mikrořadiče MCS-51.

U mikrořadičů 8051 se velké množství operací provádí s osmibitovým akumulátorem A, jedním z pracovních registrů R0R7, popř. s buňkou paměti adresovanou registrem R0 či R1. Navíc je však možné mnoho operací provádět přímo s paměťovými buňkami v interní paměti údajů nebo s registry speciálních funkcí (SFR); existuje například instrukce typu MOV adresa, #osmibitová_data, kterou lze naplnit libovolnou buňku interní RAM (ležící na adresách 0×00 až 0×7f) popř. SFR.

Kvůli tomu, že rozsah takzvané „externí paměti“ RAM může v případě původního 8051 nabývat až kapacity 64 kB, je množina pracovních registrů doplněna o šestnáctibitový registr DPTR (Data Pointer), do něhož lze přímo načíst šestnáctibitovou konstantu instrukcí MOV DPTR, #šestnáctibitová_data, popř. zvýšit jeho hodnotu o jedničku pomocí instrukce INC DPTR, což je užitečné například při procházení polem.

6. Paměťový subsystém

Paměťový subsystém čipů XC800 je poměrně složitý, což vyplývá z omezení samotné architektury 8051. Relativní složitost uspořádání pamětí a adresovacích režimů vynikne zejména při porovnání s některými dalšími (novějšími) osmibitovými mikrořadiči, například s čipy H8. Původní mikrořadiče 8051 totiž obsahovaly interní paměť údajů o kapacitě pouhých 128 bajtů (v případě modelu 8052 dokonce „celých“ 256 bajtů), ke které byla navíc připojena paměťová oblast o velikosti taktéž 128 bajtů, do níž byly mapovány registry speciálních funkcí (SFR). Prvních 128 bajtů RAM je dostupných přímo; z pohledu programátora se jedná o adresy 0×00 až 0×7f.

Do adresového rozsahu 0×80 až 0×ff, tj. do 128 bajtů ležících za pamětí údajů, je namapována oblast takzvaných registrů speciálních funkcí neboli SFR (Special Function Registers). Jedná se o registry, pomocí nichž se konfigurují různé moduly mikrořadiče Intel 8051, například čítače/časovače, sériový port a paralelní porty, nebo jsou v nich naopak uloženy různé příznaky a data naplňovaná samotným mikrořadičem, zejména příznak přetečení čítače/časovače, znak přijatý sériovým portem, stav jednotlivých přerušení atd. Mezi registry speciálních funkcí patří i samotný akumulátor A/ACC uložený na adrese 0×e0, pomocný registr B na adrese 0×f0, který je používán při násobení a dělení, stavové slovo programu PSW či ukazatel na vrchol zásobníku SP. Některé registry speciálních funkcí jsou dostupné pouze jako celistvé bajty, tj. jejich obsah lze načíst například instrukcí mov A,direct, ovšem několik těchto registrů lze alternativně adresovat i po jednotlivých bitech, podobně jako oblast 128 bitů (16 bajtů) v paměti údajů (tyto registry jsou součástí Boolovského procesoru).

Obrázek 6: Obsah speciálních funkčních registrů zobrazený v emulátoru J51.

Přístup k paměti údajů (tj. ke 128 bajtům na adresách 0×00 až 0×7f) i k registrům speciálních funkcí (128 bajtů na adresách 0×80 až 0×ff) je jednoznačný v případě mikrořadiče Intel 8051, ovšem u mikrořadiče Intel 8052 museli jeho konstruktéři vyřešit, jakým způsobem bude adresování probíhat ve chvíli, kdy má paměť údajů kapacitu 256 bajtů namísto 128 bajtů, a adresy v instrukčních slovech mají pouze osmibitovou délku. Řešení tohoto problému spočívá v tom, že horních 128 bajtů paměti údajů je dostupných pouze při nepřímé adresaci (tj. použití instrukcí s operandy @R0 a @R1), zatímco dolních 128 bajtů paměti údajů a 128 bajtů se SFR je dostupných při adresaci přímé.

Situace se dále komplikuje v případě, že je k interní paměti údajů navíc připojena paměť externí, musí se použít plná šestnáctibitová adresa, která je uložená v šestnáctibitovém registru DPTR (Data Pointer), popř. osmibitová adresa uložená v registru R0 či R1, ovšem horních osm bitů adresy musí být při provedení instrukce „vystaveno“ na portu číslo 2.

Poznámka: „externí paměť“ je sice stále používaný termín, ovšem na XC800 je i tato paměť umístěna na stejném čipu.

Programová paměť je z tohoto hlediska jednodušší, protože se může jednat o jediný blok o velikosti 64 kB (původně jen 4 kB).

Konstruktéři čipů XC800 museli tyto vlastnosti původních mikrořadičů 8051 a 8052 brát v úvahu aby dodrželi zpětnou kompatibilitu. Proto navrhli systém paměťových banků, který vlastně známe i z mnoha dalších typů mikroprocesorů. Čipy XC800 totiž adresují až 1 MB paměti, která je rozdělena do banků o velikosti 64 kB (takových banků je šestnáct). Banky se používají jak pro programovou paměť, tak i pro paměť datovou. O přepínání banků se stará modul MMU neboli Memory Management Unit, který obsahuje trojici čtyřbitových registrů: CB (Current Bank), NB (Next Bank) a IB (Interrupt Bank).

Navíc se musí dodržet zpětná kompatibilita při přechodu mezi paměťovými banky, což znamená, že relativní skoky nikdy bank nemění (pro tyto skoky paměť stále končí na hranici 64 kB; chudáci programátoři překladačů). Jediné instrukce, které bank mohou přepnout, jsou instrukce LJMP, LCALL a ACALL, u datové paměti je přepnutí vždy explicitní. Navíc došlo k další změně – zásobník o velikosti 128 bajtů může být umístěn kdekoli v paměťovém rozsahu 1 MB, není tedy nutné, aby zabíral cenné bajty v prvních dvou oblastech RAM (to sice není zpětně kompatibilní chování, ale v případě potřeby lze zajistit původní umístění zásobníku).

O bloku XRAM jsme se již zmínili – ta je namapována do datového prostoru v banku 2 a v programovém prostoru v posledním šestnáctém banku. Lze ji tedy zpřístupnit jak instrukcí MOVX (přes DPTR či R0 R1) tak i MOVC.

7. Multiplication/Division Unit (MDU)

Vzhledem k tomu, že instrukce MUL AB akceptuje osmibitové operandy se šestnáctibitovým výsledkem a instrukce DIV AB počítá jen osmibitové výsledky, jsou čipy XC800 doplněny o samostatně pracující koprocesor nazvaný MDU neboli Multiplication/Division Unit. Tento obvod tvoří násobička a dělička pracující nezávisle na CPU, která je doplněna o sadu dvanácti datových registrů, jednoho řídicího registru a jednoho registru stavového (všechny registry jsou samozřejmě osmibitové). Kromě operací násobení a dělení dokáže MDU provést i bitové posuny doleva a doprava a taktéž operaci „normalizace“ vstupní hodnoty tak, aby nejvyšší bit byl vždy jedničkový. Tato operace vrací i počet provedených posunů, takže ji lze využít například při softwarové implementaci FP operací.

MDU podporuje tyto operace:

Operace Typ Operand 1 Operand 2 Výsledek Zbytek Počet hodinových cyklů
Násobení signed 16bit 16bit 32bit × 16
Dělení signed 32bit 16bit 32bit 16bit 33
Dělení signed 16bit 16bit 16bit 16bit 17
Násobení unsigned 16bit 16bit 32bit × 16
Dělení unsigned 32bit 16bit 32bit 16bit 32
Dělení unsigned 16bit 16bit 16bit 16bit 16
Normalizace × × × × × 1–32
Posun L/R × × × × × 1–32

Tento modul obsahuje následující registry:

Registr Význam
MDUSTAT stavový registru modulu
MDUCON řídicí registr, obsahuje mj. i kód prováděné operace a příznak, že se operace provádí (nuluje se automaticky)
MD0 registr pro vstupní operand
MR0 registr pro uložení výsledku
MD1 -//-
MR1 -//-
MD2 -//-
MR2 -//-
MD3 -//-
MR3 -//-
MD4 -//-
MR4 -//-
MD5 -//-
MR5 -//-

Příklady použití těchto registrů:

násobení 16bit × 16bit → 32bit:           MD1:MD0 × MD5:MD4 → MR3:MR2:MR1:MR0
dělení:  32bit ÷ 16bit → 16bit (+zbytek): MD3:MD2:MD1:MD0 ÷ MD5:MD5 → MR5:MR4 zbytek MR3:MR0

Poznámka: MDU lze zcela vypnout a snížit tak spotřebu celého čipu.

8. Field Oriented Control (FOC)

Důležitou součástí většiny mikrořadičů řady XC800 je modul nazvaný FOC neboli (Sensorless) Field Oriented Control*. Tento modul je, jak již jeho název napovídá, určený pro přesné řízení synchronních elektrických motorů (či mnohdy spíše motorků) s permanentními magnety v rotoru (PMSM – Permanent Magnet Synchronous Motor). Na rozdíl od krokových motorků vyžadují PMSM pro přesné řízení bez vzniku vibrací a zbytečně velkého namáhání hřídele vytvoření točivého magnetického pole ideálně se sinusovým průběhem. A právě pro vytvoření trojice analogových signálů se sinusovým průběhem a vzájemným fázovým posunem 120°, které navíc reaguje na zatížení atd. je určen FOC. Interní struktura tohoto modulu je poměrně složitá, ovšem nám postačuje vědět, že na vstupu je zapotřebí specifikovat referenční rychlost a na výstupu modulu FOC se analogové signály generují s využitím PWM (pulsně-šířkové modulace). Modul navíc musí zjišťovat aktuální polohu rotoru měřením proudu protékajícího statorem, takže obsahuje rychlý A/D převodník zapojený na výstup operačního zesilovače.

9. Algoritmus CORDIC (COrdinate Rotation DIgital Computer)

Velmi zajímavé je zařazení koprocesoru s implementovaným algoritmem CORDIC (COrdinate Rotation DIgital Computer). I zde se ukazuje, že autoři mikrořadičů XC800 zvolili řešení založené na relativně primitivním jádře 8051 vybaveném specializovanými moduly oproti obecnému rychlejšímu jádru, které by výpočty řešilo programově. Vraťme se však k CORDICu.

Jedná se o výpočetní metodu využívající iteraci, kterou pro účely jednoduchého a rychlého výpočtu goniometrických funkcí bez použití násobiček a děliček navrhl a zpopularizoval Jack Volder už v polovině minulého století. Později se ukázalo, že tuto metodu je možné po malých úpravách použít i pro výpočty dalších matematických funkcí, například arkustangenty, arkussinu, arkuskosinu, ale i pro vyčíslení délky vektoru či jeho rychlou rotaci o libovolný úhel; včetně transformace bodu či vektoru z polárních souřadnic do souřadnic kartézských. Již větší úpravy si vyžádala aplikace metody CORDIC pro výpočet hyperbolických funkcí (sinh(), cosh(), tanh()) a funkcí logaritmických, základní myšlenka a princip práce však zůstává stejný.

Vzhledem k tomu, že se při aplikaci algoritmu CORDIC využívají pouze ty nejzákladnější matematické operace (bitový posun doleva a doprava, sečítání, odečítání a porovnání dvou hodnot), je možné CORDIC využít ve všech číslicových systémech, ve kterých je zapotřebí šetřit použitými prostředky, tj. počtem logických hradel, kapacitou obsazené paměti, možnostmi použitých čipů atd. CORDIC tak byl implementován a s úspěchem používán například v kalkulačkách, osmibitových mikrořadičích (řada Intel 8051 a Motorola 68HC11), osmibitových domácích počítačích (Atari, Sinclair ZX Spectrum atd.) a mnoha specializovaných obvodech vytvořených pomocí programovatelných polí FPGA. Zajímavá je implementace CORDICu na mikrořadičové stavebnici Basic STAMP. V největší míře však bylo CORDICu využito v některých matematických koprocesorech (FPU), protože bylo zjištěno, že některé funkční bloky zabezpečující chod CORDICu zůstávají stále stejné, bez ohledu na to, jaká funkce je počítána, což do značné míry zjednodušilo (a tím pádem i zlevnilo) výrobu FPU. Samozřejmě se také snížil počet hradel nutných pro implementaci goniometrických, hyperbolických a logaritmických funkcí.

  1. Andraka, Ray: „A survey of CORDIC algorithms for FPGA based computers“,
    ACM, 1998
  2. Despain, A.M.:„Fourier Transform Computations Using CORDIC Iterations“,
    IEEE Transactions on Computers, Volume 23, strany 993–1001, 1974
  3. Mazenc C., Merrheim, X., Muller, J.M.: „Computing Functions Arccos and Arcsin Using CORDIC“,
    IEEE Transactions on Computers, Volume 42, strany 118–122, 1993
  4. Volder, Jack: „Binary computation algorithms for coordinate rotation and function generation“,
    Convair Report IAR-1, 1956
  5. Volder, Jack: „The CORDIC Trigonometric Computing Technique“,
    IRE Transactions on Electronic Computing, Vol EC-8, strany 330–334, 1959
  6. NVIDIA Corporation: „Floating-Point Specials on the GPU“,
    2005

10. Princip CORDICu: rotace vektoru r okolo počátku souřadného systému

Princip práce algoritmu CORDIC vychází z vyjádření rotace vektoru o určitý úhel δ a z následné úpravy vzorce pro rotaci tak, aby se eliminovaly zbytečně složité a časově náročné multiplikativní operace. Nejprve si napišme vzorce pro hodnoty funkcí sinus a kosinus součtu dvou úhlů. Jedná se o známé středoškolské vztahy používané pro úpravu výrazů s goniometrickými funkcemi:

sin(α+β)=sin α cos β + cos α sin β
cos(α+β)=cos α cos β – sin α sin β

Jak si ukážeme o několik odstavců níže, je možné tyto vzorečky použít pro vyjádření rotace vektoru. Vektor r, kterým budeme rotovat, může být vyjádřen souřadnicemi [x0, y0], přičemž je možné provést převod z kartézských souřadnic do souřadnic polárních:

x0=r cos φ
y0=r sin φ

kde r představuje délku vektoru r a φ je úhel vektoru měřený od kladné horizontální poloosy souřadného systému. Pokud bude vektor r rotován o úhel δ, změní se koncový bod vektoru tak, že bude ležet na kružnici o stejném poloměru r, ale úhel vektoru (opět měřený od kladné horizontální poloosy) se zvětší o δ. Tuto skutečnost je možné vyjádřit vztahy:

xr=r cos (φ+δ)
yr=r sin (φ+δ)

Dále je možné rozepsat výrazy cos (φ+δ) a sin (φ+δ) podle prvních dvou uvedených vzorečků a následně zpětně dosadit za výrazy r cos φ a r sin φ původní souřadnice vektoru r, tj. x0 a y0:

xr=r (cos φ cos δ – sin φ sin δ)=x0 cos δ – y0 sin δ
yr=r (sin φ cos δ + cos φ sin δ)=x0 sin δ + y0 cos δ

Všimněte si, že se ve výsledných vztazích nevyskytuje ani hodnota r ani úhel původního vektoru φ. To znamená, že převod na polární souřadnice pro nás byl pouze matematickou pomůckou při odvozování vzorce pro rotaci a ve skutečnosti se nebude nikdy provádět.

11. Úprava vztahu rotace vektoru pro algoritmus CORDIC

Pro účely algoritmu CORDIC se tento vztah dále upravuje. První úprava spočívá v tom, že se obě rovnice vydělí hodnotou cos δ, takže dostaneme vztahy:

xr /cos δ=x0 – y0 sin δ/cos δ
yr /cos δ=x0 sin δ/cos δ + y0

Pokud si uvědomíme skutečnost, že sin δ/cos δ=tan δ, můžeme pokračovat v úpravách:

xr /cos δ=x0 – y0 tan δ
yr /cos δ=y0 + x0 tan δ

a následně:

xr=cos δ(x0 – y0 tan δ)
yr=cos δ(y0 + x0 tan δ)

Nyní přichází základní myšlenka, na které je CORDIC postaven. Pokud budeme volit úhel δ takovým způsobem, aby jeho tangenta nabývala hodnot 2-i (pro i>0), je možné tangentu ve vzorci nahradit násobením zvolenou hodnotou 2-i; v tomto případě je však možné násobení nahradit jednoduchým a přitom rychlým bitovým posunem. Omezení hodnoty tangenty na zvolenou sadu hodnot však znamená, že se vektor nemůže rotovat o libovolný úhel, ale pouze o úhel odpovídající tangentě z dané sady. To však není problém, protože rotaci o libovolný je možné zapsat pomocí série rotací (doprava či doleva), například:

δ=δ123+…

Naproti tomu, že se parciální rotace mohou provádět v obou směrech (tj. jak doprava, tak i doleva), můžeme místo hodnoty cos δ dosadit konstantu Ki, protože platí cos δ=cos -δ. Nakonec místo tan δ přímo dosadíme mocninu dvojky 2-i a pomocí parametru di směr rotace (parametr di nabývá pouze hodnot +1 a –1):

xr=Ki (x0 – y0 di 2-i)
yr=Ki (y0 + x0 di 2-i)

Zbývá nám zjistit hodnotu konstanty Ki. Platí:

Ki=cos (arctan 2-i)=1/(1+2-2i)1/2

Limitně se součin hodnot Ki (po nekonečně mnoha iteracích) blíží k 0,6073, to znamená, že touto hodnotou bude v některých případech nutné vydělit výsledek (v jiných případech nám naopak toto zesílení při rotaci vadit nebude).

Veškerá práce algoritmu CORDIC spočívá v tom, že se nastaví počáteční souřadnice vektoru r a iterativně se provádí rotace o předem známé úhly δ1…δn tak, aby se dosáhlo požadované hodnoty rotace δ.

12. Hodnoty úhlů, po kterých se provádí rotace

Jak jsme si uvedli v předchozí kapitole, musí tangenty úhlů použitých v CORDICu splňovat podmínku tan δ=2-i. Pokud budeme veškeré výpočty provádět v prvním kvadrantu (ve skutečnosti však může počítat i ve čtvrtém kvadrantu), začíná se s úhlem 45°, tj. π/4, protože tan π/4=1. Další úhly jsou samozřejmě menší; o jaké hodnoty se konkrétně jedná, nám dá přehled následující tabulka:

i 21-i úhel δ
1 1.0000000000 45.000000000
2 0.5000000000 26.565051177
3 0.2500000000 14.036243468
4 0.1250000000 7.125016349
5 0.0625000000 3.576334375
6 0.0312500000 1.789910608
7 0.0156250000 0.895173710
8 0.0078125000 0.447614171
9 0.0039062500 0.223810500
10 0.0019531250 0.111905677

13. Ukázka: výpočet funkcí sin a cos algoritmem CORDIC

Nyní si na jednoduchém příkladu ukážeme, jakým způsobem je možné algoritmus CORDIC použít pro výpočet funkcí sinus a kosinus. Nejprve jsou spočteny tabulky úhlů a hodnota druhých záporných mocnin hodnoty 2. Při implementaci CORDICu na FPU, MCU či FPGA by se tyto tabulky samozřejmě znovu nevytvářely: tabulka úhlů by byla uložena v paměti (či masce obvodu) a tabulka mocnin hodnoty 2 by se implementovala pomocí bitových posunů.

Po vytvoření tabulek je již možné CORDIC spustit. Počáteční souřadnice vektoru r jsou nastaveny na hodnotu [1, 0]. Vektor je posléze v iterační smyčce rotován tak dlouho, dokud neproběhne daný počet iterací. Úhel vektoru r se přitom neustále přibližuje k zadanému úhlu δ, jelikož se v iterační smyčce adaptivně zadaný úhel buď zmenšuje či zvětšuje o hodnotu uloženou v tabulce atans[]. Výsledek, tj. hodnoty funkcí sinus a kosinus, je uložen v nových souřadnicích vektoru r (vynásobený o konstantu K) a to z toho důvodu, že vektor rotoval na jednotkové kružnici a souřadnice jakéhokoli bodu ležícího na jednotkové kružnici přímo odpovídají hodnotám sinu a kosinu úhlu tohoto bodu počítaného od kladné horizontální poloosy.

// --------------------------------------------------------
// Výpočet hodnot funkcí sin() a cos() pomocí iteračního
// algoritmu CORDIC.
// --------------------------------------------------------
 
#include <stdio.h>
#include <math.h>
 
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
 
// maximální počet iterací při běhu algoritmu
#define MAX_ITER 10
 
// "zesílení" při rotacích
#define K 0.6073
 
// tabulka arkustangentu úhlů
double atans[MAX_ITER];
 
// tabulka záporných celočíselných mocnin hodnoty 2
double pows[MAX_ITER];
 
// naplnění tabulek atans[] a pows[]
void createTables(void)
{
    int i;
    for (i=0; i<MAX_ITER; i++) {
        double p=pow(2.0, -i);
        atans[i]=atan(p);
        pows[i]=p;
    }
}
 
// výpočet funkcí sin() a cos() pro zadaný úhel delta
void sincos(double delta, double *sinval, double *cosval)
{
    int i;
    double x0=1.0;                          // nastavení počátečních podmínek
    double y0=0.0;
    double xn;
    for (i=0; i<MAX_ITER; i++) {            // iterační smyčka
        if (delta<0) {                      // úhel je záporný => rotace doleva
            xn=x0+y0*pows[i];
            y0-=x0*pows[i];
            delta+=atans[i];
        }
        else {                              // úhel je kladný => rotace doprava
            xn=x0-y0*pows[i];
            y0+=x0*pows[i];
            delta-=atans[i];
        }
        x0=xn;
    }
    *sinval=y0*K;                           // opravit "zesílení" výsledku
    *cosval=x0*K;
}
 
int main(void)
{
    int i;
    createTables();
    for (i=0; i<=90; i++) {                 // výpočetní smyčka
        double delta;                       // úhel, ze kterého se počítá sin a cos
        double sinval;                      // vypočtené hodnoty
        double cosval;
        double sinerr;                      // absolutní chyby
        double coserr;
        delta=i*M_PI/180.0;                 // převod úhlu na radiány
        sincos(delta, &sinval, &cosval);    // výpočet sinu a kosinu
        sinerr=fabs(sinval-sin(delta));     // výpočet absolutních chyb
        coserr=fabs(cosval-cos(delta));
                                            // tisk výsledků
        printf("%02d\t%12.10f\t%12.10f\t%12.10f\t%12.10f\t%8.3f%%\t%8.3f%%\n",
                i,
                sinval, cosval,
                sinerr, coserr,
                100.0*sinerr/sinval, 100.0*coserr/cosval);
    }
    return 0;
}
 
// finito

Výsledek běhu předchozího programu je zobrazen v následující tabulce. Kromě vypočtených hodnot sinů a kosinů zadaného úhlu je spočtena i absolutní a relativní chyba, přičemž je zapotřebí upozornit na to, že relativní chyba pro obě krajní hodnoty (ty by měly vyjít nulové) je poněkud zavádějící. V každém případě však výsledky běhu algoritmu pro deset iterací nejsou špatné, zvláště když si uvědomíme, že se v každé iteraci provádělo pouze několik základních operací, konkrétně dva bitové posuvy a tři součty (či rozdíly):

--------------------------------------------------------------------------------------------------
vstupní   vypočtená       vypočtená       sin             cos              sin               cos
úhel    hodnota sin()   hodnota cos()   absolutní chyba absolutní chyba  rel.chyba       rel.chyba
--------------------------------------------------------------------------------------------------
00      0.0011726802    1.0000761814    0.0011726802    0.0000761814     100.000%          0.008%
01      0.0167806202    0.9999360752    0.0006717863    0.0000883801       4.003%          0.009%
02      0.0363058568    0.9994176447    0.0014063601    0.0000268177       3.874%          0.003%
03      0.0519144682    0.9987285075    0.0004214880    0.0000989728       0.812%          0.010%
04      0.0714093909    0.9975241564    0.0016529171    0.0000398938       2.315%          0.004%
05      0.0858859660    0.9963821278    0.0012697767    0.0001874297       1.478%          0.019%
06      0.1053286152    0.9945147694    0.0008001519    0.0000071260       0.760%          0.001%
07      0.1208522102    0.9927479474    0.0010171332    0.0002017957       0.842%          0.020%
08      0.1401999641    0.9902008452    0.0010268631    0.0000672235       0.732%          0.007%
09      0.1556537948    0.9878894877    0.0007806702    0.0002011471       0.502%          0.020%
...
40      0.6418729918    0.7669112114    0.0009146178    0.0008667682       0.142%          0.113%
41      0.6567280845    0.7542293861    0.0006690555    0.0004801942       0.102%          0.064%
42      0.6684306187    0.7438778473    0.0006999876    0.0007330218       0.105%          0.099%
43      0.6828308344    0.7306817333    0.0008324743    0.0006719683       0.122%          0.092%
44      0.6941513412    0.7199358716    0.0005070292    0.0005960713       0.073%          0.083%
45      0.7062435465    0.7080775359    0.0008632347    0.0009707547       0.122%          0.137%
46      0.7199358716    0.6941513412    0.0005960713    0.0005070292       0.083%          0.073%
47      0.7306817333    0.6828308344    0.0006719683    0.0008324743       0.092%          0.122%
48      0.7438778473    0.6684306187    0.0007330218    0.0006999876       0.099%          0.105%
49      0.7542293861    0.6567280845    0.0004801942    0.0006690555       0.064%          0.102%
50      0.7669112114    0.6418729918    0.0008667682    0.0009146178       0.113%          0.142%
...
81      0.9878894877    0.1556537948    0.0002011471    0.0007806702       0.020%          0.502%
82      0.9902008452    0.1401999641    0.0000672235    0.0010268631       0.007%          0.732%
83      0.9927479474    0.1208522102    0.0002017957    0.0010171332       0.020%          0.842%
84      0.9945147694    0.1053286152    0.0000071260    0.0008001519       0.001%          0.760%
85      0.9963821278    0.0858859660    0.0001874297    0.0012697767       0.019%          1.478%
86      0.9975241564    0.0714093909    0.0000398938    0.0016529171       0.004%          2.315%
87      0.9987285075    0.0519144682    0.0000989728    0.0004214880       0.010%          0.812%
88      0.9994176447    0.0363058568    0.0000268177    0.0014063601       0.003%          3.874%
89      0.9999360752    0.0167806202    0.0000883801    0.0006717863       0.009%          4.003%
90      1.0000761814    0.0011726802    0.0000761814    0.0011726802       0.008%        100.000%

14. CORDIC a formát pevné řádové čárky

Ve skutečnosti se CORDIC prakticky vždy implementuje takovým způsobem, že se nepoužívají hodnoty typu double, ale formát s pevnou řádovou čárkou. Násobení hodnotami z tabulky pows se nahradí bitovým posunem, takže se v iterační smyčce používají jen základní operace: součet, rozdíl a bitové posuny, zhruba takto:

/* datový typ, se kterým budeme pracovat */
typedef signed int fx;
 
/* výpočet funkce sin() pro zadaný úhel delta */
fx fx_sin_cordic_optim_iter(fx delta, int iter)
{
    int i;
    static fx K_fx=(fx)(K_float*(2<<(B-1)));
    /* nastavení počátečních podmínek */
    fx x0=int2fx(1);
    fx y0=0;
    fx xn;
    for (i=0; i<iter; i++) {                /* iterační smyčka */
        if (delta<0) {                      /* úhel je záporný => rotace doleva */
            xn=x0 + y0>>i;                  /* místo násobení bitový posuv */
            y0-=x0>>i;
            delta+=atans[i];
        }
        else {                              /* úhel je kladný => rotace doprava */
            xn=x0 - y0>>i;
            y0+=x0>>i;
            delta-=atans[i];
        }
        x0=xn;
    }
    return fx_mul(y0, K_fx);                /* opravit "zesílení" výsledku */
}

Podobným způsobem je CORDIC implementován v koprocesoru mikrořadiče XC800.

15. CORDIC na čipech XC800

Mikrořadiče XC800 obsahují koprocesor pro výpočet hodnot různých funkcí s využitím algoritmu CORDIC, který je zde parametrizovatelný a umožňuje používat nejenom předpočítané hodnoty funkce atan (rotace tak, jak je chápána v Euklidovské geometrii), ale atanh (rotace v hyperbolické geometrii) a lineární funkci (ta se hodí při násobeních a děleních). Počet iterací při výpočtu dosahuje šestnácti kroků, což je pro většinu použití plně dostačuje, a to jak z hlediska přesnosti výsledku, tak i doby trvání výpočtu. Navíc je možné zvolit rychlost výpočtů – buď se použije původní hodinový signál či signál vynásobený dvěma (pravděpodobně se provede synchronizace na obě hrany signálu). Při použití dvojnásobné rychlosti výpočtu a šestnácti iterací je výpočet dokončen v přibližně 41 cyklech, což je hodnota, která by nebyla čistě softwarovými prostředky vůbec možná, zvláště s ohledem na to, že výsledek je 16bitový a mezivýpočty jsou prováděny s přesností 20 bitů.

Hodnoty ei jsou vybírány z tabulky hodnot funkcí atan či atanh podle postupu popsaného v předchozích kapitolách. Pro klasický CORDIC je m=1, pro hyperbolickou geometrii je m=-1.

root_podpora

Tabulky hodnot funkcí atan a atanh obsahují slova široká dvacet bitů; interně je použit formát FX (fixed point) s devatenácti bity za řádovou čárkou (tečkou).

Komunikace s koprocesorem CORDIC probíhá přes několik registrů. Samotný koprocesor pracuje nezávisle na CPU (který může jednoduše zjistit, zda již došlo k dokončení výpočtu či zda je dostupný pouze mezivýsledek):

Registr Význam
CD_CORDxL použit pro zápis prvotní hodnoty X pro algoritmus CORDIC
CD_CORDxH dtto, ovšem obsahuje horních osm bitů
   
CD_CORDYL podobný význam, ovšem pro hodnotu Y
CD_CORDYH podobný význam, ovšem pro hodnotu Y
   
CD_CORDZL podobný význam, ovšem pro hodnotu Z
CD_CORDZH podobný význam, ovšem pro hodnotu Z
   
CD_STATC stavový a datový registr
CD_CON řídicí registr

16. Odkazy na Internetu

  1. XC800 family
    https://en.wikipedia.org/wi­ki/XC800_family
  2. Permanent Magnet Synchronous Motor
    https://en.wikipedia.org/wi­ki/Synchronous_motor#Perma­nent_magnet_motors
  3. Implementing field oriented control of a brushless DC motor
    http://www.eetimes.com/do­cument.asp?doc_id=1279321
  4. Vector control (motor)
    https://en.wikipedia.org/wi­ki/Vector_control_(motor)
  5. Motorola DSP56k
    https://www.rockbox.org/wi­ki/MotorolaDSP56k
  6. Motorola 56000 (Wikipedia)
    http://en.wikipedia.org/wi­ki/Motorola_56000
  7. Using the Motorola DSP56002EVM for Amateur Radio DSP Projects
    http://www.johanforrer.net/EV­M/article.html
  8. The Atari Falcon030 „Personal Integrated Media System“
    http://www.atarimuseum.com/com­puters/16bits/falcon030.html
  9. Turtle Beach Corporation (stránky společnosti)
    http://www.turtlebeach.com/
  10. Turtle Beach Corporation (Wikipedia)
    https://en.wikipedia.org/wi­ki/Turtle_Beach_Corporati­on
  11. Atari Falcon 030 DSP 3D engine test
    http://www.digiti.info/vi­deo/WHQwMjNRaExfLWs=/atari_fal­con030_dsp_3d_engine_test
  12. Atari Falcon030 (německy)
    http://www.maedicke.de/ata­ri/hardware/falcon.htm
  13. Old-computers.com: Atari Falcon030
    http://www.old-computers.com/museum/compu­ter.asp?c=125&st=1
  14. Atari Falcon030 (Wikipedia)
    http://en.wikipedia.org/wi­ki/Atari_Falcon
  15. Past and current projects (including Falcon stuff)
    http://os.inf.tu-dresden.de/~nf2/projects/projects.html
  16. Atari Falcon 030: The Case For The Defence
    http://www.soundonsound.com/sos/1994_ar­ticles/sep94/atarifalcon.html
  17. DaVinci processor family
    http://www.ti.com/general/doc­s/datasheetdiagram.tsp?ge­nericPartNumber=TMS320DM365&di­agramId=64193
  18. Texas Instruments DaVinci
    https://en.wikipedia.org/wi­ki/Texas_Instruments_DaVin­ci
  19. TMS320DM6446 (DaVinci)
    http://www.ti.com/product/tms320dm6446
  20. Digital Media Video Processors (TI)
    http://www.ti.com/lsds/ti/pro­cessors/dsp/media_processor­s/davinci/products.page#
  21. TI Wiki
    http://processors.wiki.ti­.com/index.php/Main_Page
  22. C5000 ultra-low-power DSP
    http://www.ti.com/lsds/ti/pro­cessors/dsp/c5000_dsp/over­view.page
  23. OMAP (Wikipedia)
    https://en.wikipedia.org/wiki/OMAP
  24. OMAP – TI Wiki
    http://processors.wiki.ti­.com/index.php/OMAP
  25. Why OMAP can't compete in smartphones
    http://www.eetimes.com/au­thor.asp?section_id=40&doc_id=1286602
  26. Applications Processors – The Heart of the Smartphone
    http://www.engineering.com/E­lectronicsDesign/Electronic­sDesignArticles/ArticleID/5791/Ap­plications-Processors-The-Heart-of-the-Smartphone.aspx
  27. TI cuts 1,700 jobs in OMAP shift
    http://www.eetimes.com/do­cument.asp?doc_id=1262782
  28. VLIW: Very Long Instruction Word: Texas Instruments TMS320C6×
    http://www.ecs.umass.edu/e­ce/koren/architecture/VLIW/2/ti1­.html
  29. An Introduction To Very-Long Instruction Word (VLIW) Computer Architecture
    Philips Semiconductors
  30. VLIW Architectures for DSP: A Two-Part Lecture (PDF, slajdy)
    http://www.bdti.com/MyBDTI/pub­s/vliw_icspat99.pdf
  31. Very long instruction word (Wikipedia)
    https://en.wikipedia.org/wi­ki/Very_long_instruction_word
  32. A VLIW Approach to Architecture, Compilers and Tools
    http://www.vliw.org/book/
  33. VEX Toolchain (VEX = VLIW Example)
    http://www.hpl.hp.com/downloads/vex/
  34. Elbrus (computer)
    https://en.wikipedia.org/wi­ki/Elbrus_%28computer%29
  35. Super Harvard Architecture Single-Chip Computer
    https://en.wikipedia.org/wi­ki/Super_Harvard_Architec­ture_Single-Chip_Computer
  36. Digital Signal Processors (stránky TI)
    http://www.ti.com/lsds/ti/pro­cessors/dsp/overview.page
  37. C674× Low Power DSP (stránky TI)
    http://www.ti.com/lsds/ti/pro­cessors/dsp/c6000_dsp/c674×/o­verview.page
  38. TMS320C30 (stránky TI)
    http://www.ti.com/product/tms320c30
  39. TMS320C6722B
    http://www.ti.com/product/tms320c6722b/des­cription
  40. Introduction to DSP
    http://www.ti.com/lit/wp/spry281/spry­281.pdf
  41. The Evolution of TMS (Family of DSPs)
    http://www.slideshare.net/mo­to_modx/theevo1
  42. Datasheet k TMS32010
    http://www.datasheetarchi­ve.com/dlmain/49326c32a52050140ab­ffe6f0ac4894aa09889/M/TMS32010
  43. 1979: Single Chip Digital Signal Processor Introduced
    http://www.computerhistory­.org/siliconengine/single-chip-digital-signal-processor-introduced/
  44. The TMS32010. The DSP chip that changed the destiny of a semiconductor giant
    http://www.tihaa.org/histo­rian/TMS32010–12.pdf
  45. Texas Instruments TMS320 (Wikipedia)
    https://en.wikipedia.org/wi­ki/Texas_Instruments_TMS320
  46. Great Microprocessors of the Past and Present: Part IX: Signetics 8×300, Early cambrian DSP ancestor (1978):
    http://www.cpushack.com/CPU/cpu2­.html#Sec2Part9
  47. Great Microprocessors of the Past and Present (V 13.4.0)
    http://jbayko.sasktelwebsi­te.net/cpu.html
  48. Introduction to DSP – DSP processors:
    http://www.bores.com/courses/in­tro/chips/index.htm
  49. The Scientist and Engineer's Guide to Digital Signal Processing:
    http://www.dspguide.com/
  50. Digital signal processor (Wikipedia EN)
    http://en.wikipedia.org/wi­ki/Digital_signal_processor
  51. Digitální signálový procesor (Wikipedia CZ)
    http://cs.wikipedia.org/wi­ki/Digitální_signálový_pro­cesor
  52. Digital Signal Processing FAQs
    http://dspguru.com/dsp/faqs
  53. Reprezentace numerických hodnot ve formátech FX a FP
    http://www.root.cz/clanky/fixed-point-arithmetic/
  54. IEEE 754 a její příbuzenstvo: FP formáty
    http://www.root.cz/clanky/norma-ieee-754-a-pribuzni-formaty-plovouci-radove-tecky/
  55. Čtyři základní způsoby uložení čísel pomocí FX formátů
    http://www.root.cz/clanky/binarni-reprezentace-numerickych-hodnot-v-fx-formatu/
  56. Základní aritmetické operace prováděné v FX formátu
    http://www.root.cz/clanky/zakladni-aritmeticke-operace-provadene-ve-formatu-fx/
  57. Aritmetické operace s hodnotami uloženými ve formátu FP
    http://www.root.cz/clanky/aritmeticke-operace-s-hodnotami-ve-formatu-plovouci-radove-carky/
  58. FIR Filter FAQ
    http://dspguru.com/dsp/faqs/fir
  59. Finite impulse response (Wikipedia)
    http://en.wikipedia.org/wi­ki/Finite_impulse_response
  60. DSPRelated
    http://www.dsprelated.com/
  61. Addressing mode (Wikipedia)
    https://en.wikipedia.org/wi­ki/Addressing_mode
  62. Orthogonal instruction set
    https://en.wikipedia.org/wi­ki/Orthogonal_instruction_set
  63. TI 16-bit and 32-bit microcontrollers
    http://www.ti.com/lsds/ti/mi­crocontrollers16-bit32-bit/overview.page
  64. TMS 32010 Assembly Language Programmer's Guide (kniha na Amazonu)
    https://www.amazon.com/32010-Assembly-Language-Programmers-Guide/dp/0904047423
  65. COSC2425: PC Architecture and Machine Language, PC Assembly Language
    http://www.austincc.edu/rblac­k/courses/COSC2425/index.html

Byl pro vás článek přínosný?