Line 58... |
Line 58... |
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 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 baud_rate_c : natural := 19200; -- simulation UART output baudrate
|
constant baud0_rate_c : natural := 19200; -- simulation UART0 (primary UART) baud rate
|
|
constant baud1_rate_c : natural := 19200; -- simulation UART1 (secondary UART) baud rate
|
-- simulated external Wishbone memory A (can be used as external IMEM) --
|
-- simulated external Wishbone memory A (can be used as external IMEM) --
|
constant ext_mem_a_base_addr_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- wishbone memory base address (external IMEM base)
|
constant ext_mem_a_base_addr_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- wishbone memory base address (external IMEM base)
|
constant ext_mem_a_size_c : natural := imem_size_c; -- wishbone memory size in bytes
|
constant ext_mem_a_size_c : natural := imem_size_c; -- wishbone memory size in bytes
|
constant ext_mem_a_latency_c : natural := 8; -- latency in clock cycles (min 1, max 255), plus 1 cycle initial delay
|
constant ext_mem_a_latency_c : natural := 8; -- latency in clock cycles (min 1, max 255), plus 1 cycle initial delay
|
-- simulated external Wishbone memory B (can be used as external DMEM) --
|
-- simulated external Wishbone memory B (can be used as external DMEM) --
|
Line 78... |
Line 79... |
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
|
|
-- 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;
|
constant baud_val_c : real := real(f_clock_c) / real(baud_rate_c);
|
constant uart0_baud_val_c : real := real(f_clock_c) / real(baud0_rate_c);
|
|
constant uart1_baud_val_c : real := real(f_clock_c) / real(baud1_rate_c);
|
constant t_clock_c : time := (1 sec) / f_clock_c;
|
constant t_clock_c : time := (1 sec) / f_clock_c;
|
|
|
-- text.io --
|
|
file file_uart_tx_out : text open write_mode is "neorv32.testbench_uart.out";
|
|
|
|
-- generators --
|
-- generators --
|
signal clk_gen, rst_gen : std_ulogic := '0';
|
signal clk_gen, rst_gen : std_ulogic := '0';
|
|
|
-- simulation uart receiver --
|
-- text.io --
|
signal uart_txd : std_ulogic;
|
file file_uart0_tx_out : text open write_mode is "neorv32.testbench_uart0.out";
|
signal uart_rx_sync : std_ulogic_vector(04 downto 0) := (others => '1');
|
file file_uart1_tx_out : text open write_mode is "neorv32.testbench_uart1.out";
|
signal uart_rx_busy : std_ulogic := '0';
|
|
signal uart_rx_sreg : std_ulogic_vector(08 downto 0) := (others => '0');
|
-- simulation uart0 receiver --
|
signal uart_rx_baud_cnt : real;
|
signal uart0_txd : std_ulogic;
|
signal uart_rx_bitcnt : natural;
|
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;
|
|
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(31 downto 0);
|
|
|
-- twi --
|
-- twi --
|
Line 106... |
Line 117... |
-- spi --
|
-- spi --
|
signal spi_data : std_ulogic;
|
signal spi_data : std_ulogic;
|
|
|
-- irq --
|
-- irq --
|
signal msi_ring, mei_ring : std_ulogic;
|
signal msi_ring, mei_ring : std_ulogic;
|
signal soc_firq_ring : std_ulogic_vector(7 downto 0);
|
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 209... |
Line 220... |
-- External memory interface --
|
-- External memory interface --
|
MEM_EXT_EN => true, -- implement external memory bus interface?
|
MEM_EXT_EN => true, -- implement external memory bus interface?
|
-- 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_UART_EN => true, -- implement universal asynchronous receiver/transmitter (UART)?
|
IO_UART0_EN => true, -- implement primary universal asynchronous receiver/transmitter (UART0)?
|
|
IO_UART1_EN => true, -- implement secondary universal asynchronous receiver/transmitter (UART1)?
|
IO_SPI_EN => true, -- implement serial peripheral interface (SPI)?
|
IO_SPI_EN => true, -- implement serial peripheral interface (SPI)?
|
IO_TWI_EN => true, -- implement two-wire interface (TWI)?
|
IO_TWI_EN => true, -- implement two-wire interface (TWI)?
|
IO_PWM_EN => true, -- implement pulse-width modulation unit (PWM)?
|
IO_PWM_EN => true, -- implement pulse-width modulation unit (PWM)?
|
IO_WDT_EN => true, -- implement watch dog timer (WDT)?
|
IO_WDT_EN => true, -- implement watch dog timer (WDT)?
|
IO_TRNG_EN => false, -- trng cannot be simulated
|
IO_TRNG_EN => false, -- trng cannot be simulated
|
Line 241... |
Line 253... |
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
|
-- 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
|
-- UART (available if IO_UART_EN = true) --
|
-- primary UART0 (available if IO_UART0_EN = true) --
|
uart_txd_o => uart_txd, -- UART send data
|
uart0_txd_o => uart0_txd, -- UART0 send data
|
uart_rxd_i => uart_txd, -- UART receive data
|
uart0_rxd_i => uart0_txd, -- UART0 receive data
|
|
-- secondary UART1 (available if IO_UART1_EN = true) --
|
|
uart1_txd_o => uart1_txd, -- UART1 send data
|
|
uart1_rxd_i => uart1_txd, -- UART1 receive data
|
-- SPI (available if IO_SPI_EN = true) --
|
-- SPI (available if IO_SPI_EN = true) --
|
spi_sck_o => open, -- SPI serial clock
|
spi_sck_o => open, -- SPI serial clock
|
spi_sdo_o => spi_data, -- controller data out, peripheral data in
|
spi_sdo_o => spi_data, -- controller data out, peripheral data in
|
spi_sdi_i => spi_data, -- controller data in, peripheral data out
|
spi_sdi_i => spi_data, -- controller data in, peripheral data out
|
spi_csn_o => open, -- SPI CS
|
spi_csn_o => open, -- SPI CS
|
Line 273... |
Line 288... |
-- TWI termination (pull-ups) --
|
-- TWI termination (pull-ups) --
|
twi_scl <= 'H';
|
twi_scl <= 'H';
|
twi_sda <= 'H';
|
twi_sda <= 'H';
|
|
|
|
|
-- Console UART Receiver ------------------------------------------------------------------
|
-- Console UART0 Receiver -----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
uart_rx_console: process(clk_gen)
|
uart0_rx_console: process(clk_gen)
|
variable i : integer;
|
variable i : integer;
|
variable l : line;
|
variable l : line;
|
begin
|
begin
|
-- "UART" --
|
-- "UART" --
|
if rising_edge(clk_gen) then
|
if rising_edge(clk_gen) then
|
-- synchronizer --
|
-- synchronizer --
|
uart_rx_sync <= uart_rx_sync(3 downto 0) & uart_txd;
|
uart0_rx_sync <= uart0_rx_sync(3 downto 0) & uart0_txd;
|
-- arbiter --
|
-- arbiter --
|
if (uart_rx_busy = '0') then -- idle
|
if (uart0_rx_busy = '0') then -- idle
|
uart_rx_busy <= '0';
|
uart0_rx_busy <= '0';
|
uart_rx_baud_cnt <= round(0.5 * baud_val_c);
|
uart0_rx_baud_cnt <= round(0.5 * uart0_baud_val_c);
|
uart_rx_bitcnt <= 9;
|
uart0_rx_bitcnt <= 9;
|
if (uart_rx_sync(4 downto 1) = "1100") then -- start bit? (falling edge)
|
if (uart0_rx_sync(4 downto 1) = "1100") then -- start bit? (falling edge)
|
uart_rx_busy <= '1';
|
uart0_rx_busy <= '1';
|
end if;
|
end if;
|
else
|
else
|
if (uart_rx_baud_cnt <= 0.0) then
|
if (uart0_rx_baud_cnt <= 0.0) then
|
if (uart_rx_bitcnt = 1) then
|
if (uart0_rx_bitcnt = 1) then
|
uart_rx_baud_cnt <= round(0.5 * baud_val_c);
|
uart0_rx_baud_cnt <= round(0.5 * uart0_baud_val_c);
|
else
|
else
|
uart_rx_baud_cnt <= round(baud_val_c);
|
uart0_rx_baud_cnt <= round(uart0_baud_val_c);
|
end if;
|
end if;
|
if (uart_rx_bitcnt = 0) then
|
if (uart0_rx_bitcnt = 0) then
|
uart_rx_busy <= '0'; -- done
|
uart0_rx_busy <= '0'; -- done
|
i := to_integer(unsigned(uart_rx_sreg(8 downto 1)));
|
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;
|
|
|
|
|
|
-- Console UART1 Receiver -----------------------------------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
uart1_rx_console: process(clk_gen)
|
|
variable i : integer;
|
|
variable l : line;
|
|
begin
|
|
-- "UART" --
|
|
if rising_edge(clk_gen) then
|
|
-- synchronizer --
|
|
uart1_rx_sync <= uart1_rx_sync(3 downto 0) & uart1_txd;
|
|
-- arbiter --
|
|
if (uart1_rx_busy = '0') then -- idle
|
|
uart1_rx_busy <= '0';
|
|
uart1_rx_baud_cnt <= round(0.5 * uart1_baud_val_c);
|
|
uart1_rx_bitcnt <= 9;
|
|
if (uart1_rx_sync(4 downto 1) = "1100") then -- start bit? (falling edge)
|
|
uart1_rx_busy <= '1';
|
|
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?
|
if (i < 32) or (i > 32+95) then -- printable char?
|
report "NEORV32_TB_UART.TX: (" & integer'image(i) & ")"; -- print code
|
report "NEORV32_TB_UART1.TX: (" & integer'image(i) & ")"; -- print code
|
else
|
else
|
report "NEORV32_TB_UART.TX: " & character'val(i); -- print ASCII
|
report "NEORV32_TB_UART1.TX: " & character'val(i); -- print ASCII
|
end if;
|
end if;
|
|
|
if (i = 10) then -- Linux line break
|
if (i = 10) then -- Linux line break
|
writeline(file_uart_tx_out, l);
|
writeline(file_uart1_tx_out, l);
|
elsif (i /= 13) then -- Remove additional carriage return
|
elsif (i /= 13) then -- Remove additional carriage return
|
write(l, character'val(i));
|
write(l, character'val(i));
|
end if;
|
end if;
|
else
|
else
|
uart_rx_sreg <= uart_rx_sync(4) & uart_rx_sreg(8 downto 1);
|
uart1_rx_sreg <= uart1_rx_sync(4) & uart1_rx_sreg(8 downto 1);
|
uart_rx_bitcnt <= uart_rx_bitcnt - 1;
|
uart1_rx_bitcnt <= uart1_rx_bitcnt - 1;
|
end if;
|
end if;
|
else
|
else
|
uart_rx_baud_cnt <= uart_rx_baud_cnt - 1.0;
|
uart1_rx_baud_cnt <= uart1_rx_baud_cnt - 1.0;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process uart_rx_console;
|
end process uart1_rx_console;
|
|
|
|
|
-- Wishbone Fabric ------------------------------------------------------------------------
|
-- Wishbone Fabric ------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- CPU broadcast signals --
|
-- CPU broadcast signals --
|
Line 510... |
Line 577... |
mei_ring <= '0';
|
mei_ring <= '0';
|
soc_firq_ring <= (others => '0');
|
soc_firq_ring <= (others => '0');
|
if ((wb_irq.cyc and wb_irq.stb and wb_irq.we and and_all_f(wb_irq.sel)) = '1') then
|
if ((wb_irq.cyc and wb_irq.stb and wb_irq.we and and_all_f(wb_irq.sel)) = '1') then
|
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(24); -- fast interrupt SoC channel 0
|
--
|
soc_firq_ring(1) <= wb_irq.wdata(25); -- fast interrupt SoC channel 1
|
soc_firq_ring(0) <= wb_irq.wdata(26); -- fast interrupt SoC channel 0 (-> FIRQ channel 10)
|
soc_firq_ring(2) <= wb_irq.wdata(26); -- fast interrupt SoC channel 2
|
soc_firq_ring(1) <= wb_irq.wdata(27); -- fast interrupt SoC channel 1 (-> FIRQ channel 11)
|
soc_firq_ring(3) <= wb_irq.wdata(27); -- fast interrupt SoC channel 3
|
soc_firq_ring(2) <= wb_irq.wdata(28); -- fast interrupt SoC channel 2 (-> FIRQ channel 12)
|
soc_firq_ring(4) <= wb_irq.wdata(28); -- fast interrupt SoC channel 4
|
soc_firq_ring(3) <= wb_irq.wdata(29); -- fast interrupt SoC channel 3 (-> FIRQ channel 13)
|
soc_firq_ring(5) <= wb_irq.wdata(29); -- fast interrupt SoC channel 5
|
soc_firq_ring(4) <= wb_irq.wdata(30); -- fast interrupt SoC channel 4 (-> FIRQ channel 14)
|
soc_firq_ring(6) <= wb_irq.wdata(30); -- fast interrupt SoC channel 6
|
soc_firq_ring(5) <= wb_irq.wdata(31); -- fast interrupt SoC channel 5 (-> FIRQ channel 15)
|
soc_firq_ring(7) <= wb_irq.wdata(31); -- fast interrupt SoC channel 7
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end process irq_trigger;
|
end process irq_trigger;
|
|
|
|
|