You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			220 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			VHDL
		
	
			
		
		
	
	
			220 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			VHDL
		
	
-- The Potato Processor - SoC design for the Arty FPGA board
 | 
						|
-- (c) Kristian Klomsten Skordal 2016 <kristian.skordal@wafflemail.net>
 | 
						|
 | 
						|
library ieee;
 | 
						|
use ieee.std_logic_1164.all;
 | 
						|
use ieee.math_real.all;
 | 
						|
 | 
						|
library work;
 | 
						|
use work.wishbone_types.all;
 | 
						|
 | 
						|
 | 
						|
-- 0x00000000: Main memory (1 MB)
 | 
						|
-- 0xc0002000: UART0 (for host communication)
 | 
						|
entity toplevel is
 | 
						|
  generic (
 | 
						|
    MEMORY_SIZE   : positive := 1048576;
 | 
						|
    RAM_INIT_FILE : string   := "firmware.hex");
 | 
						|
	port(
 | 
						|
		clk       : in  std_logic;
 | 
						|
		reset_n   : in  std_logic;
 | 
						|
		
 | 
						|
		-- UART0 signals:
 | 
						|
		uart0_txd : out std_logic;
 | 
						|
		uart0_rxd : in  std_logic
 | 
						|
	);
 | 
						|
end entity toplevel;
 | 
						|
 | 
						|
architecture behaviour of toplevel is
 | 
						|
 | 
						|
	-- Reset signals:
 | 
						|
	signal reset : std_logic;
 | 
						|
 | 
						|
	-- Internal clock signals:
 | 
						|
	signal system_clk : std_logic;
 | 
						|
	signal timer_clk  : std_logic;
 | 
						|
	signal system_clk_locked : std_logic;
 | 
						|
 | 
						|
	-- wishbone signals:
 | 
						|
	signal wishbone_proc_out: wishbone_master_out;
 | 
						|
	signal wishbone_proc_in: wishbone_slave_out;
 | 
						|
 | 
						|
	-- Processor signals:
 | 
						|
	signal processor_adr_out : std_logic_vector(63 downto 0);
 | 
						|
	signal processor_sel_out : std_logic_vector(7 downto 0);
 | 
						|
	signal processor_cyc_out : std_logic;
 | 
						|
	signal processor_stb_out : std_logic;
 | 
						|
	signal processor_we_out  : std_logic;
 | 
						|
	signal processor_dat_out : std_logic_vector(63 downto 0);
 | 
						|
	signal processor_dat_in  : std_logic_vector(63 downto 0);
 | 
						|
	signal processor_ack_in  : std_logic;
 | 
						|
	
 | 
						|
	-- UART0 signals:
 | 
						|
	signal uart0_adr_in  : std_logic_vector(11 downto 0);
 | 
						|
	signal uart0_dat_in  : std_logic_vector( 7 downto 0);
 | 
						|
	signal uart0_dat_out : std_logic_vector( 7 downto 0);
 | 
						|
	signal uart0_cyc_in  : std_logic;
 | 
						|
	signal uart0_stb_in  : std_logic;
 | 
						|
	signal uart0_we_in   : std_logic;
 | 
						|
	signal uart0_ack_out : std_logic;
 | 
						|
 | 
						|
	-- Main memory signals:
 | 
						|
	signal main_memory_adr_in  : std_logic_vector(positive(ceil(log2(real(MEMORY_SIZE))))-1 downto 0);
 | 
						|
	signal main_memory_dat_in  : std_logic_vector(63 downto 0);
 | 
						|
	signal main_memory_dat_out : std_logic_vector(63 downto 0);
 | 
						|
	signal main_memory_cyc_in  : std_logic;
 | 
						|
	signal main_memory_stb_in  : std_logic;
 | 
						|
	signal main_memory_sel_in  : std_logic_vector(7 downto 0);
 | 
						|
	signal main_memory_we_in   : std_logic;
 | 
						|
	signal main_memory_ack_out : std_logic;
 | 
						|
 | 
						|
	-- Selected peripheral on the interconnect:
 | 
						|
	type intercon_peripheral_type is (
 | 
						|
		PERIPHERAL_UART0, PERIPHERAL_MAIN_MEMORY, PERIPHERAL_ERROR,
 | 
						|
		PERIPHERAL_NONE);
 | 
						|
	signal intercon_peripheral : intercon_peripheral_type := PERIPHERAL_NONE;
 | 
						|
 | 
						|
	-- Interconnect address decoder state:
 | 
						|
	signal intercon_busy : boolean := false;
 | 
						|
 | 
						|
	-- disable for now
 | 
						|
	signal gpio_pins : std_logic_vector(11 downto 0);
 | 
						|
	signal uart1_txd : std_logic;
 | 
						|
	signal uart1_rxd : std_logic;
 | 
						|
begin
 | 
						|
 | 
						|
	address_decoder: process(system_clk)
 | 
						|
	begin
 | 
						|
		if rising_edge(system_clk) then
 | 
						|
			if reset = '1' then
 | 
						|
				intercon_peripheral <= PERIPHERAL_NONE;
 | 
						|
				intercon_busy <= false;
 | 
						|
			else
 | 
						|
				if not intercon_busy then
 | 
						|
					if processor_cyc_out = '1' then
 | 
						|
						intercon_busy <= true;
 | 
						|
 | 
						|
						if processor_adr_out(31 downto 24) = x"00" then -- Main memory space
 | 
						|
							intercon_peripheral <= PERIPHERAL_MAIN_MEMORY;
 | 
						|
						elsif processor_adr_out(31 downto 24) = x"c0" then -- Peripheral memory space
 | 
						|
							case processor_adr_out(15 downto 12) is
 | 
						|
								when x"2" =>
 | 
						|
									intercon_peripheral <= PERIPHERAL_UART0;
 | 
						|
								when others => -- Invalid address - delegated to the error peripheral
 | 
						|
									intercon_peripheral <= PERIPHERAL_ERROR;
 | 
						|
							end case;
 | 
						|
						else
 | 
						|
							intercon_peripheral <= PERIPHERAL_ERROR;
 | 
						|
						end if;
 | 
						|
					else
 | 
						|
						intercon_peripheral <= PERIPHERAL_NONE;
 | 
						|
					end if;
 | 
						|
				else
 | 
						|
					if processor_cyc_out = '0' then
 | 
						|
						intercon_busy <= false;
 | 
						|
						intercon_peripheral <= PERIPHERAL_NONE;
 | 
						|
					end if;
 | 
						|
				end if;
 | 
						|
			end if;
 | 
						|
		end if;
 | 
						|
	end process address_decoder;
 | 
						|
 | 
						|
	processor_intercon: process(all)
 | 
						|
	begin
 | 
						|
		case intercon_peripheral is
 | 
						|
			when PERIPHERAL_UART0 =>
 | 
						|
				processor_ack_in <= uart0_ack_out;
 | 
						|
				processor_dat_in <= x"00000000000000" & uart0_dat_out;
 | 
						|
			when PERIPHERAL_MAIN_MEMORY =>
 | 
						|
				processor_ack_in <= main_memory_ack_out;
 | 
						|
				processor_dat_in <= main_memory_dat_out;
 | 
						|
			when PERIPHERAL_NONE =>
 | 
						|
				processor_ack_in <= '0';
 | 
						|
				processor_dat_in <= (others => '0');
 | 
						|
			when others =>
 | 
						|
				processor_ack_in <= '0';
 | 
						|
				processor_dat_in <= (others => '0');
 | 
						|
		end case;
 | 
						|
	end process processor_intercon;
 | 
						|
 | 
						|
	reset_controller: entity work.pp_soc_reset
 | 
						|
		port map(
 | 
						|
			clk => system_clk,
 | 
						|
			reset_n => reset_n,
 | 
						|
			reset_out => reset,
 | 
						|
			system_clk => system_clk,
 | 
						|
			system_clk_locked => system_clk_locked
 | 
						|
		);
 | 
						|
 | 
						|
	clkgen: entity work.clock_generator
 | 
						|
		port map(
 | 
						|
			clk => clk,
 | 
						|
			resetn => reset_n,
 | 
						|
			system_clk => system_clk,
 | 
						|
			locked => system_clk_locked
 | 
						|
		);
 | 
						|
 | 
						|
	processor: entity work.core
 | 
						|
		port map(
 | 
						|
			clk => system_clk,
 | 
						|
			rst => reset,
 | 
						|
 | 
						|
			wishbone_out => wishbone_proc_out,
 | 
						|
			wishbone_in => wishbone_proc_in
 | 
						|
	);
 | 
						|
	processor_adr_out <= wishbone_proc_out.adr;
 | 
						|
	processor_dat_out <= wishbone_proc_out.dat;
 | 
						|
	processor_sel_out <= wishbone_proc_out.sel;
 | 
						|
	processor_cyc_out <= wishbone_proc_out.cyc;
 | 
						|
	processor_stb_out <= wishbone_proc_out.stb;
 | 
						|
	processor_we_out <= wishbone_proc_out.we;
 | 
						|
	wishbone_proc_in.dat <= processor_dat_in;
 | 
						|
	wishbone_proc_in.ack <= processor_ack_in;
 | 
						|
 | 
						|
	uart0: entity work.pp_soc_uart
 | 
						|
		generic map(
 | 
						|
			FIFO_DEPTH => 32
 | 
						|
		) port map(
 | 
						|
			clk => system_clk,
 | 
						|
			reset => reset,
 | 
						|
			txd => uart0_txd,
 | 
						|
			rxd => uart0_rxd,
 | 
						|
			wb_adr_in => uart0_adr_in,
 | 
						|
			wb_dat_in => uart0_dat_in,
 | 
						|
			wb_dat_out => uart0_dat_out,
 | 
						|
			wb_cyc_in => uart0_cyc_in,
 | 
						|
			wb_stb_in => uart0_stb_in,
 | 
						|
			wb_we_in => uart0_we_in,
 | 
						|
			wb_ack_out => uart0_ack_out
 | 
						|
		);
 | 
						|
	uart0_adr_in <= processor_adr_out(uart0_adr_in'range);
 | 
						|
	uart0_dat_in <= processor_dat_out(7 downto 0);
 | 
						|
	uart0_we_in  <= processor_we_out;
 | 
						|
	uart0_cyc_in <= processor_cyc_out when intercon_peripheral = PERIPHERAL_UART0 else '0';
 | 
						|
	uart0_stb_in <= processor_stb_out when intercon_peripheral = PERIPHERAL_UART0 else '0';
 | 
						|
 | 
						|
	main_memory: entity work.pp_soc_memory
 | 
						|
		generic map(
 | 
						|
			MEMORY_SIZE   => MEMORY_SIZE,
 | 
						|
			RAM_INIT_FILE => RAM_INIT_FILE
 | 
						|
		) port map(
 | 
						|
			clk => system_clk,
 | 
						|
			reset => reset,
 | 
						|
			wb_adr_in => main_memory_adr_in,
 | 
						|
			wb_dat_in => main_memory_dat_in,
 | 
						|
			wb_dat_out => main_memory_dat_out,
 | 
						|
			wb_cyc_in => main_memory_cyc_in,
 | 
						|
			wb_stb_in => main_memory_stb_in,
 | 
						|
			wb_sel_in => main_memory_sel_in,
 | 
						|
			wb_we_in => main_memory_we_in,
 | 
						|
			wb_ack_out => main_memory_ack_out
 | 
						|
		);
 | 
						|
	main_memory_adr_in <= processor_adr_out(main_memory_adr_in'range);
 | 
						|
	main_memory_dat_in <= processor_dat_out;
 | 
						|
	main_memory_we_in  <= processor_we_out;
 | 
						|
	main_memory_sel_in <= processor_sel_out;
 | 
						|
	main_memory_cyc_in <= processor_cyc_out when intercon_peripheral = PERIPHERAL_MAIN_MEMORY else '0';
 | 
						|
	main_memory_stb_in <= processor_stb_out when intercon_peripheral = PERIPHERAL_MAIN_MEMORY else '0';
 | 
						|
	
 | 
						|
end architecture behaviour;
 |