Desenvolvimento
This presentation is the property of its rightful owner.
Sponsored Links
1 / 41

Desenvolvimento de um processador (8 bits) PowerPoint PPT Presentation


  • 48 Views
  • Uploaded on
  • Presentation posted in: General

Desenvolvimento de um processador (8 bits). Processador. 8 bits de dados e 16 bits de endereço. master. I/O. ROM. RAM. slave. slave. slave. x ”8000” ----------- x ”FFFF”. x ”4000” ----------- x ”7FFF”. x ”0000” ----------- x ”3FFF”.

Download Presentation

Desenvolvimento de um processador (8 bits)

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Desenvolvimento de um processador 8 bits

Desenvolvimento de um processador (8 bits)

Processador

8 bits de dados e 16 bits de endereço

master

I/O

ROM

RAM

slave

slave

slave

x”8000”

-----------

x”FFFF”

x”4000”

-----------

x”7FFF”

x”0000”

-----------

x”3FFF”

http://www-md.e-technik.uni-rostock.de/lehre/vlsi_i/proc8/index.html.


Desenvolvimento de um processador 8 bits

Package

constant data_width:integer := 8;

constant addr_width:integer := 16;

subtype data_type is integer range 0 to 2** data_width-1

subtype addr_type is integer range 0 to 2** addr_width-1

+ outros tipos de dados


Desenvolvimento de um processador 8 bits

Grupos de sinais de interface

type bus_slv_in_type is

record

data : data_type; -- Data in

addr : addr_type; -- Address in

en : boolean; -- Enable

wr : boolean; -- Write

end record;

type bus_slv_out_type is

record

data : data_type; -- Data out

end record;

------------------------------------------------------

-- RAM (Bus Slave)

-----------------------------------------------------

component ram

generic (

depth : integer);

port (

clk : in std_logic;

busi : in bus_slv_in_type;

buso : out bus_slv_out_type);

end component;

subtype data_type is integer range 0 to 2** data_width-1

subtype addr_type is integer range 0 to 2** addr_width-1


Desenvolvimento de um processador 8 bits

-- Shift

constant SLLi : data_type := 24; -- shift logical left

constant SLRi : data_type := 25; -- shift logical right

constant ROLi : data_type := 26; -- rotate left

constant RORi : data_type := 27; -- rotate right

-- Jump

constant JMPi : data_type := 32; -- jump to address

constant JCi : data_type := 33; -- jump when carry flag is set

constant JNCi : data_type := 34; -- jump when carry flag is not set

constant JZi : data_type := 35; -- jump when zero flag is set

constant JNZi : data_type := 36; -- jump when zero flag is not set

-----------------------------------------------------------------------------

-- Memory mapped addresses

-----------------------------------------------------------------------------

constant ADDR_LED : addr_type := 0;

constant ADDR_SEG : addr_type := 1;

constant ADDR_SWITCH : addr_type := 2;

-----------------------------------------------------------------------------

-- Processor Flags

-----------------------------------------------------------------------------

type flags_type is

record

c : boolean; -- Carry flag

z : boolean; -- Zero flag

end record;

-----------------------------------------------------------------------------

--

-- Interfaces and Components

--

-----------------------------------------------------------------------------

library ieee;

use ieee.std_logic_1164.all;

package proc_pack is

-----------------------------------------------------------------------------

-- Data and address width

-----------------------------------------------------------------------------

constant data_width : integer := 8;

constant addr_width : integer := 16;

subtype data_type is integer range 0 to 2 ** data_width - 1;

subtype addr_type is integer range 0 to 2 ** addr_width - 1;

-----------------------------------------------------------------------------

-- Opcodes

-----------------------------------------------------------------------------

-- NOP

constant NOPi : data_type := 0; -- No Operation

-- Load and store

constant LDAi : data_type := 1; -- load from address to accu

constant LDCi : data_type := 2; -- load constant to accu

constant STAi : data_type := 3; -- store accu to address

constant LDXi : data_type := 8; -- load index register with constant

constant INCXi : data_type := 9; -- increment index register

constant DECXi : data_type := 10; -- decrement index register

-- Arithmetic

constant ADDi : data_type := 16; -- add data from address to accu

constant SUBi : data_type := 17; -- sub data from address from accu

constant NOTi : data_type := 18; -- sub data from address from accu

constant ANDi : data_type := 19; -- AND data from address with accu

constant ORi : data_type := 20; -- OR data from address with accu

constant XORi : data_type := 21; -- XOR data from address with accu


Desenvolvimento de um processador 8 bits

-----------------------------------------------------------------------------

-- Bus arbiter

-----------------------------------------------------------------------------

component arb

generic (

slaves : integer);

port (

msti : out bus_mst_in_type;

msto : in bus_mst_out_type;

slvi : out bus_slv_in_vector(0 to slaves - 1);

slvo : in bus_slv_out_vector(0 to slaves - 1));

end component;

-----------------------------------------------------------------------------

-- Processor (Bus Master)

-----------------------------------------------------------------------------

component proc

port (

clk : in std_logic;

rst : in std_logic;

en : in boolean;

busi : in bus_mst_in_type;

buso : out bus_mst_out_type);

end component;

-----------------------------------------------------------------------------

-- RAM (Bus Slave)

-----------------------------------------------------------------------------

component ram

generic (

depth : integer);

port (

clk : in std_logic;

busi : in bus_slv_in_type;

buso : out bus_slv_out_type);

end component;

-----------------------------------------------------------------------------

-- Bus interface (Master and Slave)

-----------------------------------------------------------------------------

type bus_mst_in_type is

record

data : data_type; -- Data in

end record;

type bus_mst_out_type is

record

data : data_type; -- Data out

addr : addr_type; -- Address out

en : boolean; -- Enable

wr : boolean; -- Write

end record;

type bus_slv_in_type is

record

data : data_type; -- Data in

addr : addr_type; -- Address in

en : boolean; -- Enable

wr : boolean; -- Write

end record;

type bus_slv_out_type is

record

data : data_type; -- Data out

end record;

type bus_slv_in_vector is array (natural range <>) of bus_slv_in_type;

type bus_slv_out_vector is array (natural range <>) of bus_slv_out_type;


Desenvolvimento de um processador 8 bits

-----------------------------------------------------------------------------

-- ROM (Bus Slave)

-----------------------------------------------------------------------------

component rom

generic (

depth : integer);

port (

clk : in std_logic;

busi : in bus_slv_in_type;

buso : out bus_slv_out_type);

end component;

-----------------------------------------------------------------------------

-- I/O and peripherals (Bus Slave)

-----------------------------------------------------------------------------

type io_in_type is

record

switch : std_logic_vector(7 downto 0); -- External Switches

end record;

type io_out_type is

record

seg_low : std_logic_vector(6 downto 0); -- External 7-segment low

seg_high : std_logic_vector(6 downto 0); -- External 7-segment high

led : std_logic_vector(7 downto 0); -- External LEDs

end record;

component io

generic (

depth : integer);

port (

clk : in std_logic;

rst : in std_logic;

busi : in bus_slv_in_type;

buso : out bus_slv_out_type;

ioi : in io_in_type;

ioo : out io_out_type);

end component;

end proc_pack;


Desenvolvimento de um processador 8 bits

Sistema

bus_mst_in_type

-- data

bus_mst_out_type

-- addr

-- data

-- en

-- wr

Processador

system.vhd

Arbiter (arb.vhd)

8 Bit dados e 16 Bit endereço

bus_slv_in_type

-- addr

-- data

-- en

-- wr

-- data

bus_slv_out_type

-- data

I/O

ROM

RAM

io_in_type

-- switch

io_out_type

-- led

-- seg

LEDs

Switches


Desenvolvimento de um processador 8 bits

Processador

O projecto:

I/O

ROM

RAM

use work.proc_pack.all;

entity arb is

generic (

slaves : integer := 3);

port (

msti : out bus_mst_in_type;

msto : in bus_mst_out_type;

slvi : out bus_slv_in_vector(0 to slaves - 1);

slvo : in bus_slv_out_vector(0 to slaves - 1));

end arb;

Os pacotes:

master

slave

slave

slave


Desenvolvimento de um processador 8 bits

architecture rtl of arb is

begin -- rtl

comb : process (msto, slvo)

variable slave : integer range 0 to slaves - 1;

begin -- process comb

-- Check the upper two address bits, and select a slave

case msto.addr / (2 ** (addr_width - 2)) is

when 0 => slave := 0; -- ROM : 0x0000 - 0x3FFF

when 1 => slave := 1; -- RAM : 0x4000 - 0x7FFF

when others => slave := 2; -- I/O : 0x8000 - 0xFFFF

end case;

-- Drive all slave inputs

for i in 0 to slaves - 1 loop

slvi(i).data <= msto.data;

slvi(i).addr <= msto.addr;

slvi(i).en <= msto.en and slave = i;

slvi(i).wr <= msto.wr;

end loop; -- i

-- Drive master inputs

msti.data <= slvo(slave).data;

end process comb;

end rtl;


Desenvolvimento de um processador 8 bits

O projecto:

entity io is

generic (

depth : integer);

port (

clk : in std_logic;

rst : in std_logic;

busi : in bus_slv_in_type;

buso : out bus_slv_out_type;

ioi : in io_in_type;

ioo : out io_out_type);

end io;

architecture rtl of io is

-- Registers

type reg_type is

record

ioo : io_out_type; -- registered output

buso : bus_slv_out_type;-- registered output

end record;

-- Signals to registers

signal r, rin : reg_type;

Os pacotes:


Desenvolvimento de um processador 8 bits

begin -- rtl

-----------------------------------------------------------------------------

-- Combinational logic

-----------------------------------------------------------------------------

comb: process (r, busi, ioi)

variable v : reg_type;

begin -- process comb

v := r;

---------------------------------------------------------------------------

-- Read access

---------------------------------------------------------------------------

if busi.en and not busi.wr then

case busi.addr mod depth is

when ADDR_LED =>

v.buso.data := to_unsigned_integer(r.ioo.led);

when ADDR_SWITCH =>

v.buso.data := to_unsigned_integer(ioi.switch);

when others =>

null;

end case;

end if;

Ler dados


Desenvolvimento de um processador 8 bits

---------------------------------------------------------------------------

-- Write access

---------------------------------------------------------------------------

if busi.en and busi.wr then

case busi.addr mod depth is

when ADDR_LED =>

v.ioo.led := to_unsigned_std_logic_vector(busi.data, 8);

when ADDR_SEG =>

v.ioo.seg_high := int2seg((busi.data / 16) mod 16);

v.ioo.seg_low := int2seg(busi.data mod 16);

when others =>

null;

end case;

end if;

---------------------------------------------------------------------------

-- Drive registers and signals

---------------------------------------------------------------------------

rin <= v;

ioo <= r.ioo;

buso <= r.buso;

end process comb;

Escrever dados


Desenvolvimento de um processador 8 bits

-----------------------------------------------------------------------------

-- Registers

-----------------------------------------------------------------------------

regs: process (clk, rst)

begin -- process regs

if rising_edge(clk) then

r <= rin;

end if;

if rst = '1' then

r.ioo.seg_low <= (others => '1');

r.ioo.seg_high <= (others => '1');

r.ioo.led <= (others => '0');

end if;

end process regs;

end rtl;


Desenvolvimento de um processador 8 bits

O projecto:

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.NUMERIC_STD.ALL;

--use IEEE.STD_LOGIC_ARITH.ALL;

--use IEEE.STD_LOGIC_UNSIGNED.ALL;

use work.macros.all;

use work.proc_pack.all;

entity proc is

port (

clk : in std_logic;

rst : in std_logic;

en : in boolean;

busi : in bus_mst_in_type;

buso : out bus_mst_out_type);

end proc;

Os pacotes:


Desenvolvimento de um processador 8 bits

architecture rtl of proc is

-- Processor states

type state_type is (fetch_op, -- Fetch opcode

fetch_addr_high, -- Fetch address high part

fetch_addr_low, -- Fetch address low part

execute); -- Execute operation

-- Processor registers

type reg_type is

record

state : state_type; -- Processor state

pc : addr_type; -- Program counter

opcode : data_type; -- Fetched opcode

addr : addr_type; -- Fetched address

accu : unsigned(data_width - 1 downto 0); -- Accumulator

x : data_type; -- Index register

flags : flags_type; -- Flags

buso : bus_mst_out_type; -- Registered outputs

end record;

-- Register signals

signal r, rin : reg_type;

fetch op

fetch addr_high

execute

Instruções de 1 e 2 Bytes

fetch addr_low


Desenvolvimento de um processador 8 bits

begin -- rtl

-----------------------------------------------------------------------------

-- Combinational Logic

-----------------------------------------------------------------------------

comb: process (r, en, busi)

-- Variable for register manipulation

variable v : reg_type;

-- Variable for accu with carry out

variable vaccu : unsigned(data_widthdownto 0);

begin -- process comb

---------------------------------------------------------------------------

-- Default assignments

---------------------------------------------------------------------------

v := r;


Desenvolvimento de um processador 8 bits

-- Do not access memory by default

v.buso.en := false;

-- Do not write by default

v.buso.wr := false;

if en then

-- Access memory

v.buso.en := true;

-- Address out is mostly program counter value

v.buso.addr := r.pc;

-- Data out is mostly accumulator value

v.buso.data := to_integer(r.accu);

-- Program counter is incremented by default

v.pc := (r.pc + 1) mod 2**addr_width;

---------------------------------------------------------------------------

-- State machine

---------------------------------------------------------------------------


Desenvolvimento de um processador 8 bits

case r.state is

when fetch_op => -- Fetch the op code

v.opcode := busi.data; -- store the op code

case v.opcode is -- and check it

when RORi | DECXi | INCXi | NOPi => -- When single byte operation go to execute

v.state := execute; -- and halt the program counter

v.pc := r.pc;

when LDCi | LDXi => -- When two byte operation go to execute

v.state := execute;

when others => -- otherwise fetch the address

v.state := fetch_addr_high;

end case;

when fetch_addr_high => -- Fetch the high part of the address

v.addr := busi.data; -- and store it in address register

v.state := fetch_addr_low;

when fetch_addr_low => -- Fetch the low part of the address

v.addr := to_integer(to_unsigned(r.addr, data_width) & -- combine it with the high part

to_unsigned(busi.data, data_width)); -- and store the result in address register

v.buso.addr := v.addr; -- Put the address on the bus

v.pc := r.pc; -- Halt the program counter

case r.opcode is -- check the op code

when STAi => -- write to Memory

v.buso.wr := true;

when JMPi => -- load the address to program counter

v.pc := v.addr;

when JCi => -- load the address to program counter when carry flag is set

if r.flags.c then v.pc := v.addr; end if;

when JNCi => -- load the address to program counter when carry flag is not set

if not r.flags.c then v.pc := v.addr; end if;

when JZi => -- load the address to program counter when zero flag is set

if r.flags.z then v.pc := v.addr; end if;

when JNZi => -- load the address to program counter when zero flag is not set

if not r.flags.z then v.pc := v.addr; end if;

when others => null;

end case;


Desenvolvimento de um processador 8 bits

v.state := execute; -- go to execute

when execute => -- Execute the instruction

-- check opcode

case r.opcode is

when LDCi | LDAi => -- Load data to accumulator

v.accu := to_unsigned(busi.data, data_width);

when LDXi => -- Load data to index register

v.x := busi.data;

when ADDi => -- execute addition

vaccu := '0' & r.accu + to_unsigned(busi.data, data_width + 1);

v.accu := vaccu(data_width - 1 downto 0); -- Assign to accumulator

v.flags.c := to_boolean(vaccu(data_width)); -- Assign flags

v.flags.z := to_integer(v.accu) = 0;

when SUBi => -- execute subtraction

vaccu := '0' & r.accu - to_unsigned(busi.data, data_width + 1);

v.accu := vaccu(data_width - 1 downto 0); -- Assign to accumulator

v.flags.c := to_boolean(vaccu(data_width)); -- Assign flags

v.flags.z := to_integer(v.accu) = 0;

when ANDi => -- AND and assign to accumulator

v.accu := r.accu and to_unsigned(busi.data, data_width);

v.flags.z := to_integer(v.accu) = 0; -- Assign flags

when RORi => -- Rotate through carry

v.accu := to_std_logic(r.flags.c) & r.accu(data_width - 1 downto 1);

v.flags.c := to_boolean(r.accu(0));

when DECXi => -- Decrement index register

v.x := (r.x - 1) mod 2 ** data_width;

v.flags.z := v.x = 0; -- Assign flags

when INCXi =>-- Increment index register

v.x := (r.x + 1) mod 2 ** data_width;

v.flags.z := v.x = 0; -- Assign flags

when others => null;

end case;

v.state := fetch_op; -- go to fetch operand

end case;

end if;


Desenvolvimento de um processador 8 bits

-- Drive register in and signals

rin <= v;

buso <= r.buso;

end process comb;

-----------------------------------------------------------------------------

-- Registers FSM MEMORY

-----------------------------------------------------------------------------

regs: process (clk, rst)

begin -- process regs

if rising_edge(clk) then

r <= rin;

end if;

if rst = '1' then

r.state <= execute;

r.pc <= 0;

r.opcode <= NOPi;

r.accu <= (others => '0');

r.flags <= (others => false);

end if;

end process regs;

end rtl;


Desenvolvimento de um processador 8 bits

O projecto:

library ieee;

use ieee.std_logic_1164.all;

use work.proc_pack.all;

entity rom is

generic (

depth : integer := 256);

port (

clk : in std_logic;

busi : in bus_slv_in_type;

buso : out bus_slv_out_type);

end rom;

Os pacotes:


Desenvolvimento de um processador 8 bits

architecture rtl of rom is -- Define your ROM content here

type mem_type is array (0 to depth - 1) of data_type;

constant mem : mem_type := ( -- Exemplo

LDCi, 1, -- load increment (0, 1)

STAi, 64, 0, -- store it at 0x4000 (2, 3, 4)

LDCi, 48, -- load the value 48 = 3016(5, 6)

STAi, 128, ADDR_SEG, -- show on 7-segment (7, 8, 9)

SUBi, 64, 0, -- decrement with value at 0x4000 (10, 11,12)

JNZi, 0, 7, -- if no carry out repeat at address 7 (13,14,15)

STAi, 128, ADDR_SEG, -- load the last value 0 (16,17,18)

LDCi, 128, -- load the value 10000000 (19, 20)

STAi, 128, ADDR_LED, -- turn on LED(7) (21,22,23)

JMPi, 0, 21, -- endless loop to address 21(24,25,26)

others => 0);

ROM

Accumulador

1

0

8000 4000 0000

RAM

64

RAM

Accumulador

I/O

1

128

0


Desenvolvimento de um processador 8 bits

--constant mem : mem_type := (

---- load Switch to mem

--LDAi, 128, ADDR_SWITCH, -- addr 0,1,2 Load switch to accumulator

---- Operator 1

--STAi, 64, 0, -- addr 3,4,5

---- Operator 2

--STAi, 64, 1, -- addr 6,7,8

---- Load mask to accu

--LDCi, 240, -- addr 9,10

---- apply mask to Op1in order to extract Op1

--ANDi, 64, 0, -- addr 11,12,13

---- Save OP1

--RORi,-- 14

--RORi,-- 15

--RORi,-- 16

--RORi,-- 17

--STAi, 64, 0, -- addr 18,19,20 0 keeps the most significant 4 bits of switch

--LDCi, 15, -- addr 21,22

--ANDi, 64, 1, -- addr 23,24,25 Accumulator keeps the lest significant 4 bits of switch

--ADDi, 64, 0, -- addr 26,27,28 Accumulator + register 0

--STAi, 128, ADDR_LED,

--JMPi, 0, 0,

--others => 0);


Desenvolvimento de um processador 8 bits

begin -- rtl

rom_proc: process (clk)

begin

if rising_edge(clk) then

if busi.en then

buso.data <= mem(busi.addr mod depth);

end if;

end if;

end process rom_proc;

end rtl;


Desenvolvimento de um processador 8 bits

Library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity RAM is

generic (AddressBits : positive;

DataBits : positive);

port (Clock : in STD_LOGIC;

WriteAddress : in STD_LOGIC_VECTOR(AddressBits - 1 downto 0);

WriteEnable : in STD_LOGIC;

DataIn : in STD_LOGIC_VECTOR(DataBits - 1 downto 0);

ReadAddress : in STD_LOGIC_VECTOR(AddressBits - 1 downto 0);

DataOut : out STD_LOGIC_VECTOR(DataBits - 1 downto 0));

end RAM;

architecture Behavioral of RAM is

type MemMatrix is array (0 to 2**AddressBits - 1) of

STD_LOGIC_VECTOR (DataBits - 1 downto 0);

signal Memory : MemMatrix := (others => x"00");

begin

process(Clock)

begin

if rising_edge (Clock) then

if WriteEnable = '1' then

Memory(conv_integer(WriteAddress)) <= DataIn;

end if;

DataOut <= Memory(conv_integer(ReadAddress));

end if;

end process;

end Behavioral;

O projecto:

Os pacotes:


Desenvolvimento de um processador 8 bits

Arbiter

use work.proc_pack.all;

entity arb is

generic (

slaves : integer := 3);

port (

msti : out bus_mst_in_type;

msto : in bus_mst_out_type;

slvi : out bus_slv_in_vector(0 to slaves - 1);

slvo : in bus_slv_out_vector(0 to slaves - 1));

end arb;

architecture rtl of arb is

begin -- rtl


Desenvolvimento de um processador 8 bits

comb : process (msto, slvo)

variable slave : integer range 0 to slaves - 1;

begin -- process comb

-- Check the the upper two address bits, and select a slave

case msto.addr / (2 ** (addr_width - 2)) is

when 0 => slave := 0; -- ROM : 0x0000 - 0x3FFF

when 1 => slave := 1; -- RAM : 0x4000 - 0x7FFF

when others => slave := 2; -- I/O : 0x8000 - 0xFFFF

end case;

-- Drive all slave inputs

for i in 0 to slaves - 1 loop

slvi(i).data <= msto.data;

slvi(i).addr <= msto.addr;

slvi(i).en <= msto.en and slave = i;

slvi(i).wr <= msto.wr;

end loop; -- i

-- Drive master inputs

msti.data <= slvo(slave).data;

end process comb;

end rtl;

System


Desenvolvimento de um processador 8 bits

-- ROM, RAM, I/O (Bus slaves)

signal slvi : bus_slv_in_vector(0 to 2);

signal slvo : bus_slv_out_vector(0 to 2);

-- I/O Signals

signal ioi : io_in_type;

signal ioo : io_out_type;

begin -- str

-----------------------------------------------------------------------------

-- Clock scaler to slow the processor down

-----------------------------------------------------------------------------

scale_clk : process (clk, rst)

variable counter :

unsigned(log2_ceil(CLK_RATE / TICKS_PER_SECOND) downto 0);

begin -- process scale_clk

if rising_edge(clk) then

counter := counter - 1;

if counter(counter'high) = '1' then

counter :=

to_unsigned(CLK_RATE / TICKS_PER_SECOND - 1, counter'length);

tick <= true;

else

tick <= false;

end if;

end if;

if rst = '1' then

counter := (others => '0');

tick <= false;

end if;

end process scale_clk;

library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

use work.macros.all;

use work.proc_pack.all;

entity system is

generic (

-- Adjust the "speed" of the processor here. Specifies the number of

-- processor clock cycles per second.

TICKS_PER_SECOND : integer := 16);

port (

clk : in std_logic;

rst : in std_logic;

-- I/O

-- seven-segment display

seg_low : out std_logic_vector(6 downto 0);

seg_high : out std_logic_vector(6 downto 0);

-- LEDs

led : out std_logic_vector(7 downto 0);

-- Switches

switch : in std_logic_vector(7 downto 0));

end system;

architecture str of system is

-- Processor tick

signal tick : boolean;

-- Processor (Bus master)

signal msti : bus_mst_in_type;

signal msto : bus_mst_out_type;


Desenvolvimento de um processador 8 bits

-----------------------------------------------------------------------------

-- Bus arbiter

-----------------------------------------------------------------------------

arb_i: arb

generic map (

slaves => 3)

port map (

msti => msti,

msto => msto,

slvi => slvi,

slvo => slvo);

-----------------------------------------------------------------------------

-- Processor (Bus master)

-----------------------------------------------------------------------------

proc_i : proc

port map (

clk => clk,

rst => rst,

en => tick,

busi => msti,

buso => msto);

-----------------------------------------------------------------------------

-- ROM (Bus slave 0)

-----------------------------------------------------------------------------

rom_i : rom

generic map (

depth => 256)

port map (

clk => clk,

busi => slvi(0),

buso => slvo(0));

-----------------------------------------------------------------------------

-- RAM (Bus slave 1)

-----------------------------------------------------------------------------

ram_i : ram

generic map (

depth => 256)

port map (

clk => clk,

busi => slvi(1),

buso => slvo(1));

-----------------------------------------------------------------------------

-- I/O module (Bus slave 2)

-----------------------------------------------------------------------------

io_i : io

generic map (

depth => 32)

port map (

clk => clk,

rst => rst,

busi => slvi(2),

buso => slvo(2),

ioi => ioi,

ioo => ioo);

-----------------------------------------------------------------------------

-- I/O signals

-----------------------------------------------------------------------------

-- LEDs

led <= ioo.led;

-- Seven-segment display

seg_low <= ioo.seg_low;

seg_high <= ioo.seg_high;

-- Switches

ioi.switch <= switch;

end str;


Desenvolvimento de um processador 8 bits

ROM

-- show on 7-segment

STAi, 128, ADDR_SEG,

-- increment with value at 0x4000

ADDi, 64, 0,

-- if no carry out repeat at address 5

JNCi, 0, 5,

-- turn on LED(7)

LDCi, 128,

STAi, 128, ADDR_LED,

-- endless loop to address 19

JMPi, 0, 19,

others => 0);

begin -- rtl

rom_proc: process (clk)

begin -- process ram_proc

if rising_edge(clk) then

if busi.en then

buso.data <= mem(busi.addr mod depth);

end if;

end if;

end process rom_proc;

end rtl;

entity rom is

generic (

depth : integer := 256);

port (

clk : in std_logic;

busi : in bus_slv_in_type;

buso : out bus_slv_out_type);

end rom;

architecture rtl of rom is

-- Define your ROM content here.

type mem_type is array (0 to depth - 1) of data_type;

constant mem : mem_type := (

-- load increment

LDCi, 1,

-- store it at 0x4000

STAi, 64, 0,


Desenvolvimento de um processador 8 bits

RAM

library ieee;

use ieee.std_logic_1164.all;

use work.proc_pack.all;

entity ram is

generic (

depth : integer := 256);

port (

clk : in std_logic;

busi : in bus_slv_in_type;

buso : out bus_slv_out_type);

end ram;

architecture rtl of ram is

-- RAM storage signal

type mem_type is array (0 to depth - 1) of data_type;

signal mem : mem_type;

-- Temporary read address, required for correct synthesis

-- Refer to Xilinx XST User Guide for more information.

signal addr, read_addr : integer range 0 to depth – 1;

begin -- rtl

addr <= busi.addr mod depth;

ram_proc: process (clk)

begin -- process ram_proc

if rising_edge(clk) then

if busi.en then

if busi.wr then

mem(addr) <= busi.data;

end if;

read_addr <= addr;

end if;

end if;

end process ram_proc;

buso.data <= mem(read_addr);

end rtl;


Desenvolvimento de um processador 8 bits

I/O

-----------------------------------------------------------------------------

-- Combinational logic

-----------------------------------------------------------------------------

comb: process (r, busi, ioi)

variable v : reg_type;

begin -- process comb

v := r;

---------------------------------------------------------------------------

-- Read access

---------------------------------------------------------------------------

if busi.en and not busi.wr then

case busi.addr mod depth is

when ADDR_LED =>

v.buso.data := to_unsigned_integer(r.ioo.led);

when ADDR_SWITCH =>

v.buso.data := to_unsigned_integer(ioi.switch);

when others =>

null;

end case;

end if;

---------------------------------------------------------------------------

-- Write access

---------------------------------------------------------------------------

if busi.en and busi.wr then

case busi.addr mod depth is

when ADDR_LED =>

v.ioo.led := to_unsigned_std_logic_vector(busi.data, 8);

when ADDR_SEG =>

v.ioo.seg_high := int2seg((busi.data / 16) mod 16);

v.ioo.seg_low := int2seg(busi.data mod 16);

when others =>

null;

end case;

end if;

library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

use work.macros.all;

use work.proc_pack.all;

entity io is

generic (

depth : integer);

port (

clk : in std_logic;

rst : in std_logic;

busi : in bus_slv_in_type;

buso : out bus_slv_out_type;

ioi : in io_in_type;

ioo : out io_out_type);

end io;

architecture rtl of io is

-- Registers

type reg_type is

record

ioo : io_out_type; -- registered output

buso : bus_slv_out_type; -- registered output

end record;

-- Signals to registers

signal r, rin : reg_type;

begin -- rtl


Desenvolvimento de um processador 8 bits

---------------------------------------------------------------------------

-- Drive registers and signals

---------------------------------------------------------------------------

rin <= v;

ioo <= r.ioo;

buso <= r.buso;

end process comb;

-----------------------------------------------------------------------------

-- Registers

-----------------------------------------------------------------------------

regs: process (clk, rst)

begin -- process regs

if rising_edge(clk) then

r <= rin;

end if;

if rst = '1' then

r.ioo.seg_low <= (others => '0');

r.ioo.seg_high <= (others => '0');

r.ioo.led <= (others => '0');

end if;

end process regs;

end rtl;


Desenvolvimento de um processador 8 bits

Processor

fetch op

fetch addr_high

execute

Instruções de 1 e 2 Bytes

fetch addr_low


Desenvolvimento de um processador 8 bits

library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

use work.macros.all;

use work.proc_pack.all;

entity proc is

port (

clk : in std_logic;

rst : in std_logic;

en : in boolean;

busi : in bus_mst_in_type;

buso : out bus_mst_out_type);

end proc;

architecture rtl of proc is

-- Processor states

type state_type is (fetch_op, -- Fetch opcode

fetch_addr_high, -- Fetch address high part

fetch_addr_low, -- Fetch address low part

execute); -- Execute operation

-- Processor registers

type reg_type is

record

state : state_type; -- Processor state

pc : addr_type; -- Program counter

opcode : data_type; -- Fetched opcode

addr : addr_type; -- Fetched address

accu : unsigned(data_width - 1 downto 0); -- Accumulator

x : data_type; -- Index register

flags : flags_type; -- Flags

buso : bus_mst_out_type; -- Registered outputs

end record;

-- Register signals

signal r, rin : reg_type;

begin -- rtl

-----------------------------------------------------------------------------

-- Combinational Logic

-----------------------------------------------------------------------------

comb: process (r, en, busi)

-- Variable for register manipulation

variable v : reg_type;

-- Variable for accu with carry out

variable vaccu : unsigned(data_width downto 0);

begin -- process comb

---------------------------------------------------------------------------

-- Default assignments

---------------------------------------------------------------------------

v := r;

-- Do not access memory by default

v.buso.en := false;

-- Do not write by default

v.buso.wr := false;

if en then

-- Access memory

v.buso.en := true;

-- Address out is mostly program counter value

v.buso.addr := r.pc;

-- Data out is mostly accumulator value

v.buso.data := to_integer(r.accu);

-- Program counter is incremented by default

v.pc := (r.pc + 1) mod 2**addr_width;


Desenvolvimento de um processador 8 bits

---------------------------------------------------------------------------

-- State machine

---------------------------------------------------------------------------

case r.state is

-- Fetch the opcode

when fetch_op =>

-- store the opcode

v.opcode := busi.data;

-- and check it

case v.opcode is

when RORi | DECXi =>

-- When single byte operation go to execute

v.state := execute;

-- and halt the program counter

v.pc := r.pc;

when LDCi | LDXi =>

-- When two byte operation go to execute

v.state := execute;

when others =>

-- otherwise fetch the address

v.state := fetch_addr_high;

end case;

-- Fetch the high part of the address

when fetch_addr_high =>

-- and store it in address register

v.addr := busi.data;

v.state := fetch_addr_low;

-- Fetch the low part of the address

when fetch_addr_low =>

-- combine it with the high part

-- and store the result in address register

v.addr := to_integer(to_unsigned(r.addr, data_width) &

to_unsigned(busi.data, data_width))

-- Put the address on the bus

v.buso.addr := v.addr;

-- Halt the program counter

v.pc := r.pc;

-- check the opcode

case r.opcode is

when STAi =>

-- write to Memory

v.buso.wr := true;

when JMPi =>

-- load the address to programm counter

v.pc := v.addr;

when JCi =>

-- load the address to programm counter when carry flag is set

if r.flags.c then

v.pc := v.addr;

end if;

when JNCi =>

-- load the address to programm counter when carry flag is not set

if not r.flags.c then

v.pc := v.addr;

end if;

when JZi =>

-- load the address to programm counter when zero flag is set

if r.flags.z then

v.pc := v.addr;

end if;

when JNZi =>

-- load the address to programm counter when zero flag is not set

if not r.flags.z then

v.pc := v.addr;

end if;

when others =>

null;

end case;

-- goto execute

v.state := execute;


Desenvolvimento de um processador 8 bits

-- Execute the instruction

when execute =>

-- check opcode

case r.opcode is

when LDCi | LDAi =>

-- Load data to accumulator

v.accu := to_unsigned(busi.data, data_width);

when LDXi =>

-- Load data to index register

v.x := busi.data;

when ADDi =>

vaccu := '0' & r.accu + to_unsigned(busi.data, data_width + 1);

-- Assign to accumulator

v.accu := vaccu(data_width - 1 downto 0);

-- Assign flags

v.flags.c := to_boolean(vaccu(data_width));

v.flags.z := to_integer(v.accu) = 0;

when ANDi =>

-- AND and assign to accumulator

v.accu := r.accu and to_unsigned(busi.data, data_width);

-- Assign flags

v.flags.z := to_integer(v.accu) = 0;

when RORi =>

-- Rotate through carry

v.accu := to_std_logic(r.flags.c) & r.accu(data_width - 1 downto 1);

v.flags.c := to_boolean(r.accu(0));

when DECXi =>

-- Decrement index register

v.x := (r.x - 1) mod 2 ** data_width;

-- Assign flags

v.flags.z := v.x = 0;

when others =>

null;

end case;

-- goto fetch operand

v.state := fetch_op;

end case;

end if;

---------------------------------------------------------------------------

-- Drive register in and signals

---------------------------------------------------------------------------

rin <= v;

buso <= r.buso;

end process comb;

-----------------------------------------------------------------------------

-- Registers

-----------------------------------------------------------------------------

regs: process (clk, rst)

begin -- process regs

if rising_edge(clk) then

r <= rin;

end if;

if rst = '1' then

r.state <= execute;

r.pc <= 0;

r.opcode <= NOPi;

r.accu <= (others => '0');

r.flags <= (others => false);

end if;

end process regs;

end rtl;


Desenvolvimento de um processador 8 bits

Testbench

use ieee.std_logic_1164.all;

use work.macros.all;

use work.proc_pack.all;

use work.syslog.all;

entity system_tb is

generic (

-- length of clock period

PERIOD : time := 1 sec / CLK_RATE;

-- Time after simulation is terminated

DURATION : time := 10 sec;

-- Processor ticks per second

TICKS_PER_SECOND : integer := CLK_RATE / 2);

end system_tb;

architecture beh of system_tb is

-- UUT component

component system

generic (

TICKS_PER_SECOND : integer);

port (

clk : in std_logic;

rst : in std_logic;

seg_low : out std_logic_vector(6 downto 0);

seg_high : out std_logic_vector(6 downto 0);

led : out std_logic_vector(7 downto 0);

switch : in std_logic_vector(7 downto 0));

end component;

-- UUT signals

signal clk : std_logic := '0';

signal rst : std_logic := '1';

signal seg_low : std_logic_vector(6 downto 0);

signal seg_high : std_logic_vector(6 downto 0);

signal led : std_logic_vector(7 downto 0);

signal switch : std_logic_vector(7 downto 0) := (others => '0');

begin -- beh

-----------------------------------------------------------------------------

-- UUT instance

-----------------------------------------------------------------------------

UUT: system

generic map (

TICKS_PER_SECOND => TICKS_PER_SECOND)

port map (

clk => clk,

rst => rst,

seg_low => seg_low,

seg_high => seg_high,

led => led,

switch => switch);

-----------------------------------------------------------------------------

-- Generate clock

-----------------------------------------------------------------------------

clk <= not clk after PERIOD / 2;


Desenvolvimento de um processador 8 bits

-----------------------------------------------------------------------------

-- The test process

-----------------------------------------------------------------------------

test: process

variable result : integer;

begin -- process test

-- Generate reset

rst <= '1';

wait for 4 * PERIOD;

rst <= '0';

-- Wait for LED(7)

wait until rising_edge(clk) and led(7) = '1';

-- Terminate simulation

syslog_terminate;

end process test;

-----------------------------------------------------------------------------

-- The time bomb

-----------------------------------------------------------------------------

time_bomb: process

begin -- process time_bomb

-- Wait until the bomb explodes

wait for DURATION;

-- Give error message and terminate simulation

syslog(error, "Program did not finish");

syslog_terminate;

end process time_bomb;

end beh;


Desenvolvimento de um processador 8 bits

Adicionar uma nova instrução

LDA 0x1234, X ; Load value from (0x1234 + X) into accu

  • Três passos seguintes:

  • Definir o código de operação em proc_pack.vhd;

  • Se necessário adicionar um novo estado ao proc.vhd

  • Adicionar entradas case em estados do processador

constant LDAIXi : data_type := 11; -- load from address + x

Ver a próxima página

-- Execute the instruction

when execute =>

-- check opcode

case r.opcode is

when LDCi | LDAi | LDAIXi =>

-- Load data to accumulator

v.accu := to_unsigned(busi.data, data_width);


Desenvolvimento de um processador 8 bits

-- Fetch the low part of the address

when fetch_addr_low =>

-- combine it with the high part

-- and store the result in address register

v.addr := to_integer(to_unsigned(r.addr, data_width) &

to_unsigned(busi.data, data_width));

-- Put the address on the bus

v.buso.addr := v.addr;

-- Halt the program counter

v.pc := r.pc;

-- check the opcode

case r.opcode is

when LDAIXi =>

-- add x to the address and put it on the bus

v.buso.addr := v.addr + r.x;

when STAi =>

-- write to Memory

v.buso.wr := true;


  • Login