From c2577b5446e8f2d80bee28c7594df2a7d72569e6 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 24 Mar 2021 22:00:27 +1100 Subject: [PATCH] Add ASIC target Signed-off-by: Anton Blanchard --- Makefile | 32 ++++++-- asic/microwatt_asic-verilator.cpp | 83 +++++++++++++++++++ asic/top-asic.vhdl | 127 ++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 5 deletions(-) create mode 100644 asic/microwatt_asic-verilator.cpp create mode 100644 asic/top-asic.vhdl diff --git a/Makefile b/Makefile index 85a0fee..5856081 100644 --- a/Makefile +++ b/Makefile @@ -55,15 +55,18 @@ all = core_tb icache_tb dcache_tb dmi_dtm_tb \ all: $(all) -core_files = decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \ - utils.vhdl plru.vhdl cache_ram.vhdl icache.vhdl \ +base_core_files = decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \ + utils.vhdl plru.vhdl icache.vhdl \ decode1.vhdl helpers.vhdl insn_helpers.vhdl \ - control.vhdl decode2.vhdl register_file.vhdl \ + control.vhdl decode2.vhdl \ cr_file.vhdl crhelpers.vhdl ppc_fx_insns.vhdl rotator.vhdl \ - logical.vhdl countbits.vhdl multiply.vhdl divider.vhdl execute1.vhdl \ + logical.vhdl countbits.vhdl divider.vhdl execute1.vhdl \ loadstore1.vhdl mmu.vhdl dcache.vhdl writeback.vhdl core_debug.vhdl \ core.vhdl fpu.vhdl pmu.vhdl +core_files = $(base_core_files) register_file.vhdl cache_ram.vhdl multiply.vhdl +asic_core_files = $(base_core_files) asic/register_file.vhdl asic/cache_ram.vhdl asic/multiply.vhdl + soc_files = wishbone_arbiter.vhdl wishbone_bram_wrapper.vhdl sync_fifo.vhdl \ wishbone_debug_master.vhdl xics.vhdl syscon.vhdl gpio.vhdl soc.vhdl \ spi_rxtx.vhdl spi_flash_ctrl.vhdl @@ -218,7 +221,6 @@ GHDL_IMAGE_GENERICS=-gMEMORY_SIZE=$(MEMORY_SIZE) -gRAM_INIT_FILE=$(RAM_INIT_FILE -gRESET_LOW=$(RESET_LOW) -gCLK_INPUT=$(CLK_INPUT) -gCLK_FREQUENCY=$(CLK_FREQUENCY) -gICACHE_NUM_LINES=$(ICACHE_NUM_LINES) \ $(LITEDRAM_GHDL_ARG) - ifeq ($(FPGA_TARGET), verilator) RESET_LOW=true CLK_INPUT=50000000 @@ -226,22 +228,41 @@ CLK_FREQUENCY=50000000 clkgen=fpga/clk_gen_bypass.vhd endif +ifeq ($(FPGA_TARGET), caravel) +MEMORY_SIZE=4096 +RESET_LOW=true +CLK_INPUT=100000000 +CLK_FREQUENCY=100000000 +endif + fpga_files = fpga/soc_reset.vhdl \ fpga/pp_fifo.vhd fpga/pp_soc_uart.vhd fpga/main_bram.vhdl \ nonrandom.vhdl +asic_files = fpga/pp_fifo.vhd fpga/pp_soc_uart.vhd asic/main_bram.vhdl \ + asic/top-asic.vhdl $(dmi_dtm) nonrandom.vhdl + synth_files = $(core_files) $(soc_files) $(soc_extra_synth) $(fpga_files) $(clkgen) $(toplevel) $(dmi_dtm) +asic_synth_files = $(asic_core_files) $(soc_files) $(asic_files) + microwatt.json: $(synth_files) $(RAM_INIT_FILE) $(YOSYS) $(GHDLSYNTH) -p "ghdl --std=08 --no-formal $(GHDL_IMAGE_GENERICS) $(synth_files) -e toplevel; read_verilog $(uart_files) $(soc_extra_v); synth_ecp5 -abc9 -nowidelut -json $@ $(SYNTH_ECP5_FLAGS)" microwatt.v: $(synth_files) $(RAM_INIT_FILE) $(YOSYS) $(GHDLSYNTH) -p "ghdl --std=08 --no-formal $(GHDL_IMAGE_GENERICS) $(synth_files) -e toplevel; write_verilog $@" +microwatt_asic.v: $(asic_synth_files) + $(YOSYS) $(GHDLSYNTH) -p "ghdl --std=08 --no-formal $(GHDL_IMAGE_GENERICS) $(asic_synth_files) -e toplevel; write_verilog $@" + microwatt-verilator: microwatt.v verilator/microwatt-verilator.cpp verilator/uart-verilator.c $(VERILATOR) $(VERILATOR_FLAGS) -CFLAGS "$(VERILATOR_CFLAGS) -DCLK_FREQUENCY=$(CLK_FREQUENCY)" -Iuart16550 --assert --cc --exe --build $^ -o $@ -top-module toplevel @cp -f obj_dir/microwatt-verilator microwatt-verilator +microwatt_asic-verilator: microwatt_asic.v asic/microwatt_asic-verilator.cpp verilator/uart-verilator.c + $(VERILATOR) $(VERILATOR_FLAGS) -CFLAGS "$(VERILATOR_CFLAGS) -DCLK_FREQUENCY=$(CLK_FREQUENCY)" -Iuart16550 -Iasic/behavioural --assert --cc --exe --build $^ -o $@ -top-module toplevel + @cp -f obj_dir/microwatt_asic-verilator microwatt_asic-verilator + microwatt_out.config: microwatt.json $(LPF) $(NEXTPNR) --json $< --lpf $(LPF) --textcfg $@.tmp $(NEXTPNR_FLAGS) --package $(PACKAGE) mv -f $@.tmp $@ @@ -324,6 +345,7 @@ _clean: rm -f scripts/mw_debug/mw_debug rm -f microwatt.bin microwatt.json microwatt.svf microwatt_out.config rm -f microwatt.v microwatt-verilator + rm -f microwatt_asic.v microwatt_asic-verilator rm -rf obj_dir/ clean: _clean diff --git a/asic/microwatt_asic-verilator.cpp b/asic/microwatt_asic-verilator.cpp new file mode 100644 index 0000000..3c37f0a --- /dev/null +++ b/asic/microwatt_asic-verilator.cpp @@ -0,0 +1,83 @@ +#include +#include "Vtoplevel.h" +#include "verilated.h" +#include "verilated_vcd_c.h" + +/* + * Current simulation time + * This is a 64-bit integer to reduce wrap over issues and + * allow modulus. You can also use a double, if you wish. + */ +vluint64_t main_time = 0; + +/* + * Called by $time in Verilog + * converts to double, to match + * what SystemC does + */ +double sc_time_stamp(void) +{ + return main_time; +} + +#if VM_TRACE +VerilatedVcdC *tfp; +#endif + +void tick(Vtoplevel *top) +{ + top->ext_clk = 1; + top->eval(); +#if VM_TRACE + if (tfp) + tfp->dump((double) main_time); +#endif + main_time++; + + top->ext_clk = 0; + top->eval(); +#if VM_TRACE + if (tfp) + tfp->dump((double) main_time); +#endif + main_time++; +} + +void uart_tx(unsigned char tx); +unsigned char uart_rx(void); + +int main(int argc, char **argv) +{ + Verilated::commandArgs(argc, argv); + + // init top verilog instance + Vtoplevel* top = new Vtoplevel; + +#if VM_TRACE + // init trace dump + Verilated::traceEverOn(true); + tfp = new VerilatedVcdC; + top->trace(tfp, 99); + tfp->open("microwatt-verilator.vcd"); +#endif + + // Reset + top->ext_rst = 0; + for (unsigned long i = 0; i < 5; i++) + tick(top); + top->ext_rst = 1; + + while(!Verilated::gotFinish()) { + tick(top); + + uart_tx(top->uart0_txd); + top->uart0_rxd = uart_rx(); + } + +#if VM_TRACE + tfp->close(); + delete tfp; +#endif + + delete top; +} diff --git a/asic/top-asic.vhdl b/asic/top-asic.vhdl new file mode 100644 index 0000000..fd40e75 --- /dev/null +++ b/asic/top-asic.vhdl @@ -0,0 +1,127 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wishbone_types.all; + +entity toplevel is + generic ( + MEMORY_SIZE : integer := 8192; + RAM_INIT_FILE : string := "firmware.hex"; + RESET_LOW : boolean := true; + CLK_INPUT : positive := 100000000; + CLK_FREQUENCY : positive := 100000000; + HAS_FPU : boolean := true; + HAS_BTC : boolean := false; + NO_BRAM : boolean := false; + DISABLE_FLATTEN_CORE : boolean := false; + ALT_RESET_ADDRESS : std_logic_vector(63 downto 0) := (27 downto 0 => '0', others => '1'); + SPI_FLASH_OFFSET : integer := 0; + SPI_FLASH_DEF_CKDV : natural := 4; + SPI_FLASH_DEF_QUAD : boolean := false; + SPI_BOOT_CLOCKS : boolean := false; + LOG_LENGTH : natural := 0; + UART_IS_16550 : boolean := true; + HAS_UART1 : boolean := false; + ICACHE_NUM_LINES : natural := 4; + ICACHE_NUM_WAYS : natural := 1; + ICACHE_TLB_SIZE : natural := 4; + DCACHE_NUM_LINES : natural := 4; + DCACHE_NUM_WAYS : natural := 1; + DCACHE_TLB_SET_SIZE : natural := 2; + DCACHE_TLB_NUM_WAYS : natural := 2; + HAS_GPIO : boolean := true; + NGPIO : natural := 32 + ); + port( + ext_clk : in std_ulogic; + ext_rst : in std_ulogic; + + -- UART0 signals: + uart0_txd : out std_ulogic; + uart0_rxd : in std_ulogic; + + -- SPI + spi_flash_cs_n : out std_ulogic; + spi_flash_clk : out std_ulogic; + spi_flash_sdat_i : in std_ulogic_vector(3 downto 0); + spi_flash_sdat_o : out std_ulogic_vector(3 downto 0); + spi_flash_sdat_oe : out std_ulogic_vector(3 downto 0); + + -- GPIO + gpio_in : in std_ulogic_vector(NGPIO - 1 downto 0); + gpio_out : out std_ulogic_vector(NGPIO - 1 downto 0); + gpio_dir : out std_ulogic_vector(NGPIO - 1 downto 0); + + -- Add an I/O pin to select fetching from flash on reset + alt_reset : in std_ulogic + ); +end entity toplevel; + +architecture behaviour of toplevel is + -- reset signals + signal system_rst : std_ulogic; +begin + + system_rst <= not ext_rst when RESET_LOW else ext_rst; + + -- Main SoC + soc0: entity work.soc + generic map( + MEMORY_SIZE => MEMORY_SIZE, + RAM_INIT_FILE => RAM_INIT_FILE, + SIM => false, + CLK_FREQ => CLK_FREQUENCY, + HAS_FPU => HAS_FPU, + HAS_BTC => HAS_BTC, + HAS_DRAM => false, + DRAM_SIZE => 0, + DRAM_INIT_SIZE => 0, + DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE, + ALT_RESET_ADDRESS => ALT_RESET_ADDRESS, + HAS_SPI_FLASH => true, + 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_BOOT_CLOCKS => SPI_BOOT_CLOCKS, + LOG_LENGTH => LOG_LENGTH, + UART0_IS_16550 => UART_IS_16550, + HAS_UART1 => HAS_UART1, + HAS_GPIO => HAS_GPIO, + NGPIO => NGPIO, + ICACHE_NUM_LINES => ICACHE_NUM_LINES, + ICACHE_NUM_WAYS => ICACHE_NUM_WAYS, + ICACHE_TLB_SIZE => ICACHE_TLB_SIZE, + DCACHE_NUM_LINES => DCACHE_NUM_LINES, + DCACHE_NUM_WAYS => DCACHE_NUM_WAYS, + DCACHE_TLB_SET_SIZE => DCACHE_TLB_SET_SIZE, + DCACHE_TLB_NUM_WAYS => DCACHE_TLB_NUM_WAYS + ) + port map ( + -- System signals + system_clk => ext_clk, + rst => system_rst, + + -- UART signals + uart0_txd => uart0_txd, + uart0_rxd => uart0_rxd, + + -- SPI signals + spi_flash_sck => spi_flash_clk, + spi_flash_cs_n => spi_flash_cs_n, + spi_flash_sdat_o => spi_flash_sdat_o, + spi_flash_sdat_oe => spi_flash_sdat_oe, + spi_flash_sdat_i => spi_flash_sdat_i, + + -- GPIO signals + gpio_in => gpio_in, + gpio_out => gpio_out, + gpio_dir => gpio_dir, + + -- Reset PC to flash offset 0 (ie 0xf000000) + alt_reset => alt_reset + ); + +end architecture behaviour;