Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial Internet of Things >> Ingebed

Beschrijving van gecombineerde circuits in Verilog

06 januari 2019 door Dr. Steve Arar

Dit artikel introduceert de technieken voor het beschrijven van combinatorische circuits in Verilog door te onderzoeken hoe de voorwaardelijke operator kan worden gebruikt om combinatorische waarheidstabellen te beschrijven.

Dit artikel introduceert de technieken voor het beschrijven van combinatorische circuits in Verilog door te onderzoeken hoe de voorwaardelijke operator kan worden gebruikt om combinatorische waarheidstabellen te beschrijven. Het laat ook zien hoe u het Verilog-blok "always" kunt gebruiken voor het beschrijven van combinatorische circuits - een "always" -blok kan ons een nog eenvoudigere oplossing bieden om een ​​digitaal circuit te beschrijven.

In een vorig artikel bespraken we het gebruik van het Verilog-sleutelwoord 'toewijzen' om een ​​doorlopende opdracht uit te voeren. Dergelijke toewijzingen zijn altijd actief en kunnen worden gebruikt om een ​​beschrijving op poortniveau van digitale schakelingen te verkrijgen. In de volgende code, die een AND-poort beschrijft, wordt bijvoorbeeld de rechterkant continu geëvalueerd en wordt het resultaat op het out1-net gezet:

toewijzen uit1 =a &b;  

Verilog heeft een voorwaardelijke operator (?:) waarmee we een voorwaarde kunnen controleren voordat we dergelijke toewijzingen maken. De syntaxis wordt hieronder gegeven:

assign [signal_name] =[conditional_expression] ? [value_if_true] :[value_if_false]; 

De "conditional_expression" wordt geëvalueerd. Als het waar is, wordt "value_if_true" toegewezen aan "signal_name". Als het niet waar is, krijgt "signal_name" "value_if_false". Beschouw als voorbeeld de volgende code:

toewijzen out1 =(sel) ? (a &b) :(a|b); 

Als "sel" waar is, wordt a&b toegewezen aan "out1". Als het niet waar is, krijgt "out1" a|b. Daarom implementeert de bovenstaande code de functionaliteit van een 2-naar-1 multiplexer. De conceptuele implementatie van deze code kan zijn zoals weergegeven in figuur 1 hieronder.

De voorwaardelijke toewijzing stelt ons in staat om een ​​meer abstracte beschrijving van bepaalde circuits te hebben, omdat het de functionaliteit heeft van een "if" -instructie die te vinden is in traditionele computerprogrammeertalen. De voorwaardelijke operator kan in een geneste vorm worden gebruikt om complexere circuits te implementeren. Voorbeeld 1 bespreekt deze details.

Voorbeeld 1:Geneste voorwaardelijke operators

Gebruik de voorwaardelijke operator (?:) om een ​​4-naar-2 prioriteits-encoder te beschrijven met de volgende waarheidstabel:

De Verilog-code voor deze prioriteits-encoder wordt hieronder gegeven:

 module Prio_4_to_2 ( ingangsdraad [3:0] x, uitgangsdraad [1:0] y, uitgangsdraad v); toewijzen y =x[3] ? 2'b11 :x[2] ? 2'b10 :x[1] ? 2'b01:2'b00; toewijzen v =( x[3] | x[2] | x[1] | x[0] ) ? 1'b1 :1'b0; eindmodule 

Afgezien van de regels 7 tot en met 10, bevat de code de basistaalelementen die in ons vorige artikel zijn besproken. Laten we deze regels eens bekijken.

De termen 2'b11, 2'b10, 2'b01 verwijzen naar de Verilog-notaties die twee-bits binaire getallen vertegenwoordigen. Over het algemeen geeft het eerste getal (vóór 'b) het aantal bits aan. De letter b geeft aan dat de getallen binair zijn. De cijfers na 'b geven de waarde van het getal. Daarom is 2'b01 de Verilog-notatie om een ​​twee-bits binair getal met waarde 01 weer te geven en 3'b100 staat voor een drie-bits binair getal met waarde 100.

Regel 7 controleert de MSB van de invoer, x[3], in een voorwaardelijke operator. Als x[3]=1, wordt de voorwaarde geëvalueerd als waar en wordt 2’b11 toegewezen aan y (de toegekende waarde wordt uit de waarheidstabel gehaald). Als x[3]=0, wordt de voorwaarde geëvalueerd als onwaar en wordt de uitdrukking na de dubbele punt (:) toegewezen aan y. De uitdrukking na de dubbele punt is de code in regel 8, die zelf een andere voorwaardelijke operator is.

De tweede voorwaardelijke operator in regel 8 onderzoekt het op één na meest significante bit van de invoer, x[2], om te bepalen of 2'b10 moet worden toegewezen aan y of aan de uitdrukking na de dubbele punt, wat weer een andere voorwaardelijke operator is (regel 9). geëvalueerd worden. U kunt controleren of de waarden die zijn toegewezen aan y overeenkomen met de gegeven waarheidstabel.

De geldige uitgang (v) van de waarheidstabel zal logisch hoog zijn als ten minste één bit van de ingang logisch hoog is. Regel 11 toont deze beschrijving door de bitsgewijze OR-operator (|) toe te passen op de bits van de invoer. Een Xilinx ISE-simulatie van de bovenstaande code wordt getoond in figuur 2.

Figuur 2. Een Xilinx ISE-simulatie uit de bovenstaande code.

Het is belangrijk op te merken dat de voorwaardelijke expressies achtereenvolgens worden geëvalueerd totdat een echte expressie is gevonden. De toewijzing die overeenkomt met deze ware uitdrukking zal worden uitgevoerd. Als gevolg hiervan hebben de eerder geëvalueerde uitdrukkingen een hogere prioriteit in vergelijking met de volgende. Dit betekent dat, in theorie, een conditionele operator meer geschikt is voor het implementeren van een prioriteitsnetwerk (Figuur 3) in plaats van een uitgebalanceerde structuur zoals een multiplexer (Figuur 4).

Figuur 3. Een prioriteitsnetwerk.

Figuur 4. Een n-to-1 multiplexer waarbij er geen prioriteit is tussen de ingangen.

Een vorig artikel onthult een soortgelijke discussie over gelijktijdige VHDL-opdrachten.

Verilog Procedurele Verklaringen

We kunnen elk combinatiecircuit uit elkaar halen in een paar logische basispoorten (AND, OR, NOT, enz.) en de "assign" -instructie gebruiken om deze poorten te beschrijven (een beschrijving op poortniveau). We kunnen ook de voorwaardelijke operator gebruiken die in de vorige sectie is besproken om een ​​meer abstracte manier te hebben om enkele combinatorische circuits te beschrijven (vergelijkbaar met de "if"-verklaring van computerprogrammeertalen). Er is echter nog een krachtigere oplossing:het Verilog-blok "altijd" gebruiken.

Binnen een "altijd" -blok kunnen we procedurele verklaringen hebben die in volgorde worden uitgevoerd. Bovendien ondersteunt het blok “always” abstracte taalconstructies zoals “if” en “case” statements.

De sequentiële uitvoeringsfunctie, samen met de abstracte taalconstructies die beschikbaar zijn in een "altijd" -blok, stellen ons in staat om de functionaliteit van een circuit gemakkelijker te beschrijven, vanwege het feit dat menselijk redeneren een sequentieel karakter heeft en afhankelijk is van abstracte beschrijvingen. We denken meestal op een algoritmische manier op hoog niveau in plaats van in termen van logische poorten op laag niveau. Een "altijd" -blok kan ons een eenvoudigere oplossing bieden om een ​​digitaal circuit te beschrijven. Voor meer details over waarom HDL's beschrijvingen ondersteunen op basis van sequentiële instructies, zie mijn artikel Inleiding tot sequentiële VHDL-statements.

Voorbeeld 2:"Altijd" blokverklaringen

De vereenvoudigde syntaxis van een "altijd" blok wordt hieronder gegeven:

altijd @(gevoeligheid_lijst) begin sequentiële_statements; einde 

De gevoeligheid_lijst geeft aan wanneer de opeenvolgende instructies in het blok "altijd" moeten worden uitgevoerd. Overweeg bijvoorbeeld het blok "altijd" te gebruiken om het circuit in figuur 5 te beschrijven.

Figuur 5. Circuit_1

Als a of b verandert, kan de uitvoer veranderen, wat betekent dat zowel a als b in de gevoeligheidslijst van het blok "altijd" moeten staan. In het algemeen moeten voor een combinatorisch circuit alle ingangssignalen worden opgenomen in de gevoeligheidslijst.

Nu kunnen we de bitsgewijze AND-operator gebruiken om de functionaliteit van het circuit (a&b) te beschrijven en het resultaat aan de uitvoer toe te wijzen. Binnen een “altijd” blok zijn er twee verschillende soorten opdrachten:de blokkerende opdracht (=) en de niet-blokkerende opdracht (<=). Met behulp van de blokkeringsopdracht krijgen we de volgende code:

altijd @(a, b)begin out1 =a &b;end 

Wat is het verschil tussen een blokkerende opdracht en een niet-blokkerende opdracht?

Bij een blokkeringstoewijzing wordt de rechterkant geëvalueerd en onmiddellijk toegewezen aan out1. Dus wanneer regel 3 wordt uitgevoerd, wordt out1 onmiddellijk bijgewerkt voordat we naar de volgende regel van de code gaan. De naam "blokkeringstoewijzing" benadrukt dat de komende regels worden geblokkeerd totdat de linkerkant wordt bijgewerkt.

Bij een niet-blokkerende toewijzing wordt de rechteruitdrukking geëvalueerd, maar deze wordt pas toegepast op de linkervariabele als we het einde van het blok "altijd" bereiken. De keuze voor een blokkerende of niet-blokkerende opdracht kan verwarrend zijn voor een beginner en oneigenlijk gebruik ervan kan leiden tot ongewenste functionaliteit. Het gebruik van blokkeringstoewijzingen om flip-flops af te leiden kan bijvoorbeeld een raceconditie introduceren.

Voor dit inleidende artikel gaan we niet verder in op details en houden we ons aan één simpele richtlijn om mogelijke valkuilen te vermijden:gebruik de blokkeringstoewijzingen bij het schrijven van de code voor een combinatorisch circuit. Daarom wordt het blok "altijd" in lijst 1 gebruikt om een ​​EN-poort te beschrijven.

In een vorig artikel maakten we kennis met het Verilog-gegevenstype "wire". Dit datatype vertegenwoordigt een fysieke draad in ons FPGA-ontwerp. Binnen een "altijd" -blok kunnen we volgens de Verilog-standaard geen waarde toewijzen aan een "draad". In plaats daarvan gebruiken we het gegevenstype "reg". De naam "reg" is enigszins verwarrend, maar houd er rekening mee dat een "reg" al dan niet kan leiden tot een fysiek opslagelement in uw ontwerp. De volgende code is de Verilog-beschrijving van Afbeelding 5 met een "altijd" -blok. Merk op dat het uitvoergegevenstype "reg" moet zijn omdat het zijn waarde krijgt van een procedurele toewijzing.

 module Circuit_1 ( ingangsdraad a, ingangsdraad b, uitgangsreg out1 ); altijd @ (a, b) begin out1 =a &b; einde eindmodule 

In dit artikel maakten we kennis met de voorwaardelijke operator van Verilog. We hebben de geneste vorm van deze operator gebruikt om een ​​prioriteits-encoder te beschrijven. Vervolgens hebben we een krachtigere taalconstructie aangeroerd, het "altijd" -blok, om combinatorische circuits te beschrijven. In toekomstige artikelen zullen we het gebruik van het blok "altijd" onderzoeken om sequentiële circuits te implementeren.


Ingebed

  1. Inleiding tot Verilog
  2. Inleiding tot DC-circuits
  3. Inleiding tot AC-circuits
  4. Meerdere combinatiecircuits gebruiken
  5. Gelijkrichterschakelingen
  6. Besturingscircuits
  7. C#-operators
  8. C# ternair (? :) Operator
  9. Verilog-zelfstudie
  10. Verilog-aaneenschakeling
  11. Verilog `ifdef voorwaardelijke compilatie'