文章目錄
- 使用function名稱作為“常量”
- numeric_std包集中使用乘法的注意項
- variable的使用
- 對于entity設置屬性的方法
- 在entity聲明中嵌入function的定義
- VHDL仿真
- 讀寫文件
- File declaration/File handing
- File reading
- File writing
- 小例子
- 使用函數
- 模塊中打印出調試信息
使用function名稱作為“常量”
測試代碼如下,function僅有名稱,沒有輸入,在function內部使用全局constant進行參數處理,后續代碼中可以直接使用function名稱作為常量
numeric_std包集中使用乘法的注意項
近日看到一個VHDL Coding Style中提示說,使用numeric_std包集時,不要直接將unsigned/signed數據與natural/integer類型的數據相乘。
今天看了一下numeric_std的源碼發現,如果直接直接將無符號數/有符號數與整數相乘的話,乘積很有可能會溢出。主要原因是由于,包集在實現整數與符號數相乘的時候,是先將整數轉成了無符號數/有符號數,之后再進行的乘法運算,而整數轉換后的位寬是與輸入的符號數的位寬相一致的,這就可能導致在整數進行類型轉換的過程中,出現數據溢出的情況。
這其實算不上bug,因為源碼中對此進行了明確說明,主要是在使用的時候需要注意規避這一點,不要讓符號數與整數直接相乘,可以手動進行位寬轉換后再做運算。相應的源碼如下圖所示,
variable的使用
在網上流傳的介紹VHDL Coding Style的文章中,一般是不建議在可綜合的代碼中使用變量的,這大概是由于variable具有局部作用域、賦值立即生效、仿真工具支持的不夠等幾個原因。但最近看到幾段VHDL代碼,大量使用variable,且使用方式非常規范。在一個prcoess中進行組合邏輯的設計,在另一個prcoess中使用寄存器進行時序邏輯的設計。在使用變量的process中,一般是如下的處理流程,
- Latch the current value
- 各類組合邏輯
- Combinatorial outputs before the reset
- Reset
- Register the variable for next clock cycle
- Registered Outputs
comb : process (localMac, r, rst, rxMaster, txSlave) isvariable v : RegType;variable i : natural;
begin-- Latch the current valuev := r;-- Reset the flagsv.rxSlave := AXI_STREAM_SLAVE_INIT_C;if txSlave.tReady = '1' thenv.txMaster.tValid := '0';v.txMaster.tLast := '0';v.txMaster.tUser := (others => '0');v.txMaster.tKeep := (others => '1');end if;-- State Machinecase r.state is-- end case;-- Combinatorial outputs before the resetrxSlave <= v.rxSlave;-- Resetif (rst = '1') thenv := REG_INIT_C;end if;-- Register the variable for next clock cyclerin <= v;-- Registered Outputs txMaster <= r.txMaster;end process comb;seq : process (clk) is
beginif rising_edge(clk) thenr <= rin after TPD_G;end if;
end process seq;
free_range_vhdl.pdf
11.4 Signals vs. Variables
對于entity設置屬性的方法
類似的,對于verilog的module設置attribute的方法如下,
在entity聲明中嵌入function的定義
VHDL仿真
有時寫vhdl時,使用了record、array等數據類型,此時使用verilog進行仿真時略有不便,用vhdl仿真倒是方便不少。
讀寫文件
File declaration/File handing
File reading
File writing
小例子
使用函數
library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;entity test is
end test;architecture Behavioral of test is-- convert a hex string to a std_logic_vectorfunction hex_string_to_std_logic_vector(inp: string; width : integer)return std_logic_vector isconstant strlen : integer := inp'LENGTH;variable result : std_logic_vector(width-1 downto 0);variable bitval : std_logic_vector((strlen*4)-1 downto 0);variable posn : integer;variable ch : character;variable vec : string(1 to strlen);beginvec := inp;-- default value is zeroresult := (others => '0');posn := (strlen*4)-1;for i in 1 to strlen loopch := vec(i);case ch iswhen '0' => bitval(posn downto posn-3) := "0000";when '1' => bitval(posn downto posn-3) := "0001";when '2' => bitval(posn downto posn-3) := "0010";when '3' => bitval(posn downto posn-3) := "0011";when '4' => bitval(posn downto posn-3) := "0100";when '5' => bitval(posn downto posn-3) := "0101";when '6' => bitval(posn downto posn-3) := "0110";when '7' => bitval(posn downto posn-3) := "0111";when '8' => bitval(posn downto posn-3) := "1000";when '9' => bitval(posn downto posn-3) := "1001";when 'A' | 'a' => bitval(posn downto posn-3) := "1010";when 'B' | 'b' => bitval(posn downto posn-3) := "1011";when 'C' | 'c' => bitval(posn downto posn-3) := "1100";when 'D' | 'd' => bitval(posn downto posn-3) := "1101";when 'E' | 'e' => bitval(posn downto posn-3) := "1110";when 'F' | 'f' => bitval(posn downto posn-3) := "1111";when others => bitval(posn downto posn-3) := "XXXX";-- synthesis translate_offASSERT falseREPORT "Invalid hex value" SEVERITY ERROR;-- synthesis translate_onend case;posn := posn - 4;end loop;if (width <= strlen*4) then-- bitval larger than desired widthresult := bitval(width-1 downto 0);else-- bitval smaller than desired width-- MSB is padded with zeros since default value for result is all 0sresult((strlen*4)-1 downto 0) := bitval;end if;return result;end;-- convert a binary string into a std_logic_vector (e.g., 0b10.1 = 101)function bin_string_to_std_logic_vector (inp : string)return std_logic_vectorisvariable pos : integer;variable vec : string(1 to inp'length);variable result : std_logic_vector(inp'length-1 downto 0);beginvec := inp;pos := inp'length-1;-- Set default valueresult := (others => '0');for i in 1 to vec'length loop-- synthesis translate_offif (pos < 0) and (vec(i) = '0' or vec(i) = '1' or vec(i) = 'X' or vec(i) = 'U') thenassert falsereport "Input string is larger than output std_logic_vector. Truncating output.";return result;end if;-- synthesis translate_onif vec(i) = '0' thenresult(pos) := '0';pos := pos - 1;end if;if vec(i) = '1' thenresult(pos) := '1';pos := pos - 1;end if;-- synthesis translate_offif (vec(i) = 'X' or vec(i) = 'U') thenresult(pos) := 'U';pos := pos - 1;end if;-- synthesis translate_onend loop;return result;end;signal data_1 : std_logic_vector(5 downto 0);signal data_2 : std_logic_vector(7 downto 0);begindata_1 <= bin_string_to_std_logic_vector("101001");data_2 <= hex_string_to_std_logic_vector("45",8);end Behavioral;
模塊中打印出調試信息
VHDL的仿真不如verilog方便,因此一般我都是用verilog對整個模塊做仿真。但有的時候,想在某個可綜合的VHDL模塊內部嵌入仿真調試信息,這樣在仿真時可以更直觀的觀測到運行結果。這在verilog中可以直接使用display和monitor函數,在VHDL中則需要借用report函數或者自己編寫函數實現。
library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;
library work;
-- use work.stdio_h.all;entity counter is
generic(SIM_VERBOSE : natural := 1
);
port ( clk : in std_logic;cnt : out std_logic_vector(15 downto 0)
);
end counter;architecture Behavioral of counter issignal cnt_i : unsigned(15 downto 0) := (others=>'0');begincnt <= std_logic_vector(cnt_i);process(clk)beginif rising_edge(clk) thencnt_i <= cnt_i + 1;-- if(SIM_VERBOSE=1) then
-- if(cnt_i = 20) then
-- printf("The time is %d ns\n",now);
-- printf("The cnt_i value is %u\n",std_logic_vector(cnt_i));
-- printf("-------------------------\n");
-- end if;
-- end if;end if;end process;-- synthesis translate_offgen_sim_info : if SIM_VERBOSE=1 generatebeginprocess(cnt_i)use work.stdio_h.all;beginif(cnt_i = 20) thenprintf("The time is %d ns\n",now);printf("The cnt_i value is %u\n",std_logic_vector(cnt_i)); printf("-------------------------------------------------------\n");printf("The cnt_i value is %s,the cnt_i part value is %u \n",std_logic_vector(cnt_i),std_logic_vector(cnt_i(3 downto 0)));printf("-------------------------------------------------------\n");end if;end process;end generate;-- synthesis translate_onend Behavioral;
Modelsim運行結果如下所示,