【问题标题】:How to set a value at moduleEN - VHDL如何在 moduleEN - VHDL 中设置值
【发布时间】:2015-04-29 10:34:37
【问题描述】:

我有这个代码:

library IEEE;

use IEEE.std_logic_1164.all;

entity Controller is
port (
    CLK : in std_logic;
    OutENABLE : out std_logic_vector (2 downto 0);
    ModuleRESET : in std_logic;
    ModuleENABLE : in std_logic
);
end Controller;

architecture Controller_archi of Controller is
    signal Counter : integer range 0 to 4200 := 0;

    begin
        process (CLK, ModuleRESET)
        begin
            if ModuleRESET = '0' then
                OutENABLE <= (others => '0');
                Counter <= 0;
            elsif rising_edge(CLK) then
                if ModuleENABLE = '1' then
                    Counter <= Counter + 1;
                    case Counter is
                        when 0 =>
                            OutENABLE <= "001";
                        when 450 =>
                            OutENABLE <= "010";
                        when 900 =>
                            OutENABLE <= "100";
                        when 1350 =>
                            OutENABLE <= "001";
                            Counter <= 0;
                        when others =>
                    end case;
                else
                    OutENABLE <= "000";
                end if;
            end if;
        end process;

end Controller_archi;

但它并没有像我需要的那样工作。

我需要什么:

  • 当ModuleENABLE 立即变为“1”时OutENABLE 变为“001”而不是一开始rising_edge(CLK) (现在,在这段代码中,如果 ModuleENABLE 变为“1”,则 OutENABLE 不会从“000 " 到 "001",在第一个上升沿(CLK) 后变为 "001")
  • 当rising_edge(CLK) 和OutENABLE 时计数器上升,它会在每个CLK 事件中更新。 (现在,在此代码中,计数器在上升沿(CLK)时上升,但 OutENABLE 在上升沿(CLK)时更新,而不是在 CLK 上升和下降时更新)

所以我修改了代码来做到这一点:

library IEEE;
use IEEE.std_logic_1164.all;

entity Controller is
port (
    CLK : in std_logic;
    OutENABLE : out std_logic_vector (2 downto 0);
    ModuleRESET : in std_logic;
    ModuleENABLE : in std_logic
);
end Controller;

architecture Controller_archi of Controller is
    signal Counter : integer range 0 to 4200 := 0;

    begin
        process (CLK, ModuleENABLE, ModuleRESET)
        begin
            if ModuleRESET = '0' then
                OutENABLE <= (others => '0');
                Counter <= 0;
            elsif ModuleENABLE = '1' then
                if rising_edge(CLK) then
                    Counter <= Counter + 1;
                end if;
                    case Counter is
                        when 0 =>
                            OutENABLE <= "001";
                        when 450 =>
                            OutENABLE <= "010";
                        when 900 =>
                            OutENABLE <= "100";
                        when 1350 =>
                            OutENABLE <= "001";
                            Counter <= 0;
                        when others =>
                    end case;
             else
                 Counter <= 0;
                 OutENABLE <= "000";
             end if;
        end process;

end Controller_archi;

现在代码像我在 ModelSim 中需要的那样工作,但是当我合成它或编译它并再次模拟时它不起作用。

我的问题是:

  • 第二个代码有什么问题以及如何解决?

  • 如果我无法修复第二个代码,我如何修改第一个代码以按我的需要工作?

【问题讨论】:

    标签: vhdl counter


    【解决方案1】:

    第二个代码有什么问题以及如何修复它?

    您的综合工具对时钟线和复位线的连接方式很挑剔。您必须使用如下结构:

            if ModuleRESET = '0' then
               ...
            elsif rising_edge(CLK) then
    

    或者综合工具无法识别时钟和复位线。

    如果我无法修复第二个代码,我如何修改第一个代码以按我的需要工作?

    您需要将“OutENABLE”移到第一个进程之外,并移到它自己的进程中。从你所说的,OutENABLE 不应该是一个寄存器 - 它应该是 Counter、ModuleRESET 和 ModuleENABLE 的组合函数。试试这个。

        process (CLK, ModuleRESET)
        begin
            if ModuleRESET = '0' then
                Counter <= 0;
            elsif rising_edge(CLK) then
                if ModuleENABLE = '1' then
                    Counter <= Counter + 1;
                    case Counter is
                        when 1350 =>
                           Counter <= 0;
                        when others =>
                           null;
                    end case;
                end if;
            end if;
        end process;
    
        process (Counter, ModuleRESET, ModuleEnable)
        begin
            OutENABLE <= "000";
            if ModuleRESET = '1' and ModuleENABLE = '1' then
                case Counter is
                    when 0 .. 449 =>
                        OutENABLE <= "001";
                    when 450 .. 899 =>
                        OutENABLE <= "010";
                    when 900 .. 1349 =>
                        OutENABLE <= "100";
                    when others =>
                        OutENABLE <= "001";
                end case;
            end if;
        end process;
    

    【讨论】:

    • 我没有很好地解释我需要从这段代码中得到什么。第一个代码正在工作,但不是我需要的。我已经在我的问题中更新了我需要什么(你可以在 Strong 中找到它),你能再检查一下吗?
    • 我得到这两个错误:多个非三态驱动程序用于控制器中的 net OutENABLE(2 downto 0);控制器中网络 OutENABLE(2 downto 0) 的未解决三态驱动程序;当我尝试编译代码时。
    • 这意味着在两个进程中都有对 OutENABLE 的分配。对不起。我的错。已更正。
    • 现在代码可以运行了。但是我在模拟中有一个错误。例如,当 OutENABLE 处于状态“010”时,它有时会随机进入“000”,然后进入“100”,然后返回“010”,时间为 1ns。
    • 很高兴它为您工作。 OutENABLE 现在由一些组合逻辑生成,但是当计数器增加时您不会立即得到答案:仍然存在传播延迟,这说明了您在模拟器中看到的内容,以及暂时无效的状态(“故障”)。避免这种情况的方法是将 OutENABLE 变成一个寄存器,就像您最初的解决方案一样,在这种情况下,OutENABLE 在达到时钟边缘之前不会改变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多