时钟配置 - VHDL编码Altera DE1音频编解码器芯片

时间:2017-04-27 06:07:11

标签: vhdl fpga intel-fpga

我正在开发一个项目,我需要在Altera DE1板上编码WM8731音频编解码器芯片。该项目非常基础。它不需要处理输入音频信号。来自输入的信号应直接中继到输出。

主要任务是通过I2C协议设置编解码器芯片。我是VHDL的新手,我在理解这个概念时遇到了一些问题。

在使用之前,需要对编解码器芯片进行初始化。这包括通过I2C传递数据集。下面给出要传递的数据以及描述。

    constant sdin_load : std_logic_vector (11*24-1 downto 0) 
    --this contains codec configuration data

问题 - 主时钟频率为50MHz,I2C总线频率为100KHz。所以项目要求:
1)声明位计数器; - 位计数器,运行频率为100kHz,
2)声明字计数器; - 字计数器,运行在大约5kHz
3)声明计数器的位长; - 分频器计数器,运行频率为50MHz

据我所知,由于主时钟和I2C时钟频率不同,我们需要有一个计数器来跟踪事件。我的理解:
1)位计数器可以从1到500计数,即50MHz / 100KHz。因此,每当计数器转到500时,传输下一位信息。
2)这是我不理解的部分。如果字计数器以5KHz运行,那么它将只计算20个I2C时钟脉冲(100KHz / 5KHz)而不是它发送的29位信息。
3)最后,为什么我们需要声明一个运行在50MHz的位长的计数器?我们已经按照这个频率运行了时钟。

我们已经获得了示例代码。用于执行计数器。我附上完整的架构供参考。

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;

感谢。

1 个答案:

答案 0 :(得分:1)

这可能不是您正在寻找的答案,但我会发布它可能有用。

如果您的主要目标是仅对音频芯片进行编程,而不一定使用I2C协议,则可以使用I2C模块,例如OpenCores。你可以找到很好的项目。我不能推荐特定的I2C,但你可以尝试很多I2C项目。

另一个可以尝试寻找IP的地方是Altera的IP库。我不知道那里是否有I2C,因为我使用Xilinx设备,但你可以试试。

编辑: 好的,我还会更多地提到实际问题,可能是你真正实现i2c的任务。 据我所知,你被要求有计数器,而不是时钟。这不一样。而对于这个5KHz - 据说它将 5KHz,可能是因为你已经指出的原因。 如果你问这个计数器需要什么,我想:

  1. 发送数据的时钟
  2. 你必须知道何时停止传播。
  3. 这是用于比特长度,所以这个50MHz应该是50KHz?这会更合理。
  4. 仔细阅读本代码的评论内容。