-- VCU118 Debug Top-Level - Add heartbeat LED and basic diagnostics LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; LIBRARY unisim; USE unisim.vcomponents.ALL; LIBRARY work; USE work.wishbone_types.ALL; ENTITY toplevel IS GENERIC ( MEMORY_SIZE : INTEGER := 16384; -- This can go up a lot more DRAM_SIZE : INTEGER := 268435456; RAM_INIT_FILE : STRING := "firmware.hex"; RESET_LOW : BOOLEAN := false; -- VCU118 reset button is active-high CLK_INPUT : POSITIVE := 125000000; -- Match physical clock CLK_FREQUENCY : POSITIVE := 125000000; -- Same as input (no PLL) HAS_FPU : BOOLEAN := true; HAS_BTC : BOOLEAN := true; ICACHE_NUM_LINES : NATURAL := 64; LOG_LENGTH : NATURAL := 512; DISABLE_FLATTEN_CORE : BOOLEAN := false; UART_IS_16550 : BOOLEAN := true; NO_BRAM : BOOLEAN := false; USE_LITEDRAM : BOOLEAN := false; HAS_SPI_FLASH: BOOLEAN := false ); PORT ( -- VCU118 differential clock input ext_clk_p : IN STD_ULOGIC; ext_clk_n : IN STD_ULOGIC; -- VCU118 reset button ext_rst : IN STD_ULOGIC; -- UART0 signals uart0_txd : OUT STD_ULOGIC; uart0_rxd : IN STD_ULOGIC; -- Debug LEDs (use some GPIO LEDs from VCU118) debug_led0 : OUT STD_ULOGIC; -- Heartbeat - clock working debug_led1 : OUT STD_ULOGIC; -- Reset state debug_led2 : OUT STD_ULOGIC; -- SoC running debug_led3 : OUT STD_ULOGIC; -- UART activity debug_led4 : OUT STD_ULOGIC; -- Init done debug_led5 : OUT STD_ULOGIC -- Init error ); END ENTITY toplevel; ARCHITECTURE behaviour OF toplevel IS -- Reset signals SIGNAL soc_rst : STD_ULOGIC; SIGNAL pll_rst : STD_ULOGIC; -- Internal clock signals SIGNAL system_clk : STD_ULOGIC; SIGNAL system_clk_locked : STD_ULOGIC; -- Single-ended clock from differential input SIGNAL ext_clk_single : STD_ULOGIC; -- Debug signals SIGNAL heartbeat_counter : unsigned(27 DOWNTO 0) := (OTHERS => '0'); SIGNAL uart_activity : STD_ULOGIC := '0'; SIGNAL uart_activity_counter : unsigned(23 DOWNTO 0) := (OTHERS => '0'); SIGNAL soc_run_out : STD_ULOGIC; SIGNAL soc_run_outs : STD_ULOGIC_VECTOR(0 DOWNTO 0); -- Add run_outs signal for NCPUS=1 SIGNAL init_done : STD_ULOGIC; SIGNAL init_error : STD_ULOGIC; -- Dummy DRAM wishbone interface (not used when USE_LITEDRAM = false) SIGNAL wb_dram_in : wishbone_master_out; SIGNAL wb_dram_out : wishbone_slave_out; SIGNAL wb_ext_io_in : wb_io_master_out; SIGNAL wb_ext_io_out : wb_io_slave_out; SIGNAL wb_ext_is_dram_csr : STD_ULOGIC; SIGNAL wb_ext_is_dram_init : STD_ULOGIC; function get_bram_size return natural is begin if USE_LITEDRAM and NO_BRAM then return 0; else return MEMORY_SIZE; end if; end function; function get_payload_size return natural is begin if USE_LITEDRAM and NO_BRAM then return MEMORY_SIZE; else return 0; end if; end function; constant BRAM_SIZE : natural := get_bram_size; constant PAYLOAD_SIZE : natural := get_payload_size; BEGIN -- Convert differential clock to single-ended (MUST come before BUFG) clk_ibufgds : IBUFGDS PORT MAP( I => ext_clk_p, IB => ext_clk_n, O => ext_clk_single ); -- Clock buffering (no PLL for 125MHz passthrough) clk_bufg : BUFG PORT MAP( I => ext_clk_single, O => system_clk ); -- Since we're not using a PLL, clock is always "locked" system_clk_locked <= '1'; -- Use the soc_reset entity for proper reset sequencing reset_controller : ENTITY work.soc_reset GENERIC MAP( RESET_LOW => RESET_LOW, PLL_RESET_BITS => 18 -- Adjust as needed ) PORT MAP( ext_clk => ext_clk_single, pll_clk => system_clk, pll_locked_in => system_clk_locked, ext_rst_in => ext_rst, pll_rst_out => pll_rst, rst_out => soc_rst ); -- Heartbeat counter for LED - ~0.93Hz at 125MHz (2^27 / 125MHz) heartbeat_proc : PROCESS (system_clk) BEGIN IF rising_edge(system_clk) THEN IF soc_rst = '1' THEN heartbeat_counter <= (OTHERS => '0'); ELSE heartbeat_counter <= heartbeat_counter + 1; END IF; END IF; END PROCESS; -- UART activity detector with timeout uart_activity_proc : PROCESS (system_clk) BEGIN IF rising_edge(system_clk) THEN IF soc_rst = '1' THEN uart_activity <= '0'; uart_activity_counter <= (OTHERS => '0'); ELSE -- Detect any UART transmit activity (start bit = '0') IF uart0_txd = '0' THEN uart_activity <= '1'; uart_activity_counter <= (OTHERS => '1'); ELSIF uart_activity_counter /= 0 THEN uart_activity_counter <= uart_activity_counter - 1; ELSE uart_activity <= '0'; END IF; END IF; END IF; END PROCESS; -- Debug LED assignments debug_led0 <= heartbeat_counter(27); -- Heartbeat - proves clock works debug_led1 <= NOT soc_rst; -- ON when system running (not in reset) debug_led2 <= soc_run_outs(0); -- SoC run status debug_led3 <= uart_activity; -- UART activity indicator debug_led4 <= init_done; -- Always '1' for no-DRAM config debug_led5 <= init_error; -- Always '0' for no-DRAM config -- Conditional DDR4 Generation no_litedram_gen : IF NOT USE_LITEDRAM GENERATE init_done <= '1'; init_error <= '0'; wb_dram_out.dat <= (OTHERS => '0'); wb_dram_out.ack <= '0'; wb_dram_out.stall <= '0'; wb_ext_io_out.dat <= (OTHERS => '0'); wb_ext_io_out.ack <= '0'; wb_ext_io_out.stall <= '0'; wb_ext_is_dram_csr <= '0'; wb_ext_is_dram_init <= '0'; END GENERATE no_litedram_gen; -- Main SoC soc0 : ENTITY work.soc GENERIC MAP( MEMORY_SIZE => BRAM_SIZE, RAM_INIT_FILE => RAM_INIT_FILE, HAS_SPI_FLASH => false, SIM => false, NCPUS => 1, CLK_FREQ => CLK_FREQUENCY, HAS_FPU => HAS_FPU, HAS_BTC => HAS_BTC, HAS_DRAM => USE_LITEDRAM, DRAM_SIZE => DRAM_SIZE, DRAM_INIT_SIZE => 0, -- No DRAM init when not using LiteDRAM ICACHE_NUM_LINES => ICACHE_NUM_LINES, LOG_LENGTH => LOG_LENGTH, DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE, UART0_IS_16550 => UART_IS_16550, HAS_UART1 => false ) PORT MAP( system_clk => system_clk, rst => soc_rst, uart0_txd => uart0_txd, uart0_rxd => uart0_rxd, -- DRAM wishbone (not used but needs to be connected) wb_dram_in => wb_dram_in, wb_dram_out => wb_dram_out, wb_ext_io_in => wb_ext_io_in, wb_ext_io_out => wb_ext_io_out, wb_ext_is_dram_csr => wb_ext_is_dram_csr, wb_ext_is_dram_init => wb_ext_is_dram_init, -- Run status output run_outs => soc_run_outs ); END ARCHITECTURE behaviour;