Synthese av VHDL: Difference between revisions

From ift
No edit summary
No edit summary
Line 15: Line 15:
Sett opp lisensen i Quartus ved å starte Quartus, og velg menyen
Sett opp lisensen i Quartus ved å starte Quartus, og velg menyen


Precision er eit program som bruker Quartus til å syntetisere vhdl-koden. For å starte opp dette skriv: presision i eit terminalvindu. Vel deretter New Project, og deretter Add input file(i dette tilfelle alu_example.vhdl). Så går vi inn på Setup design, velger ein kretsprodusent, den ønska kretsen og designfrekvens(i vårt tilfelle valgte vi Altera APEX 20KE med frekvens 200MHz). Trykk så compile, og synthesize. No kan vi sjå på den generte kretsen i RTL Schematic og Technology Schematic(syntese med den valgte kretsen).
Precision er eit program som bruker Quartus til å syntetisere vhdl-koden.  
For å starte opp dette skriv: presision i eit terminalvindu.  
Vel deretter New Project, og deretter Add input file(i dette tilfelle alu_example.vhdl).  
Så går vi inn på Setup design, velger ein kretsprodusent, den ønska kretsen og designfrekvens(i vårt tilfelle valgte vi Altera APEX 20KE 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.
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.


Hvis du får en "ROOTDIR"-error, mangler det en variabel. Skriv følgende i terminalen:
Hvis du får en "ROOTDIR"-error, mangler det en variabel. Skriv følgende i terminalen:
Line 26: Line 32:
==Modelsim==
==Modelsim==


Start opp Modelsim, lag nytt prosjekt og legg til vhdl fila(alu_example.vhdl). Så legg vi til fila som Precision generte i prosjektdir til 'precision/prosjektnavn_temp_1/simulation/modelsim/prosjektnavn.vho' (i vårt tilfelle 'alu/add_sub_alu_temp_1/simulation/modelsim/add_sub_alu.vho').
Start opp Modelsim, lag nytt prosjekt og legg til vhdl fila(alu_example.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').


Legg til mapping av alterabiblioteket
Legg til mapping av alterabiblioteket
Line 32: Line 38:
vmap apex20ke /prog/altera/vhdl/apex20ke
vmap apex20ke /prog/altera/vhdl/apex20ke


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:


<pre>
<pre>

Revision as of 16:22, 14 February 2010

Synthesisering av vhdl kode

Grunnen til at vi skal synthesisere 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 utsignale frå den sythisierte og den opprinnelige koden. Vi bruker ein alu som eksempel.

Precision

mentor
precision

Pass på at lisensen for Quartus er korrekt satt opp, og at Precision finner Quartus. Sett opp lisensen i Quartus ved å starte Quartus, og velg menyen

Precision er eit program som bruker Quartus til å syntetisere vhdl-koden. For å starte opp dette skriv: presision i eit terminalvindu. Vel deretter New Project, og deretter Add input file(i dette tilfelle alu_example.vhdl). Så går vi inn på Setup design, velger ein kretsprodusent, den ønska kretsen og designfrekvens(i vårt tilfelle valgte vi Altera APEX 20KE 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. 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.

Hvis du får en "ROOTDIR"-error, mangler det en variabel. Skriv følgende i terminalen:

setenv QUARTUS_ROOTDIR /prog/altera/altera8.0

Modelsim

Start opp Modelsim, lag nytt prosjekt og legg til vhdl fila(alu_example.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').

Legg til mapping av alterabiblioteket

vmap apex20ke /prog/altera/vhdl/apex20ke

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).

NB. Simulatoren feilar hvis vi har beheld entity deklarasjonen i begge filane som skal inkluderast i testbenken. Dette kan vi løyse enten ved å ha ulike entitynavn på den synthesiserte og opprinnlige komponenten, eller ved å fjerne enitity deklarasjonen i den opprinnelige koden.

Simulering med timing

vsim -t ps alu_tb -sdfmax :alu_tb:ali=/heim/yngve/vhdl/syntese/alu_temp_1/simulation/modelsim/add_sub_alu_vhd.sdo

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 Modelsim vil vi derfor få ein del feilmeldingar dei første 50 nanosekunda.

Konklusjon

Vi kan teste om den synthesisere 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 alu_example.vhdl

LIBRARY ieee;
USE ieee.std_logic_1164.All;
USE ieee.std_logic_unsigned.all;

ENTITY add_sub_alu IS
  PORT (clk, 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 (clk = '1' AND clk'LAST_VALUE = '0') 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 <= "0000";
WHEN hold     => int_reg <= reg;
WHEN OTHERS   => int_reg <= reg;
END CASE;
END PROCESS alu;

mem: PROCESS (clk) is
BEGIN
IF (clk = '1' AND clk'LAST_VALUE = '0') 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) <= null;
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, 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 <= '0', '1' 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;