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

时间:2015-11-11 10:38:41

标签: vhdl

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

这是RAM

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;

这是CPU:

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

entity cpu is
    Port(
    clk: IN std_logic;
    rst: IN std_logic;
    instruction: OUT std_logic;
    address : OUT std_logic_vector(0 to 15);
    obus: OUT std_logic_vector(0 to 7);
    ibus: IN std_logic_vector(0 to 7)
    );
end cpu;

architecture Behavioral of cpu is
    --signal reg_1, reg_2, reg_3, reg_4, reg_5, reg_acc, reg_addr1, reg_addr2: std_logic_vector(0 to 7);
    signal pointer, s_pointer: std_logic_vector(0 to 15);
    signal state, s_state, test: integer range 0 to 3;
    signal read3, s_read3, execute, s_execute: std_logic;

    type reg is array (integer range <>) of std_logic_vector(0 to 7);
    signal registers: reg (0 to 7);
    signal handler: reg (0 to 2);

begin

---HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH---
---
---     Slave process (runs at '0')
---
---HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH--- 

    slave: process (clk, s_pointer, s_state, s_read3, s_execute)
    begin
        if clk = '0' then
            pointer <= s_pointer;
            state <= s_state;
            read3 <= s_read3;
            execute <= s_execute;
        end if;
    end process;

---HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH---
---
---     Master process (runs at '1')
---
---HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH--- 

    master: process (clk, rst, ibus, pointer, state, read3, execute)
    begin
        if rst = '1' then
            s_state <= 0;
---HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH---
---
---     FSM to read instructions
---
---HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH---         
        elsif clk = '1' and state = 0 then          
            s_state <= 1;
            s_pointer <= "0000000000000000";
            address <= "0000000000000000";
            s_read3 <= '0';
            s_execute <= '0';
            instruction <= '0';
            handler(0) <= "ZZZZZZZZ";
            handler(1) <= "ZZZZZZZZ";       
            handler(2) <= "ZZZZZZZZ";
        elsif clk = '1' and execute = '0' then
            address <= pointer;
            s_pointer <= pointer + 1;
            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
                    --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;
            elsif state = 2 then
                handler(1) <= ibus;
                if read3 = '1' then
                    s_state <= 3;   
                    s_read3 <= '0';
                elsif read3 = '0' then
                    s_state <= 1;
                    s_execute <= '1';
                end if;
            elsif state = 3 then
                handler(2) <= ibus;
                s_state <= 1;
                s_execute <= '1';
            end if;

---HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH---
---
---     Execution phase
---
---HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH---

        elsif clk = '1' and execute = '1' then
            --not yet implemented
            s_execute <= '0';
        end if;
    end process; 

end Behavioral;

这两个模块都链接在这个顶层模块中:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity microprocessor is
    Port(
    clk: IN std_logic;
    rst: IN std_logic
    );
end microprocessor;

architecture Behavioral of microprocessor is

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

component cpu is
    Port(
    clk: IN std_logic;
    rst: IN std_logic;
    instruction: OUT std_logic;
    address : OUT std_logic_vector(0 to 15);
    obus: OUT std_logic_vector(0 to 7);
    ibus: IN std_logic_vector(0 to 7)
    );
end component;

signal address: std_logic_vector(0 to 15);
signal ctrbus: std_logic_vector(0 to 7);
signal rtcbus: std_logic_vector(0 to 7);
signal instruction: std_logic;

begin
memory1: memory port map (
            clk => clk,
            instruction => instruction,
            address => address,
            ibus => ctrbus,
            obus => rtcbus
            );
cpu1: cpu port map (
            clk => clk,
            rst => rst,
            instruction => instruction,
            address => address,
            ibus => rtcbus,
            obus => ctrbus
            );
end Behavioral;

好的,我知道这是很多代码,但我真的很感激任何帮助。 所以,我的问题是,在模拟时,在第5个时钟周期,会发生奇怪的事情。此时,RAM将“11100111”置于其obus上,因此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;

这可以在模拟中使用,因为s_state和s_read3都获得它们各自的值。但是,最后一个条件也会被执行,因为s_execute也会变为'1'!我不明白这是怎么可能的,怎么可能呢

ibus(0 to 2) = "111"

和这个

(ibus(0) = '0' or ibus(0 to 2) = "100")

同时是真的吗?

非常感谢, Reygok

1 个答案:

答案 0 :(得分:0)

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

  • clk为高时,您的主进程应该是透明的,否则应该锁定。但是,当execute有元数据时,它不起作用。将其重构为具有单个外部if clk='1',就像您的从属进程一样
  • 主进程中的重置是可疑的。它只清除一个信号,使其他所有信号不受影响。所以,你有一个复杂的多功能锁存器。再想一想:重置所有信号,或者(更好)移动外部if clk='1'内的复位,或者(甚至更好)在锁存过程之外明确地将复位实现为AND门。保持闩锁尽可能简单。
  • 使用(others => '0')等代替0 / Z
  • 的长列表
  • 摆脱std_logic_arith / std_logic_unsigned。第一眼, 你甚至不需要它们。如果您确实需要它们,请始终使用 numeric_std相反,除非你有充分的理由不

关于你的具体问题:这两个条件不能同时成立,但它们并非必须如此。发生了什么ibusclk1时正在改变其状态。当它有一个值时,您的代码设置为s_states_read3;当它有另一个值时,它设置s_execute。其他信号保持不变,因为您没有分配给它们。

您没有指定ibus,因此您需要找出其发生变化的原因。你应该把它锁在你的奴隶过程中吗?

您可能还应该返回并确认在主进程的任何路径中未明确更改的任何信号实际上都以正确的值结束。您的主密码是可疑的,只是因为ibus可能会改变并有效锁定某些信号,即使clk 1时它们是透明的,也不是很明显。 {1}}。您可能需要重新设计:将所有主输出清除为外部if clk='1'之后的第一个操作,然后分配给所有输出,无论当前的输入状态。