12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016 |
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.numeric_std.all;
- use ieee.math_real.all;
- use std.textio.all;
- use std.env.stop;
- library work;
- use work.common.all;
- use work.utils.all;
- use work.wishbone_types.all;
- -- Memory map. *** Keep include/microwatt_soc.h updated on changes ***
- --
- -- Main bus:
- -- 0x00000000: Block RAM (MEMORY_SIZE) or DRAM depending on syscon
- -- 0x40000000: DRAM (when present)
- -- 0x80000000: Block RAM (aliased & repeated)
- -- IO Bus:
- -- 0xc0000000: SYSCON
- -- 0xc0002000: UART0
- -- 0xc0003000: UART1 (if any)
- -- 0xc0004000: XICS ICP
- -- 0xc0005000: XICS ICS
- -- 0xc0006000: SPI Flash controller
- -- 0xc8nnnnnn: External IO bus
- -- 0xf0000000: Flash "ROM" mapping
- -- 0xff000000: DRAM init code (if any) or flash ROM (**)
- -- External IO bus:
- -- 0xc8000000: LiteDRAM control (CSRs)
- -- 0xc8020000: LiteEth CSRs (*)
- -- 0xc8030000: LiteEth MMIO (*)
- -- (*) LiteEth must be a single aligned 32KB block as the CSRs and MMIOs
- -- are actually decoded as a single wishbone which LiteEth will
- -- internally split based on bit 16.
- -- (**) DRAM init code is currently special and goes to the external
- -- IO bus, this will be fixed when it's moved out of litedram and
- -- into the main SoC once we have a common "firmware".
- -- Interrupt numbers:
- --
- -- 0 : UART0
- -- 1 : Ethernet
- entity soc is
- generic (
- MEMORY_SIZE : natural;
- RAM_INIT_FILE : string;
- CLK_FREQ : positive;
- SIM : boolean;
- HAS_FPU : boolean := true;
- HAS_BTC : boolean := true;
- DISABLE_FLATTEN_CORE : boolean := false;
- EXTERNAL_CORE : boolean := false;
- HAS_DRAM : boolean := false;
- SIM_MAIN_BRAM : boolean := false;
- SIM_BRAM_CHAINBOOT : positive := 0;
- DRAM_SIZE : integer := 0;
- RESET_ADDRESS : std_ulogic_vector(63 downto 0) := (others => '0');
- -- hack to jump-start alternative (e.g. verilator-loaded linux kernel)
- -- RESET_ADDRESS : std_ulogic_vector(63 downto 0) := (22 downto 21 => '1', others => '0');
- DRAM_INIT_SIZE : integer := 0;
- HAS_SPI_FLASH : boolean := false;
- SPI_FLASH_DLINES : positive := 1;
- SPI_FLASH_OFFSET : integer := 0;
- SPI_FLASH_DEF_CKDV : natural := 2;
- SPI_FLASH_DEF_QUAD : boolean := false;
- LOG_LENGTH : natural := 512;
- HAS_LITEETH : boolean := false;
- UART0_IS_16550 : boolean := true;
- HAS_UART1 : boolean := false
- );
- port(
- rst : in std_ulogic;
- system_clk : in std_ulogic;
- -- "Large" (64-bit) DRAM wishbone
- wb_dram_in : out wishbone_master_out;
- wb_dram_out : in wishbone_slave_out := wishbone_slave_out_init;
- -- "Small" (32-bit) external IO wishbone
- wb_ext_io_in : out wb_io_master_out;
- wb_ext_io_out : in wb_io_slave_out := wb_io_slave_out_init;
- wb_ext_is_dram_csr : out std_ulogic;
- wb_ext_is_dram_init : out std_ulogic;
- wb_ext_is_eth : out std_ulogic;
- -- External interrupts
- ext_irq_eth : in std_ulogic := '0';
- -- BRAM verilator access
- bram_we : out std_ulogic;
- bram_re : out std_ulogic;
- bram_addr : out std_logic_vector(log2ceil(MEMORY_SIZE) - 3- 1 downto 0);
- bram_di : out std_logic_vector(63 downto 0);
- bram_do : in std_logic_vector(63 downto 0);
- bram_sel : out std_logic_vector(7 downto 0);
- -- UART0 signals:
- uart0_txd : out std_ulogic;
- uart0_rxd : in std_ulogic := '0';
- -- UART1 signals:
- uart1_txd : out std_ulogic;
- uart1_rxd : in std_ulogic := '0';
- -- SPI Flash signals
- spi_flash_sck : out std_ulogic;
- spi_flash_cs_n : out std_ulogic;
- spi_flash_sdat_o : out std_ulogic_vector(SPI_FLASH_DLINES-1 downto 0);
- spi_flash_sdat_oe : out std_ulogic_vector(SPI_FLASH_DLINES-1 downto 0);
- spi_flash_sdat_i : in std_ulogic_vector(SPI_FLASH_DLINES-1 downto 0) := (others => '1');
- -- DRAM controller signals
- alt_reset : in std_ulogic := '0';
- -- for verilator debugging
- nia_req: out std_ulogic;
- nia: out std_ulogic_vector(63 downto 0);
- msr_o: out std_ulogic_vector(63 downto 0);
- insn: out std_ulogic_vector(31 downto 0);
- ldst_req: out std_ulogic;
- ldst_addr: out std_ulogic_vector(63 downto 0)
- );
- end entity soc;
- architecture behaviour of soc is
- -- Wishbone master signals:
- signal wishbone_dcore_in : wishbone_slave_out;
- signal wishbone_dcore_out : wishbone_master_out;
- signal wishbone_icore_in : wishbone_slave_out;
- signal wishbone_icore_out : wishbone_master_out;
- signal wishbone_debug_in : wishbone_slave_out;
- signal wishbone_debug_out : wishbone_master_out;
- -- Arbiter array (ghdl doesnt' support assigning the array
- -- elements in the entity instantiation)
- constant NUM_WB_MASTERS : positive := 3;
- signal wb_masters_out : wishbone_master_out_vector(0 to NUM_WB_MASTERS-1);
- signal wb_masters_in : wishbone_slave_out_vector(0 to NUM_WB_MASTERS-1);
- -- Wishbone master (output of arbiter):
- signal wb_master_in : wishbone_slave_out;
- signal wb_master_out : wishbone_master_out;
- -- Main "IO" bus, from main slave decoder to the latch
- signal wb_io_in : wishbone_master_out;
- signal wb_io_out : wishbone_slave_out;
- -- Secondary (smaller) IO bus after the IO bus latch
- signal wb_sio_out : wb_io_master_out;
- signal wb_sio_in : wb_io_slave_out;
- -- Syscon signals
- signal dram_at_0 : std_ulogic;
- signal do_core_reset : std_ulogic;
- signal wb_syscon_in : wb_io_master_out;
- signal wb_syscon_out : wb_io_slave_out;
- -- UART0 signals:
- signal wb_uart0_in : wb_io_master_out;
- signal wb_uart0_out : wb_io_slave_out;
- signal uart0_dat8 : std_ulogic_vector(7 downto 0);
- signal uart0_irq : std_ulogic;
- -- UART1 signals:
- signal wb_uart1_in : wb_io_master_out;
- signal wb_uart1_out : wb_io_slave_out;
- signal uart1_dat8 : std_ulogic_vector(7 downto 0);
- signal uart1_irq : std_ulogic;
- -- SPI Flash controller signals:
- signal wb_spiflash_in : wb_io_master_out;
- signal wb_spiflash_out : wb_io_slave_out;
- signal wb_spiflash_is_reg : std_ulogic;
- signal wb_spiflash_is_map : std_ulogic;
- -- XICS signals:
- signal wb_xics_icp_in : wb_io_master_out;
- signal wb_xics_icp_out : wb_io_slave_out;
- signal wb_xics_ics_in : wb_io_master_out;
- signal wb_xics_ics_out : wb_io_slave_out;
- signal int_level_in : std_ulogic_vector(15 downto 0);
- signal ics_to_icp : ics_to_icp_t;
- signal core_ext_irq : std_ulogic;
- -- Main memory signals:
- signal wb_bram_in : wishbone_master_out;
- signal wb_bram_out : wishbone_slave_out;
- -- DMI debug bus signals
- signal dmi_addr : std_ulogic_vector(7 downto 0);
- signal dmi_din : std_ulogic_vector(63 downto 0);
- signal dmi_dout : std_ulogic_vector(63 downto 0);
- signal dmi_req : std_ulogic;
- signal dmi_wr : std_ulogic;
- signal dmi_ack : std_ulogic;
- -- Per slave DMI signals
- signal dmi_wb_dout : std_ulogic_vector(63 downto 0);
- signal dmi_wb_req : std_ulogic;
- signal dmi_wb_ack : std_ulogic;
- signal dmi_core_dout : std_ulogic_vector(63 downto 0);
- signal dmi_core_req : std_ulogic;
- signal dmi_core_ack : std_ulogic;
- -- Delayed/latched resets and alt_reset
- signal rst_core : std_ulogic := '1';
- signal rst_uart : std_ulogic := '1';
- signal rst_xics : std_ulogic := '1';
- signal rst_spi : std_ulogic := '1';
- signal rst_bram : std_ulogic := '1';
- signal rst_dtm : std_ulogic := '1';
- signal rst_wbar : std_ulogic := '1';
- signal rst_wbdb : std_ulogic := '1';
- signal alt_reset_d : std_ulogic;
- -- IO branch split:
- type slave_io_type is (SLAVE_IO_SYSCON,
- SLAVE_IO_UART,
- SLAVE_IO_ICP,
- SLAVE_IO_ICS,
- SLAVE_IO_UART1,
- SLAVE_IO_SPI_FLASH_REG,
- SLAVE_IO_SPI_FLASH_MAP,
- SLAVE_IO_EXTERNAL,
- SLAVE_IO_NONE);
- signal slave_io_dbg : slave_io_type;
- -- This is the component exported by the 16550 compatible
- -- UART from FuseSoC.
- --
- component uart_top port (
- wb_clk_i : in std_ulogic;
- wb_rst_i : in std_ulogic;
- wb_adr_i : in std_ulogic_vector(2 downto 0);
- wb_dat_i : in std_ulogic_vector(7 downto 0);
- wb_dat_o : out std_ulogic_vector(7 downto 0);
- wb_we_i : in std_ulogic;
- wb_stb_i : in std_ulogic;
- wb_cyc_i : in std_ulogic;
- wb_ack_o : out std_ulogic;
- int_o : out std_ulogic;
- stx_pad_o : out std_ulogic;
- srx_pad_i : in std_ulogic;
- rts_pad_o : out std_ulogic;
- cts_pad_i : in std_ulogic;
- dtr_pad_o : out std_ulogic;
- dsr_pad_i : in std_ulogic;
- ri_pad_i : in std_ulogic;
- dcd_pad_i : in std_ulogic
- );
- end component;
- -- use this for external processor core (e.g. mycore.v, not core.vhdl)
- component external_core_top port (
- clk : in std_ulogic;
- rst : in std_ulogic;
- alt_reset : in std_ulogic;
- wishbone_insn_in : in wishbone_slave_out;
- wishbone_insn_out : out wishbone_master_out;
- wishbone_data_in : in wishbone_slave_out;
- wishbone_data_out : out wishbone_master_out;
- dmi_addr : in std_ulogic_vector(3 downto 0) := (others => 'U');
- dmi_din : in std_ulogic_vector(63 downto 0) := (others => 'U');
- dmi_dout : out std_ulogic_vector(63 downto 0) := (others => 'U');
- dmi_req : in std_ulogic := 'U';
- dmi_wr : in std_ulogic := 'U';
- dmi_ack : out std_ulogic := 'U';
- ext_irq : in std_ulogic;
- terminated_out : out std_logic := 'U';
- -- for verilator debugging
- nia_req: out std_ulogic := 'U';
- msr_o: out std_ulogic_vector(63 downto 0) := (others => 'U');
- nia: out std_ulogic_vector(63 downto 0) := (others => 'U');
- insn: out std_ulogic_vector(31 downto 0) := (others => 'U');
- ldst_req: out std_ulogic := 'U';
- ldst_addr: out std_ulogic_vector(63 downto 0) := (others => 'U')
- );
- end component;
- begin
- resets: process(system_clk)
- begin
- if rising_edge(system_clk) then
- rst_core <= rst or do_core_reset;
- rst_uart <= rst;
- rst_spi <= rst;
- rst_xics <= rst;
- rst_bram <= rst;
- rst_dtm <= rst;
- rst_wbar <= rst;
- rst_wbdb <= rst;
- alt_reset_d <= alt_reset;
- end if;
- end process;
- -- Processor core
- processor_internal: if not EXTERNAL_CORE generate
- processor: entity work.core
- generic map(
- SIM => SIM,
- HAS_FPU => HAS_FPU,
- HAS_BTC => HAS_BTC,
- DISABLE_FLATTEN => DISABLE_FLATTEN_CORE,
- RESET_ADDRESS => RESET_ADDRESS,
- ALT_RESET_ADDRESS => (23 downto 0 => '0', others => '1'),
- LOG_LENGTH => LOG_LENGTH
- )
- port map(
- clk => system_clk,
- rst => rst_core,
- alt_reset => alt_reset_d,
- wishbone_insn_in => wishbone_icore_in,
- wishbone_insn_out => wishbone_icore_out,
- wishbone_data_in => wishbone_dcore_in,
- wishbone_data_out => wishbone_dcore_out,
- dmi_addr => dmi_addr(3 downto 0),
- dmi_dout => dmi_core_dout,
- dmi_din => dmi_dout,
- dmi_wr => dmi_wr,
- dmi_ack => dmi_core_ack,
- dmi_req => dmi_core_req,
- ext_irq => core_ext_irq,
- nia_req => nia_req,
- nia => nia,
- msr_o => msr_o,
- insn => insn,
- ldst_req => ldst_req,
- ldst_addr => ldst_addr
- );
- end generate;
- processor_external: if EXTERNAL_CORE generate
- processor: external_core_top
- port map(
- clk => system_clk,
- rst => rst_core,
- alt_reset => alt_reset_d,
- wishbone_insn_in => wishbone_icore_in,
- wishbone_insn_out => wishbone_icore_out,
- wishbone_data_in => wishbone_dcore_in,
- wishbone_data_out => wishbone_dcore_out,
- dmi_addr => dmi_addr(3 downto 0),
- dmi_dout => dmi_core_dout,
- dmi_din => dmi_dout,
- dmi_wr => dmi_wr,
- dmi_ack => dmi_core_ack,
- dmi_req => dmi_core_req,
- ext_irq => core_ext_irq,
- nia_req => nia_req,
- nia => nia,
- msr_o => msr_o,
- insn => insn
- );
- end generate;
- -- Wishbone bus master arbiter & mux
- wb_masters_out <= (0 => wishbone_dcore_out,
- 1 => wishbone_icore_out,
- 2 => wishbone_debug_out);
- wishbone_dcore_in <= wb_masters_in(0);
- wishbone_icore_in <= wb_masters_in(1);
- wishbone_debug_in <= wb_masters_in(2);
- wishbone_arbiter_0: entity work.wishbone_arbiter
- generic map(
- NUM_MASTERS => NUM_WB_MASTERS
- )
- port map(
- clk => system_clk,
- rst => rst_wbar,
- wb_masters_in => wb_masters_out,
- wb_masters_out => wb_masters_in,
- wb_slave_out => wb_master_out,
- wb_slave_in => wb_master_in
- );
- -- Top level Wishbone slaves address decoder & mux
- --
- -- From CPU to BRAM, DRAM, IO, selected on top 3 bits and dram_at_0
- -- 0000 - BRAM
- -- 0001 - DRAM
- -- 01xx - DRAM
- -- 10xx - BRAM
- -- 11xx - IO
- --
- slave_top_intercon: process(wb_master_out, wb_bram_out, wb_dram_out, wb_io_out, dram_at_0)
- type slave_top_type is (SLAVE_TOP_BRAM,
- SLAVE_TOP_DRAM,
- SLAVE_TOP_IO);
- variable slave_top : slave_top_type;
- variable top_decode : std_ulogic_vector(3 downto 0);
- begin
- -- Top-level address decoder
- top_decode := wb_master_out.adr(31 downto 29) & dram_at_0;
- slave_top := SLAVE_TOP_BRAM;
- if std_match(top_decode, "0000") then
- slave_top := SLAVE_TOP_BRAM;
- elsif std_match(top_decode, "0001") then
- slave_top := SLAVE_TOP_DRAM;
- elsif std_match(top_decode, "01--") then
- slave_top := SLAVE_TOP_DRAM;
- elsif std_match(top_decode, "10--") then
- slave_top := SLAVE_TOP_BRAM;
- elsif std_match(top_decode, "11--") then
- slave_top := SLAVE_TOP_IO;
- end if;
- -- Top level wishbone muxing.
- wb_bram_in <= wb_master_out;
- wb_bram_in.cyc <= '0';
- wb_dram_in <= wb_master_out;
- wb_dram_in.cyc <= '0';
- wb_io_in <= wb_master_out;
- wb_io_in.cyc <= '0';
- case slave_top is
- when SLAVE_TOP_BRAM =>
- wb_bram_in.cyc <= wb_master_out.cyc;
- wb_master_in <= wb_bram_out;
- when SLAVE_TOP_DRAM =>
- if HAS_DRAM then
- wb_dram_in.cyc <= wb_master_out.cyc;
- wb_master_in <= wb_dram_out;
- else
- wb_master_in.ack <= wb_master_out.cyc and wb_master_out.stb;
- wb_master_in.dat <= (others => '1');
- wb_master_in.stall <= '0';
- end if;
- when SLAVE_TOP_IO =>
- wb_io_in.cyc <= wb_master_out.cyc;
- wb_master_in <= wb_io_out;
- end case;
- end process slave_top_intercon;
- -- IO wishbone slave 64->32 bits converter
- --
- -- For timing reasons, this adds a one cycle latch on the way both
- -- in and out. This relaxes timing and routing pressure on the "main"
- -- memory bus by moving all simple IOs to a slower 32-bit bus.
- --
- -- This implementation is rather dumb at the moment, no stash buffer,
- -- so we stall whenever that latch is busy. This can be improved.
- --
- slave_io_latch: process(system_clk)
- -- State
- type state_t is (IDLE, WAIT_ACK_BOT, WAIT_ACK_TOP);
- variable state : state_t;
- -- Misc
- variable has_top : boolean;
- variable has_bot : boolean;
- begin
- if rising_edge(system_clk) then
- if (rst) then
- state := IDLE;
- wb_io_out.ack <= '0';
- wb_io_out.stall <= '0';
- wb_sio_out.cyc <= '0';
- wb_sio_out.stb <= '0';
- has_top := false;
- has_bot := false;
- else
- case state is
- when IDLE =>
- -- Clear ACK in case it was set
- wb_io_out.ack <= '0';
- -- Do we have a cycle ?
- if wb_io_in.cyc = '1' and wb_io_in.stb = '1' then
- -- Stall master until we are done, we are't (yet) pipelining
- -- this, it's all slow IOs.
- wb_io_out.stall <= '1';
- -- Start cycle downstream
- wb_sio_out.cyc <= '1';
- wb_sio_out.stb <= '1';
- -- Copy write enable to IO out, copy address as well
- wb_sio_out.we <= wb_io_in.we;
- wb_sio_out.adr <= wb_io_in.adr(wb_sio_out.adr'left downto 3) & "000";
- -- Do we have a top word and/or a bottom word ?
- has_top := wb_io_in.sel(7 downto 4) /= "0000";
- has_bot := wb_io_in.sel(3 downto 0) /= "0000";
- -- If we have a bottom word, handle it first, otherwise
- -- send the top word down. XXX Split the actual mux out
- -- and only generate a control signal.
- if has_bot then
- if wb_io_in.we = '1' then
- wb_sio_out.dat <= wb_io_in.dat(31 downto 0);
- end if;
- wb_sio_out.sel <= wb_io_in.sel(3 downto 0);
- -- Wait for ack
- state := WAIT_ACK_BOT;
- else
- if wb_io_in.we = '1' then
- wb_sio_out.dat <= wb_io_in.dat(63 downto 32);
- end if;
- wb_sio_out.sel <= wb_io_in.sel(7 downto 4);
- -- Bump address
- wb_sio_out.adr(2) <= '1';
- -- Wait for ack
- state := WAIT_ACK_TOP;
- end if;
- end if;
- when WAIT_ACK_BOT =>
- -- If we aren't stalled by the device, clear stb
- if wb_sio_in.stall = '0' then
- wb_sio_out.stb <= '0';
- end if;
- -- Handle ack
- if wb_sio_in.ack = '1' then
- -- If it's a read, latch the data
- if wb_sio_out.we = '0' then
- wb_io_out.dat(31 downto 0) <= wb_sio_in.dat;
- end if;
- -- Do we have a "top" part as well ?
- if has_top then
- -- Latch data & sel
- if wb_io_in.we = '1' then
- wb_sio_out.dat <= wb_io_in.dat(63 downto 32);
- end if;
- wb_sio_out.sel <= wb_io_in.sel(7 downto 4);
- -- Bump address and set STB
- wb_sio_out.adr(2) <= '1';
- wb_sio_out.stb <= '1';
- -- Wait for new ack
- state := WAIT_ACK_TOP;
- else
- -- We are done, ack up, clear cyc downstram
- wb_sio_out.cyc <= '0';
- -- And ack & unstall upstream
- wb_io_out.ack <= '1';
- wb_io_out.stall <= '0';
- -- Wait for next one
- state := IDLE;
- end if;
- end if;
- when WAIT_ACK_TOP =>
- -- If we aren't stalled by the device, clear stb
- if wb_sio_in.stall = '0' then
- wb_sio_out.stb <= '0';
- end if;
- -- Handle ack
- if wb_sio_in.ack = '1' then
- -- If it's a read, latch the data
- if wb_sio_out.we = '0' then
- wb_io_out.dat(63 downto 32) <= wb_sio_in.dat;
- end if;
- -- We are done, ack up, clear cyc downstram
- wb_sio_out.cyc <= '0';
- -- And ack & unstall upstream
- wb_io_out.ack <= '1';
- wb_io_out.stall <= '0';
- -- Wait for next one
- state := IDLE;
- end if;
- end case;
- end if;
- end if;
- end process;
-
- -- IO wishbone slave intercon.
- --
- slave_io_intercon: process(wb_sio_out, wb_syscon_out, wb_uart0_out, wb_uart1_out,
- wb_ext_io_out, wb_xics_icp_out, wb_xics_ics_out,
- wb_spiflash_out)
- variable slave_io : slave_io_type;
- variable match : std_ulogic_vector(31 downto 12);
- variable ext_valid : boolean;
- begin
- -- Simple address decoder.
- slave_io := SLAVE_IO_NONE;
- match := "11" & wb_sio_out.adr(29 downto 12);
- if std_match(match, x"FF---") and HAS_DRAM then
- slave_io := SLAVE_IO_EXTERNAL;
- elsif std_match(match, x"F----") then
- slave_io := SLAVE_IO_SPI_FLASH_MAP;
- elsif std_match(match, x"C0000") then
- slave_io := SLAVE_IO_SYSCON;
- elsif std_match(match, x"C0002") then
- slave_io := SLAVE_IO_UART;
- elsif std_match(match, x"C0003") then
- slave_io := SLAVE_IO_UART1;
- elsif std_match(match, x"C8---") then
- slave_io := SLAVE_IO_EXTERNAL;
- elsif std_match(match, x"C0004") then
- slave_io := SLAVE_IO_ICP;
- elsif std_match(match, x"C0005") then
- slave_io := SLAVE_IO_ICS;
- elsif std_match(match, x"C0006") then
- slave_io := SLAVE_IO_SPI_FLASH_REG;
- end if;
- slave_io_dbg <= slave_io;
- wb_uart0_in <= wb_sio_out;
- wb_uart0_in.cyc <= '0';
- wb_uart1_in <= wb_sio_out;
- wb_uart1_in.cyc <= '0';
- wb_spiflash_in <= wb_sio_out;
- wb_spiflash_in.cyc <= '0';
- wb_spiflash_is_reg <= '0';
- wb_spiflash_is_map <= '0';
- -- Only give xics 8 bits of wb addr (for now...)
- wb_xics_icp_in <= wb_sio_out;
- wb_xics_icp_in.adr <= (others => '0');
- wb_xics_icp_in.adr(7 downto 0) <= wb_sio_out.adr(7 downto 0);
- wb_xics_icp_in.cyc <= '0';
- wb_xics_ics_in <= wb_sio_out;
- wb_xics_ics_in.adr <= (others => '0');
- wb_xics_ics_in.adr(11 downto 0) <= wb_sio_out.adr(11 downto 0);
- wb_xics_ics_in.cyc <= '0';
- wb_ext_io_in <= wb_sio_out;
- wb_ext_io_in.cyc <= '0';
- wb_syscon_in <= wb_sio_out;
- wb_syscon_in.cyc <= '0';
- wb_ext_is_dram_csr <= '0';
- wb_ext_is_dram_init <= '0';
- wb_ext_is_eth <= '0';
- -- Default response, ack & return all 1's
- wb_sio_in.dat <= (others => '1');
- wb_sio_in.ack <= wb_sio_out.stb and wb_sio_out.cyc;
- wb_sio_in.stall <= '0';
- case slave_io is
- when SLAVE_IO_EXTERNAL =>
- -- Ext IO "chip selects"
- --
- -- DRAM init is special at 0xFF* so we just test the top
- -- bit. Everything else is at 0xC8* so we test only bits
- -- 23 downto 16.
- --
- ext_valid := false;
- if wb_sio_out.adr(29) = '1' and HAS_DRAM then -- DRAM init is special
- wb_ext_is_dram_init <= '1';
- ext_valid := true;
- elsif wb_sio_out.adr(23 downto 16) = x"00" and HAS_DRAM then
- wb_ext_is_dram_csr <= '1';
- ext_valid := true;
- elsif wb_sio_out.adr(23 downto 16) = x"02" and HAS_LITEETH then
- wb_ext_is_eth <= '1';
- ext_valid := true;
- elsif wb_sio_out.adr(23 downto 16) = x"03" and HAS_LITEETH then
- wb_ext_is_eth <= '1';
- ext_valid := true;
- end if;
- if ext_valid then
- wb_ext_io_in.cyc <= wb_sio_out.cyc;
- wb_sio_in <= wb_ext_io_out;
- end if;
- when SLAVE_IO_SYSCON =>
- wb_syscon_in.cyc <= wb_sio_out.cyc;
- wb_sio_in <= wb_syscon_out;
- when SLAVE_IO_UART =>
- wb_uart0_in.cyc <= wb_sio_out.cyc;
- wb_sio_in <= wb_uart0_out;
- when SLAVE_IO_ICP =>
- wb_xics_icp_in.cyc <= wb_sio_out.cyc;
- wb_sio_in <= wb_xics_icp_out;
- when SLAVE_IO_ICS =>
- wb_xics_ics_in.cyc <= wb_sio_out.cyc;
- wb_sio_in <= wb_xics_ics_out;
- when SLAVE_IO_UART1 =>
- wb_uart1_in.cyc <= wb_sio_out.cyc;
- wb_sio_in <= wb_uart1_out;
- when SLAVE_IO_SPI_FLASH_MAP =>
- -- Clear top bits so they don't make their way to the
- -- fash chip.
- wb_spiflash_in.adr(29 downto 28) <= "00";
- wb_spiflash_in.cyc <= wb_sio_out.cyc;
- wb_sio_in <= wb_spiflash_out;
- wb_spiflash_is_map <= '1';
- when SLAVE_IO_SPI_FLASH_REG =>
- wb_spiflash_in.cyc <= wb_sio_out.cyc;
- wb_sio_in <= wb_spiflash_out;
- wb_spiflash_is_reg <= '1';
- when others =>
- end case;
- end process;
- -- Syscon slave
- syscon0: entity work.syscon
- generic map(
- HAS_UART => true,
- HAS_DRAM => HAS_DRAM,
- BRAM_SIZE => MEMORY_SIZE,
- DRAM_SIZE => DRAM_SIZE,
- DRAM_INIT_SIZE => DRAM_INIT_SIZE,
- SIM_BRAM_CHAINBOOT => SIM_BRAM_CHAINBOOT,
- CLK_FREQ => CLK_FREQ,
- HAS_SPI_FLASH => HAS_SPI_FLASH,
- SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
- HAS_LITEETH => HAS_LITEETH,
- UART0_IS_16550 => UART0_IS_16550,
- HAS_UART1 => HAS_UART1
- )
- 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 => do_core_reset,
- soc_reset => open -- XXX TODO
- );
- --
- -- UART0
- --
- -- Either potato (legacy) or 16550
- --
- uart0_pp: if not UART0_IS_16550 generate
- uart0: entity work.pp_soc_uart
- generic map(
- FIFO_DEPTH => 32
- )
- port map(
- clk => system_clk,
- reset => rst_uart,
- txd => uart0_txd,
- rxd => uart0_rxd,
- irq => uart0_irq,
- wb_adr_in => wb_uart0_in.adr(11 downto 0),
- wb_dat_in => wb_uart0_in.dat(7 downto 0),
- wb_dat_out => uart0_dat8,
- wb_cyc_in => wb_uart0_in.cyc,
- wb_stb_in => wb_uart0_in.stb,
- wb_we_in => wb_uart0_in.we,
- wb_ack_out => wb_uart0_out.ack
- );
- end generate;
- uart0_16550 : if UART0_IS_16550 generate
- signal irq_l : std_ulogic;
- begin
- uart0: uart_top
- port map (
- wb_clk_i => system_clk,
- wb_rst_i => rst_uart,
- wb_adr_i => wb_uart0_in.adr(4 downto 2),
- wb_dat_i => wb_uart0_in.dat(7 downto 0),
- wb_dat_o => uart0_dat8,
- wb_we_i => wb_uart0_in.we,
- wb_stb_i => wb_uart0_in.stb,
- wb_cyc_i => wb_uart0_in.cyc,
- wb_ack_o => wb_uart0_out.ack,
- int_o => irq_l,
- stx_pad_o => uart0_txd,
- srx_pad_i => uart0_rxd,
- rts_pad_o => open,
- cts_pad_i => '1',
- dtr_pad_o => open,
- dsr_pad_i => '1',
- ri_pad_i => '0',
- dcd_pad_i => '1'
- );
- -- Add a register on the irq out, helps timing
- uart0_irq_latch: process(system_clk)
- begin
- if rising_edge(system_clk) then
- uart0_irq <= irq_l;
- end if;
- end process;
- end generate;
- wb_uart0_out.dat <= x"000000" & uart0_dat8;
- wb_uart0_out.stall <= wb_uart0_in.cyc and not wb_uart0_out.ack;
- --
- -- UART1
- --
- -- Always 16550 if it exists
- --
- uart1: if HAS_UART1 generate
- signal irq_l : std_ulogic;
- begin
- uart1: uart_top
- port map (
- wb_clk_i => system_clk,
- wb_rst_i => rst_uart,
- wb_adr_i => wb_uart1_in.adr(4 downto 2),
- wb_dat_i => wb_uart1_in.dat(7 downto 0),
- wb_dat_o => uart1_dat8,
- wb_we_i => wb_uart1_in.we,
- wb_stb_i => wb_uart1_in.stb,
- wb_cyc_i => wb_uart1_in.cyc,
- wb_ack_o => wb_uart1_out.ack,
- int_o => irq_l,
- stx_pad_o => uart1_txd,
- srx_pad_i => uart1_rxd,
- rts_pad_o => open,
- cts_pad_i => '1',
- dtr_pad_o => open,
- dsr_pad_i => '1',
- ri_pad_i => '0',
- dcd_pad_i => '1'
- );
- -- Add a register on the irq out, helps timing
- uart0_irq_latch: process(system_clk)
- begin
- if rising_edge(system_clk) then
- uart1_irq <= irq_l;
- end if;
- end process;
- wb_uart1_out.dat <= x"000000" & uart1_dat8;
- wb_uart1_out.stall <= wb_uart1_in.cyc and not wb_uart1_out.ack;
- end generate;
- no_uart1 : if not HAS_UART1 generate
- wb_uart1_out.dat <= x"00000000";
- wb_uart1_out.ack <= wb_uart1_in.cyc and wb_uart1_in.stb;
- wb_uart1_out.stall <= '0';
- uart1_irq <= '0';
- end generate;
- spiflash_gen: if HAS_SPI_FLASH generate
- spiflash: entity work.spi_flash_ctrl
- generic map (
- DATA_LINES => SPI_FLASH_DLINES,
- DEF_CLK_DIV => SPI_FLASH_DEF_CKDV,
- DEF_QUAD_READ => SPI_FLASH_DEF_QUAD
- )
- port map(
- rst => rst_spi,
- clk => system_clk,
- wb_in => wb_spiflash_in,
- wb_out => wb_spiflash_out,
- wb_sel_reg => wb_spiflash_is_reg,
- wb_sel_map => wb_spiflash_is_map,
- sck => spi_flash_sck,
- cs_n => spi_flash_cs_n,
- sdat_o => spi_flash_sdat_o,
- sdat_oe => spi_flash_sdat_oe,
- sdat_i => spi_flash_sdat_i
- );
- end generate;
- no_spi0_gen: if not HAS_SPI_FLASH generate
- wb_spiflash_out.dat <= (others => '1');
- wb_spiflash_out.ack <= wb_spiflash_in.cyc and wb_spiflash_in.stb;
- wb_spiflash_out.stall <= wb_spiflash_in.cyc and not wb_spiflash_out.ack;
- end generate;
- xics_icp: entity work.xics_icp
- port map(
- clk => system_clk,
- rst => rst_xics,
- wb_in => wb_xics_icp_in,
- wb_out => wb_xics_icp_out,
- ics_in => ics_to_icp,
- core_irq_out => core_ext_irq
- );
- xics_ics: entity work.xics_ics
- generic map(
- SRC_NUM => 16,
- PRIO_BITS => 3
- )
- port map(
- clk => system_clk,
- rst => rst_xics,
- wb_in => wb_xics_ics_in,
- wb_out => wb_xics_ics_out,
- int_level_in => int_level_in,
- icp_out => ics_to_icp
- );
- -- Assign external interrupts
- interrupts: process(all)
- begin
- int_level_in <= (others => '0');
- int_level_in(0) <= uart0_irq;
- int_level_in(1) <= ext_irq_eth;
- int_level_in(2) <= uart1_irq;
- end process;
- -- BRAM Memory slave
- bram: if MEMORY_SIZE /= 0 generate
- bram0: entity work.wishbone_bram_wrapper
- generic map(
- MEMORY_SIZE => MEMORY_SIZE,
- RAM_INIT_FILE => RAM_INIT_FILE,
- SIM_MAIN_BRAM => SIM_MAIN_BRAM
- )
- port map(
- clk => system_clk,
- rst => rst_bram,
- wishbone_in => wb_bram_in,
- wishbone_out => wb_bram_out,
- bram_we => bram_we,
- bram_re => bram_re,
- bram_addr => bram_addr,
- bram_di => bram_di,
- bram_do => bram_do,
- bram_sel => bram_sel
- );
- end generate;
- no_bram: if MEMORY_SIZE = 0 generate
- wb_bram_out.ack <= wb_bram_in.cyc and wb_bram_in.stb;
- wb_bram_out.dat <= x"FFFFFFFFFFFFFFFF";
- wb_bram_out.stall <= wb_bram_in.cyc and not wb_bram_out.ack;
- end generate;
- -- DMI(debug bus) <-> JTAG bridge
- dtm: entity work.dmi_dtm
- generic map(
- ABITS => 8,
- DBITS => 64
- )
- port map(
- sys_clk => system_clk,
- sys_reset => rst_dtm,
- dmi_addr => dmi_addr,
- dmi_din => dmi_din,
- dmi_dout => dmi_dout,
- dmi_req => dmi_req,
- dmi_wr => dmi_wr,
- dmi_ack => dmi_ack
- );
- -- DMI interconnect
- dmi_intercon: process(dmi_addr, dmi_req,
- dmi_wb_ack, dmi_wb_dout,
- dmi_core_ack, dmi_core_dout)
- -- DMI address map (each address is a full 64-bit register)
- --
- -- Offset: Size: Slave:
- -- 0 4 Wishbone
- -- 10 16 Core
- type slave_type is (SLAVE_WB,
- SLAVE_CORE,
- SLAVE_NONE);
- variable slave : slave_type;
- begin
- -- Simple address decoder
- slave := SLAVE_NONE;
- if std_match(dmi_addr, "000000--") then
- slave := SLAVE_WB;
- elsif std_match(dmi_addr, "0001----") then
- slave := SLAVE_CORE;
- end if;
- -- DMI muxing
- dmi_wb_req <= '0';
- dmi_core_req <= '0';
- case slave is
- when SLAVE_WB =>
- dmi_wb_req <= dmi_req;
- dmi_ack <= dmi_wb_ack;
- dmi_din <= dmi_wb_dout;
- when SLAVE_CORE =>
- dmi_core_req <= dmi_req;
- dmi_ack <= dmi_core_ack;
- dmi_din <= dmi_core_dout;
- when others =>
- dmi_ack <= dmi_req;
- dmi_din <= (others => '1');
- end case;
- -- SIM magic exit
- if SIM and dmi_req = '1' and dmi_addr = "11111111" and dmi_wr = '1' then
- stop;
- end if;
- end process;
- -- Wishbone debug master (TODO: Add a DMI address decoder)
- wishbone_debug: entity work.wishbone_debug_master
- port map(clk => system_clk,
- rst => rst_wbdb,
- dmi_addr => dmi_addr(1 downto 0),
- dmi_dout => dmi_wb_dout,
- dmi_din => dmi_dout,
- dmi_wr => dmi_wr,
- dmi_ack => dmi_wb_ack,
- dmi_req => dmi_wb_req,
- wb_in => wishbone_debug_in,
- wb_out => wishbone_debug_out);
- end architecture behaviour;
|