Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> VHDL

VHDL Dual 7-segment Display Controller voor Pmod SSD – Eenvoudige FPGA-integratie

In dit artikel presenteer ik een VHDL-module die een tweecijferig getal kan weergeven op de Pmod SSD: Seven-segment Display van Digilent. De dual 7-segment display is compatibel met de Pmod-interface, wat betekent dat u het zonder solderen kunt gebruiken. Het past in de Pmod-connector, die standaard is op veel FPGA-ontwikkelborden.

Om de VHDL-implementatie te testen, gebruik ik de Lattice iCEstick, een goedkoop FPGA-ontwikkelbord met een Pmod-connector. Naast de iCEstick hebt u een 2×6-pin naar Dual 6-pin Pmod Splitter Kabel nodig om van de parallelle Pmod-connector op de iCEstick te converteren naar de in-serie versie van de stekker die de 7-segment display verwacht. Ten slotte raad ik aan een USB type-A verlengkabel te kopen omdat het direct in de USB-poort op de computer steken van de iCEstick onpraktisch is.

Hoe 7-segment displays werken

Er zijn veel verschillende 7-segment displays op de markt. Het aantal cijfers varieert ertussen, en zo doet de fysieke interface en pinout. Een generieke oplossing die alle mogelijke 7-segment displays die u kunt tegenkomen dekt, zou waarschijnlijk niet erg gebruiksvriendelijk zijn. U kunt echter de code die in dit artikel gepresenteerd wordt als basis gebruiken en aanpassen aan uw behoeften.

De afbeelding hierboven is uit de datasheet voor de Digilent Pmod-module. Het toont hoe de 7-segment display verbindt met de Pmod-pins. Deze pins zijn direct toegankelijk voor de FPGA op de iCEstick.

Zeven van de pinnen besturen elk een segment op het display. Door een logische hoge waarde op zo'n pin te zetten, zal het corresponderende segment op het display oplichten. Maar er zijn twee cijfers op dit display, en we kunnen er maar één tegelijk besturen. De P4/C pin op de J2-connector selecteert het ene of het andere cijfer. Wanneer de logische spanning op deze pin '0' is, verlicht het rechter cijfer, als het '1' is, wordt het linkercijfer geactiveerd.

De "DP" decimaal punt is niet aangesloten en kan niet benaderd worden.

De entity

De onderstaande code toont de entity van onze seg7 VHDL-module. De entity heeft een generieke poort met een constante genaamd clk_cnt_bits. Het definieert de lengte van een interne teller die de ververstempo van het display regelt, de frequentie van wisselen tussen het linker- en rechtercijfer.

De exacte frequentie is niet essentieel. Selecteer een tellerlengte die in het bereik ligt van 50 tot een paar honderd Hertz. De formule die het ververstempo bepaalt is refresh_hz = 2^clk_cnt_bits / clk_hz.

 entity seg7 is generic ( -- refresh_hz = (2 ** clk_cnt_bits) / clk_hz clk_cnt_bits : integer ); port ( clk : in std_logic; rst : in std_logic; value : in integer range 0 to 99; segments : out std_logic_vector(6 downto 0); digit_sel : out std_logic ); end seg7; 

Naast de klok en reset, heeft de entity één invoersignaal: de waarde die op de 7-segment display getoond moet worden. Het value signaal is een integer-type beperkt tot het bereik 0 tot 99 omdat dit de enige getallen zijn die mogelijk zijn om te tonen met slechts twee cijfers.

De uitvoersignalen zijn de zeven segmenten als vector en het cijferselectiesignaal voor het kiezen van het linker- of rechtercijfer om te verlichten.

Een binair gecodeerd decimaal voorstellen

Om de cijfers die op het display getoond worden voor te stellen, zullen we het formaat gebruiken dat bekend is als binair gecodeerd decimaal (BCD). Terwijl een binaire representatie de meest efficiënte manier is om het decimale getal op te slaan, lopen we in problemen wanneer we proberen het op te splitsen in het linker- en rechtercijfer om op het display te tonen. We kunnen niet onderscheiden tussen de decimale cijfers door simpelweg de vector die het getal opslaat te snijden.

 subtype digit_type is integer range 0 to 9; type digits_type is array (1 downto 0) of digit_type; signal digit : digit_type; signal digits : digits_type; 

Zoals in de bovenstaande code getoond, declareren we een subtype van de integer op het bereik 0 tot 9 voor het beschrijven van de waarde die door één decimaal cijfer vertegenwoordigd kan worden. Dan declareren we een nieuw array-type dat twee dergelijke BCD-waarden kan bevatten. Het digit signaal houdt het getal dat momenteel getoond wordt op de linker- of rechterkant van het display. Aan de andere kant bevat het digits signaal de individuele decimale karakters voor de twee cijfers, zoals ze zullen verschijnen voor een persoon die het scherm bekijkt.

Decimaal omzetten naar BCD

De invoer voor deze module, value, is een integer op het bereik 0 tot 99, een binaire representatie van het getal. We moeten deze enkele integer omzetten in twee integers op het bereik 0 tot 9, de BCD's.

Het standaardalgoritme hiervoor is Double Dabble, ook bekend als het shift-and-add-3 algoritme. Hoewel dit prima te gebruiken is, kies ik voor een kortere oplossing in ons geval omdat we slechts twee cijfers hoeven te scheiden.

 digits(1) <= value / 10; digits(0) <= value - ((value / 10) * 10); 

Door gehele deling te gebruiken zoals in de bovenstaande code getoond, kunnen we het meest significante decimale cijfer isoleren en toewijzen aan het digits(1) signaal. Om het minst significante cijfer op te halen, kunnen we het meest significante cijfer aftrekken van het value signaal, wat ons overlaat met alleen het getal om toe te wijzen aan het digits(0) signaal.

Klokcycli tellen

Tijd vertragen in FPGA's is gewoon een kwestie van klokcycli tellen. De klokperiode is het enigste voorspelbare tijdsinterval waarop u in uw VHDL-code kunt vertrouwen. De onderstaande code toont het clk_cnt signaal, dat we gebruiken voor het tellen van klokcycli. De clk_cnt_bits generiek bepaalt hoeveel bits te reserveren voor dit unsigned signaal.

 signal clk_cnt : unsigned(clk_cnt_bits - 1 downto 0); 

Het exacte ververstempo van het display is van minder belang, daarom heb ik gekozen voor een unsigned-type hier. Het stelt ons in staat het zelf-wrappende gedrag van het unsigned-signaal te benutten. Alles wat we hoeven te doen is de teller te incrementeren op elke stijgende flank van de klok. De onderstaande code toont het synchrone proces met reset dat dit verzorgt.

 COUNT_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then clk_cnt <= (others => '0'); else clk_cnt <= clk_cnt + 1; end if; end if; end process; 

Wisselen tussen cijfers

Nu we de vrij-draaiende teller werkend hebben, kunnen we de meest significante bit (MSB) van het unsigned-tellersignaal gebruiken om te schakelen tussen de twee cijfers. De MSB wisselt tussen '0' en '1' met een 50% duty cycle. De eerste regel van de onderstaande code stelt het digit_sel signaal in op basis van de waarde van de MSB. De tweede regel implementeert een multiplexer met de MSB als selector. Het doorstuurt de waarde van het actieve cijfer uit de digits array naar het digit signaal.

 digit_sel <= clk_cnt(clk_cnt'high); digit <= digits(0) when clk_cnt(clk_cnt'high) = '0' else digits(1); 

BCD naar 7-segment encoder


De laatste stap van de seg7-module is het vertalen van de BCD opgeslagen in het digit signaal naar een visuele representatie op de 7-segment display. De onderstaande code toont een proces dat dit bereikt door een case-statement te gebruiken.

De positie in de vector van elk bit-litteraal correspondeert met één segment op het display. Index 0 is gelijk aan segment A, index 1 is B, en zo verder, tot index 6, die segment G bestuurt. De mapping van segmenten naar vector-indexen is afgeleid van de datasheet voor de Digilent 7-segment display.

 ENCODER_PROC : process(digit) begin case digit is when 0 => segments <= "0111111"; when 1 => segments <= "0000110"; when 2 => segments <= "1011011"; when 3 => segments <= "1001111"; when 4 => segments <= "1100110"; when 5 => segments <= "1101101"; when 6 => segments <= "1111101"; when 7 => segments <= "0000111"; when 8 => segments <= "1111111"; when 9 => segments <= "1101111"; end case; end process; 

De output

De seg7 VHDL-module zal op het display weergeven wat u ook toewijst aan het value invoersignAal. In de testbench verhogen we het value signaal een keer per seconde. Dan simuleren we iets meer dan 100 seconden zodat we het wrappunt van de value teller kunnen observeren.

De golfvorm hierboven is van ModelSim. Het toont het eerste deel van de simulatie, waar de waarde geteld heeft van 0 tot 15. We kunnen zien dat de getallen in de digits array ook tellen. De eenen (0) tellen elke keer dat het value signaal verandert, terwijl de tientallen (1) optellen op elk tiende getal.

U kunt het ModelSim-project, inclusief de testbench, downloaden met het onderstaande formulier.

Als u de seg7-module implementeert als top-module op de FPGA, zal het display waarschijnlijk een stabiel "00" tonen. Dat is omdat '0' de meest voorkomende standaardwaarde is die aan ongeïnitialiseerde signalen in FPGA's wordt gegeven. Wanneer het value signaal op alle nullen gezet wordt, toont het display gewoon dat.

Om door alle mogelijke invoergetallen te cyclen, creëerde ik een wrapper VHDL-module die het value signaal tien keer per seconde verhoogt. Ik instantiateerde de seg7-module in de wrapper voordat ik het ontwerp op de Lattice iCEstick implementeerde. De lusende Gif-video hieronder toont hoe het geïmplementeerde ontwerp eruitziet op de 7-segment display.

De Pmod SSD kopen: Seven-segment Display

De 7-segment display die in deze blogpost gebruikt wordt komt van Digilent. U kunt de Pmod-module kopen via de Digilent-webshop, of u kunt het bij een van de vele herverkopers krijgen. In de onderstaande lijst heb ik gelinkt naar de productpagina voor de display in een paar online elektronicawinkels die het item voorradig hebben.

  • Digilent
  • Digi-Key
  • Mouser
  • RS Electronics (UK)
    (Ga naar de RS Electronics-hoofdpagina om de site voor uw land te selecteren)
  • Farnell (UK)
    (Ga naar de Farnell-hoofdpagina om de site voor uw land te selecteren)

Let op dat als u de Digilent 7-segment display wilt gebruiken met de Lattice iCEstick, of een ander FPGA-ontwikkelbord met een 6×2-pin Pmod-connector, u ook een splitter-kabel nodig hebt. De kabel is beschikbaar bij Digilent, Digi-key, Mouser, en RS Electronics.

Daarnaast zijn alle componenten beschikbaar bij diverse verkopers op Amazon en eBay.

VHDL-cursus met de Digilent 7-segment display

Ik heb een nieuwe VHDL- en FPGA-cursus voor absolute beginners gelanceerd. In de cursus gebruik ik de 7-segment display van Digilent en het Lattice iCEstick FPGA-ontwikkelbord om VHDL te leren. Klik op de onderstaande link om meer over de cursus te lezen!

FPGA en VHDL Fast-Track:

Hands-On voor Absolute Beginners

Bent u bekend met programmeren maar nieuw voor VHDL?

Heeft u een korte inleiding nodig op dit onbekende onderwerp?

Is uw schema vol zonder tijd over om te studeren?

Begrijp de basis van FPGA-ontwikkeling met VHDL in een paar avonden! Deze cursus is voor IT-professionals en studenten die een snelle doorloop van het onderwerp nodig hebben. Met deze cursus en het goedkope Lattice iCEstick-ontwikkelbord, zult u binnen uren echte hardware ontwikkelen.

Klik hier om meer te lezen en in te schrijven:
FPGA en VHDL Fast-Track: Hands-On voor Absolute Beginners


VHDL

  1. VHDL Records Gebruiken voor Schone, Herbruikbare FIFO-interfaces
  2. Een 'breathing LED' effect maken met een sinusgolf uit Block RAM
  3. Beginner's guide: Modelsim gebruiken voor FPGA en ASIC-simulatie
  4. De Case-When-statement in VHDL onder de knie krijgen: efficiënte multiplexer-ontwerpen
  5. Impure functies in VHDL gebruiken: FSM-leesbaarheid en onderhoudbaarheid verbeteren
  6. Uitgebreide Gids voor VHDL Type Conversies met Numeric_Std en Std_Logic_Arith
  7. Willekeurige getallen genereren in VHDL: Van Uniform naar OSVVM
  8. Een AXI FIFO implementeren in Block RAM met Ready/Valid Handshake
  9. Ontwerpen van een robuuste VHDL-ringbuffer FIFO in blok-RAM
  10. Je eerste VHDL-programma: Stap-voor-stap Hello World tutorial
  11. VUnit 101: Een praktische gids voor geautomatiseerde VHDL-verificatie