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:
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?
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 bexxxxx001001
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.)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.
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