Synthese av VHDL - Oppdatert

From ift
Revision as of 13:16, 24 March 2016 by Ogr043 (talk | contribs)

Syntetiseringen av VHDL kode

Vi ønsker å syntisere koden for å lage beskrivelse av koden tilpasset en FPGA-chip. Vi skal først syntisere koden med Quartus. Deretter skal vi simulere denne koden og sammenligne med den opprinnelige koden uten timing-informasjon. Vi bruker en ALU som eksempel.

Det er viktig at vi bruker Quartus og ModelSim fra samme utgivelse om vi ikke ønsker å kompilere våre egne simuleringsbibliotek. Du kan installere Quartus og ModelSim gratis og bruke lisens-server på UiB sitt nettverk. Vi bruker Quartus Prime 15.1 og ModelSim 10.4b.

Quartus

Lag et nytt prosjekt, kall det add_sub_alu og velg en passende mappe. Velg empty project, og deretter legg til add_sub_alu.vhd. Velg en CycloneIV-chip. Vi valgte EP4CE115F29. Det er chipen på Terasic DE2-115. Pass på at add_sub_alu.vhd er valgt som top-level og trykk så Start Compilation (Ctrl-L). Dette gjør at Quartus går gjennom alle stegene for å produsere filene vi er ute etter. I simulation/modelsim/ finner vi nå add_sub_alu.vho og add_sub_alu_vhd.sdo. Vho-filen(VHDL Output File) er filen som inneholder nå det opprinnelige designet, men også mange nye moduler med cycloneive-prefix. Disse entitetene beskriver ressurser på den fysiske FPGA-chipen. Sdo-filen(Standard Delay Format Output File) inneholder detaljer om delay fra hver modul på chippen.

Modelsim

Start opp Modelsim, lag nytt prosjekt og legg til vhdl fila for designet add_sub_alu.vhd og testbenken alu_tb.vhd. Så legg vi til fila som Quartus generte i prosjektdir til simulation/modelsim/add_sub_alu.vho.

Den Quartus-genererte filen vil ha samme entitetsnavn som den opprinnelige, og vil derfor ikke kunne simuleres samtid. Vi endrer derfor den genererte filen til å ha entiteten 'add_sub_alu_synth' og architecturen 'structure' (i vårt tilfelle endret den seg til structure automatisk).

Vi kan nå kompilere filene våre og deretter simulere testbenken. I testbenken vår ser vi at vi har kalt den syntiserte entiteten alu_synt. Dette skal vi bruke nå.

Velg Start Simulation - deretter work og alu_tb. Se så på SDF-fanen. Legg til add_sub_alu_vhd.sdo generert av Quartus tidligere. Under apply to region må du skrive: /alu_tb/alu_synt

Dette er altså området vi ønsker at sdo-filen skal gi informasjon om. Trykk så OK.

add wave *


Simulering med timing

Konklusjon

Kode

Kode til add_sub_alu.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'EVENT AND clk = '1') 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'EVENT AND clk = '1') 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, 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;