processador 8 bits de dados e 16 bits de endereço rom ram i/o x”0000” ----------- x”3fff”...

41
Processa dor 8 bits de dados e 16 bits de endereço ROM RAM I/O x”0000” ----------- x”3FFF” x”4000” ----------- x”7FFF” x”8000” ----------- x”FFFF” master slave slave slave ttp://www-md.e-technik.uni-rostock.de/lehre/vlsi_i/proc8/index.html .

Upload: godfrey-fitzgerald

Post on 14-Dec-2015

227 views

Category:

Documents


1 download

TRANSCRIPT

Processador

8 bits de dados e 16 bits de endereço

ROM RAM I/Ox”0000”-----------x”3FFF”

x”4000”-----------x”7FFF”

x”8000”-----------x”FFFF”

master

slave slave slave

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

constant data_width : integer := 8;constant addr_width : integer := 16;

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

+ outros tipos de dados

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-1subtype addr_type is integer range 0 to 2** addr_width-1

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

-- 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 -- -----------------------------------------------------------------------------

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

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

----------------------------------------------------------------------------- -- 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 LEDsend 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;

Processador

8 Bit dados e 16 Bit endereço

ROM RAM I/O

Arbiter (arb.vhd)

bus_mst_in_type-- databus_mst_out_type-- addr-- data-- en-- wr

LEDsSwitches

bus_slv_in_type-- addr-- data-- en-- wr-- databus_slv_out_type-- dataio_in_type

-- switchio_out_type-- led-- seg

system.vhd

O projecto:

Os pacotes: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;

Processador

ROM RAM I/O

master

slave slave slave

architecture rtl of arb isbegin -- 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;

O projecto:

Os pacotes:

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

----------------------------------------------------------------------------- -- 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

--------------------------------------------------------------------------- -- 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

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

O projecto:

Os pacotes:

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;

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

executefetch

addr_high

fetch addr_low

Instruções de 1 e 2 Bytes

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;

--------------------------------------------------------------------------- -- State machine ---------------------------------------------------------------------------

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;

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;

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

O projecto:

Os pacotes:

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;

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);

Accumulador1

RAM

0Accumulador 1

ROM0

RAM64

I/O128 8000

4

000

0

000

--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 Op1 in 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);

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;

O projecto:

Os pacotes:

Library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity RAM isgeneric (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 istype MemMatrix is array (0 to 2**AddressBits - 1) of

STD_LOGIC_VECTOR (DataBits - 1 downto 0);signal Memory : MemMatrix := (others => x"00");beginprocess(Clock)begin if rising_edge (Clock) then

if WriteEnable = '1' thenMemory(conv_integer(WriteAddress)) <= DataIn;

end if;DataOut <= Memory(conv_integer(ReadAddress));

end if;end process;end Behavioral;

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

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;

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;

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

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

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,

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

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;

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

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

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

fetch op

executefetch

addr_high

fetch addr_low

Instruções de 1 e 2 Bytes

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;

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

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

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;

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

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

Três passos seguintes:1.Definir o código de operação em proc_pack.vhd;2.Se necessário adicionar um novo estado ao proc.vhd3.Adicionar entradas case em estados do processador

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

-- 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);

Ver a próxima página

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