我正在学习在Xilinx(VHDL)上编码。接下来,我想制作一个简单的微处理器/微控制器,并在此过程中了解切片组件。所以我的目标是尝试使用AMD 2901(4位片)对8位微处理器进行编码。 (我已经拥有2901的代码及其有关输入和输出信号的所有信息。)
我知道第一步是制作微处理器的架构,所以我最终得到了这样的东西(我知道总线的带宽将与我正在寻找的东西非常不同)。
http://www.cs.binghamton.edu/~reckert/wk15fig1.JPG (基本上我对微处理器和微控制器的所有了解都是从http://www.cs.binghamton.edu/~reckert/hardwire3new.html}
获得的以下是准时问题:
如图所示,如何编写中央总线代码?如何使用图中央大总线“监听”和“写”我的内存和组件?
我想使用2901 ALU(其中两个),所以我有一个8位微处理器。问题是:假设我的操作码使用xxxxx001
(其中x是控制信号,001表示为ALU添加)以便在ALU上添加功能,所以...因为我有一个切片ALU我的操作码应该是xxxxx001001
是否向两个ALU发出指令?或者ALU应该共享相同的“001”命令? (我想可以知道如何在VHDL中使用总线,使两个端口“监听”或其他东西。)
如果您可以与我分享一些教程或链接信息,可以帮助我实现我的目标,这将是非常棒的。我搜索了很多,发现的信息非常少。
答案 0 :(得分:3)
这个答案是关于你问题的第3部分。
您可能会发现查看the MCPU project很有用。它是77行VHDL代码中的8位CPU。因为作者已经将整个设计压缩成32个宏单元,所以代码在某些地方有点棘手,但是the design document有帮助。
我还创建了一个针对代码可读性的重构版本,包含在下面。请注意,我不是该项目的原作者 - 所有荣誉都归TimBöscke所有。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity mcpu is
port (
data_bus: inout std_logic_vector(7 downto 0);
address: out std_logic_vector(5 downto 0);
n_oe: out std_logic;
-- Asynchronous memory interface
n_we: out std_logic;
n_reset: in std_logic;
clock: in std_logic
);
end;
architecture refactored of mcpu is
signal accumulator: std_logic_vector(8 downto 0);
alias carry is accumulator(8);
alias result is accumulator(7 downto 0);
alias opcode is data_bus(7 downto 6);
signal address_register: std_logic_vector(5 downto 0);
signal pc: std_logic_vector(5 downto 0);
signal states: std_logic_vector(2 downto 0);
type cpu_state_type is (FETCH, WRITE, ALU_ADD, ALU_NOR, BRANCH_NOT_TAKEN);
signal cpu_state: cpu_state_type;
type state_encoding_type is array (cpu_state_type) of std_logic_vector(2 downto 0);
constant STATE_ENCODING: state_encoding_type := (
FETCH => "000",
WRITE => "001",
ALU_ADD => "010",
ALU_NOR => "011",
BRANCH_NOT_TAKEN => "101"
);
begin
process (clock, n_reset)
begin
if not n_reset then
-- start execution at memory location 0
address_register <= (others => '0');
states <= "000";
cpu_state <= FETCH;
accumulator <= (others => '0');
pc <= (others => '0');
elsif rising_edge(clock) then
-- PC / Adress path
if cpu_state = FETCH then
pc <= address_register + 1;
address_register <= data_bus(5 downto 0);
else
address_register <= pc;
end if;
-- ALU / Data Path
case cpu_state is
when ALU_ADD =>
accumulator <= ('0' & result) + ('0' & data_bus);
when ALU_NOR =>
result <= result nor data_bus;
when BRANCH_NOT_TAKEN =>
carry <= '0';
when others => null;
end case;
-- State machine
if cpu_state /= FETCH then
cpu_state <= FETCH;
elsif opcode ?= "11" and carry then
cpu_state <= BRANCH_NOT_TAKEN;
else
states <= "0" & not opcode; -- execute instruction
case opcode is
when "00" => cpu_state <= ALU_NOR; -- 011
when "01" => cpu_state <= ALU_ADD; -- 010
when "10" => cpu_state <= WRITE; -- 001
when "11" => cpu_state <= FETCH; -- 000
when others => null;
end case;
end if;
end if;
end process;
-- output
address <= address_register;
data_bus <= result when (cpu_state = WRITE) else (others => 'Z');
-- output enable is active low, asserted only when
-- rst=1, clk=0, and state!=001(wr_acc) and state!=101(read_pc)
n_oe <= '1' when (clock='1' or cpu_state = WRITE or n_reset = '0' or cpu_state = BRANCH_NOT_TAKEN) else '0';
-- write enable is active low, asserted only when
-- rst=1, clk=0, and state=001(wr_acc)
n_we <= '1' when (clock = '1' or cpu_state /= WRITE or n_reset = '0') else '0';
end;