[WIP] Add initial version of Aquila LPC slave core
[microwatt.git] / fpga / top-rcs-arctic-tern-bmc-card.vhdl
index 3b02aa3888c4fde6b057597fdf39f44e529b57bc..e05809b7d5981c0d3695d8618037aa9a20575c72 100644 (file)
@@ -23,6 +23,7 @@ entity toplevel is
         LOG_LENGTH         : natural := 0;
         USE_LITEETH        : boolean  := true;
         USE_TERCEL         : boolean  := true;
+        USE_LPC_SLAVE      : boolean  := true;
         UART_IS_16550      : boolean  := true;
         HAS_UART1          : boolean  := false;
         ICACHE_NUM_LINES   : natural := 64
@@ -42,6 +43,13 @@ entity toplevel is
         spi_flash_wp_n   : inout std_ulogic;
         spi_flash_hold_n : inout std_ulogic;
 
+        -- LPC slave
+        lpc_slave_data     : inout std_ulogic_vector(3 downto 0);
+        lpc_slave_serirq   : inout std_ulogic;
+        lpc_slave_frame_n  : in std_ulogic;
+        lpc_slave_reset_n  : in std_ulogic;
+        lpc_slave_clock    : in std_ulogic;
+
         -- Ethernet
         eth_clocks_tx    : out std_ulogic;
         eth_clocks_rx    : in std_ulogic;
@@ -89,6 +97,7 @@ architecture behaviour of toplevel is
     signal wb_ext_is_dram_init : std_ulogic;
     signal wb_ext_is_eth       : std_ulogic;
     signal wb_ext_is_tercel    : std_ulogic;
+    signal wb_ext_is_lpc_slave : std_ulogic;
 
     -- DRAM main data wishbone connection
     signal wb_dram_in          : wishbone_master_out;
@@ -104,6 +113,9 @@ architecture behaviour of toplevel is
     -- Tercel connection
     signal wb_tercel_out       : wb_io_slave_out := wb_io_slave_out_init;
 
+    -- Aquila connection
+    signal wb_lpc_slave_out    : wb_io_slave_out := wb_io_slave_out_init;
+
     -- Control/status
     signal core_alt_reset : std_ulogic;
 
@@ -114,10 +126,24 @@ architecture behaviour of toplevel is
     signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
     signal spi_sdat_i  : std_ulogic_vector(3 downto 0);
 
+    -- LPC slave bus
+    signal lpc_sdat_o   : std_ulogic_vector(3 downto 0);
+    signal lpc_slave_oe : std_ulogic;
+    signal lpc_sdat_i   : std_ulogic_vector(3 downto 0);
+    signal lpc_sirq_o   : std_ulogic;
+    signal lpc_sirq_oe  : std_ulogic;
+    signal lpc_sirq_i   : std_ulogic;
+    signal lpc_sframe_n : std_ulogic;
+    signal lpc_sreset_n : std_ulogic;
+    signal lpc_sclock   : std_ulogic;
+
     -- SPI main data wishbone connection
     signal wb_spiflash_in      : wb_io_master_out;
     signal wb_spiflash_out     : wb_io_slave_out;
 
+    signal wb_master_lpc_slave_in  : wishbone_slave_out;
+    signal wb_master_lpc_slave_out : wishbone_master_out;
+
     -- Fixup various memory sizes based on generics
     function get_bram_size return natural is
     begin
@@ -146,9 +172,21 @@ architecture behaviour of toplevel is
             USRMCLKTS : IN STD_ULOGIC
         );
     END COMPONENT;
+
     attribute syn_noprune: boolean ;
     attribute syn_noprune of USRMCLK: component is true;
 
+    component aquila_lpc_sdr_tristate
+        port(
+            i   : out std_ulogic;
+            oe  : in std_ulogic;
+            o   : in std_ulogic;
+            clk : in std_ulogic;
+            p   : inout std_ulogic
+        );
+    end component;
+    attribute syn_noprune of aquila_lpc_sdr_tristate: component is true;
+
 begin
 
     -- Main SoC
@@ -171,6 +209,7 @@ begin
             LOG_LENGTH         => LOG_LENGTH,
             HAS_LITEETH        => USE_LITEETH,
             HAS_TERCEL         => USE_TERCEL,
+            HAS_LPC_SLAVE      => USE_LPC_SLAVE,
             UART0_IS_16550     => UART_IS_16550,
             HAS_UART1          => HAS_UART1,
             ICACHE_NUM_LINES   => ICACHE_NUM_LINES
@@ -198,10 +237,14 @@ begin
             wb_ext_is_dram_init  => wb_ext_is_dram_init,
             wb_ext_is_eth        => wb_ext_is_eth,
             wb_ext_is_tercel     => wb_ext_is_tercel,
+            wb_ext_is_lpc_slave  => wb_ext_is_lpc_slave,
 
             wb_spiflash_in       => wb_spiflash_in,
             wb_spiflash_out      => wb_spiflash_out,
 
+            wb_lpc_slave_in      => wb_master_lpc_slave_in,
+            wb_lpc_slave_out     => wb_master_lpc_slave_out,
+
             alt_reset            => core_alt_reset
             );
 
@@ -495,9 +538,148 @@ begin
 
     end generate;
 
+    -- LPC slave
+    --
+    lpc_sframe_n   <= lpc_slave_frame_n;
+    lpc_sreset_n   <= lpc_slave_reset_n;
+    lpc_sclock     <= lpc_slave_clock;
+
+    lpc_sdat_buf_0: aquila_lpc_sdr_tristate port map (
+        o   => lpc_sdat_o(0),
+        oe  => lpc_slave_oe,
+        i   => lpc_sdat_i(0),
+        clk => lpc_sclock,
+        p   => lpc_slave_data(0)
+        );
+
+    lpc_sdat_buf_1: aquila_lpc_sdr_tristate port map (
+        o   => lpc_sdat_o(1),
+        oe  => lpc_slave_oe,
+        i   => lpc_sdat_i(1),
+        clk => lpc_sclock,
+        p   => lpc_slave_data(1)
+        );
+
+    lpc_sdat_buf_2: aquila_lpc_sdr_tristate port map (
+        o   => lpc_sdat_o(2),
+        oe  => lpc_slave_oe,
+        i   => lpc_sdat_i(2),
+        clk => lpc_sclock,
+        p   => lpc_slave_data(2)
+        );
+
+    lpc_sdat_buf_3: aquila_lpc_sdr_tristate port map (
+        o   => lpc_sdat_o(3),
+        oe  => lpc_slave_oe,
+        i   => lpc_sdat_i(3),
+        clk => lpc_sclock,
+        p   => lpc_slave_data(3)
+        );
+
+    lpc_sirq_buf: aquila_lpc_sdr_tristate port map (
+        o   => lpc_sirq_o,
+        oe  => lpc_sirq_oe,
+        i   => lpc_sirq_i,
+        clk => lpc_sclock,
+        p   => lpc_slave_serirq
+        );
+
+    has_lpc_slave : if USE_LPC_SLAVE generate
+
+        component aquila_lpc_slave_wishbone port (
+            peripheral_clock      : in std_ulogic;
+            peripheral_reset      : in std_ulogic;
+
+            lpc_data_out          : out std_ulogic_vector(3 downto 0);
+            lpc_data_in           : in std_ulogic_vector(3 downto 0);
+            lpc_data_direction    : out std_ulogic;
+            lpc_irq_out           : out std_ulogic;
+            lpc_irq_in            : in std_ulogic;
+            lpc_irq_direction     : out std_ulogic;
+
+            lpc_frame_n           : in std_ulogic;
+            lpc_reset_n           : in std_ulogic;
+            lpc_clock             : in std_ulogic;
+
+            slave_wishbone_adr    : in std_ulogic_vector(29 downto 0);
+            slave_wishbone_dat_w  : in std_ulogic_vector(31 downto 0);
+            slave_wishbone_dat_r  : out std_ulogic_vector(31 downto 0);
+            slave_wishbone_sel    : in std_ulogic_vector(3 downto 0);
+            slave_wishbone_cyc    : in std_ulogic;
+            slave_wishbone_stb    : in std_ulogic;
+            slave_wishbone_ack    : out std_ulogic;
+            slave_wishbone_we     : in std_ulogic;
+            slave_wishbone_err    : out std_ulogic;
+
+            master_wishbone_adr   : out std_ulogic_vector(wishbone_addr_bits-1 downto 0);
+            master_wishbone_dat_w : out std_ulogic_vector(wishbone_data_bits-1 downto 0);
+            master_wishbone_dat_r : in std_ulogic_vector(wishbone_data_bits-1 downto 0);
+            master_wishbone_sel   : out std_ulogic_vector(wishbone_sel_bits-1 downto 0);
+            master_wishbone_cyc   : out std_ulogic;
+            master_wishbone_stb   : out std_ulogic;
+            master_wishbone_ack   : in std_ulogic;
+            master_wishbone_we    : out std_ulogic;
+            master_wishbone_err   : in std_ulogic;
+
+            debug_port            : out std_ulogic_vector(15 downto 0);
+            lpc_clock_mirror      : out std_ulogic
+            );
+        end component;
+
+        signal wb_lpc_slave_cyc   : std_ulogic;
+
+    begin
+        lpc_slave :  aquila_lpc_slave_wishbone
+            port map(
+                peripheral_clock    => system_clk,
+                peripheral_reset    => soc_rst,
+
+                lpc_data_out           => lpc_sdat_o,
+                lpc_data_in            => lpc_sdat_i,
+                lpc_data_direction     => lpc_slave_oe,
+                lpc_irq_out            => lpc_sirq_o,
+                lpc_irq_in             => lpc_sirq_i,
+                lpc_irq_direction      => lpc_sirq_oe,
+                lpc_frame_n            => lpc_sframe_n,
+                lpc_reset_n            => lpc_sreset_n,
+                lpc_clock              => lpc_sclock,
+
+                master_wishbone_adr    => wb_master_lpc_slave_out.adr,
+                master_wishbone_dat_w  => wb_master_lpc_slave_out.dat,
+                master_wishbone_dat_r  => wb_master_lpc_slave_in.dat,
+                master_wishbone_sel    => wb_master_lpc_slave_out.sel,
+                master_wishbone_cyc    => wb_master_lpc_slave_out.cyc,
+                master_wishbone_stb    => wb_master_lpc_slave_out.stb,
+                master_wishbone_ack    => wb_master_lpc_slave_in.ack,
+                master_wishbone_we     => wb_master_lpc_slave_out.we,
+                master_wishbone_err    => '0',
+
+                slave_wishbone_adr    => wb_ext_io_in.adr,
+                slave_wishbone_dat_w  => wb_ext_io_in.dat,
+                slave_wishbone_dat_r  => wb_lpc_slave_out.dat,
+                slave_wishbone_sel    => wb_ext_io_in.sel,
+                slave_wishbone_cyc    => wb_lpc_slave_cyc,
+                slave_wishbone_stb    => wb_ext_io_in.stb,
+                slave_wishbone_ack    => wb_lpc_slave_out.ack,
+                slave_wishbone_we     => wb_ext_io_in.we,
+                slave_wishbone_err    => open,
+
+                debug_port            => open,
+                lpc_clock_mirror      => open
+                );
+
+        -- Gate cyc with "chip select" from soc
+        wb_lpc_slave_cyc <= wb_ext_io_in.cyc and wb_ext_is_lpc_slave;
+
+        -- Aquila isn't pipelined
+        wb_lpc_slave_out.stall <= not wb_lpc_slave_out.ack;
+
+    end generate;
+
     -- Mux WB response on the IO bus
     wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else
                      wb_tercel_out when wb_ext_is_tercel = '1' else
+                     wb_lpc_slave_out when wb_ext_is_lpc_slave = '1' else
                      wb_dram_ctrl_out;
 
 end architecture behaviour;