syscon: Add syscon registers
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 24 Sep 2019 12:24:31 +0000 (22:24 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 8 May 2020 11:06:16 +0000 (21:06 +1000)
These provides some info about the SoC (though it's still somewhat
incomplete and needs more work, see comments).

There's also a control register for selecting DRAM vs. BRAM at 0
(and for soft-resetting the SoC but that isn't wired up yet).

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Makefile
core_tb.vhdl
fpga/top-arty.vhdl
fpga/top-nexys-video.vhdl
litedram/gen-src/sdram_init/main.c
microwatt.core
soc.vhdl
syscon.vhdl [new file with mode: 0644]

index 1978d013be2119a65159a72a01ce5d7f3ba6097d..b9ad461272295c0684aa14439b2942dd62f93cc1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -71,7 +71,8 @@ rotator_tb.o: common.o glibc_random.o ppc_fx_insns.o insn_helpers.o rotator.o
 sim_console.o:
 sim_uart.o: wishbone_types.o sim_console.o
 xics.o: wishbone_types.o common.o
-soc.o: common.o wishbone_types.o core.o wishbone_arbiter.o sim_uart.o wishbone_bram_wrapper.o dmi_dtm_xilinx.o wishbone_debug_master.o xics.o
+soc.o: common.o wishbone_types.o core.o wishbone_arbiter.o sim_uart.o wishbone_bram_wrapper.o dmi_dtm_xilinx.o wishbone_debug_master.o xics.o syscon.o
+syscon.o: wishbone_types.o
 wishbone_arbiter.o: wishbone_types.o
 wishbone_types.o:
 writeback.o: common.o crhelpers.o
index c473de329c874083d5f1c7915eba74503980cdf1..9c08919f8aaadae80e1e448a19636cfa8ddf92b9 100644 (file)
@@ -25,7 +25,8 @@ begin
            SIM => true,
            MEMORY_SIZE => (384*1024),
            RAM_INIT_FILE => "main_ram.bin",
-           RESET_LOW => false
+           RESET_LOW => false,
+           CLK_FREQ => 100000000
            )
        port map(
            rst => rst,
index a458c04f55976c674abe8995db5726c7f7d0315e..fbea534bf64af12d31c58ddb171adee56c03fb64 100644 (file)
@@ -92,7 +92,9 @@ begin
            RAM_INIT_FILE => RAM_INIT_FILE,
            RESET_LOW     => RESET_LOW,
            SIM           => false,
+           CLK_FREQ      => CLK_FREQUENCY,
            HAS_DRAM      => USE_LITEDRAM,
+           DRAM_SIZE     => 256 * 1024 * 1024,
            DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE
            )
        port map (
index ea23dd58404fe82c48a6b5d6f84e4a3acc5fc45f..c0e3659261d878a484338b7f48bc1edc4c93e804 100644 (file)
@@ -75,7 +75,9 @@ begin
            RAM_INIT_FILE => RAM_INIT_FILE,
            RESET_LOW     => RESET_LOW,
            SIM           => false,
+           CLK_FREQ      => CLK_FREQUENCY,
            HAS_DRAM      => USE_LITEDRAM,
+           DRAM_SIZE     => 512 * 1024 * 1024,
            DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE
            )
        port map (
index cc8b714cf282e729f013e59be6a03d83d1374675..eae5c28857118dea2aff52de8029a32a8f90a861 100644 (file)
@@ -156,7 +156,8 @@ void main(void)
        printf("      INFO: %016llx\n", (unsigned long long)readq(SYSCON_BASE + 0x08));
        printf("  BRAMINFO: %016llx\n", (unsigned long long)readq(SYSCON_BASE + 0x10));
        printf("  DRAMINFO: %016llx\n", (unsigned long long)readq(SYSCON_BASE + 0x18));
-       printf("      CTRL: %016llx\n", (unsigned long long)readq(SYSCON_BASE + 0x20));
+       printf("   CLKINFO: %016llx\n", (unsigned long long)readq(SYSCON_BASE + 0x20));
+       printf("      CTRL: %016llx\n", (unsigned long long)readq(SYSCON_BASE + 0x28));
        sdrinit();
        printf("Booting from BRAM...\n");
 }
index f7002aee00a347fcaa412331a307ca4651d6d439..a1ae14bc82f5ae0a6abf1667358ff97b4fa10479 100644 (file)
@@ -46,6 +46,7 @@ filesets:
       - wishbone_bram_wrapper.vhdl
       - soc.vhdl
       - xics.vhdl
+      - syscon.vhdl
     file_type : vhdlSource-2008
 
   fpga:
index 53fa2f1f6b85d20ab5215a82f72e773104450e29..db52db3408335ada16134eccb4642f44d6b6d163 100644 (file)
--- a/soc.vhdl
+++ b/soc.vhdl
@@ -12,8 +12,9 @@ use work.wishbone_types.all;
 
 -- Memory map:
 --
--- 0x00000000: Block RAM
+-- 0x00000000: Block RAM (MEMORY_SIZE) or DRAM depending on syscon
 -- 0x40000000: DRAM (when present)
+-- 0xc0000000: SYSCON
 -- 0xc0002000: UART0
 -- 0xc0004000: XICS ICP
 -- 0xf0000000: Block RAM (aliased & repeated)
@@ -24,9 +25,11 @@ entity soc is
        MEMORY_SIZE   : positive;
        RAM_INIT_FILE : string;
        RESET_LOW     : boolean;
+       CLK_FREQ      : positive;
        SIM           : boolean;
        DISABLE_FLATTEN_CORE : boolean := false;
-       HAS_DRAM      : boolean  := false
+       HAS_DRAM      : boolean  := false;
+       DRAM_SIZE     : integer := 0
        );
     port(
        rst          : in  std_ulogic;
@@ -67,6 +70,12 @@ architecture behaviour of soc is
     signal wb_master_in       : wishbone_slave_out;
     signal wb_master_out      : wishbone_master_out;
 
+    -- Syscon signals
+    signal dram_at_0     : std_ulogic;
+    signal core_reset    : std_ulogic;
+    signal wb_syscon_in  : wishbone_master_out;
+    signal wb_syscon_out : wishbone_slave_out;
+
     -- UART0 signals:
     signal wb_uart0_in   : wishbone_master_out;
     signal wb_uart0_out  : wishbone_slave_out;
@@ -110,7 +119,7 @@ begin
            )
        port map(
            clk => system_clk,
-           rst => rst,
+           rst => rst or core_reset,
            alt_reset => alt_reset,
            wishbone_insn_in => wishbone_icore_in,
            wishbone_insn_out => wishbone_icore_out,
@@ -145,9 +154,10 @@ begin
            );
 
     -- Wishbone slaves address decoder & mux
-    slave_intercon: process(wb_master_out, wb_bram_out, wb_uart0_out, wb_dram_out)
+    slave_intercon: process(wb_master_out, wb_bram_out, wb_uart0_out, wb_dram_out, wb_syscon_out)
        -- Selected slave
-       type slave_type is (SLAVE_UART,
+       type slave_type is (SLAVE_SYSCON,
+                           SLAVE_UART,
                            SLAVE_BRAM,
                            SLAVE_DRAM,
                            SLAVE_DRAM_INIT,
@@ -161,13 +171,16 @@ begin
        -- Simple address decoder. Ignore top bits to save silicon for now
        slave := SLAVE_NONE;
        if    std_match(wb_master_out.adr, x"0-------") then
-           slave := SLAVE_BRAM;
+           slave := SLAVE_DRAM when HAS_DRAM and dram_at_0 = '1' else
+                    SLAVE_BRAM;
        elsif std_match(wb_master_out.adr, x"FFFF----") then
            slave := SLAVE_DRAM_INIT;
        elsif std_match(wb_master_out.adr, x"F-------") then
            slave := SLAVE_BRAM;
        elsif std_match(wb_master_out.adr, x"4-------") and HAS_DRAM then
            slave := SLAVE_DRAM;
+       elsif std_match(wb_master_out.adr, x"C0000---") then
+           slave := SLAVE_SYSCON;
        elsif std_match(wb_master_out.adr, x"C0002---") then
            slave := SLAVE_UART;
        elsif std_match(wb_master_out.adr, x"C01-----") then
@@ -192,6 +205,8 @@ begin
        wb_dram_in.cyc <= '0';
        wb_dram_csr <= '0';
        wb_dram_init <= '0';
+       wb_syscon_in <= wb_master_out;
+       wb_syscon_in.cyc <= '0';
        case slave is
        when SLAVE_BRAM =>
            wb_bram_in.cyc <= wb_master_out.cyc;
@@ -207,6 +222,9 @@ begin
            wb_dram_in.cyc <= wb_master_out.cyc;
            wb_master_in <= wb_dram_out;
            wb_dram_csr <= '1';
+       when SLAVE_SYSCON =>
+           wb_syscon_in.cyc <= wb_master_out.cyc;
+           wb_master_in <= wb_syscon_out;
        when SLAVE_UART =>
            wb_uart0_in.cyc <= wb_master_out.cyc;
            wb_master_in <= wb_uart0_out;
@@ -220,6 +238,25 @@ begin
        end case;
     end process slave_intercon;
 
+    -- Syscon slave
+    syscon0: entity work.syscon
+       generic map(
+           HAS_UART => true,
+           HAS_DRAM => HAS_DRAM,
+           BRAM_SIZE => MEMORY_SIZE,
+           DRAM_SIZE => DRAM_SIZE,
+           CLK_FREQ => CLK_FREQ
+       )
+       port map(
+           clk => system_clk,
+           rst => rst,
+           wishbone_in => wb_syscon_in,
+           wishbone_out => wb_syscon_out,
+           dram_at_0 => dram_at_0,
+           core_reset => core_reset,
+           soc_reset => open -- XXX TODO
+           );
+
     -- Simulated memory and UART
 
     -- UART0 wishbone slave
diff --git a/syscon.vhdl b/syscon.vhdl
new file mode 100644 (file)
index 0000000..a5b569b
--- /dev/null
@@ -0,0 +1,136 @@
+-- syscon module, a bunch of misc global system control MMIO registers
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.wishbone_types.all;
+
+entity syscon is
+    generic (
+       SIG_VALUE     : std_ulogic_vector(63 downto 0) := x"f00daa5500010001";
+       CLK_FREQ      : integer;
+       HAS_UART      : boolean;
+       HAS_DRAM      : boolean;
+       BRAM_SIZE     : integer;
+       DRAM_SIZE     : integer
+       );
+    port (
+       clk : in std_ulogic;
+       rst : in std_ulogic;
+
+       -- Wishbone ports:
+       wishbone_in : in wishbone_master_out;
+       wishbone_out : out wishbone_slave_out;
+
+       -- System control ports
+       dram_at_0  : out std_ulogic;
+       core_reset : out std_ulogic;
+       soc_reset  : out std_ulogic
+       );
+end entity syscon;
+
+
+architecture behaviour of syscon is
+    -- Register address bits
+    constant SYS_REG_BITS       : positive := 3;
+
+    -- Register addresses (matches wishbone addr downto 3, ie, 8 bytes per reg)
+    constant SYS_REG_SIG       : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000";
+    constant SYS_REG_INFO      : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001";
+    constant SYS_REG_BRAMINFO  : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "010";
+    constant SYS_REG_DRAMINFO  : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "011";
+    constant SYS_REG_CLKINFO   : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "100";
+    constant SYS_REG_CTRL      : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "101";
+
+    -- INFO register bits
+    constant SYS_REG_INFO_HAS_UART    : integer := 0;
+    constant SYS_REG_INFO_HAS_DRAM    : integer := 1;
+
+    -- BRAMINFO contains the BRAM size in the bottom 52 bits
+    -- DRAMINFO contains the DRAM size if any in the bottom 52 bits
+    -- (both have reserved top bits for future use)
+    -- CLKINFO contains the CLK frequency is HZ in the bottom 40 bits
+
+    -- CTRL register bits
+    constant SYS_REG_CTRL_BITS       : positive := 3;
+    constant SYS_REG_CTRL_DRAM_AT_0  : integer := 0;
+    constant SYS_REG_CTRL_CORE_RESET : integer := 1;
+    constant SYS_REG_CTRL_SOC_RESET  : integer := 2;
+
+    -- Ctrl register
+    signal reg_ctrl    : std_ulogic_vector(SYS_REG_CTRL_BITS-1 downto 0);
+    signal reg_ctrl_out        : std_ulogic_vector(63 downto 0);
+
+    -- Others
+    signal reg_info      : std_ulogic_vector(63 downto 0);
+    signal reg_braminfo  : std_ulogic_vector(63 downto 0);
+    signal reg_draminfo  : std_ulogic_vector(63 downto 0);
+    signal reg_clkinfo   : std_ulogic_vector(63 downto 0);
+    signal info_has_dram : std_ulogic;
+    signal info_has_uart : std_ulogic;
+    signal info_clk      : std_ulogic_vector(39 downto 0);
+begin
+
+    -- Generated output signals
+    dram_at_0 <= reg_ctrl(SYS_REG_CTRL_DRAM_AT_0);
+    soc_reset <= reg_ctrl(SYS_REG_CTRL_SOC_RESET);
+    core_reset <= reg_ctrl(SYS_REG_CTRL_CORE_RESET);
+
+    -- All register accesses are single cycle
+    wishbone_out.ack <= wishbone_in.cyc and wishbone_in.stb;
+    wishbone_out.stall <= '0';
+
+    -- Info register is hard wired
+    info_has_uart <= '1' when HAS_UART else '0';
+    info_has_dram <= '1' when HAS_DRAM else '0';
+    info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40));
+    reg_info <= (0 => info_has_uart,
+                1 => info_has_dram,
+                others => '0');
+    reg_braminfo <= x"000" & std_ulogic_vector(to_unsigned(BRAM_SIZE, 52));
+    reg_draminfo <= x"000" & std_ulogic_vector(to_unsigned(DRAM_SIZE, 52)) when HAS_DRAM
+                   else (others => '0');
+    reg_clkinfo <= (39 downto 0 => info_clk,
+                   others => '0');
+
+    -- Control register read composition
+    reg_ctrl_out <= (63 downto SYS_REG_CTRL_BITS => '0',
+                   SYS_REG_CTRL_BITS-1 downto 0 => reg_ctrl);
+
+    -- Register read mux
+    with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select wishbone_out.dat <=
+       SIG_VALUE       when SYS_REG_SIG,
+       reg_info        when SYS_REG_INFO,
+       reg_braminfo    when SYS_REG_BRAMINFO,
+       reg_draminfo    when SYS_REG_DRAMINFO,
+       reg_clkinfo     when SYS_REG_CLKINFO,
+       reg_ctrl_out    when SYS_REG_CTRL,
+       (others => '0') when others;
+
+    -- Register writes
+    regs_write: process(clk)
+    begin
+       if rising_edge(clk) then
+           if (rst) then
+               reg_ctrl <= (others => '0');
+           else
+               if wishbone_in.cyc and wishbone_in.stb and wishbone_in.we then
+                   if wishbone_in.adr(SYS_REG_BITS+2 downto 3) = SYS_REG_CTRL then
+                       reg_ctrl(SYS_REG_CTRL_BITS-1 downto 0) <=
+                           wishbone_in.dat(SYS_REG_CTRL_BITS-1 downto 0);
+                   end if;
+               end if;
+
+                -- Reset auto-clear
+                if reg_ctrl(SYS_REG_CTRL_SOC_RESET) = '1' then
+                    reg_ctrl(SYS_REG_CTRL_SOC_RESET) <= '0';
+                end if;
+                if reg_ctrl(SYS_REG_CTRL_CORE_RESET) = '1' then
+                    reg_ctrl(SYS_REG_CTRL_CORE_RESET) <= '0';
+                end if;
+           end if;
+       end if;
+    end process;
+
+end architecture behaviour;