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
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,
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 (
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 (
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");
}
- wishbone_bram_wrapper.vhdl
- soc.vhdl
- xics.vhdl
+ - syscon.vhdl
file_type : vhdlSource-2008
fpga:
-- 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)
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;
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;
)
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,
);
-- 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,
-- 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
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;
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;
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
--- /dev/null
+-- 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;