HDL stands for Hardware Description Language.
Keywords: hardware, clock, architecture, signal, waveform, delay, oscilloscope, meta-stability.
Avoid using abs
operator since it may cause an overflow which won't happen if I use if
operator instead:
--don't do this: --f_diff_1 <= std_logic_vector(abs(signed(filter_array(4) - avg(1)))); --instead, do if: if (filter_array(4) > avg(1)) then f_diff_1 <= filter_array(4) - avg(1); else f_diff_1 <= avg(1) - filter_array(4); end if;
Every time I write arithmetical expression, I'm allowed to use a single operator (whatever it is: +, -, *). So if there is a need to calculate an expression of summ involving just 4 vectors I can not just write the following:
result <= v1 + v2 + v3 + v4;
instead, I should declare two more intermediate vectors which would keep a result of adding a pair of vectors. Check it out:
res_12 <= v1 + v2; res_34 <= v3 + v4; result <= res_12 + res_34;
which finally postpones the result value by 2 ticks (res_12 and res_34 — first tick, result — second tick).
Gosh... Now I realize how much I love C++ :) where I can easily write somewhat like the following without thinking how much time it is going to take to evaluate an expression:
filtered += WEIGHTS[FILTER_WIDTH - k - 1] * abs((pLine[col + k - FILTER_WIDTH/2] & 0x000000ff) - average);
HDL is all about getting the right value at the right time.
Waveform example — most common way of debugging (in HDL) |
It seems that every signal
can be overridden only in one process.
And if I write assignment operator affiliated with the signal
in two process
es, waveform shows undefined value — something like ?
or U
— shit, anyway.
That is why I call each process
in architechture
by a label connected with a signal
being changed in the process.
So if a signal
addr_A is changed in the process
I call it ADDRESS:
ADDRESS: process (Clock) begin if (State = S_Working) then if (Start = '1') then addr_A <= (others => '0'); addr_B <= "00000000001"; -- can't use the same address of A and B ports elsif (rising_edge(Clock)) then if (addr_A < line_len) then addr_A <= addr_A + 1; addr_B <= addr_B + 1; else addr_A <= (others => '0'); addr_B <= "00000000001"; -- can't use the same address of A and B ports end if; end if; end if; end process;
So I tend to write one process
per each signal being changed in a source file. However, a signal
can be read everywhere (asynchronously, in any process
) without affecting waveform :)
unisim.ramb16_s9_s9
library UNISIM; use UNISIM.vcomponents.all; component ramb16_s9_s9 port ( DOA: out std_logic_vector(7 downto 0); DOB: out std_logic_vector(7 downto 0); DOPA: out std_logic_vector(0 downto 0); DOPB: out std_logic_vector(0 downto 0); ADDRA: in std_logic_vector(10 downto 0); ADDRB: in std_logic_vector(10 downto 0); CLKA: in std_ulogic; CLKB: in std_ulogic; DIA: in std_logic_vector(7 downto 0); DIB: in std_logic_vector(7 downto 0); DIPA: in std_logic_vector(0 downto 0); DIPB: in std_logic_vector(0 downto 0); ENA: in std_ulogic; ENB: in std_ulogic; SSRA: in std_ulogic; SSRB: in std_ulogic; WEA: in std_ulogic; WEB: in std_ulogic); end component; for all: ramb16_s9_s9 use entity unisim.ramb16_s9_s9(ramb16_s9_s9_v);
HDL
in comparison to programming languageIt feels entirely new and unknown to write HDL
'programs'. There are several reasons:
CLOCK
timing idea (gotta clearly understand what's going on at every single tick).vhd
-filelibrary IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all;
To use ram16_s9_s9
memory component I need the following to be added into a header:
library UNISIM; use UNISIM.vcomponents.all;
Two more details:
(others => '0')
construction: a vector of an arbitrary length with each bit equal to zero.1
and 0
in constants bounded by quotes "10"
and we can use any hexadecimal digits provided we put X
in front of the constant X"DEADBEEF"
(== 3735928559).integer variable
to the std_logic_vector
DOut : out std_logic_vector(7 downto 0); variable ReadValue : integer; DOut <= CONV_STD_LOGIC_VECTOR(ReadValue, 32)(7 downto 0);
File operations: input file (reads integers, gives bytes) · output file (takes byte-vector, writes integers) · copy file (uses two preceding components and copies one file to another)
VHDL samples: SAMPLES.
Ivan Yurlagin