----------------------------------------------------------------- -- uCore 1.90 - uCore.vhd -- ----------------------------------------------------------------- -- -- Author: KLAUS SCHLEISIEK -- Last change: KS 10.12.2015 15:15:49 -- -- Do not use this file except in compliance with the License. You may -- obtain a copy of the License at http://www.microcore.org/License/ -- Software distributed under the License is distributed on an "AS IS" basis, -- WITHOUT WARRANTY OF ANY KIND, either express or implied. -- See the License for the specific language governing rights and limitations -- under the License. -- -- The Initial Developer of the Original Code is Klaus.Schleisiek AT microcore.org. -- -- The uCore engine LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_signed.ALL; USE work.functions.ALL; USE work.constants.ALL; ENTITY microcore IS PORT (uBus : IN uBus_port; flags : INOUT flag_bus; core : OUT core_signals; ext_memory : OUT datamem_port; ext_din : IN data_bus; dma : IN datamem_port; dma_din : OUT data_bus; -- umbilical debug interface rxd : IN STD_LOGIC; txd : OUT STD_LOGIC ); END microcore; ARCHITECTURE rtl OF microcore IS ATTRIBUTE syn_keep : BOOLEAN; ATTRIBUTE init : STRING; ALIAS reset : STD_LOGIC IS uBus.reset; ALIAS clk : STD_LOGIC IS uBus.clk; ALIAS clk_en : STD_LOGIC IS uBus.clk_en; ALIAS read_en : STD_LOGIC IS uBus.read_en; ALIAS delay : STD_LOGIC IS uBus.delay; ALIAS except : STD_LOGIC IS uBus.except; CONSTANT cycle : NATURAL := phase_1 + phase_2; SIGNAL cycle_ctr : NATURAL RANGE 0 TO cycle + 1; COMPONENT microcontrol PORT (uBus : IN uBus_port; reset : IN STD_LOGIC; except : IN STD_LOGIC; disable : IN STD_LOGIC; uReg : OUT core_signals; progmem : OUT progmem_port; prog_din : IN inst_bus; datamem : OUT datamem_port; data_din : IN data_bus ); END COMPONENT; SIGNAL uReg : core_signals; SIGNAL core_reset : STD_LOGIC; SIGNAL core_exc : STD_LOGIC; SIGNAL progmem : progmem_port; SIGNAL datamem : datamem_port; SIGNAL data_din : data_bus; COMPONENT uart GENERIC (uartrate : NATURAL); PORT (uBus : IN uBus_port; rxd : IN STD_LOGIC; dtr : IN STD_LOGIC; txd : OUT STD_LOGIC; uart_in : IN to_uart; uart_out : OUT from_uart ); END COMPONENT; SIGNAL uart_in : to_uart; SIGNAL uart_out : from_uart; COMPONENT debugger PORT (uBus : IN uBus_port; debugrom : OUT progmem_port; debug_res : OUT STD_LOGIC; debug_exc : OUT STD_LOGIC; prog_load : OUT STD_LOGIC; debug_flag : OUT STD_LOGIC; debug_data : OUT data_bus; -- umbilical uart_in : IN from_uart; uart_out : OUT to_uart ); END COMPONENT; SIGNAL prog_load : STD_LOGIC; SIGNAL debugrom : progmem_port; SIGNAL debug_exc : STD_LOGIC; SIGNAL debug_res : STD_LOGIC; SIGNAL debug_data : data_bus; SIGNAL booting_n : STD_LOGIC := '0'; ATTRIBUTE syn_keep OF booting_n : SIGNAL IS true; ATTRIBUTE init OF booting_n : SIGNAL IS "0"; SIGNAL reset_d : STD_LOGIC; COMPONENT boot_rom PORT (addr : IN boot_addr; data : OUT inst_bus); END COMPONENT; SIGNAL boot_data : inst_bus; SIGNAL boot_adr : boot_addr; -- data memory SIGNAL cache_en : STD_LOGIC; SIGNAL cache_addr : STD_LOGIC_VECTOR(dcache_addr_width-1 DOWNTO 0); SIGNAL cache_din : data_bus; SIGNAL internal : STD_LOGIC; SIGNAL io_select : STD_LOGIC; -- program memory SIGNAL cache_pdin : inst_bus; SIGNAL pdin : inst_bus; SIGNAL pdout : inst_bus; SIGNAL penable : STD_LOGIC; SIGNAL pwrite : STD_LOGIC; SIGNAL paddr : program_addr; BEGIN ----------------------------------------------------------------------- -- sub-uCore cycle control ----------------------------------------------------------------------- read_enable: PROCESS (clk, reset) BEGIN IF reset = '1' AND async_reset THEN core.read_en <= '0'; core.clk_en <= '0'; cycle_ctr <= 1; ELSIF rising_edge(clk) THEN IF reset = '1' AND NOT async_reset THEN core.read_en <= '0'; core.clk_en <= '0'; cycle_ctr <= 1; ELSE core.clk_en <= '0'; core.read_en <= '0'; cycle_ctr <= cycle_ctr + 1; IF cycle_ctr = phase_1-1 THEN core.read_en <= '1'; END IF; IF cycle_ctr = cycle-1 THEN IF delay = '1' THEN cycle_ctr <= cycle-1; ELSE cycle_ctr <= 0; core.clk_en <= '1'; END IF; END IF; END IF; END IF; END PROCESS read_enable; ----------------------------------------------------------------------- -- internal data memory ----------------------------------------------------------------------- internal <= datamem.enable WHEN dcache_addr_width /= 0 AND datamem.addr(data_width-1 DOWNTO dcache_addr_width) = 0 ELSE '0'; cache_en <= internal AND ((clk_en AND datamem.write) OR (read_en AND NOT datamem.write)); make_inferred_datamem: IF dcache_addr_width /= 0 GENERATE cache_addr <= datamem.addr(dcache_addr_width-1 DOWNTO 0); internal_data_mem: internal_dpram GENERIC MAP(data_width, dcache_addr_width, DMEM_file) PORT MAP(clk => clk, ena => cache_en, wea => datamem.write, addra => cache_addr, dia => datamem.dout, doa => cache_din, enb => dma.enable, web => dma.write, addrb => dma.addr(dcache_addr_width-1 DOWNTO 0), dib => dma.dout, dob => dma_din ); END GENERATE make_inferred_datamem; ext_memory <= datamem; syn_select: PROCESS (reset, clk) BEGIN IF reset = '1' AND async_reset THEN io_select <= '0'; ELSIF rising_edge(clk) THEN IF reset = '1' AND NOT async_reset THEN io_select <= '0'; ELSE io_select <= internal; END IF; END IF; END PROCESS syn_select; data_din <= cache_din WHEN io_select = '1' ELSE ext_din; ----------------------------------------------------------------------- -- internal program memory ----------------------------------------------------------------------- pwrite <= debugrom.write WHEN prog_load = '1' ELSE -- progmem.write WHEN prog_ram_width /= 0 ELSE '0'; -- always r/w prog memory progmem.write WHEN prog_ram_width /= 0 AND (booting_n = '0' OR simulation) ELSE '0'; -- only during boot phase paddr <= debugrom.addr WHEN prog_load = '1' ELSE progmem.addr; pdout <= debugrom.dout WHEN prog_load = '1' ELSE progmem.dout; penable <= booting_n AND ((clk_en AND pwrite) OR (read_en AND NOT pwrite AND NOT prog_load)); internal_prog_mem: internal_ram GENERIC MAP(inst_width, pcache_addr_width, MEM_file) PORT MAP(clk => clk, en => penable, we => pwrite, addr => paddr(pcache_addr_width-1 DOWNTO 0), di => pdout, do => cache_pdin ); pdin <= cache_pdin WHEN booting_n = '1' ELSE boot_data; ----------------------------------------------------------------------- -- boot loader, reads from program memory after branch to zero (reboot) ----------------------------------------------------------------------- boot_ctrl: PROCESS (reset, clk) BEGIN IF reset = '1' AND async_reset THEN booting_n <= '0'; -- go into boot loading on reset reset_d <= '1'; ELSIF rising_edge(clk) THEN IF reset = '1' AND NOT async_reset THEN booting_n <= '0'; -- go into boot loading on reset reset_d <= '1'; ELSE IF clk_en = '1' THEN reset_d <= reset; END IF; IF (reset_d = '0' AND progmem.addr = 0 AND progmem.write = '0') OR prog_load = '1' THEN booting_n <= '1'; END IF; END IF; END IF; END PROCESS boot_ctrl; boot_adr <= progmem.addr(boot_addr_width-1 DOWNTO 0) WHEN booting_n = '0' ELSE (OTHERS => '0'); boot_loader: boot_rom PORT MAP(boot_adr, boot_data); ----------------------------------------------------------------------- -- instruction execution engine ----------------------------------------------------------------------- core_reset <= reset OR debug_res; core_exc <= except OR debug_exc; uCntrl: microcontrol PORT MAP (uBus => uBus, reset => core_reset, except => core_exc, disable => prog_load, uReg => uReg, progmem => progmem, prog_din => pdin, datamem => datamem, data_din => data_din ); core.tick <= uReg.tick; core.int <= uReg.int; core.task <= uReg.task; core.time <= uReg.time; core.debug <= debug_data; ----------------------------------------------------------------------- -- umbilical debug interface ----------------------------------------------------------------------- debug_interface: uart GENERIC MAP(umbilical_rate) PORT MAP (uBus => uBus, rxd => rxd, dtr => '1', txd => txd, uart_in => uart_in, uart_out => uart_out ); flags(f_break) <= uart_out.break; debug_unit: debugger PORT MAP (uBus => uBus, debugrom => debugrom, debug_res => debug_res, debug_exc => debug_exc, prog_load => prog_load, debug_flag => flags(f_debug), debug_data => debug_data, uart_in => uart_out, uart_out => uart_in ); END rtl;