Synthese av VHDL: Difference between revisions

From ift
mNo edit summary
m (oppdatert sdf-inkludering med sdfnoerror)
(33 intermediate revisions by 4 users not shown)
Line 1: Line 1:
===Synthesisering av vhdl kode===
===Syntetiseringen av VHDL kode===


Grunnen til at vi skal synthesisere koden, er at vi må lage beskrivelse av koden tilpassa ein krets.
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 utsignale frå den sythisierte og den opprinnelige koden. Vi bruker ein alu som eksempel.
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==


<pre>
Precision bruker Vivado til å syntetisere vhdl-koden. For å starte synteseprogrammet:
mentor
 
precision
export LM_LICENSE_FILE=1717@lisensserver:2100@lisensserver
</pre>
source /eda/mentor/2019-20/scripts/PRECISION_2019.1.1_RHELx86.sh
precision
 


Pass at lisens i Quartus er korrekt satt opp, og at Precision finner Quartus.
Vel deretter New Project, og deretter Add input file (i dette tilfelle add_sub_alu.vhd).
Sett opp lisensen i Quartus ved å starte Quartus, og velg menyen
Så går vi inn 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.


Precision er eit program som bruker Quartus til å synthisiere vhdl kode. 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).  
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


Hvis du får en "ROOTDIR"-error, mangler det en variabel. Skriv følgende i terminalen:
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.


<pre>
==Questasim==
setenv QUARTUS_ROOTDIR /prog/quartus
</pre>


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


Start opp Modelsim, lag nytt prosjekt og legg til vhdl fila(alu_example.vhdl). Så legg vi til fila som Precision generte '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).
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:


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). Vi må ha ulike entitynavn på den synthesiserte og opprinnlige komponenten, ellers vil ikkje simuleringa virka. 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:
  vmap unisim /eda/xilinx/lib/unisim
   
   
<pre>
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
test : process
wait for 1 ns;
begin
assert (data_out = data_out_synt)
wait for 1 ns;
report "Data ut er ulik"
assert (data_out = data_out_synt)
severity Error;
report "Data ut er ulik"
end process test;
severity Error;
</pre>
end process test;
 
Når vi har laga testbenken, kompilerer vi filene (husk å kompilere i rett rekkefølge med compileorder->autogenerate første gong).


Når vi har laga testbenken, kompilerer vi(husk å kompilere i rett rekkefølge med compileorder->autogenerate) filene.
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==
==Simulering med timing==


  <pre>
Eksempel på start av 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
 
</pre>
  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 Modelsim vil vi derfor få ein del feilmeldingar dei første 50 nanosekunda.
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 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.
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 alu_example.vhdl=
===Kode til add_sub_alu.vhd===


<pre>
<pre>
Line 63: Line 73:


ENTITY add_sub_alu IS
ENTITY add_sub_alu IS
PORT (clk, rst   : IN  std_logic;
PORT (
      enable_in  : IN  std_logic;
  clk         : IN  std_logic;
      start      : IN  std_logic;
  rst         : IN  std_logic;
      enable      : IN  std_logic;
  enable_in  : IN  std_logic;
      do_add      : IN  std_logic;
  start      : IN  std_logic;
      do_subtract : IN  std_logic;
  enable      : IN  std_logic;
      do_hold    : IN  std_logic;
  do_add      : IN  std_logic;
      data_in    : IN  std_logic_vector(3 DOWNTO 0);
  do_subtract : IN  std_logic;
      data_out    : OUT std_logic_vector (3 DOWNTO 0) BUS);
  do_hold    : IN  std_logic;
END add_sub_alu;
  data_in    : IN  std_logic_vector(3 DOWNTO 0);
  data_out    : OUT std_logic_vector(3 DOWNTO 0) BUS);
ARCHITECTURE algorithm OF add_sub_alu IS
END add_sub_alu;
    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 <= "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;
</pre>


=Koden til add_sub_alu.vho=
ARCHITECTURE algorithm OF add_sub_alu IS
<pre>
  TYPE  states          IS (hold, reset, add, subtract);
-- Copyright (C) 1991-2005 Altera Corporation
  SIGNAL state_var      : states;
-- Any  megafunction  design, and related netlist (encrypted  or  decrypted),
  SIGNAL reg, int_reg    : std_logic_vector(3 DOWNTO 0);
-- support information,  device programming or simulation file,  and any other
   SIGNAL latched_data_in : std_logic_vector(3 DOWNTO 0);
-- associated  documentation or information  provided by  Altera  or a partner
BEGIN
-- under  Altera's  Megafunction  Partnership   Program  may  be  used  only
-- to program  PLD  devices (but not masked  PLD  devices) from  Altera.  Any
-- other  use  of such  megafunction  design,  netlist,  support  information,
-- device programming or simulation file,  or any other  related documentation
-- or information  is prohibited  for  any  other purpose,  including, but not
-- limited to  modification,  reverse engineering,  de-compiling, or use  with
-- any other  silicon devices,  unless such use is  explicitly  licensed under
-- a separate agreement with  Altera  or a megafunction partner.  Title to the
-- intellectual property,  including patents,  copyrights,  trademarks,  trade
-- secrets,  or maskworks,  embodied in any such megafunction design, netlist,
-- support  information,  device programming or simulation file,  or any other
-- related documentation or information provided by  Altera  or a megafunction
-- partner, remains with Altera, the megafunction partner, or their respective
-- licensors. No other licenses, including any licenses needed under any third
-- party's intellectual property, are provided herein.


-- VENDOR "Altera"
latch: PROCESS (enable_in, data_in)is
-- PROGRAM "Quartus II"
BEGIN
-- VERSION "Version 4.2 Build 178 01/19/2005 Service Pack 1 SJ Full Version"
  IF (enable_in = '1') THEN
    latched_data_in <= data_in;
  END IF;
END PROCESS latch;


-- DATE "02/18/2005 13:34:52"
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
-- Device: Altera EP20K200EQC208-1 Package PQFP208
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
-- This VHDL file should be used for MODELSIM (VHDL OUTPUT FROM QUARTUS II) only
BEGIN
--
  IF rising_edge(clk) THEN
 
    reg <= int_reg;
LIBRARY IEEE, apex20ke;
  END IF;
USE IEEE.std_logic_1164.all;
END PROCESS mem;
USE apex20ke.apex20ke_components.all;
 
ENTITY add_sub_alu_synt IS
    PORT (
enable : IN std_logic;
clk : IN std_logic;
do_hold : IN std_logic;
rst : IN std_logic;
do_add : IN std_logic;
do_subtract : IN std_logic;
enable_in : IN std_logic;
data_in : IN std_logic_vector(3 DOWNTO 0);
start : IN std_logic;
data_out : OUT std_logic_vector(3 DOWNTO 0)
);
END add_sub_alu_synt;
 
ARCHITECTURE structure OF add_sub_alu_synt IS
SIGNAL gnd : std_logic := '0';
SIGNAL vcc : std_logic := '1';
SIGNAL devclrn : std_logic := '1';
SIGNAL devpor : std_logic := '1';
SIGNAL devoe : std_logic := '0';
SIGNAL ww_enable : std_logic;
SIGNAL ww_clk : std_logic;
SIGNAL ww_do_hold : std_logic;
SIGNAL ww_rst : std_logic;
SIGNAL ww_do_add : std_logic;
SIGNAL ww_do_subtract : std_logic;
SIGNAL ww_enable_in : std_logic;
SIGNAL ww_data_in : std_logic_vector(3 DOWNTO 0);
SIGNAL ww_start : std_logic;
SIGNAL ww_data_out : std_logic_vector(3 DOWNTO 0);
SIGNAL if0a5x13_aCOMBOUT : std_logic;
SIGNAL start_acombout : std_logic;
SIGNAL data_in_a2_a_acombout : std_logic;
SIGNAL do_subtract_acombout : std_logic;
SIGNAL do_hold_acombout : std_logic;
SIGNAL n5831x3 : std_logic;
SIGNAL do_add_acombout : std_logic;
SIGNAL n5831x2 : std_logic;
SIGNAL clk_acombout : std_logic;
SIGNAL rst_acombout : std_logic;
SIGNAL n544cx3 : std_logic;
SIGNAL n544cx2 : std_logic;
SIGNAL state_var_1 : std_logic;
SIGNAL data_in_a0_a_acombout : std_logic;
SIGNAL enable_in_acombout : std_logic;
SIGNAL latched_data_in_0 : std_logic;
SIGNAL nfc54x2 : std_logic;
SIGNAL cin : std_logic;
SIGNAL a_2_dup_240 : std_logic;
SIGNAL nf0a5x2 : std_logic;
SIGNAL reg_0 : std_logic;
SIGNAL enable_acombout : std_logic;
SIGNAL data_in_a1_a_acombout : std_logic;
SIGNAL latched_data_in_1 : std_logic;
SIGNAL nf0a5x8 : std_logic;
SIGNAL nf0a5x10 : std_logic;
SIGNAL nf0a5x9 : std_logic;
SIGNAL a_2_dup_239 : std_logic;
SIGNAL reg_1 : std_logic;
SIGNAL latched_data_in_2 : std_logic;
SIGNAL nf0a5x6 : std_logic;
SIGNAL nf0a5x7 : std_logic;
SIGNAL a_2_dup_238 : std_logic;
SIGNAL reg_2 : std_logic;
SIGNAL data_in_a3_a_acombout : std_logic;
SIGNAL latched_data_in_3 : std_logic;
SIGNAL nf0a5x4 : std_logic;
SIGNAL nf0a5x5 : std_logic;
SIGNAL a_2 : std_logic;
SIGNAL reg_3 : std_logic;
SIGNAL ALT_INV_rst_acombout : std_logic;


tri: PROCESS (enable, reg) is
BEGIN
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;


ww_enable <= enable;
END algorithm;</pre>
ww_clk <= clk;
ww_do_hold <= do_hold;
ww_rst <= rst;
ww_do_add <= do_add;
ww_do_subtract <= do_subtract;
ww_enable_in <= enable_in;
ww_data_in <= data_in;
ww_start <= start;
data_out <= ww_data_out;
ALT_INV_rst_acombout <= NOT rst_acombout;
 
start_ibuf : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_start,
combout => start_acombout);
 
data_in_ibuf_2 : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_data_in(2),
combout => data_in_a2_a_acombout);
 
do_subtract_ibuf : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_do_subtract,
combout => do_subtract_acombout);
 
do_hold_ibuf : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_do_hold,
combout => do_hold_acombout);
 
ib0e1x3 : apex20ke_lcell
-- Equation(s):
-- n5831x3 = do_hold_acombout & state_var_1
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "F000",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
datac => do_hold_acombout,
datad => state_var_1,
devclrn => devclrn,
devpor => devpor,
combout => n5831x3);
 
do_add_ibuf : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_do_add,
combout => do_add_acombout);
 
ib0e1x2 : apex20ke_lcell
-- Equation(s):
-- n5831x2 = n544cx3 & state_var_1 & !do_subtract_acombout # !state_var_1 & !start_acombout
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "3050",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
dataa => start_acombout,
datab => do_subtract_acombout,
datac => n544cx3,
datad => state_var_1,
devclrn => devclrn,
devpor => devpor,
combout => n5831x2);
 
clk_ibuf : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_clk,
combout => clk_acombout);
 
rst_ibuf : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_rst,
combout => rst_acombout);
 
reg_state_var_0 : apex20ke_lcell
-- Equation(s):
-- n544cx3 = DFFE(n5831x3 # n5831x2 # !n544cx3 & do_add_acombout, GLOBAL(clk_acombout), GLOBAL(rst_acombout), , )
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "FFDC",
output_mode => "reg_only")
-- pragma translate_on
PORT MAP (
dataa => n544cx3,
datab => n5831x3,
datac => do_add_acombout,
datad => n5831x2,
clk => clk_acombout,
aclr => ALT_INV_rst_acombout,
devclrn => devclrn,
devpor => devpor,
regout => n544cx3);
 
ib0e2x3 : apex20ke_lcell
-- Equation(s):
-- n544cx2 = !n544cx3 & !state_var_1 & do_add_acombout # do_subtract_acombout
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "000E",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
dataa => do_add_acombout,
datab => do_subtract_acombout,
datac => n544cx3,
datad => state_var_1,
devclrn => devclrn,
devpor => devpor,
combout => n544cx2);
 
reg_state_var_1 : apex20ke_lcell
-- Equation(s):
-- state_var_1 = DFFE(n544cx2 # !do_hold_acombout & state_var_1, GLOBAL(clk_acombout), GLOBAL(rst_acombout), , )
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "FF50",
output_mode => "reg_only")
-- pragma translate_on
PORT MAP (
dataa => do_hold_acombout,
datac => state_var_1,
datad => n544cx2,
clk => clk_acombout,
aclr => ALT_INV_rst_acombout,
devclrn => devclrn,
devpor => devpor,
regout => state_var_1);
 
data_in_ibuf_0 : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_data_in(0),
combout => data_in_a0_a_acombout);
 
enable_in_ibuf : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_enable_in,
combout => enable_in_acombout);
 
id8dfx3 : apex20ke_lcell
-- Equation(s):
-- latched_data_in_0 = enable_in_acombout & data_in_a0_a_acombout # !enable_in_acombout & latched_data_in_0
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "CACA",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
dataa => latched_data_in_0,
datab => data_in_a0_a_acombout,
datac => enable_in_acombout,
devclrn => devclrn,
devpor => devpor,
combout => latched_data_in_0);
 
id8dfx2 : apex20ke_lcell
-- Equation(s):
-- nfc54x2 = latched_data_in_0 $ (!n544cx3 # !state_var_1)
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "C30F",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
datab => state_var_1,
datac => latched_data_in_0,
datad => n544cx3,
devclrn => devclrn,
devpor => devpor,
combout => nfc54x2);
 
id8dfx1 : apex20ke_lcell
-- Equation(s):
-- cin = state_var_1 & !n544cx3
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "00CC",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
datab => state_var_1,
datad => n544cx3,
devclrn => devclrn,
devpor => devpor,
combout => cin);
 
ifc54x2 : apex20ke_lcell
-- Equation(s):
-- a_2_dup_240 = nfc54x2 $ reg_0 $ cin
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "C33C",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
datab => nfc54x2,
datac => reg_0,
datad => cin,
devclrn => devclrn,
devpor => devpor,
combout => a_2_dup_240);
 
i197dx1 : apex20ke_lcell
-- Equation(s):
-- nf0a5x2 = state_var_1 # !n544cx3
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "CCFF",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
datab => state_var_1,
datad => n544cx3,
devclrn => devclrn,
devpor => devpor,
combout => nf0a5x2);
 
reg_reg_0 : apex20ke_lcell
-- Equation(s):
-- reg_0 = DFFE(a_2_dup_240 & state_var_1, GLOBAL(clk_acombout), , , nf0a5x2)
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "F000",
output_mode => "reg_only")
-- pragma translate_on
PORT MAP (
datac => a_2_dup_240,
datad => state_var_1,
clk => clk_acombout,
ena => nf0a5x2,
devclrn => devclrn,
devpor => devpor,
regout => reg_0);
 
enable_ibuf : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_enable,
combout => enable_acombout);
 
data_in_ibuf_1 : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_data_in(1),
combout => data_in_a1_a_acombout);
 
i2456x2 : apex20ke_lcell
-- Equation(s):
-- latched_data_in_1 = enable_in_acombout & data_in_a1_a_acombout # !enable_in_acombout & latched_data_in_1
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "CFC0",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
datab => data_in_a1_a_acombout,
datac => enable_in_acombout,
datad => latched_data_in_1,
devclrn => devclrn,
devpor => devpor,
combout => latched_data_in_1);
 
i2456x1 : apex20ke_lcell
-- Equation(s):
-- nf0a5x8 = latched_data_in_1 $ (!state_var_1 # !n544cx3)
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "C333",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
datab => latched_data_in_1,
datac => n544cx3,
datad => state_var_1,
devclrn => devclrn,
devpor => devpor,
combout => nf0a5x8);
 
if0a5x14 : apex20ke_lcell
-- Equation(s):
-- nf0a5x10 = reg_0 & nfc54x2 # cin # !reg_0 & nfc54x2 & cin
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "FCC0",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
datab => reg_0,
datac => nfc54x2,
datad => cin,
devclrn => devclrn,
devpor => devpor,
combout => nf0a5x10);
 
if0a5x13 : apex20ke_lcell
-- Equation(s):
-- nf0a5x9 = CARRY(nf0a5x10)
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "arithmetic",
packed_mode => "false",
lut_mask => "00CC",
output_mode => "none")
-- pragma translate_on
PORT MAP (
datab => nf0a5x10,
devclrn => devclrn,
devpor => devpor,
cout => nf0a5x9);
 
if0a5x10 : apex20ke_lcell
-- Equation(s):
-- a_2_dup_239 = reg_1 $ nf0a5x8 $ nf0a5x9
-- nf0a5x7 = CARRY(reg_1 & !nf0a5x8 & !nf0a5x9 # !reg_1 & !nf0a5x9 # !nf0a5x8)
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "arithmetic",
cin_used => "true",
packed_mode => "false",
lut_mask => "9617",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
dataa => reg_1,
datab => nf0a5x8,
cin => nf0a5x9,
devclrn => devclrn,
devpor => devpor,
combout => a_2_dup_239,
cout => nf0a5x7);
 
reg_reg_1 : apex20ke_lcell
-- Equation(s):
-- reg_1 = DFFE(state_var_1 & a_2_dup_239, GLOBAL(clk_acombout), , , nf0a5x2)
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "F000",
output_mode => "reg_only")
-- pragma translate_on
PORT MAP (
datac => state_var_1,
datad => a_2_dup_239,
clk => clk_acombout,
ena => nf0a5x2,
devclrn => devclrn,
devpor => devpor,
regout => reg_1);
 
ia9f8x2 : apex20ke_lcell
-- Equation(s):
-- latched_data_in_2 = enable_in_acombout & data_in_a2_a_acombout # !enable_in_acombout & latched_data_in_2
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "AFA0",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
dataa => data_in_a2_a_acombout,
datac => enable_in_acombout,
datad => latched_data_in_2,
devclrn => devclrn,
devpor => devpor,
combout => latched_data_in_2);
 
ia9f8x1 : apex20ke_lcell
-- Equation(s):
-- nf0a5x6 = latched_data_in_2 $ (!state_var_1 # !n544cx3)
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "C333",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
datab => latched_data_in_2,
datac => n544cx3,
datad => state_var_1,
devclrn => devclrn,
devpor => devpor,
combout => nf0a5x6);
 
if0a5x7 : apex20ke_lcell
-- Equation(s):
-- a_2_dup_238 = reg_2 $ nf0a5x6 $ !nf0a5x7
-- nf0a5x5 = CARRY(reg_2 & nf0a5x6 # !nf0a5x7 # !reg_2 & nf0a5x6 & !nf0a5x7)
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "arithmetic",
cin_used => "true",
packed_mode => "false",
lut_mask => "698E",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
dataa => reg_2,
datab => nf0a5x6,
cin => nf0a5x7,
devclrn => devclrn,
devpor => devpor,
combout => a_2_dup_238,
cout => nf0a5x5);
 
reg_reg_2 : apex20ke_lcell
-- Equation(s):
-- reg_2 = DFFE(state_var_1 & a_2_dup_238, GLOBAL(clk_acombout), , , nf0a5x2)
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "F000",
output_mode => "reg_only")
-- pragma translate_on
PORT MAP (
datac => state_var_1,
datad => a_2_dup_238,
clk => clk_acombout,
ena => nf0a5x2,
devclrn => devclrn,
devpor => devpor,
regout => reg_2);
 
data_in_ibuf_3 : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "input",
reg_source_mode => "none",
feedback_mode => "from_pin",
power_up => "low")
-- pragma translate_on
PORT MAP (
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
oe => GND,
ena => VCC,
padio => ww_data_in(3),
combout => data_in_a3_a_acombout);
 
ia9f5x2 : apex20ke_lcell
-- Equation(s):
-- latched_data_in_3 = enable_in_acombout & data_in_a3_a_acombout # !enable_in_acombout & latched_data_in_3
 
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "F5A0",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
dataa => enable_in_acombout,
datac => data_in_a3_a_acombout,
datad => latched_data_in_3,
devclrn => devclrn,
devpor => devpor,
combout => latched_data_in_3);
 
ia9f5x1 : apex20ke_lcell
-- Equation(s):
-- nf0a5x4 = latched_data_in_3 $ (!n544cx3 # !state_var_1)


-- pragma translate_off
===Koden til alu_tb.vhdl===
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "C30F",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
datab => state_var_1,
datac => latched_data_in_3,
datad => n544cx3,
devclrn => devclrn,
devpor => devpor,
combout => nf0a5x4);


if0a5x4 : apex20ke_lcell
-- Equation(s):
-- a_2 = reg_3 $ (nf0a5x5 $ nf0a5x4)
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
cin_used => "true",
packed_mode => "false",
lut_mask => "A55A",
output_mode => "comb_only")
-- pragma translate_on
PORT MAP (
dataa => reg_3,
datad => nf0a5x4,
cin => nf0a5x5,
devclrn => devclrn,
devpor => devpor,
combout => a_2);
reg_reg_3 : apex20ke_lcell
-- Equation(s):
-- reg_3 = DFFE(state_var_1 & a_2, GLOBAL(clk_acombout), , , nf0a5x2)
-- pragma translate_off
GENERIC MAP (
operation_mode => "normal",
packed_mode => "false",
lut_mask => "F000",
output_mode => "reg_only")
-- pragma translate_on
PORT MAP (
datac => state_var_1,
datad => a_2,
clk => clk_acombout,
ena => nf0a5x2,
devclrn => devclrn,
devpor => devpor,
regout => reg_3);
tri_data_out_0 : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "output",
reg_source_mode => "none",
feedback_mode => "none",
power_up => "low")
-- pragma translate_on
PORT MAP (
datain => reg_0,
oe => enable_acombout,
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
ena => VCC,
padio => ww_data_out(0));
tri_data_out_1 : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "output",
reg_source_mode => "none",
feedback_mode => "none",
power_up => "low")
-- pragma translate_on
PORT MAP (
datain => reg_1,
oe => enable_acombout,
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
ena => VCC,
padio => ww_data_out(1));
tri_data_out_2 : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "output",
reg_source_mode => "none",
feedback_mode => "none",
power_up => "low")
-- pragma translate_on
PORT MAP (
datain => reg_2,
oe => enable_acombout,
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
ena => VCC,
padio => ww_data_out(2));
tri_data_out_3 : apex20ke_io
-- pragma translate_off
GENERIC MAP (
operation_mode => "output",
reg_source_mode => "none",
feedback_mode => "none",
power_up => "low")
-- pragma translate_on
PORT MAP (
datain => reg_3,
oe => enable_acombout,
devclrn => devclrn,
devpor => devpor,
devoe => devoe,
ena => VCC,
padio => ww_data_out(3));
END structure;
</pre>
=Koden til alu_tb.vhdl=
<pre>
<pre>
library ieee;
library ieee;
Line 1,050: Line 176:


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, reset : std_logic;
  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 alu.
  --Deklarer komponenten alu_synt.
alu : entity add_sub_alu(algorithm)
  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);


--Kobler signala til den opprinnelige komponenten.
  --Klokkegenerator
port map (
  clock_gen : process
clk => clk,
    begin
rst => reset,
    clk <= '0', '1' after 50 ns;
enable_in => enable_in,
    wait for 100 ns;
start => start,
  end process clock_gen;
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.
  --Setter testvektorane.
alu_synt : entity add_sub_alu_synth(structure)
  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";


--Kobler signala til den synthiserte komponenten.
  --Test process for å samanlikne utsignala kvart nanosekund.
port map (
  test : process
clk => clk,
  begin
rst => reset,
  wait for 1 ns;
enable_in => enable_in,
  assert (data_out = data_out_synt)
start => start,
  report "Data ut er ulik"
enable => enable,
  severity Error;
do_add => do_add,
  end process test;
do_subtract => do_subtract,
do_hold => do_hold,
data_in => data_in,
data_out => data_out_synt);


--Klokkegenerator
end architecture struct;
clock_gen : process
</pre>
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;
[[Category:Mikroelektronikk]]
 
</pre>

Revision as of 13:44, 5 February 2021

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=1717@lisensserver:2100@lisensserver
source /eda/mentor/2019-20/scripts/PRECISION_2019.1.1_RHELx86.sh
precision


Vel 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;