編碼
此示例是一系列 3 中的第二個。如果你還沒有,請首先閱讀方框圖示例。
使用符合 10 條規則的框圖 (參見框圖示例),VHDL 編碼變得簡單明瞭:
- 大的周圍矩形成為 VHDL 實體,
- 內部箭頭成為 VHDL 訊號並在架構中宣告,
- 每個方塊都成為架構體中的同步過程,
- 每個圓形塊都成為體系結構體中的組合過程。
讓我們在時序電路的框圖中說明這一點:
電路的 VHDL 模型包括兩個編譯單元:
- 描述電路名稱及其介面的實體(埠名稱,方向和型別)。它是程式框圖的大周圍矩形的直接平移。假設資料是整數,並且
clock
使用 VHDL 型別bit
(僅兩個值:'0'
和'1'
),我們的時序電路的實體可以是:
entity sequential_circuit is
port(
Data_in: in integer;
Clock: in bit;
Data_out: out integer
);
end entity sequential_circuit;
- 描述電路內部的架構(它的作用)。這是宣告內部訊號的位置以及例項化所有程序的位置。我們的時序電路架構的骨架可以是:
architecture ten_rules of sequential_circuit is
signal Sum, Next_sum: integer;
begin
<...processes...>
end architecture ten_rules;
我們有三個過程新增到架構主體,一個同步(方塊)和兩個組合(圓塊)。
同步過程如下所示:
process(clock)
begin
if rising_edge(clock) then
o1 <= i1;
...
ox <= ix;
end if;
end process;
其中 i1, i2,..., ix
是所有即進入圖的相應的正方形塊和 o1, ..., ox
是箭頭所有的箭輸出圖表的對應的正方形塊。當然,除了訊號的名稱外,絕對不會改變任何東西。沒有。甚至不是一個角色。
因此,我們的例子的同步過程是:
process(clock)
begin
if rising_edge(clock) then
Sum <= Next_sum;
end if;
end process;
這可以非正式地翻譯成:如果 clock
發生變化,只有這樣,如果變化是上升沿('0'
到'1'
),則將訊號 Next_sum
的值賦給訊號 Sum
。
組合過程如下所示:
process(i1, i2,... , ix)
variable v1: <type_of_v1>;
...
variable vy: <type_of_vy>;
begin
v1 := <default_value_for_v1>;
...
vy := <default_value_for_vy>;
o1 <= <default_value_for_o1>;
...
oz <= <default_value_for_oz>;
<statements>
end process;
其中 i1, i2,..., in
是進入圖表相應圓塊的所有箭頭。一切都沒有了。我們不會忘記任何箭頭,我們不會在列表中新增任何其他內容。
v1, ..., vy
是我們可能需要簡化過程程式碼的變數。它們與任何其他指令式程式設計語言具有完全相同的角色:保留臨時值。在閱讀之前必須完全分配它們。如果我們不能保證這一點,那麼該過程將不再是組合的,因為它將對儲存器元素的型別進行建模,以保留從一個流程執行到下一個流程執行的某些變數的值。這就是該過程開始時 vi := <default_value_for_vi>
語句的原因。請注意,<default_value_for_vi>
必須是常量。如果不是,如果它們是表示式,我們可能會意外地在表示式中使用變數並在分配變數之前讀取變數。
o1, ..., om
是所有的箭輸出的圖表的相應的圓形塊。一切都沒有了。在流程執行期間,它們必須至少分配一次。由於 VHDL 控制結構(if
,case
……)可以非常容易地防止輸出訊號被分配,我們強烈建議在過程開始時無條件地為它們分配恆定值 <default_value_for_oi>
。這樣,即使 if
語句遮蔽了訊號分配,它也會收到一個值。
除了變數的名稱(如果有的話),輸入的名稱,輸出的名稱,<default_value_for_..>
常量和 <statements>
的值之外,絕對不能將任何內容更改為此 VHDL 框架。千萬不能忘了一個預設值分配,如果你做的合成將推斷不必要的儲存元件(最有可能的鎖存器),結果不會是你最初想什麼。
在我們的示例時序電路中,組合加法器過程是:
process(Sum, Data_in)
begin
Next_sum <= 0;
Next_sum <= Sum + Data_in;
end process;
這可以非正式地翻譯成:如果 Sum
或 Data_in
(或兩者)改變將值 0 分配給訊號 Next_sum
然後再分配值 Sum + Data_in
。
由於第一個賦值(具有常量預設值 0
)緊接著是另一個覆蓋它的賦值,我們可以簡化:
process(Sum, Data_in)
begin
Next_sum <= Sum + Data_in;
end process;
第二個組合過程對應於我們在具有多個目標的輸出箭頭上新增的圓形塊,以符合 2008 之前的 VHDL 版本。其程式碼很簡單:
process(Sum)
begin
Data_out <= 0;
Data_out <= Sum;
end process;
出於與其他組合過程相同的原因,我們可以將其簡化為:
process(Sum)
begin
Data_out <= Sum;
end process;
時序電路的完整程式碼是:
-- File sequential_circuit.vhd
entity sequential_circuit is
port(
Data_in: in integer;
Clock: in bit;
Data_out: out integer
);
end entity sequential_circuit;
architecture ten_rules of sequential_circuit is
signal Sum, Next_sum: integer;
begin
process(clock)
begin
if rising_edge(clock) then
Sum <= Next_sum;
end if;
end process;
process(Sum, Data_in)
begin
Next_sum <= Sum + Data_in;
end process;
process(Sum)
begin
Data_out <= Sum;
end process;
end architecture ten_rules;
注意:我們可以按任何順序編寫這三個過程,它不會改變模擬或綜合中的最終結果。這是因為三個程序是併發語句,VHDL 將它們視為真正並行。