900 likes | 1.03k Views
VHDL Hardware Description Language. GUIDELINES. How to write HDL code:. GUIDELINES. How NOT to write HDL code:. Think Hardware NOT Software. Poorly written VHDL code will either be: Unsynthesizable Functionally incorrect Lead to poor performance/area/power results.
E N D
GUIDELINES • How to write HDL code:
GUIDELINES • How NOT to write HDL code:
Think Hardware NOT Software • Poorly written VHDL code will either be: • Unsynthesizable • Functionally incorrect • Lead to poor performance/area/power results
VHDL code basic structure • Entity (I/O and generic declaration) • Architecture structural (structure description) rtl (register transfer level description) behavioral (high-level description)
Entity declaration ENTITY entity_nameIS PORT (port_name_1 : port_type_1; port_name_2: port _type_2; . . . port_name_n: port_type_n); END entity_name;
Port types • PORT DIRECTION - IN -OUT -INOUT • SIGNAL TYPE • BIT • BIT_VECTOR(WIDTH -1 DOWNTO 0) • STD_LOGIC • STD_LOGIC_VECTOR(WIDTH -1 DOWNTO 0)
Entity declaration example (1/2) ENTITY and_gate IS PORT (i1: IN BIT; i2: IN BIT; O: OUT BIT); END and_gate;
Entity declaration example (2/2) Library ieee; Use ieee.std_logic_1164.all; ENTITY adder IS PORT (i1: IN STD_LOGIC_VECTOR(3 DOWNTO 0); i2: IN STD_LOGIC_VECTOR(3 DOWNTO 0); sum: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); carry: OUT STD_LOGIC); END adder;
Architecture declaration ARCHITECTURE architecture_name OF entity_name IS component declaration; signal declaration; BEGIN component instantiation sequential statements (processes) concurrent statements END [architecture_name];
Component declaration COMPONENT component_name PORT (port_name_1 : port_type_1; port_name_2: port _type_2; . . . port_name_n: port_type_n); END COMPONENT;
Component declaration example COMPONENT and_gate PORT (i1: IN BIT; i2: IN BIT; O: OUT BIT); END COMPONENT;
Signal declaration SIGNAL signal_name : signal_type; Examples SIGNAL data_bus: std_logic_vector(7 downto 0); SIGNAL clock: std_logic; SIGNAL count : bit_vector(5 downto 0);
Component instantiation (nominal) Label: component_name PORT MAP( port_name1 => signal_name1, port_name2 => signal_name2, … port_nameN => signal_nameN);
Example U_adder:adder PORT MAP(i1 => add1, i2 => add2, sum => s, carry => c);
Component instantiation (positional) Label: component_name PORT MAP( signal_name1, signal_name2, … signal_nameN);
Example U_adder:adder PORT MAP(add1, add2, s, c);
Structural description example (1/2) ENTITY gates IS PORT (i0,i1,i2,i3: std_logic; o: out std_logic); END gates; ARCHITECTURE str of gates IS COMPONENT and_gate PORT (i1,i2: in std_logic; o: out std_logic); END COMPONENT; SIGNAL s1,s2: std_logic; BEGIN
Structural description example (2/2) U_and1: and_gate PORT MAP(i1 => i0, i2 => i1, o => s1); U_and2: and_gate PORT MAP(i1 => i2, i2 => i3, o => s2); U_and3: and_gate PORT MAP(i1 => s1, i2 => s2, o => o); END;
VHDL operators • Arithmetic +, - , *, Synthesizable /, abs, rem, mod, **Non-synthesizable • Logical AND, OR, NOT, NAND, NOR, XOR, XNOR • Relational =, /=, <, >, <=, >=
Signal assignment signal_name <= signal_value; Examples signal a: std_logic; signal b: std_logic_vector(6 downto 0); signal c: std_logic_vector(3 downto 0); signal d: std_logic_vector(2 downto 0); CorrectIncorrect a <= ‘1’;a <= “01”; b <= “0101001”; b <= ‘0’; b(1) <= ‘0’; c <= (others => ‘0’); c <= ‘0000’; d <= (1 => ‘0’, others => ’1’); d <= b & c; b <= c & d; b(3 downto 1) <= d(1 downto 0); b(5 downto 3) <= d;
The “after” clause Used to assign signals with delay, modeling circuit behaviour • a <= d after 5 ns; -- 5 ns wire delay • b <= a and c after 20 ns; -- 20 ns gate delay Not synthesizable, is ignored by synthesis tools Useful in testbenches for creating input signal waveforms • clk <= not clk after 20 ns; -- 40 ns clock period • rst_n <= ‘0’, ‘1’ after 210 ns;
Concurrent statements –delta time b <= not a; (a = ‘1’, b = ‘1’, c= ‘0’) c <= a xor b; Time a b c 0 1 1 0 b <= not a; (a = ‘1’, b = ‘1’, c= ‘0’) c <= a xor b; Time a b c 0 1 1 0 δ 1 0 0 2δ 1 0 1 b <= not a; (a = ‘1’, b = ‘1’, c =‘0’) c <= a xor b; Time a b c 0 1 1 0 δ 1 0 0
Concurrent statements • Multiple driver error c <= a AND b; …. c <= d OR e;
Combinational circuit description ENTITY gates is port (a: in std_logic; d: out std_logic); end gates; Architecture rtl of gates is signal b: std_logic; begin b <= not a; d <= c xor b; --d<=c xor (not a); end rtl;
GENERATE STATEMENTS (concurrent only) • Used to generate multiple instances of a component in homogeneous architectures Z_Gen: For i in 0 to 7 generate z(i) <= x(i) AND y(i+8); end generate;
Generate example (1/2) ENTITY cell_array IS PORT (i: in std_logic_vector(63 downto 0); o: out std_logic_vector(63 downto 0) ); END ENTITY cell_array; ARCHITECTURE str OF cell_array IS COMPONENT cell PORT (i_north: in std_logic; i_west: in std_logic; i_east: in std_logic; o_east: out std_logic; o_west: out std_logic; o_south: out std_logic ); end component; signal west: std_logic_vector(62 downto 0); signal east: std_logic_vector(62 downto 0); BEGIN
U_cell_0: cell PORT MAP (i_north => i(0), i_west => '0', i_east => west(0), o_east => east(0), o_west => open, o_south => o(0) ); U_cell_63: cell PORT MAP (i_north => i(63), i_west => east(62), i_east => '0', o_east => open, o_west => west(62), o_south => o(63) ); U_top_gen: for i in 1 to 62 generate U_cell_i: cell PORT MAP (i_north => i(i), i_west => east(i-1), i_east => west(i), o_east => east(i), o_west => west(i-1), o_south => o(i) ); end generate; end; Generate example (2/2)
Generate example 2 (1/5) ENTITY cell_array IS PORT (i: in std_logic_vector(3 downto 0); o: out std_logic_vector(3 downto 0) ); END ENTITY cell_array; -- ARCHITECTURE str OF cell_array IS COMPONENT cell PORT (i_north: in std_logic; i_west: in std_logic; i_east: in std_logic; o_east: out std_logic; o_west: out std_logic; o_south: out std_logic ); end component; type sig_array is array (3 downto 0) of std_logic_vector(3 downto 0); type sig_array2 is array (2 downto 0) of std_logic_vector(3 downto 0); signal south: sig_array2; signal west: sig_array; signal east: sig_array;
Generate example 2(2/5) BEGIN U_cell_0_0: cell PORT MAP (i_north => i(0), i_west => '0', i_east => west(0)(0), o_east => east(0)(0), o_west => open, o_south => south(0)(0) ); U_cell_0_3: cell PORT MAP (i_north => i(3), i_west => west(0)(3), i_east => '0', o_east => east(0)(3), o_west => west(0)(3), o_south => south(0)(3) ); U_cell_3_0: cell PORT MAP (i_north => north(2)(0), i_west => '0', i_east => west(3)(0), o_east => east(3)(0), o_west => open, o_south => o(0) );
U_cell_3_3: cell PORT MAP (i_north => north(2)(3), i_west => west(3)(3), i_east => '0', o_east => open, o_west => west(3)(3), o_south => o(3) ); U_top_gen: for i in 1 to 2 generate U_cell_i_0: cell PORT MAP (i_north => i(i), i_west => east(i-1)(0), i_east => west(i)(0), o_east => east(i)(0), o_west => west(i-1)(0), o_south => south(i)(0) ); end generate; U_bottom_gen: for i in 1 to 2 generate U_cell_i_3: cell PORT MAP (i_north => south(i)(2), i_west => east(i-1)(3), i_east => west(i)(3), o_east => east(i)(3), o_west => west(i-1)(3), o_south => o(i) ); end generate; Generate example 2 (3/5)
Generate example 2 (4/5) U_left_gen: for i in 1 to 2 generate U_cell_0_i: cell PORT MAP (i_north => south(0)(i), i_west => '0', i_east => west(0)(i), o_east => east(0)(i), o_west => open, o_south => south(0)(i) ); end generate; U_right_gen: for i in 1 to 2 generate U_cell_3_i: cell PORT MAP (i_north => south(2)(i), i_west => east(3)(i-1), i_east => '0', o_east => east(3)(i), o_west => west(3)(i-1), o_south => south(3)(i) ); end generate;
Generate example 2 (5/5) U_inner_gen_x: for i in 1 to 2 generate U_inner_gen_y: for j in 1 to 2 generate U_cell_i_j: cell PORT MAP (i_north => south(i-1)(j), i_west => east(i)(j-1), i_east => west(i)(j), o_east => east(i)(j), o_west => west(i)(j-1), o_south => south(i)(j) ); end generate; end generate; END ARCHITECTURE str;
Arithmetic unit description Library ieee; Use ieee.std_logic_1164.all; Use ieee.std_logic_unsigned.all; ENTITY add1 is port (a, b: in std_logic; cin: in std_logic; sum: out std_logic; cout: out std_logic); end add1; ARCHITECTURE rtl of add1 is Signal s: std_logic_vector(1 downto 0); begin s <= (‘0’ & a) + b + cin; sum <= s(0); cout <= s(1); end;
Example Describe a 5-bit multiplier in VHDL.
When statement (concurrent)– describing MUXs Port/signal <= value1 WHEN condition1 [ELSE value2 when condition2 …] ELSE valueN; ENTITY mux IS PORT (i0: in std_logic; i1: in std_logic; s: in std_logic; o: out std_logic); END mux; ARCHITECTURE rtl OF mux IS BEGIN o <= i0 when s = ‘0’ else i1; END RTL;
with statement (concurrent)– describing MUXs WITH signal SELECT port/signal <= expression1 WHEN value1, expression2 WHEN value2, … expressionN WHEN OTHERS; ENTITY mux IS PORT (i0: in std_logic; i1: in std_logic; s: in std_logic; o: out std_logic); END mux; ARCHITECTURE rtl OF mux IS BEGIN WITH s SELECT o <= i0 WHEN ‘0’, i1 WHEN OTHERS; END rtl;
Sequential statements (1)process [process_name:] PROCESS (sensitivity list) BEGIN sequential statements END PROCESS [process_name];
COMBINATIONAL PROCESS PROCESS(a, b, c) BEGIN d <= (a AND b) OR c; END PROCESS; ALL input signals must be in sensitivity list or latches will be produced!
If statement (sequential)– describing MUXs ENTITY mux IS PORT (i0: in std_logic; i1: in std_logic; s: in std_logic; o: out std_logic); END mux; ARCHITECTURE rtl OF mux IS BEGIN process(i0, i1, s) BEGIN If s = ‘0’ then o <= i0; else o <= i1; end if; end process; END rtl; If condition1 then signal1 <= value1; signal2 <= value2; elsif condition2 then signal1 <= value3; signal2 <= value4; … [ELSE signal1 <= valuen-1; signal2 <= valuen;] end if;
CASE statement (sequential)– describing MUXs ENTITY mux IS PORT (i0: in std_logic; i1: in std_logic; s: in std_logic; o: out std_logic); END mux; ARCHITECTURE rtl OF mux IS BEGIN process(i0, i1, s) BEGIN CASE s IS WHEN ‘0’ => o <= i0; WHEN OTHERS => s <= i1; end CASE; end process; END rtl; CASE expression IS when value1 => signal1 <= value2; signal2 <= value3; when value4 => signal1 <= value4; signal2 <= value5; . . . [when others => signal1 <= valuen-1; signal2 <= valuen;] end CASE;
Example • Describe a 3-bit 4-to-1 MUX
CLOCKED PROCESS(Latch with asynchronous reset) PROCESS(clk, rst_n) BEGIN IF rst_n = ‘0’ THEN q <= (others => ‘0’); ELSIF clk= ‘1’ THEN q <= d; END IF; END PROCESS;
CLOCKED PROCESS(Latchwith synchronous reset) PROCESS(clk) BEGIN IF clk = ‘1’ THEN if rst_n = ‘0’ then q <= (others => ‘0’); else q <= d; end if; END IF; END PROCESS;
CLOCKED PROCESS(Flip-flop with asynchronous reset) PROCESS(clk, rst_n) BEGIN IF rst_n = ‘0’ THEN q <= (others => ‘0’); ELSIF clk’event and clk= ‘1’ THEN q <= d; END IF; END PROCESS;
CLOCKED PROCESS(Flip-flop with synchronous reset) PROCESS(clk) BEGIN IF clk’event and clk= ‘1’ THEN IF rst_n = ‘0’ THEN q <= (others => ‘0’); else q <= d; end if; END IF; END PROCESS;
for loop statement – shift register ENTITY shift_reg is port(clk, rst_n: in std_logic; input: in std_logic; output: out std_logic); end shift_reg; Architecture rtl of shift_reg is signal d: std_logic_vector(3 downto 0); begin process(clk, rst_n) begin if rst_n = ‘0’ then d <= (others => ‘0’); elsif rising_edge(clk) then d(0) <= input; for i in 0 to 3 loop d(i+1) <= d(i); end loop; end if; end process; output <= d(3); end; [label]: for identifier in rangeloop statements end loop;
CLOCKED VS COMBINATIONAL PROCESS (1/2) process(clk, rst) BEGIN If rst = ‘1’ then q <= ‘0’; elsif clk’event and clk = ‘1’ then CASE c IS WHEN ‘0’ => q <= a; WHEN OTHERS => q <= b; end CASE; end if; end process; process(a, b, c) BEGIN CASE c IS WHEN ‘0’ => q <= a; WHEN OTHERS => q <= b; end CASE; end process;
CLOCKED VS COMBINATIONAL PROCESS (2/2) PROCESS(a, b, c) BEGIN d <= (a AND b) OR c; END PROCESS; PROCESS(clk, rst) BEGIN if rst = ‘1’ then d <= ‘0’; elsif clk’event and clk= ‘1’ then d <= (a AND b) OR c; end if; END PROCESS;