Split FPGA toplevel from soc
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 10 Sep 2019 11:45:33 +0000 (12:45 +0100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 10 Sep 2019 15:50:49 +0000 (16:50 +0100)
This will be useful when we start needing different toplevels for
different boards.

We keep the reset and clock generators in the toplevel as they will
eventually be taken over by litedram when we integrate it, and they
are more likely to change on different system types.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
fpga/soc.vhdl [new file with mode: 0644]
fpga/toplevel.vhd [deleted file]
fpga/toplevel.vhdl [new file with mode: 0644]
microwatt.core

diff --git a/fpga/soc.vhdl b/fpga/soc.vhdl
new file mode 100644 (file)
index 0000000..2f92b48
--- /dev/null
@@ -0,0 +1,189 @@
+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 soc is
+       generic (
+           MEMORY_SIZE   : positive;
+           RAM_INIT_FILE : string;
+           RESET_LOW     : boolean
+       );
+       port(
+           rst          : in  std_ulogic;
+           system_clk   : in  std_logic;
+
+           -- UART0 signals:
+           uart0_txd    : out std_logic;
+           uart0_rxd    : in  std_logic
+       );
+end entity soc;
+
+architecture behaviour of soc is
+
+       -- 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;
+
+begin
+
+    address_decoder: process(system_clk)
+       begin
+               if rising_edge(system_clk) then
+                       if rst = '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;
+
+       processor: entity work.core
+               port map(
+                       clk => system_clk,
+                       rst => rst,
+
+                       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 => rst,
+                       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 => rst,
+                       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;
diff --git a/fpga/toplevel.vhd b/fpga/toplevel.vhd
deleted file mode 100644 (file)
index 24e2fe2..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
--- 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 := 524288;
-               RAM_INIT_FILE : string   := "firmware.hex";
-               RESET_LOW : boolean := true
-       );
-       port(
-               ext_clk   : in  std_logic;
-               ext_rst   : 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 rst : std_ulogic;
-       signal pll_rst_n : std_ulogic;
-
-       -- Internal clock signals:
-       signal system_clk : std_ulogic;
-       signal system_clk_locked : std_ulogic;
-
-       -- 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 rst = '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.soc_reset
-               generic map(
-                       RESET_LOW => RESET_LOW
-               )
-               port map(
-                       ext_clk => ext_clk,
-                       pll_clk => system_clk,
-                       pll_locked_in => system_clk_locked,
-                       ext_rst_in => ext_rst,
-                       pll_rst_out => pll_rst_n,
-                       rst_out => rst
-               );
-
-       clkgen: entity work.clock_generator
-               port map(
-                       ext_clk => ext_clk,
-                       pll_rst_in => pll_rst_n,
-                       pll_clk_out => system_clk,
-                       pll_locked_out => system_clk_locked
-               );
-
-       processor: entity work.core
-               port map(
-                       clk => system_clk,
-                       rst => rst,
-
-                       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 => rst,
-                       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 => rst,
-                       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;
diff --git a/fpga/toplevel.vhdl b/fpga/toplevel.vhdl
new file mode 100644 (file)
index 0000000..6ad5c9b
--- /dev/null
@@ -0,0 +1,67 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity toplevel is
+    generic (
+       MEMORY_SIZE   : positive := 524288;
+       RAM_INIT_FILE : string   := "firmware.hex";
+       RESET_LOW     : boolean := true
+       );
+    port(
+       ext_clk   : in  std_ulogic;
+       ext_rst   : in  std_ulogic;
+
+       -- UART0 signals:
+       uart0_txd : out std_ulogic;
+       uart0_rxd : in  std_ulogic
+       );
+end entity toplevel;
+
+architecture behaviour of toplevel is
+
+    -- Reset signals:
+    signal soc_rst : std_ulogic;
+    signal pll_rst_n : std_ulogic;
+
+    -- Internal clock signals:
+    signal system_clk : std_ulogic;
+    signal system_clk_locked : std_ulogic;
+
+begin
+
+    reset_controller: entity work.soc_reset
+       generic map(
+           RESET_LOW => RESET_LOW
+           )
+       port map(
+           ext_clk => ext_clk,
+           pll_clk => system_clk,
+           pll_locked_in => system_clk_locked,
+           ext_rst_in => ext_rst,
+           pll_rst_out => pll_rst_n,
+           rst_out => soc_rst
+           );
+
+    clkgen: entity work.clock_generator
+       port map(
+           ext_clk => ext_clk,
+           pll_rst_in => pll_rst_n,
+           pll_clk_out => system_clk,
+           pll_locked_out => system_clk_locked
+           );
+
+    -- Main SoC
+    soc0: entity work.soc
+       generic map(
+           MEMORY_SIZE   => MEMORY_SIZE,
+           RAM_INIT_FILE => RAM_INIT_FILE,
+           RESET_LOW     => RESET_LOW
+           )
+       port map (
+           system_clk        => system_clk,
+           rst               => soc_rst,
+           uart0_txd         => uart0_txd,
+           uart0_rxd         => uart0_rxd
+           );
+
+end architecture behaviour;
index c77aceee3419f6db1158517795da1cdf92ac0919..02500ad6c54739dc424a3013ec1a6402511b35a0 100644 (file)
@@ -36,7 +36,8 @@ filesets:
       - fpga/soc_reset.vhdl
       - fpga/pp_soc_uart.vhd
       - fpga/pp_utilities.vhd
-      - fpga/toplevel.vhd
+      - fpga/soc.vhdl
+      - fpga/toplevel.vhdl
       - fpga/firmware.hex : {copyto : firmware.hex, file_type : user}
     file_type : vhdlSource-2008