You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
microwatt/fpga/top-xilinx-vcu-118.vhdl

227 lines
7.6 KiB
VHDL

-- 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;