VHDL锁存问题(触发器不是选项)

VHDL锁存问题(触发器不是选项),vhdl,Vhdl,我必须设计一个带有RAM的小型CPU,我面临一个我无法处理的问题。首先,我的代码: 这是公羊 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity memory is Port( clk: IN std_logic; instruction: IN std_logic; address : IN s

我必须设计一个带有RAM的小型CPU,我面临一个我无法处理的问题。首先,我的代码:

这是公羊

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity memory is
 Port(
    clk: IN std_logic;
    instruction: IN std_logic;
    address : IN std_logic_vector(0 to 15);
    ibus: IN std_logic_vector(0 to 7);
    obus: OUT std_logic_vector(0 to 7)
 );
end memory;
architecture Behavioral of memory is

type memArr is array (integer range <> ) of std_logic_vector(0 to 7);
signal mem: memArr (0 to 65535);
signal rom: memArr (0 to 128);
signal ram: memArr (0 to 65407);

begin

-- LOAD/STORE Test

    rom(0) <= "10100110";   -- step 1: (constant) load data1 into reg_addr1
    rom(1) <= "00000000";   -- this one/

    rom(2) <= "11100111";   -- step 2: (direct) load data2 from following address into reg_addr2
    rom(3) <= "00000000";   -- this address  
    rom(4) <= "01000000";   -- contains data2/

    rom(5) <= "10100000";   -- step 3: (constant) load followig data into reg_1
    rom(6) <= "01010101";   -- this one/

    rom(7) <= "10001000";   -- step 4: (indirect) store data in reg_1 to adress in reg_addr 1 + 2/

    rom(64) <= "00000000";  -- data2 from step 2


    mem(0 to 128) <= rom;

    reading: process (clk, instruction, address)
    begin
        if clk ='1' and instruction = '0' then
            obus <= mem(conv_integer(unsigned(address)));
        end if;
    end process;

    writing: process (clk, instruction, address, ibus)
    begin
        if clk ='1' and instruction = '1' then
            ram(conv_integer(unsigned(address))) <= ibus;
        end if;
    end process;

end Behavioral;
好的,我知道这是相当多的代码,但我真的非常感谢任何帮助。 所以,我的问题是,当模拟时,在第五个时钟周期,奇怪的事情发生了。此时,RAM将11100111放在其OBU上,因此CPU在这里:

if state = 1 then
    instruction <= '0';
    handler(0) <= ibus;
    handler(1) <= "ZZZZZZZZ";
    handler(2) <= "ZZZZZZZZ";
    if (ibus(0 to 2) = "101" or ibus(0 to 2) = "110") then
        test <= 1;
        s_state <= 2;
    elsif ibus(0 to 2) = "111" then        <<<===== HERE
        --test <= 2;
        s_state <= 2;
        s_read3 <= '1';
    elsif (ibus(0) = '0' or ibus(0 to 2) = "100") then
        test <= 3;
        s_execute <= '1';
    end if;
还有这个

(ibus(0) = '0' or ibus(0 to 2) = "100")
同时是真的吗

多谢各位,
Reygok

这里的代码太多了,但有一些一般性的评论:

当clk高时,您的主进程应该是透明的,否则就锁定。但是,当execute上有metaval时,它就不起作用了。重构它,使其具有单个外部(如果clk='1'),就像从进程一样 主进程中的重置是可疑的。它只清除一个信号,其他一切都不受影响。所以,你有一个复杂的多功能闩锁。再考虑一下:重置所有信号,或者如果clk='1',最好将重置移到外部,或者更好地在锁存过程之外显式地实现重置as和门。保持闩锁尽可能简单。 使用others=>“0”等,而不是0/Z的长列表 去掉标准逻辑算术/标准逻辑无符号。乍一看, 你甚至不需要它们。如果您确实需要,请始终使用 除非你有很好的理由不这样做 关于你的具体问题:这两个条件不可能同时为真,但它们不一定是真的。发生的事情是,ibus正在改变其状态,而clk为1。当它有一个值时,代码将设置s_状态和s_read3;当它有另一个值时,它设置s_execute。其他信号保持不变,因为您没有分配给它们

您没有分配IBU,因此您需要找出它发生变化的原因。您应该在从属进程中锁定它吗


您可能还应该返回并确认在主进程的任何路径中没有显式更改的任何信号最终都具有正确的值。您的主代码是可疑的,如果只是因为您不清楚IBU可能会更改并有效地锁定某些信号,即使它们在clk为1时是透明的。您可能需要重新设计:清除所有主输出,作为外部if clk='1'后的第一个操作,然后分配给所有输出,无论输入的当前状态如何。

您确实需要了解clk='1'和rising_Edgeck之间的区别,并在继续之前将整个过程重写为正确的时钟过程。感谢您的回答,但这些过程不是触发器,它们是锁存器,应该在没有rising_Edgeck的情况下工作。这是老师给出的一个前提。这是一个如此奇怪的约束,问题可能会有用地提到你特别想要锁。所以,你只能靠自己了。怀疑唤醒过程中出现故障,或敏感度列表错误。在每个分支中添加断言,以准确了解发生了什么以及何时发生。并理解为什么每一个都会触发。你必须自己调试它。哦,这个练习的目的可能是为了强调时钟进程的优点……我已经花了几个小时亲自调试它,检查每个分支的信号,了解发生了什么以及什么时候发生的。但我不明白,这就是我来这里的原因。这当然不是练习的目的,因为这是我们整个学期唯一的一个练习。整个过程就是这个项目。你的设计似乎说明了为什么有些设计使用多相非重叠时钟,允许使用锁存而不是寄存器和更少的门。连续阶段更新和评估,而不传播基于组合延迟的不适当事件和小故障。切勿将表达式计算为同一时钟相位中的锁存输入,因为它的任何输入都是锁存的。这可能需要增加状态数、用于转换时钟相位或使用两个以上时钟相位的锁存器。非常感谢!今天我问我的老师,他告诉我问题在于ibus发生了变化,并激活了闩锁。这是因为在主进程开始时,我更改了地址,这是RAM的总线。因此RAM通过IBU发送一个新值,因为它指向一个新地址。此外,执行位实际上是错误的,或者至少不是它应该是什么样子,该功能应该通过状态4来实现;这也可以解决你提到的其他一些问题。无论如何,再次感谢你,你帮了我最大的忙:
if state = 1 then
    instruction <= '0';
    handler(0) <= ibus;
    handler(1) <= "ZZZZZZZZ";
    handler(2) <= "ZZZZZZZZ";
    if (ibus(0 to 2) = "101" or ibus(0 to 2) = "110") then
        test <= 1;
        s_state <= 2;
    elsif ibus(0 to 2) = "111" then        <<<===== HERE
        --test <= 2;
        s_state <= 2;
        s_read3 <= '1';
    elsif (ibus(0) = '0' or ibus(0 to 2) = "100") then
        test <= 3;
        s_execute <= '1';
    end if;
ibus(0 to 2) = "111"
(ibus(0) = '0' or ibus(0 to 2) = "100")