---------------------------------------------------------------- -- Chapter 21 Design for Synthesis ---------------------------------------------------------------- ---------------------------------------------------------------- -- 21.1 Synthesizable Subsets ---------------------------------------------------------------- ---------------------------------------------------------------- -- 21.2 Use of Data Types ---------------------------------------------------------------- ---------------------------------------------------------------- -- 21.2.1 Scalar Types ---------------------------------------------------------------- -- Page 635 type sample is range -64 to 63; subtype table_index is natural range 0 to 1023; type index_type is range 4 to 15; ---------------------------------------------------------------- -- 21.2.2 Composite and Other Types ---------------------------------------------------------------- -- Page 636 type coeffs is array (3 downto 0) of integer; type channel_states is array (0 to 7) of state; -- state is an enumeration type subtype word is bit_vector(31 downto 0); type reg_file is array (0 to 15) of word; type color is (red, green, blue); type plane_status is array (color) of boolean; -- non-integer index type type matrix is array (1 to 3, 1 to 3) of real; -- 2D, and floating-point elements type reg_file_set is array (0 to 3) of reg_file; -- elements are vectors of non-bits ---------------------------------------------------------------- -- 21.3 Interpretation of Standard Logic Values ---------------------------------------------------------------- -- Page 637 if request_enable = '1' then request <= ready; else request <= 'Z'; end if; ---------------------------------------------------------------- -- 21.4 Modeling Combinational Logic ---------------------------------------------------------------- -- Page 638 status <= '1' when ready and sample < limit else '0'; status <= ready and sample ?< limit; -- Example 21.1, Page 638 sum <= a + b; sum <= a + b + carry_in; sum <= a + b + unsigned'(0 => carry_in); -- Example 21.1, Page 639 tmp_sum <= ('0' & a) + ('0' & b); sum <= tmp_sum(7 downto 0); carry <= tmp_sum(8); (carry, sum) <= ('0' & a) + ('0' & b); -- Example 21.2, Page 639 with addr(1 downto 0) select request <= request_a when "00", request_b when "01", request_c when "10", request_d when "11"; with addr(1 downto 0) select request <= request_a when "00", request_b when "01", request_c when "10", request_d when "11", 'X' when others; request <= request_a when addr(1 downto 0) = "00" else request_b when addr(1 downto 0) = "01" else request_c when addr(1 downto 0) = "10" else request_d when addr(1 downto 0) = "11" else 'X'; -- Page 640 data_bus <= resize(sample_byte, 16) when std_match(sample_enable, '1') else "ZZZZZZZZZZZZZZZZ"; -- Example 21.3, Page 640 read_sample : process ( read_enable, sample, limit_exceeded, ready ) begin if std_match(read_enable, '1') then data <= sample; parity <= calc_parity(sample); status <= ready and not limit_exceeded; else data <= "ZZZZZZZZ"; parity <= 'Z'; status <= 'Z'; end if; end process read_sample; -- Example 21.4, Page 641 adder : process ( sel, a, b, c ) variable operand : integer; begin if sel = '1' then operand := a; else operand := b; end if; sum <= operand + c; end process adder; ---------------------------------------------------------------- -- 21.5 Modeling Sequential Logic ---------------------------------------------------------------- ---------------------------------------------------------------- -- 21.5.1 Modeling Edge-Triggered Logic ---------------------------------------------------------------- -- Example 21.5, Page 643 simple_reg : process ( clk ) is begin if clk'event and clk = '1' then reg_out <= data_in; end if; end process simple_reg; -- Example 21.6, Page 643 dual_reg : process ( clk ) is begin if rising_edge(clk) then if reset = '1' then q1 <= X"00"; q2 <= X"0000"; elsif en = '1' then q1 <= d1; q2 <= d2; end if; end if; end process dual_reg; -- Example 21.7, Page 644 signal d_in, count : unsigned(11 downto 0); ... up_down_counter : process (clk) is begin if rising_edge(clk) then if reset = '1' then count <= X"000"; elsif load_en = '1' then count <= d_in; elsif count_en = '1' then if dir = '1' then count <= count + 1; else count <= count - 1; end if; end if; end if; end process up_down_counter; tc <= '1' when std_match(count, X"111") else '0'; -- Example 21.8, Page 644 reg : process (clk, reset) is begin if reset = '1' then q <= "0000"; elsif rising_edge(clk) then q <= d; end if; end process reg; -- Example 21.9, Page 645 shift_reg : process (clk, reset) is begin if reset = '1' then q <= "00000000"; elsif rising_edge(clk) then if load_en = '1' then q <= d_in else q <= q(6 downto 0) & d_s; end if; end if; end process reg; -- Page 645 RegProc5 : process( clk, reset ) begin if (en = '1' and rising_edge(clk)) or reset = '1' then if reset = '1' then Q <= '0'; -- async assignment elsif en = '1' and rising_edge(clk) then -- sync condition Q <= D; -- sync assignment end if; end if ; end process ; -- Example 21.10, Page 646 reg : process is begin wait until rising_edge(clk); if reset = '1' then q <= X"00"; elsif en = '1' then q <= d; end if; end process dual_reg; -- Example 21.11, Page 646 reg : process is begin wait until reset = '1' or rising_edge(clk); if reset = '1' then q <= X"00"; elsif rising_edge(clk) then if en = '1' then q <= d; end if; end if; end process dual_reg; -- Example 21.12, Page 647 MultProc : process is begin wait until rising_edge(clk); if start = '1' then done <= '0'; P <= (others => '0'); for i in A'range loop wait until rising_edge(clk); if A(i) = '1' then P <= (P(6 downto 0) & '0') + B; else P <= P(6 downto 0) & '0'; end if; end loop; done <= '1'; end if; end process; -- Example 21.13, Page 648 UartTxFunction : process is begin TopLoop : loop if nReset = '0' then SerialDataOut <= '1'; TxRdyReg <= '1'; end if; wait until nReset = '0' or (rising_edge(UartTxClk) and DataRdy = '1'); next TopLoop when nReset = '0'; SerialDataOut <= '0'; TxRdyReg <= '0'; -- Send 8 Data Bits for i in 0 to 7 loop wait until nReset = '0' or rising_edge(UartTxClk); next TopLoop when nReset = '0'; SerialDataOut <= DataReg(i); TxRdyReg <= '0'; end loop; -- Send Parity Bit wait until nReset = '0' or rising_edge(UartTxClk); next TopLoop when nReset = '0'; SerialDataOut <= DataReg(0) xor DataReg(1) xor DataReg(2) xor DataReg(3) xor DataReg(4) xor DataReg(5) xor DataReg(6) xor DataReg(7); TxRdyReg <= '0'; -- Send Stop Bit wait until nReset = '0' or rising_edge(UartTxClk); next TopLoop when nReset = '0'; SerialDataOut <= '1'; TxRdyReg <= '1'; end loop; end process; -- Example 21.13, Page 649 UartTxFunction : process is begin TopLoop : loop wait until rising_edge(UartTxClk); if nReset = '0' then SerialDataOut <= '1'; TxRdyReg <= '1'; elsif DataRdy = '1' then SerialDataOut <= '0'; TxRdyReg <= '0'; -- Send 8 Data Bits for i in 0 to 7 loop wait rising_edge(UartTxClk); exit TopLoop when nReset = '0'; SerialDataOut <= DataReg(i); TxRdyReg <= '0'; end loop; -- Send Parity Bit wait rising_edge(UartTxClk); exit TopLoop when nReset = '0'; SerialDataOut <= DataReg(0) xor DataReg(1) xor DataReg(2) xor DataReg(3) xor DataReg(4) xor DataReg(5) xor DataReg(6) xor DataReg(7); TxRdyReg <= '0'; -- Send Stop Bit wait until rising_edge(UartTxClk); exit TopLoop when nReset = '0'; SerialDataOut <= '1'; TxRdyReg <= '1'; end if; end loop; end process; -- Page 650 wait until clk = '1'; ---------------------------------------------------------------- -- 21.5.2 Level-Sensitive Logic and Inferring Storage ---------------------------------------------------------------- -- Example 21.14, Page 650 latch : process ( enable, d ) begin if enable = '1' then q <= d; end if; end process latch; -- Example 21.15, Page 651 latch_with_reset : process ( enable, reset, d ) variable stored_value : bit; begin if reset = '1' then stored_value := '0'; elsif enable = '1' then stored_value := d; end if; q <= stored_value; end process latch_with_reset; -- Page 651 counter : process ( count_en ) variable count : natural range 0 to 15; begin q <= (q + 1) mod 16; end process counter; ---------------------------------------------------------------- -- 21.5.3 Modeling State Machines ---------------------------------------------------------------- -- Example 21.16, Page 652 architecture rtl of state_machine is type state is (ready, ack, err); signal current_state, next_state : state; begin next_state_and_output : process ( current_state, in1, in2 ) begin case current_state is when ready => out1 <= '0'; if in1 = '1' then out2 <= '1'; next_state <= ack; else out2 <= '0'; next_state <= ready; end if; when ack => out1 <= '0'; if in2 = '1' then out2 <= '0'; next_state <= ready; else out2 <= '0'; next_state <= err; end if; when err => out1 <= '1'; out2 <= '0'; next_state <= err; end case; end process next_state_and_output; state_reg : process ( clk, reset ) begin if reset = '1' then current_state <= ready; elsif rising_edge(clk) then current_state <= next_state; end if; end process state_reg; end rtl; -- Example 21.16, Page 653 next_state_and_output : process ( current_state, in1, in2 ) begin out1 <= '0'; out2 <= '0'; case current_state is when ready => if in1 = '1' then out2 <= '1'; next_state <= ack; else next_state <= ready; end if; when ack => if in2 = '1' then next_state <= ready; else next_state <= err; end if; when err => out1 <= '1'; next_state <= err; end case; end process next_state_and_output; ---------------------------------------------------------------- -- 21.6 Modeling Memories ---------------------------------------------------------------- -- Page 654 type mem_array is array (0 to 2**depth - 1) of std_ulogic_vector(width - 1 downto 0); signal RAM : mem_array; -- Example 21.17, Page 654 asynch_RAM : process (addr, d_in, we) is begin if we = '1' then RAM(to_integer(addr)) <= d_in; end if; end process asynch_RAM; d_out <= RAM(to_integer(addr)); -- Example 21.18, Page 655 synch_RAM : process (clk) is begin if rising_edge(clk) then if we = '1' then RAM(to_integer(addr)) <= d_in; end if; end if; end process synch_RAM; d_out <= RAM(to_integer(addr)); -- Example 21.19, Page 655 synch_RAM : process (clk) is begin if rising_edge(clk) then d_out <= RAM(to_integer(addr)); if we = '1' then RAM(to_integer(addr)) <= d_in; end if; end if; end process synch_RAM; -- Example 21.19, Page 656 synch_RAM : process (clk) is begin if rising_edge(clk) then if we = '1' then RAM(to_integer(addr)) <= d_in; d_out <= d_in; else d_out <= RAM(to_integer(addr)); end if; end if; end process synch_RAM; synch_RAM : process (clk) is begin if rising_edge(clk) then if en = '1' then d_out <= RAM(to_integer(addr)); if we = '1' then RAM(to_integer(addr)) <= d_in; end if; end if; end if; end process synch_RAM; -- Example 21.20, Page 656 pipelined_RAM : process (clk) is variable pipelined_en : std_ulogic; variable pipelined_d_out : std_ulogic_vector(width - 1 downto 0); begin if rising_edge(clk) then if pipelined_en = '1' then d_out <= pipelined_d_out; end if; pipelined_en := en; if en = '1' then pipelined_d_out := RAM(to_integer(addr)); if we = '1' then RAM(to_integer(addr)) <= d_in; end if; end if; end if; end process pipelined_RAM; -- Page 657 signal RAM : RAM_array := (X"0020", X"FC01", X"101E", X"C000", ... others => X"0000"); constant ROM : mem_array := (X"0020", X"FC01", X"101E", X"C000", ... others => X"0000"); d_out <= ROM(to_integer(addr)); -- Example 21.21, Page 658 decoder : process ( bcd ) is begin case bcd is when X"0" => seg <= "0111111"; when X"1" => seg <= "0000110"; when X"2" => seg <= "1011011"; when X"3" => seg <= "1001111"; when X"4" => seg <= "1100110"; when X"5" => seg <= "1101101"; when X"6" => seg <= "1111101"; when X"7" => seg <= "0000111"; when X"8" => seg <= "1111111"; when X"9" => seg <= "1101111"; when others => seg <= "1000000"; end case; end process decoder; with bcd select seg <= "0111111" when X"0", "0000110" when X"1", "1011011" when X"2", "1001111" when X"3", "1100110" when X"4", "1101101" when X"5", "1111101" when X"6", "0000111" when X"7", "1111111" when X"8", "1101111" when X"9", "1000000" when others; -- Page 658 block_ROM : process (clk) is begin if rising_edge(clk) then d_out <= ROM(to_integer(addr)); end if; end process block_ROM; ---------------------------------------------------------------- -- 21.7 Synthesis Attributes ---------------------------------------------------------------- -- Page 659 package RTL_ATTRIBUTES is attribute KEEP : boolean; attribute CREATE_HIERARCHY : boolean; attribute DISSOLVE_HIERARCHY : boolean; attribute SYNC_SET_RESET : boolean; attribute ASYNC_SET_RESET : boolean; attribute ONE_HOT : boolean; attribute ONE_COLD : boolean; attribute FSM_STATE : string; attribute FSM_COMPLETE : boolean; attribute BUFFERED : string; attribute INFER_MUX : boolean; attribute IMPLEMENTATION : string; attribute RETURN_PORT_NAME : string; attribute ENUM_ENCODING : string; attribute ROM_BLOCK : string; attribute RAM_BLOCK : string; attribute LOGIC_BLOCK : string; attribute GATED_CLOCK : boolean; attribute COMBINATIONAL : boolean; end package RTL_ATTRIBUTES; -- Page 660 attribute SYNC_SET_RESET of reset : signal is true; ... reg : process ( clk ) is begin if rising_edge(clk) then if reset = '1' then q <= (others => '0'); else q <= d; end if; end if; end process reg; -- Page 661 ff : process ( clk, reset, set ) is begin if reset = '1' then q <= '0'; elsif set = '1' then q <= '1'; elsif rising_edge(clk) then q <= d; end if; end process ff; attribute ONE_HOT of set, reset : signal is true; -- Page 662 type state_type is (idle, state1, state2); signal state, next_state : state_type; attribute FSM_STATE of state, next_state : signal is "ONE_HOT"; attribute FSM_COMPLETE of state, next_state : signal is true; ... fsm_logic : process (state, ...) is begin case state is when idle => next_state <= ...; when state1 => next_state <= ...; when state2 => next_state <= ...; when others => next_state <= idle; end case; end process fsm_logic; -- Page 663 attribute BUFFERED of clk : signal is "BUFG"; procedure multiplier ( signal clk, start : in std_ulogic; signal a, b : in unsigned(15 downto 0); signal done : out std_ulogic; signal p : out unsigned(31 downto 0) is begin ... end procedure multiplier; attribute IMPLEMENTATION of multiplier : procedure is "MULTSEQ_16X16"; ... multiplier(clk, start, data1, data2, done, product); -- Page 664 function and_or_invert (a, b, c, d : in std_ulogic) return std_ulogic is begin return not ( (a and b) or (c and d) ); end function and_or_invert; attribute IMPLEMENTATION of and_or_invert : function is "AOI"; attribute RETURN_PORT_NAME of and_or_invert : function is "O"; ... q <= and_or_invert(w, x, y, z); type state is (idle, preamble, data, crc, ok, error); attribute enum_encoding of state : type is "000 001 010 011 100 111"; -- Page 665 constant ROM : mem_array := (X"0020", X"FC01", ... others => X"0000"); attribute ROM_BLOCK of ROM : constant is "ROM_SYNCH"; signal RAM : mem_array; attribute RAM_BLOCK of RAM : signal is "RAM_PIPELINED"; attribute GATED_CLOCK of gclk : signal is true; ... gclk <= clk and enable; reg : process (gclk) is begin if rising_edge(gclk) then q <= d; end if; end process; attribute GATED_CLOCK of reg : label is true; reg : process(clk) is begin if rising_edge(clk) then if enable = '1' then q <= d; end if; end if; end process; ---------------------------------------------------------------- -- 21.8 Metacomments ---------------------------------------------------------------- -- Page 666 -- rtl_synthesis off -- rtl_synthesis on -- Example 21.22, Page 667 architecture rtl of subsystem is ... begin ... -- synthesizable processes and assignments -- rtl_synthesis off monitor : process is use std.textio.all; file monitor_file : text open write_mode is "monitor.txt"; variable L : line; ... begin ... end process monitor; -- rtl_synthesis on end architecture rtl; ---------------------------------------------------------------- -- Exercises ---------------------------------------------------------------- -- Exercise 1 type temp is range -60 to 150; type temp_vec is array (natural range <>) of temp; type location is (inside, outside, buried); type local_temp_vec is array (location) of temp; type location_vec is array (natural range <>) of location; type word_vec is array (natural range <>) of std_ulogic_vector(31 downto 0); -- Exercise 2 if sel = '0' or sel = 'L' then z <= in0; elsif sel = '1' or sel = 'H' then z <= in1; elsif sel = 'U' then z <= 'U'; else z <= 'X'; end if; -- Exercise 3 with fn select z <= a + b when "00", a - b when "01", a and b when "10", a and not b when "11"; -- Exercise 5 mux_adder : process ( sel, x, y, z, carry_in ) variable operand : unsigned(15 downto 0); begin case sel is when "00" => operand := x; when "01" => operand := y; when "10" => operand := z; when others => report "Illegal value for sel." severity error; end case; sum <= operand + carry_in; end process mux_adder;