VHDL microprocessor/microcontroller

孤人 提交于 2020-01-01 00:52:34

问题


I'm learning to code on Xilinx (VHDL). Next, I want to make a simple microprocessor/microcontroller and on the way learn a little about slice components. So my goal is try to code an 8 bits microprocessor using an AMD 2901 (4 bits-slice). (I already have the code of the 2901 and all its information about its input and output signals.)

I know the first step would be make the architecture of the microprocessor so I ended up with something like this (I understand that the bandwidth of the bus will be very different for what I'm looking for).

http://www.cs.binghamton.edu/~reckert/wk15fig1.JPG (Basically all I know about microprocessors and microcontrollers I get it from here http://www.cs.binghamton.edu/~reckert/hardwire3new.html)

So here are the punctual questions:

  1. How do I code a central bus like the diagram showed? How do I make "listen" and "write" my memory and components using a central big bus like the diagram?

  2. I want to use the 2901 ALU (two of them) so I have an 8-bit microprocessor. The question is: let’s say my opcode is using xxxxx001 (where x are control signals and 001 means add for the ALU) for add function on the ALU, so... as I have a slice ALU my opcode should be xxxxx001001 for give the instruction to both ALUs? Or should ALUs share the same "001" command? (I guess that can be done knowing how to use a bus in VHDL, making two ports "listen" or something.)

  3. If you can share with me some tutorials or links with information that can help me with my goal that will be awesome. I've searched a lot and found very very little information.


回答1:


This answer is about the 3rd part of your question.

You may find it useful to take a look at the MCPU project. It's an 8-bit CPU in 77 lines of VHDL code. Because the author has squeezed the entire design into 32 macrocells, the code is a little tricky in some places, but the design document helps.

I've also created a refactored version aiming at code readability, which is included below. Note that I'm not the original author of the project -- all kudos go to Tim Bö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;


来源:https://stackoverflow.com/questions/20955863/vhdl-microprocessor-microcontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!