OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sim/] [neorv32_tb.vhd] - Diff between revs 60 and 61

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 60 Rev 61
Line 34... Line 34...
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
-- # ********************************************************************************************* #
-- # ********************************************************************************************* #
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
-- #################################################################################################
-- #################################################################################################
 
 
 
library vunit_lib;
 
context vunit_lib.vunit_context;
 
context vunit_lib.com_context;
 
context vunit_lib.vc_context;
 
 
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use ieee.math_real.all;
 
 
library neorv32;
library neorv32;
use neorv32.neorv32_package.all;
use neorv32.neorv32_package.all;
use neorv32.neorv32_application_image.all; -- this file is generated by the image generator
use neorv32.neorv32_application_image.all; -- this file is generated by the image generator
use std.textio.all;
use std.textio.all;
 
 
 
library osvvm;
 
use osvvm.RandomPkg.all;
 
 
 
use work.uart_rx_pkg.all;
 
 
entity neorv32_tb is
entity neorv32_tb is
 
  generic (runner_cfg : string := runner_cfg_default;
 
           ci_mode : boolean := false);
end neorv32_tb;
end neorv32_tb;
 
 
architecture neorv32_tb_rtl of neorv32_tb is
architecture neorv32_tb_rtl of neorv32_tb is
 
 
  -- User Configuration ---------------------------------------------------------------------
  -- User Configuration ---------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- general --
  -- general --
  constant ext_imem_c            : boolean := false; -- false: use and boot from proc-internal IMEM, true: use and boot from external (initialized) simulated IMEM (ext. mem A)
  constant ext_imem_c            : boolean := false; -- false: use and boot from proc-internal IMEM, true: use and boot from external (initialized) simulated IMEM (ext. mem A)
  constant ext_dmem_c            : boolean := false; -- false: use proc-internal DMEM, true: use external simulated DMEM (ext. mem B)
  constant ext_dmem_c            : boolean := false; -- false: use proc-internal DMEM, true: use external simulated DMEM (ext. mem B)
  constant icache_en_c           : boolean := false; -- set true to use processor-internal instruction cache
 
  constant imem_size_c           : natural := 16*1024; -- size in bytes of processor-internal IMEM / external mem A
  constant imem_size_c           : natural := 16*1024; -- size in bytes of processor-internal IMEM / external mem A
  constant dmem_size_c           : natural := 8*1024; -- size in bytes of processor-internal DMEM / external mem B
  constant dmem_size_c           : natural := 8*1024; -- size in bytes of processor-internal DMEM / external mem B
  constant f_clock_c             : natural := 100000000; -- main clock in Hz
  constant f_clock_c             : natural := 100000000; -- main clock in Hz
  constant baud0_rate_c          : natural := 19200; -- simulation UART0 (primary UART) baud rate
  constant baud0_rate_c          : natural := 19200; -- simulation UART0 (primary UART) baud rate
  constant baud1_rate_c          : natural := 19200; -- simulation UART1 (secondary UART) baud rate
  constant baud1_rate_c          : natural := 19200; -- simulation UART1 (secondary UART) baud rate
Line 73... Line 84...
  -- simulated external Wishbone memory C (can be used to simulate external IO access) --
  -- simulated external Wishbone memory C (can be used to simulate external IO access) --
  constant ext_mem_c_base_addr_c : std_ulogic_vector(31 downto 0) := x"F0000000"; -- wishbone memory base address (default begin of EXTERNAL IO area)
  constant ext_mem_c_base_addr_c : std_ulogic_vector(31 downto 0) := x"F0000000"; -- wishbone memory base address (default begin of EXTERNAL IO area)
  constant ext_mem_c_size_c      : natural := 64; -- wishbone memory size in bytes
  constant ext_mem_c_size_c      : natural := 64; -- wishbone memory size in bytes
  constant ext_mem_c_latency_c   : natural := 3; -- latency in clock cycles (min 1, max 255), plus 1 cycle initial delay
  constant ext_mem_c_latency_c   : natural := 3; -- latency in clock cycles (min 1, max 255), plus 1 cycle initial delay
  -- simulation interrupt trigger --
  -- simulation interrupt trigger --
  constant irq_trigger_c         : std_ulogic_vector(31 downto 0) := x"FF000000";
  constant irq_trigger_base_addr_c : std_ulogic_vector(31 downto 0) := x"FF000000";
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
 
 
  -- internals - hands off! --
  -- internals - hands off! --
  constant int_imem_c       : boolean := not ext_imem_c;
  constant int_imem_c       : boolean := not ext_imem_c;
  constant int_dmem_c       : boolean := not ext_dmem_c;
  constant int_dmem_c       : boolean := not ext_dmem_c;
Line 86... Line 97...
  constant t_clock_c        : time := (1 sec) / f_clock_c;
  constant t_clock_c        : time := (1 sec) / f_clock_c;
 
 
  -- generators --
  -- generators --
  signal clk_gen, rst_gen : std_ulogic := '0';
  signal clk_gen, rst_gen : std_ulogic := '0';
 
 
  -- text.io --
  -- uart --
  file file_uart0_tx_out : text open write_mode is "neorv32.testbench_uart0.out";
 
  file file_uart1_tx_out : text open write_mode is "neorv32.testbench_uart1.out";
 
 
 
  -- simulation uart0 receiver --
 
  signal uart0_txd         : std_ulogic; -- local loop-back
  signal uart0_txd         : std_ulogic; -- local loop-back
  signal uart0_cts         : std_ulogic; -- local loop-back
  signal uart0_cts         : std_ulogic; -- local loop-back
  signal uart0_rx_sync     : std_ulogic_vector(04 downto 0) := (others => '1');
 
  signal uart0_rx_busy     : std_ulogic := '0';
 
  signal uart0_rx_sreg     : std_ulogic_vector(08 downto 0) := (others => '0');
 
  signal uart0_rx_baud_cnt : real;
 
  signal uart0_rx_bitcnt   : natural;
 
 
 
  -- simulation uart1 receiver --
 
  signal uart1_txd         : std_ulogic; -- local loop-back
  signal uart1_txd         : std_ulogic; -- local loop-back
  signal uart1_cts         : std_ulogic; -- local loop-back
  signal uart1_cts         : std_ulogic; -- local loop-back
  signal uart1_rx_sync     : std_ulogic_vector(04 downto 0) := (others => '1');
 
  signal uart1_rx_busy     : std_ulogic := '0';
 
  signal uart1_rx_sreg     : std_ulogic_vector(08 downto 0) := (others => '0');
 
  signal uart1_rx_baud_cnt : real;
 
  signal uart1_rx_bitcnt   : natural;
 
 
 
  -- gpio --
  -- gpio --
  signal gpio : std_ulogic_vector(31 downto 0);
  signal gpio : std_ulogic_vector(63 downto 0);
 
 
  -- twi --
  -- twi --
  signal twi_scl, twi_sda : std_logic;
  signal twi_scl, twi_sda : std_logic;
 
 
  -- spi --
  -- spi --
  signal spi_data : std_ulogic;
  signal spi_data : std_ulogic;
 
 
  -- irq --
  -- irq --
  signal msi_ring, mei_ring, nmi_ring : std_ulogic;
  signal msi_ring, mei_ring, nmi_ring : std_ulogic;
  signal soc_firq_ring : std_ulogic_vector(5 downto 0);
 
 
 
  -- Wishbone bus --
  -- Wishbone bus --
  type wishbone_t is record
  type wishbone_t is record
    addr  : std_ulogic_vector(31 downto 0); -- address
    addr  : std_ulogic_vector(31 downto 0); -- address
    wdata : std_ulogic_vector(31 downto 0); -- master write data
    wdata : std_ulogic_vector(31 downto 0); -- master write data
Line 137... Line 131...
    tag   : std_ulogic_vector(02 downto 0); -- request tag
    tag   : std_ulogic_vector(02 downto 0); -- request tag
    lock  : std_ulogic; -- exclusive access request
    lock  : std_ulogic; -- exclusive access request
  end record;
  end record;
  signal wb_cpu, wb_mem_a, wb_mem_b, wb_mem_c, wb_irq : wishbone_t;
  signal wb_cpu, wb_mem_a, wb_mem_b, wb_mem_c, wb_irq : wishbone_t;
 
 
  -- Wishbone memories --
  -- Wishbone access latency type --
  type ext_mem_a_ram_t is array (0 to ext_mem_a_size_c/4-1) of std_ulogic_vector(31 downto 0);
 
  type ext_mem_b_ram_t is array (0 to ext_mem_b_size_c/4-1) of std_ulogic_vector(31 downto 0);
 
  type ext_mem_c_ram_t is array (0 to ext_mem_c_size_c/4-1) of std_ulogic_vector(31 downto 0);
 
  type ext_mem_read_latency_t is array (0 to 255) of std_ulogic_vector(31 downto 0);
  type ext_mem_read_latency_t is array (0 to 255) of std_ulogic_vector(31 downto 0);
 
 
  -- exclusive access / reservation --
  -- exclusive access / reservation --
  signal ext_mem_c_atomic_reservation : std_ulogic := '0';
  signal ext_mem_c_atomic_reservation : std_ulogic := '0';
 
 
  -- init function --
  -- simulated external memory c (IO) --
  -- impure function: returns NOT the same result every time it is evaluated with the same arguments since the source file might have changed
  signal ext_ram_c : mem32_t(0 to ext_mem_c_size_c/4-1); -- uninitialized, used to simulate external IO
  impure function init_wbmem(init : application_init_image_t) return ext_mem_a_ram_t is
 
    variable mem_v : ext_mem_a_ram_t;
 
  begin
 
    mem_v := (others => (others => '0'));
 
    for i in 0 to init'length-1 loop -- init only in range of source data array
 
      if (xbus_big_endian_c = false) then
 
        mem_v(i) := init(i);
 
      else
 
        mem_v(i) := bswap32_f(init(i));
 
      end if;
 
    end loop; -- i
 
    return mem_v;
 
  end function init_wbmem;
 
 
 
  -- external memory components --
 
  signal ext_ram_a : ext_mem_a_ram_t := init_wbmem(application_init_image); -- initialized, used to simulate external IMEM
 
  signal ext_ram_b : ext_mem_b_ram_t := (others => (others => '0')); -- zero, used to simulate external DMEM
 
  signal ext_ram_c : ext_mem_c_ram_t; -- uninitialized, used to simulate external IO
 
 
 
 
  -- simulated external memory bus feedback type --
  type ext_mem_t is record
  type ext_mem_t is record
    rdata  : ext_mem_read_latency_t;
    rdata  : ext_mem_read_latency_t;
    acc_en : std_ulogic;
    acc_en : std_ulogic;
    ack    : std_ulogic_vector(ext_mem_a_latency_c-1 downto 0);
    ack    : std_ulogic_vector(ext_mem_a_latency_c-1 downto 0);
  end record;
  end record;
  signal ext_mem_a, ext_mem_b, ext_mem_c : ext_mem_t;
  signal ext_mem_a, ext_mem_b, ext_mem_c : ext_mem_t;
 
 
 
  -- stream link interface - local echo --
 
  signal slink_dat : sdata_8x32_t;
 
  signal slink_val : std_ulogic_vector(7 downto 0);
 
  signal slink_rdy : std_ulogic_vector(7 downto 0);
 
 
 
  signal slink_transmitter_dat, slink_receiver_dat : sdata_8x32_t;
 
  signal slink_transmitter_val, slink_receiver_val : std_ulogic_vector(7 downto 0);
 
  signal slink_transmitter_rdy, slink_receiver_rdy : std_ulogic_vector(7 downto 0);
 
 
 
  constant uart0_rx_logger : logger_t := get_logger("UART0.RX");
 
  constant uart1_rx_logger : logger_t := get_logger("UART1.RX");
 
  constant uart0_rx_handle : uart_rx_t := new_uart_rx(uart0_baud_val_c, uart0_rx_logger);
 
  constant uart1_rx_handle : uart_rx_t := new_uart_rx(uart1_baud_val_c, uart1_rx_logger);
 
 
 
  type axi_stream_master_vec_t is array(integer range <>) of axi_stream_master_t;
 
  type axi_stream_slave_vec_t is array(integer range <>) of axi_stream_slave_t;
 
 
 
  impure function init_slink_transmitters return axi_stream_master_vec_t is
 
    variable result : axi_stream_master_vec_t(slink_transmitter_val'range);
begin
begin
 
    for idx in result'range loop
 
      result(idx) := new_axi_stream_master(
 
        data_length => slink_transmitter_dat(idx)'length,
 
        stall_config => new_stall_config(0.05, 1, 10)
 
      );
 
    end loop;
 
 
 
    return result;
 
  end;
 
 
 
  impure function init_slink_receivers return axi_stream_slave_vec_t is
 
    variable result : axi_stream_slave_vec_t(slink_receiver_val'range);
 
  begin
 
    for idx in result'range loop
 
      result(idx) := new_axi_stream_slave(
 
        data_length => slink_receiver_dat(idx)'length,
 
        stall_config => new_stall_config(0.05, 1, 10)
 
      );
 
    end loop;
 
 
 
    return result;
 
  end;
 
 
 
  constant slink_transmitters : axi_stream_master_vec_t := init_slink_transmitters;
 
  constant slink_receivers : axi_stream_slave_vec_t := init_slink_receivers;
 
 
 
begin
 
  test_runner : process
 
    variable msg : msg_t;
 
    variable rnd : RandomPType;
 
    variable value : std_logic_vector(slink_transmitter_dat(0)'range);
 
  begin
 
    test_runner_setup(runner, runner_cfg);
 
 
 
    rnd.InitSeed(test_runner'path_name);
 
 
 
    -- Show passing checks for UART0 on the display (stdout)
 
    show(uart0_rx_logger, display_handler, pass);
 
    show(uart1_rx_logger, display_handler, pass);
 
 
 
    if ci_mode then
 
      check_uart(net, uart0_rx_handle, nul & nul);
 
    else
 
      check_uart(net, uart0_rx_handle, "Blinking LED demo program" & cr & lf);
 
    end if;
 
 
 
    if ci_mode then
 
      -- No need to send the full expectation in one big chunk
 
      check_uart(net, uart1_rx_handle, nul & nul);
 
      check_uart(net, uart1_rx_handle, "0/45" & cr & lf);
 
    end if;
 
 
 
    -- Apply some random data on each SLINK inputs and expect it to
 
    -- be echoed by the CPU. No blocking. Let the SLINK transmitters
 
    -- and receivers do this work in parallel.
 
    for idx in slink_transmitters'range loop
 
      for iter in 1 to 100 loop
 
        value := rnd.RandSlv(value'length);
 
 
 
        -- SLINK is AXI Stream compatible so the SLINK transmitters and
 
        -- and receivers are AXI Stream master and slave verification components (VCs).
 
        -- The full-featured AXI Stream verification component interface (VCI) is used
 
        -- but the AXI stream VCs also implements the basic stream VCI which also works
 
        -- for simple transactions like these. To use that interface for pushing data
 
        -- the AXI Steam VC must be "cast" to a basic stream VC using "as_stream"
 
        --
 
        -- push_stream(net, as_stream(slink_transmitters(idx)), value);
 
 
 
        push_axi_stream(net, slink_transmitters(idx), value);
 
        check_axi_stream(net, slink_receivers(idx), value, blocking => false);
 
      end loop;
 
    end loop;
 
 
 
    -- Wait until all expected data has been received
 
    --
 
    -- wait_until_idle can take the VC actor as argument but
 
    -- the more abstract view is that wait_until_idle is part
 
    -- of the sync VCI and to use it a VC must be cast
 
    -- to a sync VC
 
    wait_until_idle(net, as_sync(uart0_rx_handle));
 
    wait_until_idle(net, as_sync(uart1_rx_handle));
 
    for idx in slink_receivers'range loop
 
      wait_until_idle(net, as_sync(slink_receivers(idx)));
 
    end loop;
 
 
 
    -- Wait a bit more if some extra unexpected data is produced. If so,
 
    -- uart_rx will fail
 
    wait for (20 * 1e9 / baud0_rate_c) * ns;
 
 
 
    test_runner_cleanup(runner);
 
  end process;
 
 
 
  -- In case we get stuck waiting there is a watchdog timeout to terminate and fail the
 
  -- testbench
 
  test_runner_watchdog(runner, 50 ms);
 
 
  -- Clock/Reset Generator ------------------------------------------------------------------
  -- Clock/Reset Generator ------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  clk_gen <= not clk_gen after (t_clock_c/2);
  clk_gen <= not clk_gen after (t_clock_c/2);
  rst_gen <= '0', '1' after 60*(t_clock_c/2);
  rst_gen <= '0', '1' after 60*(t_clock_c/2);
Line 188... Line 276...
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  neorv32_top_inst: neorv32_top
  neorv32_top_inst: neorv32_top
  generic map (
  generic map (
    -- General --
    -- General --
    CLOCK_FREQUENCY              => f_clock_c,     -- clock frequency of clk_i in Hz
    CLOCK_FREQUENCY              => f_clock_c,     -- clock frequency of clk_i in Hz
    BOOTLOADER_EN                => false,         -- implement processor-internal bootloader?
 
    USER_CODE                    => x"12345678",   -- custom user code
    USER_CODE                    => x"12345678",   -- custom user code
    HW_THREAD_ID                 => 0,             -- hardware thread id (hartid) (32-bit)
    HW_THREAD_ID                 => 0,             -- hardware thread id (hartid) (32-bit)
 
    INT_BOOTLOADER_EN            => false,         -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
    -- On-Chip Debugger (OCD) --
    -- On-Chip Debugger (OCD) --
    ON_CHIP_DEBUGGER_EN          => true,          -- implement on-chip debugger
    ON_CHIP_DEBUGGER_EN          => true,          -- implement on-chip debugger
    -- RISC-V CPU Extensions --
    -- RISC-V CPU Extensions --
    CPU_EXTENSION_RISCV_A        => true,          -- implement atomic extension?
    CPU_EXTENSION_RISCV_A        => true,          -- implement atomic extension?
    CPU_EXTENSION_RISCV_C        => true,          -- implement compressed extension?
    CPU_EXTENSION_RISCV_C        => true,          -- implement compressed extension?
Line 205... Line 293...
    CPU_EXTENSION_RISCV_Zicsr    => true,          -- implement CSR system?
    CPU_EXTENSION_RISCV_Zicsr    => true,          -- implement CSR system?
    CPU_EXTENSION_RISCV_Zifencei => true,          -- implement instruction stream sync.?
    CPU_EXTENSION_RISCV_Zifencei => true,          -- implement instruction stream sync.?
    -- Extension Options --
    -- Extension Options --
    FAST_MUL_EN                  => false,         -- use DSPs for M extension's multiplier
    FAST_MUL_EN                  => false,         -- use DSPs for M extension's multiplier
    FAST_SHIFT_EN                => false,         -- use barrel shifter for shift operations
    FAST_SHIFT_EN                => false,         -- use barrel shifter for shift operations
    TINY_SHIFT_EN                => false,         -- use tiny (single-bit) shifter for shift operations
 
    CPU_CNT_WIDTH                => 64,            -- total width of CPU cycle and instret counters (0..64)
    CPU_CNT_WIDTH                => 64,            -- total width of CPU cycle and instret counters (0..64)
    -- Physical Memory Protection (PMP) --
    -- Physical Memory Protection (PMP) --
    PMP_NUM_REGIONS              => 5,             -- number of regions (0..64)
    PMP_NUM_REGIONS              => 5,             -- number of regions (0..64)
    PMP_MIN_GRANULARITY          => 64*1024,       -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
    PMP_MIN_GRANULARITY          => 64*1024,       -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
    -- Hardware Performance Monitors (HPM) --
    -- Hardware Performance Monitors (HPM) --
    HPM_NUM_CNTS                 => 12,            -- number of implemented HPM counters (0..29)
    HPM_NUM_CNTS                 => 12,            -- number of implemented HPM counters (0..29)
    HPM_CNT_WIDTH                => 40,            -- total size of HPM counters (0..64)
    HPM_CNT_WIDTH                => 40,            -- total size of HPM counters (0..64)
    -- Internal Instruction memory --
    -- Internal Instruction memory --
    MEM_INT_IMEM_EN              => int_imem_c ,   -- implement processor-internal instruction memory
    MEM_INT_IMEM_EN              => int_imem_c ,   -- implement processor-internal instruction memory
    MEM_INT_IMEM_SIZE            => imem_size_c,   -- size of processor-internal instruction memory in bytes
    MEM_INT_IMEM_SIZE            => imem_size_c,   -- size of processor-internal instruction memory in bytes
    MEM_INT_IMEM_ROM             => false,         -- implement processor-internal instruction memory as ROM
 
    -- Internal Data memory --
    -- Internal Data memory --
    MEM_INT_DMEM_EN              => int_dmem_c,    -- implement processor-internal data memory
    MEM_INT_DMEM_EN              => int_dmem_c,    -- implement processor-internal data memory
    MEM_INT_DMEM_SIZE            => dmem_size_c,   -- size of processor-internal data memory in bytes
    MEM_INT_DMEM_SIZE            => dmem_size_c,   -- size of processor-internal data memory in bytes
    -- Internal Cache memory --
    -- Internal Cache memory --
    ICACHE_EN                    => icache_en_c,   -- implement instruction cache
    ICACHE_EN                    => true,          -- implement instruction cache
    ICACHE_NUM_BLOCKS            => 8,             -- i-cache: number of blocks (min 2), has to be a power of 2
    ICACHE_NUM_BLOCKS            => 8,             -- i-cache: number of blocks (min 2), has to be a power of 2
    ICACHE_BLOCK_SIZE            => 64,            -- i-cache: block size in bytes (min 4), has to be a power of 2
    ICACHE_BLOCK_SIZE            => 64,            -- i-cache: block size in bytes (min 4), has to be a power of 2
    ICACHE_ASSOCIATIVITY         => 2,             -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
    ICACHE_ASSOCIATIVITY         => 2,             -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
    -- External memory interface --
    -- External memory interface --
    MEM_EXT_EN                   => true,          -- implement external memory bus interface?
    MEM_EXT_EN                   => true,          -- implement external memory bus interface?
    MEM_EXT_TIMEOUT              => 255,           -- cycles after a pending bus access auto-terminates (0 = disabled)
    MEM_EXT_TIMEOUT              => 255,           -- cycles after a pending bus access auto-terminates (0 = disabled)
 
    -- Stream link interface --
 
    SLINK_NUM_TX                 => 8,             -- number of TX links (0..8)
 
    SLINK_NUM_RX                 => 8,             -- number of TX links (0..8)
 
    SLINK_TX_FIFO                => 4,             -- TX fifo depth, has to be a power of two
 
    SLINK_RX_FIFO                => 1,             -- RX fifo depth, has to be a power of two
 
    -- External Interrupts Controller (XIRQ) --
 
    XIRQ_NUM_CH                  => 32,            -- number of external IRQ channels (0..32)
 
    XIRQ_TRIGGER_TYPE            => (others => '1'), -- trigger type: 0=level, 1=edge
 
    XIRQ_TRIGGER_POLARITY        => (others => '1'), -- trigger polarity: 0=low-level/falling-edge, 1=high-level/rising-edge 
    -- Processor peripherals --
    -- Processor peripherals --
    IO_GPIO_EN                   => true,          -- implement general purpose input/output port unit (GPIO)?
    IO_GPIO_EN                   => true,          -- implement general purpose input/output port unit (GPIO)?
    IO_MTIME_EN                  => true,          -- implement machine system timer (MTIME)?
    IO_MTIME_EN                  => true,          -- implement machine system timer (MTIME)?
    IO_UART0_EN                  => true,          -- implement primary universal asynchronous receiver/transmitter (UART0)?
    IO_UART0_EN                  => true,          -- implement primary universal asynchronous receiver/transmitter (UART0)?
    IO_UART1_EN                  => true,          -- implement secondary universal asynchronous receiver/transmitter (UART1)?
    IO_UART1_EN                  => true,          -- implement secondary universal asynchronous receiver/transmitter (UART1)?
Line 242... Line 337...
    IO_TRNG_EN                   => false,         -- trng cannot be simulated
    IO_TRNG_EN                   => false,         -- trng cannot be simulated
    IO_CFS_EN                    => true,          -- implement custom functions subsystem (CFS)?
    IO_CFS_EN                    => true,          -- implement custom functions subsystem (CFS)?
    IO_CFS_CONFIG                => (others => '0'), -- custom CFS configuration generic
    IO_CFS_CONFIG                => (others => '0'), -- custom CFS configuration generic
    IO_CFS_IN_SIZE               => 32,            -- size of CFS input conduit in bits
    IO_CFS_IN_SIZE               => 32,            -- size of CFS input conduit in bits
    IO_CFS_OUT_SIZE              => 32,            -- size of CFS output conduit in bits
    IO_CFS_OUT_SIZE              => 32,            -- size of CFS output conduit in bits
    IO_NCO_EN                    => true,          -- implement numerically-controlled oscillator (NCO)?
 
    IO_NEOLED_EN                 => true           -- implement NeoPixel-compatible smart LED interface (NEOLED)?
    IO_NEOLED_EN                 => true           -- implement NeoPixel-compatible smart LED interface (NEOLED)?
  )
  )
  port map (
  port map (
    -- Global control --
    -- Global control --
    clk_i       => clk_gen,         -- global clock, rising edge
    clk_i       => clk_gen,         -- global clock, rising edge
Line 270... Line 364...
    wb_ack_i    => wb_cpu.ack,      -- transfer acknowledge
    wb_ack_i    => wb_cpu.ack,      -- transfer acknowledge
    wb_err_i    => wb_cpu.err,      -- transfer error
    wb_err_i    => wb_cpu.err,      -- transfer error
    -- Advanced memory control signals (available if MEM_EXT_EN = true) --
    -- Advanced memory control signals (available if MEM_EXT_EN = true) --
    fence_o     => open,            -- indicates an executed FENCE operation
    fence_o     => open,            -- indicates an executed FENCE operation
    fencei_o    => open,            -- indicates an executed FENCEI operation
    fencei_o    => open,            -- indicates an executed FENCEI operation
 
    -- TX stream interfaces (available if SLINK_NUM_TX > 0) --
 
    slink_tx_dat_o => slink_dat,       -- output data
 
    slink_tx_val_o => slink_val,       -- valid output
 
    slink_tx_rdy_i => slink_rdy,       -- ready to send
 
    -- RX stream interfaces (available if SLINK_NUM_RX > 0) --
 
    slink_rx_dat_i => slink_dat,       -- input data
 
    slink_rx_val_i => slink_val,       -- valid input
 
    slink_rx_rdy_o => slink_rdy,       -- ready to receive
    -- GPIO (available if IO_GPIO_EN = true) --
    -- GPIO (available if IO_GPIO_EN = true) --
    gpio_o      => gpio,            -- parallel output
    gpio_o      => gpio,            -- parallel output
    gpio_i      => gpio,            -- parallel input
    gpio_i      => gpio,            -- parallel input
    -- primary UART0 (available if IO_UART0_EN = true) --
    -- primary UART0 (available if IO_UART0_EN = true) --
    uart0_txd_o => uart0_txd,       -- UART0 send data
    uart0_txd_o => uart0_txd,       -- UART0 send data
Line 296... Line 398...
    -- PWM (available if IO_PWM_NUM_CH > 0) --
    -- PWM (available if IO_PWM_NUM_CH > 0) --
    pwm_o       => open,            -- pwm channels
    pwm_o       => open,            -- pwm channels
    -- Custom Functions Subsystem IO --
    -- Custom Functions Subsystem IO --
    cfs_in_i    => (others => '0'), -- custom CFS inputs
    cfs_in_i    => (others => '0'), -- custom CFS inputs
    cfs_out_o   => open,            -- custom CFS outputs
    cfs_out_o   => open,            -- custom CFS outputs
    -- NCO output (available if IO_NCO_EN = true) --
 
    nco_o       => open,            -- numerically-controlled oscillator channels
 
    -- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
    -- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
    neoled_o    => open,            -- async serial data line
    neoled_o    => open,            -- async serial data line
    -- System time --
    -- System time --
    mtime_i     => (others => '0'), -- current system time from ext. MTIME (if IO_MTIME_EN = false)
    mtime_i     => (others => '0'), -- current system time from ext. MTIME (if IO_MTIME_EN = false)
    mtime_o     => open,            -- current system time from int. MTIME (if IO_MTIME_EN = true)
    mtime_o     => open,            -- current system time from int. MTIME (if IO_MTIME_EN = true)
    -- Interrupts --
    -- External platform interrupts (available if XIRQ_NUM_CH > 0) --
 
    xirq_i         => gpio(31 downto 0), -- IRQ channels
 
    -- CPU Interrupts --
    nm_irq_i    => nmi_ring,        -- non-maskable interrupt
    nm_irq_i    => nmi_ring,        -- non-maskable interrupt
    soc_firq_i  => soc_firq_ring,   -- fast interrupt channels
 
    mtime_irq_i => '0',             -- machine software interrupt, available if IO_MTIME_EN = false
    mtime_irq_i => '0',             -- machine software interrupt, available if IO_MTIME_EN = false
    msw_irq_i   => msi_ring,        -- machine software interrupt
    msw_irq_i   => msi_ring,        -- machine software interrupt
    mext_irq_i  => mei_ring         -- machine external interrupt
    mext_irq_i  => mei_ring         -- machine external interrupt
  );
  );
 
 
  -- TWI termination (pull-ups) --
  -- TWI termination (pull-ups) --
  twi_scl <= 'H';
  twi_scl <= 'H';
  twi_sda <= 'H';
  twi_sda <= 'H';
 
 
 
  uart0_checker: entity work.uart_rx
 
    generic map (uart0_rx_handle)
 
    port map (
 
      clk => clk_gen,
 
      uart_txd => uart0_txd);
 
 
  -- Console UART0 Receiver -----------------------------------------------------------------
  uart1_checker: entity work.uart_rx
  -- -------------------------------------------------------------------------------------------
    generic map (uart1_rx_handle)
  uart0_rx_console: process(clk_gen)
    port map (
    variable i : integer;
      clk => clk_gen,
    variable l : line;
      uart_txd => uart1_txd);
  begin
 
    -- "UART" --
 
    if rising_edge(clk_gen) then
 
      -- synchronizer --
 
      uart0_rx_sync <= uart0_rx_sync(3 downto 0) & uart0_txd;
 
      -- arbiter --
 
      if (uart0_rx_busy = '0') then -- idle
 
        uart0_rx_busy     <= '0';
 
        uart0_rx_baud_cnt <= round(0.5 * uart0_baud_val_c);
 
        uart0_rx_bitcnt   <= 9;
 
        if (uart0_rx_sync(4 downto 1) = "1100") then -- start bit? (falling edge)
 
          uart0_rx_busy <= '1';
 
        end if;
 
      else
 
        if (uart0_rx_baud_cnt <= 0.0) then
 
          if (uart0_rx_bitcnt = 1) then
 
            uart0_rx_baud_cnt <= round(0.5 * uart0_baud_val_c);
 
          else
 
            uart0_rx_baud_cnt <= round(uart0_baud_val_c);
 
          end if;
 
          if (uart0_rx_bitcnt = 0) then
 
            uart0_rx_busy <= '0'; -- done
 
            i := to_integer(unsigned(uart0_rx_sreg(8 downto 1)));
 
 
 
            if (i < 32) or (i > 32+95) then -- printable char?
 
              report "NEORV32_TB_UART0.TX: (" & integer'image(i) & ")"; -- print code
 
            else
 
              report "NEORV32_TB_UART0.TX: " & character'val(i); -- print ASCII
 
            end if;
 
 
 
            if (i = 10) then -- Linux line break
 
              writeline(file_uart0_tx_out, l);
 
            elsif (i /= 13) then -- Remove additional carriage return
 
              write(l, character'val(i));
 
            end if;
 
          else
 
            uart0_rx_sreg   <= uart0_rx_sync(4) & uart0_rx_sreg(8 downto 1);
 
            uart0_rx_bitcnt <= uart0_rx_bitcnt - 1;
 
          end if;
 
        else
 
          uart0_rx_baud_cnt <= uart0_rx_baud_cnt - 1.0;
 
        end if;
 
      end if;
 
    end if;
 
  end process uart0_rx_console;
 
 
 
 
  slink_transmitters_gen: for idx in slink_transmitters'range generate
 
    slink_transmitter : entity vunit_lib.axi_stream_master
 
      generic map(
 
        master => slink_transmitters(idx)
 
      )
 
      port map(
 
        aclk => clk_gen,
 
        tvalid => slink_transmitter_val(idx),
 
        tready => slink_transmitter_rdy(idx),
 
        std_ulogic_vector(tdata) => slink_transmitter_dat(idx)
 
      );
 
  end generate;
 
 
  -- Console UART1 Receiver -----------------------------------------------------------------
  slink_receivers_gen: for idx in slink_receivers'range generate
  -- -------------------------------------------------------------------------------------------
 
  uart1_rx_console: process(clk_gen)
 
    variable i : integer;
 
    variable l : line;
 
  begin
  begin
    -- "UART" --
    slink_receiver : entity vunit_lib.axi_stream_slave
    if rising_edge(clk_gen) then
      generic map(
      -- synchronizer --
        slave => slink_receivers(idx)
      uart1_rx_sync <= uart1_rx_sync(3 downto 0) & uart1_txd;
      )
      -- arbiter --
      port map(
      if (uart1_rx_busy = '0') then -- idle
        aclk => clk_gen,
        uart1_rx_busy     <= '0';
        tvalid => slink_receiver_val(idx),
        uart1_rx_baud_cnt <= round(0.5 * uart1_baud_val_c);
        tready => slink_receiver_rdy(idx),
        uart1_rx_bitcnt   <= 9;
        tdata => std_logic_vector(slink_receiver_dat(idx))
        if (uart1_rx_sync(4 downto 1) = "1100") then -- start bit? (falling edge)
      );
          uart1_rx_busy <= '1';
  end generate;
        end if;
 
      else
 
        if (uart1_rx_baud_cnt <= 0.0) then
 
          if (uart1_rx_bitcnt = 1) then
 
            uart1_rx_baud_cnt <= round(0.5 * uart1_baud_val_c);
 
          else
 
            uart1_rx_baud_cnt <= round(uart1_baud_val_c);
 
          end if;
 
          if (uart1_rx_bitcnt = 0) then
 
            uart1_rx_busy <= '0'; -- done
 
            i := to_integer(unsigned(uart1_rx_sreg(8 downto 1)));
 
 
 
            if (i < 32) or (i > 32+95) then -- printable char?
 
              report "NEORV32_TB_UART1.TX: (" & integer'image(i) & ")"; -- print code
 
            else
 
              report "NEORV32_TB_UART1.TX: " & character'val(i); -- print ASCII
 
            end if;
 
 
 
            if (i = 10) then -- Linux line break
  -- TODO: connect these to the CPU SLINK interface once the
              writeline(file_uart1_tx_out, l);
  -- loopback SW has been implemented
            elsif (i /= 13) then -- Remove additional carriage return
  temporary_connection : for idx in slink_transmitters'range generate
              write(l, character'val(i));
    slink_receiver_val(idx) <= slink_transmitter_val(idx);
            end if;
    slink_transmitter_rdy(idx) <= slink_receiver_rdy(idx);
          else
    slink_receiver_dat(idx) <= slink_transmitter_dat(idx);
            uart1_rx_sreg   <= uart1_rx_sync(4) & uart1_rx_sreg(8 downto 1);
  end generate;
            uart1_rx_bitcnt <= uart1_rx_bitcnt - 1;
 
          end if;
 
        else
 
          uart1_rx_baud_cnt <= uart1_rx_baud_cnt - 1.0;
 
        end if;
 
      end if;
 
    end if;
 
  end process uart1_rx_console;
 
 
 
 
 
  -- Wishbone Fabric ------------------------------------------------------------------------
  -- Wishbone Fabric ------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- CPU broadcast signals --
  -- CPU broadcast signals --
Line 460... Line 504...
 
 
  -- peripheral select via STROBE signal --
  -- peripheral select via STROBE signal --
  wb_mem_a.stb <= wb_cpu.stb when (wb_cpu.addr >= ext_mem_a_base_addr_c) and (wb_cpu.addr < std_ulogic_vector(unsigned(ext_mem_a_base_addr_c) + ext_mem_a_size_c)) else '0';
  wb_mem_a.stb <= wb_cpu.stb when (wb_cpu.addr >= ext_mem_a_base_addr_c) and (wb_cpu.addr < std_ulogic_vector(unsigned(ext_mem_a_base_addr_c) + ext_mem_a_size_c)) else '0';
  wb_mem_b.stb <= wb_cpu.stb when (wb_cpu.addr >= ext_mem_b_base_addr_c) and (wb_cpu.addr < std_ulogic_vector(unsigned(ext_mem_b_base_addr_c) + ext_mem_b_size_c)) else '0';
  wb_mem_b.stb <= wb_cpu.stb when (wb_cpu.addr >= ext_mem_b_base_addr_c) and (wb_cpu.addr < std_ulogic_vector(unsigned(ext_mem_b_base_addr_c) + ext_mem_b_size_c)) else '0';
  wb_mem_c.stb <= wb_cpu.stb when (wb_cpu.addr >= ext_mem_c_base_addr_c) and (wb_cpu.addr < std_ulogic_vector(unsigned(ext_mem_c_base_addr_c) + ext_mem_c_size_c)) else '0';
  wb_mem_c.stb <= wb_cpu.stb when (wb_cpu.addr >= ext_mem_c_base_addr_c) and (wb_cpu.addr < std_ulogic_vector(unsigned(ext_mem_c_base_addr_c) + ext_mem_c_size_c)) else '0';
  wb_irq.stb   <= wb_cpu.stb when (wb_cpu.addr =  irq_trigger_c) else '0';
  wb_irq.stb   <= wb_cpu.stb when (wb_cpu.addr =  irq_trigger_base_addr_c) else '0';
 
 
 
 
  -- Wishbone Memory A (simulated external IMEM) --------------------------------------------
  -- Wishbone Memory A (simulated external IMEM) --------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
 
  generate_ext_imem:
 
  if ext_imem_c generate
  ext_mem_a_access: process(clk_gen)
  ext_mem_a_access: process(clk_gen)
 
      variable ext_ram_a : mem32_t(0 to ext_mem_a_size_c/4-1) := mem32_init_f(application_init_image, ext_mem_a_size_c/4); -- initialized, used to simulate external IMEM
  begin
  begin
    if rising_edge(clk_gen) then
    if rising_edge(clk_gen) then
      -- control --
      -- control --
      ext_mem_a.ack(0) <= wb_mem_a.cyc and wb_mem_a.stb; -- wishbone acknowledge
      ext_mem_a.ack(0) <= wb_mem_a.cyc and wb_mem_a.stb; -- wishbone acknowledge
 
 
      -- write access --
      -- write access --
      if ((wb_mem_a.cyc and wb_mem_a.stb and wb_mem_a.we) = '1') then -- valid write access
      if ((wb_mem_a.cyc and wb_mem_a.stb and wb_mem_a.we) = '1') then -- valid write access
        for i in 0 to 3 loop
        for i in 0 to 3 loop
          if (wb_mem_a.sel(i) = '1') then
          if (wb_mem_a.sel(i) = '1') then
            ext_ram_a(to_integer(unsigned(wb_mem_a.addr(index_size_f(ext_mem_a_size_c/4)+1 downto 2))))(7+i*8 downto 0+i*8) <= wb_mem_a.wdata(7+i*8 downto 0+i*8);
              ext_ram_a(to_integer(unsigned(wb_mem_a.addr(index_size_f(ext_mem_a_size_c/4)+1 downto 2))))(7+i*8 downto 0+i*8) := wb_mem_a.wdata(7+i*8 downto 0+i*8);
          end if;
          end if;
        end loop; -- i
        end loop; -- i
      end if;
      end if;
 
 
      -- read access --
      -- read access --
Line 501... Line 548...
        wb_mem_a.rdata <= (others => '0');
        wb_mem_a.rdata <= (others => '0');
        wb_mem_a.ack   <= '0';
        wb_mem_a.ack   <= '0';
      end if;
      end if;
    end if;
    end if;
  end process ext_mem_a_access;
  end process ext_mem_a_access;
 
  end generate;
 
 
 
  generate_ext_imem_false:
 
  if (ext_imem_c = false) generate
 
    wb_mem_a.rdata <= (others => '0');
 
    wb_mem_a.ack   <= '0';
 
  end generate;
 
 
 
 
  -- Wishbone Memory B (simulated external DMEM) --------------------------------------------
  -- Wishbone Memory B (simulated external DMEM) --------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  ext_mem_b_access: process(clk_gen)
  ext_mem_b_access: process(clk_gen)
 
    variable ext_ram_b : mem32_t(0 to ext_mem_b_size_c/4-1) := (others => (others => '0')); -- zero, used to simulate external DMEM
  begin
  begin
    if rising_edge(clk_gen) then
    if rising_edge(clk_gen) then
      -- control --
      -- control --
      ext_mem_b.ack(0) <= wb_mem_b.cyc and wb_mem_b.stb; -- wishbone acknowledge
      ext_mem_b.ack(0) <= wb_mem_b.cyc and wb_mem_b.stb; -- wishbone acknowledge
 
 
      -- write access --
      -- write access --
      if ((wb_mem_b.cyc and wb_mem_b.stb and wb_mem_b.we) = '1') then -- valid write access
      if ((wb_mem_b.cyc and wb_mem_b.stb and wb_mem_b.we) = '1') then -- valid write access
        for i in 0 to 3 loop
        for i in 0 to 3 loop
          if (wb_mem_b.sel(i) = '1') then
          if (wb_mem_b.sel(i) = '1') then
            ext_ram_b(to_integer(unsigned(wb_mem_b.addr(index_size_f(ext_mem_b_size_c/4)+1 downto 2))))(7+i*8 downto 0+i*8) <= wb_mem_b.wdata(7+i*8 downto 0+i*8);
            ext_ram_b(to_integer(unsigned(wb_mem_b.addr(index_size_f(ext_mem_b_size_c/4)+1 downto 2))))(7+i*8 downto 0+i*8) := wb_mem_b.wdata(7+i*8 downto 0+i*8);
          end if;
          end if;
        end loop; -- i
        end loop; -- i
      end if;
      end if;
 
 
      -- read access --
      -- read access --
Line 606... Line 661...
      wb_irq.err   <= '0';
      wb_irq.err   <= '0';
      -- trigger IRQ using CSR.MIE bit layout --
      -- trigger IRQ using CSR.MIE bit layout --
      nmi_ring      <= '0';
      nmi_ring      <= '0';
      msi_ring      <= '0';
      msi_ring      <= '0';
      mei_ring      <= '0';
      mei_ring      <= '0';
      soc_firq_ring <= (others => '0');
 
      if ((wb_irq.cyc and wb_irq.stb and wb_irq.we and and_reduce_f(wb_irq.sel)) = '1') then
      if ((wb_irq.cyc and wb_irq.stb and wb_irq.we and and_reduce_f(wb_irq.sel)) = '1') then
        nmi_ring         <= wb_irq.wdata(00); -- non-maskable interrupt
        nmi_ring         <= wb_irq.wdata(00); -- non-maskable interrupt
        msi_ring         <= wb_irq.wdata(03); -- machine software interrupt
        msi_ring         <= wb_irq.wdata(03); -- machine software interrupt
        mei_ring         <= wb_irq.wdata(11); -- machine software interrupt
        mei_ring         <= wb_irq.wdata(11); -- machine software interrupt
        --
 
        soc_firq_ring(0) <= wb_irq.wdata(26); -- fast interrupt SoC channel 0 (-> FIRQ channel 10)
 
        soc_firq_ring(1) <= wb_irq.wdata(27); -- fast interrupt SoC channel 1 (-> FIRQ channel 11)
 
        soc_firq_ring(2) <= wb_irq.wdata(28); -- fast interrupt SoC channel 2 (-> FIRQ channel 12)
 
        soc_firq_ring(3) <= wb_irq.wdata(29); -- fast interrupt SoC channel 3 (-> FIRQ channel 13)
 
        soc_firq_ring(4) <= wb_irq.wdata(30); -- fast interrupt SoC channel 4 (-> FIRQ channel 14)
 
        soc_firq_ring(5) <= wb_irq.wdata(31); -- fast interrupt SoC channel 5 (-> FIRQ channel 15)
 
      end if;
      end if;
    end if;
    end if;
  end process irq_trigger;
  end process irq_trigger;
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.