本文介绍了VHDL:在一个处理块中进行多次上升边缘检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对VHDL(和一般的数字电路)还很陌生,我正在尝试使用BCD样式块实现两位数的计数器.在该电路的外部将有一些按钮,按下这些按钮将使感兴趣的数字增加一个(就像闹钟一样).这是一个异步操作,在某种形式的编辑模式下(外部强制执行)会发生.我编写的代码在没有"elsifrise_edge(digitUp1 then then)"和"elsifriseing_edge(digitUp1 then then)"的情况下可以正常工作,但是包含它们失败.我真的不知道为什么它不起作用或如何解决.不断出现错误,例如无法在此时钟沿实现寄存器分配",无法推断count2 [3]的寄存器,因为其行为取决于多个不同时钟的边沿"和无法推断针对的时钟" MinuteCounter.vhd(21)处的count2 [3],因为它不在时钟沿之外保持其值".任何帮助将不胜感激.

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;

-- ToDo: ENFORCE ON ALL COUNTERS (externally) LOGIC TO PAUSE AT MAX/MIN

entity MinuteCounter is
port( clockIn, digitUp1, digitUp2, reset, counting, countUp : in std_logic;
      clockOut : out std_logic;
      BCD1, BCD2 : out std_logic_vector(3 downto 0));
end MinuteCounter;

architecture structure of MinuteCounter is
signal count1, count2 : std_logic_vector(3 downto 0);
signal carryOut : std_logic;
begin

process( clockIn, digitUp1, digitUp2, countUp, reset, counting)
begin 

    -- Asynchronous reset
    if reset = '1' then
        count1 <= "0000";
        count2 <= "0000";

    -- What to run when there's an active edge of the clock
    elsif rising_edge(clockIn) then

        -- Code to run when timer is running
        if counting = '1' then

            -- What to do when counting up
            if countUp = '1' then
                if ((count1 = "1001") and (count2 = "0101")) then
                    count1 <= "0000";
                    count2 <= "0000";
                    if carryOut = '0' then
                        carryOut <= '1';
                    else
                        carryOut <= '0';
                    end if;
                elsif count1 = "1001" then
                    count1 <= "0000";
                    count2 <= count2 + 1;
                else
                    count1 <= count1 + 1;
                end if;

            -- What to do when counting down (This logic is hard to understand)
            else
                if ((count1 = "0000") and (count2 = "0000")) then
                    count1 <= "1001";
                    count2 <= "0101";
                    if carryOut = '0' then
                        carryOut <= '1';
                    else
                        carryOut <= '0';
                    end if;
                elsif count1 = "0000" then
                    count1 <= "1001";
                    count2 <= count2 - 1;
                else
                    count1 <= count1 - 1;
                end if;
            end if;

        -- When counting is disabled, but there is an active edge (do nothing)
        else
            count1 <= count1;
            count2 <= count2;
        end if;

    -- Code to run when entering values (will not be run if counting = '1') << Externally enforced
    elsif rising_edge(digitUp1) then
        if count1 = "1001" then
            count1 <= "0000";
            count1 <= count1 + 1;
        else
            count1 <= count1 + 1;
        end if;

    -- Code to run when entering values (will not be run if counting = '1') << Externally enforced
    elsif rising_edge(digitUp2) then
        if count2 = "0101" then
            count2 <= "0000";
            count2 <= count2 + 1;
        else
            count2 <= count2 + 1;
        end if;

    -- What to do when there is no active edge or other events (nothing)
    else
        count1 <= count1;
        count2 <= count2;
    end if;

end process;

-- Assign outputs
BCD1 <= count1;
BCD2 <= count2;
clockOut <= carryOut;

end structure;
解决方案

问题标题中说明了为什么不起作用":在流程块中有多个上升沿检测. >

VHDL用于描述硬件,并且没有基本的电路元件可以响应多个时钟信号.因此,您无法以这种方式描述电路.

那么您如何解决呢?

您将电路转换成一个电路,其中任何单个进程都只有一个时钟信号(并且可以选择使用正确使用的一个异步复位信号).可以使用实数寄存器和触发器来实现.

两种方法是:

  1. 几个过程,使用信号在它们之间进行通信
  2. 一个具有单个时钟的进程,在主时钟沿上对其他信号进行采样.

这些之间的正确决定需要对设计有一定的整体了解.

这里听起来好像所有三个时钟信号实际上都是按下按钮,而不是一个快速时钟.因此,您不能保证在按下另一个按钮时会有时钟沿.

因此,这是前进的许多方法之一:制作一个时钟信号(过程外),该信号将覆盖所有三个输入事件.

my_clock <= clockIn or digitUp1 or digitUp2;

现在您可以使用以下时钟重写该过程:

process(my_clock, reset) is
begin
   if reset = '1' then
      -- reset actions
   elsif rising_edge(my_clock) then
      -- what caused this event?
      if digitUp1 = '1' then      -- bump digit 1
      elsif digitup2 = '1' then   -- bump digit 2
      else                        -- count normally
      endif;
   end if;
end process;

注意:

  1. 由于这是一个适当的同步过程,因此灵敏度列表中仅包括时钟和复位.
  2. 尽管从某种意义上讲这是可行的,但它可能不是客户想要的:例如,如果他按住所有三个按钮会发生什么?您可能需要探索其他设计方法.

I'm pretty new to VHDL (and digital circuits in general), and I'm trying to implement a counter of two digits using BCD style blocks. External to this circuit there is going to be buttons, which when pressed, will bump the digit of interest up by one (much like an alarm clock would). This is an asynchronous action, and will occur when in some form of edit mode (externally enforced). The code I have written works fine without the "elsif rising_edge(digitUp1) then" and "elsif rising_edge(digitUp1) then" blocks, but fails with them included. I really have no idea why it doesn't work or how I can fix it. Keep getting errors like "couldn't implement registers for assignments on this clock edge", "can't infer register for count2[3] because its behavior depends on the edges of multiple distinct clocks" and "Can't infer register for "count2[3]" at MinuteCounter.vhd(21) because it does not hold its value outside the clock edge". Any help would be greatly appreciated.

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;

-- ToDo: ENFORCE ON ALL COUNTERS (externally) LOGIC TO PAUSE AT MAX/MIN

entity MinuteCounter is
port( clockIn, digitUp1, digitUp2, reset, counting, countUp : in std_logic;
      clockOut : out std_logic;
      BCD1, BCD2 : out std_logic_vector(3 downto 0));
end MinuteCounter;

architecture structure of MinuteCounter is
signal count1, count2 : std_logic_vector(3 downto 0);
signal carryOut : std_logic;
begin

process( clockIn, digitUp1, digitUp2, countUp, reset, counting)
begin 

    -- Asynchronous reset
    if reset = '1' then
        count1 <= "0000";
        count2 <= "0000";

    -- What to run when there's an active edge of the clock
    elsif rising_edge(clockIn) then

        -- Code to run when timer is running
        if counting = '1' then

            -- What to do when counting up
            if countUp = '1' then
                if ((count1 = "1001") and (count2 = "0101")) then
                    count1 <= "0000";
                    count2 <= "0000";
                    if carryOut = '0' then
                        carryOut <= '1';
                    else
                        carryOut <= '0';
                    end if;
                elsif count1 = "1001" then
                    count1 <= "0000";
                    count2 <= count2 + 1;
                else
                    count1 <= count1 + 1;
                end if;

            -- What to do when counting down (This logic is hard to understand)
            else
                if ((count1 = "0000") and (count2 = "0000")) then
                    count1 <= "1001";
                    count2 <= "0101";
                    if carryOut = '0' then
                        carryOut <= '1';
                    else
                        carryOut <= '0';
                    end if;
                elsif count1 = "0000" then
                    count1 <= "1001";
                    count2 <= count2 - 1;
                else
                    count1 <= count1 - 1;
                end if;
            end if;

        -- When counting is disabled, but there is an active edge (do nothing)
        else
            count1 <= count1;
            count2 <= count2;
        end if;

    -- Code to run when entering values (will not be run if counting = '1') << Externally enforced
    elsif rising_edge(digitUp1) then
        if count1 = "1001" then
            count1 <= "0000";
            count1 <= count1 + 1;
        else
            count1 <= count1 + 1;
        end if;

    -- Code to run when entering values (will not be run if counting = '1') << Externally enforced
    elsif rising_edge(digitUp2) then
        if count2 = "0101" then
            count2 <= "0000";
            count2 <= count2 + 1;
        else
            count2 <= count2 + 1;
        end if;

    -- What to do when there is no active edge or other events (nothing)
    else
        count1 <= count1;
        count2 <= count2;
    end if;

end process;

-- Assign outputs
BCD1 <= count1;
BCD2 <= count2;
clockOut <= carryOut;

end structure;
解决方案

The "why it doesn't work" is explained in the question title : Multiple rising_edge detections inside a process block.

VHDL is designed to describe hardware, and there is no basic circuit element that responds to multiple clock signals. So you cannot describe a circuit that way.

So how do you fix it?

You transform the circuit into one where any single process only has one clock signal (and optionally, one asynchronous reset signal as you are using correctly). This can be implemented using real registers and flip flops.

Two ways are :

  1. several processes, using signals to communicate between them
  2. A single process, with a single clock, sampling the other signals on the main clock edge.

The correct decision between these requires some overall knowledge of the design.

Here it sounds as if all three clock signals are actually button presses, rather than one fast clock. Therefore you cannot guarantee that there will be a clock edge while another button is pressed.

So here is one of many ways forward : make a clock signal (outside the process) which will cover all three input events.

my_clock <= clockIn or digitUp1 or digitUp2;

Now you can rewrite the process using this clock:

process(my_clock, reset) is
begin
   if reset = '1' then
      -- reset actions
   elsif rising_edge(my_clock) then
      -- what caused this event?
      if digitUp1 = '1' then      -- bump digit 1
      elsif digitup2 = '1' then   -- bump digit 2
      else                        -- count normally
      endif;
   end if;
end process;

Notes:

  1. As this is a proper synchronous process, only clock and reset belong in the sensitivity list.
  2. Though this will work in a sense, it may not be what the customer wants : what happens if he holds down all three buttons for example? You may want to explore other approaches to the design.

这篇关于VHDL:在一个处理块中进行多次上升边缘检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 21:43