BUDAPESTI MŰSZAKI ÉS GAZDASÁGTUDOMÁNYI EGYETEM VILLAMOSMÉRNÖKI ÉS INFORMATIKAI KAR MÉRÉSTECHNIKA ÉS INFORMÁCIÓS RENDSZEREK TANSZÉK HDL nyelvek: VHDL Fehér Béla Szántó Péter, Lazányi János, Raikovich Tamás BME MIT atórium
Strukturális elemek Entity: interfész megadás Architecture: viselkedés, funkcionalitás leírása Configuration: Architecture/Entity választás Package: függvények, típus deklarációk Library: lefordított VHDL objektumok gyűjteménye
Entity Interfész megadás a modul és a külvilág között entity hadder is port ( a, b: in std_logic; s, co: out std_logic ); end hadder;
Port típusok in Bemenet, csak olvasható out Kimenet, csak írható (!) buffer Kimenet, de olvasható, csak egy meghajtó jel inout Kétirányú port
Architecture A terv implementációt tartalmazó blokk Egy Entity tartalmazhat több Architecture-t Entity portok elérhetők az összes Architecture-ből Párhuzamosan végrehajtott utasításokat tartalmaz entity hadder is port ( a, b: in std_logic; ); end hadder; architecture rtl of hadder is... end rtl;
Strukturális leírás A VHDL támogatja a hierarchikus leírást, azaz a komponensek példányosítását Komponens deklaráció Példányosítás (egyedi névvel) Port hozzárendelés név szerint sorrend szerint
Komponens deklaráció Példányosítani kívánt komponensek deklarációja architecture rtl of adder is component hadder port ( a, b: in std_logic; s, co: out std_logic ); end component;
Példányosítás (1) port(a, b, ci : in std_logic; so, co : out std_logic); architecture struct of adder is --komponens deklaráció signal c0, c1, s0 : std_logic; hadder_0: hadder port map(a, b, s0, c0); hader_1: hadder port map(s0, c0, so, c1); or_0: or2 port map(c0, c1, co);
Példányosítás (2) port(a, b, ci : in std_logic; so, co : out std_logic); architecture struct of adder is --komponens deklaráció signal c0, c1, s0 : std_logic; hadder_0: hadder port map(a=>a, b=>b, s=>s0, co=>c0); hader_1: hadder port map(a=>s0, b=>c0, s=>so, co=>c1); or_0: or2 port map(a=>c0, b=>c1, o=>co);
Példányosítás (3) port(a, b, ci : in std_logic; so, co : out std_logic); architecture struct of adder is -- NINCS komponens deklaráció!!! signal c0, c1, s0 : std_logic; hadder_0: entity work.hadder(rtl) port map(a=>a, b=>b, s=>s0, co=>c0); hader_1: entity work.hadder(rtl) port map(a=>s0, b=>c0, s=>so, co=>c1); or_0: entity work.or2(rtl) port map(a=>c0, b=>c1, o=>co);
Package Package tartalmazhat: konstans deklarációk típus deklarációk komponensek szubrutinok Felhasználás Entity-ben: package USER_PACK is end USER_PACK; use work.user_pack.all;
Package példa library IEEE; use IEEE.STD_LOGIC_1164.all; package USER_PACK is function MIN (a: integer; b: integer) return integer; end USER_PACK; package body USER_PACK is function MIN( a: integer; b: integer) return integer is if (a<b) then return a; else return b; end if; end MIN; end USER_PACK;
Library Minden lefordított objektum Library-be kerül package, entity, architecture, configuration Saját objektumok: work library Standard library-k Felhasználás: library IEEE; use IEEE.std_logic_1164.all;
Megjegyzések, konstansok Megjegyzések -- egy soros Nincs több soros Konstansok 1 bites: 0, 1 Vektor Bináris: 00010010 Hexadecimális: x AB (a konstans és a változó szélessége ugyanaz!!) CONV_STD_LOGIC_VECTOR(konstans, bitszám)
Adattípusok Standard adattípusok boolean (true, false) bit (0, 1) integer (platform függő, min. 32 bit) real (lebegőpontos, nem szintetizálható) time Library-kben előre definiált adattípusok szintézisre: std_logic_1164 Saját adattípusok
Bit, integer Bit típus (csak 0, 1) signal sb : bit; signal sbv : bit_vector(3 downto 0); sb <= 0 ; sbv <= 0000 ; v. sbv <= x A ; Integer signal si : integer range 0 to 15; si <= 2; Szintézis után ugyanaz (lehet) az eredmény
Vektor változók Konkatenálás &: csak kifejezés jobb oldalán Csoportosítás (,,,): kifejezés mindkét oldalán Kiválasztás signal a2, b2, c2, d2: bit_vector(1 downto 0); signal a4, b4, c4: bit_vector(3 downto 0); a4 <= a2 & b2; (c2, d2) <= 0101 ; d2 <= b4(2 downto 1); c4 <= (0=> 1, others=> 0 );
Time típus Mértékegység: fs, ps, ns, us, ms, sec, min, hr Szimulációhoz, modellezéshez használható végrehajtás késleltetése fizikai késleltetések modellezése Szorozható és osztható (eredmény: time ): integer real
Time példa constant PERIOD : time := 5 ns; process wait for PERIOD; wait for 2*PERIOD; wait for 3.5*PERIOD; end process; CLK <= not CLK after PERIOD/2;
IEEE std_logic std_ulogic, std_ulogic_vector, std_logic, std_logic_vector értékek: ` U `, nem inicializált ` X `, ismeretlen ` 0 `, ` 1 `, ` Z `, nagy impedanciás ` W `, ismeretlen (gyenge meghajtás) ` L `, gyenge 0 ` H `, gyenge 1 ` - `, don`t care
std_logic/std_ulogic Resolved/Unresolved a <= 1 ; a <= b; Eredmény: std_logic: a = 1 std_ulogic: ERROR Elvileg, de szintézer függő! Szimuláció alapállapot: U (undefined) Ipari szabvány: std_logic
std_logic_arith (1) std_logic_arith package signed és unsigned datatípus signal a : signed(7 downto 0); NEM tud műveletet végezni std_logic_vector típuson c <= signed(a)*signed(b); std_logic_signed és std_logic_unsigned package std_logic_arith package kiterjesztése ugyanazokat a műveleteket ismeri, de std_logic típuson NEM használható egyszerre a kettő (egy file-ban) Történelmi hagyomány, NEM javasolt a használata Nem is igazán szabvány, IEEE megoldás hiányában a Synopsys kezdte el használni
std_logic_arith (2) library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_signed.all; entity mul is port ( op_a, op_b : in std_logic_vector(17 downto 0); res : out std_logic_vector(35 downto 0) ); end mul; architecture rtl of mul is res <= op_a * op_b; end mul;
IEEE.NUMERIC_STD (1) IEEE.NUMERIC_STD package signed és unsigned datatípus signal a : signed(7 downto 0); signal a : unsigned(7 downto 0); Operátorok Aritmetikai, logikai, shift RESIZE Típus konverziót meg kell adni std_logic_vector( signal név ): signed/unsigned std signed( signal név ): std signed 1 bit átadása st_logic-nak működik
IEEE.NUMERIC_STD (2) library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity mul is port ( op_a, op_b : in std_logic_vector(17 downto 0); res : out std_logic_vector(35 downto 0) ); end mul; architecture rtl of mul is signal res_s: signed(35 downto 0); res_s <= signed(op_a) * signed(op_b); res <= std_logic_vector(res_s); end mul;
Tömbök Előre definiált méretű type array0 is array (15 downto 0) of std_logic_vector(7 downto 0); signal m : array0; Deklarációkor állítható méret type array0 is array (natural range <>) of std_logic_vector(7 downto 0); signal m : array0(15 downto 0); Index típus lehet bármi, de tipikusan csak az integer szintetizálható
Record ~struktúra létrehozása type date_r is record year : std_logic_vector(15 downto 0); month : std_logic_vector( 3 downto 0); day : std_logic_vector( 4 downto 0); end record; signal date0, date1, date2 : date_r; date0 <= (x 0000, 0000, 00000 ); date1.year <= x 0000 ; date2 <= date1; record eleme lehet record
Egyedi típusok Tipikusan állapotgépekhez jobban olvasható kód limitált értékkészlet type STATE_TYPE is (RED, GREEN, BLUE); Értékadáskor, vizsgálatkor csak a definiált értékek használhatók Szintézerek tipikusan automatikus leképzést (definíció - bitminta) valósítanak meg De rögzíthető
Logikai operátorok Prioritás: not; and, or, nand, xor, xnor Vektor változókon bitenként hajtódnak végre Minden operandusnak ugyanolyan típusúnak és méretűnek kell lennie
Relációs operátorok <; <=; =; /=; >=; > Minden standard adattípusra definiált std_logic_vector std_logic_arith std_logic_signed/std_logic_unsigned package Előjeles változók!
Aritmetikai operátorok +; -; *; **; /; mod; abs; rem Előre definiált integer változókra std_logic_vector std_logic_arith std_logic_signed/std_logic_unsigned package NEM mindegyik szintetizálható tipikusan: +, -, *
Shift operátorok sll, srr logikai shiftelés sla, sra aritmetikai shiftelés az utolsó bit shiftelődik be általában megkötésekkel szintetizálható rol, ror rotálás a kieső bit shiftelődik be általában megkötésekkel szintetizálható
Konkurrens utasítások Architecture-ön belüli egyszerű értékadások Egymással és a process-ekkel párhuzamos kiértékelés Signal típusú változónak adhatnak értéket A kifejezés bal oldala azonnal kiértékelődik ha a jobb oldali változók megváltoznak
When Feltételes értékadás ÉRTÉK: konstans vagy signal When Else: ~IF - ELSE szerkezet CÉL <= ÉRTÉK_0 when FELTÉTEL_0 else ÉRTÉK_1 when FELTÉTEL_1 else ÉRTÉK_N; With When: ~CASE szerkezet with VÁLTOZÓ select CÉL <= ÉRTÉK_0 when KONSTANS_0, ÉRTÉK_1 when KONSTANS_1 KONSTANS_2, ÉRTÉK_N when others;
When (példa) res <= 001 when (din=1) else 010 when (din=2) else 011 when (din=4) else 100 when (din=8) else 000 ; with din select res <= 001 when 1, res <= 010 when 2, res <= 011 when 4, res <= 100 when 8, res <= 000 when others;
Process Architecture-ön belül használható A process-ek egymással (és a process-en kívüli értékadásokkal) párhuzamosan hajtódnak végre A végrehajtást triggereli érzékenységi lista wait szerkezet Írható változók: signal variable (lokális változó) (shared variable)
Process Érzékenységi lista: a process végrehajtása ennek teljesülésekor történik szintérzékeny, élérzékeny process(a,b) c <= a or b; end process; process(clk) if (clk event and clk= 1 ) then c <= a or b; end if; end process; process(clk) if rising_edge(clk) then c <= a or b; end if; end process;
Szekvenciális kifejezések If szerkezet (csak process-ben) if FELTÉTEL then elsif FELTÉTEL then else end if; Case szerkezet (csak process-ben) case KIFEJEZÉS is when ÉRTÉK_0 => when ÉRTÉK_1 => when others => end case;
For ciklus (1) Ciklus változó implicit deklarálva Ciklusok száma fix Szekvenciális végrehajtás, szintetizálható könnyű (túl) komplex logikát leírni!! Gondolkozz HW fejjel!! Pl.: 2:4 dekóder process(a) b <= 0000 ; for I in 0 to 3 loop if (a=i) then b(i) <= 1 ; end if; end loop; end process;
For ciklus (2) Hexa decimális átalakítás Osztás, modulo képzés nem szintetizálható dec_10 <= hex_num/10; dec_1 <= hex_num mod 10; Kis változószélességre: ROM, VHDL kóddal számolva process(hex_num) variable dec_v : std_logic_vector(3 downto 0); dec_v := (others=>'0'); for I in 1 to 15 loop if (hex_num = I) then dec_v := CONV_STD_LOGIC_VECTOR((I/10), 4); end if; dec_1 <= dec_v; end loop; end process;
While ciklus Feltételtől függő számú ciklus végrehajtás feltétel függhet változótól Tipikusan NEM szintetizálható Szimulációban hasznos while FELTÉTEL loop end loop;
Wait Wait felfüggeszti a process végrehajtását a feltétel teljesüléséig NEM használható érzékenységi listával együtt Feltétel: adott ideig (szimuláció) jel értékétől függően process(clk) if (clk event and clk= 1 ) then Q <= D; end if; end prcess; process Q <= D; wait until clk= 1 ; end process;
Variable Process-en belül lokális (kivéve shared) Azonnali értékadás (signal: a process lefutása után ) Értéke átadható signal-nak Értékét tartja a következő process futásig Pl.: túlcsordulás detekció: process(clk) variable ovl : std_logic; ovl := not accu(34); for IB in 35 to 46 loop ovl := ovl or not accu(ib); end loop; ovl := ovl and accu(47); accu_ovl_n <= ovl; end process;
Variable signal (1) process(clk) if rising_edge(clk) then d <= a + b; e <= d + c; end if; end process;
Variable signal (2) process(clk) variable d : std_logic_vector(7 downto 0); if rising_edge(clk) then d := a + b; e <= d + c; end if; end process;
Variable signal (3) process(clk) variable d : std_logic_vector(7 downto 0); if rising_edge(clk) then f <= d; d := a + b; -- ÉRTKADÁS SORREND!!! e <= d + c; end if; end process;
Paraméterezhető modulok (1) Entity deklaráció entity adder generic( DWIDTH : integer ); port( a, b : in std_logic_vector(dwidth-1 downto 0); c : out std_logic_vector(dwidth downto 0) ); end adder; architecture rtl of adder is c <= ( 0 & a) + ( 0 & b); end rtl;
Paraméterezhető modulok (2) Példányosítás adder_16: entity work.adder(rtl) generic map( DWIDTH => 16 ) port map( a => in_data0, b => in_data1, c => out_data0 );
Generate Architecture-en belül Struktúra ismétlése, tartalmazhat: Konkurrens értékadás Process Példányosítás
Generate példa Pl.: cím dekóder signal cs_int : std_logic_vector(15 downto 0); GEN_CS_INT: for ICS in 0 to 15 generate cs_int(ics) <= 1 when (cs= 1 and addr=ics) else 0 ; end generate; Eredmény: 16 db komparátor + 16 db ÉS kapu
Process Flip Flop Flip Flop: élérzékeny D tároló process (clk) if (clk event and clk= 1 ) then c <= a and b; end if; end process; process (clk) if rising_edge(clk) then c <= a and b; end if; clk a b D[0] Q[0] c end process;
Process Flip Flop Szinkron reset process(clk) if (clk event and clk= 1 ) then if (rst= 1 ) c <= 0 ; else c <= a and b; end if; end if; end process; Aszinkron reset process(clk, rst) if (rst= 1 ) c <= 1 ; elsif (clk event and clk= 1 ) then c <= a and b; end if; end process; clk a b D[0] R Q[0] c rst
Process Flip Flop Xilinx FPGA-kban a FF egy CLK bemenettel, két alaphelyzet beállító jellel és egy CE órajel engedélyező bemenettel rendelkezik. Szinkron vezérlés: Minden jel kiértékelése szinkron, ebben az esetben érvényesítés az órajel aktív élénél process(clk) if (clk event and clk= 1 ) then if (rst= 1 ) then c <= 0 ; elsif (set= 1 ) then c <= 1 ; else c <= a and b; end if; end process; clk set a b rst S D[0] Q[0] R c
Process Flip Flop Xilinx FPGA-kban a FF egy CLK bemenettel, két alaphelyzet beállító jellel és egy CE órajel engedélyező bemenettel rendelkezik. Aszinkron vezérlés: A vezérlőjelek változása azonnal érvényre jut, prioritás a felírás sorrendjében process(clk, rst, set) if (rst= 1 ) then c <= 0 ; elsif (set= 1 ) then c <= 1 ; elsif (clk event and clk= 1 ) then c <= a and b; end if; end process; clk set a b rst S D[0] Q[0] R c
Process kombinációs logikához Szemléletesen: A process eseményvezérelt A bemenőjelek bármely változása ilyen esemény Ennek hatására az eljárás lefut, a kimenet kiértékelődik process (a, b) c <= a and b; end process; a b c
Process latch Latch tároló természetesen szándékosan is generálható: Az engedélyező gate bemenet magas értéke mellett a tároló transzparens, míg a gate bemenet alacsony értéke mellett zárt, tartja értékét. process (g, a, b) if (g= 1 ) then c <= a and b; end if; end process; a b g D[0] C lat c Q[0] c
Process latch hiba A tipikus véletlen Latch Nem teljes if vagy case szerkezet Szintézer általában figyelmeztet process(sel,in0, in1, in2) case sel is when 00 => r <= in0; when 01 => r <= in1; when 10 => r <= in2; end case; end process; process(sel,in0, in1, in2) if (sel=0) then r <= in0; elsif (sel=1) then r <= in1; elsif (sel=2) then r <= in2; end if; end process;
Konkurrens értékadás latch hiba r <= in0 when (sel=0) else in1 when (sel=1) else in2 when (sel=2); with sel select r <= in0 when 0, r <= in1 when 1, r <= in2 when 2;
Process helyes Helyes kód process(sel,in0, in1, in2) case sel is when 00 => r <= in0; when 01 => r <= in1; when 10 => r <= in2; when others => r <= X ; end case; end process; process(sel,in0, in1, in2) if (sel=0) then r <= in0; elsif (sel=1) then r <= in1; else r <= in2; end if; end process;
Strukturális leírás Hierarchia felépítése: modulok összekapcsolása signal xor0 : std_logic; xor_inst0 entity work.xor_m(rtl) port map(i0=>in0, i1=>in1, o=>xor0); xor_inst1 entity work.xor_m(rtl) port map(i0=>xor0, i1=>in2, o=>r); in0 in1 xor_m i0 i1 o xor_inst0 xor_m i0 i1 o xor_inst1 r in2
Strukturális leírás - generate Hierarchia felépítése: modulok összekapcsolása in_bus0(0) <= in0; in_bus1 <= in2 & in1; GEN_INST: for I in 0 to 1 generate xor_inst entity work.xor_m(rtl) port map(i0=>in_bus0(i), i1=>in_bus1(i), o=>in_bus0(i+1)); end generate; r <= in_bus0(2); in0 in1 xor_m i0 i1 o xor_inst0 xor_m i0 i1 o xor_inst1 r in2
Példa MUX (1.) Különböző leírási stílusok a 2:1 multiplexerre process(sel,in0, in1) case sel is when 0 => r <= in0; when 1 => r <= in1; end case; end process; process(sel,in0, in1) if (sel=1) then r <= in1; else r <= in0; end if; end process; in_b <= in1 & in0; r <= in_b(conv_integer(sel)); r <= in1 when (sel= 1 ) else in0;
Példa MUX (2.) 4:1 multiplexer in0 [1] 0 in2 1 process(sel, in0, in1, in2, in3) case sel is when 00 => r <= in0; when 01 => r <= in1; when 10 => r <= in2; when 11 => r <= in3; end case; end process; sel[1:0] in1 [1] 0 1 I0 I1 O r [0] S in3
Példa 1 bites összeadó xor_0: entity work.xor3_m(rtl) port map (i0=>a, i1=>b, i2=>cin, o=>s); and_0: entity work.and2_m(rtl) port map (i0=>a, i1=>b, o=>a0); and_1: entity work.and2_m(rtl) port map (i0=>a, i1=>cin, o=>a1); and_2: entity work.and2_m(rtl) port map (i0=>b, i1=>cin, o=>a2); or_0: entity work.or3_m(rtl) port map (i0=>a0, i1=>a1, i2=>a2, o=>cout); s <= a xor b xor cin; cout <= (a and b) or (a and cin) or (b and cin); signal dbus : std_logic_vector(1 downto 0); dbus <= a + b + cin; s <= dbus(0); cout <= dbus(1);
Példa 4 bites összeadó signal cout : std_logic_vector(3 downto 0); add0: entity work.add1_full(rtl) port map (a=>a(0), b=>b(0), cin=> 0, cout=>cout(0), s=>s(0)); add1: entity work.add1_full(rtl) port map (a=>a(1), b=>b(1), cin=>cout(0), cout=>cout(1), s=>s(1)); add2: entity work.add1_full(rtl) port map (a=>a(2), b=>b(2), cin=>cout(1), cout=>cout(2), s=>s(2)); add3: entity work.add1_full(rtl) port map (a=>a(3), b=>b(3), cin=>cout(2), cout=>s(4), s=>s(3)); a,b : in std_logic_vector(3 downto 0); s : out std_logic_vector(4 downto 0); s <= ( 0 & a) + ( 0 & b);
Példa 4 bites összeadó, logikai op.
Példa 4 bites összeadó, + operátor
Példa 4 bites összeadó, + IBUF IBUF [3] I O b_ibuf[3] IBUF [3] [3] [3] LUT2_6 XORCY [3] OBUF [4] I O s_obuf[4] [4] [4:0] s[4:0] IBUF [2] I O b_ibuf[2] IBUF [2] [3] I O a_ibuf[3] LUT2_6 [3] s_axb_3 MUXCY_L s_s_3 MUXCY S OBUF [3] I O s_obuf[3] [3] [1] I b_ibuf[1] O [1] [2] I a_ibuf[2] O [2] [2] [2] s_axb_2 S [2] DI LO [3] DI CI O [4] [2] I OBUF O [2] b[3:0] [3:0] IBUF [0] I O b_ibuf[0] [0] IBUF [1] I O a_ibuf[1] [1] [1] [1] LUT2_6 s_axb_1 [1] DI MUXCY_L S LO CI s_cry_2 s_cry_3 XORCY [2] s_obuf[2] OBUF [1] I O [1] a[3:0] [3:0] IBUF [0] I O a_ibuf[0] [0] [0] [0] LUT2_6 s_axb_0 [0] [0] S [0] DI MUXCY_L LO CI s_cry_1 s_s_2 XORCY [1] s_obuf[1] OBUF [0] I O [0] 0 CI s_cry_0 s_s_1 s_obuf[0]
Példa: Shift regiszter 16 bites shift regiszter, A LUT4 SRL16 soros shiftregiszter kihasználására clk, sh, din: in std_logic; dout: out std_logic; signal shr: std_logic_vector(15 downto 0); process (clk) if (clk event and clk= 1 ) then if (sh= 1 ) then shr <= shr(14 downto 0) & din; end if; end if; dout <= shr(15);
Példa: Számláló Számláló minta leírás Szinkron, 8 bites Szinkron RESET Tölthető Engedélyezhető fel/le számláló Megj: A CE nagyobb prioritású, mint a töltés, ez nem tipikus clk, rst, ce, load, dir : in std_logic; din: in std_logic_vector(7 downto 0), dout: out std_logic_vector(7 downto 0); signal cntr_reg : std_logic_vector(7 downto 0); process (clk) if (clk event and clk= 1 ) then if (rst= 1 ) then cntr_reg <= (others=> 0 ); elsif (ce= 1 ) if (load= 1 ) then cntr_reg <= din; elsif (dir= 1 ) then cntr_reg <= cntr_reg 1; else cntr_reg <= cntr_reg + 1; end if; end if; end if; end process; dout <= cntr_reg;
FPGA primitívek Minden FPGA erőforrás közvetlenül is beépíthető CLB LUT 16x1 bit ROM, RAM LUT 16x1 bit shift regiszter MUXFi, MUXCY, XORCY Flip-flop primitívek BlokkRAM 16384 bit dual port memória + paritás Paraméterezhető adatszélesség Hardver szorzó (aszinkron, szinkron)
ROM (aszinkron!) LUT ROM process (addr) case (addr) is when 0000 => dout <= ÉRTÉK_0; when 0001 => dout <= ÉRTÉK_1; when 1111 => dout <= ÉRTÉK_15; end case; end process; Xilinx primitívek ROM16X1, ROM32x1,..
LUT RAM RAM: szinkron írás, aszinkron olvasás type ram_array is array (15 downto 0) of std_logic; signal memory : ram_array; process (clk) if (clk event and clk= 1 ) then if (we= 1 ) then memory(conv_integer(addr)) <= din; end if; end if; end process; dout <= memory(conv_integer(addr)); Xilinx primitívek Single port: RAM16X1S,.. Dual port: RAM16X1D,
Olvasás: aszinkron LUT RAM időzítés Számlálóval generált címzés CÍM 0 1 2 3 4 5 6 Írás: szinkron ADAT D0 D1 D2 D3 D4 D5 D6 Írás történik a bejelölt órajel felfutó éleknél CÍM ADAT 0 1 2 3 4 5 6 D0 D1 D2 D3 D4 D5 D6 WE
LUT shift regiszter Shift regiszter signal srl : std_logic_vector(15 downto 0); process (clk) if (clk event and clk= 1 ) then if (en= 1 ) then srl <= srl(14 downto 0) & din; end if; end if; end process; dout <= srl(conv_integer(addr)); NINCS reset bemenet Xilinx primitívek: SRLC16, SRLC16E
Shift regiszter tömb Maximum 16 mély 8 bit széles késleltető regiszter type srl_ar is array (15 downto 0) of std_logic_vector(7 downto 0); signal srl : srl_ar; process (clk) if (clk event and clk= 1 ) then if (en= 1 ) then srl(0) <= din; for IW in 1 to 15 loop srl(iw) <= srl(iw-1); end loop; end if; end if; end process; dout <= srl(conv_integer(addr));
BlockRAM Szinkron, dual port memória Méret: 16384 + 2048 (paritás) Adatszélesség: 1, 2, 4, 9, 18, 36 bit Portok: CLK, WE, EN, SSR (órajel, írás engedélyezés, engedélyezés, reset) ADDR, DI, DO (cím, adat be-, kimenet) Minden bemenet mintavételezett Kimenet az órajel felfutó élt követően kb. 2-3 ns Xilinx primitívek Single port: RAMB16_S1 RAMB16_S36 Dual port: RAMB16_S1_S1 RAMB16_S36_S36
Olvasás: szinkron BlockRAM időzítés Számlálóval generált címzés CÍM 0 1 2 3 4 5 6 Írás: szinkron ADAT D0 D1 D2 D3 D4 D5 D6 Írás történik a bejelölt órajel felfutó éleknél CÍM ADAT 0 1 2 3 4 5 6 D0 D1 D2 D3 D4 D5 D6 WE
Írás-olvasás ütközés Írás alatt a BlockRAM adatkimenete (írási port) Nem változik (NO_ CHANGE) A régi adat kerül a kimenetre (READ_FIRST) Az éppen beírt adat kerül a kimenetre (WRITE_FIRST) Dual-port konfiguráció esetében ha a két port címe megegyezik, és az egyiken írás történik, a másik adatkimenete érvénytelen (kivéve READ_FIRST mód) Mindkét porton azonos címre történő írás érvénytelenné teszi a beírt adatot
SP BlockRAM Read First type MT is array (511 downto 0) of std_logic_vector(35 downto 0); signal mem : MT; process (clk) if (clk'event and clk='1') then if (ce='1') then if (we='1') then memory(conv_integer(addr)) <= din; end if; if (rst='1') then dout <= (others=>'0'); else dout <= memory(conv_integer(addr)); end if; end if; end if; end process;
SP BlockRAM Write First type MT is array (511 downto 0) of std_logic_vector(35 downto 0); signal mem : MT; process (clk) if (clk'event and clk='1') then if (ce='1') then if (we='1') then memory(conv_integer(addr)) <= din; end if; if (rst='1') then dout <= (others=>'0'); elsif (we= 1 ) then dout <= din; else dout <= memory(conv_integer(addr)); end if; end if; end if; end process;
Azonos órajelek True Dual-port memória Egy process, általában szintetizálható A két port különböző órajelről jár két process-ben kell ugyanazt a (memóriát reprezentáló) változót írni Szintézer függő az implementáció signal típusú változó shared variable típus
Attribútumok Szintézer direktívák Attributum készlet szintézer függő Signal/variable, példány, entity, entity test is port( ); attribute opt_mode: string; attribute opt_mode of test: entity is "area"; end test; architecture rtl of test is attribute max_fanout : string; signal res : std_logic_vector(7 downto 0); attribute max_fanout of res : signal is 50 ; end rtl;
FSM_EXTRACT Attribútumok (1.) attribute FSM_EXTRACT : string; attribute FSM_EXTRACT of state: signal is TRUE ; FSM_STYLE attribute FSM_STYLE : string; attribute FSM_STYLE of state: signal is lut ; -- LUT, BRAM FSM_ENCODING attribute FSM_ENCODING : string; attribute FSM_ENCODING of state: signal is one-hot ; -- auto, one-hot, compact, sequential, gray, johnson, user type state_type is (IDLE, CFG_RAM_RD, PREPARE, REQ, TRANSFER, SLAVE_TERM, CFG_RAM_WR); signal state : state_type; attribute fsm_encoding : string; attribute fsm_encoding of state : signal is "user"; attribute enum_encoding : string; attribute enum_encoding of state_type : type is "0000001 0000010 0000100 0001000 0010000 0100000 1000000";
Attribútumok (2.) REGISTER_DUPLICATION attribute REGISTER_DUPLICATION : string; attribute REGISTER_DUPLICATION of test: entity is yes ; EQUIVALENT_REGISTER_REMOVAL attribute EQUIVALENT_REGISTER_REMOVAL : string; attribute EQUIVALENT_REGISTER_REMOVAL of test: entity is yes ; REGISTER_BALANCING attribute REGISTER_BALANCING : string; attribute REGISTER_BALANCING of test: entity is yes ; -- signal/entity; yes, no, forward, backward attribute MOVE_FIRST_STAGE : string; attribute MOVE_FIRST_STAGE of test: entity is yes ; attribute MOVE_LAST_STAGE : string; attribute MOVE_LAST_STAGE of test: entity is yes ;
Attribútumok (3.) USE_CLOCK_ENABLE attribute USE_CLOCK_ENABLE : string; attribute USE_CLOCK_ENABLE of data: signal is yes ; -- signal, entity, component, instance; auto, yes, no USE_SYNC_RESET attribute USE_SYNC_RESET : string; attribute USE_SYNC_RESET of test: entity is yes ; USE_SYNC_SET attribute USE_SYNC_SET : string; attribute USE_SYNC_SET of test: entity is yes ; Megj: setup time-ok: D: 0,27; CE: 0,47; RST: 0,78
Attribútumok (4.) MAX_FANOUT attribute MAX_FANOUT : string; attribute MAX_FANOUT of data: signal is 5 ; -- signal, entity; integer KEEP attribute KEEP : string; attribute KEEP of data: signal is TRUE ; IOB attribute IOB : string; attribute IOB of test: label is TRUE ; -- component, entity, label; auto, true, false
Attribútumok (5.) ROM_STYLE attribute ROM_STYLE : string; attribute ROM_STYLE of mem: signal is distributed ; -- signal, entity; auto, block, distributed --!! ROM_EXTRACT RAM_STYLE attribute RAM_STYLE : string; attribute RAM_STYLE of data: signal is block ; -- signal, entity; auto, block, distributed --!! RAM_EXTRACT
Attribútumok (6.) USE_CARRY_CHAIN attribute USE_CARRY_CHAIN : string; attribute USE_CARRY_CHAIN of add: signal is no OPT_MODE attribute OPT_MODE : string; attribute OPT_MODE of test: entity is area ; -- entity; area, speed Példa: PORTOK ); attribute opt_mode: string; attribute opt_mode of test: entity is "area"; end test;
RLOC attribute u_set : string; attribute u_set of XORCY_L_DW: label is ("SET" & str(num, 10)); attribute u_set of REG_OUT_DW: label is ("SET" & str(num, 10)); attribute rloc: string; attribute rloc of XORCY_L_DW : label is "X0Y0"; attribute rloc of REG_OUT_DW : label is "X0Y0"; muxcy_out(0) <= '0'; GEN_MUXCY: for I in 0 to DW generate mux_sel(i) <= (not op_a(i)) xor op_b(i); -- op_a!= op_b MUXCY_L_i : MUXCY_L port map ( LO => muxcy_out(i+1), CI => muxcy_out(i), DI => op_a(i), S => mux_sel(i) ); end generate; XORCY_L_DW: XORCY_L port map ( LO => sub_res(dw), CI => muxcy_out(dw+1), LI => mux_sel(dw) ); REG_OUT_DW: FDCE port map ( Q => res(dw), C => clk, CE => en, CLR => '0', D => sub_res(dw) );
Időzítések (UCF) Csoportok INST *cpu_if* TNM=FFS TNM_CPU_REGS; INST *filter* TNM=FFS TNM_FILTER_REGS; -- FFS, RAMS, LATCHES, CPUS, MULTS Explicit TIMESPEC "TS_FALSE1" = FROM "TNM_CPUREGS" TO TNM_FILTER_REGS 10 ns; False Path TIMESPEC "TS_FALSE1" = FROM "TNM_CPUREGS" TO TNM_FILTER_REGS TIG; Clock-domain NET "clk1" TNM_NET = "clk1"; NET "clk2" TNM_NET = "clk2"; TIMESPEC TS_clk1_to_clk2 = FROM clk1 TO clk2 10 ns;
Elhelyezés Csoport AREA_GROUP "AGROUP1" RANGE = SLICE_X6Y11:SLICE_X9Y6 ; GROUP: CLOSED, OPEN PLACE: CLOSED, OPEN Elemek hozzárendelése INST "RAM_CCNT" AREA_GROUP = "AGROUP1";
Összefoglalás Az FPGA erőforrások használata a HDL nyelvekből különböző módokon is elérhető Érdemes a magasabb szintű leírást használni Kevesebb munka, tömör leírás Egyértelmű tervezői szándék specifikáció Eszköz független leírás, könnyebben migrálható más eszközökre A speciális funkciók, egyedi beállítások szükségessé tehetik az alacsonyszintű technológiai primitívek használatát