Historia standardu ASCII sięga jeszcze lat 60. Powstał on w celu usprawnienia komunikacji przez dalekopisy, czyli zdalnie sterowane maszyny do pisania. Wszystkim małym i wielkim literom alfabetu łacińskiego, cyfrom, znakom interpunkcyjnym, nawiasom itp. przyporządkowano liczby od 0 do 127. Liczby te dało się zapisywać na magistrali 7-bitowej. Niedługo później dodano ósmy bit, ponieważ większość komputerów w latach 80. była 8-bitowa.
Stworzyło to możliwość wyświetlania 256 różnych znaków, a każdy z nich zajmował dokładnie 1 bajt pamięci. Powstało wiele różnych tablic znaków ASCII – jedną z nich widzimy na rysunku 1. Różnią się one znakami diakrytycznymi, charakterystycznymi dla różnych języków, a także znakami matematycznymi czy różnego rodzaju kreskami, z których można budować tabele. Warto dodać, że pierwsze 32 znaki często miały specjalne znaczenie i służyły do kontroli transmisji, przejścia do kolejnej linii, tabulacji itp.
Moduł Decoder14seg
Moduł jest bardzo prosty, a jego kod pokazano na listingu 1. Na wejściu Data_i (linia 2) dostarczamy 8-bitowy kod ASCII znaku, który chcemy wyświetlić. Na wyjściu Segments_o (linia 3) w następnym takcie zegarowym pojawia się 14-bitowa bitmapa, którą można przekazać bezpośrednio do sterownika wyświetlacza. Moduł pracuje, kiedy wejście Enable_i znajduje się w stanie wysokim, natomiast kiedy jest ono w stanie niskim, wówczas wyjście Segments_o pozostaje bez zmian, niezależnie od tego, co się dzieje na wejściu danych oraz Clock (wejście Reset ma zawsze priorytet).
W module Decoder14seg blok always jest sekwencyjny. Z tego powodu wynik na wyjściu pojawia się dopiero po wystąpieniu rosnącego zbocza sygnału zegarowego. Dlaczego tak dziwnie? Rozwiązanie ze sterownika wyświetlacza 7-segmentowego wydaje się prostsze i bardziej intuicyjne. Rzeczywiście tak jest, ale w tym przypadku stosujemy bardzo sprytną sztuczkę optymalizacyjną – tak skonstruowana instrukcja case zostanie bowiem w całości zaimplementowana w bloku pamięci EBR.
Ponadto funkcjonalność wejścia Enable_i również zostanie zaimplementowana w EBR bez korzystania z uniwersalnych zasobów logicznych.
Jak to możliwe? Otóż instrukcja case, przypisująca wartość jednej zmiennej tylko na podstawie innej pojedynczej zmiennej, w gruncie rzeczy odpowiada... pamięci ROM. W takiej pamięci stan wyjścia danych ustalany jest tylko na podstawie stanu wejścia adresowego. 8-bitowe wejście Data_i stanowi w rzeczywistości wejście adresowe pamięci ROM, w której zapisanych zostało 256 stałych o długości 14 bitów. W ten sposób można zaoszczędzić mnóstwo uniwersalnych zasobów logicznych, zastępując je tylko jednym blokiem pamięci EBR. Trzeba spełnić tu tylko jeden warunek: blok always musi być sekwencyjny, bo pamięć EBR ma charakter synchroniczny i musi działać z sygnałem zegarowym (co zostało dokładniej omówione w 15. odcinku kursu).