【发布时间】:2015-11-12 21:22:18
【问题描述】:
我必须设计一个带有 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;
这是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")
同时是真的吗?
提前非常感谢, 雷哥克
【问题讨论】:
-
您确实需要了解
clk = '1'和rising_edge(clk)之间的区别,并在继续之前将整个代码重写为正确的时钟进程。 -
感谢您的回答,但这些进程不是触发器,它们是锁存器,它们应该在没有上升沿(clk)的情况下工作。这是老师给的前提。
-
这是一个奇怪的约束,以至于问题可能有用地提到您特别想要闩锁。所以,你是靠自己的。嫌疑人在唤醒过程中出现故障,或敏感度列表错误。在每个分支中添加断言,以准确了解发生了什么以及何时发生。并理解为什么每一个都会触发。你必须自己调试它。哦,练习的目的可能是加强时钟进程的优点......
-
我已经尝试了好几个小时,通过检查每个分支的信号并了解发生的情况和时间来自己调试它。但我想不通,这就是我来这里的原因。这当然不是练习的目的,因为这是我们整个学期唯一的练习。整个课程就是这个项目。
-
您的设计似乎证明了为什么某些设计使用多相(非重叠)时钟,允许使用锁存器而不是寄存器(更少的门)。连续阶段更新和评估,而不传播基于组合延迟的不适当事件(故障)。永远不要在同一时钟相位将表达式评估为锁存输入,它的任何输入都被锁存。这可能需要增加状态数、用于转换时钟相位的锁存器或使用两个以上的时钟相位。
标签: vhdl