可程式設計邏輯/VHDL 程序
在 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 語句是一個 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;
以下示例將被綜合為下面的多路複用器

除了組合邏輯之外,為了建立有用的數字邏輯電路,我們需要一種在硬體中建立暫存器的方法。可以使用類似於以下的程序模板建立暫存器(觸發器)
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”用於組合邏輯的輸出和暫存器的下一個時鐘輸出有助於實現這一點。