mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
Merge pull request #213 from ozbenh/uart16550
Add support for standard 16550 style UART
This commit is contained in:
commit
57604c1a6e
5
Makefile
5
Makefile
@ -55,8 +55,9 @@ soc_files = $(core_files) wishbone_arbiter.vhdl wishbone_bram_wrapper.vhdl sync_
|
||||
spi_rxtx.vhdl spi_flash_ctrl.vhdl
|
||||
|
||||
|
||||
soc_sim_files = $(soc_files) sim_console.vhdl sim_uart.vhdl sim_bram_helpers.vhdl \
|
||||
sim_bram.vhdl sim_jtag_socket.vhdl sim_jtag.vhdl dmi_dtm_xilinx.vhdl
|
||||
soc_sim_files = $(soc_files) sim_console.vhdl sim_pp_uart.vhdl sim_bram_helpers.vhdl \
|
||||
sim_bram.vhdl sim_jtag_socket.vhdl sim_jtag.vhdl dmi_dtm_xilinx.vhdl \
|
||||
sim_16550_uart.vhdl
|
||||
|
||||
soc_sim_c_files = sim_vhpi_c.c sim_bram_helpers_c.c sim_console_c.c \
|
||||
sim_jtag_socket_c.c
|
||||
|
||||
@ -27,6 +27,7 @@ package common is
|
||||
constant SPR_DSISR : spr_num_t := 18;
|
||||
constant SPR_DAR : spr_num_t := 19;
|
||||
constant SPR_TB : spr_num_t := 268;
|
||||
constant SPR_TBU : spr_num_t := 269;
|
||||
constant SPR_DEC : spr_num_t := 22;
|
||||
constant SPR_SRR0 : spr_num_t := 26;
|
||||
constant SPR_SRR1 : spr_num_t := 27;
|
||||
|
||||
@ -752,6 +752,9 @@ begin
|
||||
case decode_spr_num(e_in.insn) is
|
||||
when SPR_TB =>
|
||||
spr_val := ctrl.tb;
|
||||
when SPR_TBU =>
|
||||
spr_val(63 downto 32) := (others => '0');
|
||||
spr_val(31 downto 0) := ctrl.tb(63 downto 32);
|
||||
when SPR_DEC =>
|
||||
spr_val := ctrl.dec;
|
||||
when 724 => -- LOG_ADDR SPR
|
||||
|
||||
@ -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 := true
|
||||
);
|
||||
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 := true
|
||||
);
|
||||
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 := true;
|
||||
);
|
||||
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
|
||||
|
||||
Binary file not shown.
@ -7,7 +7,7 @@
|
||||
|
||||
int main(void)
|
||||
{
|
||||
potato_uart_init();
|
||||
console_init();
|
||||
|
||||
puts(HELLO_WORLD);
|
||||
|
||||
|
||||
Binary file not shown.
@ -514,73 +514,118 @@ e8010010ebc1fff0
|
||||
7c0803a6ebe1fff8
|
||||
3c4000014e800020
|
||||
7c0802a63842a000
|
||||
3fe2fffffbe1fff8
|
||||
f80100103bff7240
|
||||
48000051f821ffd1
|
||||
7fe3fb7860000000
|
||||
60000000480001d5
|
||||
7fe3fb787c641b78
|
||||
600000004800017d
|
||||
60000000480000ed
|
||||
480001295463063e
|
||||
f821ffe1f8010010
|
||||
60000000480001dd
|
||||
386373a83c62ffff
|
||||
6000000048000141
|
||||
600000004800002d
|
||||
480000a95463063e
|
||||
4bffffec60000000
|
||||
0100000000000000
|
||||
3c40000100000180
|
||||
3c40000100000080
|
||||
600000003842a000
|
||||
6000000039228000
|
||||
8929000039428008
|
||||
419e00302f890000
|
||||
39290014e92a0000
|
||||
7d204eaa7c0004ac
|
||||
4182ffec71290001
|
||||
7c0004ace86a0000
|
||||
5463063e7c601eaa
|
||||
e92a00004e800020
|
||||
7c0004ac39290010
|
||||
712900017d204eea
|
||||
e86a00004082ffec
|
||||
7c0004ac38630008
|
||||
4bffffd07c601eea
|
||||
0000000000000000
|
||||
3c40000100000000
|
||||
600000003842a000
|
||||
6000000039228000
|
||||
8929000039428008
|
||||
419e002c2f890000
|
||||
39290014e92a0000
|
||||
7d204eaa7c0004ac
|
||||
4182ffec71290020
|
||||
7c0004ace92a0000
|
||||
4e8000207c604faa
|
||||
39290010e92a0000
|
||||
7d204eea7c0004ac
|
||||
4082ffec71290008
|
||||
e94a00005469063e
|
||||
7d2057ea7c0004ac
|
||||
000000004e800020
|
||||
0000000000000000
|
||||
3842a0003c400001
|
||||
fbc1fff07c0802a6
|
||||
3bc3fffffbe1fff8
|
||||
f821ffd1f8010010
|
||||
2fbf00008ffe0001
|
||||
38210030409e0010
|
||||
4bfffe5c38600000
|
||||
409e000c2b9f000a
|
||||
4bffff413860000d
|
||||
4bffff397fe3fb78
|
||||
000000004bffffd0
|
||||
0000028001000000
|
||||
7d4348ae39200000
|
||||
409e000c2f8a0000
|
||||
4e8000207d234b78
|
||||
4bffffe839290001
|
||||
0000000000000000
|
||||
3c40000100000000
|
||||
3d20c0003842a000
|
||||
6129200060000000
|
||||
f922800079290020
|
||||
612900203d20c000
|
||||
7c0004ac79290020
|
||||
3d40001c7d204eea
|
||||
7d295392614a2000
|
||||
394a0018e9428000
|
||||
7c0004ac3929ffff
|
||||
7929002061290020
|
||||
7d204eea7c0004ac
|
||||
792906003d00c000
|
||||
7908002061080008
|
||||
7d0046ea7c0004ac
|
||||
3940000071080020
|
||||
3d40c00041820018
|
||||
794a0020614a0040
|
||||
7d4056ea7c0004ac
|
||||
600000003d00c000
|
||||
38e2800060000000
|
||||
7908002061082000
|
||||
3d00001cf9028008
|
||||
7d29439261082000
|
||||
79080fc37948f804
|
||||
3940000141820080
|
||||
6108200c3d00c000
|
||||
7908002099470000
|
||||
7c0004ac3940ff80
|
||||
e94280087d4047aa
|
||||
7d2057aa7c0004ac
|
||||
7929c202e9428008
|
||||
7c0004ac394a0004
|
||||
e92280087d2057aa
|
||||
3929000c39400003
|
||||
7d404faa7c0004ac
|
||||
39290010e9228008
|
||||
7d404faa7c0004ac
|
||||
39400007e9228008
|
||||
7c0004ac39290008
|
||||
4e8000207d404faa
|
||||
990700003d40c000
|
||||
614a20183929ffff
|
||||
7c0004ac794a0020
|
||||
4e8000207d2057ea
|
||||
0000000000000000
|
||||
3c40000100000000
|
||||
600000003842a000
|
||||
394000ffe9228000
|
||||
2ea4000039228000
|
||||
2f89000089290000
|
||||
e922800860000000
|
||||
41960024419e0030
|
||||
2fa3000039400002
|
||||
614a0001419e0008
|
||||
7c0004ac39290004
|
||||
4e8000207d404faa
|
||||
4bffffe039400000
|
||||
6063000241960008
|
||||
7c0004ac39290020
|
||||
4e8000207d404fea
|
||||
0000000000000000
|
||||
3c40000100000000
|
||||
600000003842a000
|
||||
39400000e9228000
|
||||
7c0004ac39290020
|
||||
4e8000207d404fea
|
||||
0000000000000000
|
||||
3c40000100000000
|
||||
600000003842a000
|
||||
39290010e9228000
|
||||
7d204eea7c0004ac
|
||||
4082ffe871290001
|
||||
38630008e8628000
|
||||
7c601eea7c0004ac
|
||||
4e8000205463063e
|
||||
0000000000000000
|
||||
3c40000100000000
|
||||
600000003842a000
|
||||
39290010e9228000
|
||||
7d204eea7c0004ac
|
||||
4082ffe871290008
|
||||
7c0004ace9228000
|
||||
4e8000207c604fea
|
||||
0000000000000000
|
||||
3c40000100000000
|
||||
7c0802a63842a000
|
||||
fbe1fff8fbc1fff0
|
||||
7c7f1b787fc32214
|
||||
f821ffd1f8010010
|
||||
409e000c7fbff040
|
||||
4bfffe0c38210030
|
||||
3bff0001887f0000
|
||||
4bffffe44bffff8d
|
||||
0100000000000000
|
||||
3920000000000280
|
||||
2f8a00007d4348ae
|
||||
7d234b78409e000c
|
||||
392900014e800020
|
||||
000000004bffffe8
|
||||
0000000000000000
|
||||
6f57206f6c6c6548
|
||||
0000000a0d646c72
|
||||
000000000a646c72
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
#include <stddef.h>
|
||||
|
||||
void potato_uart_init(void);
|
||||
void potato_uart_irq_en(void);
|
||||
void potato_uart_irq_dis(void);
|
||||
void console_init(void);
|
||||
void console_set_irq_en(bool rx_irq, bool tx_irq);
|
||||
int getchar(void);
|
||||
int putchar(int c);
|
||||
int puts(const char *str);
|
||||
|
||||
@ -37,6 +37,9 @@
|
||||
#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_INFO_HAS_ARTB (1ull << 7)
|
||||
#define SYS_REG_BRAMINFO 0x10
|
||||
#define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull
|
||||
#define SYS_REG_DRAMINFO 0x18
|
||||
@ -50,7 +53,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)
|
||||
|
||||
|
||||
/*
|
||||
@ -65,6 +70,59 @@
|
||||
#define POTATO_CONSOLE_STATUS_TX_FULL 0x08
|
||||
#define POTATO_CONSOLE_CLOCK_DIV 0x18
|
||||
#define POTATO_CONSOLE_IRQ_EN 0x20
|
||||
#define POTATO_CONSOLE_IRQ_RX 0x01
|
||||
#define POTATO_CONSOLE_IRQ_TX 0x02
|
||||
|
||||
/*
|
||||
* 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_IER_RDI 0x01
|
||||
#define UART_REG_IER_THRI 0x02
|
||||
#define UART_REG_IER_RLSI 0x04
|
||||
#define UART_REG_IER_MSI 0x08
|
||||
#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
|
||||
|
||||
138
lib/console.c
138
lib/console.c
@ -5,22 +5,29 @@
|
||||
#include "microwatt_soc.h"
|
||||
#include "io.h"
|
||||
|
||||
#define UART_FREQ 115200
|
||||
#define UART_BAUDS 115200
|
||||
|
||||
/*
|
||||
* Core UART functions to implement for a port
|
||||
*/
|
||||
|
||||
static uint64_t potato_uart_base;
|
||||
bool uart_is_std;
|
||||
|
||||
static uint64_t uart_base;
|
||||
|
||||
static unsigned long uart_divisor(unsigned long uart_freq, unsigned long bauds)
|
||||
{
|
||||
return uart_freq / (bauds * 16);
|
||||
}
|
||||
|
||||
static uint64_t potato_uart_reg_read(int offset)
|
||||
{
|
||||
return readq(potato_uart_base + offset);
|
||||
return readq(uart_base + offset);
|
||||
}
|
||||
|
||||
static void potato_uart_reg_write(int offset, uint64_t val)
|
||||
{
|
||||
writeq(val, potato_uart_base + offset);
|
||||
writeq(val, uart_base + offset);
|
||||
}
|
||||
|
||||
static int potato_uart_rx_empty(void)
|
||||
@ -65,45 +72,93 @@ static void potato_uart_write(char c)
|
||||
potato_uart_reg_write(POTATO_CONSOLE_TX, val);
|
||||
}
|
||||
|
||||
static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long uart_freq)
|
||||
static void potato_uart_init(uint64_t uart_freq)
|
||||
{
|
||||
return proc_freq / (uart_freq * 16) - 1;
|
||||
unsigned long div = uart_divisor(uart_freq, UART_BAUDS) - 1;
|
||||
potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, div);
|
||||
}
|
||||
|
||||
void potato_uart_init(void)
|
||||
static void potato_uart_set_irq_en(bool rx_irq, bool tx_irq)
|
||||
{
|
||||
uint64_t proc_freq;
|
||||
uint64_t en = 0;
|
||||
|
||||
potato_uart_base = UART_BASE;
|
||||
proc_freq = readq(SYSCON_BASE + SYS_REG_CLKINFO) & SYS_REG_CLKINFO_FREQ_MASK;
|
||||
|
||||
potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(proc_freq, UART_FREQ));
|
||||
if (rx_irq)
|
||||
en |= POTATO_CONSOLE_IRQ_RX;
|
||||
if (tx_irq)
|
||||
en |= POTATO_CONSOLE_IRQ_TX;
|
||||
potato_uart_reg_write(POTATO_CONSOLE_IRQ_EN, en);
|
||||
}
|
||||
|
||||
void potato_uart_irq_en(void)
|
||||
static bool std_uart_rx_empty(void)
|
||||
{
|
||||
potato_uart_reg_write(POTATO_CONSOLE_IRQ_EN, 0xff);
|
||||
return !(readb(uart_base + UART_REG_LSR) & UART_REG_LSR_DR);
|
||||
}
|
||||
|
||||
void potato_uart_irq_dis(void)
|
||||
static uint8_t std_uart_read(void)
|
||||
{
|
||||
potato_uart_reg_write(POTATO_CONSOLE_IRQ_EN, 0x00);
|
||||
return readb(uart_base + UART_REG_RX);
|
||||
}
|
||||
|
||||
static bool std_uart_tx_full(void)
|
||||
{
|
||||
return !(readb(uart_base + UART_REG_LSR) & UART_REG_LSR_THRE);
|
||||
}
|
||||
|
||||
static void std_uart_write(uint8_t c)
|
||||
{
|
||||
writeb(c, uart_base + UART_REG_TX);
|
||||
}
|
||||
|
||||
static void std_uart_set_irq_en(bool rx_irq, bool tx_irq)
|
||||
{
|
||||
uint8_t ier = 0;
|
||||
|
||||
if (tx_irq)
|
||||
ier |= UART_REG_IER_THRI;
|
||||
if (rx_irq)
|
||||
ier |= UART_REG_IER_RDI;
|
||||
writeb(ier, uart_base + UART_REG_IER);
|
||||
}
|
||||
|
||||
static void std_uart_init(uint64_t uart_freq)
|
||||
{
|
||||
unsigned long div = uart_divisor(uart_freq, UART_BAUDS);
|
||||
|
||||
writeb(UART_REG_LCR_DLAB, uart_base + UART_REG_LCR);
|
||||
writeb(div & 0xff, uart_base + UART_REG_DLL);
|
||||
writeb(div >> 8, uart_base + UART_REG_DLM);
|
||||
writeb(UART_REG_LCR_8BIT, uart_base + UART_REG_LCR);
|
||||
writeb(UART_REG_MCR_DTR |
|
||||
UART_REG_MCR_RTS, uart_base + UART_REG_MCR);
|
||||
writeb(UART_REG_FCR_EN_FIFO |
|
||||
UART_REG_FCR_CLR_RCVR |
|
||||
UART_REG_FCR_CLR_XMIT, uart_base + UART_REG_FCR);
|
||||
}
|
||||
|
||||
int getchar(void)
|
||||
{
|
||||
while (potato_uart_rx_empty())
|
||||
/* Do nothing */ ;
|
||||
|
||||
return potato_uart_read();
|
||||
if (uart_is_std) {
|
||||
while (std_uart_rx_empty())
|
||||
/* Do nothing */ ;
|
||||
return std_uart_read();
|
||||
} else {
|
||||
while (potato_uart_rx_empty())
|
||||
/* Do nothing */ ;
|
||||
return potato_uart_read();
|
||||
}
|
||||
}
|
||||
|
||||
int putchar(int c)
|
||||
{
|
||||
while (potato_uart_tx_full())
|
||||
/* Do Nothing */;
|
||||
|
||||
potato_uart_write(c);
|
||||
if (uart_is_std) {
|
||||
while(std_uart_tx_full())
|
||||
/* Do Nothing */;
|
||||
std_uart_write(c);
|
||||
} else {
|
||||
while (potato_uart_tx_full())
|
||||
/* Do Nothing */;
|
||||
potato_uart_write(c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -131,3 +186,38 @@ size_t strlen(const char *s)
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
void console_init(void)
|
||||
{
|
||||
uint64_t sys_info;
|
||||
uint64_t proc_freq;
|
||||
uint64_t uart_info = 0;
|
||||
uint64_t uart_freq = 0;
|
||||
|
||||
proc_freq = readq(SYSCON_BASE + SYS_REG_CLKINFO) & SYS_REG_CLKINFO_FREQ_MASK;
|
||||
sys_info = readq(SYSCON_BASE + SYS_REG_INFO);
|
||||
|
||||
if (sys_info & SYS_REG_INFO_HAS_LARGE_SYSCON) {
|
||||
uart_info = readq(SYSCON_BASE + SYS_REG_UART0_INFO);
|
||||
uart_freq = uart_info & 0xffffffff;
|
||||
}
|
||||
if (uart_freq == 0)
|
||||
uart_freq = proc_freq;
|
||||
|
||||
uart_base = UART_BASE;
|
||||
if (uart_info & SYS_REG_UART_IS_16550) {
|
||||
uart_is_std = true;
|
||||
std_uart_init(proc_freq);
|
||||
} else {
|
||||
uart_is_std = false;
|
||||
potato_uart_init(proc_freq);
|
||||
}
|
||||
}
|
||||
|
||||
void console_set_irq_en(bool rx_irq, bool tx_irq)
|
||||
{
|
||||
if (uart_is_std)
|
||||
std_uart_set_irq_en(rx_irq, tx_irq);
|
||||
else
|
||||
potato_uart_set_irq_en(rx_irq, tx_irq);
|
||||
}
|
||||
|
||||
@ -241,7 +241,7 @@ uint64_t main(void)
|
||||
bool try_flash = false;
|
||||
|
||||
/* Init the UART */
|
||||
potato_uart_init();
|
||||
console_init();
|
||||
|
||||
printf("\n\nWelcome to Microwatt !\n\n");
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
41119
micropython/firmware.hex
41119
micropython/firmware.hex
File diff suppressed because it is too large
Load Diff
@ -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 : true
|
||||
|
||||
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)
|
||||
|
||||
@ -25,7 +25,7 @@ void init_bss()
|
||||
int main(void)
|
||||
{
|
||||
init_bss();
|
||||
potato_uart_init();
|
||||
console_init();
|
||||
|
||||
puts(HELLO_WORLD);
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ sim_provides = {
|
||||
"dmi_dtm" : "dmi_dtm_xilinx.vhdl",
|
||||
"clock_generator" : "fpga/clk_gen_bypass.vhd",
|
||||
"main_bram" : "sim_bram.vhdl",
|
||||
"pp_soc_uart" : "sim_uart.vhdl"
|
||||
"pp_soc_uart" : "sim_pp_uart.vhdl"
|
||||
}
|
||||
|
||||
if synth:
|
||||
|
||||
421
sim_16550_uart.vhdl
Normal file
421
sim_16550_uart.vhdl
Normal file
@ -0,0 +1,421 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.sim_console.all;
|
||||
|
||||
entity uart_top is
|
||||
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 entity uart_top;
|
||||
|
||||
architecture behaviour of uart_top is
|
||||
|
||||
-- Call POLL every N clocks to generate interrupts
|
||||
constant POLL_DELAY : natural := 100;
|
||||
|
||||
-- Register definitions
|
||||
subtype reg_adr_t is std_ulogic_vector(2 downto 0);
|
||||
|
||||
constant REG_IDX_RXTX : reg_adr_t := "000";
|
||||
constant REG_IDX_IER : reg_adr_t := "001";
|
||||
constant REG_IDX_IIR_FCR : reg_adr_t := "010";
|
||||
constant REG_IDX_LCR : reg_adr_t := "011";
|
||||
constant REG_IDX_MCR : reg_adr_t := "100";
|
||||
constant REG_IDX_LSR : reg_adr_t := "101";
|
||||
constant REG_IDX_MSR : reg_adr_t := "110";
|
||||
constant REG_IDX_SCR : reg_adr_t := "111";
|
||||
|
||||
-- IER bits
|
||||
constant REG_IER_RDI_BIT : natural := 0;
|
||||
constant REG_IER_THRI_BIT : natural := 1;
|
||||
constant REG_IER_RLSI_BIT : natural := 2;
|
||||
constant REG_IER_MSI_BIT : natural := 3;
|
||||
|
||||
-- IIR bit
|
||||
constant REG_IIR_NO_INT : natural := 0;
|
||||
-- IIR values for bit 3 downto 0
|
||||
constant REG_IIR_RDI : std_ulogic_vector(3 downto 1) := "010";
|
||||
constant REG_IIR_THRI : std_ulogic_vector(3 downto 1) := "001";
|
||||
constant REG_IIR_RLSI : std_ulogic_vector(3 downto 1) := "011";
|
||||
constant REG_IIR_MSI : std_ulogic_vector(3 downto 1) := "000";
|
||||
|
||||
-- FCR bits
|
||||
constant REG_FCR_EN_FIFO_BIT : natural := 0; -- Always 1
|
||||
constant REG_FCR_CLR_RCVR_BIT : natural := 1;
|
||||
constant REG_FCR_CLR_XMIT_BIT : natural := 2;
|
||||
constant REG_FCR_DMA_SEL_BIT : natural := 3; -- Not implemented
|
||||
-- FCR values for FIFO threshold in bits 7 downto 6
|
||||
constant REG_FCR_FIFO_TRIG1 : std_ulogic_vector(7 downto 6) := "00";
|
||||
constant REG_FCR_FIFO_TRIG4 : std_ulogic_vector(7 downto 6) := "01";
|
||||
constant REG_FCR_FIFO_TRIG8 : std_ulogic_vector(7 downto 6) := "10";
|
||||
constant REG_FCR_FIFO_TRIG14 : std_ulogic_vector(7 downto 6) := "11";
|
||||
|
||||
-- LCR bits
|
||||
constant REG_LCR_STOP_BIT : natural := 2;
|
||||
constant REG_LCR_PARITY_BIT : natural := 3;
|
||||
constant REG_LCR_EPAR_BIT : natural := 4;
|
||||
constant REG_LCR_SPAR_BIT : natural := 5;
|
||||
constant REG_LCR_SBC_BIT : natural := 6;
|
||||
constant REG_LCR_DLAB_BIT : natural := 7;
|
||||
-- LCR values for data length (bits 1 downto 0)
|
||||
constant REG_LCR_WLEN5 : std_ulogic_vector(1 downto 0) := "00";
|
||||
constant REG_LCR_WLEN6 : std_ulogic_vector(1 downto 0) := "01";
|
||||
constant REG_LCR_WLEN7 : std_ulogic_vector(1 downto 0) := "10";
|
||||
constant REG_LCR_WLEN8 : std_ulogic_vector(1 downto 0) := "11";
|
||||
|
||||
-- MCR bits
|
||||
constant REG_MCR_DTR_BIT : natural := 0;
|
||||
constant REG_MCR_RTS_BIT : natural := 1;
|
||||
constant REG_MCR_OUT1_BIT : natural := 2;
|
||||
constant REG_MCR_OUT2_BIT : natural := 3;
|
||||
constant REG_MCR_LOOP_BIT : natural := 4;
|
||||
|
||||
-- LSR bits
|
||||
constant REG_LSR_DR_BIT : natural := 0;
|
||||
constant REG_LSR_OE_BIT : natural := 1;
|
||||
constant REG_LSR_PE_BIT : natural := 2;
|
||||
constant REG_LSR_FE_BIT : natural := 3;
|
||||
constant REG_LSR_BI_BIT : natural := 4;
|
||||
constant REG_LSR_THRE_BIT : natural := 5;
|
||||
constant REG_LSR_TEMT_BIT : natural := 6;
|
||||
constant REG_LSR_FIFOE_BIT : natural := 7;
|
||||
|
||||
-- MSR bits
|
||||
constant REG_MSR_DCTS_BIT : natural := 0;
|
||||
constant REG_MSR_DDSR_BIT : natural := 1;
|
||||
constant REG_MSR_TERI_BIT : natural := 2;
|
||||
constant REG_MSR_DDCD_BIT : natural := 3;
|
||||
constant REG_MSR_CTS_BIT : natural := 4;
|
||||
constant REG_MSR_DSR_BIT : natural := 5;
|
||||
constant REG_MSR_RI_BIT : natural := 6;
|
||||
constant REG_MSR_DCD_BIT : natural := 7;
|
||||
|
||||
-- Wishbone signals decode:
|
||||
signal reg_idx : reg_adr_t;
|
||||
signal wb_phase : std_ulogic;
|
||||
signal reg_write : std_ulogic;
|
||||
signal reg_read : std_ulogic;
|
||||
|
||||
-- Register storage
|
||||
signal reg_ier : std_ulogic_vector(3 downto 0);
|
||||
signal reg_iir : std_ulogic_vector(3 downto 0);
|
||||
signal reg_fcr : std_ulogic_vector(7 downto 6);
|
||||
signal reg_lcr : std_ulogic_vector(7 downto 0);
|
||||
signal reg_mcr : std_ulogic_vector(4 downto 0);
|
||||
signal reg_lsr : std_ulogic_vector(7 downto 0);
|
||||
signal reg_msr : std_ulogic_vector(7 downto 0);
|
||||
signal reg_scr : std_ulogic_vector(7 downto 0);
|
||||
|
||||
signal reg_div : std_ulogic_vector(15 downto 0);
|
||||
|
||||
-- Control signals
|
||||
signal rx_fifo_clr : std_ulogic;
|
||||
signal tx_fifo_clr : std_ulogic;
|
||||
|
||||
-- Pending interrupts
|
||||
signal int_rdi_pending : std_ulogic;
|
||||
signal int_thri_pending : std_ulogic;
|
||||
signal int_rlsi_pending : std_ulogic;
|
||||
signal int_msi_pending : std_ulogic;
|
||||
|
||||
-- Actual data output
|
||||
signal data_out : std_ulogic_vector(7 downto 0) := x"00";
|
||||
|
||||
-- Incoming data pending signal
|
||||
signal data_in_pending : std_ulogic := '0';
|
||||
|
||||
-- Useful aliases
|
||||
alias dlab : std_ulogic is reg_lcr(REG_LCR_DLAB_BIT);
|
||||
|
||||
alias clk : std_ulogic is wb_clk_i;
|
||||
alias rst : std_ulogic is wb_rst_i;
|
||||
alias cyc : std_ulogic is wb_cyc_i;
|
||||
alias stb : std_ulogic is wb_stb_i;
|
||||
alias we : std_ulogic is wb_we_i;
|
||||
begin
|
||||
|
||||
-- Register index shortcut
|
||||
reg_idx <= wb_adr_i(2 downto 0);
|
||||
|
||||
-- 2 phases WB process.
|
||||
--
|
||||
-- Among others, this gives us a "free" cycle for the
|
||||
-- side effects of some accesses percolate in the form
|
||||
-- of status bit changes in other registers.
|
||||
wb_cycle: process(clk)
|
||||
variable phase : std_ulogic := '0';
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if wb_phase = '0' then
|
||||
if cyc = '1' and stb = '1' then
|
||||
wb_ack_o <= '1';
|
||||
wb_phase <= '1';
|
||||
end if;
|
||||
else
|
||||
wb_ack_o <= '0';
|
||||
wb_phase <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Reg read/write signals
|
||||
reg_write <= cyc and stb and we and not wb_phase;
|
||||
reg_read <= cyc and stb and not we and not wb_phase;
|
||||
|
||||
-- Register read is synchronous to avoid collisions with
|
||||
-- read-clear side effects
|
||||
do_reg_read: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
wb_dat_o <= x"00";
|
||||
if reg_read = '1' then
|
||||
case reg_idx is
|
||||
when REG_IDX_RXTX =>
|
||||
if dlab = '1' then
|
||||
wb_dat_o <= reg_div(7 downto 0);
|
||||
else
|
||||
wb_dat_o <= data_out;
|
||||
end if;
|
||||
when REG_IDX_IER =>
|
||||
if dlab = '1' then
|
||||
wb_dat_o <= reg_div(15 downto 8);
|
||||
else
|
||||
wb_dat_o <= "0000" & reg_ier;
|
||||
end if;
|
||||
when REG_IDX_IIR_FCR =>
|
||||
-- Top bits always set as FIFO is always enabled
|
||||
wb_dat_o <= "1100" & reg_iir;
|
||||
when REG_IDX_LCR =>
|
||||
wb_dat_o <= reg_lcr;
|
||||
when REG_IDX_LSR =>
|
||||
wb_dat_o <= reg_lsr;
|
||||
when REG_IDX_MSR =>
|
||||
wb_dat_o <= reg_msr;
|
||||
when REG_IDX_SCR =>
|
||||
wb_dat_o <= reg_scr;
|
||||
when others =>
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Receive/send synchronous process
|
||||
rxtx: process(clk)
|
||||
variable dp : std_ulogic;
|
||||
variable poll_cnt : natural;
|
||||
variable sim_tmp : std_ulogic_vector(63 downto 0);
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '0' then
|
||||
dp := data_in_pending;
|
||||
if dlab = '0' and reg_idx = REG_IDX_RXTX then
|
||||
if reg_write = '1' then
|
||||
-- FIFO write
|
||||
-- XXX Simulate the FIFO and delays for more
|
||||
-- accurate behaviour & interrupts
|
||||
sim_console_write(x"00000000000000" & wb_dat_i);
|
||||
end if;
|
||||
if reg_read = '1' then
|
||||
dp := '0';
|
||||
data_out <= x"00";
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Poll for incoming data
|
||||
if poll_cnt = 0 or (reg_read = '1' and reg_idx = REG_IDX_LSR) then
|
||||
sim_console_poll(sim_tmp);
|
||||
poll_cnt := POLL_DELAY;
|
||||
if dp = '0' and sim_tmp(0) = '1' then
|
||||
dp := '1';
|
||||
sim_console_read(sim_tmp);
|
||||
data_out <= sim_tmp(7 downto 0);
|
||||
end if;
|
||||
poll_cnt := poll_cnt - 1;
|
||||
end if;
|
||||
data_in_pending <= dp;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Interrupt pending bits
|
||||
int_rdi_pending <= data_in_pending;
|
||||
int_thri_pending <= '1';
|
||||
int_rlsi_pending <= reg_lsr(REG_LSR_OE_BIT) or
|
||||
reg_lsr(REG_LSR_PE_BIT) or
|
||||
reg_lsr(REG_LSR_FE_BIT) or
|
||||
reg_lsr(REG_LSR_BI_BIT);
|
||||
int_msi_pending <= reg_msr(REG_MSR_DCTS_BIT) or
|
||||
reg_msr(REG_MSR_DDSR_BIT) or
|
||||
reg_msr(REG_MSR_TERI_BIT) or
|
||||
reg_msr(REG_MSR_DDCD_BIT);
|
||||
|
||||
-- Derive interrupt output from IIR
|
||||
int_o <= not reg_iir(REG_IIR_NO_INT);
|
||||
|
||||
-- Divisor register
|
||||
div_reg_w: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
reg_div <= (others => '0');
|
||||
elsif reg_write = '1' and dlab = '1' then
|
||||
if reg_idx = REG_IDX_RXTX then
|
||||
reg_div(7 downto 0) <= wb_dat_i;
|
||||
elsif reg_idx = REG_IDX_IER then
|
||||
reg_div(15 downto 8) <= wb_dat_i;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- IER register
|
||||
ier_reg_w: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
reg_ier <= "0000";
|
||||
else
|
||||
if reg_write = '1' and dlab = '0' and reg_idx = REG_IDX_IER then
|
||||
reg_ier <= wb_dat_i(3 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- IIR (read only) generation
|
||||
iir_reg_w: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
reg_iir <= "0001";
|
||||
if int_rlsi_pending = '1' and reg_ier(REG_IER_RLSI_BIT) = '1' then
|
||||
reg_iir <= REG_IIR_RLSI & "0";
|
||||
elsif int_rdi_pending = '1' and reg_ier(REG_IER_RDI_BIT) = '1' then
|
||||
reg_iir <= REG_IIR_RDI & "0";
|
||||
elsif int_thri_pending = '1' and reg_ier(REG_IER_THRI_BIT) = '1' then
|
||||
reg_iir <= REG_IIR_THRI & "0";
|
||||
elsif int_msi_pending = '1' and reg_ier(REG_IER_MSI_BIT) = '1' then
|
||||
reg_iir <= REG_IIR_MSI & "0";
|
||||
end if;
|
||||
|
||||
-- It *seems* like reading IIR should clear THRI for
|
||||
-- some amount of time until it gets set again a few
|
||||
-- clocks later if the transmitter is still empty. We
|
||||
-- don't do that at this point.
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- FCR (write only) register
|
||||
fcr_reg_w: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
reg_fcr <= "11";
|
||||
rx_fifo_clr <= '1';
|
||||
tx_fifo_clr <= '1';
|
||||
elsif reg_write = '1' and reg_idx = REG_IDX_IIR_FCR then
|
||||
reg_fcr <= wb_dat_i(7 downto 6);
|
||||
rx_fifo_clr <= wb_dat_i(REG_FCR_CLR_RCVR_BIT);
|
||||
tx_fifo_clr <= wb_dat_i(REG_FCR_CLR_XMIT_BIT);
|
||||
else
|
||||
rx_fifo_clr <= '0';
|
||||
tx_fifo_clr <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- LCR register
|
||||
lcr_reg_w: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
reg_lcr <= "00000011";
|
||||
elsif reg_write = '1' and reg_idx = REG_IDX_LCR then
|
||||
reg_lcr <= wb_dat_i;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- MCR register
|
||||
mcr_reg_w: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
reg_mcr <= "00000";
|
||||
elsif reg_write = '1' and reg_idx = REG_IDX_MCR then
|
||||
reg_mcr <= wb_dat_i(4 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- LSR register
|
||||
lsr_reg_w: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
reg_lsr <= "00000000";
|
||||
else
|
||||
reg_lsr(REG_LSR_DR_BIT) <= data_in_pending;
|
||||
|
||||
-- Clear error bits on read. Those bits are
|
||||
-- always 0 in sim for now.
|
||||
-- if reg_read = '1' and reg_idx = REG_IDX_LSR then
|
||||
-- reg_lsr(REG_LSR_OE_BIT) <= '0';
|
||||
-- reg_lsr(REG_LSR_PE_BIT) <= '0';
|
||||
-- reg_lsr(REG_LSR_FE_BIT) <= '0';
|
||||
-- reg_lsr(REG_LSR_BI_BIT) <= '0';
|
||||
-- reg_lsr(REG_LSR_FIFOE_BIT) <= '0';
|
||||
-- end if;
|
||||
|
||||
-- Tx FIFO empty indicators. Always empty in sim
|
||||
reg_lsr(REG_LSR_THRE_BIT) <= '1';
|
||||
reg_lsr(REG_LSR_TEMT_BIT) <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- MSR register
|
||||
msr_reg_w: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
reg_msr <= "00000000";
|
||||
elsif reg_read = '1' and reg_idx = REG_IDX_MSR then
|
||||
reg_msr <= "00000000";
|
||||
-- XXX TODO bit setting machine...
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- SCR register
|
||||
scr_reg_w: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
reg_scr <= "00000000";
|
||||
elsif reg_write = '1' and reg_idx = REG_IDX_SCR then
|
||||
reg_scr <= wb_dat_i;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture behaviour;
|
||||
@ -71,8 +71,11 @@ void sim_console_poll(unsigned char *__rt)
|
||||
ret = poll(fdset, 1, 0);
|
||||
//fprintf(stderr, "poll returns %d\n", ret);
|
||||
|
||||
if (ret == 1)
|
||||
val = 1;
|
||||
if (ret == 1) {
|
||||
if (fdset[0].revents & POLLIN)
|
||||
val = 1;
|
||||
// fprintf(stderr, "poll revents: 0x%x\n", fdset[0].revents);
|
||||
}
|
||||
|
||||
to_std_logic_vector(val, __rt, 64);
|
||||
}
|
||||
|
||||
179
soc.vhdl
179
soc.vhdl
@ -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 := true;
|
||||
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
|
||||
|
||||
63
syscon.vhdl
63
syscon.vhdl
@ -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,32 @@ 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
|
||||
constant SYS_REG_INFO_HAS_ARTB : integer := 7; -- Has architected TB frequency
|
||||
|
||||
-- BRAMINFO contains the BRAM size in the bottom 52 bits
|
||||
-- DRAMINFO contains the DRAM size if any in the bottom 52 bits
|
||||
@ -76,6 +83,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 +100,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 +128,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 +154,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 +175,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);
|
||||
|
||||
@ -25,7 +25,7 @@ int main(void)
|
||||
{
|
||||
int fail = 0;
|
||||
|
||||
potato_uart_init();
|
||||
console_init();
|
||||
|
||||
print_test_number(1);
|
||||
if (dec_test_1() != 0) {
|
||||
|
||||
@ -23,7 +23,7 @@ int main(void)
|
||||
{
|
||||
int fail = 0;
|
||||
|
||||
potato_uart_init();
|
||||
console_init();
|
||||
|
||||
print_test_number(1);
|
||||
if (ill_test_1() != 0) {
|
||||
|
||||
Binary file not shown.
@ -24,7 +24,7 @@ int main(void)
|
||||
{
|
||||
int fail = 0;
|
||||
|
||||
potato_uart_init();
|
||||
console_init();
|
||||
|
||||
print_test_number(1);
|
||||
if (test_addpcis_1() != 0) {
|
||||
|
||||
@ -661,7 +661,7 @@ void do_test(int num, int (*test)(void))
|
||||
|
||||
int main(void)
|
||||
{
|
||||
potato_uart_init();
|
||||
console_init();
|
||||
init_mmu();
|
||||
|
||||
do_test(1, mmu_test_1);
|
||||
|
||||
@ -228,7 +228,7 @@ void do_test(int num, int (*fn)(unsigned long))
|
||||
|
||||
int main(void)
|
||||
{
|
||||
potato_uart_init();
|
||||
console_init();
|
||||
init_mmu();
|
||||
map(0x2000, 0x2000, REF | CHG | PERM_RD | PERM_EX); /* map code page */
|
||||
map(0x7000, 0x7000, REF | CHG | PERM_RD | PERM_WR); /* map stack page */
|
||||
|
||||
@ -23,7 +23,7 @@ int main(void)
|
||||
{
|
||||
int fail = 0;
|
||||
|
||||
potato_uart_init();
|
||||
console_init();
|
||||
|
||||
print_test_number(1);
|
||||
if (sc_test_1() != 0) {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -83,7 +83,7 @@ void ipi_isr(void) {
|
||||
void uart_isr(void) {
|
||||
debug_puts(UART);
|
||||
|
||||
potato_uart_irq_dis(); // disable interrupt to ack it
|
||||
console_set_irq_en(false, false);
|
||||
|
||||
isrs_run |= ISR_UART;
|
||||
}
|
||||
@ -202,7 +202,7 @@ int xics_test_1(void)
|
||||
icp_write8(XICS_XIRR, 0x00); // mask all interrupts
|
||||
|
||||
// trigger two interrupts
|
||||
potato_uart_irq_en(); // cause serial interrupt
|
||||
console_set_irq_en(true,true);// cause serial interrupt
|
||||
ics_write_xive(0x6, 0); // set source to prio 6
|
||||
icp_write8(XICS_MFRR, 0x04); // cause ipi interrupt at prio 5
|
||||
|
||||
@ -222,7 +222,7 @@ int xics_test_1(void)
|
||||
|
||||
// cleanup
|
||||
icp_write8(XICS_XIRR, 0x00); // mask all interrupts
|
||||
potato_uart_irq_dis();
|
||||
console_set_irq_en(false, false);
|
||||
ics_write_xive(0, 0xff);
|
||||
isrs_run = 0;
|
||||
|
||||
@ -242,7 +242,7 @@ int xics_test_2(void)
|
||||
assert(isrs_run == 0);
|
||||
|
||||
// trigger both
|
||||
potato_uart_irq_en(); // cause 0x500 interrupt
|
||||
console_set_irq_en(true, true);
|
||||
icp_write8(XICS_MFRR, 0x05); // cause 0x500 interrupt
|
||||
|
||||
delay();
|
||||
@ -250,7 +250,7 @@ int xics_test_2(void)
|
||||
|
||||
// cleanup
|
||||
icp_write8(XICS_XIRR, 0x00); // mask all interrupts
|
||||
potato_uart_irq_dis();
|
||||
console_set_irq_en(false, false);
|
||||
isrs_run = 0;
|
||||
|
||||
return 0;
|
||||
@ -307,7 +307,7 @@ int main(void)
|
||||
int i = 0;
|
||||
int (*t)(void);
|
||||
|
||||
potato_uart_init();
|
||||
console_init();
|
||||
ipi_running = false;
|
||||
|
||||
/* run the tests */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user