Tärning med ABEL-macro I den här laborationen ska du konstruera en tärning med en räknare, som stegas fram då en tryckknapp trycks ned och som visar tärningsmönstret då knappen släpps. Så här ser kopplingsschemat ut för den modul, MOD687-2, som du ska använda: Modulen ser ut så här: 1
Tryckknappen ska grinda en 4MHz klocka till en räknare. När tryckknappen är nedtryckt ska räknaren räkna, när knappen släpps ska räknaren stoppa i det tillstånd den var. Räknaren ska räkna från noll till och med fem (alltså sex tillstånd) och sedan börja om från början igen. Räknarens utgångar ska avkodas så att lysdioderna visar det klassiska tärningsmönstret: När räknarutgången är noll ska tärningen visa en "etta", när den är ett ska tärningen visa "två" o s v. Det är alltså tre problem som ska lösas och det är som vanligt en god ide att lösa vart och ett av problemen för sig innan det hela slutligen kombineras. 1. Vi måste konstruera en räknare som kan grindas och som räknar från 0 till och med 5 och sedan börjar om från början igen. 2. Alla mekaniska tryckknappar uppvisar kontaktstudsar när de trycks ned och släpps. Det tar så där 5-10 millisekunder för kontakten att stabilisera sig och under tiden alstras hundratals slutningar och brytningar. Vi måste hitta ett sätt att eliminera studsarna. 3. De sju lysdioderna måste drivas från räknaren så att det korrekta tärningsmönstret tänds för vart och ett av de sex räknartillstånden. Låt oss börja från början med räknaren! Räknaren En räknare som ska räkna till fem måste ha 3 bitar. En tvåbitars räknare har bara 4 tillstånd, d v s den kan räkna från noll till och med tre. En trebitars räknare har 8 tillstånd, d v s den kan räkna från noll till och med sju. I vårt fall måste räknesekvensen kortas ned, så att räknaren går tillbaka till noll i stället för att fortsätta till sex. Detta åstadkommer man enkelt med återkoppling, d v s en visst tillstånd hos räknaren avkodas och nollställer räknaren. Det finns två olika typer av nollställning på räknarna i Xilinx bibliotek, asynkron och synkron nollställning. I räknarnamnet står C för Clear, vilket innebär asynkron nollställning. R står för Reset, vilket innebär synkron nollställning. I båda fallen har räknarna en aktivt hög ingång för nollställningen, d v s en etta in på nollställningsingången nollställer räknaren. Vad är det då för skillnad? Jo, vid asynkron nollställning sker nollställningen omedelbart när nollställnings-ingången sätts hög. Vid synkron nollställning däremot sker nollställningen först när räknaren klockas nästa gång! När det går ska du alltid använda räknare med synkron nollställning. Ett synkront system blir alltid tillförlitligare och enklare att felsöka än ett asynkront. Låt oss anta att du vill avkoda räknaren så att den räknar till fem och sedan börjar om från början igen. Om du använder en räknare med asynkron nollställning måste du avkoda tillstånder sex. Omedelbart när tillståndet sex inträffar går nollställningsingången hög och räknaren nollställs. I och med detta är ju inte tillståndet sex längre, utan noll, och nollställningssignalen försvinner. Den utgörs alltså av en mycket kort "blipp", precis lagom lång för att räknaren ska nollställas. 2
Längden kommer att bestämmas av fördröjningarna i avkodaren och räknaren och inte av klockan. En annan nackdel med den asynkrona avkodningen är att räknaren under ett kort ögonblick kommer att inta tillståndet sex, ett tillstånd som ju egentligen inte alls ska vara med i sekvensen, vi vill ju att räknaren ska räkna mellan 0 och fem. Med synkron nollställning blir det mycket lugnare. Vill du att räknaren ska räkna till fem ska du avkoda tillståndet fem. Så fort räknaren har intagit tillståndet fem blir alltså nollställningsingången hög, men inget händer förrän nästa gång räknaren klockas, då först sker nollställningen. Räknaren intar följaktligen aldrig något "falskt" tillstånd utan går direkt tillbaka till noll. Tärningsräknaren ska ha ytterligare en egenskap, det måste vara möjligt att grinda dess klocka. Detta innebär att den ska ha en ingång CE, clock enable. I princip är detta en inbyggd AND-grind, där klockan utgör ena ingången och CE den andra. Endast när CE är hög släpps klockpulserna fram. Du ska alltså leta fram en trebits binärräknare med synkron reset och clock enable. Med Xilinx nomenklatur blir detta CB3RE. CB står för counter, binary, alltså binärräknare, 3 står för antalet bitar, R står för synkron reset och E står för clock enable. När du så småningom ritar schemat och letar i komponentlistan visar det sig att det inte finns någon CB3RE. Däremot finns CB4RE och det går precis lika bra, du får lämna en utgång oansluten och använda de tre som behövs. Det kan verka som slöseri med de begränsade resurser som finns, men så är inte fallet. När konstruktionen implementeras är programvaran smart nog att eliminera delar av komponenter som inte används! Starta nu Projektmanagern, välj New Project och kalla det tarning (undvik å, ä och ö, det är ett amerikanskt program!). Klicka på OK. Starta schemaeditorn genom att klicka på AND-grinden i Design Entry-ikonen. 3
Klicka på komponentikonen i "verktygslådan" vid vänsterkanten, hämta räknaren CB4RE och placera den på schemat. Hämta sedan en AND-grind med tre ingångar, varav en ingång är inverterande, AND3B1, och placera den till höger om räknaren. Beteckningen AND står givetvis för AND-grind, 3 står för tre ingångar och B1 betyder att en av dessa tre ingångar är inverterande. Nu vet du allt som behövs för att tyda beteckningarna för alla de olika kombinatoriska kretsarna i schemaeditorns komponentlista! Koppla ihop AND-grinden och räknaren så att tillståndet 5, d v s binärt 101, avkodas och nollställer räknaren synkront. Så här ser det ut: Spara med File-Save och generera nätlista med Options-Create Netlist. Följande fönster visas: Det står att du ska titta på varningar som visas i det lägre fönstret i projektmanagern. Varningarna, som markeras med blå text, talar om att vissa av räknarens in- och utgångar är oanslutna. Det är precis som vi vill ha det, så klicka på OK. Klicka sedan på Options-Export Netlist, se till att filnamnet är tarning och att filtypen är Edif 200 [*.EDN] och klicka på Open. Genom att nu köra en simulering kan du förvissa dig om att räknaren fungerar som den ska. Det som ska kollas är att räkaren verkligen räknar när den klockas och CE = "ett" och att den stoppar när CE = "0". Du ska givetvis förvissa dig om att räknaren räknar från noll till och med fem och sedan börjar om från noll igen. 4
Starta simulatorn genom att gå till projektmanagern och klicka på Simulationikonen: Ett blankt simulatorfönster visas. Du ska nu se till att de nödvändiga signalerna visas. Klicka därför på Signal-Add Signals. Detta fönster visas: Eftersom du inte satt ut några signalnamn är vänstra kolumnen nästan tom, den innehåller bara signalen SimGlobalReset, som ger simulatorn möjlighet att göra reset av hela din konstruktion och den ska vi inte använda just nu. Istället ska du gå till andra kolumnen och dubbelklicka på räknaren CB4RE. Den kommer då att expanderas i högra kolumnen så att du kan se alla dess anslutningar: 5
Välj nu de intressanta signalerna genom att dubbelklicka på dem: Stäng fönstret genom att klicka på Close. Simulatorns "Waveform Viewer" viar nu ett tomt tidsdiagram med de valda signalerna i vänsterkanten. Tillordna nu stimuli till C och CE genom att klicka på Signal-Add Stimulators. Fönstret "Stimulator Selection" visas. Tillordna signalen CE stimulit tangenten e genom att klicka på CE så att den blåmarkeras och sedan klicka på. Tillordna sedan signalen C stimulit B0 genom att klicka på C så att den blåmarkeras och sedan klicka på den gula "lysdioden" längst till höger i raden Bc: Se också till att alla simulatorns inställningar är så som visas här: 6
Klicka på Options-Preferences och ändra klockfrekvensen till 4MHz: Klicka på OK. Tryck en gång på tangenten e på tangentbordet (litet e) så att signalen CE = 0. Klicka sedan femton gånger på steg-ikonen, vilket motsvarar 750 ns. Räknaren är nollställd och räknar inte: Tryck en gång till på tangenten e, så att CE = 1. Klicka sedan 25 gånger på stegikonen, vilket motsvarar 1250 ns. Räknaren räknar: 7
Du kan se att räknaren stegas fram till ett på den första positivt gående klockpulsen efter att CE=1. Varje ny positivt gående klockpuls stegar fram räknaren ytterligare ett steg. Observera att när räknaren räknat till fem, efter cirka 1.85 µs, blir R=1, eftersom AND-grinden avkodar tillståndet fem. Räknaren ska inte nollställas förrän vid nästa klockpuls, eftersom räknaren har synkron reset. Tryck en sista gång på tangenten e, så att CE = 0. Klicka åtta gånger på stegikonen. Så här ser det ut: Men idén var ju att räknaren skulle stoppa när e sattes lika med noll. Vad som verkligen hände var istället att den nollställdes av nästa klockpuls, för att sedan stoppa. Vi vill ju att den ska stå kvar i det tillståndet som gällde då CE sattes lika med noll utan att nollställas. Lösningen är enkel. Gå till schemaeditorn och lägg till en AND-grind på resetingången, styrd av samma signal som CE. För att det ska gå enkelt att simulera måste du sätta ut signalnamnet på CE, eftersom den går till två kretsar, både räknaren och AND-grinden. Klicka på nät-ikonen och skriv namnet CE i fönstret som visas. Klicka på OK och placera namnet CE så här: 8
Spara med File-Save och generera nätlistan med Options-Create Netlist och Options-Export Netlist. För att du ska vara säker på att detta äntligen fungerar är det säkrast att simulera igen. Gå till projektmanagern och starta simulatorn igen genom att klicka på Simulation-ikonen. En del signaler försvann förmodligen när du ändrade i schemat. Se till att du väljer samma signaler som tidigare beskrevs på sidan 6 men välj CE ur kolumnen till vänster när signalfönstret visas. Så här ska det se ut innan du kör simuleringen: Gör nu om processen från sidan 7, d v s tryck en gång på tangenten e på tangentbordet (litet e) så att signalen CE = 0. Klicka sedan femton gånger på stegikonen, vilket motsvarar 750 ns. Räknaren är nollställd och räknar inte, så än så länge ser allt bra ut: Tryck en gång till på tangenten e, så att CE = 1. Klicka sedan 25 gånger på stegikonen, vilket motsvarar 1250 ns. Räknaren räknar och allt ser bra ut, R=1 men räknaren nollställs inte ännu: 9
Nu kommer slutprovet... Kommer det att fungera? Tryck en sista gång på tangenten e, så att CE = 0. Klicka åtta gånger på steg-ikonen. Så här ser det ut: Alldeles utsökt, räknaren står kvar i tillståndet fem efter att CE=1. Problemet har fixats! Det var tur vi upptäckte det här beteendet hos räknaren, annars skulle vi ha gjort en tärning som bara kunde visa ett, två, tre, fyra och fem och det hade nog inte gått hem så bra i spelsalongerna i Las Vegas! Du har alltså visat att räknaren bär sig åt precis som den ska! Det är nu dags att titta närmare på tryckknappen. Avstudsning av tryckknapp Tryckknappen SW1 är av växlande typ med två pull-up-motstånd i resistansnätet R1. Om ingen trycker på knappen är CPLD pin nummer P70 jordad och P68 ligger på +5V. När knappen är nedtryckt ligger P70 på +5V och P68 är jordad. När knappen är på väg mellan de två lägena har studsarna upphört och både P70 och P68 ligger temporärt på +5V, ända tills knappen växlar tillstånd, studsar, och stannar i det nya läget. Vad som behövs för att avstudsa en sådan anordning är helt enkelt en SR-vippa (ibland kallad SR-latch) bestående av två korskopplade NAND-grindar. I laborationen Räknare med sjusegmentdisplay kan du lära dig exakt hur avstudsningen går till, här nöjer vi oss med att konstatera att en SR-vippa, kopplad till räknarens ingång CE, är precis vad som behövs för att styra räknaren så att den räknar endast när knappen är nedtryckt. Du ska nu rita en SR-vippa som styrs av tryckknappen via två IPAD och två IBUF till vänster om räknaren i det existerande schemat. Schemat innehåller för övrigt ett antal röda och gröna små fyrkanter. Dessa är rester av simuleringen. Du kan ta bort dem genom att först klicka på indikator-ikonen och sedan i tur och ordning klicka på de små fyrkanterna. Du ska också koppla in klockan till räknaren. Klockan utgörs av en 4MHz kristalloscillator och finns inbyggd på labkortet CPLD95. Den är kopplad till pinne 9 på CPLDn. Alla insignaler behöver en IPAD, även klockan. Det behövs alltid en 10
speciell buffer för att driva en eller flera klockingångar. Den kallas BUFG, Global Clock Buffer, i komponentlistan. Glöm inte att sätta ut pinnumren på de tre IPADsymbolerna! Sätt också ut signalnamnen NC på P70 (för Normally Closed, d v s Normalt kontakt), NO på P68 (för Normally Open, d v s Normalt öppen) och CLK på P9 (för klocka). Så här ska resultatet se ut: Det enda som återstår nu är att styra lysdioderna. Avkodare för lysdioderna I det här avsnittet ska vi slå två flugor i en smäll! Du ska göra en avkodare som transformerar räknarens tillstånd till kombinationer av tända och släckta lysdioder, men du ska göra avkodaren som ett macro med hjälp av ett högnivåspråk, ABEL. I laborationen Räknare med sjusegmentdisplay fick du lära dig att göra ett macro medelst schemaritning, men här ska vi som sagt utnyttja ABEL, som är ett enkelt men kraftfullt språk. Det går ganska lätt att beskriva de flesta digitala konstruktioner med ABEL, men det är speciellt enkelt om lösningen föreligger i tabellform som du snart ska se. Genom att göra ett macro för avkodaren får du som resultat en egen komponent i komponentlistan, som kan återanvändas i andra konstruktioner, varje gång du behöver en tärningsavkodare. OK, det kanske inte är så ofta, men nu får du i alla fall lära dig hur man gör! Vi börjar med att sammanställa tärningsavkodarens beteende som en tabell över sambandet mellan räknarens sex tillstånd och de lysdioder som ska vara tända vid respektive tillstånd. Observera att en lysdiod tänds då den motsvarande utgången är "noll", se kopplingsschemat på sidan 1. 11
Så här ser tabellen ut: Antal "ögon" Binärt D1 D2 D3 D4 D5 D6 D7 1 000 1 1 1 0 1 1 1 2 001 1 1 0 1 0 1 1 3 010 1 1 0 0 0 1 1 4 011 0 1 0 1 0 1 0 5 100 0 1 0 0 0 1 0 6 101 0 0 0 1 0 0 0 Det ABEL-program som ska skrivas gör du med hjälp av ABEL-editorn. För att starta ABEL-editorn går du till Projektmanagern och klickar till vänster på ikonen Design Entry, på texten HDL. Följande fönster visas: Se till att "Use HDL Design Wizard" är markerat och klicka på OK. 12
Klicka på Next. Detta fönster visas: Se till att ABEL är förprickat och klicka på Next. Detta visas: Skriv in filnamnet tarn_led och tryck på Next (ge inte denna fil samma namn som projektet, kalla den alltså inte tarning, programmet klarar inte det!). 13
Nu är du inne i Design Wizard. Du ska nu sätta ut portar, d v s in- och ut-gångar på schemasymbolen som visas till vänster. Det behövs tre ingångar att så småningom koppla till räknaren (Q0, Q1 och Q2) och sju utgångar (D1, D2, D3, D4, D5, D6, D7) att koppla till lysdioderna. Så här gör du: Klicka på New, se till att Input är markerad och skriv Q0 på raden Name. Klicka på New igen, skriv Q1. Klicka på New, skriv Q2 och klicka på New. Nu finns alla ingångar på plats. Så här ser det ut: Den namnlösa extra ingången längst nere till vänster på symbolen ska vi nu raskt göra till utgång! Markera Output och skriv D1 som namn. D1 hamnar nu på symbolens högra sida, ingångar hamnar alltid till vänster och utgångar till höger. När det gäller utgångar måste du specificera vilken typ av utgång det gäller, det finns nämligen två olika typer, kombinatorisk (Combinatorial) och register (Registered). Om kretsen du konstruerar har en klocka, som t ex räknare och skiftregister, måste du se till att välja typen register. I vårt fall finns ingen klocka, en viss kombination på ingångarna ska "omedelbart" ge en viss annan kombination på utgångarna. Dina utgångar är alltså kombinatoriska. Detta väljer du genom att klicka på Advanced och markera Combinatorial. Klicka på OK. I fortsättningen blir nu alla utgångar du sätter dit kombinatoriska. 14
Sätt dit ut resterande utgångar med New, D2, New, D3 o s v tills du kommit till New, D7. Klicka sedan på Finish. Följande fönster, HDL Editorn, visas: Som du ser har Design Wizard, med din medverkan, börjat skriva programmet! I alla programmeringsspråk används speciella termer. I ABEL kallas sådana termer och uttryck reserverade termer och du får förstås inte använda sådana för dina egna signalnamn eller variabler. HDL-editorn markerar automatiskt reserverade termer med röd färg. T ex PIN och end är reserverade. Du kan använda stora eller små bokstäver. Dina egna signalnamn och andra variabler markeras automatiskt med svart färg. Kommentarer i programmet ska börjar med ett citationstecken och markeras automatiskt med grön färg. Ett ABEL-program har alltid den allmänna struktur som visas ovan. Första raden innehåller programnamnet, föregått av termen module. Detta måste vara det namn du gett filen! Nästa rad måste ha termen Title, följd av ett namn inom enkla anföringstecken. Detta namn kan vara vad som helst, t ex (som här) programnamnet eller en kort förklarande beskriving som Title 'avkodare for tarning'. Strö inte grus i maskineriet genom att använda å, ä och ö! Sista raden i programmet ska alltid vara end, följt av programnamnet. 15
Mellan Title och end finns själva programmet, som alltid består av två delar. Först kommer deklarationsdelen, som startar med termen Declarations. Här deklareras bl a in- och utgångar. Den andra delen av programmet är ekvationsdelen, som startar med termen Equations. Här skriver du de ekvationer och uttryck som beskriver hur din design ska uppföra sig. Genom att använda "Design Wizard" blir deklarationsdelen automatiskt ifylld, men även utan Wizard är det hela mycket enkelt. Varje insignal deklareras som signalnamn följt av termen PIN och ett semikolon, alltså t ex Q0 PIN; Utsignalerna deklareras som signalnamn följt av termen PIN istype följt av typen inom enkla anföringstecken och avslutat med semikolon. Typen skrivs 'com' för kombinatorisk utgång och 'reg' för registerutgång. I din konstruktion används ju enbart kombinatoriska utgångar, alltså t ex D1 PIN istype 'com'; Låt oss nu gå till ekvationsdelen, som ännu är helt tom. Ekvationsdelen blir mycket enkel om du kan beskriva din design med en sanningstabell. Exakt så här lägger du till sanningstabellen: Spara genom att klicka på File-Save. Klicka sedan på Project-Create Macro. 16
Detta fönster visas: Efter en kort stund, kanske en halv minut eller så, visas denna text längst ner i editorfönstret: Detta betyder att programmet "syntetiserat" din design, d v s konverterat den till en nätlista och en schemasymbol. Starta nu schemaeditorn igen och klicka på "AND-grinden" för att gå in i komponentplaceringsmod. Listan över symboler har nu utökats med din egen symbol för tärningsavkodaren, den står allra först i listan och heter förstås TARN_LED: 17
Klicka på TARN_LED och placera den i schemat, till höger om räknaren, och koppla in Q0, Q1 och Q2: Koppla utgångarna D1, D2, D3, D4, D5, D6 och D7 via sju OBUF till sju OPAD och sätt ut pinnumren på OPAD-symbolerna enligt schemat på sidan 1. Så här blir det: Generera nätlista genom att klicka på Options-Create Netlist och Options-Export Netlist. Gå till Projektmanagern och klicka på Implementation-ikonen: 18
Efter någon minut är implementeringen klar och detta fönster visas: Kvittera genom att klicka på OK. Det är nu dags att generera SVF-filen, som används för nedladdning till din krets. Klicka på Programming-ikonen: Klicka på Output-Create SVF file. Fönstret SVF Options visas. Klicka på OK. Fönstret Create a new SVF file visas. Eftersom du ska placera filen i roten i foldern tärning klickar du tre gånger på foldersymbolen och klickar därefter på Save. För att slutligen generera filen klickar du på Operations-Program, varvid detta fönster visas. Se till att det står en bock vid Erase Before Programming och klicka på OK. 19
Efter ett par sekunder är filen klar och ett fönster visas, som talar om att allt gick bra: Kvittera genom att klicka på OK. Nu är filen klar och du kan ladda ned den i kretsen. Starta utforskaren, leta rätt på din SVF-fil som ligger under C\Fndtn\Active\Projects\tarning. Se till att nedladdningskabeln och matningsspänningen är anslutna till kortet och dubbelklicka på filen tarning.svf. När nedladdningen är klar kan du nu äntligen testa din tärning! 4 februari 2001 Anders Andersson 20