added DEVNULL io device for testing and faster simulation console output

This commit is contained in:
stnolting 2020-06-25 20:15:37 +02:00
parent ddaa93b787
commit ea0acbe2c7
14 changed files with 977 additions and 953 deletions

File diff suppressed because it is too large Load diff

View file

@ -982,7 +982,7 @@ package neorv32_bootloader_image is
00000971 => x"4c420a0a",
00000972 => x"203a5644",
00000973 => x"206e754a",
00000974 => x"32203432",
00000974 => x"32203532",
00000975 => x"0a303230",
00000976 => x"3a565748",
00000977 => x"00002020",

View file

@ -81,7 +81,8 @@ entity neorv32_cpu is
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)?
IO_CLIC_USE : boolean := true; -- implement core local interrupt controller (CLIC)?
IO_TRNG_USE : boolean := true -- implement true random number generator (TRNG)?
IO_TRNG_USE : boolean := true; -- implement true random number generator (TRNG)?
IO_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
);
port (
-- global control --
@ -168,7 +169,8 @@ begin
IO_PWM_USE => IO_PWM_USE, -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE => IO_WDT_USE, -- implement watch dog timer (WDT)?
IO_CLIC_USE => IO_CLIC_USE, -- implement core local interrupt controller (CLIC)?
IO_TRNG_USE => IO_TRNG_USE -- implement true random number generator (TRNG)?
IO_TRNG_USE => IO_TRNG_USE, -- implement true random number generator (TRNG)?
IO_DEVNULL_USE => IO_DEVNULL_USE -- implement dummy device (DEVNULL)?
)
port map (
-- global control --

View file

@ -165,7 +165,7 @@ begin
shifter_unit: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
shift_sreg <= (others => '-');
shift_sreg <= (others => '0');
shift_cnt <= (others => '0');
shift_cmd_ff <= '0';
elsif rising_edge(clk_i) then
@ -241,7 +241,7 @@ begin
when alu_cmd_and_c => alu_res <= opa and opb;
when alu_cmd_shift_c => alu_res <= shift_sreg;
when alu_cmd_slt_c => alu_res <= (others => '0'); alu_res(0) <= cmp_less;
when others => alu_res <= (others => '-'); -- undefined
when others => alu_res <= (others => '0'); -- undefined
end case;
end process alu_function_mux;

View file

@ -75,7 +75,8 @@ entity neorv32_cpu_control is
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)?
IO_CLIC_USE : boolean := true; -- implement core local interrupt controller (CLIC)?
IO_TRNG_USE : boolean := true -- implement true random number generator (TRNG)?
IO_TRNG_USE : boolean := true; -- implement true random number generator (TRNG)?
IO_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
);
port (
-- global control --
@ -388,7 +389,7 @@ begin
when funct3_sr_c => alu_operation_v := alu_cmd_shift_c; -- SRL(I) / SRA(I)
when funct3_or_c => alu_operation_v := alu_cmd_or_c; -- OR(I)
when funct3_and_c => alu_operation_v := alu_cmd_and_c; -- AND(I)
when others => alu_operation_v := (others => '-'); -- undefined
when others => alu_operation_v := (others => '0'); -- undefined
end case;
-- is rs1 = r0? --
@ -903,10 +904,10 @@ begin
irq_buf <= (others => '0');
exc_ack <= (others => '0');
irq_ack <= (others => '0');
exc_src <= (others => '-');
exc_src <= (others => '0');
exc_cpu_start <= '0';
exc_cause <= (others => '0');
mtinst <= (others => '-');
mtinst <= (others => '0');
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_Zicsr = true) then
-- exception buffer: misaligned load/store/instruction address
@ -1092,10 +1093,10 @@ begin
mie_msie <= '0';
mie_meie <= '0';
mie_mtie <= '0';
mtvec <= (others => '-');
mtval <= (others => '-');
mepc <= (others => '-');
mip_msip <= '-';
mtvec <= (others => '0');
mtval <= (others => '0');
mepc <= (others => '0');
mip_msip <= '0';
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_Zicsr = true) then
mip_msip <= '0';
@ -1134,7 +1135,7 @@ begin
if (exc_cpu_ack = '1') then -- exception start?
if (exc_cause(exc_cause_nxt'left) = '1') then -- for INTERRUPTs: mepc = address of next (unclompeted) instruction
mepc <= pc_reg;
mtval <= (others => '-'); -- not specified
mtval <= (others => '0'); -- not specified
else -- for EXCEPTIONs: mepc = address of next (unclompeted) instruction
mepc <= pc_backup2_reg;
if ((exc_src(exception_iaccess_c) or exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction
@ -1243,15 +1244,16 @@ begin
csr_rdata_o(03) <= bool_to_ulogic_f(MEM_INT_IMEM_ROM); -- implement processor-internal instruction memory as ROM
csr_rdata_o(04) <= bool_to_ulogic_f(MEM_INT_DMEM_USE); -- implement processor-internal data memory
--
csr_rdata_o(16) <= bool_to_ulogic_f(IO_GPIO_USE); -- implement general purpose input/output port unit (GPIO)?
csr_rdata_o(17) <= bool_to_ulogic_f(IO_MTIME_USE); -- implement machine system timer (MTIME)?
csr_rdata_o(18) <= bool_to_ulogic_f(IO_UART_USE); -- implement universal asynchronous receiver/transmitter (UART)?
csr_rdata_o(19) <= bool_to_ulogic_f(IO_SPI_USE); -- implement serial peripheral interface (SPI)?
csr_rdata_o(20) <= bool_to_ulogic_f(IO_TWI_USE); -- implement two-wire interface (TWI)?
csr_rdata_o(21) <= bool_to_ulogic_f(IO_PWM_USE); -- implement pulse-width modulation unit (PWM)?
csr_rdata_o(22) <= bool_to_ulogic_f(IO_WDT_USE); -- implement watch dog timer (WDT)?
csr_rdata_o(23) <= bool_to_ulogic_f(IO_CLIC_USE); -- implement core local interrupt controller (CLIC)?
csr_rdata_o(24) <= bool_to_ulogic_f(IO_TRNG_USE); -- implement true random number generator (TRNG)?
csr_rdata_o(16) <= bool_to_ulogic_f(IO_GPIO_USE); -- implement general purpose input/output port unit (GPIO)?
csr_rdata_o(17) <= bool_to_ulogic_f(IO_MTIME_USE); -- implement machine system timer (MTIME)?
csr_rdata_o(18) <= bool_to_ulogic_f(IO_UART_USE); -- implement universal asynchronous receiver/transmitter (UART)?
csr_rdata_o(19) <= bool_to_ulogic_f(IO_SPI_USE); -- implement serial peripheral interface (SPI)?
csr_rdata_o(20) <= bool_to_ulogic_f(IO_TWI_USE); -- implement two-wire interface (TWI)?
csr_rdata_o(21) <= bool_to_ulogic_f(IO_PWM_USE); -- implement pulse-width modulation unit (PWM)?
csr_rdata_o(22) <= bool_to_ulogic_f(IO_WDT_USE); -- implement watch dog timer (WDT)?
csr_rdata_o(23) <= bool_to_ulogic_f(IO_CLIC_USE); -- implement core local interrupt controller (CLIC)?
csr_rdata_o(24) <= bool_to_ulogic_f(IO_TRNG_USE); -- implement true random number generator (TRNG)?
csr_rdata_o(25) <= bool_to_ulogic_f(IO_DEVNULL_USE); -- implement dummy device (DEVNULL)?
when x"fc1" => -- R/-: mclock - processor clock speed
csr_rdata_o <= std_ulogic_vector(to_unsigned(CLOCK_FREQUENCY, 32));
when x"fc4" => -- R/-: mispacebase - Base address of instruction memory space

View file

@ -95,12 +95,12 @@ begin
if (rstn_i = '0') then
state <= IDLE;
cp_op <= (others => '0');
opx <= (others => '-');
opy <= (others => '-');
cnt <= (others => '-');
start <= '-';
opx <= (others => '0');
opy <= (others => '0');
cnt <= (others => '0');
start <= '0';
valid_o <= '0';
div_res_corr <= '-';
div_res_corr <= '0';
elsif rising_edge(clk_i) then
-- defaults --
start <= '0';
@ -254,7 +254,7 @@ begin
when cp_op_remu_c =>
res_o <= remainder;
when others => -- undefined
res_o <= (others => '-');
res_o <= (others => '0');
end case;
end if;
end process operation_result;

View file

@ -0,0 +1,115 @@
-- #################################################################################################
-- # << NEORV32 - /DEV/NULL (DEVNULL) Dummy Device with Simulation Output >> #
-- # ********************************************************************************************* #
-- # In simulation: This unit will output the lowest 8 bit of the written data as ASCII chars #
-- # to the simulator console and to a text file ("neorv32.devnull.out"). #
-- # In real hardware: This unit implements a "/dev/null" device. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
-- # #
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
-- # conditions and the following disclaimer. #
-- # #
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
-- # conditions and the following disclaimer in the documentation and/or other materials #
-- # provided with the distribution. #
-- # #
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
-- # endorse or promote products derived from this software without specific prior written #
-- # permission. #
-- # #
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
-- # OF THE POSSIBILITY OF SUCH DAMAGE. #
-- # ********************************************************************************************* #
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library neorv32;
use neorv32.neorv32_package.all;
use std.textio.all;
entity neorv32_devnull is
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
ben_i : in std_ulogic_vector(03 downto 0); -- byte write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic -- transfer acknowledge
);
end neorv32_devnull;
architecture neorv32_devnull_rtl of neorv32_devnull is
-- configuration --
constant sim_output_en_c : boolean := true; -- output lowest byte as char to simulator
-- text.io --
file file_devnull_out : text open write_mode is "neorv32.devnull.out";
-- IO space: module base address --
constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(devnull_size_c); -- low address boundary bit
-- access control --
signal acc_en : std_ulogic; -- module access enable
begin
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = devnull_base_c(hi_abb_c downto lo_abb_c)) else '0';
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
variable i : integer;
variable la, lb : line; -- we need to variables here since "writeline" seems to flush the source variable
begin
if rising_edge(clk_i) then
ack_o <= acc_en and (wren_i or rden_i);
if ((acc_en and wren_i and ben_i(0)) = '1') then
-- print lowest byte as ASCII to console --
if (sim_output_en_c = true) then
i := to_integer(unsigned(data_i(7 downto 0)));
if (i >= 128) then -- out of range?
i := 0;
end if;
if (i /= 10) and (i /= 13) then -- skip linebreaks
write(la, character'val(i));
write(lb, character'val(i));
end if;
if (i = 10) then -- line break: write to screen and file
writeline(output, la);
writeline(file_devnull_out, lb);
end if;
end if;
end if;
end if;
end process rw_access;
-- output --
data_o <= (others => '0');
end neorv32_devnull_rtl;

View file

@ -41,7 +41,7 @@ package neorv32_package is
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- data width - FIXED!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"00000203"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"00000204"; -- no touchy!
-- Internal Functions ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
@ -125,7 +125,12 @@ package neorv32_package is
-- RESERVED --
--constant ???_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC8"; -- base address, fixed!
--constant ???_size_c : natural := 14*4; -- bytes, fixed!
--constant ???_size_c : natural := 13*4; -- bytes, fixed!
-- Dummy Device (with SIM output) (DEVNULL) --
constant devnull_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFFC"; -- base address, fixed!
constant devnull_size_c : natural := 1*4; -- bytes, fixed!
constant devnull_data_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(devnull_base_c) + x"00000000");
-- Main Control Bus -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
@ -361,7 +366,8 @@ package neorv32_package is
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)?
IO_CLIC_USE : boolean := true; -- implement core local interrupt controller (CLIC)?
IO_TRNG_USE : boolean := false -- implement true random number generator (TRNG)?
IO_TRNG_USE : boolean := false; -- implement true random number generator (TRNG)?
IO_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
);
port (
-- Global control --
@ -434,7 +440,8 @@ package neorv32_package is
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)?
IO_CLIC_USE : boolean := true; -- implement core local interrupt controller (CLIC)?
IO_TRNG_USE : boolean := true -- implement true random number generator (TRNG)?
IO_TRNG_USE : boolean := true; -- implement true random number generator (TRNG)?
IO_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
);
port (
-- global control --
@ -631,7 +638,8 @@ package neorv32_package is
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)?
IO_CLIC_USE : boolean := true; -- implement core local interrupt controller (CLIC)?
IO_TRNG_USE : boolean := true -- implement true random number generator (TRNG)?
IO_TRNG_USE : boolean := true; -- implement true random number generator (TRNG)?
IO_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
);
port (
-- global control --
@ -941,6 +949,22 @@ package neorv32_package is
);
end component;
-- Component: Dummy Device with SIM Output (DEVNULL) -------------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_devnull
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
ben_i : in std_ulogic_vector(03 downto 0); -- byte write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic -- transfer acknowledge
);
end component;
end neorv32_package;
package body neorv32_package is

View file

@ -79,7 +79,8 @@ entity neorv32_top is
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)?
IO_CLIC_USE : boolean := true; -- implement core local interrupt controller (CLIC)?
IO_TRNG_USE : boolean := false -- implement true random number generator (TRNG)?
IO_TRNG_USE : boolean := false; -- implement true random number generator (TRNG)?
IO_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
);
port (
-- Global control --
@ -181,6 +182,8 @@ architecture neorv32_top_rtl of neorv32_top is
signal clic_ack : std_ulogic;
signal trng_rdata : std_ulogic_vector(data_width_c-1 downto 0);
signal trng_ack : std_ulogic;
signal devnull_rdata : std_ulogic_vector(data_width_c-1 downto 0);
signal devnull_ack : std_ulogic;
-- IRQs --
signal mtime_irq : std_ulogic;
@ -340,7 +343,8 @@ begin
IO_PWM_USE => IO_PWM_USE, -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE => IO_WDT_USE, -- implement watch dog timer (WDT)?
IO_CLIC_USE => IO_CLIC_USE, -- implement core local interrupt controller (CLIC)?
IO_TRNG_USE => IO_TRNG_USE -- implement true random number generator (TRNG)?
IO_TRNG_USE => IO_TRNG_USE, -- implement true random number generator (TRNG)?
IO_DEVNULL_USE => IO_DEVNULL_USE -- implement dummy device (DEVNULL)?
)
port map (
-- global control --
@ -362,11 +366,11 @@ begin
-- CPU data input --
cpu_rdata <= (imem_rdata or dmem_rdata or bootrom_rdata) or wishbone_rdata or (gpio_rdata or mtime_rdata or
uart_rdata or spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or clic_rdata or trng_rdata);
uart_rdata or spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or clic_rdata or trng_rdata or devnull_rdata);
-- CPU ACK input --
cpu_ack <= (imem_ack or dmem_ack or bootrom_ack) or wishbone_ack or (gpio_ack or mtime_ack or
uart_ack or spi_ack or twi_ack or pwm_ack or wdt_ack or clic_ack or trng_ack);
uart_ack or spi_ack or twi_ack or pwm_ack or wdt_ack or clic_ack or trng_ack or devnull_ack);
-- CPU bus error input --
cpu_err <= wishbone_err;
@ -827,4 +831,29 @@ begin
end generate;
-- Dummy Device (DEVNULL) -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_devnull_inst_true:
if (IO_DEVNULL_USE = true) generate
neorv32_devnull_inst: neorv32_devnull
port map (
-- host access --
clk_i => clk_i, -- global clock line
addr_i => cpu_addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
ben_i => cpu_ben, -- byte write enable
data_i => cpu_wdata, -- data in
data_o => devnull_rdata, -- data out
ack_o => devnull_ack -- transfer acknowledge
);
end generate;
neorv32_devnull_inst_false:
if (IO_DEVNULL_USE = false) generate
devnull_rdata <= (others => '0');
devnull_ack <= '0';
end generate;
end neorv32_top_rtl;

View file

@ -250,7 +250,7 @@ begin
case tmp_v is
when "101" => db_enable <= '1'; db_data <= '1'; -- rising edge -> '1'
when "110" => db_enable <= '1'; db_data <= '0'; -- falling edge -> '0'
when others => db_enable <= '0'; db_data <= '-'; -- invalid
when others => db_enable <= '0'; db_data <= '0'; -- invalid
end case;
end process debiasing;

View file

@ -101,7 +101,8 @@ begin
IO_PWM_USE => false, -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE => true, -- implement watch dog timer (WDT)?
IO_CLIC_USE => true, -- implement core local interrupt controller (CLIC)?
IO_TRNG_USE => false -- implement true random number generator (TRNG)?
IO_TRNG_USE => false, -- implement true random number generator (TRNG)?
IO_DEVNULL_USE => true -- implement dummy device (DEVNULL)?
)
port map (
-- Global control --

View file

@ -1,5 +1,10 @@
-- #################################################################################################
-- # << NEORV32 - Simple Testbench with UART-to-Console module >> #
-- # << NEORV32 - Simple Testbench >> #
-- # ********************************************************************************************* #
-- # This testbench provides a virtual UART receiver connected to the processor's uart_txd_o #
-- # signals. The received chars are shown in the simulator console and also written to a file #
-- # ("neorv32.testbench_uart.out"). #
-- # Futhermore, this testbench provides a simple RAM connected to the external Wishbone bus. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
@ -52,25 +57,17 @@ architecture neorv32_tb_rtl of neorv32_tb is
constant f_clock_c : real := 100000000.0; -- main clock in Hz
constant f_clock_nat_c : natural := 100000000; -- main clock in Hz
constant baud_rate_c : real := 19200.0; -- standard UART baudrate
constant wb_mem_size_c : natural := 256; -- wishbone memory size in bytes
constant wb_mem_base_addr_c : std_ulogic_vector(31 downto 0) := x"F0000000"; -- wishbone memory base address
constant wb_mem_size_c : natural := 256; -- wishbone memory size in bytes
-- -------------------------------------------------------------------------------------------
-- textio --
file file_uart_tx_out : text open write_mode is "neorv32.sim_uart.out";
-- text.io --
file file_uart_tx_out : text open write_mode is "neorv32.testbench_uart.out";
-- internal configuration --
constant baud_val_c : real := f_clock_c / baud_rate_c;
constant f_clk_c : natural := natural(f_clock_c);
-- reduced ASCII table --
type ascii_t is array (0 to 94) of character;
constant ascii_lut : ascii_t := (' ', '!', '"', '#', '$', '%', '&', ''', '(', ')', '*', '+', ',', '-',
'.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A',
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
'V', 'W', 'X', 'Y', 'Z', '[', '\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~');
-- generators --
signal clk_gen, rst_gen : std_ulogic := '0';
@ -106,12 +103,14 @@ architecture neorv32_tb_rtl of neorv32_tb is
signal wb_cpu : wishbone_t;
-- Wishbone memory --
-- Wishbone memory, SimCom --
type wb_mem_file_t is array (0 to wb_mem_size_c/4-1) of std_ulogic_vector(31 downto 0);
signal wb_mem_file : wb_mem_file_t := (others => (others => '0'));
signal rb_en : std_ulogic;
signal r_data : std_ulogic_vector(31 downto 0);
signal wb_acc_en : std_ulogic;
signal wb_mem_file : wb_mem_file_t := (others => (others => '0'));
signal rb_en : std_ulogic;
signal r_data : std_ulogic_vector(31 downto 0);
signal wb_acc_en : std_ulogic;
signal wb_mem_rdata : std_ulogic_vector(31 downto 0);
signal wb_mem_ack : std_ulogic;
begin
@ -158,7 +157,8 @@ begin
IO_PWM_USE => true, -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE => true, -- implement watch dog timer (WDT)?
IO_CLIC_USE => true, -- implement core local interrupt controller (CLIC)?
IO_TRNG_USE => false -- implement true random number generator (TRNG)?
IO_TRNG_USE => false, -- implement true random number generator (TRNG)?
IO_DEVNULL_USE => true -- implement dummy device (DEVNULL)?
)
port map (
-- Global control --
@ -195,18 +195,22 @@ begin
ext_ack_o => open -- external interrupt request acknowledge
);
-- twi termination --
-- TWI termination --
twi_scl <= 'H';
twi_sda <= 'H';
-- Wishbone read-back --
wb_cpu.rdata <= wb_mem_rdata;
wb_cpu.ack <= wb_mem_ack;
wb_cpu.err <= '0';
-- Console UART Receiver ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
uart_rx_console: process(clk_gen)
variable i, j : integer;
variable line_tmp : line;
variable i : integer;
variable l : line;
begin
-- "UART" --
if rising_edge(clk_gen) then
-- synchronizer --
@ -221,7 +225,6 @@ begin
end if;
else
if (uart_rx_baud_cnt = 0.0) then
-- adapt to the inter-frame pause - which is not implemented in the neo430 uart ;)
if (uart_rx_bitcnt = 1) then
uart_rx_baud_cnt <= round(0.5 * baud_val_c);
else
@ -230,21 +233,17 @@ begin
if (uart_rx_bitcnt = 0) then
uart_rx_busy <= '0'; -- done
i := to_integer(unsigned(uart_rx_sreg(8 downto 1)));
j := i - 32;
if (j < 0) or (j > 95) then
j := 0; -- undefined = SPACE
end if;
if (i < 32) or (j > 32+95) then
report "UART TX: (" & integer'image(i) & ")"; -- print code
if (i < 32) or (i > 32+95) then -- printable char?
report "SIM_UART TX: (" & integer'image(i) & ")"; -- print code
else
report "UART TX: " & ascii_lut(j); -- print ASCII
report "SIM_UART TX: " & character'val(i); -- print ASCII
end if;
if (i = 10) then -- Linux line break
writeline(file_uart_tx_out, line_tmp);
writeline(file_uart_tx_out, l);
elsif (i /= 13) then -- Remove additional carriage return
write(line_tmp, ascii_lut(j));
write(l, character'val(i));
end if;
else
uart_rx_sreg <= uart_rx_sync(4) & uart_rx_sreg(8 downto 1);
@ -264,7 +263,7 @@ begin
begin
if rising_edge(clk_gen) then
rb_en <= wb_cpu.cyc and wb_cpu.stb and wb_acc_en and (not wb_cpu.we); -- read-back control
wb_cpu.ack <= wb_cpu.cyc and wb_cpu.stb and wb_acc_en; -- wishbone acknowledge
wb_mem_ack <= wb_cpu.cyc and wb_cpu.stb and wb_acc_en; -- wishbone acknowledge
if ((wb_cpu.cyc and wb_cpu.stb and wb_acc_en and wb_cpu.we) = '1') then -- valid write access
for i in 0 to 3 loop
if (wb_cpu.sel(i) = '1') then
@ -280,7 +279,7 @@ begin
wb_acc_en <= '1' when (wb_cpu.addr >= wb_mem_base_addr_c) and (wb_cpu.addr < std_ulogic_vector(unsigned(wb_mem_base_addr_c) + wb_mem_size_c)) else '0';
-- output gate --
wb_cpu.rdata <= r_data when (rb_en = '1') else (others=> '0');
wb_cpu.err <= '0';
wb_mem_rdata <= r_data when (rb_en = '1') else (others=> '0');
end neorv32_tb_rtl;

View file

@ -144,7 +144,8 @@ enum NEORV32_CPU_MIP_enum {
CPU_MFEATURES_IO_PWM = 21, /**< CPU mfeatures CSR (21) (r/-): Pulse-width modulation unit implemented when 1 (via IO_PWM_USE generic) */
CPU_MFEATURES_IO_WDT = 22, /**< CPU mfeatures CSR (22) (r/-): Watchdog timer implemented when 1 (via IO_WDT_USE generic) */
CPU_MFEATURES_IO_CLIC = 23, /**< CPU mfeatures CSR (23) (r/-): Core-local interrupt controller implemented when 1 (via IO_CLIC_USE generic) */
CPU_MFEATURES_IO_TRNG = 24 /**< CPU mfeatures CSR (24) (r/-): True random number generator implemented when 1 (via IO_TRNG_USE generic) */
CPU_MFEATURES_IO_TRNG = 24, /**< CPU mfeatures CSR (24) (r/-): True random number generator implemented when 1 (via IO_TRNG_USE generic) */
CPU_MFEATURES_IO_DEVNULL = 25 /**< CPU mfeatures CSR (24) (r/-): Dummy device implemented when 1 (via IO_DEVNULL_USE generic) */
};
@ -491,6 +492,15 @@ enum NEORV32_TRNG_DUTY_enum {
/**@}*/
/**********************************************************************//**
* @name IO Device: Dummy Device (DEVNULL)
**************************************************************************/
/**@{*/
/** TRNG data register (r/w) */
#define DEVNULL_DATA (*(IO_REG32 0xFFFFFFFC))
/**@}*/
// ----------------------------------------------------------------------------
// Include all IO driver headers
// ----------------------------------------------------------------------------

View file

@ -130,14 +130,21 @@ void neorv32_uart_disable(void) {
* Send single char via UART.
*
* @note This function is blocking.
* @warning The 'SIMCOM_UART_OVERRIDE' compiler user flag will forward all UART TX data to the SIMCOM simulation console output.
*
* @param[in] c Char to be send.
**************************************************************************/
void neorv32_uart_putc(char c) {
#ifdef DEVNULL_UART_OVERRIDE
#warning UART OVERRIDE! Sending all UART.TX data to DEVNULL simulation output instead of UART transmitter. Use this for simulations only!
DEVNULL_DATA = (uint32_t)c;
#else
// wait for previous transfer to finish
while ((UART_CT & (1<<UART_CT_TX_BUSY)) != 0);
UART_DATA = ((uint32_t)c) << UART_DATA_LSB;
#endif
}