mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-23 13:47:33 -04:00
added DEVNULL io device for testing and faster simulation console output
This commit is contained in:
parent
ddaa93b787
commit
ea0acbe2c7
14 changed files with 977 additions and 953 deletions
File diff suppressed because it is too large
Load diff
|
@ -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",
|
||||
|
|
|
@ -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 --
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
115
rtl/core/neorv32_devnull.vhd
Normal file
115
rtl/core/neorv32_devnull.vhd
Normal 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;
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 --
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue