Obsah

Export page to Open Document format

10 - Principy VHDL

Úvod

Myšlenka

Jazyk pro popis hardwaru (Hardware Description Language)

Algoritmus
Algoritmus je konečná uspořádaná množina úplně definovaných kroků pro vyřešení nějakého problému. Intuitivně algoritmem rozumíme postup, který nás dovede k řešení úlohy. Formálněji vyjádřeno se jedná o přesně definovanou konečnou posloupnost příkazů (kroků), jejichž prováděním pro každé přípustné vstupní hodnoty získáme po konečném počtu kroků odpovídající hodnoty výstupní.

algoritmus lze naimplementovat softwarově, hardwarově, jejich kombinace

Jsme-li schopni naimplementovat sekvenci, selekci, iteraci, je možné řešit každý algoritmicky řešitelný problém.

sekvence

selekce

iterace

výhody obvodové implementace

  • výrazně rychlejší, vyšší stupeň paralelismu, specifické komponenty (Fourierova transformace)
  • obvykle menší plocha čipu (pouze nezbytné součásti) a spotřeba energie

nevýhody obvodové implementace

  • vyšší výrobní náklady než u obecného procesoru
  • obtížnějsí návrh než software
  • často jednoúčelové

Způsoby popisu

  • strukturálně - popis pomocí komponent a zapojení (vodičů), bližší konečnému návrhu
  • behaviorální - popis konstrukcemi běžnými v prog. jazycích (cykly, procedury, funkce), vhodné pro simulaci

elementární komponenty jsou popsány behaviorálně (např. AND ⇒ nemá smysl popisovat jeho strukturu)

Proces syntézy

  • behaviorální syntéza - popis na nejvyšší úrovni (viz. behaviorální popis), výstupem popis na úrovni meziregistrových přenosů, nevýhodou je nemožnost ovlivnit výsledný popis (závislí na vývojových nástrojích)
  • RTL (Register Transfer Language) syntéza - popis pomocí registrů, čítačů, automatů, atd., oddělena datová (registry, sčítačky, …) a řídící část (FSM), výstupem popis pomocí hradel
  • logická syntéza - popis na úrovní hradel, sestaven z komponent cílové architektury propojených vodiči

Základní kontrukce jazyka

-- knihovny
library IEEE;
use IEEE.std_logic_1164.all;
 
-- popis rozhraní
entity FA is
  port (
    A, B, CI : in std_logic;
    S, COUT : out std_logic);
end FA;
 
-- realizace rozhraní
architecture RTL of FA is
begin
  S <= A xor B xor CI;
  COUT <= (A and B) or (A and CI) or (B and CI);
end RTL;

Popis kódu

  • uvedení knihoven, které se budou používat (na začátku kódu)
    • library - použivá knihovna
    • use - výběr dané komponenty z knihovny
  • popis rozhraní obvodu
    • entity jmeno is
    • port - deklarace signálů (in, out, inout; std_logic, std_logic_vector, …)
  • implementace rozhraní
    • architecture typ_popisu of jmeno is
    • uvnitř je popis, který probíhá paralélně (nezávisí na pořadí příkazů)
    • před begin deklarace signálů, komponent, atd. použitých v implementaci
  • přiřazení logické hodnoty signálu

Strukturální popis sčítačky

definice komponent

library IEEE;
use IEEE.std_logic_1164.all;
 
entity OR3 is
  port (
  A, B, C : in std_logic;
  Z : out std_logic);
end OR3;
 
architecture DF of OR3 is
begin
  Z <= A or B or C;
end DF;

+ další komponenty

popis obvodu z komponent

library IEEE;
use IEEE.std_logic_1164.all;
 
entity FA is
  port(
    A, B, CI : in std_logic;
    S, COUT : out std_logic);
end FA;
 
architecture LIB of FA is
  component EO
    port( A, B : in std_logic; Z : out std_logic);
  end component;
 
  component AN2
    port( A, B : in std_logic; Z : out std_logic);
  end component;
 
  component OR3
    port( A, B, C : in std_logic; Z : out std_logic);
  end component;
 
  signal S1, A1, A3, A2 : std_logic;
begin
  u0 : EO port map( A => A, B => B, Z => S1);
  u1 : EO port map( A => CI, B => S1, Z => S);
  u2 : AN2 port map( A => A, B => B, Z => A1);
  u3 : AN2 port map( A => A, B => CI, Z => A2);
  u4 : AN2 port map( A => B, B => CI, Z => A3);
  u5 : OR3 port map( A => A1, B => A2, C => A3, Z => COUT);
end LIB;

Popis kódu

  • component - include komponenty vytvořené v jiném souboru
  • port map - propojení portů jednotlivých komponent (mapování portů)
    • port_komponenty ⇒ signal definovaný pro architecture
    • u0 : E0 - pojmenovani_instance : komponenta

Behaviorální popis sčítačky

architecture BEH of FA is
begin
  p1 : PROCESS(A, B, CIN)
  BEGIN
    IF (A='1' AND B='1') OR (A='1' AND CIN='1') OR
    (B ='1' AND CIN='1') THEN
      COUT <= '1';
    ELSE
      COUT <= '0';
    END IF;
    S <= A XOR B XOR CIN;
  END PROCESS;
end BEH;

Popis kódu

  • PROCESS - pro popis chování obvodu a jeho části, příkazy se v něm vykonávají sekvenčně
    • může obsahovat proměnné, řídící struktury, přiřazení signálů
    • návěstí p1 je nepovinné, v závorkách seznam citlivých signálů - proces se provede, je-li aktivní jeden ze signálů

Test Bench

sada testů pro danou komponentu

-- testbench pro FA
library ieee;
use ieee.std_logic_1164.all;
 
entity tb_fa is
end tb_fa;
 
architecture arch_tb_fa of tb_fa is
  -- pomoci techto signalu se pripojime k testovane jednotce
  signal A, B, CI: std_logic;
  signal S, COUT : std_logic;
 
  -- tuto jednotku budeme testovat ("deklarace")
  component FA port (
    A, B, CI : in std_logic;
    S, COUT : out std_logic);
  end component;
begin
  -- "instance" testovane jednotky je pripojena pomoci zavedenych signalu
  UUT : FA
  port map (
    S => S, COUT => COUT);
 
  -- vlastni testovani zkousi vsechny kombinace na vstupech
  process
  begin
    A <= '0'; B <= '0'; CI <= '0';
    wait for 10 ns;
    A <= '0'; B <= '0'; CI <= '1';
    wait for 10 ns;
    A <= '0'; B <= '1'; CI <= '0';
    wait for 10 ns;
    A <= '0'; B <= '1'; CI <= '1';
    wait for 10 ns;
    A <= '1'; B <= '0'; CI <= '0';
    wait for 10 ns;
    A <= '1'; B <= '0'; CI <= '1';
    wait for 10 ns;
    A <= '1'; B <= '1'; CI <= '0';
    wait for 10 ns;
    A <= '1'; B <= '1'; CI <= '1';
    wait for 10 ns;
  end process;
end arch_tb_fa;

Průběh testů

Vybrané konstrukce

Knihovny

ieee.std_logic_1164.all

umožňuje vícehodnotové stavy

std_logic - jeden vodič
std_logic_vector - skupina vodičů (např. sběrnice)

ieee.std_logic_unsigned.all

definuje aritmetické operátory nad binárními vektory pro operace sčítání (+), odčítání (-) a násobení (*).

ieee.std_logic_arith.all

umožňuje pracovat s čísly se znaménkem i bez znaménka tak, že zavádí dva nové typy signed a unsigned. Binární hodnotu h datového typu std_logic_vector můžeme zkonvertovat na typ unsigned zápisem unsigned (h) a na typ signed zápisem signed(h).
Pomocí funkce conv_integer je možné provádět konverze mezi hodnotami typu integer a std_logic_vector, např.

signal c : std_logic_vector (3 downto 0);
signal ci : integer;
c <=1000;
ci <= conv_integer(signed(c)); -- v ci bude -8

Konstanty

CONSTANT constant_name : type_name [:= value];
CONSTANT PI : REAL := 3.14;
CONSTANT SPEED : INTEGER;

Proměnné

Určeny pro lokální uložení dat. Hodnota se mění ihned po přiřazení ( := )

VARIABLE variable_name : type_name [:= value];
VARIABLE opcode : STD_LOGIC_VECTOR (3 DOWNTO 0) := "0000";
VARIABLE freq : INTEGER;

Signály

Slouží pro komunikaci mezi VHDL moduly
přiřazena se zpožděním, po skončení všech částí procesů

SIGNAL signal_name : type_name [:= value];
signal din: STD_LOGIC_VECTOR (7 downto 0); -- 7 MSB, 0 LSB, pristup k jednotlivým bitům: din(4), ...
signal a: STD_LOGIC_VECTOR (0 to 2);       -- 0 MSB, 2 LSB
signal y: STD_LOGIC;

Porty entity

Datové typy

real, integer

constant pi: real := 3.14;
constant cislo: integer := 5;
-- soustavy: 123 (10), 8#730# (8), 16#FFFF# (16), 2#1001# (2)
-- pro std_logic_vector - "0111101" (2), X"76" (16), O"77" (8)

výčtový typ

-- Vytvoření nového výčtového typu muj_stav
TYPE muj_stav IS (reset, idle, rw, io);
-- Vytvoření proměnné typu muj_stav
signal stav: muj_stav;
-- Do proměnné lze přiřadit pouze hodnotu daného typu
stav <= reset; -- nelze psát, např. stav <= "00"

atributy

pro skalární typy, pomocí apostrofu

VARIABLE pom: integer;
 
pom`pred -- předchůdce
pom`succ -- následník
pom`high -- maximální hodnota v rozsahu
pom`low  -- minimální hodnota v rozsahu

signály obsahují specifické atributy, např. active, last_active, last_event, last_value atd.
pro clk: clk'event (změna hodnoty)

pole

type ram_typ is array(0 to 63) of STD_LOGIC_VECTOR(15 downto 0);
 
signal ram: ram_typ;
 
ram(0) <= x"1a0f";

Operátory

logické

and, or, nand, nor, xor, nxor, not

relační

=, /=, >, <, <=, >=

aritmetické
Binární: +, -, *, /, rem, mod, * * (mocnina)
Operátory rem i mod produkují zbytek po celočíselném dělení (výsledek a mod b má znaménko shodné s b, a rem b má znaménko shodné s a)
Unární: +, -, abs

Posuvy a rotace
Posuvy: SLL, SRL (logický), SLA, SRA (aritmetický – zachovává nejnižší bit)
Rotace: ROL (vlevo), ROR (vpravo)

Konkatenace

signal a, b: std_logic_vector (3 downto 0) := "0011";
signal c: std_logic_vector (7 downto 0) := "1111";
 
c <= a & b; -- konkatenace, v c bude „00111111“
 
a <= a(2 downto 0) & a(3); -- „0011“ -> “0110”, rotace
 
b(3 downto 2) <= “01”; -- práce s horními dvěma bity b
 
c <= (0’, ‘1’, others=>0); -- agregace, a <= 01000000

Priorita operátorů

Proces

process [(sensitivity_list)]
  [subprogram_decl|subprogram_body]
  [type_decl]
  [subtype_decl]
  [constant_decl]
  [variable_decl]
  [file_decl]
  [alias_decl]
  [attribute_decl]
  [attribute_spec]
  [use_clause]
begin
  [sequential_statements]
end process [proc_label];

V rámci procesu lze použít:

if

if condition then
  sequential_statements
{elsif condition then
  sequential_statements}
[else
  sequential_statements]
end if;

case

case expression is
  {when choices => sequential_statements}
end case;

volba musí být ve tvaru:

value => sequential_statements -- pro jednu hodnotu
value1 | value2 ... => sequential_statements -- pro více hodnot
value1 to value2 => sequential_statements -- pro určitý rozsah
others => sequential_statements -- pro ostatní

příklad

case BCD is
  when "0000" => LED := "1111110";
  when "0001" => LED := "1100000";
  when "0010" => LED := "1011011";
  when "0011" => LED := "1110011";
  when "0100" => LED := "1100101";
  when "0101" => LED := "0110111";
  when "0110" => LED := "0111111";
  when "0111" => LED := "1100010";
  when "1000" => LED := "1111111";
  when "1001" => LED := "1110111";
  when others => LED := "-------"; -- don't care
end case;

Loop

[label:] while condition loop
... sequence of statements ...
end loop label;
[label:] for loop_variable in range loop
... sequence of statements...
end loop label;

Ukončení současné iterace.

next [loop_label][when condition];

Opuštění cyklu:

exit [loop_label][when condition];

Assert

dovoluje v průběhu činnosti programu otestovat určitou kritickou podmínku a následně eventuelně ukončit činnost simulace.

assert condition
[report string_expr]
[severity failure|error|warning|note];
process (CLK, DIN) behavior of a D-FF
  variable X: integer;
  ...
begin
  ...
  assert (X > 3)
  report "setup violation"
  severity warning;
  ...
end process;

Wait

Dynamicky řídí spouštění a pozastavování procesů. Pokud je tento příkaz použit v rámci procesu, pak proces nesmí obsahovat citlivostní seznam.

wait
[on signal_name {, signal_name}]
[until condition]
[for time_expr];

Výběrové přiřazení signálu

with expression select
  signal_name <=expression when value{, expression when value};
with MYSEL select
  Z <= A when 15,
       B when 22,
       C when 28;

Podmíněné přiřazení signálu

signal_name <=expression when condition else
{expression when condition else}

Příklad:

Z <= A when (X > 3) else
     B when (X < 3) else
     C;

Příklady

Multiplexor

library ieee;
use ieee.std_logic_1164.all;
entity Mux is
  port( I3: in std_logic_vector(2 downto 0);
    I2: in std_logic_vector(2 downto 0);
    I1: in std_logic_vector(2 downto 0);
    I0: in std_logic_vector(2 downto 0);
    S: in std_logic_vector(1 downto 0);
    O: out std_logic_vector(2 downto 0)
  );
end Mux;
 
-- varianta 1
architecture behv1 of Mux is
begin
  process(I3,I2,I1,I0,S)
  begin
    -- příkaz case
    case S is
      when "00" => O <= I0;
      when "01" => O <= I1;
      when "10" => O <= I2;
      when "11" => O <= I3;
      when others => O <= "XXX";
    end case;
  end process;
end behv1;
 
-- varianta 2
architecture behv2 of Mux is
begin
  -- příkaz when.. else
  O <= I0 when S="00" else
       I1 when S="01" else
       I2 when S="10" else
       I3 when S="11" else
       "XXX";
end behv2;

Dekodér

library IEEE;
use IEEE.std_logic_1164.all;
entity dec3to8 is
  port (
    addr: in STD_LOGIC_VECTOR (2 downto 0);
    y: out STD_LOGIC_VECTOR (7 downto 0)
  );
end dec3to8;
 
architecture dec3to8 of dec3to8 is
begin
  with addr select
    y <= "10000000" when "111",
         "01000000" when "110",
         "00100000" when "101",
         "00010000" when "100",
         "00001000" when "011",
         "00000100" when "010",
         "00000010" when "001",
         "00000001" when others;
end dec3to8;

alternativně pomocí procesu:

process(addr)
begin
  y <= "00000000";
  case addr is
    when "000" => y <= "00000001";
    when "001" => y <= "00000010";
    when "010" => y <= "00000100";
    when "011" => y <= "00001000";
    when "100" => y <= "00010000";
    when "101" => y <= "00100000";
    when "110" => y <= "01000000";
    when "111" => y <= "10000000";
    when others => null;
  end case;
end process;

ALU

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
 
entity ALU is
  port( A: in std_logic_vector(1 downto 0);
    B: in std_logic_vector(1 downto 0);
    Sel: in std_logic_vector(1 downto 0);
    Res: out std_logic_vector(1 downto 0)
  );
end ALU;
 
architecture behv of ALU is
begin
  process(A,B,Sel)
  begin
    case Sel is
      when "00" => Res <= A + B;
      when "01" => Res <= A + (not B) + 1;
      when "10" => Res <= A and B;
      when "11" => Res <= A or B;
      when others => Res <= "XX";
    end case;
  end process;
end behv;

Další popisu obvodů lze nalézt zde od strany 25.

Potvrzení

10
Celé jménoOK!!!
vagy2011-03-31 14:13:05 
Jirka Hynek2011-04-13 16:50:31 
 2