Add Tercel PHY reset synchronization
[microwatt.git] / syscon.vhdl
index a9dd1cc9ea3f2e97acb87c5aad627d3c8732662a..31d8d0ae8d907d8cdb2968e68d1741dfe88cfb7b 100644 (file)
@@ -8,12 +8,18 @@ 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
+       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;
+       DRAM_INIT_SIZE   : integer;
+        HAS_SPI_FLASH    : boolean;
+        SPI_FLASH_OFFSET : integer;
+       HAS_LITEETH      : boolean;
+        UART0_IS_16550   : boolean;
+        HAS_UART1        : boolean
        );
     port (
        clk : in std_ulogic;
@@ -33,22 +39,32 @@ end entity syscon;
 
 architecture behaviour of syscon is
     -- Register address bits
-    constant SYS_REG_BITS       : positive := 3;
+    constant SYS_REG_BITS       : positive := 6;
 
     -- 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";
+    constant SYS_REG_SIG         : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000000";
+    constant SYS_REG_INFO        : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000001";
+    constant SYS_REG_BRAMINFO    : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000010";
+    constant SYS_REG_DRAMINFO    : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000011";
+    constant SYS_REG_CLKINFO     : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000100";
+    constant SYS_REG_CTRL        : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000101";
+    constant SYS_REG_DRAMINITINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000110";
+    constant SYS_REG_SPIFLASHINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000111";
+    constant SYS_REG_UART0_INFO   : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001000";
+    constant SYS_REG_UART1_INFO   : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001001";
 
     -- Muxed reg read signal
     signal reg_out     : std_ulogic_vector(63 downto 0);
 
     -- INFO register bits
-    constant SYS_REG_INFO_HAS_UART    : integer := 0;
-    constant SYS_REG_INFO_HAS_DRAM    : integer := 1;
+    constant SYS_REG_INFO_HAS_UART    : integer := 0;  -- Has a UART (always set)
+    constant SYS_REG_INFO_HAS_DRAM    : integer := 1;  -- Has DRAM
+    constant SYS_REG_INFO_HAS_BRAM    : integer := 2;  -- Has "main" BRAM
+    constant SYS_REG_INFO_HAS_SPIF    : integer := 3;  -- Has SPI flash
+    constant SYS_REG_INFO_HAS_LETH    : integer := 4;  -- Has LiteEth ethernet
+    constant SYS_REG_INFO_HAS_LSYS    : integer := 5;  -- Has 6-bit address syscon
+    constant SYS_REG_INFO_HAS_URT1    : integer := 6;  -- Has second UART
+    constant SYS_REG_INFO_HAS_ARTB    : integer := 7;  -- Has architected TB frequency
 
     -- BRAMINFO contains the BRAM size in the bottom 52 bits
     -- DRAMINFO contains the DRAM size if any in the bottom 52 bits
@@ -61,6 +77,18 @@ architecture behaviour of syscon is
     constant SYS_REG_CTRL_CORE_RESET : integer := 1;
     constant SYS_REG_CTRL_SOC_RESET  : integer := 2;
 
+    -- SPI Info register bits
+    --
+    -- Top 32-bit is flash offset which is the amount of flash
+    -- reserved for the FPGA bitfile if any
+    constant SYS_REG_SPI_INFO_IS_FLASH : integer := 0;
+
+    -- UART0/1 info registers bits
+    --
+    --  0 ..31  : UART clock freq (in HZ)
+    --      32  : UART is 16550 (otherwise pp)
+    --
+
     -- 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);
@@ -69,49 +97,99 @@ architecture behaviour of syscon is
     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_dramiinfo : std_ulogic_vector(63 downto 0);
     signal reg_clkinfo   : std_ulogic_vector(63 downto 0);
+    signal reg_spiinfo   : std_ulogic_vector(63 downto 0);
+    signal reg_uart0info : std_ulogic_vector(63 downto 0);
+    signal reg_uart1info : std_ulogic_vector(63 downto 0);
     signal info_has_dram : std_ulogic;
+    signal info_has_bram : std_ulogic;
     signal info_has_uart : std_ulogic;
+    signal info_has_spif : std_ulogic;
+    signal info_has_leth : std_ulogic;
+    signal info_has_urt1 : std_ulogic;
     signal info_clk      : std_ulogic_vector(39 downto 0);
+    signal info_fl_off   : std_ulogic_vector(31 downto 0);
+    signal uinfo_16550   : std_ulogic;
+    signal uinfo_freq    : std_ulogic_vector(31 downto 0);
+
+    -- Wishbone response latch
+    signal wb_rsp        : wb_io_slave_out;
 begin
 
     -- Generated output signals
-    dram_at_0 <= reg_ctrl(SYS_REG_CTRL_DRAM_AT_0);
+    dram_at_0 <= '1' when BRAM_SIZE = 0 else 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_has_uart <= '1' when HAS_UART       else '0';
+    info_has_dram <= '1' when HAS_DRAM       else '0';
+    info_has_bram <= '1' when BRAM_SIZE /= 0 else '0';
+    info_has_spif <= '1' when HAS_SPI_FLASH  else '0';
+    info_has_leth <= '1' when HAS_LITEETH    else '0';
+    info_has_urt1 <= '1' when HAS_UART1      else '0';
     info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40));
-    reg_info <= (0 => info_has_uart,
-                1 => info_has_dram,
+    reg_info <= (SYS_REG_INFO_HAS_UART  => info_has_uart,
+                SYS_REG_INFO_HAS_DRAM  => info_has_dram,
+                 SYS_REG_INFO_HAS_BRAM  => info_has_bram,
+                 SYS_REG_INFO_HAS_SPIF  => info_has_spif,
+                 SYS_REG_INFO_HAS_LETH  => info_has_leth,
+                 SYS_REG_INFO_HAS_LSYS  => '1',
+                 SYS_REG_INFO_HAS_URT1  => info_has_urt1,
                 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_dramiinfo <= x"000" & std_ulogic_vector(to_unsigned(DRAM_INIT_SIZE, 52)) when HAS_DRAM
+                     else (others => '0');
     reg_clkinfo <= (39 downto 0 => info_clk,
                    others => '0');
+    info_fl_off <= std_ulogic_vector(to_unsigned(SPI_FLASH_OFFSET, 32));
+    reg_spiinfo <= (31 downto 0 => info_fl_off,
+                    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
+    -- UART info registers read composition
+    uinfo_16550   <= '1' when UART0_IS_16550 else '0';
+    uinfo_freq    <= std_ulogic_vector(to_unsigned(CLK_FREQ, 32));
+    reg_uart0info <= (32           => uinfo_16550,
+                      31 downto 0  => uinfo_freq,
+                      others       => '0');
+    reg_uart1info <= (32           => '1',
+                      31 downto 0  => uinfo_freq,
+                      others       => '0');
+
+    -- Wishbone response
+    wb_rsp.ack <= wishbone_in.cyc and wishbone_in.stb;
     with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select reg_out <=
        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_dramiinfo   when SYS_REG_DRAMINITINFO,
        reg_clkinfo     when SYS_REG_CLKINFO,
        reg_ctrl_out    when SYS_REG_CTRL,
+       reg_spiinfo     when SYS_REG_SPIFLASHINFO,
+        reg_uart0info   when SYS_REG_UART0_INFO,
+        reg_uart1info   when SYS_REG_UART1_INFO,
        (others => '0') when others;
-    wishbone_out.dat <= reg_out(63 downto 32) when wishbone_in.adr(2) = '1' else
-                        reg_out(31 downto 0);
+    wb_rsp.dat   <= reg_out(63 downto 32) when wishbone_in.adr(2) = '1' else
+                  reg_out(31 downto 0);
+    wb_rsp.stall <= '0';
+
+    -- Wishbone response latch
+    regs_read: process(clk)
+    begin
+        if rising_edge(clk) then
+            -- Send response from latch
+            wishbone_out <= wb_rsp;
+        end if;
+    end process;
 
     -- Register writes
     regs_write: process(clk)
@@ -136,6 +214,11 @@ begin
                 if reg_ctrl(SYS_REG_CTRL_CORE_RESET) = '1' then
                     reg_ctrl(SYS_REG_CTRL_CORE_RESET) <= '0';
                 end if;
+
+                -- If BRAM doesn't exist, force DRAM at 0
+                if BRAM_SIZE = 0 then
+                    reg_ctrl(SYS_REG_CTRL_DRAM_AT_0) <= '1';
+                end if;
            end if;
        end if;
     end process;