Synthese av VHDL: Difference between revisions
mNo edit summary |
mNo edit summary |
||
(13 intermediate revisions by 2 users not shown) | |||
Line 7: | Line 7: | ||
==Precision== | ==Precision== | ||
Precision bruker Vivado til å syntetisere vhdl-koden. For å starte synteseprogrammet: | |||
Precision bruker | |||
export LM_LICENSE_FILE=27001@lisensserver1:29000@lisensserver2 | |||
source /eda/Siemens/2023-24/scripts/PRECISION_2023.2_RHELx86.sh | |||
precision | precision | ||
Erstatt lisensserver med rett navn på lisensserver (se "Micro-how-to" i mikroelektronikk-teamet).Nye versjoner av programvaren ligger i /eda/Siemens sortert på årstall. | |||
Velg deretter New Project, og deretter Add input file (i dette tilfelle add_sub_alu.vhd). | |||
Så går vi inn på Setup design, velger ein kretsprodusent, den ønska kretsen og designfrekvens, for eksempel Zynq med frekvens 200MHz. For å få ut en vhdl fil av den syntetiserte koden må en gå på Tools->Options->Output og hak av for VHDL og trykk ok. | |||
Pass på at Precision finner Vivado, settes i menyen: | |||
Tools > Options > Place and Route Settings | |||
deretter | |||
Vivado > Integrated Place and Route > path to Xilinx Vivado installation tree | |||
settes til | |||
/eda/xilinx/Vivado/2020.2 | |||
Trykk så compile, og synthesize. | |||
No kan vi sjå på den generte kretsen i RTL Schematic og Technology Schematic (syntese med den valgte kretsen) under Schematics på venstre side. | |||
==Questasim== | |||
Start opp Questasim, lag nytt prosjekt og legg til vhdl fila (add_sub_alu.vhdl). Så legg vi til fila som Precision generte i prosjektdir til 'precision/prosjektnavn_temp_1/prosjektnavn.vhd' (i vårt tilfelle 'alu/add_sub_alu_temp_1/add_sub_alu.vhd'). | |||
Vi har kompilert disse bibliotekene til mappen / | Vi trenger simuleringsbibliotek for den valgte kretsfamilien for å kunne simulere etter "Place and Route". Disse bibliotekene kan genereres fra Vivado med menyen | ||
Tools > Compile Simulation Libraries | |||
men, vi har kompilert disse unisim-bibliotekene til mappen /eda/xilinx/lib. Du kan "mappe" disse slik: | |||
vmap | vmap unisim /eda/xilinx/lib/unisim | ||
Deretter legger vi til ei ny vhdl fil der vi skal lage testbenken vår. Vi legger til ein komponent av den opprinnelige og den synthesiserte vhdl koden. Vi koblar alle inngangane til samme signal på testbenken, og gir ut 2 forskjellige utsignal for å samanlikne ved hjelp av assert(sjå fila alu_tb.vhdl). På grunn av at utsignala av dei to komponentane ikkje skifta heilt synkront, testa vi berre kvart nanosekund ved å putta assert inn i ein process med wait for 1ns: | Deretter legger vi til ei ny vhdl fil der vi skal lage testbenken vår. Vi legger til ein komponent av den opprinnelige og den synthesiserte vhdl koden. Vi koblar alle inngangane til samme signal på testbenken, og gir ut 2 forskjellige utsignal for å samanlikne ved hjelp av assert(sjå fila alu_tb.vhdl). På grunn av at utsignala av dei to komponentane ikkje skifta heilt synkront, testa vi berre kvart nanosekund ved å putta assert inn i ein process med wait for 1ns: | ||
Line 48: | Line 54: | ||
==Simulering med timing== | ==Simulering med timing== | ||
Eksempel på start av simulering med timing: | |||
vsim -t ps | vsim -t ps -sdfnoerror -sdfmax /alu_synth=/home/kaf003/VHDL_Prosjekter/PHYS321/vivado_impl_1/add_sub_alu_synth.sdf work.alu_tb | ||
Vi kan sjå at i dei første 50 nanosekunda er utsignala ulike. Dette er fordi før første klokkeflanke er verdiane udefinert i den opprinnelige komponenten, medan den synthesisere ikkje kan ha udefinerte verdiar. I | Vi kan sjå at i dei første 50 nanosekunda er utsignala ulike. Dette er fordi før første klokkeflanke er verdiane udefinert i den opprinnelige komponenten, medan den synthesisere ikkje kan ha udefinerte verdiar. I Questasim vil vi derfor få ein del feilmeldingar dei første 50 nanosekunda. | ||
==Konklusjon== | ==Konklusjon== | ||
Vi kan teste om den | Vi kan teste om den syntesiserte komponenten oppfører seg likt med den opprinnelige komponenten ved å koble begge to til samme testbenk. Vi fekk problem i overgangane når vi testa kontinuerlig, så vi løyste problemet ved å berre teste kvart naonosekund. Bortsett frå dei første 50 nanosekunda (sjå grunn over) kan vi sjå at begge komponetane gir ut samme utsignal. Vi prøvde å bruke samme enitynavn på begge komponentane med ulik arcitechture, men fekk berre lov å kompilere og ikkje simulere. Vi kan derfor konkludere med at desse må ha ulike navn. | ||
==Kode== | ==Kode== | ||
===Kode til | ===Kode til add_sub_alu.vhd=== | ||
<pre> | <pre> | ||
Line 68: | Line 74: | ||
ENTITY add_sub_alu IS | ENTITY add_sub_alu IS | ||
PORT ( | |||
clk : IN std_logic; | |||
rst : IN std_logic; | |||
enable_in : IN std_logic; | enable_in : IN std_logic; | ||
start : IN std_logic; | start : IN std_logic; | ||
Line 76: | Line 84: | ||
do_hold : IN std_logic; | do_hold : IN std_logic; | ||
data_in : IN std_logic_vector(3 DOWNTO 0); | data_in : IN std_logic_vector(3 DOWNTO 0); | ||
data_out : OUT std_logic_vector (3 DOWNTO 0) BUS); | data_out : OUT std_logic_vector(3 DOWNTO 0) BUS); | ||
END add_sub_alu; | END add_sub_alu; | ||
ARCHITECTURE algorithm OF add_sub_alu IS | ARCHITECTURE algorithm OF add_sub_alu IS | ||
TYPE states IS (hold, reset, add, subtract); | TYPE states IS (hold, reset, add, subtract); | ||
SIGNAL state_var : states; | SIGNAL state_var : states; | ||
SIGNAL reg, int_reg : std_logic_vector(3 DOWNTO 0); | SIGNAL reg, int_reg : std_logic_vector(3 DOWNTO 0); | ||
SIGNAL latched_data_in: std_logic_vector(3 DOWNTO 0); | SIGNAL latched_data_in : std_logic_vector(3 DOWNTO 0); | ||
BEGIN | BEGIN | ||
latch: PROCESS (enable_in, data_in)is | latch: PROCESS (enable_in, data_in)is | ||
BEGIN | BEGIN | ||
IF (enable_in = '1') THEN | IF (enable_in = '1') THEN | ||
latched_data_in <= data_in; | latched_data_in <= data_in; | ||
END IF; | END IF; | ||
END PROCESS latch; | END PROCESS latch; | ||
fsm: PROCESS (clk, rst) is | fsm: PROCESS (clk, rst) is | ||
BEGIN | BEGIN | ||
IF (rst = '0') THEN | IF (rst = '0') THEN | ||
state_var <= reset; | state_var <= reset; | ||
ELSIF (clk | ELSIF rising_edge(clk) THEN | ||
CASE state_var IS | CASE state_var IS | ||
WHEN hold | WHEN hold => | ||
state_var <= reset; | IF (start = '1') THEN | ||
END IF; | state_var <= reset; | ||
WHEN reset => IF (do_add = '1') THEN | END IF; | ||
state_var <= add; | WHEN reset => | ||
ELSIF (do_subtract = '1') THEN | IF (do_add = '1') THEN | ||
state_var <= subtract; | state_var <= add; | ||
END IF; | ELSIF (do_subtract = '1') THEN | ||
WHEN add => IF (do_hold = '1') THEN | state_var <= subtract; | ||
state_var <= hold; | END IF; | ||
ELSIF (do_subtract = '1') THEN | WHEN add => | ||
state_var <= subtract; | IF (do_hold = '1') THEN | ||
END IF; | state_var <= hold; | ||
WHEN subtract => IF (do_hold = '1') THEN | ELSIF (do_subtract = '1') THEN | ||
state_var <= hold; | state_var <= subtract; | ||
ELSIF (do_add = '1') THEN | END IF; | ||
state_var <= add; | WHEN subtract => | ||
END IF; | IF (do_hold = '1') THEN | ||
WHEN OTHERS => state_var <= reset; | state_var <= hold; | ||
END CASE; | ELSIF (do_add = '1') THEN | ||
END IF; | state_var <= add; | ||
END IF; | |||
WHEN OTHERS => state_var <= reset; | |||
END CASE; | |||
END IF; | |||
END PROCESS fsm; | END PROCESS fsm; | ||
Line 125: | Line 137: | ||
BEGIN | BEGIN | ||
CASE state_var IS | CASE state_var IS | ||
WHEN add => int_reg <= reg + latched_data_in; | WHEN add => int_reg <= reg + latched_data_in; | ||
WHEN subtract => int_reg <= reg - latched_data_in; | WHEN subtract => int_reg <= reg - latched_data_in; | ||
WHEN reset => int_reg <= | WHEN reset => int_reg <= (others => '0'); | ||
WHEN hold => int_reg <= reg; | WHEN hold => int_reg <= reg; | ||
WHEN OTHERS => int_reg <= reg; | WHEN OTHERS => int_reg <= reg; | ||
END CASE; | END CASE; | ||
END PROCESS alu; | END PROCESS alu; | ||
Line 135: | Line 147: | ||
mem: PROCESS (clk) is | mem: PROCESS (clk) is | ||
BEGIN | BEGIN | ||
IF (clk | IF rising_edge(clk) THEN | ||
reg <= int_reg; | reg <= int_reg; | ||
END IF; | END IF; | ||
END PROCESS mem; | END PROCESS mem; | ||
tri: PROCESS (enable, reg) is | tri: PROCESS (enable, reg) is | ||
BEGIN | BEGIN | ||
FOR i IN 3 DOWNTO 0 LOOP | FOR i IN 3 DOWNTO 0 LOOP | ||
IF (enable = '1') THEN | IF (enable = '1') THEN | ||
data_out(i) <= reg(i); | data_out(i) <= reg(i); | ||
ELSE | ELSE | ||
data_out(i) <= 'Z'; | data_out(i) <= 'Z'; | ||
END IF; | END IF; | ||
END LOOP; | END LOOP; | ||
END PROCESS tri; | END PROCESS tri; | ||
END algorithm; | END algorithm;</pre> | ||
</pre> | |||
===Koden til alu_tb.vhdl=== | ===Koden til alu_tb.vhdl=== | ||
Line 166: | Line 177: | ||
architecture struct of alu_tb is | architecture struct of alu_tb is | ||
--Deklaring av signal som skal koblast til komponentane. | --Deklaring av signal som skal koblast til komponentane. | ||
--Alle innsignal er felles, medan vi har 2 forskjellige utsignal. | --Alle innsignal er felles, medan vi har 2 forskjellige utsignal. | ||
signal clk | signal clk : std_logic; | ||
signal enable_in : std_logic; | signal reset : std_logic; | ||
signal start : std_logic; | signal enable_in : std_logic; | ||
signal enable : std_logic; | signal start : std_logic; | ||
signal do_add : std_logic; | signal enable : std_logic; | ||
signal do_subtract : std_logic; | signal do_add : std_logic; | ||
signal do_hold : std_logic; | signal do_subtract : std_logic; | ||
signal data_in : std_logic_vector(3 downto 0); | signal do_hold : std_logic; | ||
signal data_out : std_logic_vector(3 downto 0); | signal data_in : std_logic_vector(3 downto 0); | ||
signal data_out_synt : std_logic_vector(3 downto 0); | signal data_out : std_logic_vector(3 downto 0); | ||
signal data_out_synt : std_logic_vector(3 downto 0); | |||
begin | begin | ||
--Deklarer komponenten alu. | |||
alu : entity add_sub_alu(algorithm) | |||
--Kobler signala til den opprinnelige komponenten. | |||
port map ( | |||
clk => clk, | |||
rst => reset, | |||
enable_in => enable_in, | |||
start => start, | |||
enable => enable, | |||
do_add => do_add, | |||
do_subtract => do_subtract, | |||
do_hold => do_hold, | |||
data_in => data_in, | |||
data_out => data_out); | |||
--Deklarer komponenten | --Deklarer komponenten alu_synt. | ||
alu_synt : entity add_sub_alu_synth(structure) | |||
--Kobler signala til den synthiserte komponenten. | |||
port map ( | |||
clk => clk, | |||
rst => reset, | |||
enable_in => enable_in, | |||
start => start, | |||
enable => enable, | |||
do_add => do_add, | |||
do_subtract => do_subtract, | |||
do_hold => do_hold, | |||
data_in => data_in, | |||
data_out => data_out_synt); | |||
-- | --Klokkegenerator | ||
clock_gen : process | |||
clk = | begin | ||
clk <= '0', '1' after 50 ns; | |||
wait for 100 ns; | |||
end process clock_gen; | |||
--Setter testvektorane. | |||
reset <= '0', '1' after 60 ns; | |||
enable <= '1', '0' after 900 ns; | |||
enable_in <= '1', '0' after 400 ns; | |||
start <= '1', '0' after 300 ns; | |||
do_add <= '1', '0' after 660 ns; | |||
do_subtract <= '0'; | |||
do_hold <= '0'; | |||
data_in <= X"3"; | |||
--Setter testvektorane. | |||
reset <= '0', '1' after 60 ns; | |||
enable <= '1', '0' after 900 ns; | |||
enable_in <= '1', '0' after 400 ns; | |||
start <= '1', '0' after 300 ns; | |||
do_add <= '1', '0' after 660 ns; | |||
do_subtract <= '0'; | |||
do_hold <= '0'; | |||
data_in <= X"3" | |||
end; | --Test process for å samanlikne utsignala kvart nanosekund. | ||
test : process | |||
begin | |||
wait for 1 ns; | |||
assert (data_out = data_out_synt) | |||
report "Data ut er ulik" | |||
severity Error; | |||
end process test; | |||
end architecture struct; | |||
</pre> | </pre> | ||
[[Category:Mikroelektronikk]] | [[Category:Mikroelektronikk]] |
Latest revision as of 11:43, 30 May 2024
Syntetiseringen av VHDL kode
Grunnen til at vi skal syntetisere koden, er at vi må lage beskrivelse av koden tilpassa ein krets.
Vi vil no prøve å synthesisere vhdl kode. Og etterpå vil vi lage ein testbenk der vi samanliknar utsignala frå den syntetiserte og den opprinnelige koden. Vi bruker ein alu som eksempel.
Precision
Precision bruker Vivado til å syntetisere vhdl-koden. For å starte synteseprogrammet:
export LM_LICENSE_FILE=27001@lisensserver1:29000@lisensserver2 source /eda/Siemens/2023-24/scripts/PRECISION_2023.2_RHELx86.sh precision
Erstatt lisensserver med rett navn på lisensserver (se "Micro-how-to" i mikroelektronikk-teamet).Nye versjoner av programvaren ligger i /eda/Siemens sortert på årstall.
Velg deretter New Project, og deretter Add input file (i dette tilfelle add_sub_alu.vhd). Så går vi inn på Setup design, velger ein kretsprodusent, den ønska kretsen og designfrekvens, for eksempel Zynq med frekvens 200MHz. For å få ut en vhdl fil av den syntetiserte koden må en gå på Tools->Options->Output og hak av for VHDL og trykk ok.
Pass på at Precision finner Vivado, settes i menyen:
Tools > Options > Place and Route Settings
deretter
Vivado > Integrated Place and Route > path to Xilinx Vivado installation tree
settes til
/eda/xilinx/Vivado/2020.2
Trykk så compile, og synthesize. No kan vi sjå på den generte kretsen i RTL Schematic og Technology Schematic (syntese med den valgte kretsen) under Schematics på venstre side.
Questasim
Start opp Questasim, lag nytt prosjekt og legg til vhdl fila (add_sub_alu.vhdl). Så legg vi til fila som Precision generte i prosjektdir til 'precision/prosjektnavn_temp_1/prosjektnavn.vhd' (i vårt tilfelle 'alu/add_sub_alu_temp_1/add_sub_alu.vhd').
Vi trenger simuleringsbibliotek for den valgte kretsfamilien for å kunne simulere etter "Place and Route". Disse bibliotekene kan genereres fra Vivado med menyen
Tools > Compile Simulation Libraries
men, vi har kompilert disse unisim-bibliotekene til mappen /eda/xilinx/lib. Du kan "mappe" disse slik:
vmap unisim /eda/xilinx/lib/unisim
Deretter legger vi til ei ny vhdl fil der vi skal lage testbenken vår. Vi legger til ein komponent av den opprinnelige og den synthesiserte vhdl koden. Vi koblar alle inngangane til samme signal på testbenken, og gir ut 2 forskjellige utsignal for å samanlikne ved hjelp av assert(sjå fila alu_tb.vhdl). På grunn av at utsignala av dei to komponentane ikkje skifta heilt synkront, testa vi berre kvart nanosekund ved å putta assert inn i ein process med wait for 1ns:
test : process begin wait for 1 ns; assert (data_out = data_out_synt) report "Data ut er ulik" severity Error; end process test;
Når vi har laga testbenken, kompilerer vi filene (husk å kompilere i rett rekkefølge med compileorder->autogenerate første gong).
Siden precision generer samme navn på entityen og architecturen på den syntetiserte filen som i den orginale så vil ikke simulatoren kjøre de samtidig. Dette endres ved å endre entity fra add_sub_alu til add_sub_alu_synth og skifte navnet på architecture fra algoritm til structure øverst og nederst i den syntetiserte filen.
Simulering med timing
Eksempel på start av simulering med timing:
vsim -t ps -sdfnoerror -sdfmax /alu_synth=/home/kaf003/VHDL_Prosjekter/PHYS321/vivado_impl_1/add_sub_alu_synth.sdf work.alu_tb
Vi kan sjå at i dei første 50 nanosekunda er utsignala ulike. Dette er fordi før første klokkeflanke er verdiane udefinert i den opprinnelige komponenten, medan den synthesisere ikkje kan ha udefinerte verdiar. I Questasim vil vi derfor få ein del feilmeldingar dei første 50 nanosekunda.
Konklusjon
Vi kan teste om den syntesiserte komponenten oppfører seg likt med den opprinnelige komponenten ved å koble begge to til samme testbenk. Vi fekk problem i overgangane når vi testa kontinuerlig, så vi løyste problemet ved å berre teste kvart naonosekund. Bortsett frå dei første 50 nanosekunda (sjå grunn over) kan vi sjå at begge komponetane gir ut samme utsignal. Vi prøvde å bruke samme enitynavn på begge komponentane med ulik arcitechture, men fekk berre lov å kompilere og ikkje simulere. Vi kan derfor konkludere med at desse må ha ulike navn.
Kode
Kode til add_sub_alu.vhd
LIBRARY ieee; USE ieee.std_logic_1164.All; USE ieee.std_logic_unsigned.all; ENTITY add_sub_alu IS PORT ( clk : IN std_logic; rst : IN std_logic; enable_in : IN std_logic; start : IN std_logic; enable : IN std_logic; do_add : IN std_logic; do_subtract : IN std_logic; do_hold : IN std_logic; data_in : IN std_logic_vector(3 DOWNTO 0); data_out : OUT std_logic_vector(3 DOWNTO 0) BUS); END add_sub_alu; ARCHITECTURE algorithm OF add_sub_alu IS TYPE states IS (hold, reset, add, subtract); SIGNAL state_var : states; SIGNAL reg, int_reg : std_logic_vector(3 DOWNTO 0); SIGNAL latched_data_in : std_logic_vector(3 DOWNTO 0); BEGIN latch: PROCESS (enable_in, data_in)is BEGIN IF (enable_in = '1') THEN latched_data_in <= data_in; END IF; END PROCESS latch; fsm: PROCESS (clk, rst) is BEGIN IF (rst = '0') THEN state_var <= reset; ELSIF rising_edge(clk) THEN CASE state_var IS WHEN hold => IF (start = '1') THEN state_var <= reset; END IF; WHEN reset => IF (do_add = '1') THEN state_var <= add; ELSIF (do_subtract = '1') THEN state_var <= subtract; END IF; WHEN add => IF (do_hold = '1') THEN state_var <= hold; ELSIF (do_subtract = '1') THEN state_var <= subtract; END IF; WHEN subtract => IF (do_hold = '1') THEN state_var <= hold; ELSIF (do_add = '1') THEN state_var <= add; END IF; WHEN OTHERS => state_var <= reset; END CASE; END IF; END PROCESS fsm; alu: PROCESS (state_var, latched_data_in, reg)is BEGIN CASE state_var IS WHEN add => int_reg <= reg + latched_data_in; WHEN subtract => int_reg <= reg - latched_data_in; WHEN reset => int_reg <= (others => '0'); WHEN hold => int_reg <= reg; WHEN OTHERS => int_reg <= reg; END CASE; END PROCESS alu; mem: PROCESS (clk) is BEGIN IF rising_edge(clk) THEN reg <= int_reg; END IF; END PROCESS mem; tri: PROCESS (enable, reg) is BEGIN FOR i IN 3 DOWNTO 0 LOOP IF (enable = '1') THEN data_out(i) <= reg(i); ELSE data_out(i) <= 'Z'; END IF; END LOOP; END PROCESS tri; END algorithm;
Koden til alu_tb.vhdl
library ieee; use ieee.std_logic_1164.all; library work; use work.all; entity alu_tb is end entity alu_tb; architecture struct of alu_tb is --Deklaring av signal som skal koblast til komponentane. --Alle innsignal er felles, medan vi har 2 forskjellige utsignal. signal clk : std_logic; signal reset : std_logic; signal enable_in : std_logic; signal start : std_logic; signal enable : std_logic; signal do_add : std_logic; signal do_subtract : std_logic; signal do_hold : std_logic; signal data_in : std_logic_vector(3 downto 0); signal data_out : std_logic_vector(3 downto 0); signal data_out_synt : std_logic_vector(3 downto 0); begin --Deklarer komponenten alu. alu : entity add_sub_alu(algorithm) --Kobler signala til den opprinnelige komponenten. port map ( clk => clk, rst => reset, enable_in => enable_in, start => start, enable => enable, do_add => do_add, do_subtract => do_subtract, do_hold => do_hold, data_in => data_in, data_out => data_out); --Deklarer komponenten alu_synt. alu_synt : entity add_sub_alu_synth(structure) --Kobler signala til den synthiserte komponenten. port map ( clk => clk, rst => reset, enable_in => enable_in, start => start, enable => enable, do_add => do_add, do_subtract => do_subtract, do_hold => do_hold, data_in => data_in, data_out => data_out_synt); --Klokkegenerator clock_gen : process begin clk <= '0', '1' after 50 ns; wait for 100 ns; end process clock_gen; --Setter testvektorane. reset <= '0', '1' after 60 ns; enable <= '1', '0' after 900 ns; enable_in <= '1', '0' after 400 ns; start <= '1', '0' after 300 ns; do_add <= '1', '0' after 660 ns; do_subtract <= '0'; do_hold <= '0'; data_in <= X"3"; --Test process for å samanlikne utsignala kvart nanosekund. test : process begin wait for 1 ns; assert (data_out = data_out_synt) report "Data ut er ulik" severity Error; end process test; end architecture struct;