1 |
198 |
zero_gravi |
-- #################################################################################################
|
2 |
|
|
-- # << NEO430 - Simple testbench >> #
|
3 |
|
|
-- # ********************************************************************************************* #
|
4 |
|
|
-- # This simple testbench instantiates the top entity of the NEO430 processors, generates clock #
|
5 |
|
|
-- # and reset signals and outputs data send via the processor's UART to the simulator console. #
|
6 |
|
|
-- # ********************************************************************************************* #
|
7 |
|
|
-- # BSD 3-Clause License #
|
8 |
|
|
-- # #
|
9 |
|
|
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved. #
|
10 |
|
|
-- # #
|
11 |
|
|
-- # Redistribution and use in source and binary forms, with or without modification, are #
|
12 |
|
|
-- # permitted provided that the following conditions are met: #
|
13 |
|
|
-- # #
|
14 |
|
|
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
15 |
|
|
-- # conditions and the following disclaimer. #
|
16 |
|
|
-- # #
|
17 |
|
|
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
|
18 |
|
|
-- # conditions and the following disclaimer in the documentation and/or other materials #
|
19 |
|
|
-- # provided with the distribution. #
|
20 |
|
|
-- # #
|
21 |
|
|
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
|
22 |
|
|
-- # endorse or promote products derived from this software without specific prior written #
|
23 |
|
|
-- # permission. #
|
24 |
|
|
-- # #
|
25 |
|
|
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
|
26 |
|
|
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
|
27 |
|
|
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
|
28 |
|
|
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
|
29 |
|
|
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
|
30 |
|
|
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
|
31 |
|
|
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
|
32 |
|
|
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
|
33 |
|
|
-- # OF THE POSSIBILITY OF SUCH DAMAGE. #
|
34 |
|
|
-- # ********************************************************************************************* #
|
35 |
|
|
-- # The NEO430 Processor - https://github.com/stnolting/neo430 #
|
36 |
|
|
-- #################################################################################################
|
37 |
|
|
|
38 |
|
|
library ieee;
|
39 |
|
|
use ieee.std_logic_1164.all;
|
40 |
|
|
use ieee.numeric_std.all;
|
41 |
|
|
use ieee.math_real.all;
|
42 |
|
|
|
43 |
|
|
library neo430;
|
44 |
|
|
use neo430.neo430_package.all;
|
45 |
|
|
use std.textio.all;
|
46 |
|
|
|
47 |
|
|
entity neo430_tb is
|
48 |
|
|
end neo430_tb;
|
49 |
|
|
|
50 |
|
|
architecture neo430_tb_rtl of neo430_tb is
|
51 |
|
|
|
52 |
|
|
-- User Configuration ---------------------------------------------------------------------
|
53 |
|
|
-- -------------------------------------------------------------------------------------------
|
54 |
|
|
constant t_clock_c : time := 10 ns; -- main clock period
|
55 |
|
|
constant f_clock_c : real := 100000000.0; -- main clock in Hz
|
56 |
|
|
constant baud_rate_c : real := 19200.0; -- standard UART baudrate
|
57 |
|
|
-- -------------------------------------------------------------------------------------------
|
58 |
|
|
|
59 |
|
|
-- textio --
|
60 |
|
|
file file_uart_tx_out : text open write_mode is "neo430.uart_tx.txt";
|
61 |
|
|
|
62 |
|
|
-- internal configuration --
|
63 |
|
|
constant baud_val_c : real := f_clock_c / baud_rate_c;
|
64 |
|
|
constant f_clk_c : natural := natural(f_clock_c);
|
65 |
|
|
|
66 |
|
|
-- reduced ASCII table --
|
67 |
|
|
type ascii_t is array (0 to 94) of character;
|
68 |
|
|
constant ascii_lut : ascii_t := (' ', '!', '"', '#', '$', '%', '&', ''', '(', ')', '*', '+', ',', '-',
|
69 |
|
|
'.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A',
|
70 |
|
|
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
|
71 |
|
|
'V', 'W', 'X', 'Y', 'Z', '[', '\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
72 |
|
|
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~');
|
73 |
|
|
|
74 |
|
|
-- generators --
|
75 |
|
|
signal clk_gen, rst_gen : std_ulogic := '0';
|
76 |
|
|
signal irq, irq_ack : std_ulogic_vector(7 downto 0);
|
77 |
|
|
|
78 |
|
|
-- local signals --
|
79 |
|
|
signal uart_txd : std_ulogic;
|
80 |
|
|
signal spi_data : std_ulogic;
|
81 |
|
|
|
82 |
|
|
-- simulation uart receiver --
|
83 |
|
|
signal uart_rx_sync : std_ulogic_vector(04 downto 0) := (others => '1');
|
84 |
|
|
signal uart_rx_busy : std_ulogic := '0';
|
85 |
|
|
signal uart_rx_sreg : std_ulogic_vector(08 downto 0) := (others => '0');
|
86 |
|
|
signal uart_rx_baud_cnt : real;
|
87 |
|
|
signal uart_rx_bitcnt : natural;
|
88 |
|
|
|
89 |
|
|
-- twi --
|
90 |
|
|
signal twi_sda : std_logic;
|
91 |
|
|
signal twi_scl : std_logic;
|
92 |
|
|
|
93 |
|
|
begin
|
94 |
|
|
|
95 |
|
|
-- Clock/Reset Generator ----------------------------------------------------
|
96 |
|
|
-- -----------------------------------------------------------------------------
|
97 |
|
|
clk_gen <= not clk_gen after (t_clock_c/2);
|
98 |
|
|
rst_gen <= '0', '1' after 60*(t_clock_c/2);
|
99 |
|
|
|
100 |
|
|
|
101 |
|
|
-- CPU Core -----------------------------------------------------------------
|
102 |
|
|
-- -----------------------------------------------------------------------------
|
103 |
|
|
neo430_top_inst: neo430_top
|
104 |
|
|
generic map (
|
105 |
|
|
-- general configuration --
|
106 |
|
|
CLOCK_SPEED => f_clk_c, -- main clock in Hz
|
107 |
|
|
IMEM_SIZE => 4*1024, -- internal IMEM size in bytes, max 48kB (default=4kB)
|
108 |
|
|
DMEM_SIZE => 2*1024, -- internal DMEM size in bytes, max 12kB (default=2kB)
|
109 |
|
|
-- additional configuration --
|
110 |
|
|
USER_CODE => x"4788", -- custom user code
|
111 |
|
|
-- module configuration --
|
112 |
|
|
MULDIV_USE => true, -- implement multiplier/divider unit? (default=true)
|
113 |
|
|
WB32_USE => true, -- implement WB32 unit? (default=true)
|
114 |
|
|
WDT_USE => true, -- implement WBT? (default=true)
|
115 |
|
|
GPIO_USE => true, -- implement GPIO unit? (default=true)
|
116 |
|
|
TIMER_USE => true, -- implement timer? (default=true)
|
117 |
|
|
UART_USE => true, -- implement UART? (default=true)
|
118 |
|
|
CRC_USE => true, -- implement CRC unit? (default=true)
|
119 |
|
|
CFU_USE => false, -- implement custom functions unit? (default=false)
|
120 |
|
|
PWM_USE => true, -- implement PWM controller? (default=true)
|
121 |
|
|
TWI_USE => true, -- implement two wire serial interface? (default=true)
|
122 |
|
|
SPI_USE => true, -- implement SPI? (default=true)
|
123 |
|
|
TRNG_USE => false, -- implement TRNG? (default=false) - CANNOT BE SIMULATED!
|
124 |
|
|
EXIRQ_USE => true, -- implement EXIRQ? (default=true)
|
125 |
|
|
FREQ_GEN_USE => true, -- implement FREQ_GEN? (default=true)
|
126 |
|
|
-- boot configuration --
|
127 |
|
|
BOOTLD_USE => false, -- implement and use bootloader? (default=true)
|
128 |
|
|
IMEM_AS_ROM => false -- implement IMEM as read-only memory? (default=false)
|
129 |
|
|
)
|
130 |
|
|
port map (
|
131 |
|
|
-- global control --
|
132 |
|
|
clk_i => clk_gen, -- global clock, rising edge
|
133 |
|
|
rst_i => rst_gen, -- global reset, async, low-active
|
134 |
|
|
-- gpio --
|
135 |
|
|
gpio_o => open, -- parallel output
|
136 |
|
|
gpio_i => x"0000", -- parallel input
|
137 |
|
|
-- pwm channels --
|
138 |
|
|
pwm_o => open, -- pwm channels
|
139 |
|
|
-- arbitrary frequency generator --
|
140 |
|
|
freq_gen_o => open, -- programmable frequency output
|
141 |
|
|
-- serial com --
|
142 |
|
|
uart_txd_o => uart_txd, -- UART send data
|
143 |
|
|
uart_rxd_i => uart_txd, -- UART receive data
|
144 |
|
|
spi_sclk_o => open, -- serial clock line
|
145 |
|
|
spi_mosi_o => spi_data, -- serial data line out
|
146 |
|
|
spi_miso_i => spi_data, -- serial data line in
|
147 |
|
|
spi_cs_o => open, -- SPI CS 0..5
|
148 |
|
|
twi_sda_io => twi_sda, -- twi serial data line
|
149 |
|
|
twi_scl_io => twi_scl, -- twi serial clock line
|
150 |
|
|
-- 32-bit wishbone interface --
|
151 |
|
|
wb_adr_o => open, -- address
|
152 |
|
|
wb_dat_i => x"00000000", -- read data
|
153 |
|
|
wb_dat_o => open, -- write data
|
154 |
|
|
wb_we_o => open, -- read/write
|
155 |
|
|
wb_sel_o => open, -- byte enable
|
156 |
|
|
wb_stb_o => open, -- strobe
|
157 |
|
|
wb_cyc_o => open, -- valid cycle
|
158 |
|
|
wb_ack_i => '0', -- transfer acknowledge
|
159 |
|
|
-- external interrupts --
|
160 |
|
|
ext_irq_i => irq, -- external interrupt request lines
|
161 |
|
|
ext_ack_o => irq_ack -- external interrupt request acknowledges
|
162 |
|
|
);
|
163 |
|
|
|
164 |
|
|
-- twi pull-ups --
|
165 |
|
|
twi_sda <= 'H';
|
166 |
|
|
twi_scl <= 'H';
|
167 |
|
|
|
168 |
|
|
|
169 |
|
|
-- Interrupt Generator ------------------------------------------------------
|
170 |
|
|
-- -----------------------------------------------------------------------------
|
171 |
|
|
interrupt_gen: process
|
172 |
|
|
begin
|
173 |
|
|
irq <= (others => '0');
|
174 |
|
|
wait for 20 ms;
|
175 |
|
|
wait until rising_edge(clk_gen);
|
176 |
|
|
irq <= "00000111";
|
177 |
|
|
wait for t_clock_c;
|
178 |
|
|
wait;
|
179 |
|
|
end process interrupt_gen;
|
180 |
|
|
|
181 |
|
|
|
182 |
|
|
-- Console UART Receiver ----------------------------------------------------
|
183 |
|
|
-- -----------------------------------------------------------------------------
|
184 |
|
|
uart_rx_unit: process(clk_gen)
|
185 |
|
|
variable i, j : integer;
|
186 |
|
|
variable line_tmp : line;
|
187 |
|
|
begin
|
188 |
|
|
|
189 |
|
|
-- "UART" --
|
190 |
|
|
if rising_edge(clk_gen) then
|
191 |
|
|
-- synchronizer --
|
192 |
|
|
uart_rx_sync <= uart_rx_sync(3 downto 0) & uart_txd;
|
193 |
|
|
-- arbiter --
|
194 |
|
|
if (uart_rx_busy = '0') then -- idle
|
195 |
|
|
uart_rx_busy <= '0';
|
196 |
|
|
uart_rx_baud_cnt <= round(0.5 * baud_val_c);
|
197 |
|
|
uart_rx_bitcnt <= 9;
|
198 |
|
|
if (uart_rx_sync(4 downto 1) = "1100") then -- start bit? (falling edge)
|
199 |
|
|
uart_rx_busy <= '1';
|
200 |
|
|
end if;
|
201 |
|
|
else
|
202 |
|
|
if (uart_rx_baud_cnt = 0.0) then
|
203 |
|
|
-- adapt to the inter-frame pause - which is not implemented in the neo430 uart ;)
|
204 |
|
|
if (uart_rx_bitcnt = 1) then
|
205 |
|
|
uart_rx_baud_cnt <= round(0.5 * baud_val_c);
|
206 |
|
|
else
|
207 |
|
|
uart_rx_baud_cnt <= round(baud_val_c);
|
208 |
|
|
end if;
|
209 |
|
|
if (uart_rx_bitcnt = 0) then
|
210 |
|
|
uart_rx_busy <= '0'; -- done
|
211 |
|
|
i := to_integer(unsigned(uart_rx_sreg(8 downto 1)));
|
212 |
|
|
j := i - 32;
|
213 |
|
|
if (j < 0) or (j > 95) then
|
214 |
|
|
j := 0; -- undefined = SPACE
|
215 |
|
|
end if;
|
216 |
|
|
|
217 |
|
|
if (i < 32) or (j > 32+95) then
|
218 |
|
|
report "UART TX: (" & integer'image(i) & ")"; -- print code
|
219 |
|
|
else
|
220 |
|
|
report "UART TX: " & ascii_lut(j); -- print ASCII
|
221 |
|
|
end if;
|
222 |
|
|
|
223 |
|
|
if (i = 10) then -- Linux line break
|
224 |
|
|
writeline(file_uart_tx_out, line_tmp);
|
225 |
|
|
elsif (i /= 13) then -- Remove additional carriage return
|
226 |
|
|
write(line_tmp, ascii_lut(j));
|
227 |
|
|
end if;
|
228 |
|
|
else
|
229 |
|
|
uart_rx_sreg <= uart_rx_sync(4) & uart_rx_sreg(8 downto 1);
|
230 |
|
|
uart_rx_bitcnt <= uart_rx_bitcnt - 1;
|
231 |
|
|
end if;
|
232 |
|
|
else
|
233 |
|
|
uart_rx_baud_cnt <= uart_rx_baud_cnt - 1.0;
|
234 |
|
|
end if;
|
235 |
|
|
end if;
|
236 |
|
|
end if;
|
237 |
|
|
end process uart_rx_unit;
|
238 |
|
|
|
239 |
|
|
|
240 |
|
|
end neo430_tb_rtl;
|