首页 文章

在非时钟信号上使用rising_edge是不是很糟糕?还有替代品吗?

提问于
浏览
2

我正在研究VHDL设计并且我已经开始工作了,但是代码非常丑陋,事实上我似乎正在努力解决语言设计以实现我的目标,这让我觉得有些不对劲 . 我是VHDL的新手,但是我已经在这个项目的小块工作了将近一个月,所以我有了一般的想法 . 但是,这部分有点复杂 .

我需要一个在信号上升沿(END_ADC)之后产生一个时钟周期长脉冲(LOAD_PULSE)的过程,但是直到从该信号的最新上升沿(END_ADC)经过4个时钟或者下降沿为止 . 第二个信号(LVAL) .

为了完成等待期,我 Build 了一个计数微秒和周期的计时器模块,这里:

entity uS_generator is
    generic(
        Frequency       : integer := 66                                     -- Frequency in MHz
    );
    Port ( 
        CLK     : in STD_LOGIC;
        RESET   : in STD_LOGIC;
        T_CNT   : out integer range Frequency downto 1 := 1;
        uS_CNT  : out integer range 65535 downto 0 := 0
    );
end uS_generator;

architecture behavior of uS_generator is

    signal T_CNT_INT        : integer range Frequency downto 1 := 1;        -- Counter for 1 uS
    signal uS_CNT_INT       : integer range 65535 downto 0 := 0;

begin

    COUNT: process(CLK, RESET)
    begin
        if RESET = '1' then
            T_CNT_INT   <= 1;
            uS_CNT_INT  <= 0;
        elsif rising_edge(CLK) then
            if T_CNT_INT = (Frequency - 1) then                             -- Increment one clock early so last rising edge sees one uS elapsed.
                uS_CNT_INT <= uS_CNT_INT + 1;
                T_CNT_INT <= T_CNT_INT + 1;
                if uS_CNT_INT = 65535 then
                    uS_CNT_INT <= 0;
                end if;
            elsif T_CNT_INT = Frequency then
                T_CNT_INT <= 1;
            else
                T_CNT_INT <= T_CNT_INT + 1;
            end if;
        end if;
    end process COUNT;

    T_CNT   <= T_CNT_INT;
    uS_CNT  <= uS_CNT_INT;

end behavior;

我用于设计脉冲生成部分的过程如下:

loadPulseProc: process(PIXEL_CLK, END_ADC, RESET)
begin

    if RESET = '1' then
        PULSE_FLAG <= '0';
        LOAD_PULSE <= '0';
    elsif rising_edge(END_ADC) then
        PULSE_FLAG <= '1';
    end if;

    if rising_edge(PIXEL_CLK) then
        if PULSE_FLAG = '1' and END_ADC = '1' and LVAL <= '0' and ADC_TMR_T >= 4 and LVAL_TMR_T >= 4 then
            LOAD_PULSE <= '1', '0' after PIXEL_CLK_T;
            PULSE_FLAG <= '0';
        end if;
    end if;

end process loadPulseProc;

ADCTimerProc: process(END_ADC, RESET)
begin

    if RESET = '1' then
        ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
    end if;

    if rising_edge(END_ADC) then
        ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
    end if;

    if falling_edge(END_ADC) then
        ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
    end if;

end process ADCTimerProc;

LVALTimerProc: process(LVAL, RESET)
begin

    if RESET = '1' then
        LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
    end if;

    if rising_edge(LVAL) then
        LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
    end if;

    if falling_edge(LVAL) then
        LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
    end if;         

end process LVALTimerProc;

PIXEL_CLK_T是时钟周期,15.152 ns .

这个设计工作,仿真表明它按照我的要求,但只有在重大麻烦之后才能避免因使用fall_edge调用的多个rising_edge而导致的错误,将它们分成真正应该在一起的单独的if语句 . 据我所知,使用rising_edge和falling_edge似乎只保留给时钟,所以这只是不好的做法?如何避免这种行为,但仍然创建相同的输出?

谢谢!

1 回答

  • 7

    是的, rising_edge()/falling_edge() 只应用于时钟信号 . 虽然它在仿真中工作,但它可能会导致问题和合成中的意外硬件 .

    综合工具从函数的参数推断出时钟,并将这些信号/线放在FPGA的特殊轨道上(假设您的目标是FPGA用于您的设计) . 该工具将进一步推断特殊时钟缓冲器,并在输入时钟引脚不是时钟引脚时发出警告 .

    引入几个时钟会导致异步设计,并使其易受跨时钟故障的影响 .

    检测信号的上升沿或下降沿由边缘检测电路完成,如下所述,它将前一个时钟周期中的信号与当前值进行比较 .

    需要的信号:

    signal mySignal_d : std_logic := '0'; 
    signal mySignal_re : std_logic;
    

    需要的逻辑:

    mySignal_d <= mySignal when rising_edge(Clock); 
    mySignal_re <= not mySignal_d and mySignal;
    

    第一行转换为1位D触发器(您也可以使用进程) . 当 mySignal 从低变为高时,第二行产生一个周期选通信号 . 我正在使用 *_d 表示原始输入的延迟信号,而 *_re 表示上升沿 .

    生成的信号仍然与 Clock 同步 .

相关问题