Microprocessor / Microcontroller VHDL

I am learning Xilinx code (VHDL). Then I want to make a simple microprocessor / microcontroller and learn a little about the components of the slice along the way. So my goal is to program an 8-bit microprocessor using the AMD 2901 (4-bit slice). (I already have code 2901 and all its information about its input and output signals.)

I know that the first step will be the microprocessor architecture, so I got something like this (I understand that the bus bandwidth will be very different for what I'm looking for).

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

So, here are the punctual questions:

  • How to code the central bus as shown in the diagram? How to make your memory and components โ€œlistenโ€ and โ€œrecordโ€ using a central large bus such as a diagram?

  • I want to use 2901 ALU (two of them), so I have an 8-bit microprocessor. The question arises: let's say my operation code uses xxxxx001(where x is the control signal, and 001 means add for ALU) to add a function to ALU, so ... since I have an ALU fragment, my operation code should be xxxxx001001for specifying instructions for both Alu? Or should the ALU use the same "001" command? (I suppose this can be done by knowing how to use the bus in VHDL by making two ports โ€œlistenโ€ or something like that.)

  • , , . .

0
1

.

MCPU. 8- 77 VHDL. 32 , , .

, , . , - .

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;
+3

All Articles