CMD + K
Minne og register
Bistabile systemer, minnecelle, RAM, lås og D-vippe, klokkesignal, register og synkron logikk. FPGA og oppslagstabeller (LUT).
- 01Forklare hvorfor to inverterte tilbakekoblede invertere gir et bistabilt system med to stabile tilstander
- 02Skille en transparent lås fra en flank-trigget D-vippe og forklare hvorfor master-slave-koblingen gjør flankene rene
- 03Beskrive synkron logikk som kombinatorisk logikk mellom register, og hvilken konstraint som setter maks klokkefrekvens
- 04Forklare hvordan en LUT i en FPGA realiserer en vilkårlig kombinatorisk funksjon ved å lagre sannhetstabellen i RAM
Logikk uten hukommelse er ikke nok
Kombinatorisk logikk har én svakhet: så snart inngangene endrer seg, glemmer den hva utgangen var. Den regner ut en funksjon av nåtiden, ingenting mer. Men en CPU må huske hva som sto i registeret for ett klokkeskritt siden, en teller må huske den forrige verdien, en tilstandsmaskin må huske hvilken tilstand den er i.
Vi trenger en byggekloss som husker en bit — som holder tilstand til vi velger å endre den. Det er minne, og det er grunnlaget for telleverk, registre, RAM og hele CPU-er. Dette kapittelet bygger opp minne lag for lag: bistabil node → minnecelle → lås → D-vippe → register → synkron logikk → FPGA.
Bistabilt system — tilbakekobling som låser
Sett to invertere i serie, og koble utgangen til den andre tilbake til inngangen til den første. Hvis noden Q starter på 1, gir inverter 1 ut 0, som inverter 2 gjør om til 1 igjen — Q forsterker seg selv. Hvis Q starter på 0, holder den 0.
To stabile punkter, ingen vei mellom dem uten ekstern påvirkning. Det er definisjonen på et bistabilt system: en krets med to stabile tilstander som holder seg i den den ble satt i.
Hva skjer hvis to invertere prøver å drive samme node Q med ulik verdi samtidig? Da settes spenningen av motstandsforholdet i utgangstrinnene, gitt av ƒspenningsdeling i bistabilt system. Den med lavest utgangsmotstand vinner. Dette er prinsippet bak å skrive til en minnecelle — vi drar Q til ønsket verdi med en sterkere driver enn de invertere som prøver å holde den fast.
En minnecelle er altså en bistabil krets, typisk to invertere i et kryss-koblet par, med to tilgang-transistorer på utsiden. Tilgang-transistorene styres av en word-line og kobler cellen til bit-linjene når raden er valgt. Med tilgangen lukket holder cellen seg selv; åpen kan vi lese eller skrive.
RAM som matrise av celler
ram er Random Access Memory: en matrise av slike minneceller arrangert i rader og kolonner, med en adressedekoder som velger ut én rad om gangen. 1 KB RAM er 8192 celler, hver med tilbakekoblet par av invertere og to tilgang-transistorer. Den moderne SRAM-cellen bruker seks transistorer per bit — derav navnet 6T-celle.
Når du leser fra en adresse, kobler adressedekoderen ut akkurat den raden, og innholdet i cellene drives ut på bit-linjene. Når du skriver, drar driverne fra utsiden bit-linjene til den ønskede verdien, og overstyrer cellens egen tilbakekobling — akkurat samme prinsipp som spenningsdelingen over.
Det viktige er at RAM er flyktig. Når strømmen forsvinner, mister cellene tilbakekoblingen, og innholdet er tapt. Det er forskjellen fra flash og harddisk: SRAM og DRAM må refreshe seg selv kontinuerlig, men er til gjengjeld raske å lese og skrive.
Lås — transparent eller låst
En lås (latch) er en minnecelle utstyrt med en kontroll-inngang som bestemmer om dataene slippes gjennom eller ikke. Når CLK = 0 er låsen transparent — utgangen følger inngangen, omtrent som en kort kabel. Når CLK = 1 låser den, og holder den verdien som lå på inngangen i overgangsøyeblikket.
Problemet med en ren lås er at den ikke er entydig flank-trigget. Hvis CLK står lenge på 0 og inngangen endrer seg, slipper alle endringene gjennom én etter én. Det betyr at en lås kan brukes som data-buffer, men ikke som hjørnesteinen i en synkron krets, fordi vi får ingen ren takt i systemet — for mye sniker seg gjennom mens klokken er lav.
D-vippe — fanger ved flanken
For å fikse dette setter vi to låser i kaskade, styrt av invertert klokke: master-låsen er åpen når CLK = 0, slave er låst. Når CLK = 1 låser master det den hadde rett før flanken, og slave slipper det videre. Resultatet er at utgangen endrer seg kun ved den stigende flanken på CLK, og er stabil hele resten av perioden.
Dette er en d-vippe — Data flip-flop. Den fanger D-inngangen ved hver stigende flanke og holder den uendret til neste flanke. D-vippa er hjørnesteinen i alt synkront design og det enkleste 1-bit minneelementet vi praktisk bygger.
For at D-vippa skal være pålitelig må D-inngangen være stabil i et lite tidsvindu rundt klokkeflanken: en setup-tid før, og en hold-tid etter. Brytes dette går vippa i metastabilitet — verken klar 0 eller klar 1, og kan ende opp på et tilfeldig nivå i mikrosekunder.
Klokken som metronom
klokkesignal er det periodiske signalet som setter takten. En firkant-bølge som veksler mellom 0 og 1 med en fast periode T. Frekvensen er den enkle ƒklokkefrekvens — 100 MHz tilsvarer en periode på 10 ns, 1 GHz tilsvarer 1 ns, 4 GHz på en moderne CPU tilsvarer 0,25 ns mellom hver flanke.
Hele kretsen er enig om at endringer skjer ved klokkeflanken og ingen andre steder. Mellom flankene har den kombinatoriske logikken tid til å "regne ferdig" og slå seg til ro i en stabil tilstand før neste flanke fanger resultatet. Klokken er det som synkroniserer alt: alle vippene flytter sin bit på samme tidspunkt, og hele systemet beveger seg framover som en blokk.
Register — N D-vipper med felles klokke
Et register er bare N D-vipper styrt av samme klokke. Et 32-bits register holder 32 biter, og oppdateres samlet ved hver stigende flanke. En CPU har titalls slike registre internt — én for hvert generelt formål, én for programtelleren, én for statusflagg, og ofte et helt register-fil med 32 eller flere.
Registre er det vi bruker når vi vil mellomlagre mellom kombinatoriske trinn. Mellom hvert sett av D-vipper kan vi ha så mye kombinatorisk logikk som vi vil, så lenge den rekker å produsere et stabilt resultat før neste klokkeflanke.
Synkron logikk — kombinatorisk imellom
Klassisk digital design er synkron logikk: kombinatorisk logikk plassert mellom register med felles klokke. Det betyr at hvert "trinn" av regningen tar nøyaktig én klokkeperiode. Hvis logikken er for treg må vi senke klokken, eller bryte trinnet opp i flere stadier (pipelining).
Konstrasten er asynkron logikk, der hver krets reagerer fritt på inngangene sine. Asynkron kan være raskere, men er et mareritt å verifisere fordi små forsinkelser mellom signaler gir race-conditions. Industrien har valgt synkront, fordi det gir et enkelt mentalt bilde: klokken tikker, alt skjer ved flanken, mellomtidene er ingens ansvar.
For at synkron logikk skal være korrekt må ƒklokkeperiode-konstraint være oppfylt: klokkeperioden må være lang nok til at signalet propagerer gjennom kombinatorisk logikk og setter seg før setup-tiden til neste vippe. Det er nettopp denne grensen som setter taket på klokkefrekvensen i en CPU — for mye logikk per trinn, og du må enten pipeline eller akseptere lavere klokke.
FPGA og oppslagstabeller
En tradisjonell digital krets bygges som en bestemt ASIC: gate-array, ledningstrasé, det hele. Med en fpga trenger vi det ikke — den er en omprogrammerbar matrise av små logiske celler, der hver celle er en lut koblet til en D-vippe.
En LUT er ganske enkelt en liten RAM. En 4-input LUT har 16 minneceller, én for hver mulig kombinasjon av de fire inngangene. Når inngangene endrer seg, leses ut den cellen som tilsvarer den nye kombinasjonen — og det er nettopp sannhetstabellen til den logiske funksjonen.
Det vakre er at vi kan endre sannhetstabellen ved å skrive om RAM-innholdet. Dermed blir samme fysiske krets en AND-gate, en XOR-gate eller en 4-til-1 multiplexer — bare ved å laste inn en ny konfigurasjon i LUT-cellene. Mellom LUT-ene sitter D-vipper og programmerbare ruter-elementer som kobler cellene sammen til større logiske blokker.
Hele kjeden av minneceller, D-vipper og kombinatorisk logikk fra dette kapittelet finner du igjen på et FPGA-chip, bare massivt parallellisert. Når du i lab brenner en konfigurasjon til FPGA-en, sender du i praksis sannhetstabellene til alle LUT-ene og koblingsmønsteret mellom dem.