uart: Import and hook up opencore 16550 compatible UART

This imports via fusesoc a 16550 compatible (ie "standard") UART,
and wires it up optionally in the SoC instead of the potato one.

This also adds support for a second UART (which is always a
16550) to Arty, wired to JC "bottom" port.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
pull/213/head
Benjamin Herrenschmidt 4 years ago
parent 76e2c7d81c
commit 7575b1e0c2

@ -13,10 +13,10 @@ set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart_mai
# Pmod Header JC: UART (bottom)
################################################################################

#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_cts_n }];
#set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_tx }];
#set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rx }];
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rts_n }];
set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_cts_n }];
set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_tx }];
set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rx }];
set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rts_n }];

################################################################################
# RGB LEDs

@ -22,7 +22,9 @@ entity toplevel is
SPI_FLASH_DEF_CKDV : natural := 1;
SPI_FLASH_DEF_QUAD : boolean := true;
LOG_LENGTH : natural := 512;
USE_LITEETH : boolean := false
USE_LITEETH : boolean := false;
UART_IS_16550 : boolean := false;
HAS_UART1 : boolean := false
);
port(
ext_clk : in std_ulogic;
@ -32,6 +34,12 @@ entity toplevel is
uart_main_tx : out std_ulogic;
uart_main_rx : in std_ulogic;

-- UART1 signals:
uart_pmod_tx : out std_ulogic;
uart_pmod_rx : in std_ulogic;
uart_pmod_cts_n : in std_ulogic;
uart_pmod_rts_n : out std_ulogic;

-- LEDs
led0_b : out std_ulogic;
led0_g : out std_ulogic;
@ -170,7 +178,9 @@ begin
SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
LOG_LENGTH => LOG_LENGTH,
USE_LITEETH => USE_LITEETH
HAS_LITEETH => USE_LITEETH,
UART0_IS_16550 => UART_IS_16550,
HAS_UART1 => HAS_UART1
)
port map (
-- System signals
@ -181,6 +191,10 @@ begin
uart0_txd => uart_main_tx,
uart0_rxd => uart_main_rx,

-- UART1 signals
uart1_txd => uart_pmod_tx,
uart1_rxd => uart_pmod_rx,

-- SPI signals
spi_flash_sck => spi_sck,
spi_flash_cs_n => spi_cs_n,
@ -202,6 +216,8 @@ begin
alt_reset => core_alt_reset
);

uart_pmod_rts_n <= '0';

-- SPI Flash
--
-- Note: Unlike many other boards, the SPI flash on the Arty has

@ -11,7 +11,8 @@ entity toplevel is
RESET_LOW : boolean := true;
CLK_INPUT : positive := 100000000;
CLK_FREQUENCY : positive := 100000000;
DISABLE_FLATTEN_CORE : boolean := false
DISABLE_FLATTEN_CORE : boolean := false;
UART_IS_16550 : boolean := false
);
port(
ext_clk : in std_ulogic;
@ -67,7 +68,8 @@ begin
RAM_INIT_FILE => RAM_INIT_FILE,
SIM => false,
CLK_FREQ => CLK_FREQUENCY,
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE,
UART0_IS_16550 => UART_IS_16550
)
port map (
system_clk => system_clk,

@ -19,7 +19,8 @@ entity toplevel is
DISABLE_FLATTEN_CORE : boolean := false;
SPI_FLASH_OFFSET : integer := 10485760;
SPI_FLASH_DEF_CKDV : natural := 1;
SPI_FLASH_DEF_QUAD : boolean := true
SPI_FLASH_DEF_QUAD : boolean := true;
UART_IS_16550 : boolean := false;
);
port(
ext_clk : in std_ulogic;
@ -126,7 +127,8 @@ begin
SPI_FLASH_DLINES => 4,
SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
UART0_IS_16550 => UART_IS_16550
)
port map (
-- System signals

@ -37,6 +37,8 @@
#define SYS_REG_INFO_HAS_BRAM (1ull << 2)
#define SYS_REG_INFO_HAS_SPI_FLASH (1ull << 3)
#define SYS_REG_INFO_HAS_LITEETH (1ull << 4)
#define SYS_REG_INFO_HAS_LARGE_SYSCON (1ull << 5)
#define SYS_REG_INFO_HAS_UART1 (1ull << 6)
#define SYS_REG_BRAMINFO 0x10
#define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull
#define SYS_REG_DRAMINFO 0x18
@ -50,7 +52,9 @@
#define SYS_REG_DRAMINITINFO 0x30
#define SYS_REG_SPI_INFO 0x38
#define SYS_REG_SPI_INFO_FLASH_OFF_MASK 0xffffffff

#define SYS_REG_UART0_INFO 0x40
#define SYS_REG_UART1_INFO 0x48
#define SYS_REG_UART_IS_16550 (1ull << 32)


/*
@ -66,6 +70,53 @@
#define POTATO_CONSOLE_CLOCK_DIV 0x18
#define POTATO_CONSOLE_IRQ_EN 0x20

/*
* Register definitionss for our standard (16550 style) UART
*/
#define UART_REG_RX 0x00
#define UART_REG_TX 0x00
#define UART_REG_DLL 0x00
#define UART_REG_IER 0x04
#define UART_REG_DLM 0x04
#define UART_REG_IIR 0x08
#define UART_REG_FCR 0x08
#define UART_REG_FCR_EN_FIFO 0x01
#define UART_REG_FCR_CLR_RCVR 0x02
#define UART_REG_FCR_CLR_XMIT 0x04
#define UART_REG_FCR_TRIG1 0x00
#define UART_REG_FCR_TRIG4 0x40
#define UART_REG_FCR_TRIG8 0x80
#define UART_REG_FCR_TRIG14 0xc0
#define UART_REG_LCR 0x0c
#define UART_REG_LCR_5BIT 0x00
#define UART_REG_LCR_6BIT 0x01
#define UART_REG_LCR_7BIT 0x02
#define UART_REG_LCR_8BIT 0x03
#define UART_REG_LCR_STOP 0x04
#define UART_REG_LCR_PAR 0x08
#define UART_REG_LCR_EVEN_PAR 0x10
#define UART_REG_LCR_STIC_PAR 0x20
#define UART_REG_LCR_BREAK 0x40
#define UART_REG_LCR_DLAB 0x80
#define UART_REG_MCR 0x10
#define UART_REG_MCR_DTR 0x01
#define UART_REG_MCR_RTS 0x02
#define UART_REG_MCR_OUT1 0x04
#define UART_REG_MCR_OUT2 0x08
#define UART_REG_MCR_LOOP 0x10
#define UART_REG_LSR 0x14
#define UART_REG_LSR_DR 0x01
#define UART_REG_LSR_OE 0x02
#define UART_REG_LSR_PE 0x04
#define UART_REG_LSR_FE 0x08
#define UART_REG_LSR_BI 0x10
#define UART_REG_LSR_THRE 0x20
#define UART_REG_LSR_TEMT 0x40
#define UART_REG_LSR_FIFOE 0x80
#define UART_REG_MSR 0x18
#define UART_REG_SCR 0x1c


/*
* Register definitions for the SPI controller
*/

@ -103,10 +103,13 @@ filesets:
liteeth:
depend : [":microwatt:liteeth"]

uart16550:
depend : ["::uart16550"]

targets:
nexys_a7:
default_tool: vivado
filesets: [core, nexys_a7, soc, fpga, debug_xilinx, xilinx_specific]
filesets: [core, nexys_a7, soc, fpga, debug_xilinx, uart16550, xilinx_specific]
parameters :
- memory_size
- ram_init_file
@ -114,13 +117,15 @@ targets:
- clk_frequency
- disable_flatten_core
- log_length=2048
- uart_is_16550
- has_uart1
tools:
vivado: {part : xc7a100tcsg324-1}
toplevel : toplevel

nexys_video-nodram:
default_tool: vivado
filesets: [core, nexys_video, soc, fpga, debug_xilinx, xilinx_specific]
filesets: [core, nexys_video, soc, fpga, debug_xilinx, uart16550, xilinx_specific]
parameters :
- memory_size
- ram_init_file
@ -129,13 +134,15 @@ targets:
- disable_flatten_core
- spi_flash_offset=10485760
- log_length=2048
- uart_is_16550
- has_uart1
tools:
vivado: {part : xc7a200tsbg484-1}
toplevel : toplevel

nexys_video:
default_tool: vivado
filesets: [core, nexys_video, soc, fpga, debug_xilinx, litedram, xilinx_specific]
filesets: [core, nexys_video, soc, fpga, debug_xilinx, litedram, uart16550, xilinx_specific]
parameters:
- memory_size
- ram_init_file
@ -151,7 +158,7 @@ targets:

arty_a7-35-nodram:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx, xilinx_specific]
filesets: [core, arty_a7, soc, fpga, debug_xilinx, uart16550, xilinx_specific]
parameters :
- memory_size
- ram_init_file
@ -160,13 +167,15 @@ targets:
- disable_flatten_core
- spi_flash_offset=3145728
- log_length=512
- uart_is_16550
- has_uart1
tools:
vivado: {part : xc7a35ticsg324-1L}
toplevel : toplevel

arty_a7-35:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx, litedram, liteeth, xilinx_specific]
filesets: [core, arty_a7, soc, fpga, debug_xilinx, litedram, liteeth, uart16550, xilinx_specific]
parameters :
- memory_size
- ram_init_file
@ -176,6 +185,8 @@ targets:
- no_bram
- spi_flash_offset=3145728
- log_length=512
- uart_is_16550
- has_uart1
generate: [litedram_arty, liteeth_arty]
tools:
vivado: {part : xc7a35ticsg324-1L}
@ -183,7 +194,7 @@ targets:

arty_a7-100-nodram:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx, xilinx_specific]
filesets: [core, arty_a7, soc, fpga, debug_xilinx, uart16550, xilinx_specific]
parameters :
- memory_size
- ram_init_file
@ -192,13 +203,15 @@ targets:
- disable_flatten_core
- spi_flash_offset=4194304
- log_length=2048
- uart_is_16550
- has_uart1
tools:
vivado: {part : xc7a100ticsg324-1L}
toplevel : toplevel

arty_a7-100:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx, litedram, liteeth, xilinx_specific]
filesets: [core, arty_a7, soc, fpga, debug_xilinx, litedram, liteeth, uart16550, xilinx_specific]
parameters:
- memory_size
- ram_init_file
@ -208,6 +221,8 @@ targets:
- no_bram
- spi_flash_offset=4194304
- log_length=2048
- uart_is_16550
- has_uart1
generate: [litedram_arty, liteeth_arty]
tools:
vivado: {part : xc7a100ticsg324-1L}
@ -215,7 +230,7 @@ targets:

cmod_a7-35:
default_tool: vivado
filesets: [core, cmod_a7-35, soc, fpga, debug_xilinx, xilinx_specific]
filesets: [core, cmod_a7-35, soc, fpga, debug_xilinx, uart16550, xilinx_specific]
parameters :
- memory_size
- ram_init_file
@ -224,6 +239,8 @@ targets:
- clk_frequency
- disable_flatten_core
- log_length=512
- uart_is_16550
- has_uart1
tools:
vivado: {part : xc7a35tcpg236-1}
toplevel : toplevel
@ -294,6 +311,18 @@ parameters:
paramtype : generic
default : false

uart_is_16550:
datatype : bool
description : Use 16550-compatible UART from OpenCores
paramtype : generic
default : false

has_uart1:
datatype : bool
description : Enable second UART (always 16550-compatible)
paramtype : generic
default : false

no_bram:
datatype : bool
description : No internal block RAM (only DRAM and init code carrying payload)

@ -20,6 +20,7 @@ use work.wishbone_types.all;
-- IO Bus:
-- 0xc0000000: SYSCON
-- 0xc0002000: UART0
-- 0xc0003000: UART1 (if any)
-- 0xc0004000: XICS ICP
-- 0xc0005000: XICS ICS
-- 0xc0006000: SPI Flash controller
@ -61,7 +62,9 @@ entity soc is
SPI_FLASH_DEF_CKDV : natural := 2;
SPI_FLASH_DEF_QUAD : boolean := false;
LOG_LENGTH : natural := 512;
HAS_LITEETH : boolean := false
HAS_LITEETH : boolean := false;
UART0_IS_16550 : boolean := false;
HAS_UART1 : boolean := false
);
port(
rst : in std_ulogic;
@ -85,6 +88,10 @@ entity soc is
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;
@ -137,6 +144,12 @@ architecture behaviour of soc is
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;
@ -188,12 +201,37 @@ architecture behaviour of soc is
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;
begin

resets: process(system_clk)
@ -458,7 +496,7 @@ begin
-- IO wishbone slave intercon.
--
slave_io_intercon: process(wb_sio_out, wb_syscon_out, wb_uart0_out,
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;
@ -478,6 +516,8 @@ begin
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
@ -490,6 +530,8 @@ begin
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';
@ -559,6 +601,9 @@ begin
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.
@ -586,7 +631,9 @@ begin
CLK_FREQ => CLK_FREQ,
HAS_SPI_FLASH => HAS_SPI_FLASH,
SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
HAS_LITEETH => HAS_LITEETH
HAS_LITEETH => HAS_LITEETH,
UART0_IS_16550 => UART0_IS_16550,
HAS_UART1 => HAS_UART1
)
port map(
clk => system_clk,
@ -598,30 +645,115 @@ begin
soc_reset => open -- XXX TODO
);

-- Simulated memory and UART
--
-- 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;

-- UART0 wishbone slave
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
);
wb_uart0_out.dat <= x"000000" & uart0_dat8;
wb_uart0_out.stall <= 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 <= 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';
end generate;

spiflash_gen: if HAS_SPI_FLASH generate
spiflash: entity work.spi_flash_ctrl
generic map (
@ -680,6 +812,7 @@ 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

@ -17,7 +17,9 @@ entity syscon is
DRAM_INIT_SIZE : integer;
HAS_SPI_FLASH : boolean;
SPI_FLASH_OFFSET : integer;
HAS_LITEETH : boolean
HAS_LITEETH : boolean;
UART0_IS_16550 : boolean;
HAS_UART1 : boolean
);
port (
clk : in std_ulogic;
@ -37,27 +39,31 @@ end entity syscon;

architecture behaviour of syscon is
-- Register address bits
constant SYS_REG_BITS : positive := 3;
constant SYS_REG_BITS : positive := 6;

-- Register addresses (matches wishbone addr downto 3, ie, 8 bytes per reg)
constant SYS_REG_SIG : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000";
constant SYS_REG_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001";
constant SYS_REG_BRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "010";
constant SYS_REG_DRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "011";
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";
constant SYS_REG_DRAMINITINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "110";
constant SYS_REG_SPIFLASHINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "111";
constant SYS_REG_SIG : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000000";
constant SYS_REG_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000001";
constant SYS_REG_BRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000010";
constant SYS_REG_DRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000011";
constant SYS_REG_CLKINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000100";
constant SYS_REG_CTRL : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000101";
constant SYS_REG_DRAMINITINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000110";
constant SYS_REG_SPIFLASHINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000111";
constant SYS_REG_UART0_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001000";
constant SYS_REG_UART1_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001001";

-- 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;
constant SYS_REG_INFO_HAS_BRAM : integer := 2;
constant SYS_REG_INFO_HAS_SPIF : integer := 3;
constant SYS_REG_INFO_HAS_LETH : integer := 4;
constant SYS_REG_INFO_HAS_UART : integer := 0; -- Has a UART (always set)
constant SYS_REG_INFO_HAS_DRAM : integer := 1; -- Has DRAM
constant SYS_REG_INFO_HAS_BRAM : integer := 2; -- Has "main" BRAM
constant SYS_REG_INFO_HAS_SPIF : integer := 3; -- Has SPI flash
constant SYS_REG_INFO_HAS_LETH : integer := 4; -- Has LiteEth ethernet
constant SYS_REG_INFO_HAS_LSYS : integer := 5; -- Has 6-bit address syscon
constant SYS_REG_INFO_HAS_URT1 : integer := 6; -- Has second UART

-- BRAMINFO contains the BRAM size in the bottom 52 bits
-- DRAMINFO contains the DRAM size if any in the bottom 52 bits
@ -76,6 +82,12 @@ architecture behaviour of syscon is
-- reserved for the FPGA bitfile if any
constant SYS_REG_SPI_INFO_IS_FLASH : integer := 0;

-- UART0/1 info registers bits
--
-- 0 ..31 : UART clock freq (in HZ)
-- 32 : UART is 16550 (otherwise pp)
--

-- Ctrl register
signal reg_ctrl : std_ulogic_vector(SYS_REG_CTRL_BITS-1 downto 0);
signal reg_ctrl_out : std_ulogic_vector(63 downto 0);
@ -87,13 +99,18 @@ architecture behaviour of syscon is
signal reg_dramiinfo : std_ulogic_vector(63 downto 0);
signal reg_clkinfo : std_ulogic_vector(63 downto 0);
signal reg_spiinfo : std_ulogic_vector(63 downto 0);
signal reg_uart0info : std_ulogic_vector(63 downto 0);
signal reg_uart1info : std_ulogic_vector(63 downto 0);
signal info_has_dram : std_ulogic;
signal info_has_bram : std_ulogic;
signal info_has_uart : std_ulogic;
signal info_has_spif : std_ulogic;
signal info_has_leth : std_ulogic;
signal info_has_urt1 : std_ulogic;
signal info_clk : std_ulogic_vector(39 downto 0);
signal info_fl_off : std_ulogic_vector(31 downto 0);
signal uinfo_16550 : std_ulogic;
signal uinfo_freq : std_ulogic_vector(31 downto 0);

-- Wishbone response latch
signal wb_rsp : wb_io_slave_out;
@ -110,12 +127,15 @@ begin
info_has_bram <= '1' when BRAM_SIZE /= 0 else '0';
info_has_spif <= '1' when HAS_SPI_FLASH else '0';
info_has_leth <= '1' when HAS_LITEETH else '0';
info_has_urt1 <= '1' when HAS_UART1 else '0';
info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40));
reg_info <= (SYS_REG_INFO_HAS_UART => info_has_uart,
SYS_REG_INFO_HAS_DRAM => info_has_dram,
SYS_REG_INFO_HAS_BRAM => info_has_bram,
SYS_REG_INFO_HAS_SPIF => info_has_spif,
SYS_REG_INFO_HAS_LETH => info_has_leth,
SYS_REG_INFO_HAS_LSYS => '1',
SYS_REG_INFO_HAS_URT1 => info_has_urt1,
others => '0');

reg_braminfo <= x"000" & std_ulogic_vector(to_unsigned(BRAM_SIZE, 52));
@ -133,6 +153,16 @@ begin
reg_ctrl_out <= (63 downto SYS_REG_CTRL_BITS => '0',
SYS_REG_CTRL_BITS-1 downto 0 => reg_ctrl);

-- UART info registers read composition
uinfo_16550 <= '1' when UART0_IS_16550 else '0';
uinfo_freq <= std_ulogic_vector(to_unsigned(CLK_FREQ, 32));
reg_uart0info <= (32 => uinfo_16550,
31 downto 0 => uinfo_freq,
others => '0');
reg_uart1info <= (32 => '1',
31 downto 0 => uinfo_freq,
others => '0');

-- Wishbone response
wb_rsp.ack <= wishbone_in.cyc and wishbone_in.stb;
with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select reg_out <=
@ -144,6 +174,8 @@ begin
reg_clkinfo when SYS_REG_CLKINFO,
reg_ctrl_out when SYS_REG_CTRL,
reg_spiinfo when SYS_REG_SPIFLASHINFO,
reg_uart0info when SYS_REG_UART0_INFO,
reg_uart1info when SYS_REG_UART1_INFO,
(others => '0') when others;
wb_rsp.dat <= reg_out(63 downto 32) when wishbone_in.adr(2) = '1' else
reg_out(31 downto 0);

Loading…
Cancel
Save