2014-01-06 90 views
0

我正在學習在Xilinx(VHDL)上編寫代碼。接下來,我想製作一個簡單的微處理器/微控制器,並在途中學習一些關於切片組件的知識。所以我的目標是嘗試使用AMD 2901(4位片)對8位微處理器進行編碼。 (我已經有了2901的代碼以及它的輸入和輸出信號的所有信息。)VHDL微處理器/微控制器

我知道第一步是使微處理器的架構,所以我最終得到了類似的東西(我明白總線的帶寬將與我所尋找的有很大不同)。

http://www.cs.binghamton.edu/~reckert/wk15fig1.JPG (基本上所有我知道的微處理器和微控制器我把它從這裏http://www.cs.binghamton.edu/~reckert/hardwire3new.html

因此,這裏是準時的問題:

  1. 如何編寫一箇中央總線像圖表現?我如何使用中央大巴士(如圖)「聽」和「寫」我的記憶和組件?

  2. 我想使用2901 ALU(其中兩個),所以我有一個8位微處理器。問題是:假設我的操作碼正在使用xxxxx001(其中x是控制信號,001表示爲ALU添加),因此對於ALU上的添加功能,因爲我有一個slice ALU,因此我的操作碼應爲xxxxx001001指令給兩個ALU?或者應該ALU共享相同的「001」命令? (我想這可以知道如何使用VHDL中的總線,使兩個端口「聽」或什麼)

  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;