Я работаю над проектом, в котором от меня требуется кодировать микросхему аудиокодека WM8731 на плате Altera DE1. Проект очень простой. Нет необходимости обрабатывать входящие аудиосигналы. Сигнал со входа должен напрямую передаваться на выход.
Основная задача - настроить микросхему кодека по протоколу I2C. Я новичок в VHDL, и у меня возникли проблемы с пониманием концепции.
Перед использованием чип кодека необходимо инициализировать. Он состоит из передачи наборов данных через I2C. Передаваемые данные приведены ниже вместе с описанием.
constant sdin_load : std_logic_vector (11*24-1 downto 0)
--this contains codec configuration data
Проблема - основная тактовая частота составляет 50 МГц, а частота шины I2C - 100 кГц. Итак, проекты просят:
1) объявить счетчик битов; - битовый счетчик, работает на частоте 100кГц,
2) объявить счетчик слов; - счетчик слов, работает на частоте около 5 кГц
3) объявить счетчик длины в битах; - счетчик делителя частоты, работающий на частоте 50 МГц
Я понимаю, что, поскольку основные часы и часы I2C имеют разную частоту, нам нужен счетчик для отслеживания событий. Насколько я понимаю:
1) Битовый счетчик может считать от 1 до 500, что составляет 50 МГц / 100 кГц. Таким образом, всякий раз, когда счетчик достигает 500, передается следующий бит информации.
2) Это та часть, которую я не понимаю. Если счетчик слов работает на частоте 5 кГц, он будет считать только 20 импульсов тактовой частоты I2C (100 кГц / 5 кГц), а не 29 бит информации, которую он отправляет.
3) Наконец, зачем нам объявлять счетчик длины в битах, работающий на частоте 50 МГц? У нас уже есть часы, работающие на этой частоте.
Нам дали образец кода. для реализации счетчика. Я прилагаю полную архитектуру для справки.
library ieee;
use ieee.std_logic_1164.all;
entity codec_init is
port
(
CLOCK_50 : in std_logic; -- master clock
RES_N : in std_logic; -- reset, active 0
SCLK : out std_logic; -- serial clock
SDIN : out std_logic -- serial data
);
end entity;
architecture rtl of codec_init is
constant sdin_load : std_logic_vector (11*24-1 downto 0)
--this contains codec configuration data
begin
process (CLOCK_50)
begin
if (rising_edge(CLOCK_50)) then
-- reset actions
if (RES_N = '0') then
-- reset the counters to an appropriate state
...; -- load the frequency divider,
-- 50MHz/500=100kHz bus speed
...; -- load the shift register
...; -- load the bit counter,
-- 29 bits in the word protocol
...; -- load the word counter, 11 words
-- reset the outputs to an appropriate state
...;
...;
elsif (...) then -- deadlock in the end
-- do nothing, wait for the next reset
-- modify reference counters
-- for frequency divider, bits and words
elsif (...) then -- at the end of each bit
...; -- reload the frequency divider counter
if (bcnt = 0) then -- at the end of each word
...; -- reset the bit counter
...; --modify the word counter
else -- the bit is not the end of a word
...; --modify the bit counter
end if;
else -- if not the end of the bit
...; -- modify the frequency divider
end if;
-- generating SCLK, it is going up and then down inside each bit
if (...) then -- condition when SCLK goes up
...;
elsif (...) then -- condition when SCLK goes down
...;
end if;
-- generating serial data output
if (...) then -- start transition condition
...;
elsif (...) then -- ack bit condition
...;
elsif (...) then -- stop transition condition
...;
elsif(...) then -- condition for the non-special bits
...; -- shifting
...;
end if;
-----------------------------
end if;
end process;
-- forming the output with high impedance states for ack-s
SDIN <= 'Z' when (...condition for ack bits...)
else (sdout);
end rtl;
Спасибо.