Copyright c 2003 by Valery Sklyarov and Iouliia
Copyright (c) 2003 by Valery Sklyarov and Iouliia Skliarova: DETUA, IEETA, Aveiro University, Portugal
Any project includes permanent component interacting with VHDL code. This enables us to get data from DIP switchers and buttons and to display results on LEDs and LCD Index: Result: 1 8 1 1 0 L 1 B 1 0 S 1. DIP. . S 8 L 2 L 3 L B 4 4 Permanent project LEDs block buttons VHDL block will be given for all considered constructions of VHDL. Tested VHDL block can be directly connected to the first block and it allows to verify any VHDL construction in the respective circuit Tested VHDL block
divider can be used in order to examine all changes in VHDL code in visual mode
library IEEE; use IEEE. STD_LOGIC_1164. ALL; use IEEE. STD_LOGIC_ARITH. ALL; use IEEE. STD_LOGIC_UNSIGNED. ALL; common libraries entity VHDL_test is Port ( data_in : in std_logic_vector(7 downto 0); data_out : out std_logic_vector(3 downto 0); index_out : out std_logic_vector(3 downto 0); clk : in std_logic; code reset : in std_logic); of entity This is a positional association, end VHDL_test; where the values are associated with elements from left to right architecture Behavioral of VHDL_test is signal my_bus : std_logic_vector(3 downto 0); signal bit 3, bit 2, bit 1, bit 0 : std_logic; begin bit 3 <= '0'; bit 2 <= '1'; bit 1 <= '1'; Result: 7 bit 0 <= '1'; my_bus <= (bit 3, bit 2, bit 1, bit 0); data_out <= my_bus; Example in end Behavioral; Aggregation is a grouping of values to form an array or record expression VHDL_AF. zip
code of entity architecture Behavioral of VHDL_test is -- declaration of bit 3, …, bit 0 and my_bus begin bit 3 <= '0'; bit 2 <= '1'; bit 1 <= '1'; bit 0 <= '1'; my_bus <= (0=>bit 3, 2=>bit 2, 1=>bit 1, 3=>bit 0); data_out <= my_bus; -- value > appears on LCD end Behavioral; Result: Example in VHDL_AF. zip > This is named association The elements are explicitly referenced and the order is not taken into account
code of entity architecture Behavioral of VHDL_test is -- declaration of bit 3, …, bit 0 and my_bus begin bit 3 <= '0'; bit 2 <= '1'; bit 1 <= '1'; bit 0 <= '1'; my_bus <= (0=>bit 3, 2=>bit 2, 1=>bit 1, 3=>bit 0); data_out <= my_bus; -- value > appears on LCD end Behavioral; Result: Example in VHDL_AF. zip >
code of entity architecture Behavioral of VHDL_test is signal my_bus : std_logic_vector(3 downto 0); begin my_bus <= (1 downto 0 => '1', others => '0'); data_out <= my_bus; -- value 3 appears on LCD end Behavioral; Result: 3 The elements can be grouped. The keyword others indicates the remaining elements Example in VHDL_AF. zip
code of entity architecture Behavioral of VHDL_test is type my_packet is record first_bit : std_logic; second_bit : std_logic; data : std_logic_vector (1 downto 0); end record; signal record_data : my_packet; begin record_data <= ('0', '1', "01"); data_out <= record_data. first_bit & record_data. second_bit & record_data; -- value 5 appears on LCD end Behavioral; Example in VHDL_AF. zip Result: 5 Aggregates are used in order to assign a record
aggregates and arrays std_logic code of entity architecture Behavioral of VHDL_test is type my_array is array(3 downto 0) of std_logic; type my_packet is array(0 to 5) of my_array; signal my_data : my_packet : = (others => "0110"); begin data_out <= my_data(2)(3) & my_data(2)(2) & my_data(2)(1) & my_data(2)(0); -- value 6 appears on LCD end Behavioral; 3 2 1 0 my_array Result: 6 my_array my_data Example in VHDL_AF. zip my_packet my_array
code of entity architecture Behavioral of VHDL_test is type my_array is array(3 downto 0) of std_logic; type my_packet is array(0 to 5) of my_array; signal my_data : my_packet : = (others => "0110"); begin data_out <= my_data(2)(3) & my_data(2)(2) & my_data(2)(1) & my_data(2)(0); -- value 6 appears on LCD end Behavioral; Result: Example in VHDL_AF. zip 6
Index: Result: 0 4 entity VHDL_test is Port ( data_in : in std_logic_vector(7 downto 0); data_out : out std_logic_vector(3 downto 0); index_out : out std_logic_vector(3 downto 0); clk : in std_logic; reset : in std_logic); end VHDL_test; Index: Result: 1 4 Index: Result: 2 4 Index: Result: 5 8 Example in VHDL_AF. zip Index: Result: 4 4 Index: Result: 3 9
The divider provides clock with ~ 1 Hz frequency architecture Behavioral of VHDL_test is type my_array is array(3 downto 0) of std_logic; type my_packet is array(0 to 5) of my_array; initialization signal my_data : my_packet : = (others => "0110"); process(reset, clk) variable my_ind : integer range 0 to 5; begin if reset = '1' then my_data <= (5=>"1000", 3=>"1001", others => "0100"); my_ind : = 0; elsif rising_edge(clk) then data_out <= my_data(my_ind)(3) & my_data(my_ind)(2) & output to my_data(my_ind)(1) & my_data(my_ind)(0); display index_out <= conv_std_logic_vector(my_ind, 4); index on LCD if my_ind = 5 then my_ind : = 0; else my_ind : = my_ind + 1; end if; end process; forming a sequence data output for given index my_ind end Behavioral; 0, 1, 2, 3, 4, 5 of indexes Example in VHDL_AF. zip
architecture ARCH_NAME of ENTITY_NAME is <declarations> begin <concurrent statements> end ARCH_NAME; Items are visible in any process or block within the architecture entity VHDL_test is Port ( data_in : in std_logic_vector(7 downto 0); data_out : out std_logic_vector(3 downto 0)); end VHDL_test; architecture Behavioral of VHDL_test is signal operand. A, operand. B, result : std_logic_vector (3 downto 0); begin data_out <= data_in(7 downto 6) * data_in(5 downto 4); end Behavioral; Example in VHDL_AF. zip
1 0 S 0. . . S 7 Result: 6 2*3=6 entity VHDL_test is Port ( data_in : in std_logic_vector(7 downto 0); data_out : out std_logic_vector(3 downto 0)); end VHDL_test; architecture Behavioral of VHDL_test is signal operand. A, operand. B, result : std_logic_vector (3 downto 0); begin data_out <= data_in(7 downto 6) * data_in(5 downto 4); end Behavioral; Example in VHDL_AF. zip
1 Mode 1 (S 1): Mode 2 (S 2): Mode 3 (S 3): Example in VHDL_ASS. zip 2 3 4
State. CAD diagram for FSM Divider, which provides ≈ 1 Hz frequency for FSM (for visual mode) VHDL code of the FSM created by State. CAD Control of DIP switchers and LEDs FSM Example in VHDL_ASS. zip
SW 1 SW 2 SW 3 LED 1 LED 2 LED 3 LED 4 Example in VHDL_ASS. zip
Example in VHDL_ASS. zip LEDs : out std_logic_vector(3 downto 0); entity LCD_struc is Port ( switchers : in std_logic_vector(2 downto 0); LEDs : out std_logic_vector(3 downto 0); clk 48 : in std_logic; rst : in std_logic); end LCD_struc; LCD_struc architecture Behavioral of LCD_struc is 48 MHz component LED_SW clk 48 Divider PORT (CLK, RESET, SW 1, SW 2, SW 3: IN std_logic; rst loc_clk rst LED 1, LED 2, LED 3, LED 4 : OUT std_logic); 1 Hz internal_clock end component; CLK component Divider RESET S 3 Port ( clk 48 : in std_logic; switchers(2) SW 1 LED_SW S 2 SW 2 switchers(1) rst : in std_logic; S 1 SW 3 switchers(0) loc_clk : out std_logic); LED 1 LED 2 LED 3 LED 4 switchers : in end component; std_logic_vector signal internal_clock : STD_LOGIC; (2 downto 0); LEDs(0) LEDs(1) LEDs(2) LEDs(3) begin L 1 L 2 L 3 L 4 FSM : Divider port map(clk 48, rst, internal_clock); led_control : LED_SW port map(internal_clock, rst, switchers(2), switchers(1), switchers(0), LEDs(1), LEDs(2), LEDs(3)); end Behavioral;
Example in VHDL_ASS. zip LEDs : out std_logic_vector(3 downto 0); entity LCD_struc is Port ( switchers : in std_logic_vector(2 downto 0); LEDs : out std_logic_vector(3 downto 0); clk 48 : in std_logic; rst : in std_logic); end LCD_struc; LCD_struc architecture Behavioral of LCD_struc is 48 MHz component LED_SW clk 48 Divider PORT (CLK, RESET, SW 1, SW 2, SW 3: IN std_logic; rst loc_clk rst LED 1, LED 2, LED 3, LED 4 : OUT std_logic); 1 Hz internal_clock end component; CLK component Divider RESET S 3 Port ( clk 48 : in std_logic; switchers(2) SW 1 LED_SW S 2 SW 2 switchers(1) rst : in std_logic; S 1 SW 3 switchers(0) loc_clk : out std_logic); LED 1 LED 2 LED 3 LED 4 switchers : in end component; std_logic_vector signal internal_clock : STD_LOGIC; (2 downto 0); LEDs(0) LEDs(1) LEDs(2) LEDs(3) begin L 1 L 2 L 3 L 4 connection FSM : Divider port map(clk 48, rst, internal_clock); led_control : LED_SW port map(internal_clock, rst, switchers(2), switchers(1), switchers(0), LEDs(1), LEDs(2), LEDs(3)); end Behavioral;
type_name is array (range) of type_of_elements; data_in = 00110000 type RAM is array (9 downto 0) of std_logic_vector(7 downto 0); signal my_RAM : RAM; my_RAM(0) = “ 00110000” my_RAM(1) = “ 00110001” architecture Behavioral of VHDL_test is my_RAM(2) = “ 00110010” type RAM is array (9 downto 0) of std_logic_vector(7 downto 0); my_RAM(3) = “ 0011” signal my_RAM : RAM; my_RAM(4) = “ 00110100” begin my_RAM(5) = “ 00110101” process(clk, reset) my_RAM(6) = “ 00110110” variable tmp : integer range 0 to 9; my_RAM(7) = “ 00110111” begin my_RAM(8) = “ 00111000” if reset = '1' then tmp : = 0; my_RAM(9) = “ 00111001” elsif rising_edge(clk) then my_RAM(tmp) <= data_in + conv_std_logic_vector(tmp, 8); if (tmp < 9) then tmp : = tmp + 1; else tmp : = 0; end if; end process;
object’attribute_name; process(clk, reset) begin if falling_edge(clk) then for i in my_RAM'range loop data_out <= my_RAM(i); end loop; end if; end process; process(clk, reset) begin if falling_edge(clk) then for i in my_RAM'reverse_range loop data_out <= my_RAM(i); end loop; end if; end process; -- the result is “ 00110000” (ASCII – 0) -- the result is “ 00111001” (ASCII – 9)
object’attribute_name; object’high object’low object’event the upper bound of object the lower bound of object True when signal object changes process(clk, reset) variable tmp : integer range 0 to 9; begin if reset = '1' then tmp : = 0; etc. elsif falling_edge(clk) then data_out <= my_RAM(tmp); index_out <= "000" & my_RAM(tmp)(my_RAM(tmp)'right); index_out <= "000" & my_RAM(tmp)(my_RAM(tmp)'left); length index_out <= x"30" + conv_std_logic_vector((my_RAM'length)-1, 8); --my_RAM'high - my_RAM'low + 1 - the result is 9 index_out <= x"30" + conv_std_logic_vector(my_RAM(0)'length, 8); if (tmp < 9) then tmp : = tmp + 1; else tmp : = 0; end if; end process; the most left bit the most right bit the result is “ 00111000” (ASCII – 8)
label: block (unsupported_in_ISE_optional_ guard_condition) declarations begin concurrent_statements end block label; Block permits to group concurrent statements within an architecture -- ………………. . -- …………… begin Programmable_MUX: block signal link : std_logic_vector(R-1 downto 0); begin X M MUX_OUT MUX : Gen_Mux generic map(L=>8, R=>3) port map(link, X, MUX_OUT); MUX_RAM : RAM generic map(N=>3, deep=>8, R=>3) port map(clk, we, di, state, ar, link); end block Programmable_MUX; -- ……………. for reprogramming RAM state link RAM
level: block signal m_out : std_logic; signal composed : std_logic_vector(R downto 0); begin composed <= ds & m_out; level_CC: Prog_Mux generic map(L=>8, R=>3) port map(clk, wem, di, ar, ds, X, m_out); level_RAM: RAM generic map(N=>3, deep=>16, R=>4) port map (clk, we, di, composed, ar, T); end block level; y 0 Y y. N-1 Output RAM x 0 X x 0 M X x. L-1 RAM X M RAM fdc 0 0 0 RAM fdc. R-1 RAM R-1 G blocks Y
Interaction with DIP switches, push buttons and LEDs for trenz TE-XC 2 Se prototyping board see more details in Tutorial 2 case state is when "0000“ => a <= "00"; cpld_cs <= '1'; cpld_rw <= '1'; when "0001" => cpld_cs <= '0'; when "0010" => lpb <= d; when "0011" => cpld_cs <= '1'; when "0100" => a <= "10"; cpld_rw <= '0'; when "0101" => cpld_cs <= '0'; when "0110" => cpld_cs <= '1'; when "0111" => a <= "01"; cpld_cs <= '1'; cpld_rw <= '1'; when "1000" => cpld_cs <= '0'; when "1001" => dipswitch <= d; when "1010" => cpld_cs <= '1'; when others => cpld_cs <= '1'; end case; 1 1 0 L 1 0 . . S 8 L 2 B 1 bu tt S 1. DIP on s L 3 L 4 CPLD LEDs XC 9572 XL a(2: 1) B 4 cpld_cs cpld_rw
entity VHDL_test is Port ( data_in : in std_logic_vector(7 downto 0); --. . . . data_in index_out “ 0000” “ 00000001” “ 00000010” “ 0001” converts std_logic_vector to integer process(clk, reset) “ 00000011” “ 0001” variable tmp : integer; “ 00000100” “ 0001” begin “ 00000101” “ 0001” if falling_edge(clk) then “ 00000110” “ 0010” tmp : = conv_integer(data_in); “ 00000111” “ 0011” case tmp is “ 00001000” “ 0010” when 0 => index_out <= "0000"; “ 00001001” “ 0011” when 1 to 5 => index_out <= "0001"; “ 00001010” “ 0010” when 6|8|10 => index_out <= "0010"; “ 00001011” “ 0011” when others => index_out <= "0011"; “ 00001100” “ 0011” end case; “ 00001101” “ 0011” end if; “ 00001110” “ 0011” end process; …………. . “ 0011”
entity VHDL_test is Port ( data_in : in std_logic_vector(7 downto 0); --. . . . process(clk, reset) begin if falling_edge(clk) then case data_in is when "0000" => index_out <= "0000"; when "00000001"| "00000010"| "00000011"| "00000100"| "00000101" => index_out <= "0001"; when "00000110"| "00001000"| "00001010" => index_out <= "0010"; when others => index_out <= "0011"; end case; end if; end process; data_in index_out “ 0000” “ 00000001” “ 00000010” “ 0001” “ 00000011” “ 00000100” “ 0001” “ 00000101” “ 00000110” “ 00000111” “ 00001000” “ 0010” “ 00001001” “ 0011” “ 00001010” “ 00001011” “ 00001100” “ 0011” “ 00001101” “ 0011” “ 00001110” “ 0011” …………. . “ 0011”
don’t care process(clk, reset) begin if falling_edge(clk) then case data_in is when "00010110" => index_out <= "0000"; when "0001 -0 -0" => index_out <= "0001"; when "0000 ----" => index_out <= "0010 "; when others => index_out <= "0011"; end case; end if; end process; don’t care data_in index_out “ 0000” “ 0010” “ 00000001” “ 0010” “…………. ” “ 0010” “ 00001111” “ 0010” “ 00010000” “ 00010001” “ 0011” “ 00010010” “ 00010011” “ 00010100” “ 0011” “ 00010101” “ 0011” “ 00010110” “ 00010111” “ 0011” “…………. . ” “ 0011” “ 00011000” “ 00011001” “ 0011” “ 00011010” “ 0001” “…………. . ” “ 0011”
component_name generic (generic_list); port(port_list) end component Divider Port ( clk 48 : in std_logic; rst : in std_logic; loc_clk : out std_logic); end component; Generic multiplexer component Gen_Mux is generic ( L : integer; R : integer); Port ( SEL : in STD_LOGIC_VECTOR(R-1 downto 0); X : in STD_LOGIC_VECTOR(L-1 downto 0); MUX_OUT : out STD_LOGIC); end component;
label: component_name generic map (generic_list) port map (port_list); architecture Behavioral of LCD_struc is component LED_SW Port (CLK, RESET, SW 1, SW 2, SW 3: IN std_logic; LED 1, LED 2, LED 3, LED 4 : OUT std_logic); end component; component Divider Port ( clk 48 : in std_logic; rst : in std_logic; loc_clk : out std_logic); end component; signal internal_clock : STD_LOGIC; begin FSM : Divider port map(clk 48, rst, internal_clock); led_control : LED_SW port map(internal_clock, rst, switchers(2), switchers(1), switchers(0), LEDs(1), LEDs(2), LEDs(3)); end Behavioral; Example in VHDL_ASS. zip
label: component_name generic map (generic_list) port map (port_list); architecture Behavioral of Prog_Mux is component Gen_Mux is generic ( L : integer; R : integer); Port ( SEL : in STD_LOGIC_VECTOR(R-1 downto 0); X : in STD_LOGIC_VECTOR(L-1 downto 0); MUX_OUT : out STD_LOGIC); end component; --. . . signal link : std_logic_vector(R-1 downto 0); begin MUX : Gen_Mux generic map(L=>8, R=>3) port map(link, X, MUX_OUT); --. . . end Behavioral;
constant_name : type : = value; architecture Behavioral of display is --. . . . constant line 1: string(1 to 3) : = "; --. . . . begin --. . . . -- see tutorial 3 architecture Behavioral of display is --. . . . constant ternary_vector : std_logic_vector(5 downto 0) : = "01 -1 -0"; constant my_const : integer : = 7; --. . . . begin --. . . .
entity_name is generic(generic_list); port(port_list) end entity_name; entity Prog_Mux is generic ( L : integer : = 8; R : integer : = 3); Port ( clk : in std_logic; we : in std_logic; di : in std_logic_vector(R-1 downto 0); ar : in std_logic_vector(R-1 downto 0); state : in STD_LOGIC_VECTOR(R-1 downto 0); X : in STD_LOGIC_VECTOR(L-1 downto 0); MUX_OUT : out STD_LOGIC); end Prog_Mux;
exit; exit <loop_label> when condition; entity VHDL_test is Port ( index_out : out std_logic_vector(3 downto 0); --. . . . . on off process(data_in) variable index : integer range 0 to 5; index_out keeps begin the number of index : = 0; last DIP switch “on” the last DIP index_out <= (others => '0'); from left to right switch, which loop is checked is 4 exit when index = 5; if data_in(index)= '1' then For example: index_out <= conv_std_logic_vector(index, 4); 0 end if; off 1 on index : = index + 1; 2 end loop; end process; index_out = 2
exit; exit <loop_label> when condition; process(data_in) The result is the same as variable index : integer range; in the previous example begin index : = 0; index_out <= (others => '0'); for index in data_in'reverse_range loop if index = 5 then exit; else if data_in(index)= '1' then index_out <= conv_std_logic_vector(index, 4); end if; end loop; end process;
exit; exit <loop_label> when condition; for index in data_in'reverse_range loop on process(data_in) variable index : integer range; begin index : = 0; the number of index_out <= (others => '0'); the last DIP for index in data_in'range loop switch, which exit when index = 5; is checked is 6 if data_in(index)= '1' then index_out <= conv_std_logic_vector(index, 4); end if; end loop; end process; compare with the previous examples off index_out keeps the number of the last DIP switch “on” from right to left i. e. only DIP switchers 6 and 7 are checked index_out keeps the number of the last DIP switch “on” from left to right
exit <loop_label>; process(data_in) variable index : integer; begin index : = 0; index_out <= (others => '0'); ext: for index in data_in'range loop int: for I in 0 to 7 loop exit ext when index = I; exit int when I = 4; end loop int; end loop ext; index_out <= conv_std_logic_vector(index, 4); end process; label of internal loop label of external loop The optional loop_label may be used to indicate which loop has to be exited
<label> for control_variable in range loop sequential statements end loop < label > There are many other examples with for loop in this tutorial process (data_in) variable temp : std_logic; begin temp : = '0'; for i in data_in'range loop temp : = temp xor data_in(i); end loop; index_out <= "000" & temp; end process; off tests parity on off on process (data_in) variable temp : integer range 0 to 6; begin temp : = 0; for i in 6 downto 0 loop if data_in(i) = '1' then temp : = temp+1; end if; end loop; index_out <= conv_std_logic_vector(temp, 4); end process; on off counts the number of “ones” in 7 first DIP switchers index_out = “ 0001” index_out = “ 0000” index_out = “ 0010”
entity VHDL_test is Port ( data_in data_out end VHDL_test; function_name (parameter_list) return type is < declarations> begin <sequential statements> end function_name : in std_logic_vector(7 downto 0); : out std_logic_vector(3 downto 0)); for i in input'range loop temp : = temp xor input(i); end loop; architecture Behavioral of VHDL_test is function parity (input : std_logic_vector) return std_logic is variable temp : std_logic : = '0'; begin for i in input'range loop temp : = temp xor input(i); end loop; return temp; end parity; begin data_out <= "000" & parity(data_in); end Behavioral; Example in VHDL_AF. zip function call for our example i will be changed from 7 to 0 this function is valid for any size of input parameter - input
function_name (parameter_list) return type is < declarations> begin <sequential statements> end function_name architecture Behavioral of VHDL_test is function parity (input : std_logic_vector) return std_logic is variable temp : std_logic : = '0'; begin for i in input'range loop temp : = temp xor input(i); end loop; return temp; end parity; begin data_out <= "000" & parity(data_in); end Behavioral; Example in VHDL_AF. zip
function_name (parameter_list) return type is < declarations> begin <sequential statements> end function_name architecture Behavioral of VHDL_test is function parity (input : std_logic_vector) return std_logic is variable temp : std_logic : = '0'; begin for i in input'range loop temp : = temp xor input(i); end loop; return temp; end parity; begin data_out <= "000" & parity(data_in); end Behavioral; Example in VHDL_AF. zip
1 2 3 4 Example in VHDL_AF. zip
function declaration library IEEE; use IEEE. STD_LOGIC_1164. all; package func_lib is function parity (input : std_logic_vector) end func_lib; return std_logic; package body func_lib is function parity (input : std_logic_vector) return std_logic is variable temp : std_logic : = '0'; begin for i in input'range loop temp : = temp xor input(i); end loop; return temp; end parity; end func_lib; Example in VHDL_AF. zip function definition
library IEEE; use IEEE. STD_LOGIC_1164. ALL; use IEEE. STD_LOGIC_ARITH. ALL; use IEEE. STD_LOGIC_UNSIGNED. ALL; use work. func_lib. all; entity VHDL_test is Port ( data_in : in std_logic_vector(7 downto 0); data_out : out std_logic_vector(3 downto 0); index_out : out std_logic_vector(3 downto 0); clk : in std_logic; reset : in std_logic); end VHDL_test; architecture Behavioral of VHDL_test is begin data_out <= "000" & parity(data_in); end Behavioral; Example in VHDL_AF. zip
label: for parameter in range generate concurrent statements end generate label; generic ( R : integer : = 3; -- other generic statements ); --. . . . FSM_reg: -- register of an FSM for i in 0 to R-1 generate REG: FDC port map (CS(i), clk, rst, NS(i)); end generate FSM_reg; next state (NS) clk rst D Flip-Flop with Asynchronous Clear from Xilinx library current state (CS) The for … generate construction can be used to instantiate an array of component, for example: REG
This is a top level specification of a reprogrammable finite state machine (RFSM) See complete example in the tutorial about RFSMs library IEEE; use IEEE. STD_LOGIC_1164. ALL; use IEEE. STD_LOGIC_ARITH. ALL; use IEEE. STD_LOGIC_UNSIGNED. ALL; entity ROM_FSM is generic ( L : integer : = 8; R : integer : = 3; N : integer : = 4; G : integer : = 2); Port ( clk : in std_logic; rst : in std_logic; X : in STD_LOGIC_VECTOR(L-1 downto 0); Y : out STD_LOGIC_VECTOR(N-1 downto 0)); end ROM_FSM;
architecture Behavioral of ROM_FSM is component FDC generic (INIT : bit : = '1'); port ( Q : out STD_ULOGIC; C : in STD_ULOGIC; CLR : in STD_ULOGIC; D : in STD_ULOGIC); end component; component level is generic ( L : integer : = 8; R : integer : = 3; N : integer : = 3); Port ( X : in STD_LOGIC_VECTOR(L-1 downto 0); ds : in STD_LOGIC_VECTOR(R-1 downto 0); T : out STD_LOGIC_VECTOR(N-1 downto 0)); end component;
signal m_out : std_logic_vector(G downto 1); type between_levels is array (G downto 0) of std_logic_vector (R-1 downto 0); signal dummy_state : between_levels; begin Y <= '0' & dummy_state(0); FSM_reg: for i in 0 to R-1 generate REG: FDC port map (dummy_state(0)(i), clk, rst, dummy_state(G)(i)); end generate FSM_reg; FSM_CC: for i in 1 to G generate level_PM: level end generate FSM_CC; end Behavioral; generic map(L=>8, R=>3, N=>3) port map(X, dummy_state(i-1), dummy_state(i));
entity_name is generic (generic_list); port (declarations); end entity_name; component_name is generic (generic_list); port (declarations); end component; instance_label: component_name generic map (association_list); port map (association_list); entity Gen_Mux is generic ( L : integer : = 8; R : integer : = 3); Port ( SEL : in STD_LOGIC_VECTOR(R-1 downto 0); X : in STD_LOGIC_VECTOR(L-1 downto 0); MUX_OUT : out STD_LOGIC); end Gen_Mux; component Gen_Mux is generic ( L : integer; R : integer); Port (SEL : in STD_LOGIC_VECTOR(R-1 downto 0); X : in STD_LOGIC_VECTOR(L-1 downto 0); MUX_OUT : out STD_LOGIC); end component; MUX: Gen_Mux generic map(L=>8, R=>3) port map(link, X, MUX_OUT); Generics enable us to pass instance specific information into an entity
library IEEE; use IEEE. STD_LOGIC_1164. ALL; use IEEE. STD_LOGIC_ARITH. ALL; use IEEE. STD_LOGIC_UNSIGNED. ALL; entity Gen_Mux is -- default value generic ( L : integer : = 8; -- default value R : integer : = 3); Port ( SEL : in STD_LOGIC_VECTOR(R-1 downto 0); X : in STD_LOGIC_VECTOR(L-1 downto 0); MUX_OUT : out STD_LOGIC); end Gen_Mux; architecture Behavioral of Gen_Mux is begin MUX_OUT <= X(conv_integer(SEL)); end Behavioral;
library IEEE; use IEEE. STD_LOGIC_1164. ALL; use IEEE. STD_LOGIC_ARITH. ALL; use IEEE. STD_LOGIC_UNSIGNED. ALL; entity ROM is generic ( N : integer : = 3; deep : integer : = 8; R : integer : = 3); port ( a : in std_logic_vector(R-1 downto 0); spo : out std_logic_vector(N-1 downto 0)); end ROM; -- address -- data architecture Behavioral of ROM is type ram_type is array (deep-1 downto 0) of std_logic_vector (N-1 downto 0); constant ROM : ram_type : = ("111", "110", "101", "011", "100", "010", "001", "000"); begin spo <= ROM(conv_integer(a)); end Behavioral;
library IEEE; use IEEE. STD_LOGIC_1164. ALL; use IEEE. STD_LOGIC_ARITH. ALL; use IEEE. STD_LOGIC_UNSIGNED. ALL; entity Prog_Mux is generic ( L : integer : = 8; R : integer : = 3); Port ( state : in STD_LOGIC_VECTOR(R-1 downto 0); X : in STD_LOGIC_VECTOR(L-1 downto 0); MUX_OUT : out STD_LOGIC); end Prog_Mux; X gen_mux link state rom MUX_OUT
architecture Behavioral of Prog_Mux is component Gen_Mux is generic ( L : integer; R : integer); Port ( SEL : in STD_LOGIC_VECTOR(R-1 downto 0); X : in STD_LOGIC_VECTOR(L-1 downto 0); MUX_OUT : out STD_LOGIC); end component; component ROM is generic ( N : integer; deep : integer : = 8; R : integer); port ( a : in std_logic_vector(R-1 downto 0); spo : out std_logic_vector(N-1 downto 0)); end component; signal link : std_logic_vector(R-1 downto 0); begin MUX : Gen_Mux generic map(L=>8, R=>3) port map(link, X, MUX_OUT); MUX_ROM : ROM generic map(N=>3, deep=>8, R=>3) port map(state, link); end Behavioral;
if condition 1 then sequential_ statements elsif condition 2 then sequential_statements else sequential_statements end if; process(clk, rst) variable tmp, ind: integer; begin if rst= '1' then tmp: =0; ind : =0; elsif falling_edge(clk) then if rs 232 in = '0' then ind : = 1; end if; if (tmp >= 1) then if (tmp <= 8) then LCD_symbol(tmp-1) <= rs 232 in; end if; if ind = 1 then tmp : = tmp + 1; end if; if (tmp >= 9) and (rs 232 in = '1') then tmp : = 0; ind : = 0; end if; result <= LCD_symbol; end process;
if condition 1 then sequential_ statements elsif condition 2 then sequential_statements else sequential_statements end if; process (CLK, RESET) begin if RESET='1' then COUNT <= "0000"; elsif CLK='1' and CLK'event then if CE='1' then counter example if LOAD='1' then from ISE 5. 2 COUNT <= DIN; template else if DIR='1' then COUNT <= COUNT + 1; else COUNT <= COUNT - 1; end if; end process; 5 1 2 3 4
library_name <, library_name>; library IEEE; use IEEE. STD_LOGIC_1164. ALL; use IEEE. STD_LOGIC_ARITH. ALL; use IEEE. STD_LOGIC_UNSIGNED. ALL; permits to use the respective packages of the library IEEE The library WORK do not have to be declared
Literals are used in expressions separator (underscore) is ignored in the literal and it permits to use more readable form index_out <= conv_std_logic_vector(2#01_10#, 4); -- the result is 6 base can be from 2 to 16 numeric literal bit vector, for example, std_logic_vector index_out <= B"1_001"; -- the result is 9 base might be binary (B or b), octal (O or o) or hexadecimal (X or x) Arrays of characters, such as strings and bit vectors are enclosed by quotes constant line 1: string(1 to 8): = " Index: " & CR; non-printing character can be concatenated
Literals are used in expressions index_out <= conv_std_logic_vector(2#01_10#, 4); -- the result is 6 index_out <= conv_std_logic_vector(3#00_21#, 4); -- the result is 7 index_out <= conv_std_logic_vector(9#00_10#, 4); -- the result is 9 index_out <= conv_std_logic_vector(12#00_10# - 10#00_10#, 4); -- the result is 2 index_out <= B"1_001"; -- the result is 9 index_out <= abs(O"31"); -- the result is 9 (011 001) index_out <= abs(x"F_34"); -- the result is 4 (1111 00110100) constant line 1: string(1 to 8): = " Index: "; constant line 2: string(1 to 10): = " Result: "; see VHDL code for the block lcd from slide 3
Names are used for identifiers. Names may be composed of letters, digits and underscore. Case is not significant, i. e. uppercase and lowercase letters are considered to be the same. Names must begin with a letter. VHDL reserved words cannot be used as names. variable tmp 32, ind: integer; variable temp : std_logic : = '0'; or variable Te. Mp : std_logic : = '0'; signal my_sig 2 : std_logic_vector; signal M 3 d : integer; entity, wait, exit, …. .
next; next loop_label; next <loop_label> when condition; off process(data_in) the number of on variable index : integer; the last DIP begin switch, which index : = 0; is checked is 4 index_out <= (others => '0'); for index in data_in'reverse_range loop index_out keeps if index = 5 then exit; the number of the elsif index = 2 then next; last DIP switch “on” from left to right else (except DIP switch 2) if data_in(index)= '1' then index_out <= conv_std_logic_vector(index, 4); end if; For example: end if; 0 end loop; off 1 on end process; 2 index_out = 1
next; next loop_label; next <loop_label> when condition; process(data_in) variable index : integer; begin index_out keeps index : = 0; the number of the index_out <= (others => '0'); last DIP switch “on” for index in data_in'reverse_range loop from left to right next when index = 3; (except DIP switch 3) if index = 5 then exit; else The number of if data_in(index)= '1' then the last DIP index_out <= conv_std_logic_vector(index, 4); switch, which end if; is checked is 4 end if; end loop; end process;
null; The null statement performs no action process(data_in) begin case data_in(1 downto 0) is when "00" => index_out <= "0" & (data_in(7 downto 5) and data_in(4 downto 2)); when "01" => index_out <= "0" & (data_in(7 downto 5) or data_in(4 downto 2)); when "10" => index_out <= "0" & (data_in(7 downto 5) xor data_in(4 downto 2)); when others => null; end case; end process; on off 01 245 -7 operation: “ 00” – AND; “ 01” – OR; “ 10” - XOR operand 2 null indicates no action operand 1 when the code operation is equal to “ 11”
used in expressions architecture Behavioral of VHDL_test is signal for_op 1, for_op 2, result : integer; --. . . . . begin for_op 1 <= conv_integer(data_in(7 downto 5)); for_op 2 <= conv_integer(data_in(4 downto 2)); process(data_in) begin case data_in(1 downto 0) is when "00" => result <= for_op 1 + for_op 2; when "01" => result <= for_op 1 - for_op 2; when "10" => result <= for_op 1 * for_op 2; when others => null; end case; end process; index_out <= conv_std_logic_vector(result, 4); Logical operators: and, or, nand, nor, xor, not Arithmetical operators: + - addition, - - subtraction, * - multiplication, / - division performs subtraction over integers with sign (which is the most significant bit)
used in expressions for_op 1 <= conv_integer(data_in(7 downto 2)); process(data_in) begin case data_in(1 downto 0) is when "00" => result <= for_op 1 / 2; when "01" => result <= for_op 1 / 4; when "10" => result <= for_op 1 / 8; when others => null; end case; end process; index_out <= conv_std_logic_vector(result, 4); Arithmetical operators: + - addition, - - subtraction, * - multiplication, / - division
used in expressions process(data_in) begin if data_in(0) < data_in(1) then index_out(0) <= '1'; else index_out(0) <= '0'; end if; if data_in(2) > data_in(3) then index_out(1) <= '1'; else index_out(1) <= '0'; end if; if data_in(4) <= data_in(5) then index_out(2) <= '1'; else index_out(2) <= '0'; end if; if data_in(6) >= data_in(7) then index_out(3) <= '1'; else index_out(3) <= '0'; end if; end process; & - concatenation operator Relational operators: < - less than, > - greater than, <= - less than or equal to, >= - grater than or equal to For example: index_out <= “ 01” & “ 10”; Result: index_out = “ 0110”
package Package_Name is declarations end Package_Name; 1 2 package func_lib is function parity (input : std_logic_vector) return std_logic; end func_lib; 3 5 4 6 7
package Package_Name is declarations end Package_Name; library IEEE; use IEEE. STD_LOGIC_1164. all; package <Package_Name> is type <new_type> is record <type_name> end record; : std_logic_vector( 7 downto 0); : std_logic; constant <constant_name> : time : = <time_unit> ns; : integer : = <value>; function <function_name> (signal <signal_name> : in <type_declaration>) return <type_declaration>; procedure <procedure_name> (<type_declaration> <constant_name> : in <type_declaration>); end <Package_Name>;
package body Package_Name is subprogram_bodies end Package_Name; package body <Package_Name> is -- Example 1 function <function_name> (signal <signal_name> : in <type_declaration> ) return <type_declaration> is variable <variable_name> : <type_declaration>; begin <variable_name> : = <signal_name> xor <signal_name>); return <variable_name>; end <function_name>; -- Example 2 function <function_name> (signal <signal_name> : in <type_declaration>; signal <signal_name> : in <type_declaration> ) return <type_declaration> is begin if (<signal_name> = '1') then return <signal_name>; else return 'Z'; end if; end <function_name>; -- Procedure Example procedure <procedure_name> (<type_declaration> <constant_name> : in <type_declaration>) is begin end <procedure_name>; end <Package_Name>;
procedure_name (parameter_list) is declarations begin sequential_statements end procedure_name architecture bhv of lcd is --. . . . . procedure dec 4_bcd (signal dec 4 : in std_logic_vector(3 downto 0); signal bcd. M : out std_logic_vector(3 downto 0); signal bcd. L : out std_logic_vector(3 downto 0)) is begin This procedure converts case dec 4 is 4 bit binary number to 8 when "0 ---" | "100 -" => bcd. M <= (others=>'0'); bit BCD number, where bcd. L <= dec 4; bcd. L is the less significant when others => bcd. M <= "0001"; BCD digit and bcd. M is the bcd. L <= dec 4 + "0110"; most significant BCD digit end case; end dec 4_bcd; --. . . . . begin --. . . . .
The considered procedure is used in the lcd. vhd file (see slide 2) The procedure might be tested with the aid of the following process in the vhdl_test file (see slide 2) process(clk, reset) variable tmp : std_logic_vector(3 downto 0); begin if reset = '1' then tmp : = "0000"; elsif rising_edge(clk) then tmp : = tmp+1; end if; index_out <= tmp; end process; clock frequency is equal 1 -2 Hz Index: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 00 …
<label> process (<sensitivity_list>) declarations begin sequential_statements end process <label> I_am_label: process(clk) variable tmp : std_logic_vector(3 downto 0); begin if rising_edge(clk)then tmp : = tmp+1; index_out <= tmp; end if; end process I_am_label; The sensitivity_list is a set of signals. Any change in these signals causes the process to be activated Similar processes I_am_label: process variable tmp : std_logic_vector(3 downto 0); begin wait until rising_edge(clk); The sensitivity_list of a combinational tmp : = tmp+1; process (for a combinational circuit) index_out <= tmp; must contain all the input signals and the end process I_am_label; process must update all the output signals
type’(expression); The type of a qualified expression is explicitly indicated index_out <= std_logic_vector'("0000") + example 2; architecture Behavioral of VHDL_test is signal example 2 : integer range 0 to 15 : = 11; --. . . . . Qualified expressions may be useful when overloaded functions or procedures are called. It permits to indicate the correct version by providing proper types of the arguments
used in architecture signal_name : type; signal_name : type : = initial_value; Any signal that is driven by more than one process architecture Behavioral of VHDL_test is signal example 1 : std_logic_vector(3 downto 0) : = "1010"; (concurrent statement or component) must be signal example 2 : integer range 0 to 15 : = 11; declared with a resolved signal example 3 : std_logic_vector(0 to 3) : = "1100"; type, i. e. std_logic or --. . . std_logic_vector Signals cannot be declared in a process, a function or a procedure (but they can be formal parameters of a function or a procedure)
used in architecture delay is usually ignored by synthesis tools signal_name <= expression; signal_name <= expression after delay; result <= for_op 1 + for_op 2; for_op 1 <= conv_integer(data_in(7 downto 2)); result <= for_op 1 * for_op 2 after 10 ns; sum <= op 1 xor op 2 after 20 ms;
used in architecture signal_name <= expression 1 when condition 1 else expression 2 when condition 2 else expression 3; each condition is a Boolean expression the final else must be used result <= for_op 1 + for_op 2 when data_in(1 downto 0) = "00" else for_op 1 - for_op 2 when data_in(1 downto 0) = "01" else for_op 1 * for_op 2 when data_in(1 downto 0) = "10" else result;
used in architecture The rules are the same as for the case statement (including specification of a range) with expression select signal_name <= expression 1 when value 1, expression 2 when value 2, expression 3 when others; with data_in(1 downto 0) select result <= for_op 1 + for_op 2 when "00", for_op 1 - for_op 2 when "01", for_op 1 * for_op 2 when "10", result when others;
used in process, procedure signal_name <= expression; signal_name <= expression after delay; Loadable shift register from ISE 5. 2 synthesis template process (CLK)begin if CLK'event and CLK='1' then if (LOAD='1') then REG <= LOAD_DATA; else REG <= DIN & REG(3 downto 1); end if; DOUT <= REG(0); end process; Sequential signal assignments will be done only when the respective process suspends. If there are several assignments to the same signal the last one takes affect --. . . A <=B; A<= C+D; end process;
subtype sybtype_name is base_type range_values; subtype tiny is integer range 0 to 63; subtype part_of_std is std_logic range '1' to '-'; subtype word 8 is std_logic_vector (8 downto 1); type serial_pac is array (0 to 8) of word 8; constant line_RS : serial_pac : = ( x"1 B", --delete display x"44", --delete display x"4 C", --delete display x"1 B", --draw line (ESC) x"47", --draw line (code of this operation) x"30", -- x 1 left point x"15", -- y 1 upper point x"E 6", -- x 2 right point x"72"); -- y 2 bottom point 1) 2) 3) 4) 5) 6) 7) 8) 9) '1' - logical 1 '0' - logical 0 'H' – weak 1 'L' – weak 0 'X' – unknown 'U' – uninitialized 'Z' – high impedance '-' – don't care 'W' – weak unknown std_logic values
type_name is type_specification; Pre-defined in VHDL scalar types are: integer, real, bit, Boolean, character type positive_integers is range 0 to integer'high; type FSM_states is (start, increment, save, decrement, repeat); signal state : FSM_states; signal p_i : positive_integers; subtype word 8 is std_logic_vector (8 downto 1); type serial_pac is array (0 to 8) of word 8; constant line_RS : serial_pac : = ( x"1 B", --delete display x"44", --delete display x"4 C", --delete display x"1 B", --draw line (ESC) x"47", --draw line (code of this operation) x"30", -- x 1 left point x"15", -- y 1 upper point x"E 6", -- x 2 right point x"72"); -- y 2 bottom point
type_name is type_specification; type serial_package is record start_bit : std_logic; data_bits : std_logic_vector (7 downto 0); parity_bit : std_ulogic; stop_bit : std_logic; number : integer range 0 to 127; end record; signal my_sp : serial_package; my_sp. number <= 10; my_sp. start_bit <= '1'; my_sp. data_bits <= (others => '1'); Record type objects can be assigned using aggregates (see section A - aggregates) . Assigning individual fields
target_type(expression) Only closely related expression might be converted function(expression) examples: type my_array is array (0 to 5) of std_logic; signal mem 1 : my_array; signal mem 2 : std_logic_vector (0 to 5); -- mem 1 <= mem 2; mem 1 <= my_array(mem 2); mem 2 <= std_logic_vector(mem 1); error -- OK use IEEE. NUMERIC_STD. ALL; -- for to_unsigned --. . . . . index_out <= conv_std_logic_vector(index, 4); for_op 1 <= conv_integer(data_in(7 downto 5)); index_out <= std_logic_vector(to_unsigned(character'pos('6'), 4)); index_out <= std_logic_vector(to_unsigned(character'pos(line 2(1)), 8));
For conversion between non closely related types a user-defined function can be used, for example: architecture Behavioral of VHDL_test is --. . . . . function Bollean_to_std_logic(input : Boolean) return std_logic is begin if input then return '1'; else return '0'; end if; end Bollean_to_std_logic; --. . . . . begin index_out <= "000" & Bollean_to_std_logic(true);
used in process, procedure, function variable_name : type; variable_name : type : = initial_value; process(clk, reset) variable tmp : std_logic_vector(3 downto 0); begin if reset = '1' then tmp : = "0000"; elsif rising_edge(clk) then tmp : = tmp+1; end if; index_out <= tmp; end process; function parity (input : std_logic_vector) return std_logic is variable temp : std_logic : = '0'; begin for i in input'range loop temp : = temp xor input(i); end loop; return temp; end parity; variable my_int : integer range 25 downto 0; variable line : string(1 to 7) : = "Index: "; variable for_test : Boolean : = false; variable flag : std_logic : = '1'; variable positive_integer : integer range 0 to integer'high;
used in process, procedure, function variable_name : = expression; tmp : = conv_integer(data_in); tmp : = tmp+1; temp : = temp xor input(i); variable assignment is done immediately Assignment can be done from signals to variables and vice versa (type match has to be provided) -- declared as external port of an entity index_out : buffer std_logic_vector(3 downto 0); -- declared in a process my_proc variable tmp : std_logic_vector(3 downto 0); -- possible assignments in the process my_proc index_out <= tmp; tmp : = index_out;
wait until condition; process variable tmp : std_logic_vector(3 downto 0); begin wait until rising_edge(clk); tmp : = tmp+1; index_out <= tmp; end process; wait; wait for time; wait on list_of_signals These wait statements are usually not supported by synthesis tools It is not allowed to use wait statement in any process with a sensitivity list
while condition loop sequential statements end loop; entity VHDL_test is Port ( index_out : out std_logic_vector(3 downto 0); --. . . . . loop sequential statements end loop; on off process(data_in) variable index : integer range 0 to 5; index_out keeps begin the number of index : = 0; last DIP switch “on” the last DIP index_out <= (others => '0'); from left to right switch, which loop is checked is 4 exit when index = 5; if data_in(index)= '1' then For example: index_out <= conv_std_logic_vector(index, 4); 0 end if; off 1 on index : = index + 1; 2 end loop; end process; index_out = 2
while condition loop sequential statements end loop; process(data_in) variable index : integer range 0 to 5; begin Repeat the index : = 0; loop until index_out <= (others => '0'); index is not while index /= 5 loop equal to 5 if data_in(index)= '1' then index_out <= conv_std_logic_vector(index, 4); end if; index : = index + 1; end loop; end process;
Sections of the tutorial that have examples in the projects VHDL_AF. zip, VHDL_ASS. zip have the following indication: All the other sections (i. e. sections without such indication) have examples in the project VHDL. zip Example in VHDL_AF. zip OR VHDL_ASS. zip
-- uncomment for [W while statement] ---- elsif index = 2 then next; --process(data_in) --variable index : integer range 0 to 5; --begin -index : = 0; -- uncomment for [W while Linesstatement] with double comment -index_out <= (others => '0'); process(data_in) indication (i. e. – and --) can be -while index /= 5 loop variable index : integer alternatively range 0 to 5; used for the same -'1' theni. e. for one step these begin if data_in(index)= example, -<=are conv_std_logic_vector(index, 4); index : = index_out 0; lines not needed, but for -end if; index_out <= (others =>steps '0'); they have to be the other -index while: = index /=+uncommented. 51; loop All the required -end loop; if data_in(index)= '1' then in this details are presented --end process; index_out <= conv_std_logic_vector(index, 4); tutorial end if; index : = index + 1; end loop; end process; Some examples, such as that are useful for sections [B blocks], [C case] and [C component], can be found in another tutorial (a reference to the particular tutorial is provided)
- Slides: 89