【问题标题】:Integer to unsigned conversion going wrong VHDL quartus整数到无符号转换出错 VHDL quartus
【发布时间】:2016-06-26 23:44:56
【问题描述】:

我遇到了波形输出错误的问题,基本上我的代码作为一个计数器工作,当我的负载信号等于“1”时,计数器会上升,如果负载信号为“0”,则计数器不会” t 很重要。我有一个明确的信号让计数器进入 0,我的问题出在输出中,输出始终显示相同的值,并且当清除信号等于 1 时不会进入 0。

波形下方:

代码下方:

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

entity tot is
port (
      i_CLR  : IN STD_LOGIC;         
      i_CLK  : IN STD_ULOGIC;        
      i_DINL : IN STD_LOGIC ;        
      i_DINK : IN INTEGER;           
      o_DOUTK : BUFFER INTEGER);      
end tot;

architecture arch_1 of tot is
signal w_K : integer;                
begin
PROCESS (i_DINL)
begin
    IF rising_edge(i_CLK) THEN       
        IF (i_CLR = '1') THEN        
            w_K <= 0;                
        ELSE                         
            w_K <= i_DINK;           
        END IF;
        IF (i_DINL = '1') THEN       
            w_K <= w_K + 1;          
        ELSE                      
            w_K <= w_K;              
        END IF;
        o_DOUTK <= w_K;            
    END IF;
    end process;
end arch_1;

更新 1:

architecture arch_1 of tot is
    signal w_k:  integer;                
begin
process (i_clk)   -- WAS (i_dinl)
begin
    if rising_edge(i_clk) then     
        if i_clr = '1' then        
            w_k <= 0;                
        else
            w_k <= i_dink;       
        end if;
        if i_dinl = '1' then       
            w_k <= w_k + 1;          
        -- else
        --     w_k <= w_k;          
        end if;
        -- o_doutk <= w_k;            
    end if;
    end process;

    o_doutk <= w_k;  -- MOVED to here.

end architecture arch_1;

当我尝试执行此逻辑将值从 k 加载到初始计数值时,波形中的错误仍然出现。

波形:


更新2(正确情况):

在阅读了 cmets 后,我得到了解决问题的方法,我使用状态机让我的计数器从 K 加载先前的值,使用这段代码我已经让代码正常工作。

LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_unsigned.ALL;
use IEEE.std_logic_arith.ALL;

ENTITY controle IS
  PORT (
      i_RST  : IN STD_LOGIC;
      i_CLR  : IN STD_LOGIC;         -- Sinal vindo do controle para limpar o valor de K
      i_CLK  : IN STD_ULOGIC;        -- Sinal de clock para sincronizar com o controle
      i_DINL : IN STD_LOGIC ;        -- Sinal de load para carregar K
      i_DINK : IN INTEGER;           -- Valor antigo de K
      o_DOUTK : BUFFER INTEGER
      );     
END controle;

ARCHITECTURE arch_1 OF controle IS
  TYPE state_type IS (s0, s1, s2,s3);
  SIGNAL stateT : state_type;

   signal w_k:  integer;  
BEGIN

  PROCESS(i_CLK)
  BEGIN
    IF rising_edge(i_CLK) THEN
      IF (i_RST = '1') THEN
        stateT <= s0;
      ELSE
        CASE stateT IS
          when s0 => if (i_CLR = '1') THEN
                        w_k <= 0;
                        stateT <= s2;
                     else
                        stateT <= s1;
                     end if;
          when s1 => if (i_dinl = '1') then 
                       w_k <= i_dink;
                       stateT <= s2;
                     end if;
          when s2 => w_K <= w_k + 1;
                     stateT <= s3;
          when s3 => o_DOUTK <= w_K; 
                     stateT <= s0;
        END CASE;
      END IF;
    END IF;
  END PROCESS;


END arch_1;

【问题讨论】:

    标签: integer vhdl unsigned waveform quartus


    【解决方案1】:

    您的敏感度列表和 if 语句不符合您的预期。

    试试:

    architecture arch_1 of tot is
        signal w_k:  integer;                
    begin
    process (i_clk)   -- WAS (i_dinl)
    begin
        if rising_edge(i_clk) then       
            if i_clr = '1' then        
                w_k <= 0;                
            -- else
            --     w_k <= i_dink;       
            -- end if;
            elsif i_dinl = '1' then       
                w_k <= w_k + 1;          
            -- else
            --     w_k <= w_k;          
            end if;
            -- o_doutk <= w_k;            
        end if;
        end process;
    
        o_doutk <= w_k;  -- MOVED to here.
    
    end architecture arch_1;
    

    这给出了:

    我用这个测试台创建了一个完整的MCVE

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity tot_tb is
    end entity;
    
    architecture foo of tot_tb is
        signal clr:     std_logic := '1';
        signal clk:     std_logic := '0';
        signal dinl:    std_logic := '1';
        signal dink:    integer := 8;
        signal doutk:   integer;
    begin
    DUT:
        entity work.tot
            port map (
                i_clr => clr,
                i_clk => clk,
                i_dinl => dinl,
                i_dink => dink,
                o_doutk => doutk
            );
    CLOCK:
        process
        begin
            wait for 10 ns;
            clk <= not clk;
            if now > 650 ns then
                wait;
            end if;
        end process;
    STIMULI:
        process
        begin
            wait for 240 ns;
            clr <= '0';
            wait for 100 ns;
            clr <= '1';
            wait for 40 ns;
            clr <= '0';
            wait;
        end process;
    
    end architecture;
    

    也不需要提到包 numeric_std 的 use 子句(所有算术都是基于整数的)。

    如果没有看到你打算在这里做什么的完整表示,o_doutk 不需要是模式buffer,它可以是模式out

    所有赋值都在 if 语句中,条件在 i_clk 的上升沿,所以 i_clk 应该是一个敏感列表项。灵敏度列表中没有其他信号。

    对输出的赋值是一个并发语句,它将被详细说明为一个等效的过程。单独的语句/过程背后的想法是防止时钟延迟在模拟中将 w_k 的新值分配给 o_doutk。

    当任何挂起的进程尚未恢复和挂起时,不会更新任何信号值。 w_k 没有改变的原因是因为你有两个独立的 if 语句。对于任何目标仿真时间,只有一个投影输出波形,第二个 if 语句从提供重置值分配的第一个 if 语句中替换了 w_k 的投影值。

    由于分配 w_k 模型顺序(时钟)逻辑的过程,您不会通过未能为 else 替代方案提供值来推断锁存器。 如果您的灵敏度列表中有 i_clk 而不是 i_dinl 并且您的波形显示了 w_k (o_doutk) 的整个值,您会看到它在重置期间递增,从 INTEGER'LOW 开始,因为在声明 w_k。

    创建单个 if 语句只允许有条件地遇到一个赋值语句,这意味着重置值 0 将生效。

    来自 IEEE Std 1076-2008 10.8 If 语句:

    if 语句根据一个或多个相应条件的值选择一个或不执行一个封闭的语句序列。

    使用状态机的最终解决方案似乎没有用:

    architecture arch_1 of tot is          -- WAS controle NOW tot
        type state_type is (s0, s1, s2,s3);
        signal statet : state_type;
    
        signal w_k:  integer;  
    
    begin
    
        process (i_clk)
        begin
            if rising_edge(i_clk) then
                if i_clr = '1' then           -- WAS i_rst NOW i_clr
                    statet <= s0;
                else
                    case statet is
                        when s0 => 
                            if i_clr = '1' then
                                w_k <= 0;
                            else
                                statet <= s1;
                            end if;
                        when s1 => 
                            if i_dinl = '1' then 
                                w_k <= i_dink;
                                statet <= s2;
                            end if;
                        when s2 => 
                            w_k <= w_k + 1;
                            statet <= s3;
                        when s3 => 
                            o_doutk <= w_k; 
                            statet <= s0;
                    end case;
                end if;
            end if;
        end process;
    END arch_1;
    

    它产生:

    这与根据您的问题构建的任何可能的叙述都不匹配。

    请注意,在显示递增值的 w_k 和 o_doutk 之间存在一个时钟延迟,并且您只能在 w_k 上使用新值到达状态 s3 一次。在 reset invalid 和 i_dink 加载到 w_k 之间还有一个时钟延迟。

    如果这个波形是你想要的,那么这个答案是错误的。如果这不是您想要的,您的问题不清楚,那么您的解决方案就是错误的。在任何一种情况下,您都应该撤回对这个答案的接受。

    根据 i_dinl 的状态加载或增加 w_k 可能更合适,而不是状态:

    architecture foo of tot is
        signal w_k:  integer;
    begin
        process (i_clk)   -- WAS (i_dinl)
        begin
            if rising_edge(i_clk) then
                if i_clr = '1' then
                    w_k <= 0;
                -- else
                --     w_k <= i_dink;
                -- end if;
                elsif i_dinl = '1' then
                    w_k <= w_k + 1;
                -- else
                else 
                --     w_k <= w_k;
                    w_k <= i_dink;
                end if;
                -- o_doutk <= w_k;
            end if;
        end process;
    
        o_doutk <= w_k;  -- MOVED to here.
    
    end architecture;
    

    这给出了:

    一般来说,您会期望一个单独的控制信号来启用计数,尤其是在您使用异步复位的情况下。

    wahab 建议使用状态是基于将四个函数(clr、load、increment、hold)编码为两个输入。状态由提供两个控制输入的任何东西保持。

    请注意,这与您的两个波形中的任何一个都不匹配,并且您的问题不是针对您的解决方案或这个解决方案的 MCVE](https://stackoverflow.com/help/mcve)。

    【讨论】:

    • 此解决方案有效,但是当我尝试从 K 加载信号时,例如:我的 i_DINK = 7,并且我喜欢从该值开始递增计数器,但在我清除来自第一次,计数器从 0 开始计数,就像在您的波形中看到的那样,我已经更新了我的问题以显示这一点。
    • 您基本上有四种情况: 1. 将计数清零 2. 将输入值加载到计数寄存器中 3. 将计数增加 1 4. 保持计数不变 您有 2 个控制信号, i_clear 和 i_dinl。您可以创建一个四态、状态机来解决您的问题。
    • @wahab,我创建了你提到的状态机,现在它可以正常工作了,谢谢!
    • 谢谢你@user1155120。
    • @user1155120,加载增强器的K值的部分在原始代码中(第一个),但我忘记在问题描述中解释这一点,以便在您更正时我的错误是您的代码没有加载 K。我将您的答案保留为正确,因为它确实解决了我的错误值问题。感谢并为我的错误感到抱歉!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 2012-01-09
    相关资源
    最近更新 更多