跳轉到內容

可程式設計邏輯/VHDL 程序

來自華夏公益教科書,開放的書籍,開放的世界

併發 vs. 順序評估

[編輯 | 編輯原始碼]

在 VHDL 中有兩種方式進行訊號賦值。訊號賦值可以透過併發語句或順序語句完成。併發語句中的賦值立即生效。在以下示例程式碼中,可以認為當 sFlag = '1' 時,sQ 將始終具有 sD 的值。否則它將為零。這將在 sD 或 sFlag 改變後的一個模擬“週期”內生效。

architecture rtl of some_entity
    signal sFlag: std_logic;
    signal sD: std_logic;
    signal sQ: std_logic;
begin
    with sFlag select
	  sQ <= sD  when '1',
		'0' when others;
end architecture some_entity;

使用程序允許我們編寫功能等效的程式碼,只是使用更自然的順序語句。在程序中,語句按順序執行,並且只有程序中所有賦值的最終結果才會生效。可以將程序視為執行的迷你“程式”,並在完成後應用其訊號賦值的結果。下面顯示了功能等效的順序程式碼

architecture rtl of some_entity
    signal sFlag: std_logic;
    signal sD: std_logic;
    signal sQ: std_logic;
begin
    process(sFlag, sD)
    begin
        sQ <= '0';
        if(sFlag = '1') then
            sQ <= sD;
        end if;
    end process;
end architecture some_entity;

當跟蹤此程式碼時,sQ 最初被賦值為零。然後,如果 sFlag = '1',sQ 被賦值為 sD。sQ 不會更新,直到整個程序執行完畢。由於整個程序在一個模擬“週期”內執行,因此最終結果與使用併發賦值的程式碼相同。

使用“wait”的程序

[編輯 | 編輯原始碼]

程序可以構建的一種方式是使用 wait 語句。wait 語句是一個 VHDL 結構,它告訴模擬器延遲執行多長時間或在什麼條件下繼續執行。以下是 wait 語句的示例

-- Tells the simulator to delay evaluation of the rest of the process for 10 ns;
wait for 10 ns;
-- Tells the simulator to delay evaluation of the rest of the process until a_flag contains the value of '1'
wait until a_flag = '1';

透過使用 wait 語句,模擬器知道何時停止執行程序並讓時間在模擬中前進。wait 語句在程序中使用,如以下示例所示

signal sClk: std_logic := '0';
constant cClkPeriod: time := 10 ns;
...

pClockSim: process
begin
  sClk <= not sClk;
  wait for cClkPeriod/2;
end process pClockSim;

在此示例中,訊號 sClk 被賦值為其當前值的相反值。然後,程序將等待由常量 cClkPeriod 指定時間的一半,之後將繼續執行。當程序結束時,評估將立即從程序開頭繼續。

使用 wait 語句的程序通常不可綜合,通常用於測試平臺。但是,它們通常直觀易用,允許快速構建測試平臺模組和生成用於檢查 VHDL 模組功能的其他測試訊號。

使用敏感度列表的程序

[編輯 | 編輯原始碼]

使用程序的另一種方式是使用敏感度列表

...
architecture rtl of some_entity is
  signal a_flag:       std_logic;
  signal another_flag: std_logic;
  ...
begin
  ...
  process(another_flag)
  begin
    a_flag <= another_flag;
  end process;
  ...
end architecture rtl;

敏感度列表 (another_flag) 是模擬器監視更改的訊號的逗號分隔列表。當這些訊號發生變化時,模擬器將評估程序並更新分配的訊號。在上面的示例中,程序將在訊號“another_flag”發生變化時執行。

併發語句作為程序

[編輯 | 編輯原始碼]

體系結構中的併發語句可以解釋為具有單個語句的程序。

...
architecture rtl of some_entity is
  signal a_flag:       std_logic;
  signal another_flag: std_logic;
  ...
begin
  ...
  process(another_flag)
  begin
    a_flag <= another_flag;
  end process;
  ...
end architecture rtl;

此程式碼可以縮寫為

...
architecture rtl of some_entity is
  signal a_flag:       std_logic;
  signal another_flag: std_logic;
  ...
begin
  ...
  a_flag <= another_flag;
  ...
end architecture rtl;

體系結構中的併發語句簡化了模組的語法,並允許使用更少的 VHDL 結構進行簡單的賦值。

程序的綜合

[編輯 | 編輯原始碼]

由於程序排程評估的概念無法直接轉換為物理邏輯,因此程序被解釋為表示組合邏輯塊或暫存器。綜合工具通常會從具有敏感度列表的程序中解釋組合邏輯塊。

architecture rtl of some_entity
    signal sFlag: std_logic;
    signal sD: std_logic;
    signal sQ: std_logic;
begin
    process(sFlag, sD)
    begin
        sQ <= '0';
        if(sFlag = '1') then
            sQ <= sD;
        end if;
    end process;
end architecture some_entity;

以下示例將被綜合為下面的多路複用器

從順序“if”語句綜合的多路複用器

除了組合邏輯之外,為了建立有用的數字邏輯電路,我們需要一種在硬體中建立暫存器的方法。可以使用類似於以下的程序模板建立暫存器(觸發器)

process(clk, reset)
begin
  if(reset = '1') then
    sQ <= '0';
  elsif rising_edge(clk) then
    sQ <= sQ_next;
  end if;
end process

綜合後,此程式碼將建立一個具有非同步高電平復位的暫存器,其“D”輸入為 sQ_next,輸出為 sQ。

用於描述組合邏輯的具有敏感度列表的程序和“暫存器模板”程序可以一起使用來描述 RTL 數位電路

signal clk: std_logic;
signal reset: std_logic;
signal sQ: std_logic;
signal sQ_next: std_logic;
...
-- Combinatorial logic that assigns a value to sQ_next
process(sQ)
begin
  sQ_next <= not sQ;
end process;

-- This process will create a register that will store the value of sQ_next for one
-- clock cycle
process(clk, reset)
begin
  if(reset = '1') then
    sQ <= '0';
  elsif rising_edge(clk) then
    sQ <= sQ_next;
  end if;
end process

同樣,RTL 電路的組合部分使用具有敏感度列表的程序來表達。然後使用上面的標準暫存器模板建立暫存器。

程序編碼技巧

[編輯 | 編輯原始碼]
  • 使用程序描述組合邏輯時,始終在程序頂部將所有分配的訊號“初始化”為預設值。
  • 儘管更短,但一位作者的經驗表明,將 RTL 邏輯分離成兩個程序(一個用於組合邏輯,一個用於暫存器)更不容易出錯。使用訊號如“sQ”用於暫存器的當前輸出和“sQ_next”用於組合邏輯的輸出和暫存器的下一個時鐘輸出有助於實現這一點。
華夏公益教科書