首页 文章

VHDL微处理器/微控制器

提问于
浏览
0

我正在学习在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中使用总线,制作两个端口"listen"或其他东西 . )

  • 如果您可以与我分享一些教程或链接信息,可以帮助我实现我的目标,这将是非常棒的 . 我搜索了很多,发现的信息非常少 .

1 回答

  • 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;
    

相关问题