我必须设计一个带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
答案 0 :(得分:0)
这里有太多代码,但有一些一般性评论:
clk
为高时,您的主进程应该是透明的,否则应该锁定。但是,当execute
有元数据时,它不起作用。将其重构为具有单个外部if clk='1'
,就像您的从属进程一样if clk='1'
内的复位,或者(甚至更好)在锁存过程之外明确地将复位实现为AND
门。保持闩锁尽可能简单。(others => '0')
等代替0
/ Z
std_logic_arith
/ std_logic_unsigned
。第一眼,
你甚至不需要它们。如果您确实需要它们,请始终使用
numeric_std
相反,除非你有充分的理由不关于你的具体问题:这两个条件不能同时成立,但它们并非必须如此。发生了什么ibus
在clk
为1
时正在改变其状态。当它有一个值时,您的代码设置为s_state
和s_read3
;当它有另一个值时,它设置s_execute
。其他信号保持不变,因为您没有分配给它们。
您没有指定ibus
,因此您需要找出其发生变化的原因。你应该把它锁在你的奴隶过程中吗?
您可能还应该返回并确认在主进程的任何路径中未明确更改的任何信号实际上都以正确的值结束。您的主密码是可疑的,只是因为ibus
可能会改变并有效锁定某些信号,即使clk
1
时它们是透明的,也不是很明显。 {1}}。您可能需要重新设计:将所有主输出清除为外部if clk='1'
之后的第一个操作,然后分配给所有输出,无论当前的输入状态。