William Sandqvist william@kth.se Räknare En räknare är en speciell typ av sekvensnät som registrerar antalet inkommande klockpulser. Registreringen sker efter någon kod, oftast binärkod. Efter ett visst antal pulser tar räknarens tillstånd slut och den börjar om från början igen. Man talar om räknarens modul ( dvs. hur många tillstånd räknecykeln innehåller ). Räknaren behöver inte ha någon insignal utom klockpulserna ( som kan ses som insignalen ). Ett sådant sekvensnät kallas för autonomt. Det går naturligtvis bra att konstruera alla tänkbara räknare som Moore-automater, men litteraturen är full av exempel på "fiffiga" räknare uppbyggda bara av vippor ( och ibland någon grind ). Dessa lösningar är antingen speciellt komponentsnåla eller optimala ur någon annan aspekt, och därför värda att känna till. William Sandqvist william@kth.se
William Sandqvist william@kth.se Binärkoden Om man studerar en tabell över binärkoden så upptäcker man lätt vissa regelbundenheter. Till exempel så ser man att det i första kolumnen är varannan "1" och varannan "0". I kolumnen därefter upprepas mönstret, men nu med två rader "1" innan det kommer två rader med "0" osv. Detta utnyttjas hos de asynkrona räknarna. William Sandqvist william@kth.se
William Sandqvist william@kth.se Asynkron räknare Figuren ovan visar en binärräknare med tre vippor, räknecykeln har åtta tillstånd så det är en Modulo-8 räknare. Räknaren är uppbygd av T-vippor, de har alla T=1 och "togglar" därför vid varje klockpuls. Den första vippan Q0 "togglar" för varje klockpuls. Vippan därefter Q1 klockas av den första vippan. Den kommer därför bara att "toggla" för varannan klockpuls. Den tredje vippan Q2 kommer "toggla" för varannan varannan klockpuls. N st vippor ger modulen 2N. Klockfrekvensen delas ned så att den sista vippan QN slår om med frekvensen f = CP/2N [Hz]. Ditt armbandsur har en oscillator med en klock-kristall med resonansfrekvensen 32,768 kHz. I klockan finns en räknare med 15 vippor. Dessa delar ned klockfrekvensen till 1 Hz. Enligt binärtabellen kommer räknaren därför att räkna i binärkod. ( Q2Q1Q0: 000 001 010 011 100 101 110 111 000 ... ). William Sandqvist william@kth.se
Asynkronräknarens svaghet Asynkronräknaren har den enklast tänkbara uppbyggnaden. Eftersom klockpulserna tar vägen genom vipporna så kan dessa inte slå om exakt samtidigt. Om man läser av den binära koden på vippornas utgångar för att invänta ett visst räknevärde kan man bli "lurad". Vipporna slår om en efter en och man säger att klockpulsen "ripplar" genom vipporna ( asynkronräknare kallas därför ibland för rippelräknare. Ripple = vågskvalp ). Medan detta pågår kan det kortvarigt förekomma felaktiga räknevärden ( så kallade "räknespikar" ). Detta problem har man löst med de synkrona räknarna. William Sandqvist william@kth.se
William Sandqvist william@kth.se Synkronräknaren Klockpulserna går direkt till alla vippor och därför slår de om samtidigt. Vilka vippor som ska slå om eller ej styrs med T-ingångarna. Den första vippan har T=1 och den slår om för varje klockpuls. Ur binärtabellen kan man se att en viss vippa ska slå om när alla vippor som är före den står på "1". Det vilkoret får man från AND-grindarna i den sk. Carrykedjan och det är dessa som styr T-ingångarna. Vill man utöka räknaren sker det med en vippa och en AND-grind per steg. Om räknaren är lång och består av många steg, måste informationen om att den första vippan står på "1" färdas genom många AND-grindar. Denna signal som kallas för RC, RippleCarry, begränsar räknaren högsta användbara frekvens. ( RCO står för RippleCarryOutput ). För att öka räknarens snabbhet kan man införa en "Carrylookahead"-grind. Genom att avläsa många vippors utgångar på en gång med en ensam AND-grind får man snabbare reda på ifall alla tidigare vippor står på "1". William Sandqvist william@kth.se
William Sandqvist william@kth.se Countdown Hur gör man en räknare för nedräkning? Vad vore en raketuppskjutning eller en tidsstyrd bomb utan nedräkning ( Countdown )? Antag att man använder vippornas inversutgångar i stället för de vanliga utgångarna. En modulo-8 räknare räknar då: 111 110 101 100 011 010 001 000 111 ... det vill säga nedräkning! En reversibel räknare har en styringång för att välja upp/ner-räkning. Ett grindnät ( multiplexor-kretsar ) växlar då mellan vippornas utgångar och inversutgångar. Olika räkne-Moduler En räknare för vår vanliga tideräkning dvs år, månader, dagar, timmar, minuter och sekunder behöver vara sammansatt av en mängd olika typer modulo-räknare. ( Modulo- 365/366, 31/30/29/28, 2, 12, 60, 60, 10 ... ). Trots många försök från Franska revolutionens dagar och framåt att förändra tideräkningen till ett decimalt system är vår "krångliga" tideräkning här för att stanna, och därmed behovet av alla räknarkretsar. William Sandqvist william@kth.se
William Sandqvist william@kth.se Ringräknaren Om ett skiftregisters serieutgång ansluts till dess serieingång säger man att skiftregistret "roterar" ett tal. En ringräknare är ett sådant återkopplat skiftregister. Man ser från början till att bara en av vipporna innehåller "1" ( vanligen den första ), och därefter skiftas denna 1:a runt mellan vipporna. Räknekoden är inte binärkod, utan den brukar kallas för "one hot". Vill man tex räkna modulo-4 har man fyra vippor och kan direkt, utan logikkretsar, se på vippornas utgångar hur långt räknaren hunnit. Det är viktigt att det bara är en av vipporna som är "1" från början. I annat fall kan räknaren "fastna" i andra räknecykler. Om vipporna har direktverkande asynkrona SR-ingångar kan man låta en Reset-puls initiera vipporna innan man startar räknaren. Det är också möjligt att utföra vipporna så att de startar med "0", och att en av dem startar med "1", vid spänningstillslaget. William Sandqvist william@kth.se
William Sandqvist william@kth.se Möbiusräknaren Ett skiftregisters där man återför serie-utgångens inverterade värde till serie-ingången kallas för en sk. Möbius-räknare. Räknekoden brukar kallas för "creeping Code". För varje räknesteg tillkommer en 1:a tills registret är fullt, då försvinner i stället en 1:a för varje steg. I likhet med Graykoden förändras bara en position åt gången. Räknemodulen blir 2 ggr antalet vippor, vilket är mer "ekonomiskt" än vad gäller ringräknaren. Även för denna räknare är det viktigt att den startar i ett tillstånd som ingår i räknecykeln, annars fastnar den i en annan räknrecykel. Eftersom "0000" ingår i cykeln brukar man "resetta" alla vippor innan räknaren startas, alternativt tillverkar man vippor som startar med "0" vid spänningstillslag. Möbiusbandet William Sandqvist william@kth.se
William Sandqvist william@kth.se Johnssonavkodningen Möbius-räknaren är även känd som Johnsonräknare efter Robert Johnson vid University of Utah som utvecklade ett "fiffigt" avkodarschema för "creeping code". Med bara 2-ingångars AND-grindar kan alla räknepositioner avkodas. Johnsonräknaren kan byggas som ett repeterbart mönster på IC-kretsens yta ( en vippa och två AND-grindar ), vilket gör den totalt sett ekonomisk trots den stora åtgången på vippor. Johnson counter William Sandqvist william@kth.se
William Sandqvist william@kth.se Pseudoslumptal Exempel på ett återkopplat skiftregister med 16 vippor. I figuren sker "avtapp-ning" från vippa 0,2, 3, och 5. Skiftregistrets ingång matas med EXOR-funktionen av dessa bitar. Just denna "avtappning" ger en maximalt lång talsekvens som upprepas efter 65535 ggr. Om alla vipporna I skiftregistret är “0” så stannar slumptalssekvensen, så den kombinationen måste undvikas! William Sandqvist william@kth.se
William Sandqvist william@kth.se PIC-program Många algoritmer för slumptal utnyttjar multiplikation och division, något som inte är midrange PIC-processorernas starkaste sida. Nedanstående algoritm bygger i stället på tekniken med "återkopplade shiftregister", som ger hyfsade slumptal utan allt för mycket kod ... /* Random number function */ char rand( void ) { /* 0x0000 won't run ... */ bit EXOR_out; static char rand_hi, rand_lo; if( !rand_hi && !rand_lo ) rand_lo = 0x01; EXOR_out ^= rand_lo.0; EXOR_out ^= rand_lo.2; EXOR_out ^= rand_lo.3; EXOR_out ^= rand_lo.5; Carry = EXOR_out; /* rotate right */ rand_hi = rr( rand_hi); rand_lo = rr( rand_lo); return rand_lo; } Linear feedback shift registers William Sandqvist william@kth.se