VHDL-Synthese für Fortgeschrittene Ronald Hecht ronald.hecht@etechnik.uni-rostock.de

Preview:

Citation preview

VHDL-Synthese für Fortgeschrittene

Ronald Hechtronald.hecht@etechnik.uni-rostock.de

Motivation Synthese-Tools werden immer

leistungsfähiger Abstraktionslevel steigern!

Lesbarkeit Wartbarkeit Design-Reuse

Robustheit des Codes erhöhen!

Überblick ieee.numeric_std und integer Packages Clock und Reset Technologie-Mapping Flexible Interfaces 2-Prozess-Methode

Das Paket numeric_std std_logic_arith/signed/unsigned sind

Synopsys Pakete Defacto Industrie Standard, aber nicht

standardisiert numeric_std ist IEEE 1076.3 Standard Strenger typisierte Operatoren Für neue Designs streng empfohlen

type UNSIGNED is array (NATURAL range <>) of STD_LOGIC;type SIGNED is array (NATURAL range <>) of STD_LOGIC;

Typumwandlungstd_logic_vector Es ist nicht definiert, ob std_logic_vector

signed oder unsigned ist Deshalb explizite Typumwandlung

variable slv : std_logic_vector(7 downto 0);variable u : unsigned(7 downto 0);variable s : signed(7 downto 0);

slv := std_logic_vector(u);slv := std_logic_vector(s);u := unsigned(slv);s := signed(slv);

Typumwandlunginteger Konvertierungsfunktionen to_... Bei Umwandlung von std_logic_vector

nach integer signed/unsigned beachten!

variable ui : integer range 0 to 255;variable si : integer range -128 to 127;

ui := to_integer(u);si := to_integer(s);ui := to_integer(unsigned(slv));

u := to_unsigned(ui, u'length);s := to_signed(si, s'length);slv := std_logic_vector(to_unsigned(ui, slv'length));

Operatoren in numeric_std Alle gängigen Integeroperationen

Schiebeoperationen

Operationen mit std_logic_vector etwas umständlich aber eindeutig

+ - * / mod rem = /= < > <= >=

shift_left shift_right rotate_left rotate_rightsll srl rol ror

u := u + 1;s := s + 1;slv := std_logic_vector(unsigned(slv) + 1);

integer und boolean versus std_logic_vector signed/unsigned, std_logic_vector oft

etwas umständlich Basieren auf neunwertigem std_logic

Langsam in der Simulation im Vergleich zu integer und boolean

Verwende nach Möglichkeit integer und boolean für Zähler, Adressen, Arithmetische Operationen Interne Statussignale

Synthetisierbar!

Integer für die Synthese Immer range angeben!

Alles optimal synthesefähig!

variable a, b, c : integer range 0 to 255;variable addr : integer range 0 to depth - 1;

c := a + b; c := a * b;

-- shift left/rightc := a * 4; c := a / 8;-- wrap counterc := (a + 1) mod 256;-- get some bitsc := (a / 4) mod 16;

-- access memoryvariable mem : mem_type;o := mem(addr);

-- binary to one-hoto := (others => '0');o(addr) := '1';

Verwende Variablen! Hohe Simulationsgeschwindigkeit Einfaches Debugging Auch im Waveform-Viewer

darstellbar Sequentielle Darstellung

Sofortige Aktualisierung Besser verständlich und wartbar

Sehr gute Syntheseergebnisse

Verwende Packages! Design-Reuse, Wartbarkeit Modularität, Abstraktion

package package_name is -- Deklaration von: -- Typen und Untertypen -- Konstanten, Aliase -- Signalen, Files -- Funktionen -- Prozeduren -- Attributen -- Komponenten -- Definition von: -- Konstanten -- Attributenend package_name;

package body package_name is -- Definition von vorher -- deklarierten Objekten: -- Funktionen -- Prozeduren -- Konstanten -- Deklaration/Definition -- von zusaetzlichen -- Objektenend package_name;

Beispiel CRC-Package Beschreibung der komb. Logik

-- CRC32 Generator: "CRC-32", Ethernet, AAL5 constant CRC32_GEN : std_logic_vector(31 downto 0) := "00000100110000010001110110110111";

-- CRC-CCITT Generator: HDLCconstant CRC_CCITT_GEN : std_logic_vector(15 downto 0) := "0001000000100001";

-- calculates next crc value, data vectorfunction next_crc ( crc : std_logic_vector; -- current CRC value data : std_logic_vector; -- incoming data gen : std_logic_vector) -- generator Polynom w/o x^n return std_logic_vector; begin ... ...end next_crc;

Weitere Anwendungen von Packages Kombinatorische Logik Interfaces, Komponenten Helper-Funktionen, Typumwandlung Design Konfiguration

Verhaltensmodelle Logging

rising_edge(clk) Zwei Möglichkeiten in VHDL für

flankensensitive Elemente

rising_edge() ist in der Simulation robuster

Kürzer und einfacher aufzuschreiben Verwende rising_edge()

clk'event and clk = '1'

FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN ISBEGIN RETURN (s'EVENT AND (To_X01(s) = '1') AND (To_X01(s'LAST_VALUE) = '0'));END;

rising_edge(clk)

Register mit und ohne Reset Problem: Einige Register werden

nicht zurückgesetzt

Gated Clock oder Clock Enable

regs_wrong: process (clk, rst)begin if rst = '0' then r1 <= '0'; elsif rising_edge(clk) then r1 <= x; r2 <= y; end if;end process regs_wrong;

x

clk

rst

y

r1

r2

Alternative synthesefähige Beschreibung des Resets Ausnutzung der Priorität durch

Beschreibungsreihenfolge Synchrones und asynchrones Reset

regs_as: process (clk, rst)begin if rising_edge(clk) then r1 <= x; r2 <= y; end if; if rst = '0' then r1 <= '0'; end if;end process regs_as;

regs_s: process (clk)begin if rising_edge(clk) then r1 <= x; r2 <= y; if rst = '0' then r1 <= '0'; end if; end if;end process regs_s;

Reset – Synchron oder Asynchron? Beides hat Vor- und Nachteile

Synchrone Resets häufig für FPGAs Asynchrone Resets oft für ASICs

Konfigurierbar? Externes Reset immer einsynchronisieren!

rst_sync: process (clk, pad_rst)begin if rising_edge(clk) then r <= '1' & r(r'high downto 1); end if; if pad_rst = '0' then r <= (others => '0'); end if;end process rst_sync;rst <= r(0);

pad_rst

'1'

clk

rst

Konfigurierbares Reset Konfigurations-Packageconstant USE_SYNC_RESET : boolean := TRUE;constant USE_ASYNC_RESET : boolean := NOT(USE_SYNC_RESET);

function sync_reset(rst : std_logic) return boolean isbegin if (USE_SYNC_RESET) then return (rst = '0'); else return false; end if;end;

function async_reset(rst : std_logic) return boolean isbegin if (USE_ASYNC_RESET) then return (rst = '0'); else return false; end if;end;

Konfigurierbares Reset Verwendung der Reset-Funktionen Redundante Reset-Anweisungen

vermeidbar durch Prozedurreg: process (clk, rst)begin if rising_edge(clk) then q <= d; if sync_reset(rst) then q <= '0'; end if; end if; if async_reset(rst) then q <= '0'; end if;end process regs;

Technologie Mapping Schaltungen enthalten architektur-

spezifische Komponenten Pads RAMs, Registerfiles Spezielle Beschleunigende Hardware

Schlechte Portierbarkeit Lösung: Technologie-Wrapper für

diese Elemente

Technologie MappingDateien Wrapper in

tech_map Ausnutzung von

DesignhierarchiePackage tech_map

ipad opad iopad syncram ...

Package tech_virtex

virtex_ipad virtex_opad virtex_iopad virtex_syncram ...

Package tech_gen

gen_ipad gen_opad gen_iopad gen_syncram ...

Package tech_atc18

atc18_ipad atc18_opad atc18_iopad atc18_syncram ...

architecture str of xyz

ipad opad iopad

Technologie MappingVHDL-Implementierungpackage tech_map is

component inpad port (pad : in std_logic; q : out std_logic); end component; ...end tech_map;

entity inpad ...

architecture rtl of inpad isbegin ... ip0 : if TARGET_TECH = virtex generate ipx : virtex_inpad port map (q => q, pad => pad); end generate; ip4 : if TARGET_TECH = atc18 generate ipx : atc18_inpad port map (q => q, pad => pad); end generate; ...end rtl;

type target_tech_type is (gen, virtex, virtex2, apex, atc18, ...);

constant TARGET_TECH : target_tech_type := apex;

Flexible Interfaces Probleme bei großen Designs:

Entities haben viele Signale Änderung der Entities bedeutet

Modifikationen in vielen Dateien Schwierige Namensgebung Schlecht wartbar

Lösung: Definition flexibler Signaltypen mit Records

Flexible Interfaces – in/out Entity-in/out erzwingt zwei Datentypen Deklaration von name_in_type und

name_out_type

type mem_in_type is record data : mem_data_type; end record;

type mem_out_type is record address : mem_address_type; data : mem_data_type; data_tri : std_logic; csn : std_logic; oen : std_logic; writen : std_logic; end record;

-- Memory controllerentity mem_ctrl is port ( clk : in std_logic; rst : in std_logic; memi : in mem_in_type; memo : out mem_out_type -- noch weitere Signale -- Steuer- und -- Datenleitungen );end mem_ctrl;

Flexible Interfaces – inout? Pads können inout sein Bei Verwendung von „drive“-Signalen

kein inout-Typ notwendig

mem_ctrl_i: mem_ctrl port map ( clk => clk, rst => rst, memi => memi, memo => memo); data <= memo.data when memo.data_tri = '0' else (others => 'Z'); memi.data <= data;

-- Top Entity, Signale-- repraesentieren Padsentity top is port ( clk : in std_logic; rst : in std_logic; data : inout mem_data_type; address : out mem_address_type; csn : out std_logic; oen : out std_logic; writen : out std_logic -- noch weitere Signale );end top;

Flexible Interfaces Keine Records in den

Ports der Top-Entity Tristate-Buffer nur in der

Top-Entity Bei bidirektionalen On-

Chip-Bussen Tristate-Buffer in der Bus-Entity

On-Chip-Tristate aber stets vermeiden! Testbarkeit Geschwindigkeit

inout-Type nicht nötig

Top-EntitySub-Entity

buso

busibuso.data_tri

buso.data

busi.data

Bus-Entitybus1o

bus1i bus1o.data_tri

bus1o.data

bus1i.data

bus2o

bus2i bus2o.data_tri

bus2o.data

bus2i.data

Flexible InterfacesStrategien IPCore-Schnittstellen ähneln sich System, Steuer- und Statussignale,

RX und TX

AESDataSystem

ControlStatus

Ethernet MACSystem

ControlStatus

PHYInterface

CPU InterfaceController

CPU

EthernetControl

AESControl

SDRAMController

SDRAM

ControlStatus

System

SDRAMControl

Flexible Interfaces – Tipps Takt und Reset nicht in Records Hierarchische Recordsentity hdlc_layer is

port ( clk : in std_logic; rst : in std_logic; rx_clk : in std_logic; tx_clk : in std_logic; ctrli : in hdlc_ctrl_in_type; ctrlo : out hdlc_ctrl_out_type; clienti : in hdlc_client_in_type; cliento : out hdlc_client_out_type; hdlci : in hdlc_in_type; hdlco : out hdlc_out_type);

end hdlc_layer;

type hdlc_client_in_type is record rx : hdlc_client_rx_in_type; tx : hdlc_client_tx_in_type; end record;

type hdlc_client_out_type is record rx : hdlc_client_rx_out_type; tx : hdlc_client_tx_out_type; end record;

Flexible InterfacesVorteile Wenige Signale in der Entity und in

Sensitivity-Listen Einfaches Hinzufügen von Ports Einfaches route-through Gute Wartbarkeit Hoher Abstraktionsgrad Hierarchische Schnittstellen

Abstraktion digitaler Logik Synchrones Design (Modul) besteht aus:

Kombinatorischer Logik Registern (Flip-Flops, Speicher)

Register an den Ausgängen oder nicht? Moore/Mealy haben im Normalfall keine

Register am Ausgang

r

i

comb.logic

clk

in

registeredout

unregisteredout

register

rst

Nichtabgetaktete Ausgänge Problematische Timinganalyse Kombinatorische Schleifen möglich Undefinierte Eingangssignallaufzeit

für angeschlossene Module Glitches Vorsicht,

Probleme!

Abgetaktete Ausgänge! Am Ausgang nach Möglichkeit

immer Register

Ausnahme: Single-Cycle Handshake req mit Register ack ohne Register

Traditionelles RTL-VHDL Viele kleine parallele Anweisungen

und Prozesse Viele Signale state/next_state-Signalnamen Unflexible Designpattern

Kombinatorische Logik Register, FSMs

„Schematic-VHDL“

Traditionelles RTL-VHDL Probleme Langsame Simulation, da viele Signale

und Prozesse Schwer und meist nur mit Hilfe eines

Schaltplans zu verstehen Schwieriges Debugging Algorithmus nicht erkennbar Fehleranfällig

Latches Mehrfachtreiber

2-Prozess Methode Modul besteht nur aus 2 Prozessen

Sequentieller Prozess r = rin Kombinatorischer Prozess rin = f(r, in)

Ausgänge outreg = g(r) und outunreg = h(r, in)

r

i

comb.process

rin = f(r, in)

clk

inregistered +unregisteredout

seq.processr = rin

rst

r

rin

2-Prozess Methode Zwei lokale Signale als Record für alle

Register Register Eingang rin Register Ausgang r

Algorithmus Kombinatorischer Prozess f(r, in) Lokale Variable v für den neuen Registerinhalt

rin = v Weitere lokale Variablen für kombinatorische

Ausgänge und Zwischenergebnisse

2-Prozess Methode VHDL Beispiel Neuer Typ für alle Register Zwei Signale und ein Prozess für alle

Register Einfaches Entfernen und Hinzufügen von

Registern

type state_type is (low, high);

type reg_type is record state : state_type; o : std_logic; end record;

signal r, rin : reg_type;

reg : process (clk, rst)begin if rising_edge(clk) then r <= rin; end if; if async_reset(rst) then reset(r); end if;end process reg;

2-Prozess Methodereset(r) Bei Registerdeklaration auch die

reset-Prozedur definieren Vermeidung von Redundanz

procedure reset ( signal r : inout reg_type) isbegin -- reset r.state <= low; r.o <= '0';end reset;

reg : process (clk, rst)begin if rising_edge(clk) then r <= rin; if sync_reset(rst) then reset(r); end if; end if; if async_reset(rst) then reset(r); end if;end process reg;

2-Prozess MethodeVHDL Beispiel Variable zur

Berechnung des neuen Register-wertes

Defaultzuweisung Algorithmus Zuweisung an den

Registereingang Treiben der Aus-

gänge

comb : process (r, i) variable v : reg_type;begin -- process comb -- Defaultzuweisung v := r; -- Ausgang meist '0' v.o := '0'; -- Zustandsmaschine case r.state is when low => if i = '1' then v.state := high; v.o := '1'; end if; when high => if i = '0' then v.state := low; end if; end case; -- Ausgaenge treiben rin <= v; o <= r.o;end process comb;

2-Prozess MethodeDebugging

2-Prozess MethodeVorteile Sequentielle Beschreibung des

Algorithmus Konsistenter Coding-Style Einfach zu verstehen Sehr gut wartbar Schnell in der Simulation Problemlose Synthese Kaum Fehleranfällig

2-Prozess Methode – Tipps Defaultwerte für v.xyz Variablen für Zwischenergebnisse und

kombinatorische Ausgänge Kombinatorische Ausgabe auch mit

o<=v.ack möglich Funktionen und Prozeduren für häufig

wiederkehrende Aufgaben Mut zum einfacher lesbaren Code! Beispiele: www.gaisler.com und LAPV5DL

Duplizieren von LogikSchleifen oder „generate“? Grenzen müssen zur Compile-Time

bekannt sein

Viele weitere Anwendungen Mut zu Schleifen!

for i in r.count'range loop v.count(i) := (r.count(i) + 1) mod 8; if v.count(i) = 0 then v.tick(i) := '1'; else v.tick(i) := '0'; end if;end loop;

Auswahl von Logikif-then oder „generate“? Bedingung muss zur Compile-Time

bekannt sein

if CALIBRATE then -- remove this logic when -- CALIBRATE = false v.period_counter := r.period_counter + 1; if rising then v.period := v.period_counter; v.period_counter := 0; end if;else -- remove this logic when -- CALIBRATE = true v.period := CLK_RATE / FREQUENCY;end if;

Zusammenfassung ieee.numeric_std verwenden Integer, Variablen, Packages Takt und Reset Technologie Mapping Flexible Interfaces 2-Prozess-Methode

Recommended