VHDL Code für Versuch 5
- top.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library altera; use altera.altera_primitives_components.all; entity top is port ( CLOCK_24: in std_ulogic_vector(1 downto 0); KEY: in std_ulogic_vector(3 downto 0); SW: in std_ulogic_vector(9 downto 0); I2C_SCLK: out std_ulogic; I2C_SDAT: inout std_logic; AUD_ADCLRCK: out std_ulogic; AUD_ADCDAT: in std_ulogic; AUD_DACLRCK: out std_ulogic; AUD_DACDAT: out std_ulogic; AUD_XCK: out std_ulogic; AUD_BCLK: out std_ulogic; LEDR: out std_ulogic_vector(9 downto 0); HEX0: out std_ulogic_vector(6 downto 0) ); end; architecture struct of top is component i2c_sub is port ( clk_i: in std_ulogic; reset_ni: in std_ulogic; i2c_clk_o: out std_ulogic; i2c_dat_o: out std_ulogic; i2c_dat_i: in std_ulogic ); end component; component adcintf is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; en_i : in std_ulogic; valid_o : out std_ulogic; data_o : out std_ulogic_vector(15 downto 0); start_i : in std_ulogic; ser_dat_i : in std_ulogic); end component; component dacintf is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; load_i : in std_ulogic; data_i : in std_ulogic_vector(15 downto 0); en_i : in std_ulogic; ser_dat_o : out std_ulogic); end component; component ringbuf is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; en_i : in std_ulogic; data_i : in std_ulogic_vector(15 downto 0); data_o : out std_ulogic_vector(15 downto 0)); end component; component bclk is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; bclk_o : out std_ulogic; bclk_falling_edge_en_o : out std_ulogic); end component; component fsgen is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; bclk_falling_edge_en_i : in std_ulogic; fs_o : out std_ulogic); end component; component mclk is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; mclk_o : out std_ulogic); end component; signal clk, reset_n : std_ulogic; signal i2c_dat_o : std_ulogic; signal i2c_dat_i : std_ulogic; signal framesync : std_ulogic; signal bclk_falling_edge_en : std_ulogic; signal adc_valid : std_ulogic; signal dac_data, adc_data : std_ulogic_vector(15 downto 0); begin reset_n <= KEY(0); clk <= CLOCK_24(0); i2c_sub_i0 : i2c_sub port map ( clk_i => clk, reset_ni => reset_n, i2c_clk_o => I2C_SCLK, i2c_dat_o => i2c_dat_o, i2c_dat_i => i2c_dat_i); mclk_i0 : mclk port map( clk_i => clk, reset_ni => reset_n, mclk_o => AUD_XCK); bclk_i0 : bclk port map ( clk_i => clk, reset_ni => reset_n, bclk_o => AUD_BCLK, bclk_falling_edge_en_o => bclk_falling_edge_en); fsgen_i0 : fsgen port map ( clk_i => clk, reset_ni => reset_n, bclk_falling_edge_en_i => bclk_falling_edge_en, fs_o => framesync); dacintf_i0 : dacintf port map ( clk_i => clk, reset_ni => reset_n, load_i => framesync, data_i => dac_data, en_i => bclk_falling_edge_en, ser_dat_o => AUD_DACDAT); adcintf_i0 : adcintf port map ( clk_i => clk, reset_ni => reset_n, valid_o => adc_valid, data_o => adc_data, start_i => framesync, en_i => bclk_falling_edge_en, ser_dat_i => AUD_ADCDAT); AUD_DACLRCK <= framesync; AUD_ADCLRCK <= framesync; ringbuf_i0 : ringbuf port map ( clk_i => clk, reset_ni => reset_n, en_i => adc_valid, data_i => adc_data, data_o => dac_data); LEDR(9 downto 0) <= std_ulogic_vector(abs(signed(dac_data(15 downto 6)))); HEX0 <= "0000000"; -- i2c has an open-drain ouput i2c_dat_i <= I2C_SDAT; i2c_data_buffer_i : OPNDRN port map (a_in => i2c_dat_o, a_out => I2C_SDAT); end; -- architecture
- top_tb.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity top_tb is end; architecture beh of top_tb is component top is port ( CLOCK_24: in std_ulogic_vector(1 downto 0); KEY: in std_ulogic_vector(3 downto 0); SW: in std_ulogic_vector(9 downto 0); I2C_SCLK: out std_ulogic; I2C_SDAT: inout std_ulogic; AUD_ADCLRCK: out std_ulogic; AUD_ADCDAT: in std_ulogic; AUD_DACLRCK: out std_ulogic; AUD_DACDAT: out std_ulogic; AUD_XCK: out std_ulogic; AUD_BCLK: out std_ulogic; LEDR: out std_ulogic_vector(9 downto 0); HEX0: out std_ulogic_vector(6 downto 0) ); end component; signal clk, reset_n : std_ulogic; signal switch, ledr : std_ulogic_vector(9 downto 0); signal hex : std_ulogic_vector(6 downto 0); signal i2c_clk, i2c_dat : std_ulogic; signal key : std_ulogic_vector(3 downto 0); signal aud_adclrck, aud_adcdat, aud_daclrck, aud_dacdat, aud_xck, aud_bclk : std_ulogic; signal clk24 : std_ulogic_vector(1 downto 0); begin top_i0 : top port map ( CLOCK_24 => clk24, KEY => key, SW => switch, I2C_SCLK => i2c_clk, I2C_SDAT => i2c_dat, AUD_ADCLRCK => aud_adclrck, AUD_ADCDAT => aud_adcdat, AUD_DACLRCK => aud_daclrck, AUD_DACDAT => aud_dacdat, AUD_XCK => aud_xck, AUD_BCLK => aud_bclk, LEDR => ledr, HEX0 => hex); clock_p : process begin clk <= '0'; wait for 21 ns; clk <= '1'; wait for 21 ns; end process clock_p; clk24(0) <= clk; reset_p : process begin reset_n <= '0'; wait for 15 us; reset_n <= '1'; wait; end process reset_p; key(0) <= reset_n; key(3 downto 1) <= "000"; switch <= "0000000000"; aud_adcdat <= '1'; end; -- architecture
- mclk.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- Master Clock Generator -- Generate 12 MHz from 24 MHz entity mclk is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; mclk_o : out std_ulogic); end; architecture rtl of mclk is signal mclk : std_ulogic; begin mclk_p : process(clk_i, reset_ni) begin if reset_ni = '0' then mclk <= '0'; elsif rising_edge(clk_i) then mclk <= not mclk; end if; end process mclk_p; mclk_o <= mclk; end; -- architecture
- fsgen.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- Frame Sync Generator -- The framesync is active for one bitclock cycle entity fsgen is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; bclk_falling_edge_en_i : in std_ulogic; fs_o : out std_ulogic); end; architecture rtl of fsgen is signal counter : integer range 0 to 63; begin fs_cnt_p : process(clk_i, reset_ni) begin if reset_ni = '0' then counter <= 0; fs_o <= '0'; elsif rising_edge(clk_i) then if bclk_falling_edge_en_i = '1' then fs_o <= '0'; if counter = 63 then counter <= 0; fs_o <= '1'; else counter <= counter + 1; end if; end if; end if; end process fs_cnt_p; end; -- architecture
- bclk.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- Bitclock generator entity bclk is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; bclk_o : out std_ulogic; bclk_falling_edge_en_o : out std_ulogic); end; architecture rtl of bclk is signal clk_counter : integer range 0 to 47; signal bclk_rising_edge_en : std_ulogic; signal bclk_falling_edge_en : std_ulogic; begin bclk_cnt_p : process(clk_i, reset_ni) begin if reset_ni = '0' then clk_counter <= 0; elsif rising_edge(clk_i) then if clk_counter = 47 then clk_counter <= 0; else clk_counter <= clk_counter + 1; end if; end if; end process bclk_cnt_p; edge_comb_p : process(clk_counter) begin bclk_rising_edge_en <= '0'; bclk_falling_edge_en <= '0'; if clk_counter = 47 then bclk_rising_edge_en <= '1'; end if; if clk_counter = 23 then bclk_falling_edge_en <= '1'; end if; end process edge_comb_p; bclk_p : process(clk_i, reset_ni) begin if reset_ni = '0' then bclk_o <= '0'; elsif rising_edge(clk_i) then if bclk_rising_edge_en = '1' then bclk_o <= '1'; elsif bclk_falling_edge_en = '1' then bclk_o <= '0'; end if; end if; end process bclk_p; bclk_falling_edge_en_o <= bclk_falling_edge_en; end; -- architecture
- i2c_sub.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity i2c_sub is port ( clk_i: in std_ulogic; reset_ni: in std_ulogic; i2c_dat_o: out std_ulogic; i2c_dat_i: in std_ulogic; i2c_clk_o: out std_ulogic); end; architecture struct of i2c_sub is component i2c is port ( clk_i: in std_ulogic; reset_ni: in std_ulogic; load_i: in std_ulogic; data_i: in std_ulogic_vector(23 downto 0); i2c_clk_o: out std_ulogic; i2c_dat_o: out std_ulogic; i2c_dat_i: in std_ulogic; busy_o: out std_ulogic ); end component; component i2c_write is port ( clk_i: in std_ulogic; reset_ni: in std_ulogic; load_o: out std_ulogic; data_o: out std_ulogic_vector(23 downto 0); busy_i: in std_ulogic); end component; signal load, busy : std_ulogic; signal data : std_ulogic_vector(23 downto 0); begin i2c_i0 : i2c port map ( clk_i => clk_i, reset_ni => reset_ni, load_i => load, data_i => data, i2c_clk_o => i2c_clk_o, i2c_dat_o => i2c_dat_o, i2c_dat_i => i2c_dat_i, busy_o => busy); i2_write_i0 : i2c_write port map ( clk_i => clk_i, reset_ni => reset_ni, load_o => load, data_o => data, busy_i => busy); end; -- architecture
- i2c.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- I2C or 2-Wire Bus -- To start a transaction, pull the data line to 'L' while the clock is still 'H' -- 7 Bits Address -- 1 Bit R/W (0 = Write, 1 = Read) -- 1 Bit ACK (from Slave 0 if o.k.) -- 8 Bits Data 15..8 -- 1 Bit Ack from slave (0 if o.k.) -- 8 Bits Data 7..0 -- 1 Bit Ack from slave (0 if o.k.) entity i2c is port ( clk_i: in std_ulogic; reset_ni: in std_ulogic; load_i: in std_ulogic; data_i: in std_ulogic_vector(23 downto 0); i2c_clk_o: out std_ulogic; i2c_dat_o: out std_ulogic; i2c_dat_i: in std_ulogic; busy_o: out std_ulogic ); end; architecture rtl of i2c is -- Clock divider section constant fd_c : integer := 24000000/20000/2; -- 24 MHz system clock, 20 kHz I2C clock signal clk_cnt : integer range 0 to fd_c; signal clk_cnt_reset, clk_cnt_done : std_ulogic; -- i2c data register index signal idx : integer range 0 to 27; signal idx_inc : std_ulogic; signal idx_reset : std_ulogic; -- i2c registers with and without data for the acknowledgment section -- In cycle 8, 17 and 26 there is an i2c acknowledgement cycle where the master -- drives Z and the slave will drive "0" when everything is o.k. -- The input data from the interface is without these acknowledgement bits signal load_i2c_reg_without_ack : std_ulogic; signal i2c_reg_without_ack : std_ulogic_vector(23 downto 0); signal i2c_reg_with_ack : std_ulogic_vector(0 to 27); -- Statemachine type state_t is (idle_s, start_s, data_hold_s, data_s, clock_high_s, stop_s); signal state, next_state : state_t; -- Selection for the i2c output data type i2c_dat_sel_t is (sel_old, sel_reg, sel_one, sel_zero); signal i2c_dat_sel : i2c_dat_sel_t; type i2c_clk_sel_t is (sel_old, sel_one, sel_zero); signal i2c_clk_sel : i2c_clk_sel_t; signal i2c_clk : std_ulogic; signal i2c_clk_new : std_ulogic; signal i2c_dat : std_ulogic; signal i2c_dat_new : std_ulogic; begin -- i2c register with ack build from i2c without ack -- i2c data is transmitted msb first, so bus direction is changed also i2c_reg_with_ack(0 to 7) <= i2c_reg_without_ack(23 downto 16); i2c_reg_with_ack(8) <= '1'; i2c_reg_with_ack(9 to 16) <= i2c_reg_without_ack(15 downto 8); i2c_reg_with_ack(17) <= '1'; i2c_reg_with_ack(18 to 25) <= i2c_reg_without_ack(7 downto 0); i2c_reg_with_ack(26) <= '1'; i2c_reg_with_ack(27) <= '0'; -- This process counts the clocks for reducing the clock speed -- of the i2c clock clk_cnt_p : process(clk_i, reset_ni) begin if reset_ni = '0' then clk_cnt <= 0; elsif rising_edge(clk_i) then if clk_cnt < fd_c then clk_cnt <= clk_cnt + 1; end if; if clk_cnt_reset = '1' then clk_cnt <= 0; end if; end if; end process clk_cnt_p; clk_cnt_done <= '1' when clk_cnt = fd_c else '0'; -- This is the index for the i2c register. i2c_idx_p : process(clk_i, reset_ni) begin if reset_ni = '0' then idx <= 0; elsif rising_edge(clk_i) then if idx_inc = '1' and idx < 27 then idx <= idx + 1; end if; if idx_reset = '1' then idx <= 0; end if; end if; end process i2c_idx_p; -- This are the registered outputs for the i2c clock and data i2c_out_p : process(clk_i, reset_ni) begin if reset_ni = '0' then i2c_clk <= '1'; i2c_dat <= '1'; elsif rising_edge(clk_i) then i2c_dat <= i2c_dat_new; i2c_clk <= i2c_clk_new; end if; end process i2c_out_p; -- The i2c register without ack data i2c_data_p : process(clk_i, reset_ni) begin if reset_ni = '0' then i2c_reg_without_ack <= (others => '0'); elsif rising_edge(clk_i) then if load_i2c_reg_without_ack = '1' then i2c_reg_without_ack <= data_i; end if; end if; end process i2c_data_p; -- i2c data selection process i2c_dat_sel_p : process(i2c_dat_sel, i2c_reg_with_ack, i2c_dat, idx) begin case i2c_dat_sel is when sel_old => i2c_dat_new <= i2c_dat; when sel_reg => i2c_dat_new <= i2c_reg_with_ack(idx); when sel_one => i2c_dat_new <= '1'; when sel_zero => i2c_dat_new <= '0'; when others => i2c_dat_new <= '0'; end case; end process i2c_dat_sel_p; -- i2c clock selection process i2c_clk_sel_p : process(i2c_clk, i2c_clk_sel) begin case i2c_clk_sel is when sel_old => i2c_clk_new <= i2c_clk; when sel_one => i2c_clk_new <= '1'; when sel_zero => i2c_clk_new <= '0'; when others => i2c_clk_new <= '0'; end case; end process i2c_clk_sel_p; -- Sequential process for the statemachine statem_seq_p : process(clk_i, reset_ni) begin if reset_ni = '0' then state <= idle_s; elsif rising_edge(clk_i) then state <= next_state; end if; end process statem_seq_p; statem_comb_p: process(state, load_i, idx, clk_cnt_done) begin load_i2c_reg_without_ack<= '0'; idx_inc <= '0'; idx_reset <= '0'; clk_cnt_reset <= '0'; busy_o <= '1'; i2c_dat_sel <= sel_old; i2c_clk_sel <= sel_old; next_state <= state; case state is when idle_s => busy_o <= '0'; i2c_clk_sel <= sel_one; i2c_dat_sel <= sel_one; if load_i = '1' then load_i2c_reg_without_ack <= '1'; clk_cnt_reset <= '1'; idx_reset <= '1'; next_state <= start_s; i2c_dat_sel <= sel_zero; end if; when start_s => if clk_cnt_done = '1' then next_state <= data_hold_s; clk_cnt_reset <= '1'; i2c_clk_sel <= sel_zero; end if; when data_hold_s => next_state <= data_s; i2c_dat_sel <= sel_reg; when data_s => if clk_cnt_done = '1' then next_state <= clock_high_s; i2c_clk_sel <= sel_one; clk_cnt_reset <= '1'; end if; when clock_high_s => if clk_cnt_done = '1' then if idx = 27 then -- last bit transmitted i2c_dat_sel <= sel_one; next_state <= stop_s; else idx_inc <= '1'; i2c_clk_sel <= sel_zero; next_state <= data_hold_s; end if; clk_cnt_reset <= '1'; end if; when stop_s => if clk_cnt_done = '1' then next_state <= idle_s; end if; when others => next_state <= idle_s; end case; end process statem_comb_p; i2c_clk_o <= i2c_clk; i2c_dat_o <= i2c_dat; end; -- architecture
- i2c_write.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity i2c_write is port ( clk_i: in std_ulogic; reset_ni: in std_ulogic; load_o: out std_ulogic; data_o: out std_ulogic_vector(23 downto 0); busy_i: in std_ulogic); end; architecture rtl of i2c_write is constant num_regs_c : integer := 12; type state_t is (start_s, wait_s, done_s); signal state, next_state : state_t; signal counter : integer range 0 to num_regs_c-1; signal counter_enable : std_ulogic; type data_array_t is array(0 to num_regs_c-1) of std_ulogic_vector(23 downto 0); constant data_array : data_array_t := ( X"341200", -- Set Inactive X"341E00", -- Reset the Device X"34001A", -- Left Line In / Mute off / Volume X"34021A", -- Right Line In X"34047F", -- Headphone Left X"34067F", -- Headphone Right X"340815", -- Analog path control (MIC to ADC, DAC to output, MIC Boost) X"340A00", -- Digital path control X"340C61", -- Power Down Control (Everything switched on) X"340E13", -- Digital Audio Interface Format (Slave Mode, DSP Mode, 16 Bit) X"34100C", -- Sampling Control (8 kHz Sampling frequency, 12.288 MHz MCLK frequency) X"341201"); -- Active Control (Activate) begin seq_p : process(clk_i, reset_ni) begin if reset_ni = '0' then state <= start_s; counter <= 0; elsif rising_edge(clk_i) then state <= next_state; if counter_enable = '1' then if counter < num_regs_c - 1 then counter <= counter + 1; else counter <= 0; end if; end if; end if; end process seq_p; data_o <= data_array(counter); process(state, counter, busy_i) begin load_o <= '0'; counter_enable <= '0'; next_state <= state; case state is when start_s => load_o <= '1'; next_state <= wait_s; when wait_s => if busy_i = '0' then if counter = num_regs_c-1 then next_state <= done_s; --counter_enable <= '1'; else next_state <= start_s; counter_enable <= '1'; end if; end if; when others => next_state <= state; end case; end process; end; -- architecture
- memory.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- This VHDL memory description will result in FPGA memory usage. -- The EPC2C20 series provides a total of 52 M4K memory blocks -- Each M4K memory block contains 4608 Bits. The following configurations are supported: -- 4K 1, 2K 2, 1K 4, 512 8, 512 9, 256 16, 256 18 -- The maximum is therefore 52 x 256 = 13312 samples. entity memory is port ( clk_i : in std_ulogic; we_i : in std_ulogic; waddr_i : in unsigned(12 downto 0); raddr_i : in unsigned(12 downto 0); wdata_i : in std_ulogic_vector(15 downto 0); rdata_o : out std_ulogic_vector(15 downto 0) ); end; architecture rtl of memory is type ram_t is array(0 to 2 ** 13 - 1) of std_ulogic_vector(15 downto 0); signal ram : ram_t; begin mem_p : process(clk_i) begin if rising_edge(clk_i) then if we_i = '1' then ram(to_integer(waddr_i)) <= wdata_i; end if; rdata_o <= ram(to_integer(raddr_i)); end if; end process mem_p; end; -- architecture
- adcintf.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- ADC (Analog to Digital Converter) Interface -- Shifts in 16 bits and provides the data in parallel -- When all 16 bits are shifted in, the valid_o output is set to "1" for one clock cycle entity adcintf is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; en_i : in std_ulogic; valid_o : out std_ulogic; data_o : out std_ulogic_vector(15 downto 0); start_i : in std_ulogic; ser_dat_i : in std_ulogic); end; architecture rtl of adcintf is begin seq_p : process(clk_i, reset_ni) begin if reset_ni = '0' then elsif rising_edge(clk_i) then end if; end process seq_p; statem_comb_p : process(start_i) begin valid_o <= '0'; end process statem_comb_p; end; -- architecture
- dacintf.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- DAC (Digital to Analog Converter) Interface -- Loads a word in parallel and shifts it out as serial bit stream -- The data needs to be shifted out twice. This is required as -- the audio interface needs stereo data. entity dacintf is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; load_i : in std_ulogic; data_i : in std_ulogic_vector(15 downto 0); en_i : in std_ulogic; ser_dat_o : out std_ulogic); end; architecture rtl of dacintf is begin load_and_shift_p : process(clk_i, reset_ni) begin if reset_ni = '0' then elsif rising_edge(clk_i) then end if; end process load_and_shift_p; ser_dat_o <= '0'; end; -- architecture
- ringbuf.vhd
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- Ring Buffer stores samples in a circular buffer -- The read buffer pointer is one buffer entry ahead -- of the write buffer pointer. entity ringbuf is port ( clk_i : in std_ulogic; reset_ni : in std_ulogic; en_i : in std_ulogic; data_i : in std_ulogic_vector(15 downto 0); data_o : out std_ulogic_vector(15 downto 0)); end; architecture rtl of ringbuf is component memory is port ( clk_i : in std_ulogic; we_i : in std_ulogic; waddr_i : in unsigned(12 downto 0); raddr_i : in unsigned(12 downto 0); wdata_i : in std_ulogic_vector(15 downto 0); rdata_o : out std_ulogic_vector(15 downto 0) ); end component; signal raddr, waddr : unsigned(12 downto 0); begin mem_i0 : memory port map ( clk_i => clk_i, we_i => en_i, raddr_i => raddr, waddr_i => waddr, rdata_o => data_o, wdata_i => data_i); buffer_pointer_p : process(clk_i, reset_ni) begin if reset_ni = '0' then elsif rising_edge(clk_i) then end if; end process buffer_pointer_p; end; -- architecture