<noframes id="9ddpp">


<form id="9ddpp"><nobr id="9ddpp"><meter id="9ddpp"></meter></nobr></form><form id="9ddpp"><th id="9ddpp"><progress id="9ddpp"></progress></th></form>

<form id="9ddpp"><nobr id="9ddpp"></nobr></form><noframes id="9ddpp">

    fpga論壇|fpga設計論壇

     找回密碼
     我要注冊

    QQ登錄

    只需一步,快速開始

    搜索
    查看: 1569|回復: 5
    打印 上一主題 下一主題

    VHDL語法簡單總結

    [復制鏈接]
    跳轉到指定樓層
    1#
    fpga_feixiang 發表于 2018-6-28 15:38:36 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
    .用戶自定義數據類型

    使用關鍵字TYPE,例如:

    TYPE my_integer IS RANGE -32 TO 32;

    –用戶自定義的整數類型的子集

    TYPE student_grade IS RANGE 0 TO 100;

    –用戶自定義的自然數類型的子集

    TYPE state IS (idle, forward, backward, stop);

    –枚舉數據類型,常用于有限狀態機的狀態定義

    一般來說,枚舉類型的數據自動按順序依次編碼。

    2.子類型

    在原有已定義數據類型上加一些約束條件,可以定義該數據類型的子類型。VHDL不允許不同類型的數據直接進行操作運算,而某個數據類型的子類型則可以和原有類型數據直接進行操作運算。

    子類型定義使用SUBTYPE關鍵字。

    3.數組(ARRAY)

    ARRAY是將相同數據類型的數據集合在一起形成的一種新的數據類型。

    TYPE type_name IS ARRAY (specification) OF data_type;

    –定義新的數組類型語法結構

    SIGNAL signal_name: type_name [:= initial_value];

    –使用新的數組類型對SIGNAL,CONSTANT, VARIABLE進行聲明

    例如:

    TYPE delay_lines IS ARRAY (L-2 DOWNTO 0) OF SIGNED (W_IN-1 DOWNTO 0);

    –濾波器輸入延遲鏈類型定義

    TYPE coeffs IS ARRAY (L-1 DOWNTO 0) OF SIGNED (W_COEF-1 DOWNTO 0);

    –濾波器系數類型定義

    SIGNAL delay_regs: delay_lines;  – 信號延遲寄存器聲明

    CONSTANT coef: coeffs := (    ); –常量系數聲明并賦初值

    4.端口數組

    在定義電路的輸入/輸出端口時,有時需把端口定義為矢量陣列,而在ENTITY中不允許使用TYPE進行類型定義,所以必須在包集(PACKAGE)中根據端口的具體信號特征建立用戶自定義的數據類型,該數據類型可以供包括ENTITY在內的整個設計使用。

    —————————————PACKAGE———————————-

    library ieee;

    use ieee.std_logic_1164.all;

    ——————————————

    PACKAGE my_data_types IS

         TYPE vector_array IS ARRAY (natural range <>) OF STD_LOGIC_VECTOR(7 DOWNTO 0); –聲明8位的數組

    END my_data_types;

    ———————————–Main Code—————————————

    library ieee;

    use ieee.std_logic_1164.all;

    use work.my_data_types.all; –用戶自定義包集

    ——————————————————————

    ENTITY mux IS

    PORT (inp: IN vector_array(0 to 3);

    END mux;

    ——————————————————————————-

    5.有符號數和無符號數

    要使用SIGNED和UNSIGNED類型數據,必須在代碼開始部分聲明ieee庫中的包集std_logic_arith。它們支持算術運算但不支持邏輯運算。

    library ieee;

    use ieee.std_logic_1164.all;

    use ieee.std_logic_arith.all;

    ……

    SIGNAL a: IN SIGNED (7 DOWNTO 0);

    SIGNAL b: IN SIGNED (7 DOWNTO 0);

    SIGNAL x: IN SIGNED (7 DOWNTO 0);

    ……

    v <= a + b;

    w <= a AND b;  –非法(不支持邏輯運算)

    ——————————————————————————-

    STD_LOGIC_VECTOR類型的數據不能直接進行算術運算,只有聲明了std_logic_signed和std_logic_unsigned兩個包集后才可以像SIGNED和UNSIGNED類型的數據一樣進行算術運算。

    6.數據類型轉換

    在ieee庫的std_logic_arith包集中提供了許多數據類型轉換函數:

    1. conv_integer(p): 將數據類型為INTEGER,UNSIGNED,SIGNED,STD_ULOGIC或STD_LOGIC的操作數p轉換成INTEGER類型。不包含STD_LOGIC_VECTOR。

    2. conv_unsigned(p,b):將數據類型為INTEGER,UNSIGNED,SIGNED或STD_ULOGIC的操作數p轉換成位寬為b的UNSIGNED類型數據。

    3. conv_signed(p,b):將數據類型為INTEGER, UNSIGNED, SIGNED或STD_ULOGIC的操作數p轉換成位寬為b的SIGNED類型的數據。

    4. conv_std_logic_vector(p, b):將數據類型為INTEGER, UNSIGNED, SIGNED或STD_LOGIC的操作數p轉換成位寬為b的STD_LOGIC_VECTOR類型的數據。



    二、        運算操作符和屬性

    1.       運算操作符

    l  賦值運算符

    賦值運算符用來給信號、變量和常數賦值。

    <=    用于對SIGNAL類型賦值;

    :=     用于對VARIABLE,CONSTANT和GENERIC賦值,也可用于賦初始值;

    =>    用于對矢量中的某些位賦值,或對某些位之外的其他位賦值(常用OTHERS表示)。

    例:

    SIGNAL x: STD_LOGIC;

    VARIABLE y: STD_LOGIC_VECTOR(3 DOWNTO 0);  –最左邊的位是MSB

    SIGNAL w: STD_LOGIC_VECTOR(0 TO 7);  –最右邊的位是MSB

    x <= ‘1’;

    y := “0000”;

    w <= “1000_0000”;  – LSB位為1,其余位為0

    w <= (0 => ‘1’, OTHERS => ‘0’);  – LSB位是1, 其他位是0

    l  邏輯運算符

    操作數必須是BIT, STD_LOGIC或STD_ULOGIC類型的數據或者是這些數據類型的擴展,即BIT_VECTOR, STD_LOGIC_VECTOR,STD_ULOGIC_VECTOR。

    VHDL的邏輯運算符有以下幾種:(優先級遞減)

    &#376;   NOT —— 取反

    &#376;   AND —— 與

    &#376;   OR —— 或

    &#376;   NAND —— 與非

    &#376;   NOR —— 或非

    &#376;   XOR —— 異或

    l  算術運算符

    操作數可以是INTEGER, SIGNED, UNSIGNED, 如果聲明了std_logic_signed或std_logic_unsigned,可對STD_LOGIC_VECTOR類型的數據進行加法或減法運算。

    + —— 加

    -          —— 減

    * —— 乘

    / —— 除

    ** —— 指數運算

    MOD —— 取模

    REM —— 取余

    ABS —— 取絕對值

    加,減,乘是可以綜合成邏輯電路的;除法運算只在除數為2的n次冪時才能綜合,此時相當于對被除數右移n位;對于指數運算,只有當底數和指數都是靜態數值(常量或GENERIC參數)時才是可綜合的;對于MOD運算,結果的符號同第二個參數的符號相同,對于REM運算,結果的符號同第一個參數符號相同。

    l  關系運算符

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

    左右兩邊操作數的類型必須相同。

    l  移位操作符

    <左操作數> <移位操作符> <右操作數>

    其中左操作數必須是BIT_VECTOR類型的,右操作數必須是INTEGER類型的(可以為正數或負數)。

    VHDL中移位操作符有以下幾種:

    u  sll  邏輯左移  – 數據左移,右端補0;

    u  srl  邏輯右移  – 數據右移,左端補0;

    u  sla  算術左移  – 數據左移,同時復制最右端的位,填充在右端空出的位置;

    u  sra  算術右移  – 數據右移,同時復制最左端的位,填充在左端空出的位置;

    u  rol  循環邏輯左移 — 數據左移,從左端移出的位填充到右端空出的位置上;

    u  ror  循環邏輯右移 – 數據右移,從右端移出的位填充到左端空出的位置上。

    例:x <= “01001”,那么:

    y <= x sll 2;  – 邏輯左移2位,y<=”00100”

    y <= x sla 2;  – 算術左移2位,y<=”00111”

    y <= x srl 3;  – 邏輯右移3位,y<=”00001”

    y <= x sra 3;  – 算術右移3位,y<=”00001”

    y <= x rol 2;  – 循環左移2位,y<=”00101”

    y <= x srl -2;  –相當于邏輯左移2位

    l  并置運算符

    用于位的拼接,操作數可以是支持邏輯運算的任何數據類型。有以下兩種:

    2  &

    2  (, , , )

    與Verilog中{}的功能一樣。

    2.       屬性(ATTRIBUTE)

    l  數值類屬性

    數值類屬性用來得到數組、塊或一般數據的相關信息,例如可用來獲取數組的長度和數值范圍等。

    以下是VHDL中預定義的可綜合的數值類屬性:

    d’LOW             –返回數組索引的下限值

    d’HIGH            –返回數組索引的上限值

    d’LEFT             –返回數組索引的左邊界值

    d’RIGHT            –返回數組索引的右邊界值

    d’LENGTH       –返回矢量的長度值

    d’RANGE          –返回矢量的位寬范圍

    d’REVERSE_RANGE   –按相反的次序返回矢量的位寬范圍

    例:定義信號 SIGNAL d: STD_LOGIC_VECTOR(7 DOWNTO 0);

    則有:d’LOW = 0, d’HIGH = 7, d’LEFT = 7, d’RIGHT = 0, d’LENGTH = 8, d’RANGE = (7 DOWNTO 0), d’REVERSE_RANGE = (0 TO 7).

    l  信號類屬性

    對于信號s,有以下預定義的屬性(可綜合的):

    s’EVENT            若s的值發生變化,則返回布爾量TRUE,否則返回FALSE

    s’STABLE          若s保持穩定,則返回TRUE,否則返回FALSE

    例:clk的上升沿判斷

    IF (clk’EVENT AND clk = ‘1’)

    IF (NOT clk’STABLE AND clk = ‘1’)

    WAIT UNTIL (clk’EVENT AND clk = ‘1’)

    3.       通用屬性語句

    GENERIC語句提供了一種指定常規參數的方法,所指定的參數是靜態的,增加了代碼的可重用性,類似于Verilog中的parameter與defparam。GENERIC語句必須在ENTITY中進行聲明,由GENERIC語句指定的參數是全局的,不僅可在ENTITY內部使用,也可在后面的整個設計中使用。語法結構如下:

    GENERIC (parameter_name: parameter_type := parameter_value);

    用GENERIC語句指定多個參數:

    GENERIC (n: INTEGER := 8; vector: BIT_VECTOR := “0000_1111”);





    三、        并發代碼

    VHDL中并發描述語句有WHEN和GENERATE。除此之外,僅包含AND, NOT, +, *和sll等邏輯、算術運算操作符的賦值語句也是并發執行的。在BLOCK中的代碼也是并發執行的。

    從本質上講,VHDL代碼是并行執行的。只有PROCESS, FUNCTION, PROCEDURE內部的代碼才是順序執行的。但是當它們作為一個整體時,與其他模塊之間又是并行執行的。并發代碼稱為“數據流”代碼。

    通常我們只能用并發描述語句來實現組合邏輯電路,為了實現時序邏輯電路,必須使用順序描述語句。事實上,使用順序描述語句可以同時實現組合邏輯電路和時序邏輯電路。

    在并發代碼中可以使用以下各項:

    &#216;  運算操作符

    &#216;  WHEN語句(WHEN/ELSE或WITH/SELECT/WHEN)

    &#216;  GENERATE語句

    &#216;  BLOCK語句

    使用運算操作符

    運算類型

    運算操作符

    操作數類型

    邏輯運算

    NOT, AND, NAND,OR

    NOR, XOR, XNOR

    BIT, BIT_VECTOR, STD_LOGIC, STD_LOGIC_VECTOR

    STD_ULOGIC, STD_ULOGIC_VECTOR

    算術運算符

    +, —, *, /, **

    INTEGER, SIGNED, UNSIGNED

    比較運算符

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

    任意數據類型

    移位運算符

    sll, srl, sla, sra, rol, ror

    BIT_VECTOR

    并置運算符

    &,(, , ,)

    STD_LOGIC, STD_LOGIC_VECTOR, STD_ULOGIC

    STD_ULOGIC_VECTOR, SIGNED, UNSIGNED

    WHEN語句

    WHEN語句是一種基本的并發描述語句,有兩種形式:WHEN/ELSE和WITH/SELECT/WHEN。

    WHEN/ELSE語法結構:

    assignment WHEN condition ELSE

    assignment WHEN condition ELSE

    …;

    WITH/SELECT/WHEN語法結構

    WITH identifier SELECT

    assignment WHEN value,

    assignemnt WHEN value,

    …;

    當使用WITH/SELECT/WHEN時,必須對所有可能出現的條件給予考慮,使用關鍵字OTHERS,如果在某些條件出現時不需要進行任何操作,那應該使用UNAFFECTED。

    例:



    ————————————-with WHEN/ELSE——————————————-

    Output <= “000” WHEN (inp = ‘0’ OR reset = ‘1’) ELSE

                    “001” WHEN ctl = ‘1’ ELSE

                    “010”;

    ———————————–with WITH/SELECT/WHEN——————————–

    WITH control SELECT

           Output <= “000” WHEN reset,

                           “111” WHEN set,

                           UNAFFECTED WHEN OTHERS;

    對于WHEN語句,WHEN value的描述方式有以下幾種:

    WHEN value                           –針對單個值進行判斷

    WHEN value1 to value2          –針對取值范圍進行判斷

    WHEN value1 | value2 | …      –針對多個值進行判斷

    GENERATE語句

    GENERATE語句和順序描述語句中的LOOP語句一樣用于循環執行某項操作,通常與FOR一起使用。語法結構如下:

    label: FOR identifier IN range GENERATE

           (concurrent assignments)

    END GENERATE

    GENERATE語句還有另一種形式:IF/GENERATE,此處不允許使用ELSE。IF/GENERATE可以嵌套在FOR/GENERATE內部使用。反之亦然。

    Label1: FOR identifier IN range GENERATE

    ……

           Label2: IF condition GENERATE

                  (concurrent assignments)

           END GENERATE;

    ……
    END GENERATE;

    例:

    SIGNAL x: BIT_VECTOR(7 DOWNTO 0);

    SIGNAL y: BIT_VECTOR(15 DOWNTO 0);

    SIGNAL z: BIT_VECTOR(7 DOWNTO 0);

    ……
    G1: FOR i IN x’RANGE GENERATE

    z(i) <= x(i) AND y(i+8);

    END GENERATE;

    GENERATE中循環操作的上界和下界必須是靜態的,在使用過程中還要注意多值驅動問題。

    例:

    OK: FOR i IN 0 TO 7 GENERATE

           Output(i) <= ‘1’ WHEN (a(i) AND b(i)) = ‘1’ ELSE ‘0’;

    END GENERATE;

    —————————————————————————

    NotOK: FOR i IN 0 TO 7 GENERATE

           accum <= “1111_1111”       WHEN    (a(i) AND b(i)) = ‘1’ ELSE “0000_0000”;

    END GENERATE;

    —————————————————————-

    NotOK: FOR i IN 0 TO 7 GENERATE

           Accum <= accum + 1 WHEN x(i) = ‘1’;

    END GENERATE;

    —————————————————————-

    塊語句(BLOCK)

    VHDL中有兩種BLOCK:simple BLOCK和guarded BLOCK。

    n  Simple BLOCK

    Simple BLOCK僅僅是對原有代碼進行區域分割,增強整個代碼的可讀性和可維護性。語法結構如下:

    label:BLOCK

           [ declarative part]

    BEGIN

           (concurrent statement)

    END BLOCK label;

    —————————————————————————————————-

    ARCHITETURE example…

    BEGIN

           …

           block1: BLOCK

           BEGIN

                  …

           END BLOCK block1;

           …

           block2: BLOCK

           BEGIN

                  …

    END BLOCK block2;



    END example;

    —————————————————————————————–





    例:

    b1: BLOCK

           SIGNAL a: STD_LOGIC;

    BEGIN

           a <= input_sig WHEN ena = ‘1’ ELSE ‘z’;

    END BLOCK b1;

    ———————————————————————————————————————-

    無論是simple BLOCK還是guarded BLOCK,其內部都可以嵌套其他的BLOCK語句,相應的語法結構如下:

    label1: BLOCK

           [頂層BLOCK聲明部分]

    BEGIN

           [頂層BLOCK并發描述部分]

    label2: BLOCK

                  [嵌套BLOCK聲明部分]

    BEGIN

           [嵌套BLOCK并發描述部分]

           END BLOCK label2;

    [頂層BLOCK其他并發描述語句]

    END BLOCK label1;

    ———————————————————————————————————

    n  Guarded BLOCK

    多了一個衛式表達式,只有當衛式表達式為真時才能執行。語法結構如下:

    Label: BLOCK(衛式表達式)

           [聲明部分]

    BEGIN

           (衛式語句和其他并發描述語句)

    END BLOCK label;





    四、        順序代碼

    在PROCESS, FUNCTION, PROCEDURE內部的代碼都是順序執行的,這樣的語句包括IF,WAIT,CASE和LOOP。變量只能在順序代碼中使用,相對于信號而言,變量是局部的,所以它的值不能傳遞到PROCESS,FUNCTION和PROCEDURE的外部。

    1.      進程(PROCESS)

    進程內部經常使用IF,WAIT,CASE或LOOP語句。PROCESS具有敏感信號列表(sensitivity list),或者使用WAIT語句進行執行條件的判斷。PROCESS必須包含在主代碼段中,當敏感信號列表中的某個信號發生變化時(或者當WAIT語句的條件得到滿足時),PROCESS內部的代碼就順序執行一次。語法結構如下:

    [label: ] PROCESS (sensitivity list)

           [VARIABLE name type [range] [ := initial_value; ]]

    BEGIN

           (順序執行的代碼)

    END PROCESS [label];

    如果要在PROCESS內部使用變量,則必須在關鍵字BEGIN之前的變量聲明部分對其進行定義。變量的初始值是不可綜合的,只用于仿真。在設計同步電路時,要對某些信號邊沿的跳變進行監視(時鐘的上升沿或下降沿)。通常使用EVENT屬性來監視一個信號是否發生了變化。

    2.      信號和變量

    信號可在PACKAGE,ENTITY和ARCHITECTURE中聲明,而變量只能在一段順序描述代碼的內部聲明。因此,信號通常是全局的,變量通常是局部的。賦予變量的值是立刻生效的,在后續的代碼中,此變量將使用新的變量值,而信號的值通常只有在整個PROCESS執行完畢后才開始生效。

    3.      IF語句

    IF/ELSE語句在綜合時可能會產生不必要的優先級解碼電路。IF語句語法結構如下:

    IF conditions THEN assignments;

    ELSIF conditions THEN assignments;

    ELSE assignments;

    END IF;

    ————————————————————————————————

    例:

    IF (x < y) temp := “1111_1111”;

    ELSIF (x = y AND w = ‘0’) THEN temp := “1111_0000”;

    ELSE temp := (OTHERS => ‘0’);

    4.      WAIT語句

    如果在process中使用了WAIT語句,就不能使用敏感信號列表了。WAIT語句使用以下3種形式的語法結構:

    WAIT UNTIL signal_condition;

    WAIT ON signal1 [, signal2, ...];

    WAIT FOR time;

    WAIT UNTIL 后面只有一個信號條件表達式,更適合于實現同步電路(將時鐘的上升沿或下降沿作為條件),由于沒有敏感信號列表,所以它必須是process的第一條語句。當WAIT UNTIL語句的條件滿足是,process內部的代碼就執行一遍。

    –帶有同步復位的8bit寄存器

    process –沒有敏感信號列表

    begin

           wait until (clk’event and clk = ‘1′);

           if (rst = ‘1′) then

                  output <= (others => ‘0′);

           elsif (clk’event and clk = ‘1′) then

                  output <= input;

           end if;

    end process;

    WAIT ON 語句中可以出現多個信號,只要信號列表中的任何一個發生變化,process內的代碼就開始執行。

    –帶異步復位的8bit寄存器

    process

    begin

           wait on clk, rst;

           if (rst = ‘1′) then

                  output <= (others => ‘0′);

           elsif (clk’event and clk = ‘1′) then

                  output <= input;

           end if;

    end process;

    WAIT FOR 語句只能用于仿真。



    5.      CASE 語句

    CASE語句的語法結構如下:

    CASE 表達式 IS

           WHEN 條件表達式 => 順序執行語句;

           WHEN 條件表達式 => 順序執行語句;

           ……

    END CASE

    例:

    case control is

           when “00″      =>   x <= a; y <= b;

           when “01″      =>   x <= b; y <= c;

           when others =>     x <= “0000″; y <= “zzzz”;

    end case;

    關鍵詞OTHERS代表了所有未列出的可能情況,與Verilog中default相當。關鍵詞NULL表示沒有操作發生,如WHEN OTHERS => NULL.

    CASE語句允許在每個測試條件下執行多個賦值操作,WHEN語句只允許執行一個賦值操作。

    6.      LOOP語句

    LOOP語句用在需要多次重復執行時。語法結構有以下幾種:

    FOR/LOOP: 循環固定次數

    [label: ] FOR 循環變量 IN 范圍 LOOP

           (順序描述語句)

    END LOOP [label];

    WHILE/LOOP: 循環執行直到某個條件不再滿足

    [label: ] WHILE condition LOOP

           (順序描述語句)

    END LOOP [label];

    EXIT: 結束整個循環操作

    [label: ] EXIT  [label] [WHEN condition];

    NEXT: 跳出本次循環

    [label: ] NEXT [loop_label] [WHEN condition];



    Example: FOR/LOOP

    for i in 0 to 5 loop

           x(i) <= enable and w(i+2);

           y(0, i) <= w(i);

    end loop

    Example: WHILE/LOOP

    while (i < 10) loop — 0~9

           wait until clk’event and clk = ‘1′;

           (其他語句)

    end loop;



    for i in 0 to data’range loop

           case data(i) is

                  when ‘0′ =>  count := count + 1;

                  when others => null;

           end case;

    end loop;

    7.      CASE語句和IF語句的比較

    IF語句和CASE語句編寫的代碼在綜合、優化后最終生成的電路結構是一樣的。

    例:下面兩段代碼綜合后可以得到結構相同的多路復用器

    ————with IF————–

    if    (sel = “00″)  then x <= a;

    elsif (sel = “01″)  then x <= b;

    elsif (sel = “10″)  then x <= c;

    else x <= d;

    end if;

    ————-with case———–

    case sel is

           when “00″ =>     x <= a;

           when “01″ =>     x <= b;

           when “10″ =>     x <= c;

           when others =>  x <= d;

    end case;

    8.      CASE語句和WHEN語句的比較

    case語句和when語句的不同之處在于,when語句是并發執行的,case語句是順序實行的。

    –下面兩段代碼的功能等效

    ——-with when——————

    with sel select

           x <= a when “000″,

                   b when “001″,

                   c when “101″,

                   unaffected when others;

    ——-with case——————

    case sel is

           when “000″ => x <= a;

           when “001″ => x <= b;

           when “101″ => x <= c;

           when others => null;

    end case;

    9.      使用順序代碼設計組合邏輯電路

    原則1:確保在process中用到的所有輸入信號都出現在敏感信號列表中;

    原則2:電路的真值表必須在代碼中完整的反映出來。(否則會生成鎖存器)



    五、        信號和變量

    常量和信號是全局的,既可以用在順序執行的代碼中,也可用在并發執行的代碼中。變量是局部的,只能用在順序代碼中,并且它們的值是不能直接向外傳遞的。

    1.       常量

    CONSTANT name: type := value;

    2.       信號-signal

    VHDL中的signal代表的是邏輯電路中的“硬”連線,既可用于電路的輸入/輸出端口,也可用于電路內部各單元之間的連接。Entity的所有端口默認為signal。格式如下:

    SIGNAL name: type [range] [:= initial value];

    當信號用在順序描述語句中時,其值不是立刻更新的,信號值是在相應的進程、函數或過程完成之后才進行更新的。對信號賦初值的操作時不可綜合的。

    3.      變量

    變量僅用于局部電路的描述,只能在順序執行的代碼中使用,而且對它的賦值是立即生效的,所以新的值可在下一行代碼中立即使用。格式:

    VARIABLE name: type [range] [:= initial value];

    對變量的賦初值操作也是不可綜合的。

    4.      寄存器的數量

    當一個信號的賦值是以另一個信號的跳變為條件時,或者說當發生同步賦值時,該信號經過編譯后就會生成寄存器。如果一個變量是在一個信號跳變時被賦值的,并且該值最終又被賦給了另外的信號,則綜合后就會生成寄存器。如果一個信號在還沒有進行賦值操作時已被使用,那么也會在綜合時生成寄存器。

    process (clk)

    begin

           if (clk’event and clk = ‘1′) then

                  output1 <= temp;       – output1被寄存

                  output2 <= a;            – output2被寄存

           end if;

    end process;



    process (clk)

    begin

           if (clk’event and clk = ‘1′) then

                  output1 <= temp;       – output1被寄存

           end if;

           output2 <= a;     – output2未被寄存

    end process;



    process (clk)

           variable temp:     bit;

    begin

           if (clk’event and clk = ‘1′) then

                  temp <= a;

           end if;

           x <= temp;   – temp促使x被寄存

    end process;





    六、        包集元件

    1.      包集

    經常使用的代碼通常以component,function或procedure的形式編寫。這些代碼被添加到package中,并在最后編譯到目標library中。Package中還可以包含TYPE和CONSTANT的定義。語法格式如下:

    package package_name is

           (declaration)

    end package_name;

    package body package_name is

           (function and procedure description)

    end package_name;]

    Example6.1 簡單的程序包

    library ieee;

    use ieee.std_logic_1164.all;

    ———————————————————————-

    package my_package is

           type state is (st1, st2, st3, st4);

           type color is (red, green, blue);

           constant vec:       std_logic_vector(7 downto0) := “1111_1111″;

    end my_package;

    Example6.2 內部包含函數的package

    library ieee;

    use ieee.std_logic_1164.all;

    ———————————————————————-

    package my_package is

           type state is (st1, st2, st3, st4);

           type color is (red, green, blue);

           contant vec: std_logic_vector(7 downto 0) := “1111_1111″;

           function positive_edge(signal s: std_logic) return boolean;

    end my_package;

    ———————————————————————-

    package body my_package is

           function positive_edge(signal s: std_logic) return boolean is

           begin

                  return(s’event and s = ‘1′);

           end positive_edge;

    end my_package;

    為了在QUARTUS II中使用這些package,要在當前project目錄下新建一個文件夾,不妨起名為user_lib,把要編譯的package放進此文件夾中,然后在AssignmentsàSettingàLibrary中設置相應的目錄即可。在VHDL代碼中要使用這些package,要在主程序中加入如下代碼:

    use work.package_name.all;

    2.      元件component

    一個元件是一段結構完整的常用代碼,包括聲明,實體和結構體,使用component可以使代碼具有層次化的結構。

    元件聲明:

    component comp_name is

           port (

                  port_name1: signal_mode signal_type;

                  port_name2: signal_mode signal_type;

                  …

                  );

    end component;

    元件實例化:

    label: comp_name port map (port_list);

    元件的聲明可以放在主代碼中,即調用該元件的代碼;或者將元件的聲明放到package中,使用時在主代碼中增加一條USE語句即可,這樣避免了主代碼中每實例化一個元件就要聲明一次的麻煩。



    3.      端口映射

    在元件實例化過程中,有兩種方法實現元件端口的映射:位置映射和名稱映射。

    component inverter is

           port ( a: in    std_logic;

                   b:  out std_logic

                  );

    end component;



    U1: inverter port map(x, y);

    此處采用的是位置映射法,x對應a,y對應b。

    U1: inverter port map(a => x, b=> y);

    此處采用的是名稱映射法。對于不需要使用的端口可以斷開,只需使用關鍵字open即可,但是輸入端口不能指定為空連接。比如:

    U2: my_circuit port map(x => a, y => b, w => open, z => b);



    4.      GENERIC參數映射

    元件實例化時如果要通過GENERIC傳遞參數,則需進行GENERIC參數的映射。元件實例化的格式如下:

    label: comp_name generic map(param_list) port map(port_list);

    七、        函數和過程

    Function和procedure統稱為子程序,內部包含的都是順序描述的VHDL語言.

    八、        有限狀態機

    狀態機的設計包含兩個主要過程:狀態機建模和狀態的編碼。

    1.有限狀態機的建模

    有限狀態機通常使用CASE語句來建模,一般的模型由兩個進程組成,一個進程用來實現時序邏輯電路,另一個進程用來實現組合邏輯電路。

    模型的構建:

    (1)    分析設計目標,確定有限狀態機所需的狀態,并繪制狀態圖;

    (2)    建立VHDL實體,定義枚舉類型的數據類型;

    (3)    定義狀態變量,其數據類型為前面所定義的枚舉數據類型;例:

    TYPE STATE IS (STATE0, STATE1, STATE2, …);

    SIGNAL CR_STATE, NEXT_STATE: STATE;

    (4)    建立時序邏輯電路的實現進程;例:

    PROCESS (CLK,RESET)

    BEGIN

      IF RESET=’1’ THEN

             CR_STATE <= STATE0;

      ELSIF CLK’EVENT AND CLK=’1’ THEN

             CR_STATE <= NEXT_STATE;

    END IF;

    END PROCESS;

    (5)    使用CASE語句建立組合邏輯電路的實現進程。例:

    PROCESS(CR_STATE,INPUT)

    BEGIN

      CASE CR_STATE IS

             WHEN STATE0 =>

                                                IF INPUT = … THEN

                                                NEXT_STATE <= STATE1;

                                                END IF;

             WHEN STATE1 =>

                           …

             WHEN OHTERS => NEXT_STATE <= STATE0;

      END CASE;

    END PROCESS;







    2.狀態編碼

    狀態編碼包括二進制編碼、枚舉類型的編碼和一位有效編碼。利用一位有效編碼(One-hot encoding)可以創建更有效地在FPGA結構中實現的有限狀態機。每個狀態可以使用一個觸發器來創建狀態機,并且可以降低組合邏輯的寬度。



    有限狀態機的可能狀態由枚舉類型所定義,即:

    TYPE type_name IS(枚舉元素1, 枚舉元素2, …., 枚舉元素n);

    這個定義是通用的格式,時必須的。在該枚舉類型定義語句之后,就可以聲明信號為所定義的枚舉類型:

    TYPE STATE_TYPE IS(S1, S2, S3, S4, S5, S6, S7);

    SIGNAL CS,NS: STATE_TYPE;



    為了選擇有限狀態機的狀態編碼方式,需要指定狀態矢量。也可以通過綜合工具指定編碼方式。當在程序中指定編碼方式時,可以在枚舉類型定義語句后指定狀態矢量,例如,



    定義二進制編碼的狀態矢量的語句是:

    ATTRIBUTE ENUM_ENCODING: STRING;

    ATTRIBUTE ENUM_ENCODING OF STATE_TYPE:TYPE IS “001 010 011 100 101 110 111”;



    定義一位有效編碼的狀態矢量的語句為:

    ATTRIBUTE ENUM_ENCODING:STRING;

    ATTRIBUTE ENUM_ENCODING OF STATE_TYPE:TYPE IS ”0000001 0000010 0000100 0001000 0010000 0100000 1000000”;
    2#
    lixirui 發表于 2018-7-1 09:09:50 | 只看該作者
    VHDL語法簡單總結
    3#
    大鵬 發表于 2022-7-2 12:15:16 | 只看該作者
    VHDL語法簡單總結
    4#
    大鵬 發表于 2022-11-22 12:13:14 | 只看該作者
    VHDL語法簡單總結
    5#
    zxopenhl 發表于 2022-12-2 12:07:22 | 只看該作者
    VHDL語法簡單總結
    6#
    deckie 發表于 2022-12-4 23:07:21 | 只看該作者
    大家都不用VHDL,我還是翻完了。
    您需要登錄后才可以回帖 登錄 | 我要注冊

    本版積分規則

    關閉

    站長推薦上一條 /1 下一條

    QQ|小黑屋|手機版|Archiver|FPGA論壇 ( 京ICP備20003123號-1 )

    GMT+8, 2023-1-24 19:55 , Processed in 0.066294 second(s), 19 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回復 返回頂部 返回列表
    美女高潮黄又色高清视频app
    <noframes id="9ddpp">

    
    
    <form id="9ddpp"><nobr id="9ddpp"><meter id="9ddpp"></meter></nobr></form><form id="9ddpp"><th id="9ddpp"><progress id="9ddpp"></progress></th></form>

    <form id="9ddpp"><nobr id="9ddpp"></nobr></form><noframes id="9ddpp">