1 / 23

Desenvolvimento de um processador (8 bits)

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

graham
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. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

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

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

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

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

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

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

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

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

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

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

  12. 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,

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

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

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

  16. Processor fetch op fetch addr_high execute Instruções de 1 e 2 Bytes fetch addr_low

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

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

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

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

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

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

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

More Related