CMD + K
Digital design
Bygg større digitale system med teller, dekoder, multiplekser og tilstandsmaskin (FSM). Hysterese, pulsgenerator og don't-care-forenkling.
- 01Designe en N-bits teller og regne ut hvor mange bit som trengs for K tilstander
- 02Forklare hvordan dekoder og multiplekser brukes til å rute kontrollsignaler og data
- 03Tegne et tilstandsdiagram for en FSM og oversette det til vippe- og portlogikk
- 04Bruke hysterese og don't-care-forenkling i konkrete digital design-oppgaver
Fra vippe til system
Til nå har vi sett enkeltvipper og kombinatoriske porter. Nå skal vi bygge ekte digitale systemer av dem: tellere som husker hvor langt de har kommet, dekodere som velger riktig blokk, multipleksere som ruter signaler, og tilstandsmaskiner som styrer alt sammen i takt med klokken.
Felles for alle byggeklossene er at de bruker sekvensiell logikk. Utgangen avhenger ikke bare av inngangene nå, men også av hva som har skjedd før — kretsen har minne i form av vipper. Det er forskjellen fra et rent OR-gate, som glemmer alt straks inngangene endrer seg.
Klokken er taktslagene som beveger systemet framover. På hver positive flanke oppdaterer vippene tilstand sin samtidig. Mellom flankene står alt stille — det er kombinatorisk logikk som regner ut hva neste tilstand skal bli, og resultatet blir låst inn ved neste flanke.
Tellere og modulo
En teller (counter) er den enkleste sekvensielle byggeklossen. Den øker tilstanden med 1 for hver klokkeflanke. ƒteller — sekvens av tilstander viser regnestykket: dagens verdi pluss én, modulo antall tilstander.
Med N vipper får du ƒn bit representerer 2^n verdier forskjellige verdier — en 4-bits teller går 0, 1, 2, ..., 15, 0, 1, ... og ruller over.
Trenger du å skille K verdier, regner du baklengs: ⌈log₂(K)⌉ vipper. Skal du representere fart fra 0 til 100 km/t må du ha 7 bit (128 nivåer); 6 bit holder bare til 64.
Vil du ha en mod-K-teller der K ikke er en potens av 2, må du legge til logikk som detekterer «nådd K-1» og bruker reset-signal for å nullstille. En teller som skal telle til 90: detekter at Q = 89 og sett reset høy ved neste flanke. Da hopper telleren tilbake til 0 i stedet for å fortsette mot 127.
Tellere er kjernen i alt som krever tid eller rekkefølge. En 4-minutters-klokke som teller hvert kvartmiutt, en sekvenser som blinker LED-er i tur, en pulsgenerator som markerer hver time — alle bygger på samme prinsipp.
Dekoder og multiplekser — to motsatte byggeklosser
Når en teller har gitt deg et binært tall, må du ofte oversette det til «aktiver utgang nummer Q». Det er jobben til en dekoder. ƒdekoder (binær → one-hot) sier at akkurat én utgang er høy om gangen — den hvis indeks matcher det binære tallet på inngangen.
En 3-til-8-dekoder har tre inngangslinjer og åtte utganger. Sett inngangene til binær 5 (101), og bare Y₅ blir høy. Resultatet er one-hot-koding av tallet: én bit per mulig verdi. Det høres sløsete ut, men forenkler nedstrøms logikk — utgangen Y_k kan kobles direkte til «blokk k er aktiv» uten ekstra oversetting.
En multiplekser (mux) gjør motsatt jobb: N datainnganger, ett velgesignal som er ⌈log₂(N)⌉ bit bredt, og én utgang. Velgesignalet bestemmer hvilken inngang som kobles gjennom.
ƒ2-til-1 multiplekser viser den enkleste varianten — to datainnganger D₀ og D₁, ett velgebit s. Når s = 0 går D₀ til utgangen, når s = 1 går D₁. Det er hardware-versjonen av if (s) Y = D1 else Y = D0.
Større multipleksere settes sammen av mindre. En 4-til-1 er tre 2-til-1-muxer i et tre, eller en direkte implementasjon med to velgebit. En 8-til-1 trenger tre velgebit, og så videre.
Et typisk samspill: en teller + dekoder driver en sekvens av handlinger (Q = 0 → Y₀ aktiv → handling A; Q = 1 → Y₁ aktiv → handling B). En multiplekser med samme velgesignal kan plukke hvilken sensor som leses inn. Sammen får du en liten sekvensiell kontroller med få komponenter.
Tilstandsmaskin og tilstandsdiagram
Tellere er en spesialform av en mer generell idé: tilstandsmaskin (fsm). ƒtilstandsmaskin (fsm) oppsummerer: neste tilstand er en kombinatorisk funksjon av nåværende tilstand og inngangene. Funksjonen f er typisk en sannhetstabell du designer for hånd.
En FSM med K tilstander krever ⌈log₂(K)⌉ vipper for binær koding, eller K vipper for one-hot. Binær gir færre vipper, one-hot gir enklere kombinatorisk logikk. To tilstander trenger akkurat én vippe — det er det enkleste tilfellet og dukker opp ofte (på/av, ledig/opptatt).
Designprosessen er den samme hver gang. Først tegner du et tilstandsdiagram: sirkler er tilstander, piler er overganger, og hver pil er merket med betingelsen som utløser den. Inni sirkelen står utgangsverdiene. Så lager du en tabell over (nåværende tilstand, inngang) → (neste tilstand, utgang), forenkler boolske uttrykk, og kobler vippene.
Tenk en enkel garasjeport. Tilstand LUKKET: motor av. Knapp trykt → ÅPNER: motor opp. Topp nådd → ÅPEN. Ny knapp → LUKKER. Bunn nådd → tilbake til LUKKET. Fire tilstander, fire overganger, ferdig design — så går du tilbake og koder det opp i hardware.
To smaker av FSM: en Moore-maskin har utgang som bare avhenger av tilstanden, mens en Mealy lar utgangen også avhenge av inngangene. Moore er enklere å resonnere om og brukes når det går; Mealy gir raskere respons men kan ha glitcher når inngangen endrer seg mellom klokkeflanker.
Pulsgenerator — to byggeklosser møtes
En pulsgenerator viser hvor enkelt det blir når du kombinerer en teller med en sammenligningsblokk. ƒpulsgenerator (teller + dekoder) er hele logikken: utgangen er høy nøyaktig når telleren har nådd K-1, ellers lav.
Praktisk eksempel: en klokkekrets gir én puls hvert fjerde minutt. Du vil ha én puls hver sjette time = 360 minutter = 90 stykker av 4 minutter. Bygg en mod-90-teller drevet av 4-minutters-pulsen. Sammenlign telleren med 89 og slå ut én puls på utgangen. Reset teller. Ferdig.
Den samme strukturen gir deg klokkedeling, baudrate-generatorer og blinkende LED-er — alt som krever «en gang per K klokkeflanker». Med en 32 768 Hz oscillator og en 15-bits teller får du 1 Hz på utgangen, som er nøyaktig hvordan armbåndsur og RTC-er virker.
Hysterese — to terskler i stedet for én
En analog inngang som svever rundt en terskel skaper rot: kretsen slår av og på flere ganger per sekund mens signalet jittrer. Løsningen er hysterese. ƒhysterese — to terskler viser ideen: utgangen avhenger ikke bare av inngangen nå, men også av forrige tilstand.
Konkret: en hastighetsvarsler skal slå på en lampe når bilen kjører over 64 km/t, og slå av først når den faller under 62. To terskler, ikke én. Mellom 62 og 64 holdes utgangen uendret — derav minnet, derav vippen.
Implementasjonen er en liten FSM med to tilstander (lampe på/av) og to inngangs-betingelser (over 64, under 62). I AV-tilstand går du til PÅ kun ved over 64. I PÅ-tilstand går du til AV kun ved under 62. Mellomområdet er et ikke-overgang-bånd: ingen pil i diagrammet matcher det, så tilstanden holdes.
Schmitt-trigger er den analoge varianten av samme idé: en komparator med innebygd hysterese mellom terskelverdiene. Brukes mye på klokke-innganger og reset-knapper for å forhindre at støy på signalet utløser flere flanker enn det burde.
Don't-care — gratis forenkling
don't-care er inngangskombinasjoner som enten aldri kan oppstå, eller hvor utgangen ikke spiller noen rolle. Begge tilfellene gir frihet i logikkdesignet.
Et BCD-eksempel: med 4 bit kan du representere 0–15, men BCD bruker bare 0–9. Verdiene 10–15 oppstår aldri. Du er fri til å bestemme hva utgangen skal være på disse. Ved å sette dem til den verdien som gjør K-map-grupperingen størst, får du enklest mulig logikk.
Samme prinsipp i tilstandsmaskiner med one-hot-koding på K tilstander og K vipper: 2^K − K kombinasjoner kan aldri lovlig oppstå. Marker dem som don't-care i sannhetstabellen og forenkle deretter. Det er ofte forskjellen på et stygt og et elegant design — gratis logikk-reduksjon hvis du bare merker dem som det de er.
I praksis lønner det seg å skrive don't-care som X (eller -) i sannhetstabellen helt fra starten av designet. Velger du en konkret verdi tidlig (typisk 0), så binder du logikken til en oppførsel for tilstander systemet aldri kommer i — det gir mer komplisert krets og verre debugging hvis noe likevel skulle drive inn i et ulovlig hjørne.