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 5 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) # Pmod Header JC: UART (bottom)
################################################################################ ################################################################################


#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_cts_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 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 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 U13 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rts_n }];


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

@ -22,7 +22,9 @@ entity toplevel is
SPI_FLASH_DEF_CKDV : natural := 1; SPI_FLASH_DEF_CKDV : natural := 1;
SPI_FLASH_DEF_QUAD : boolean := true; SPI_FLASH_DEF_QUAD : boolean := true;
LOG_LENGTH : natural := 512; LOG_LENGTH : natural := 512;
USE_LITEETH : boolean := false USE_LITEETH : boolean := false;
UART_IS_16550 : boolean := false;
HAS_UART1 : boolean := false
); );
port( port(
ext_clk : in std_ulogic; ext_clk : in std_ulogic;
@ -32,6 +34,12 @@ entity toplevel is
uart_main_tx : out std_ulogic; uart_main_tx : out std_ulogic;
uart_main_rx : in 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 -- LEDs
led0_b : out std_ulogic; led0_b : out std_ulogic;
led0_g : out std_ulogic; led0_g : out std_ulogic;
@ -170,7 +178,9 @@ begin
SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV, SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD, SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
LOG_LENGTH => LOG_LENGTH, LOG_LENGTH => LOG_LENGTH,
USE_LITEETH => USE_LITEETH HAS_LITEETH => USE_LITEETH,
UART0_IS_16550 => UART_IS_16550,
HAS_UART1 => HAS_UART1
) )
port map ( port map (
-- System signals -- System signals
@ -181,6 +191,10 @@ begin
uart0_txd => uart_main_tx, uart0_txd => uart_main_tx,
uart0_rxd => uart_main_rx, uart0_rxd => uart_main_rx,


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

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


uart_pmod_rts_n <= '0';

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

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

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

@ -37,6 +37,8 @@
#define SYS_REG_INFO_HAS_BRAM (1ull << 2) #define SYS_REG_INFO_HAS_BRAM (1ull << 2)
#define SYS_REG_INFO_HAS_SPI_FLASH (1ull << 3) #define SYS_REG_INFO_HAS_SPI_FLASH (1ull << 3)
#define SYS_REG_INFO_HAS_LITEETH (1ull << 4) #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 0x10
#define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull #define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull
#define SYS_REG_DRAMINFO 0x18 #define SYS_REG_DRAMINFO 0x18
@ -50,7 +52,9 @@
#define SYS_REG_DRAMINITINFO 0x30 #define SYS_REG_DRAMINITINFO 0x30
#define SYS_REG_SPI_INFO 0x38 #define SYS_REG_SPI_INFO 0x38
#define SYS_REG_SPI_INFO_FLASH_OFF_MASK 0xffffffff #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_CLOCK_DIV 0x18
#define POTATO_CONSOLE_IRQ_EN 0x20 #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 * Register definitions for the SPI controller
*/ */

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


uart16550:
depend : ["::uart16550"]

targets: targets:
nexys_a7: nexys_a7:
default_tool: vivado 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 : parameters :
- memory_size - memory_size
- ram_init_file - ram_init_file
@ -114,13 +117,15 @@ targets:
- clk_frequency - clk_frequency
- disable_flatten_core - disable_flatten_core
- log_length=2048 - log_length=2048
- uart_is_16550
- has_uart1
tools: tools:
vivado: {part : xc7a100tcsg324-1} vivado: {part : xc7a100tcsg324-1}
toplevel : toplevel toplevel : toplevel


nexys_video-nodram: nexys_video-nodram:
default_tool: vivado 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 : parameters :
- memory_size - memory_size
- ram_init_file - ram_init_file
@ -129,13 +134,15 @@ targets:
- disable_flatten_core - disable_flatten_core
- spi_flash_offset=10485760 - spi_flash_offset=10485760
- log_length=2048 - log_length=2048
- uart_is_16550
- has_uart1
tools: tools:
vivado: {part : xc7a200tsbg484-1} vivado: {part : xc7a200tsbg484-1}
toplevel : toplevel toplevel : toplevel


nexys_video: nexys_video:
default_tool: vivado 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: parameters:
- memory_size - memory_size
- ram_init_file - ram_init_file
@ -151,7 +158,7 @@ targets:


arty_a7-35-nodram: arty_a7-35-nodram:
default_tool: vivado 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 : parameters :
- memory_size - memory_size
- ram_init_file - ram_init_file
@ -160,13 +167,15 @@ targets:
- disable_flatten_core - disable_flatten_core
- spi_flash_offset=3145728 - spi_flash_offset=3145728
- log_length=512 - log_length=512
- uart_is_16550
- has_uart1
tools: tools:
vivado: {part : xc7a35ticsg324-1L} vivado: {part : xc7a35ticsg324-1L}
toplevel : toplevel toplevel : toplevel


arty_a7-35: arty_a7-35:
default_tool: vivado 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 : parameters :
- memory_size - memory_size
- ram_init_file - ram_init_file
@ -176,6 +185,8 @@ targets:
- no_bram - no_bram
- spi_flash_offset=3145728 - spi_flash_offset=3145728
- log_length=512 - log_length=512
- uart_is_16550
- has_uart1
generate: [litedram_arty, liteeth_arty] generate: [litedram_arty, liteeth_arty]
tools: tools:
vivado: {part : xc7a35ticsg324-1L} vivado: {part : xc7a35ticsg324-1L}
@ -183,7 +194,7 @@ targets:


arty_a7-100-nodram: arty_a7-100-nodram:
default_tool: vivado 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 : parameters :
- memory_size - memory_size
- ram_init_file - ram_init_file
@ -192,13 +203,15 @@ targets:
- disable_flatten_core - disable_flatten_core
- spi_flash_offset=4194304 - spi_flash_offset=4194304
- log_length=2048 - log_length=2048
- uart_is_16550
- has_uart1
tools: tools:
vivado: {part : xc7a100ticsg324-1L} vivado: {part : xc7a100ticsg324-1L}
toplevel : toplevel toplevel : toplevel


arty_a7-100: arty_a7-100:
default_tool: vivado 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: parameters:
- memory_size - memory_size
- ram_init_file - ram_init_file
@ -208,6 +221,8 @@ targets:
- no_bram - no_bram
- spi_flash_offset=4194304 - spi_flash_offset=4194304
- log_length=2048 - log_length=2048
- uart_is_16550
- has_uart1
generate: [litedram_arty, liteeth_arty] generate: [litedram_arty, liteeth_arty]
tools: tools:
vivado: {part : xc7a100ticsg324-1L} vivado: {part : xc7a100ticsg324-1L}
@ -215,7 +230,7 @@ targets:


cmod_a7-35: cmod_a7-35:
default_tool: vivado 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 : parameters :
- memory_size - memory_size
- ram_init_file - ram_init_file
@ -224,6 +239,8 @@ targets:
- clk_frequency - clk_frequency
- disable_flatten_core - disable_flatten_core
- log_length=512 - log_length=512
- uart_is_16550
- has_uart1
tools: tools:
vivado: {part : xc7a35tcpg236-1} vivado: {part : xc7a35tcpg236-1}
toplevel : toplevel toplevel : toplevel
@ -294,6 +311,18 @@ parameters:
paramtype : generic paramtype : generic
default : false 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: no_bram:
datatype : bool datatype : bool
description : No internal block RAM (only DRAM and init code carrying payload) description : No internal block RAM (only DRAM and init code carrying payload)

@ -20,6 +20,7 @@ use work.wishbone_types.all;
-- IO Bus: -- IO Bus:
-- 0xc0000000: SYSCON -- 0xc0000000: SYSCON
-- 0xc0002000: UART0 -- 0xc0002000: UART0
-- 0xc0003000: UART1 (if any)
-- 0xc0004000: XICS ICP -- 0xc0004000: XICS ICP
-- 0xc0005000: XICS ICS -- 0xc0005000: XICS ICS
-- 0xc0006000: SPI Flash controller -- 0xc0006000: SPI Flash controller
@ -61,7 +62,9 @@ entity soc is
SPI_FLASH_DEF_CKDV : natural := 2; SPI_FLASH_DEF_CKDV : natural := 2;
SPI_FLASH_DEF_QUAD : boolean := false; SPI_FLASH_DEF_QUAD : boolean := false;
LOG_LENGTH : natural := 512; LOG_LENGTH : natural := 512;
HAS_LITEETH : boolean := false HAS_LITEETH : boolean := false;
UART0_IS_16550 : boolean := false;
HAS_UART1 : boolean := false
); );
port( port(
rst : in std_ulogic; rst : in std_ulogic;
@ -85,6 +88,10 @@ entity soc is
uart0_txd : out std_ulogic; uart0_txd : out std_ulogic;
uart0_rxd : in std_ulogic := '0'; uart0_rxd : in std_ulogic := '0';


-- UART1 signals:
uart1_txd : out std_ulogic;
uart1_rxd : in std_ulogic := '0';

-- SPI Flash signals -- SPI Flash signals
spi_flash_sck : out std_ulogic; spi_flash_sck : out std_ulogic;
spi_flash_cs_n : 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_dat8 : std_ulogic_vector(7 downto 0);
signal uart0_irq : std_ulogic; 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: -- SPI Flash controller signals:
signal wb_spiflash_in : wb_io_master_out; signal wb_spiflash_in : wb_io_master_out;
signal wb_spiflash_out : wb_io_slave_out; signal wb_spiflash_out : wb_io_slave_out;
@ -188,12 +201,37 @@ architecture behaviour of soc is
SLAVE_IO_UART, SLAVE_IO_UART,
SLAVE_IO_ICP, SLAVE_IO_ICP,
SLAVE_IO_ICS, SLAVE_IO_ICS,
SLAVE_IO_UART1,
SLAVE_IO_SPI_FLASH_REG, SLAVE_IO_SPI_FLASH_REG,
SLAVE_IO_SPI_FLASH_MAP, SLAVE_IO_SPI_FLASH_MAP,
SLAVE_IO_EXTERNAL, SLAVE_IO_EXTERNAL,
SLAVE_IO_NONE); SLAVE_IO_NONE);
signal slave_io_dbg : slave_io_type; 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 begin


resets: process(system_clk) resets: process(system_clk)
@ -458,7 +496,7 @@ begin
-- IO wishbone slave intercon. -- 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_ext_io_out, wb_xics_icp_out, wb_xics_ics_out,
wb_spiflash_out) wb_spiflash_out)
variable slave_io : slave_io_type; variable slave_io : slave_io_type;
@ -478,6 +516,8 @@ begin
slave_io := SLAVE_IO_SYSCON; slave_io := SLAVE_IO_SYSCON;
elsif std_match(match, x"C0002") then elsif std_match(match, x"C0002") then
slave_io := SLAVE_IO_UART; slave_io := SLAVE_IO_UART;
elsif std_match(match, x"C0003") then
slave_io := SLAVE_IO_UART1;
elsif std_match(match, x"C8---") then elsif std_match(match, x"C8---") then
slave_io := SLAVE_IO_EXTERNAL; slave_io := SLAVE_IO_EXTERNAL;
elsif std_match(match, x"C0004") then elsif std_match(match, x"C0004") then
@ -490,6 +530,8 @@ begin
slave_io_dbg <= slave_io; slave_io_dbg <= slave_io;
wb_uart0_in <= wb_sio_out; wb_uart0_in <= wb_sio_out;
wb_uart0_in.cyc <= '0'; 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 <= wb_sio_out;
wb_spiflash_in.cyc <= '0'; wb_spiflash_in.cyc <= '0';
wb_spiflash_is_reg <= '0'; wb_spiflash_is_reg <= '0';
@ -559,6 +601,9 @@ begin
when SLAVE_IO_ICS => when SLAVE_IO_ICS =>
wb_xics_ics_in.cyc <= wb_sio_out.cyc; wb_xics_ics_in.cyc <= wb_sio_out.cyc;
wb_sio_in <= wb_xics_ics_out; 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 => when SLAVE_IO_SPI_FLASH_MAP =>
-- Clear top bits so they don't make their way to the -- Clear top bits so they don't make their way to the
-- fash chip. -- fash chip.
@ -586,7 +631,9 @@ begin
CLK_FREQ => CLK_FREQ, CLK_FREQ => CLK_FREQ,
HAS_SPI_FLASH => HAS_SPI_FLASH, HAS_SPI_FLASH => HAS_SPI_FLASH,
SPI_FLASH_OFFSET => SPI_FLASH_OFFSET, 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( port map(
clk => system_clk, clk => system_clk,
@ -598,30 +645,115 @@ begin
soc_reset => open -- XXX TODO 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.dat <= x"000000" & uart0_dat8;
wb_uart0_out.stall <= not wb_uart0_out.ack; 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_gen: if HAS_SPI_FLASH generate
spiflash: entity work.spi_flash_ctrl spiflash: entity work.spi_flash_ctrl
generic map ( generic map (
@ -680,6 +812,7 @@ begin
int_level_in <= (others => '0'); int_level_in <= (others => '0');
int_level_in(0) <= uart0_irq; int_level_in(0) <= uart0_irq;
int_level_in(1) <= ext_irq_eth; int_level_in(1) <= ext_irq_eth;
int_level_in(2) <= uart1_irq;
end process; end process;


-- BRAM Memory slave -- BRAM Memory slave

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


architecture behaviour of syscon is architecture behaviour of syscon is
-- Register address bits -- 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) -- 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_SIG : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000000";
constant SYS_REG_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001"; 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) := "010"; 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) := "011"; 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) := "100"; 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) := "101"; 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) := "110"; 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) := "111"; 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 -- Muxed reg read signal
signal reg_out : std_ulogic_vector(63 downto 0); signal reg_out : std_ulogic_vector(63 downto 0);


-- INFO register bits -- INFO register bits
constant SYS_REG_INFO_HAS_UART : integer := 0; constant SYS_REG_INFO_HAS_UART : integer := 0; -- Has a UART (always set)
constant SYS_REG_INFO_HAS_DRAM : integer := 1; constant SYS_REG_INFO_HAS_DRAM : integer := 1; -- Has DRAM
constant SYS_REG_INFO_HAS_BRAM : integer := 2; constant SYS_REG_INFO_HAS_BRAM : integer := 2; -- Has "main" BRAM
constant SYS_REG_INFO_HAS_SPIF : integer := 3; constant SYS_REG_INFO_HAS_SPIF : integer := 3; -- Has SPI flash
constant SYS_REG_INFO_HAS_LETH : integer := 4; 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 -- BRAMINFO contains the BRAM size in the bottom 52 bits
-- DRAMINFO contains the DRAM size if any 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 -- reserved for the FPGA bitfile if any
constant SYS_REG_SPI_INFO_IS_FLASH : integer := 0; 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 -- Ctrl register
signal reg_ctrl : std_ulogic_vector(SYS_REG_CTRL_BITS-1 downto 0); signal reg_ctrl : std_ulogic_vector(SYS_REG_CTRL_BITS-1 downto 0);
signal reg_ctrl_out : std_ulogic_vector(63 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_dramiinfo : std_ulogic_vector(63 downto 0);
signal reg_clkinfo : 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_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_dram : std_ulogic;
signal info_has_bram : std_ulogic; signal info_has_bram : std_ulogic;
signal info_has_uart : std_ulogic; signal info_has_uart : std_ulogic;
signal info_has_spif : std_ulogic; signal info_has_spif : std_ulogic;
signal info_has_leth : 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_clk : std_ulogic_vector(39 downto 0);
signal info_fl_off : std_ulogic_vector(31 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 -- Wishbone response latch
signal wb_rsp : wb_io_slave_out; signal wb_rsp : wb_io_slave_out;
@ -110,12 +127,15 @@ begin
info_has_bram <= '1' when BRAM_SIZE /= 0 else '0'; info_has_bram <= '1' when BRAM_SIZE /= 0 else '0';
info_has_spif <= '1' when HAS_SPI_FLASH else '0'; info_has_spif <= '1' when HAS_SPI_FLASH else '0';
info_has_leth <= '1' when HAS_LITEETH 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)); info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40));
reg_info <= (SYS_REG_INFO_HAS_UART => info_has_uart, reg_info <= (SYS_REG_INFO_HAS_UART => info_has_uart,
SYS_REG_INFO_HAS_DRAM => info_has_dram, SYS_REG_INFO_HAS_DRAM => info_has_dram,
SYS_REG_INFO_HAS_BRAM => info_has_bram, SYS_REG_INFO_HAS_BRAM => info_has_bram,
SYS_REG_INFO_HAS_SPIF => info_has_spif, SYS_REG_INFO_HAS_SPIF => info_has_spif,
SYS_REG_INFO_HAS_LETH => info_has_leth, SYS_REG_INFO_HAS_LETH => info_has_leth,
SYS_REG_INFO_HAS_LSYS => '1',
SYS_REG_INFO_HAS_URT1 => info_has_urt1,
others => '0'); others => '0');


reg_braminfo <= x"000" & std_ulogic_vector(to_unsigned(BRAM_SIZE, 52)); 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', reg_ctrl_out <= (63 downto SYS_REG_CTRL_BITS => '0',
SYS_REG_CTRL_BITS-1 downto 0 => reg_ctrl); 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 -- Wishbone response
wb_rsp.ack <= wishbone_in.cyc and wishbone_in.stb; wb_rsp.ack <= wishbone_in.cyc and wishbone_in.stb;
with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select reg_out <= 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_clkinfo when SYS_REG_CLKINFO,
reg_ctrl_out when SYS_REG_CTRL, reg_ctrl_out when SYS_REG_CTRL,
reg_spiinfo when SYS_REG_SPIFLASHINFO, reg_spiinfo when SYS_REG_SPIFLASHINFO,
reg_uart0info when SYS_REG_UART0_INFO,
reg_uart1info when SYS_REG_UART1_INFO,
(others => '0') when others; (others => '0') when others;
wb_rsp.dat <= reg_out(63 downto 32) when wishbone_in.adr(2) = '1' else wb_rsp.dat <= reg_out(63 downto 32) when wishbone_in.adr(2) = '1' else
reg_out(31 downto 0); reg_out(31 downto 0);

Loading…
Cancel
Save