2012-12-10 66 views
5

我有這樣一個std_logic_vector:有索引這個載體可以明確地定義每個恆定如何索引std_logic_vector通過枚舉

cntrl_signals:out std_logic_vector(4 downto 0); 

的一種方式。

constant CLK_SIG:integer := 0; 
constant EN_SIG:integer := 1; 
constant FOO_SIG:integer := 2; 
constant BAR_SIG:integer := 3; 
constant BAZ_SIG:integer := 4; 

想法是使用這些來索引向量。

cntrl_signals <= (CLK_SIG=>1,EN_SIG=>1,others=>0); 

我的問題是如果有一個很好的速記方式來聲明索引(就像在C中的枚舉)?

回答

11

那麼你可以使用枚舉,最好的方法是聲明你自己的std_logic向量,由枚舉而不是整數索引。

但可能是更好的將是創紀錄的,而不是一個向量:

type Control_Signals is record 
    Clk : std_logic, 
    En : std_logic, 
    Foo : std_logic, 
    Bar : std_logic, 
    Baz : std_logic 
end record; 

編輯的詳細信息,如下評論:

平淡無奇使用std_logic_vector(和一般的VHDL的類型系統)的持有VHDL back ...

如果這是頂層實體,則std_logic_vector端口允許您在綜合設計中用頂層測試平臺替換綜合後網表。或者您可能必須遵守堅持std_logic_vector端口的陳舊的編碼風格指南。

但是在任何其他情況下,我會在包中聲明記錄,在整個設計中使用該包,並創建記錄類型的端口。當你確實需要std_logic_vectors時,這個包應該包括函數to_slvto_control_sigs(罕見的,如果你理解的話)。

這同樣適用於枚舉:

type Controls is (Clk, En, Foo, Bar, Baz); 
type Control_Signals is array(Controls) of std_logic; 
My_Bus_Ctrl : Control_Signals := (Clk => '1', En => '1', others => '0'); 
My_External_SLV_Port <= std_logic_vector(My_Bus_Ctrl); 

當然,枚舉比用C更強大一點;以及將它們用作數組索引類型,您可以遍歷它們。當你更新枚舉時,它可以讓循環保持一致!

通過枚舉索引的記錄或數組都可以工作;我更喜歡這個記錄更清潔,更符合面向對象的實踐。

在任何情況下,如果將它用於實體端口,它將變得更加有用。爲輸出總線信號(包括地址和數據)和輸入信號聲明一個記錄(或陣列!),因爲您不能在單個端口中混合方向......(FPGA中近期沒有雙向信號,因此不需要第三個端口)

現在,您的設計可以防止總線結構發生變化;更改地址寬度或添加中斷信號只會更改記錄聲明和任何實際用戶;沒有必要在整個層次中添加新的信號......

+0

第一個建議是什麼樣的?此外,cntrl_signals需要爲std_logic_vector,因爲它位於實體端口聲明中,並且對外可見。 – c0m4

+3

+1:'使用std_logic_vector(和VHDL的類型系統一般)的缺乏想象力正在把VHDL保存回去......' –

+0

哇,好信息!謝謝! – c0m4

1

布賴恩有最好的答案,但信息的另一位:

您可以創建一個這樣的枚舉:如果你有一個signal或類型的variable

type some_type is (clk, en, foo, bar, baz); 

,您可以使用'pos屬性將其轉換回數字:

variable v : some_type := foo; 

v'pos將返回整數2

+2

非常正確,答案越來越長!但是'pos和相反,some_type'val(2)返回foo可能非常有用。 –

+0

如果它合成爲一個熱點會發生什麼,會給你的元素或值的數量?也就是說,如果它是一熱的,那麼baz會給出4還是16? –

+0

'pos總是給你在類型數組中的位置(VHDL-2008的16.2.2節)。如果合成器將這些值映射到不同的表示,那麼當您詢問'pos'的值時,它將不得不提供邏輯來將其轉換回來。 –