-- Dummy DRAM
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;
+ signal wb_dram_ctrl_in : wb_io_master_out;
+ signal wb_dram_ctrl_out : wb_io_slave_out;
begin
soc0: entity work.soc
uart0_txd => open,
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
+ wb_dram_ctrl_in => wb_dram_ctrl_in,
+ wb_dram_ctrl_out => wb_dram_ctrl_out,
alt_reset => '0'
);
-- Dummy DRAM
wb_dram_out.ack <= wb_dram_in.cyc and wb_dram_in.stb;
wb_dram_out.dat <= x"FFFFFFFFFFFFFFFF";
- wb_dram_out.stall <= wb_dram_in.cyc and not wb_dram_out.ack;
+ wb_dram_out.stall <= '0';
+ wb_dram_ctrl_out.ack <= wb_dram_ctrl_in.cyc and wb_dram_ctrl_in.stb;
+ wb_dram_ctrl_out.dat <= x"FFFFFFFF";
+ wb_dram_ctrl_out.stall <= '0';
end;
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;
- -- DRAM wishbone connection
- signal wb_dram_in : wishbone_master_out;
- signal wb_dram_out : wishbone_slave_out;
- signal wb_dram_ctrl : std_ulogic;
- signal wb_dram_init : std_ulogic;
+ -- DRAM main data wishbone connection
+ signal wb_dram_in : wishbone_master_out;
+ signal wb_dram_out : wishbone_slave_out;
+
+ -- DRAM control wishbone connection
+ signal wb_dram_ctrl_in : wb_io_master_out;
+ signal wb_dram_ctrl_out : wb_io_slave_out;
+ signal wb_dram_is_csr : std_ulogic;
+ signal wb_dram_is_init : std_ulogic;
-- Control/status
signal core_alt_reset : std_ulogic;
uart0_rxd => uart_main_rx,
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
- wb_dram_ctrl => wb_dram_ctrl,
- wb_dram_init => wb_dram_init,
+ wb_dram_ctrl_in => wb_dram_ctrl_in,
+ wb_dram_ctrl_out => wb_dram_ctrl_out,
+ wb_dram_is_csr => wb_dram_is_csr,
+ wb_dram_is_init => wb_dram_is_init,
alt_reset => core_alt_reset
);
wb_in => wb_dram_in,
wb_out => wb_dram_out,
- wb_is_ctrl => wb_dram_ctrl,
- wb_is_init => wb_dram_init,
+ wb_ctrl_in => wb_dram_ctrl_in,
+ wb_ctrl_out => wb_dram_ctrl_out,
+ wb_ctrl_is_csr => wb_dram_is_csr,
+ wb_ctrl_is_init => wb_dram_is_init,
serial_tx => uart_pmod_tx,
serial_rx => uart_pmod_rx,
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;
- -- Dummy DRAM
- signal wb_dram_in : wishbone_master_out;
- signal wb_dram_out : wishbone_slave_out;
+ -- DRAM main data wishbone connection
+ signal wb_dram_in : wishbone_master_out;
+ signal wb_dram_out : wishbone_slave_out;
+
+ -- DRAM control wishbone connection
+ signal wb_dram_ctrl_in : wb_io_master_out;
+ signal wb_dram_ctrl_out : wb_io_slave_out;
+ signal wb_dram_is_csr : std_ulogic;
+ signal wb_dram_is_init : std_ulogic;
begin
rst => soc_rst,
uart0_txd => uart0_txd,
uart0_rxd => uart0_rxd,
+ wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
+ wb_dram_ctrl_in => wb_dram_ctrl_in,
+ wb_dram_ctrl_out => wb_dram_ctrl_out,
+ wb_dram_is_csr => wb_dram_is_csr,
+ wb_dram_is_init => wb_dram_is_init,
alt_reset => '0'
);
wb_dram_out.ack <= wb_dram_in.cyc and wb_dram_in.stb;
wb_dram_out.dat <= x"FFFFFFFFFFFFFFFF";
wb_dram_out.stall <= wb_dram_in.cyc and not wb_dram_out.ack;
+ wb_dram_ctrl_out.ack <= wb_dram_in.cyc and wb_dram_in.stb;
+ wb_dram_ctrl_out.dat <= x"FFFFFFFF";
+ wb_dram_ctrl_out.stall <= wb_dram_in.cyc and not wb_dram_out.ack;
end architecture behaviour;
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;
- -- DRAM wishbone connection
- signal wb_dram_in : wishbone_master_out;
- signal wb_dram_out : wishbone_slave_out;
- signal wb_dram_ctrl : std_ulogic;
- signal wb_dram_init : std_ulogic;
+ -- DRAM main data wishbone connection
+ signal wb_dram_in : wishbone_master_out;
+ signal wb_dram_out : wishbone_slave_out;
+
+ -- DRAM control wishbone connection
+ signal wb_dram_ctrl_in : wb_io_master_out;
+ signal wb_dram_ctrl_out : wb_io_slave_out;
+ signal wb_dram_is_csr : std_ulogic;
+ signal wb_dram_is_init : std_ulogic;
-- Control/status
signal core_alt_reset : std_ulogic;
uart0_rxd => uart_main_rx,
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
- wb_dram_ctrl => wb_dram_ctrl,
- wb_dram_init => wb_dram_init,
+ wb_dram_ctrl_in => wb_dram_ctrl_in,
+ wb_dram_ctrl_out => wb_dram_ctrl_out,
+ wb_dram_is_csr => wb_dram_is_csr,
+ wb_dram_is_init => wb_dram_is_init,
alt_reset => core_alt_reset
);
wb_in => wb_dram_in,
wb_out => wb_dram_out,
- wb_is_ctrl => wb_dram_ctrl,
- wb_is_init => wb_dram_init,
+ wb_ctrl_in => wb_dram_ctrl_in,
+ wb_ctrl_out => wb_dram_ctrl_out,
+ wb_ctrl_is_csr => wb_dram_is_csr,
+ wb_ctrl_is_init => wb_dram_is_init,
serial_tx => open,
serial_rx => '0',
#define MEMORY_BASE 0x00000000 /* "Main" memory alias, either BRAM or DRAM */
#define DRAM_BASE 0x40000000 /* DRAM if present */
+#define BRAM_BASE 0x80000000 /* Internal BRAM */
+
#define SYSCON_BASE 0xc0000000 /* System control regs */
#define UART_BASE 0xc0002000 /* UART */
#define XICS_BASE 0xc0004000 /* Interrupt controller */
#define DRAM_CTRL_BASE 0xc0100000 /* LiteDRAM control registers */
-#define BRAM_BASE 0xf0000000 /* Internal BRAM */
-#define DRAM_INIT_BASE 0xffff0000 /* Internal DRAM init firmware */
+#define DRAM_INIT_BASE 0xf0000000 /* Internal DRAM init firmware */
/*
* Register definitions for the syscon registers
* limitations under the License.
*/
-#define STACK_TOP 0xffff4000
+#define STACK_TOP 0xf0004000
#define FIXUP_ENDIAN \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
KEEP(*(.head))
}
. = DRAM_INIT_BASE | 0x1000;
+
.text : { *(.text*) *(.sfpr) *(.rodata*) }
.data : { *(.data*) }
.bss : { *(.bss*) }
port(
-- LiteDRAM generates the system clock and reset
-- from the input clkin
- clk_in : in std_ulogic;
- rst : in std_ulogic;
- system_clk : out std_ulogic;
- system_reset : out std_ulogic;
- core_alt_reset : out std_ulogic;
- pll_locked : out std_ulogic;
+ clk_in : in std_ulogic;
+ rst : in std_ulogic;
+ system_clk : out std_ulogic;
+ system_reset : out std_ulogic;
+ core_alt_reset : out std_ulogic;
+ pll_locked : out std_ulogic;
-- Wishbone ports:
- wb_in : in wishbone_master_out;
- wb_out : out wishbone_slave_out;
- wb_is_ctrl : in std_ulogic;
- wb_is_init : in std_ulogic;
+ wb_in : in wishbone_master_out;
+ wb_out : out wishbone_slave_out;
+ wb_ctrl_in : in wb_io_master_out;
+ wb_ctrl_out : out wb_io_slave_out;
+ wb_ctrl_is_csr : in std_ulogic;
+ wb_ctrl_is_init : in std_ulogic;
-- Init core serial debug
serial_tx : out std_ulogic;
signal wb_ctrl_ack : std_ulogic;
signal wb_ctrl_we : std_ulogic;
- signal wb_init_in : wishbone_master_out;
- signal wb_init_out : wishbone_slave_out;
+ signal wb_init_in : wb_io_master_out;
+ signal wb_init_out : wb_io_slave_out;
type state_t is (CMD, MWRITE, MREAD);
signal state : state_t;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";
- type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);
+ type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
- temp_ram(i) := temp_word;
+ temp_ram(i*2) := temp_word(31 downto 0);
+ temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
return temp_ram;
end function;
begin
- -- BRAM Memory slave
+ -- alternate core reset address set when DRAM is not initialized.
+ core_alt_reset <= not init_done;
+
+ -- BRAM Memory slave. TODO: Pipeline it with an output buffer
+ -- to improve timing
init_ram_0: process(system_clk)
variable adr : integer;
begin
if rising_edge(system_clk) then
wb_init_out.ack <= '0';
if (wb_init_in.cyc and wb_init_in.stb) = '1' then
- adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 3))));
+ adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_init_in.we = '0' then
wb_init_out.dat <= init_ram(adr);
else
- for i in 0 to 7 loop
+ for i in 0 to 3 loop
if wb_init_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_init_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
- wb_init_out.ack <= not wb_init_out.ack;
+ wb_init_out.ack <= '1';
end if;
end if;
end process;
- wb_init_in.adr <= wb_in.adr;
- wb_init_in.dat <= wb_in.dat;
- wb_init_in.sel <= wb_in.sel;
- wb_init_in.we <= wb_in.we;
- wb_init_in.stb <= wb_in.stb;
- wb_init_in.cyc <= wb_in.cyc and wb_is_init;
+ --
+ -- Control bus wishbone: This muxes the wishbone to the CSRs
+ -- and an internal small one to the init BRAM
+ --
+
+ -- Init DRAM wishbone IN signals
+ wb_init_in.adr <= wb_ctrl_in.adr;
+ wb_init_in.dat <= wb_ctrl_in.dat;
+ wb_init_in.sel <= wb_ctrl_in.sel;
+ wb_init_in.we <= wb_ctrl_in.we;
+ wb_init_in.stb <= wb_ctrl_in.stb;
+ wb_init_in.cyc <= wb_ctrl_in.cyc and wb_ctrl_is_init;
+
+ -- DRAM CSR IN signals
+ wb_ctrl_adr <= x"0000" & wb_ctrl_in.adr(15 downto 2);
+ wb_ctrl_dat_w <= wb_ctrl_in.dat;
+ wb_ctrl_sel <= wb_ctrl_in.sel;
+ wb_ctrl_we <= wb_ctrl_in.we;
+ wb_ctrl_cyc <= wb_ctrl_in.cyc and wb_ctrl_is_csr;
+ wb_ctrl_stb <= wb_ctrl_in.stb and wb_ctrl_is_csr;
- -- Address bit 3 selects the top or bottom half of the data
+ -- Ctrl bus wishbone OUT signals
+ wb_ctrl_out.ack <= wb_ctrl_ack when wb_ctrl_is_csr = '1'
+ else wb_init_out.ack;
+ wb_ctrl_out.dat <= wb_ctrl_dat_r when wb_ctrl_is_csr = '1'
+ else wb_init_out.dat;
+ wb_ctrl_out.stall <= wb_init_out.stall when wb_ctrl_is_init else
+ '0' when wb_ctrl_in.cyc = '0' else not wb_ctrl_ack;
+
+ --
+ -- Data bus wishbone to LiteDRAM native port
+ --
+ -- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
+ -- XXX TODO: Figure out how to pipeline this
+ --
ad3 <= wb_in.adr(3);
- -- DRAM data interface signals
- user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_ctrl and not wb_is_init)
- when state = CMD else '0';
- user_port0_cmd_we <= wb_in.we when state = CMD else '0';
+ -- Wishbone port IN signals
+ user_port0_cmd_valid <= wb_in.cyc and wb_in.stb when state = CMD else '0';
+ user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
- user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
- user_port0_wdata_data <= wb_in.dat & wb_in.dat;
- user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
- "00000000" & wb_in.sel;
-
- -- DRAM ctrl interface signals
- wb_ctrl_adr <= x"0000" & wb_in.adr(15 downto 2);
- wb_ctrl_dat_w <= wb_in.dat(31 downto 0);
- wb_ctrl_sel <= wb_in.sel(3 downto 0);
- wb_ctrl_cyc <= wb_in.cyc and wb_is_ctrl;
- wb_ctrl_stb <= wb_in.stb and wb_is_ctrl;
- wb_ctrl_we <= wb_in.we;
-
- -- Wishbone out signals
- wb_out.ack <= wb_ctrl_ack when wb_is_ctrl ='1' else
- wb_init_out.ack when wb_is_init = '1' else
- user_port0_wdata_ready when state = MWRITE else
+ user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
+ user_port0_wdata_data <= wb_in.dat & wb_in.dat;
+ user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
+ "00000000" & wb_in.sel;
+
+ -- Wishbone OUT signals
+ wb_out.ack <= user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';
- wb_out.dat <= (x"00000000" & wb_ctrl_dat_r) when wb_is_ctrl = '1' else
- wb_init_out.dat when wb_is_init = '1' else
- user_port0_rdata_data(127 downto 64) when ad3 = '1' else
+ wb_out.dat <= user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0);
+
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;
- -- Reset ignored, the reset controller use the pll lock signal,
- -- and alternate core reset address set when DRAM is not initialized.
- --
- core_alt_reset <= not init_done;
-
- -- State machine
+ -- DRAM user port State machine
sm: process(system_clk)
begin
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
- end case;
+ end case;
end if;
end if;
end process;
port(
-- LiteDRAM generates the system clock and reset
-- from the input clkin
- clk_in : in std_ulogic;
- rst : in std_ulogic;
- system_clk : out std_ulogic;
- system_reset : out std_ulogic;
- core_alt_reset : out std_ulogic;
- pll_locked : out std_ulogic;
+ clk_in : in std_ulogic;
+ rst : in std_ulogic;
+ system_clk : out std_ulogic;
+ system_reset : out std_ulogic;
+ core_alt_reset : out std_ulogic;
+ pll_locked : out std_ulogic;
-- Wishbone ports:
- wb_in : in wishbone_master_out;
- wb_out : out wishbone_slave_out;
- wb_is_ctrl : in std_ulogic;
- wb_is_init : in std_ulogic;
+ wb_in : in wishbone_master_out;
+ wb_out : out wishbone_slave_out;
+ wb_ctrl_in : in wb_io_master_out;
+ wb_ctrl_out : out wb_io_slave_out;
+ wb_ctrl_is_csr : in std_ulogic;
+ wb_ctrl_is_init : in std_ulogic;
-- Init core serial debug
serial_tx : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic
- );
end entity litedram_wrapper;
architecture behaviour of litedram_wrapper is
begin
+ -- Reset, lift it when init done, no alt core reset
+ system_reset <= dram_user_reset or not init_done;
+ core_alt_reset <= '0';
+
+ -- Control bus is unused
+ wb_ctrl_out.ack <= (wb_is_ctrl = '1' or wb_is_init = '1') and wb_ctrl_in.cyc;
+ else wb_init_out.ack;
+ wb_ctrl_out.dat <= (others => '0');
+ wb_ctrl_out.stall <= '0';
+
+ --
+ -- Data bus wishbone to LiteDRAM native port
+ --
-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
+ -- XXX TODO: Figure out how to pipeline this
+ --
ad3 <= wb_in.adr(3);
- -- DRAM interface signals
- user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_ctrl and not wb_is_init)
- when state = CMD else '0';
- user_port0_cmd_we <= wb_in.we when state = CMD else '0';
+ -- Wishbone port IN signals
+ user_port0_cmd_valid <= wb_in.cyc and wb_in.stb when state = CMD else '0';
+ user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
- user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
- user_port0_wdata_data <= wb_in.dat & wb_in.dat;
- user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
- "00000000" & wb_in.sel;
-
- -- Wishbone out signals. CSR and init memory do nothing, just ack
- wb_out.ack <= '1' when (wb_is_ctrl = '1' or wb_is_init = '1') else
- user_port0_wdata_ready when state = MWRITE else
+ user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
+ user_port0_wdata_data <= wb_in.dat & wb_in.dat;
+ user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
+ "00000000" & wb_in.sel;
+
+ -- Wishbone OUT signals
+ wb_out.ack <= user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';
- wb_out.dat <= (others => '0') when (wb_is_ctrl = '1' or wb_is_init = '1') else
- user_port0_rdata_data(127 downto 64) when ad3 = '1' else
+
+ wb_out.dat <= user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0);
- wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;
- -- Reset, lift it when init done, no alt core reset
- system_reset <= dram_user_reset or not init_done;
- core_alt_reset <= '0';
+ -- We don't do pipelining yet.
+ wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;
- -- State machine
+ -- DRAM user port State machine
sm: process(system_clk)
begin
port(
-- LiteDRAM generates the system clock and reset
-- from the input clkin
- clk_in : in std_ulogic;
- rst : in std_ulogic;
- system_clk : out std_ulogic;
- system_reset : out std_ulogic;
- core_alt_reset : out std_ulogic;
- pll_locked : out std_ulogic;
+ clk_in : in std_ulogic;
+ rst : in std_ulogic;
+ system_clk : out std_ulogic;
+ system_reset : out std_ulogic;
+ core_alt_reset : out std_ulogic;
+ pll_locked : out std_ulogic;
-- Wishbone ports:
- wb_in : in wishbone_master_out;
- wb_out : out wishbone_slave_out;
- wb_is_ctrl : in std_ulogic;
- wb_is_init : in std_ulogic;
+ wb_in : in wishbone_master_out;
+ wb_out : out wishbone_slave_out;
+ wb_ctrl_in : in wb_io_master_out;
+ wb_ctrl_out : out wb_io_slave_out;
+ wb_ctrl_is_csr : in std_ulogic;
+ wb_ctrl_is_init : in std_ulogic;
-- Init core serial debug
serial_tx : out std_ulogic;
signal wb_ctrl_ack : std_ulogic;
signal wb_ctrl_we : std_ulogic;
- signal wb_init_in : wishbone_master_out;
- signal wb_init_out : wishbone_slave_out;
+ signal wb_init_in : wb_io_master_out;
+ signal wb_init_out : wb_io_slave_out;
type state_t is (CMD, MWRITE, MREAD);
signal state : state_t;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";
- type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);
+ type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
- temp_ram(i) := temp_word;
+ temp_ram(i*2) := temp_word(31 downto 0);
+ temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
return temp_ram;
end function;
begin
- -- BRAM Memory slave
+ -- alternate core reset address set when DRAM is not initialized.
+ core_alt_reset <= not init_done;
+
+ -- BRAM Memory slave. TODO: Pipeline it with an output buffer
+ -- to improve timing
init_ram_0: process(system_clk)
variable adr : integer;
begin
if rising_edge(system_clk) then
wb_init_out.ack <= '0';
if (wb_init_in.cyc and wb_init_in.stb) = '1' then
- adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 3))));
+ adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_init_in.we = '0' then
wb_init_out.dat <= init_ram(adr);
else
- for i in 0 to 7 loop
+ for i in 0 to 3 loop
if wb_init_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_init_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
- wb_init_out.ack <= not wb_init_out.ack;
+ wb_init_out.ack <= '1';
end if;
end if;
end process;
- wb_init_in.adr <= wb_in.adr;
- wb_init_in.dat <= wb_in.dat;
- wb_init_in.sel <= wb_in.sel;
- wb_init_in.we <= wb_in.we;
- wb_init_in.stb <= wb_in.stb;
- wb_init_in.cyc <= wb_in.cyc and wb_is_init;
+ --
+ -- Control bus wishbone: This muxes the wishbone to the CSRs
+ -- and an internal small one to the init BRAM
+ --
+
+ -- Init DRAM wishbone IN signals
+ wb_init_in.adr <= wb_ctrl_in.adr;
+ wb_init_in.dat <= wb_ctrl_in.dat;
+ wb_init_in.sel <= wb_ctrl_in.sel;
+ wb_init_in.we <= wb_ctrl_in.we;
+ wb_init_in.stb <= wb_ctrl_in.stb;
+ wb_init_in.cyc <= wb_ctrl_in.cyc and wb_ctrl_is_init;
+
+ -- DRAM CSR IN signals
+ wb_ctrl_adr <= x"0000" & wb_ctrl_in.adr(15 downto 2);
+ wb_ctrl_dat_w <= wb_ctrl_in.dat;
+ wb_ctrl_sel <= wb_ctrl_in.sel;
+ wb_ctrl_we <= wb_ctrl_in.we;
+ wb_ctrl_cyc <= wb_ctrl_in.cyc and wb_ctrl_is_csr;
+ wb_ctrl_stb <= wb_ctrl_in.stb and wb_ctrl_is_csr;
- -- Address bit 3 selects the top or bottom half of the data
+ -- Ctrl bus wishbone OUT signals
+ wb_ctrl_out.ack <= wb_ctrl_ack when wb_ctrl_is_csr = '1'
+ else wb_init_out.ack;
+ wb_ctrl_out.dat <= wb_ctrl_dat_r when wb_ctrl_is_csr = '1'
+ else wb_init_out.dat;
+ wb_ctrl_out.stall <= wb_init_out.stall when wb_ctrl_is_init else
+ '0' when wb_ctrl_in.cyc = '0' else not wb_ctrl_ack;
+
+ --
+ -- Data bus wishbone to LiteDRAM native port
+ --
+ -- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
+ -- XXX TODO: Figure out how to pipeline this
+ --
ad3 <= wb_in.adr(3);
- -- DRAM data interface signals
- user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_ctrl and not wb_is_init)
- when state = CMD else '0';
- user_port0_cmd_we <= wb_in.we when state = CMD else '0';
+ -- Wishbone port IN signals
+ user_port0_cmd_valid <= wb_in.cyc and wb_in.stb when state = CMD else '0';
+ user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
- user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
- user_port0_wdata_data <= wb_in.dat & wb_in.dat;
- user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
- "00000000" & wb_in.sel;
-
- -- DRAM ctrl interface signals
- wb_ctrl_adr <= x"0000" & wb_in.adr(15 downto 2);
- wb_ctrl_dat_w <= wb_in.dat(31 downto 0);
- wb_ctrl_sel <= wb_in.sel(3 downto 0);
- wb_ctrl_cyc <= wb_in.cyc and wb_is_ctrl;
- wb_ctrl_stb <= wb_in.stb and wb_is_ctrl;
- wb_ctrl_we <= wb_in.we;
-
- -- Wishbone out signals
- wb_out.ack <= wb_ctrl_ack when wb_is_ctrl ='1' else
- wb_init_out.ack when wb_is_init = '1' else
- user_port0_wdata_ready when state = MWRITE else
+ user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
+ user_port0_wdata_data <= wb_in.dat & wb_in.dat;
+ user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
+ "00000000" & wb_in.sel;
+
+ -- Wishbone OUT signals
+ wb_out.ack <= user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';
- wb_out.dat <= (x"00000000" & wb_ctrl_dat_r) when wb_is_ctrl = '1' else
- wb_init_out.dat when wb_is_init = '1' else
- user_port0_rdata_data(127 downto 64) when ad3 = '1' else
+ wb_out.dat <= user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0);
+
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;
- -- Reset ignored, the reset controller use the pll lock signal,
- -- and alternate core reset address set when DRAM is not initialized.
- --
- core_alt_reset <= not init_done;
-
- -- State machine
+ -- DRAM user port State machine
sm: process(system_clk)
begin
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
- end case;
+ end case;
end if;
end if;
end process;
a64b5a7d14004a39
2402004ca64b7b7d
602100003c200000
-6421ffff782107c6
+6421f000782107c6
3d80000060213f00
798c07c6618c0000
-618c108c658cffff
+618c108c658cf000
4e8004217d8903a6
0000000048000002
0000000000000000
//--------------------------------------------------------------------------------
-// Auto-generated by Migen (0d16e03) & LiteX (3391398a) on 2020-05-15 13:30:46
+// Auto-generated by Migen (0d16e03) & LiteX (3391398a) on 2020-05-16 19:06:01
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,
port(
-- LiteDRAM generates the system clock and reset
-- from the input clkin
- clk_in : in std_ulogic;
- rst : in std_ulogic;
- system_clk : out std_ulogic;
- system_reset : out std_ulogic;
- core_alt_reset : out std_ulogic;
- pll_locked : out std_ulogic;
+ clk_in : in std_ulogic;
+ rst : in std_ulogic;
+ system_clk : out std_ulogic;
+ system_reset : out std_ulogic;
+ core_alt_reset : out std_ulogic;
+ pll_locked : out std_ulogic;
-- Wishbone ports:
- wb_in : in wishbone_master_out;
- wb_out : out wishbone_slave_out;
- wb_is_ctrl : in std_ulogic;
- wb_is_init : in std_ulogic;
+ wb_in : in wishbone_master_out;
+ wb_out : out wishbone_slave_out;
+ wb_ctrl_in : in wb_io_master_out;
+ wb_ctrl_out : out wb_io_slave_out;
+ wb_ctrl_is_csr : in std_ulogic;
+ wb_ctrl_is_init : in std_ulogic;
-- Init core serial debug
serial_tx : out std_ulogic;
signal wb_ctrl_ack : std_ulogic;
signal wb_ctrl_we : std_ulogic;
- signal wb_init_in : wishbone_master_out;
- signal wb_init_out : wishbone_slave_out;
+ signal wb_init_in : wb_io_master_out;
+ signal wb_init_out : wb_io_slave_out;
type state_t is (CMD, MWRITE, MREAD);
signal state : state_t;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";
- type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);
+ type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
- temp_ram(i) := temp_word;
+ temp_ram(i*2) := temp_word(31 downto 0);
+ temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
return temp_ram;
end function;
begin
- -- BRAM Memory slave
+ -- alternate core reset address set when DRAM is not initialized.
+ core_alt_reset <= not init_done;
+
+ -- BRAM Memory slave. TODO: Pipeline it with an output buffer
+ -- to improve timing
init_ram_0: process(system_clk)
variable adr : integer;
begin
if rising_edge(system_clk) then
wb_init_out.ack <= '0';
if (wb_init_in.cyc and wb_init_in.stb) = '1' then
- adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 3))));
+ adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_init_in.we = '0' then
wb_init_out.dat <= init_ram(adr);
else
- for i in 0 to 7 loop
+ for i in 0 to 3 loop
if wb_init_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_init_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
- wb_init_out.ack <= not wb_init_out.ack;
+ wb_init_out.ack <= '1';
end if;
end if;
end process;
- wb_init_in.adr <= wb_in.adr;
- wb_init_in.dat <= wb_in.dat;
- wb_init_in.sel <= wb_in.sel;
- wb_init_in.we <= wb_in.we;
- wb_init_in.stb <= wb_in.stb;
- wb_init_in.cyc <= wb_in.cyc and wb_is_init;
+ --
+ -- Control bus wishbone: This muxes the wishbone to the CSRs
+ -- and an internal small one to the init BRAM
+ --
+
+ -- Init DRAM wishbone IN signals
+ wb_init_in.adr <= wb_ctrl_in.adr;
+ wb_init_in.dat <= wb_ctrl_in.dat;
+ wb_init_in.sel <= wb_ctrl_in.sel;
+ wb_init_in.we <= wb_ctrl_in.we;
+ wb_init_in.stb <= wb_ctrl_in.stb;
+ wb_init_in.cyc <= wb_ctrl_in.cyc and wb_ctrl_is_init;
+
+ -- DRAM CSR IN signals
+ wb_ctrl_adr <= x"0000" & wb_ctrl_in.adr(15 downto 2);
+ wb_ctrl_dat_w <= wb_ctrl_in.dat;
+ wb_ctrl_sel <= wb_ctrl_in.sel;
+ wb_ctrl_we <= wb_ctrl_in.we;
+ wb_ctrl_cyc <= wb_ctrl_in.cyc and wb_ctrl_is_csr;
+ wb_ctrl_stb <= wb_ctrl_in.stb and wb_ctrl_is_csr;
- -- Address bit 3 selects the top or bottom half of the data
+ -- Ctrl bus wishbone OUT signals
+ wb_ctrl_out.ack <= wb_ctrl_ack when wb_ctrl_is_csr = '1'
+ else wb_init_out.ack;
+ wb_ctrl_out.dat <= wb_ctrl_dat_r when wb_ctrl_is_csr = '1'
+ else wb_init_out.dat;
+ wb_ctrl_out.stall <= wb_init_out.stall when wb_ctrl_is_init else
+ '0' when wb_ctrl_in.cyc = '0' else not wb_ctrl_ack;
+
+ --
+ -- Data bus wishbone to LiteDRAM native port
+ --
+ -- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
+ -- XXX TODO: Figure out how to pipeline this
+ --
ad3 <= wb_in.adr(3);
- -- DRAM data interface signals
- user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_ctrl and not wb_is_init)
- when state = CMD else '0';
- user_port0_cmd_we <= wb_in.we when state = CMD else '0';
+ -- Wishbone port IN signals
+ user_port0_cmd_valid <= wb_in.cyc and wb_in.stb when state = CMD else '0';
+ user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
- user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
- user_port0_wdata_data <= wb_in.dat & wb_in.dat;
- user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
- "00000000" & wb_in.sel;
-
- -- DRAM ctrl interface signals
- wb_ctrl_adr <= x"0000" & wb_in.adr(15 downto 2);
- wb_ctrl_dat_w <= wb_in.dat(31 downto 0);
- wb_ctrl_sel <= wb_in.sel(3 downto 0);
- wb_ctrl_cyc <= wb_in.cyc and wb_is_ctrl;
- wb_ctrl_stb <= wb_in.stb and wb_is_ctrl;
- wb_ctrl_we <= wb_in.we;
-
- -- Wishbone out signals
- wb_out.ack <= wb_ctrl_ack when wb_is_ctrl ='1' else
- wb_init_out.ack when wb_is_init = '1' else
- user_port0_wdata_ready when state = MWRITE else
+ user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
+ user_port0_wdata_data <= wb_in.dat & wb_in.dat;
+ user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
+ "00000000" & wb_in.sel;
+
+ -- Wishbone OUT signals
+ wb_out.ack <= user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';
- wb_out.dat <= (x"00000000" & wb_ctrl_dat_r) when wb_is_ctrl = '1' else
- wb_init_out.dat when wb_is_init = '1' else
- user_port0_rdata_data(127 downto 64) when ad3 = '1' else
+ wb_out.dat <= user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0);
+
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;
- -- Reset ignored, the reset controller use the pll lock signal,
- -- and alternate core reset address set when DRAM is not initialized.
- --
- core_alt_reset <= not init_done;
-
- -- State machine
+ -- DRAM user port State machine
sm: process(system_clk)
begin
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
- end case;
+ end case;
end if;
end if;
end process;
a64b5a7d14004a39
2402004ca64b7b7d
602100003c200000
-6421ffff782107c6
+6421f000782107c6
3d80000060213f00
798c07c6618c0000
-618c108c658cffff
+618c108c658cf000
4e8004217d8903a6
0000000048000002
0000000000000000
//--------------------------------------------------------------------------------
-// Auto-generated by Migen (0d16e03) & LiteX (3391398a) on 2020-05-15 13:30:49
+// Auto-generated by Migen (0d16e03) & LiteX (3391398a) on 2020-05-16 19:06:03
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,
-- 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
-- 0xc0004000: XICS ICP
-- 0xc0100000: LiteDRAM control (CSRs)
--- 0xf0000000: Block RAM (aliased & repeated)
--- 0xffff0000: DRAM init code (if any)
+-- 0xf0000000: DRAM init code (if any)
entity soc is
generic (
system_clk : in std_ulogic;
-- DRAM controller signals
- wb_dram_in : out wishbone_master_out;
- wb_dram_out : in wishbone_slave_out;
- wb_dram_ctrl : out std_ulogic;
- wb_dram_init : out std_ulogic;
+ wb_dram_in : out wishbone_master_out;
+ wb_dram_out : in wishbone_slave_out;
+ wb_dram_ctrl_in : out wb_io_master_out;
+ wb_dram_ctrl_out : in wb_io_slave_out;
+ wb_dram_is_csr : out std_ulogic;
+ wb_dram_is_init : out std_ulogic;
-- UART0 signals:
uart0_txd : out std_ulogic;
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 : wishbone_master_out;
- signal wb_syscon_out : wishbone_slave_out;
+ 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 : wishbone_master_out;
- signal wb_uart0_out : wishbone_slave_out;
+ signal wb_uart0_in : wb_io_master_out;
+ signal wb_uart0_out : wb_io_slave_out;
signal uart_dat8 : std_ulogic_vector(7 downto 0);
-- XICS0 signals:
- signal wb_xics0_in : wishbone_master_out;
- signal wb_xics0_out : wishbone_slave_out;
+ signal wb_xics0_in : wb_io_master_out;
+ signal wb_xics0_out : wb_io_slave_out;
signal int_level_in : std_ulogic_vector(15 downto 0);
signal xics_to_execute1 : XicsToExecute1Type;
generic map(
SIM => SIM,
DISABLE_FLATTEN => DISABLE_FLATTEN_CORE,
- ALT_RESET_ADDRESS => (15 downto 0 => '0', others => '1')
+ ALT_RESET_ADDRESS => (27 downto 0 => '0', others => '1')
)
port map(
clk => system_clk,
wb_slave_in => wb_master_in
);
- -- Wishbone slaves address decoder & mux
- 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_SYSCON,
- SLAVE_UART,
- SLAVE_BRAM,
- SLAVE_DRAM,
- SLAVE_DRAM_INIT,
- SLAVE_DRAM_CTRL,
- SLAVE_ICP_0,
- SLAVE_NONE);
- variable slave : slave_type;
+ -- 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
- -- Simple address decoder.
- slave := SLAVE_NONE;
- -- 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_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
- slave := SLAVE_DRAM_CTRL;
- elsif std_match(wb_master_out.adr, x"C0004---") then
- slave := SLAVE_ICP_0;
+ -- 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;
- -- Wishbone muxing. Defaults:
+ -- Top level wishbone muxing.
wb_bram_in <= wb_master_out;
wb_bram_in.cyc <= '0';
- wb_uart0_in <= wb_master_out;
+ 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 =>
+ wb_dram_in.cyc <= wb_master_out.cyc;
+ wb_master_in <= wb_dram_out;
+ 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_dram_ctrl_out, wb_xics0_out)
+ -- IO branch split:
+ type slave_io_type is (SLAVE_IO_SYSCON,
+ SLAVE_IO_UART,
+ SLAVE_IO_DRAM_INIT,
+ SLAVE_IO_DRAM_CSR,
+ SLAVE_IO_ICP_0,
+ SLAVE_IO_NONE);
+ variable slave_io : slave_io_type;
+
+ variable match : std_ulogic_vector(31 downto 12);
+ begin
+
+ -- Simple address decoder.
+ slave_io := SLAVE_IO_NONE;
+ match := "11" & wb_sio_out.adr(29 downto 12);
+ if std_match(match, x"F----") then
+ slave_io := SLAVE_IO_DRAM_INIT;
+ 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"C01--") then
+ slave_io := SLAVE_IO_DRAM_CSR;
+ elsif std_match(match, x"C0004") then
+ slave_io := SLAVE_IO_ICP_0;
+ end if;
+ wb_uart0_in <= wb_sio_out;
wb_uart0_in.cyc <= '0';
-- Only give xics 8 bits of wb addr
- wb_xics0_in <= wb_master_out;
+ wb_xics0_in <= wb_sio_out;
wb_xics0_in.adr <= (others => '0');
- wb_xics0_in.adr(7 downto 0) <= wb_master_out.adr(7 downto 0);
+ wb_xics0_in.adr(7 downto 0) <= wb_sio_out.adr(7 downto 0);
wb_xics0_in.cyc <= '0';
- wb_dram_in <= wb_master_out;
- wb_dram_in.cyc <= '0';
- wb_dram_ctrl <= '0';
- wb_dram_init <= '0';
- wb_syscon_in <= wb_master_out;
+ wb_dram_ctrl_in <= wb_sio_out;
+ wb_dram_ctrl_in.cyc <= '0';
+ wb_dram_is_csr <= '0';
+ wb_dram_is_init <= '0';
+
+ wb_syscon_in <= wb_sio_out;
wb_syscon_in.cyc <= '0';
- case slave is
- when SLAVE_BRAM =>
- wb_bram_in.cyc <= wb_master_out.cyc;
- wb_master_in <= wb_bram_out;
- when SLAVE_DRAM =>
- wb_dram_in.cyc <= wb_master_out.cyc;
- wb_master_in <= wb_dram_out;
- when SLAVE_DRAM_INIT =>
- wb_dram_in.cyc <= wb_master_out.cyc;
- wb_master_in <= wb_dram_out;
- wb_dram_init <= '1';
- when SLAVE_DRAM_CTRL =>
- wb_dram_in.cyc <= wb_master_out.cyc;
- wb_master_in <= wb_dram_out;
- wb_dram_ctrl <= '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;
- when SLAVE_ICP_0 =>
- wb_xics0_in.cyc <= wb_master_out.cyc;
- wb_master_in <= wb_xics0_out;
+
+ case slave_io is
+ when SLAVE_IO_DRAM_INIT =>
+ wb_dram_ctrl_in.cyc <= wb_sio_out.cyc;
+ wb_sio_in <= wb_dram_ctrl_out;
+ wb_dram_is_init <= '1';
+ when SLAVE_IO_DRAM_CSR =>
+ wb_dram_ctrl_in.cyc <= wb_sio_out.cyc;
+ wb_sio_in <= wb_dram_ctrl_out;
+ wb_dram_is_csr <= '1';
+ 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_0 =>
+ wb_xics0_in.cyc <= wb_sio_out.cyc;
+ wb_sio_in <= wb_xics0_out;
when others =>
- wb_master_in.dat <= (others => '1');
- wb_master_in.ack <= wb_master_out.stb and wb_master_out.cyc;
- wb_master_in.stall <= '0';
+ wb_sio_in.dat <= (others => '1');
+ wb_sio_in.ack <= wb_sio_out.stb and wb_sio_out.cyc;
+ wb_sio_in.stall <= '0';
end case;
- end process slave_intercon;
+
+ end process;
-- Syscon slave
syscon0: entity work.syscon
-- Simulated memory and UART
-- UART0 wishbone slave
- -- XXX FIXME: Need a proper wb64->wb8 adapter that
- -- converts SELs into low address bits and muxes
- -- data accordingly (either that or rejects large
- -- cycles).
uart0: entity work.pp_soc_uart
generic map(
FIFO_DEPTH => 32
wb_we_in => wb_uart0_in.we,
wb_ack_out => wb_uart0_out.ack
);
- wb_uart0_out.dat <= x"00000000000000" & uart_dat8;
+ wb_uart0_out.dat <= x"000000" & uart_dat8;
wb_uart0_out.stall <= '0' when wb_uart0_in.cyc = '0' else not wb_uart0_out.ack;
xics0: entity work.xics
rst : in std_ulogic;
-- Wishbone ports:
- wishbone_in : in wishbone_master_out;
- wishbone_out : out wishbone_slave_out;
+ wishbone_in : in wb_io_master_out;
+ wishbone_out : out wb_io_slave_out;
-- System control ports
dram_at_0 : out std_ulogic;
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";
+ -- Muxed reg read signal
+ signal reg_out : std_ulogic_vector(63 downto 0);
+
-- INFO register bits
constant SYS_REG_INFO_HAS_UART : integer := 0;
constant SYS_REG_INFO_HAS_DRAM : integer := 1;
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 <=
+ with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select reg_out <=
SIG_VALUE when SYS_REG_SIG,
reg_info when SYS_REG_INFO,
reg_braminfo when SYS_REG_BRAMINFO,
reg_clkinfo when SYS_REG_CLKINFO,
reg_ctrl_out when SYS_REG_CTRL,
(others => '0') when others;
+ wishbone_out.dat <= reg_out(63 downto 32) when wishbone_in.adr(2) = '1' else
+ reg_out(31 downto 0);
-- Register writes
regs_write: process(clk)
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
+ -- Change this if CTRL ever has more than 32 bits
+ if wishbone_in.adr(SYS_REG_BITS+2 downto 3) = SYS_REG_CTRL and
+ wishbone_in.adr(2) = '0' then
reg_ctrl(SYS_REG_CTRL_BITS-1 downto 0) <=
wishbone_in.dat(SYS_REG_CTRL_BITS-1 downto 0);
end if;
#include <stdint.h>
-#define XICS_BASE 0xc0004000
-
-static uint64_t xics_base = XICS_BASE;
+#include "microwatt_soc.h"
+#include "io.h"
#define XICS_XIRR_POLL 0x0
#define XICS_XIRR 0x4
uint8_t xics_read8(int offset)
{
- uint32_t val;
-
- __asm__ volatile("lbzcix %0,%1,%2" : "=r" (val) : "b" (xics_base), "r" (offset));
- return val;
+ return readb(XICS_BASE + offset);
}
void xics_write8(int offset, uint8_t val)
{
- __asm__ volatile("stbcix %0,%1,%2" : : "r" (val), "b" (xics_base), "r" (offset));
+ writeb(val, XICS_BASE + offset);
}
uint32_t xics_read32(int offset)
{
- uint32_t val;
-
- __asm__ volatile("lwzcix %0,%1,%2" : "=r" (val) : "b" (xics_base), "r" (offset));
- return val;
+ return readl(XICS_BASE + offset);
}
void xics_write32(int offset, uint32_t val)
{
- __asm__ volatile("stwcix %0,%1,%2" : : "r" (val), "b" (xics_base), "r" (offset));
+ writel(val, XICS_BASE + offset);
}
use ieee.std_logic_1164.all;
package wishbone_types is
+ --
+ -- Main CPU bus. 32-bit address, 64-bit data
+ --
constant wishbone_addr_bits : integer := 32;
constant wishbone_data_bits : integer := 64;
constant wishbone_sel_bits : integer := wishbone_data_bits/8;
type wishbone_master_out_vector is array (natural range <>) of wishbone_master_out;
type wishbone_slave_out_vector is array (natural range <>) of wishbone_slave_out;
+ --
+ -- IO Bus to a device, 30-bit address, 32-bits data
+ --
+ type wb_io_master_out is record
+ adr : std_ulogic_vector(29 downto 0);
+ dat : std_ulogic_vector(31 downto 0);
+ sel : std_ulogic_vector(3 downto 0);
+ cyc : std_ulogic;
+ stb : std_ulogic;
+ we : std_ulogic;
+ end record;
+
+ type wb_io_slave_out is record
+ dat : std_ulogic_vector(31 downto 0);
+ ack : std_ulogic;
+ stall : std_ulogic;
+ end record;
+
end package wishbone_types;
clk : in std_logic;
rst : in std_logic;
- wb_in : in wishbone_master_out;
- wb_out : out wishbone_slave_out;
+ wb_in : in wb_io_master_out;
+ wb_out : out wb_io_slave_out;
int_level_in : in std_ulogic_vector(LEVEL_NUM - 1 downto 0);
mfrr : std_ulogic_vector(7 downto 0);
mfrr_pending : std_ulogic;
irq : std_ulogic;
- wb_rd_data : wishbone_data_type;
+ wb_rd_data : std_ulogic_vector(31 downto 0);
wb_ack : std_ulogic;
end record;
constant reg_internal_init : reg_internal_t :=
-- hardwire the hardware IRQ priority
constant HW_PRIORITY : std_ulogic_vector(7 downto 0) := x"80";
- -- 32 bit offsets for each presentation
- constant XIRR_POLL : std_ulogic_vector(31 downto 0) := x"00000000";
- constant XIRR : std_ulogic_vector(31 downto 0) := x"00000004";
- constant RESV0 : std_ulogic_vector(31 downto 0) := x"00000008";
- constant MFRR : std_ulogic_vector(31 downto 0) := x"0000000c";
+ -- 8 bit offsets for each presentation
+ constant XIRR_POLL : std_ulogic_vector(7 downto 0) := x"00";
+ constant XIRR : std_ulogic_vector(7 downto 0) := x"04";
+ constant RESV0 : std_ulogic_vector(7 downto 0) := x"08";
+ constant MFRR : std_ulogic_vector(7 downto 0) := x"0c";
begin
irq_eoi := '0';
if wb_in.cyc = '1' and wb_in.stb = '1' then
- -- wishbone addresses we get are 64 bit alligned, so we
- -- need to use the sel bits to get 32 bit chunks.
v.wb_ack := '1'; -- always ack
if wb_in.we = '1' then -- write
-- writes to both XIRR are the same
- if wb_in.adr = XIRR_POLL then
- report "XICS XIRR_POLL/XIRR write";
- if wb_in.sel = x"0f" then -- 4 bytes
+ case wb_in.adr(7 downto 0) is
+ when XIRR_POLL =>
+ report "XICS XIRR_POLL write";
+ if wb_in.sel = x"f" then -- 4 bytes
+ v.cppr := wb_in.dat(31 downto 24);
+ elsif wb_in.sel = x"1" then -- 1 byte
+ v.cppr := wb_in.dat(7 downto 0);
+ end if;
+ when XIRR =>
+ if wb_in.sel = x"f" then -- 4 byte
+ report "XICS XIRR write word:" & to_hstring(wb_in.dat);
v.cppr := wb_in.dat(31 downto 24);
- elsif wb_in.sel = x"f0" then -- 4 byte
- v.cppr := wb_in.dat(63 downto 56);
irq_eoi := '1';
- elsif wb_in.sel = x"01" then -- 1 byte
+ elsif wb_in.sel = x"1" then -- 1 byte
+ report "XICS XIRR write byte:" & to_hstring(wb_in.dat(7 downto 0));
v.cppr := wb_in.dat(7 downto 0);
- elsif wb_in.sel = x"10" then -- 1 byte
- v.cppr := wb_in.dat(39 downto 32);
+ else
+ report "XICS XIRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel);
end if;
-
- elsif wb_in.adr = RESV0 then
- report "XICS MFRR write";
- if wb_in.sel = x"f0" then -- 4 bytes
+ when MFRR =>
+ if wb_in.sel = x"f" then -- 4 bytes
+ report "XICS MFRR write word:" & to_hstring(wb_in.dat);
v.mfrr_pending := '1';
- v.mfrr := wb_in.dat(63 downto 56);
- elsif wb_in.sel = x"10" then -- 1 byte
+ v.mfrr := wb_in.dat(31 downto 24);
+ elsif wb_in.sel = x"1" then -- 1 byte
+ report "XICS MFRR write byte:" & to_hstring(wb_in.dat(7 downto 0));
v.mfrr_pending := '1';
- v.mfrr := wb_in.dat(39 downto 32);
+ v.mfrr := wb_in.dat(7 downto 0);
+ else
+ report "XICS MFRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel);
end if;
-
- end if;
+ when others =>
+ end case;
else -- read
v.wb_rd_data := (others => '0');
- if wb_in.adr = XIRR_POLL then
- report "XICS XIRR_POLL/XIRR read";
- if wb_in.sel = x"0f" then
+ case wb_in.adr(7 downto 0) is
+ when XIRR_POLL =>
+ report "XICS XIRR_POLL read";
+ if wb_in.sel = x"f" then
v.wb_rd_data(23 downto 0) := r.xisr;
v.wb_rd_data(31 downto 24) := r.cppr;
- elsif wb_in.sel = x"f0" then
- v.wb_rd_data(55 downto 32) := r.xisr;
- v.wb_rd_data(63 downto 56) := r.cppr;
- xirr_accept_rd := '1';
- elsif wb_in.sel = x"01" then
+ elsif wb_in.sel = x"1" then
v.wb_rd_data(7 downto 0) := r.cppr;
- elsif wb_in.sel = x"10" then
- v.wb_rd_data(39 downto 32) := r.cppr;
+ end if;
+ when XIRR =>
+ report "XICS XIRR read";
+ if wb_in.sel = x"f" then
+ v.wb_rd_data(23 downto 0) := r.xisr;
+ v.wb_rd_data(31 downto 24) := r.cppr;
+ xirr_accept_rd := '1';
+ elsif wb_in.sel = x"1" then
+ v.wb_rd_data(7 downto 0) := r.cppr;
end if;
-
- elsif wb_in.adr = RESV0 then
+ when MFRR =>
report "XICS MFRR read";
- if wb_in.sel = x"f0" then -- 4 bytes
- v.wb_rd_data(63 downto 56) := r.mfrr;
- elsif wb_in.sel = x"10" then -- 1 byte
+ if wb_in.sel = x"f" then -- 4 bytes
+ v.wb_rd_data(31 downto 24) := r.mfrr;
+ elsif wb_in.sel = x"1" then -- 1 byte
v.wb_rd_data( 7 downto 0) := r.mfrr;
end if;
- end if;
+ when others =>
+ end case;
end if;
end if;