【问题标题】:VHDL clock divider for controlling duty and phase用于控制占空比和相位的 VHDL 时钟分频器
【发布时间】:2019-01-12 07:34:12
【问题描述】:

我正在使用高速时钟(来自内部 PLL)并尝试将其分频以生成 2 个具有不同占空比和相位关系的时钟。如果我单步输入时钟,则代码运行正常。随着频率的增加,次级输出(代码示例中的 iDM_out)的相位和占空比被破坏。在某些频率下,次级输出的占空比是正确的。在其他频率下,占空比可能达到 90% 或 199%。相位关系(DMDelay)同上。我似乎有一些关于需要时钟缓冲器的文章,所以我在输出上尝试了几种类型的 BUFF、CLKBUF 和 CLKINT,这似乎使情况变得更糟。有人对可能导致这种情况的原因有任何想法吗?

use work.A208_pckgs.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity DutyPhaseMod is
    port (
        rst     : in std_logic; 
        GLA     : in std_logic;     -- GLA is 36x faster than target frequency
        EXDuty  : in std_logic_vector(4 downto 0);  -- the number of GLA clock cycles for the EX duty cycle
        DMDuty  : in std_logic_vector(4 downto 0);  -- the number of GLA clock cycles for the DM duty cycle
        DMDelay : in std_logic_vector(4 downto 0);  -- the number of GLA clock cycles for the DM phase delay

        EX_out  : out std_logic;
        DM_out  : out std_logic
    );                   
end entity;

architecture behavioral of DutyPhaseMod is
    signal iGLA     : std_logic;
    signal iFREQlen : integer range 0 to 35;
begin
    process (rst, GLA)
        variable iEX_out    : std_logic;
        variable iDM_out    : std_logic;
        variable iEXctr     : natural range 0 to 35;
        variable iDMctr     : natural range 0 to 35;
    begin
        iFREQlen <= 35;                             -- number of clock cycles

        if rst = '1' then                           -- reset the counters on reset signal
            iEXctr  := 0;
            iDMctr  := 0;
        elsif rising_edge(GLA) then
            if iEXctr <= unsigned(EXDuty) then      -- first part of EX the duty cycle
                iEX_out := '1';             
                iEXctr := iEXctr + 1;
            elsif iEXctr < iFREQlen then            -- second part of EX duty cycle
                iEX_out := '0';
                iEXctr := iEXctr + 1;
            else                                    -- set for the start of the next cycle
                iEX_out := '1'; 
                iEXctr := 0;
            end if;

            if iEXctr = unsigned(DMDelay) then      -- reset for DM phase offset
                iDMctr := 0;                            
            elsif iDMctr <= unsigned(DMDuty) then   -- first part of the DM duty cycle
                iDM_out := '1';
                iDMctr := iDMctr + 1;
            elsif iDMctr <= iFREQlen - 1 then       -- second part of the DM duty cycle
                iDM_out := '0';
                iDMctr := iDMctr + 1;
            else                                    -- set for the start of the next cycle
                iDM_out := '1';
            end if;

            EX_out <= iEX_out;
            DM_out <= iDM_out;

        end if;
    end process;
end behavioral;

【问题讨论】:

  • 什么是 199% 占空比?
  • 199 只是一个错字,意思是 100!

标签: vhdl


【解决方案1】:

我将不顾一切地回答我自己的问题。如果您觉得我的回答不正确,请随时发表评论(或者您可以进一步添加/澄清。)我决定将我的实体分成两个进程,它似乎工作正常。第一个进程在高速时钟的上升沿处理基本时钟分频。第二个进程在高速时钟的下降沿处理辅助(相位延迟)时钟。

        library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

    entity DutyPhaseMod is
        port (
            rst     : in std_logic; 
            GLA     : in std_logic;     
            EXDuty  : in std_logic_vector(3 downto 0);
            DMDuty  : in std_logic_vector(3 downto 0);
            DMDelay : in std_logic_vector(4 downto 0);

            EX_out  : out std_logic;
            DM_out  : out std_logic
        );                   
    end entity;

    architecture behavioral of DutyPhaseMod is
        signal iGLA     : std_logic;
        signal iFREQlen : integer range 0 to 35;
        signal iEXctr   : natural range 0 to 35;
    begin
        process (rst, GLA)
            variable iEX_out    : std_logic;
        begin
            iFREQlen <= 35;

            if rst = '1' then
                iEXctr  <= 0;
            elsif rising_edge(GLA) then

                if iEXctr <= unsigned(EXDuty) then
                    iEX_out := '1';                         --
                    iEXctr <= iEXctr + 1;
                elsif iEXctr < iFREQlen then
                    iEX_out := '0';
                    iEXctr <= iEXctr + 1;
                else
                    iEX_out := '1';
                    iEXctr <= 0;
                end if;

                EX_out <= iEX_out;
            end if;
        end process;

        process (rst, GLA)
            variable iDM_out    : std_logic;
            variable iDMctr     : natural range 0 to 30;
        begin
            case FW_FREQ is
            when F_46 =>
                iFREQlen <= 35;
            when F_82 =>
                iFREQlen <= 23;
            end case;

            if rst = '1' then
                iDMctr  := 0;
            elsif falling_edge(GLA) then
                if iEXctr = unsigned(DMDelay) then  
                    iDMctr := 0;                
                elsif iDMctr <= unsigned(DMDuty) then
                    iDM_out := '1';
                    iDMctr := iDMctr + 1;
                elsif iDMctr <= iFREQlen - 1 then
                    iDM_out := '0';
                    iDMctr := iDMctr + 1;
                else
                    iDM_out := '1';
                end if;

                DM_out <= iDM_out;
            end if;
        end process;
    end behavioral;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多