Klasserna i elektronikteknik dikteras vanligtvis med populära verktyg, så jag spenderar alltid några timmar på att jobba med fri programvara. Av denna anledning har jag bestämt mig för att dela följande guide. |
Installera det nödvändiga
För att sammanställa och simulera våra program använder vi GHDL, en gratis kompilator baserad på GCC. För att se simuleringsresultaten använder vi GTKWAVE. Som redaktör rekommenderar jag Geany eftersom den känner igen nästan alla programmeringsspråk.
sudo apt-get installera ghdl gtkwave geany
Ett exempel på projekt
Låt oss använda den här komparatorn som ett exempel:
Innan du skapar ett projekt, låt oss börja med att skapa en mapp där alla filer kommer att vara värd. I det här fallet / home / user / vhdl. Där kommer vi att spara källkoden för våra program med ett .vhd-tillägg.
Sedan skriver vi vårt program med hjälp av Geany, vilket framgår av skärmdumpen.
Vi sparar det som jämför. Vhd.
Nu måste vi skapa signalerna för simuleringen. För att göra detta kommer vi att skapa en komponent som använder det tidigare blocket och vi kommer att specificera signalerna.
Linjerna A <= "0011" efter 0 ns, "0111" efter 5 ns, "0111" efter 10 ns; är de som konfigurerar insignalerna i tid
Vi sparar filerna i / home / user / vhdl. Sedan öppnar vi en terminal och sammanställer:
ghdl -a jämför.vhd
Om det inte finns några felmeddelanden lyckas kompileringen.
Nu sammanställer vi "komponenten"
ghdl -a jämför_tb.vhd
Om det inte finns några fel skapar vi den körbara:
ghdl -e jämför_tb
Slutligen återstår att utföra simuleringen och spara resultaten i den som heter "jämför.vcd"
ghdl -r jämför_tb --vcd = jämför.vcd
För att se resultaten kommer vi att använda gtkwave:
gtkwave jämför.vcd
När du är öppen, använd Ctrl-tangenten och musen för att peka på signalerna som intresserar oss och tryck på infoga. Dubbelklicka sedan på vektorerna för att se de separata signalerna. Högerklicka sedan på signalerna för att välja format (binär, hex, oktal, decimal, etc.)
Vid behov justerar förstoringsglasknappen med en fyrkant i mitten grafen till skärmen.
ALU: aritmetik och logikenhet
Okej, nu ska vi göra något mer intressant: en ALU (aritmetisk och logisk enhet). Det kommer att vara en logisk enhet, en aritmetisk enhet och en multiplexer.
Logisk enhet (LoU.vhdl)
BIBLIOTEK ieee; ANVÄND IEEE.STD_LOGIC_1164.all; ANVÄND IEEE.NUMERIC_STD.all;
ENHET lou ÄR
PORT (op1: IN std_logic_vector (7 DOWNTO 0);
op2: IN std_logic_vector (7 DOWNTO 0);
process: IN std_logic_vector (3 DOWNTO 0);
res: OUT std_logic_vector (7 DOWNTO 0));
SLUT lou;
ARKITEKTUR synth2 OF lou IS
SIGNAL a, b: UNSIGNED (op1'range);
SIGNAL c: UNSIGNED (res'range);
BÖRJA
PROCESS (a, b, process)
BÖRJA
CASE-processen ÄR
NÄR "0000" => c <= RESIZE ((inte a), c'längd);
NÄR "0001" => c <= STORLEK ((a och b), c'längd);
NÄR "0010" => c <= STORLEK ((a eller b), c'längd);
NÄR "0011" => c <= STORLEK ((a xor b), c'längd);
NÄR "0100" => c <= RESIZE ((a nand b), c'length);
NÄR "0101" => c <= STORLEK ((a eller b), c'längd);
NÄR ANDRA => null;
SLUTFALL;
AVSLUTA PROCESS;
a <= UNSIGNED (op1);
b <= UNSIGNED (op2);
res <= std_logic_vector (c);
SLUT synth2;
Aritmetisk enhet (ArU.vhd)
BIBLIOTEK ieee; ANVÄND IEEE.STD_LOGIC_1164.all; ANVÄND IEEE.NUMERIC_STD.all;
ENHET aru IS
PORT (op1: IN std_logic_vector (7 DOWNTO 0);
op2: IN std_logic_vector (7 DOWNTO 0);
process: IN std_logic_vector (3 DOWNTO 0);
res: OUT std_logic_vector (7 DOWNTO 0));
SLUT aru;
ARKITEKTUR synth av aru IS
SIGNAL a, b: UNSIGNED (op1'range);
SIGNAL c: UNSIGNED (res'range);
BÖRJA
PROCESS (a, b, process)
BÖRJA
CASE-processen ÄR
NÄR "0000" => c <= STORLEK ((a + b), c'längd);
NÄR "0001" => c <= STORLEK ((a - b), c'längd);
NÄR "0010" => c <= STORLEK ((a * b), c'längd);
NÄR "0011" => c <= STORLEK ((a / b), c'längd);
NÄR "0100" => c <= RESIZE ((a + "1"), c'längd);
NÄR "0101" => c <= STORLEK ((b + "1"), c'längd);
NÄR ANDRA => null;
SLUTFALL;
AVSLUTA PROCESS;
a <= UNSIGNED (op1);
b <= UNSIGNED (op2);
res <= std_logic_vector (c);
SLUT synth;
Multiplexer (muxVector.vhd)
BIBLIOTEK ieee; ANVÄND IEEE.STD_LOGIC_1164.all; ANVÄND IEEE.NUMERIC_STD.all;
ENTITY muxVector IS
PORT (från ARU: IN std_logic_vector (7 DOWNTO 0);
fromLOU: IN std_logic_vector (7 DOWNTO 0);
växla: IN std_logic;
utgång: ut std_logic_vector (7 DOWNTO 0));
END muxVector;
ARKITEKTUR förändring av muxVector IS
BÖRJA
med omkopplarval
output <= från ARU när '0', från LOU när andra;
END förändring;
ALU-komponent (aluComponent.vhd)
BIBLIOTEK ieee; ANVÄND IEEE.STD_LOGIC_1164.all; ANVÄND IEEE.NUMERIC_STD.all;
ENTITY alu Komponent IS
SLUT aluComponent;
ARKITEKTUR inputs_aluKomponent AV aluKomponent ÄR
KOMPONENT aru
PORT (op1: IN std_logic_vector (7 DOWNTO 0);
op2: IN std_logic_vector (7 DOWNTO 0);
process: IN std_logic_vector (3 DOWNTO 0);
res: OUT std_logic_vector (7 DOWNTO 0));
SLUTKOMPONENT;
KOMPONENT lou
PORT (op1: IN std_logic_vector (7 DOWNTO 0);
op2: IN std_logic_vector (7 DOWNTO 0);
process: IN std_logic_vector (3 DOWNTO 0);
res: OUT std_logic_vector (7 DOWNTO 0));
SLUTKOMPONENT;
KOMPONENT muxVector
PORT (från ARU: IN std_logic_vector (7 DOWNTO 0);
fromLOU: IN std_logic_vector (7 DOWNTO 0);
växla: IN std_logic;
utgång: ut std_logic_vector (7 DOWNTO 0));
SLUTKOMPONENT;
SIGNAL outputARU: std_logic_vector (7 DOWNTO 0);
SIGNAL outputLOU: std_logic_vector (7 DOWNTO 0);
signalomkopplare: std_logic;
signalprocess: std_logic_vector (3 DOWNTO 0);
signalutgång: std_logic_vector (7 DOWNTO 0);
SIGNAL A: std_logic_vector (7 NED 0);
SIGNAL B: std_logic_vector (7 DOWNTO 0);
BÖRJA
u0: aru PORT MAP (A, B, process, ARU exit);
u1: lou PORT MAP (A, B, process, LOU output);
u2: muxVector PORT MAP (utgång ARU, utgång LOU, switch, utgång);
A <= "00000011" efter 0 ns, "00000111" efter 5 ns, "00000111" efter 10 ns, "00001001" efter 15 ns, "00000000" efter 20 ns, "00000101" efter 25 ns, "00001111" efter 30 ns, "00000101" efter 35 ns;
B <= "00000010" efter 0 ns, "00000100" efter 5 ns, "00000010" efter 10 ns, "00000011" efter 15 ns, "00000100" efter 20 ns, "00000110" efter 25 ns, "00001111" efter 30 ns, "00000011" efter 35 ns;
växla <= '1' efter 0 ns, '0' efter 5 ns, '1' efter 10 ns, '0' efter 15 ns, '1' efter 20 ns, '0' efter 25 ns, '1' efter 30 ns, '0' efter 35 ns, '1' efter 40 ns;
process <= "0000" efter 0 ns, "0001" efter 5 ns, "0010" efter 10 ns, "0011" efter 15 ns, "0100" efter 20 ns, "0101" efter 25 ns, "0110" efter 30 ns;
END inputs_aluComponent;
För att inte slösa tid på att kompilera kommando för kommando medan du arbetar med programmet sparar vi en fil som heter compilar.sh med följande innehåll i samma mapp:
ghdl -a lou.vhd && ghdl -a aru.vhd && ghdl -a muxVector.vhd && ghdl -a aluComponente.vhd && ghdl -e aluKomponent && ghdl -r aluKomponent --vcd = alu & ghdlwave
Öppna en terminal, ange mappen och kör skriptet:
cd / home / user / vhdl sh compile.sh
Om det inte finns några fel öppnas gtkwave och vi kan se signalerna:
Dessa verktyg har varit mycket användbara och lättare att använda än de egna verktygen vi använder i klassen, vilket misstänksamt tar för lång tid att kompilera. Med ghdl tar det längre tid att byta fönster än att kompilera.
Mer information om VHDL
För de nya till vhdl, här de har ett grundläggande exempel på en förnekare.
Ett exempel på en video:
http://www.youtube.com/watch?v=feVMXsyLSOU
Kom ihåg att de senaste versionerna av Ubuntu inte har GHDL i sina förråd. Detta kan laddas ner för Linux / Windows från projektsidan:
http://ghdl.free.fr/site/pmwiki.php?n=Main.Download
Finns det ett sätt som GTKWave ger dig grindkretsen som den representerar?