如何减少 VHDL 设计中的 ALM 数量?

问题描述

我正在尝试为 VHDL 中的数字时钟实现一个警报模块。我已经为它编写了架构,但是当我运行 Compilation 时,我得到了太多的 Adaptive Logic Modules(大约 2000 个),我认为这太多了。我将在下面发布我的代码。

我认为在这行代码中,除法和取模运算可能是导致它的原因。

alarm_hour1   <= std_logic_vector(to_unsigned(savedHours/10,alarm_hour1'length)); 
alarm_hour0   <= std_logic_vector(to_unsigned(savedHours mod 10,alarm_hour0'length));      
alarm_minute1 <= std_logic_vector(to_unsigned(savedMinutes/10,alarm_minute1'length));     
alarm_minute0 <= std_logic_vector(to_unsigned(savedMinutes mod 10,alarm_minute0'length));

不过,我不确定如何解决这个问题。

另外,如果您能对我的设计提出更多意见,指出一些错误,以及如何改进我的设计,我将不胜感激。我对 VHDL 还很陌生,因此不胜感激。

非常感谢。

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

entity alarm is
port(
    --INPUTS
    reset                         : in std_logic;
    clock                     : in std_logic;
    alarm_enable              : in std_logic;
    alarm_set              : in std_logic;
    alarm_increment        : in std_logic;
    alarm_decrement        : in std_logic;
    currentTime_hour1      : in std_logic_vector(3 downto 0);
    currentTime_hour0      : in std_logic_vector(3 downto 0);
    currentTime_minute1   : in std_logic_vector(3 downto 0);
    currentTime_minute0    : in std_logic_vector(3 downto 0);
    
    --OUTPUTS
    alarm_buzzer              : out std_logic;
    alarm_hour1             : buffer std_logic_vector(3 downto 0) := "0000";
    alarm_hour0            : buffer std_logic_vector(3 downto 0) := "0000";
    alarm_minute1          : buffer std_logic_vector(3 downto 0) := "0000";
    alarm_minute0          : buffer std_logic_vector(3 downto 0) := "0000"
);
end alarm;

architecture alarmBehaviour of alarm is
--ALARM TIME
signal savedHours   : integer := 0;
signal savedMinutes : integer := 0;

signal incrementDecrementbuttonDetect : std_logic;

signal set_lastButtonState  : std_logic := '0';
signal setButtonDetect     : std_logic := '0';

--STATE MACHINE
type state_type is (idle,setHour,setMinute);
signal state_reg,state_next : state_type;

begin
incrementDecrementbuttonDetect <= alarm_increment or alarm_decrement;

--STATE REGISTER
process(clock,reset)
begin
    if (reset = '1') then
        state_reg <= idle;
    elsif rising_edge(clock) then
        state_reg <= state_next;
    end if;
end process;


--SET BUTTON PRESSED
process(clock)
begin
if(rising_edge(clock)) then
    if(alarm_set = '1' and set_lastButtonState = '0') then
        setButtonDetect <= '1';
    else
        setButtonDetect <= '0';
    end if;
    set_lastButtonState <= alarm_set;
end if;
end process;

--NEXT STATE
process(state_reg,setButtonDetect)
begin
    case state_reg is
        when idle =>
            if setButtonDetect = '1' then
                state_next <= setHour;
            else
                state_next <= idle;
            end if;
            
        when setHour =>
            if setButtonDetect = '1' then
                state_next <= setMinute;
            else
                state_next <= setHour;
            end if;
            
        when setMinute =>
            if setButtonDetect = '1' then
                state_next <= idle;
            else
                state_next <= setMinute;
            end if;
    end case;
end process;

process (incrementDecrementbuttonDetect,state_reg)
begin
    if rising_edge(incrementDecrementbuttonDetect) then
        case state_reg is
            when idle =>
            when setHour =>
                if alarm_increment = '1' then
                    if savedHours = 23 then
                        savedHours <= 0;
                    else
                        savedHours <= savedHours + 1;
                    end if;
                else null;
                end if;
                
                if alarm_decrement = '1' then
                    if savedHours = 0 then
                        savedHours <= 23;
                    else
                        savedHours <= savedHours - 1;
                    end if;
                else null;
                end if;
                
            when setMinute =>
                if alarm_increment = '1' then
                    if savedMinutes = 59 then
                        savedMinutes <= 0;
                    else
                        savedMinutes <= savedMinutes + 1;
                    end if;
                else null;
                end if;
                
                if alarm_decrement = '1' then
                    if savedMinutes = 0 then
                        savedMinutes <= 59;
                    else
                        savedMinutes <= savedMinutes - 1;
                    end if;
                else null;
                end if;
        end case;
    end if;

end process;
    
alarm_hour1   <= std_logic_vector(to_unsigned(savedHours/10,alarm_minute0'length));

--ALARM BUZZER CONDITION
process (currentTime_hour1,currentTime_hour0,currentTime_minute1,currentTime_minute0,alarm_enable,alarm_hour1,alarm_hour0,alarm_minute1,alarm_minute0)
begin
    if((alarm_hour1 = currentTime_hour1) and (alarm_hour0 = currentTime_hour0) 
    and (alarm_minute1 = currentTime_minute1) and (alarm_minute0 = currentTime_minute0) and alarm_enable = '1')  then
        alarm_buzzer <= '1';
    else
        alarm_buzzer <= '0';
    end if;
end process;
end alarmBehaviour;

解决方法

信号 savedHourssavedMinutes 的范围没有指定,所以 Quartus 假设它们是 32 位宽。对一个 32 位操作数的除法器进行推断,结果是一棵大的条件减法树。

将您的代码更新为类似的内容

--ALARM TIME
signal savedHours   : natural range 0 to 23 := 0;
signal savedMinutes : natural range 0 to 59 := 0;

很可能会减少 ALM 的使用。

另外,请注意 rising_edge 应该仅用于时钟信号(在 VHDL 入门级)。您可能需要一些按钮去抖动逻辑,而不是将逻辑连接到寄存器的时钟输入。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...