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

Subversion Repositories potato

[/] [potato/] [trunk/] [testbenches/] [tb_processor.vhd] - Blame information for rev 58

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 skordal
-- The Potato Processor - A simple processor for FPGAs
2
-- (c) Kristian Klomsten Skordal 2014 <kristian.skordal@wafflemail.net>
3 3 skordal
-- Report bugs and issues on <http://opencores.org/project,potato,bugtracker>
4 2 skordal
 
5
library ieee;
6
use ieee.std_logic_1164.all;
7
use ieee.numeric_std.all;
8
use ieee.std_logic_textio.all;
9
use std.textio.all;
10
 
11
use work.pp_constants.all;
12
 
13
entity tb_processor is
14
        generic(
15 58 skordal
                IMEM_SIZE : natural := 4096; --! Size of the instruction memory in bytes.
16
                DMEM_SIZE : natural := 4096; --! Size of the data memory in bytes.
17
                RESET_ADDRESS   : std_logic_vector := x"00000200"; --! Processor reset address
18
                IMEM_START_ADDR : std_logic_vector := x"00000100"; --! Instruction memory start address
19
                IMEM_FILENAME   : string := "imem_testfile.hex";   --! File containing the contents of instruction memory.
20
                DMEM_FILENAME   : string := "dmem_testfile.hex"    --! File containing the contents of data memory.
21 2 skordal
        );
22
end entity tb_processor;
23
 
24
architecture testbench of tb_processor is
25
 
26
        -- Clock signal:
27
        signal clk : std_logic := '0';
28
        constant clk_period : time := 10 ns;
29
 
30 58 skordal
        -- Timer clock signal:
31
        signal timer_clk : std_logic := '0';
32
        constant timer_clk_period : time := 100 ns;
33
 
34 2 skordal
        -- Common inputs:
35
        signal reset  : std_logic := '1';
36
 
37
        -- Instruction memory interface:
38
        signal imem_address : std_logic_vector(31 downto 0);
39
        signal imem_data_in : std_logic_vector(31 downto 0) := (others => '0');
40
        signal imem_req     : std_logic;
41
        signal imem_ack     : std_logic := '0';
42
 
43
        -- Data memory interface:
44
        signal dmem_address   : std_logic_vector(31 downto 0);
45
        signal dmem_data_in   : std_logic_vector(31 downto 0) := (others => '0');
46
        signal dmem_data_out  : std_logic_vector(31 downto 0);
47
        signal dmem_data_size : std_logic_vector( 1 downto 0);
48
        signal dmem_read_req, dmem_write_req : std_logic;
49
        signal dmem_read_ack, dmem_write_ack : std_logic := '1';
50
 
51
        -- Tohost/Fromhost:
52
        signal tohost_data       : std_logic_vector(31 downto 0);
53
        signal fromhost_data     : std_logic_vectoR(31 downto 0) := (others => '0');
54
        signal tohost_write_en   : std_logic;
55
        signal fromhost_write_en : std_logic := '0';
56
 
57
        -- External interrupt input:
58
        signal irq : std_logic_vector(7 downto 0) := (others => '0');
59
 
60
        -- Simulation initialized:
61
        signal imem_initialized, dmem_initialized, initialized : boolean := false;
62
 
63
        -- Memory array type:
64
        type memory_array is array(natural range <>) of std_logic_vector(7 downto 0);
65
        constant IMEM_BASE : natural := 0;
66 58 skordal
        constant IMEM_END  : natural := IMEM_BASE + IMEM_SIZE - 1;
67
        constant DMEM_BASE : natural := IMEM_END + 1;
68
        constant DMEM_END  : natural := IMEM_END + DMEM_SIZE;
69 2 skordal
 
70
        -- Memories:
71
        signal imem_memory : memory_array(IMEM_BASE to IMEM_END);
72
        signal dmem_memory : memory_array(DMEM_BASE to DMEM_END);
73
 
74
        signal simulation_finished : boolean := false;
75
 
76
begin
77
 
78 58 skordal
        uut: entity work.pp_core
79
                generic map(
80
                        RESET_ADDRESS => RESET_ADDRESS
81
                ) port map(
82 2 skordal
                        clk => clk,
83
                        reset => reset,
84 58 skordal
                        timer_clk => timer_clk,
85 2 skordal
                        imem_address => imem_address,
86
                        imem_data_in => imem_data_in,
87
                        imem_req => imem_req,
88
                        imem_ack => imem_ack,
89
                        dmem_address => dmem_address,
90
                        dmem_data_in => dmem_data_in,
91
                        dmem_data_out => dmem_data_out,
92
                        dmem_data_size => dmem_data_size,
93
                        dmem_read_req => dmem_read_req,
94
                        dmem_read_ack => dmem_read_ack,
95
                        dmem_write_req => dmem_write_req,
96
                        dmem_write_ack => dmem_write_ack,
97
                        tohost_data => tohost_data,
98
                        tohost_write_en => tohost_write_en,
99
                        fromhost_data => fromhost_data,
100
                        fromhost_write_en => fromhost_write_en,
101
                        irq => irq
102
                );
103
 
104
        clock: process
105
        begin
106
                clk <= '0';
107
                wait for clk_period / 2;
108
                clk <= '1';
109
                wait for clk_period / 2;
110
 
111
                if simulation_finished then
112
                        wait;
113
                end if;
114
        end process clock;
115
 
116 58 skordal
        timer_clock: process
117
        begin
118
                timer_clk <= '0';
119
                wait for timer_clk_period / 2;
120
                timer_clk <= '1';
121
                wait for timer_clk_period / 2;
122
 
123
                if simulation_finished then
124
                        wait;
125
                end if;
126
        end process timer_clock;
127
 
128 2 skordal
        --! Initializes the instruction memory from file.
129
        imem_init: process
130
                file imem_file : text open READ_MODE is IMEM_FILENAME;
131
                variable input_line  : line;
132
                variable input_index : natural;
133
                variable input_value : std_logic_vector(31 downto 0);
134
        begin
135 58 skordal
                for i in to_integer(unsigned(IMEM_START_ADDR)) / 4 to IMEM_END / 4 loop
136
                --for i in IMEM_BASE / 4 to IMEM_END / 4 loop
137 2 skordal
                        if not endfile(imem_file) then
138
                                readline(imem_file, input_line);
139
                                hread(input_line, input_value);
140
                                imem_memory(i * 4 + 0) <= input_value( 7 downto  0);
141
                                imem_memory(i * 4 + 1) <= input_value(15 downto  8);
142
                                imem_memory(i * 4 + 2) <= input_value(23 downto 16);
143
                                imem_memory(i * 4 + 3) <= input_value(31 downto 24);
144
                        else
145
                                imem_memory(i * 4 + 0) <= RISCV_NOP( 7 downto 0);
146
                                imem_memory(i * 4 + 1) <= RISCV_NOP(15 downto 8);
147
                                imem_memory(i * 4 + 2) <= RISCV_NOP(23 downto 16);
148
                                imem_memory(i * 4 + 3) <= RISCV_NOP(31 downto 24);
149
                        end if;
150
                end loop;
151
 
152
                imem_initialized <= true;
153
                wait;
154
        end process imem_init;
155
 
156
        --! Initializes and handles writes to the data memory.
157
        dmem_init_and_write: process(clk)
158
                file dmem_file : text open READ_MODE is DMEM_FILENAME;
159
                variable input_line  : line;
160
                variable input_index : natural;
161
                variable input_value : std_logic_vector(31 downto 0);
162
        begin
163
                if not dmem_initialized then
164
                        for i in DMEM_BASE / 4 to DMEM_END / 4 loop
165
                                if not endfile(dmem_file) then
166
                                        readline(dmem_file, input_line);
167
                                        hread(input_line, input_value);
168
 
169
                                        -- Read from a big-endian file:
170
                                        dmem_memory(i * 4 + 3) <= input_value( 7 downto  0);
171
                                        dmem_memory(i * 4 + 2) <= input_value(15 downto  8);
172
                                        dmem_memory(i * 4 + 1) <= input_value(23 downto 16);
173
                                        dmem_memory(i * 4 + 0) <= input_value(31 downto 24);
174
                                else
175
                                        dmem_memory(i * 4 + 0) <= (others => '0');
176
                                        dmem_memory(i * 4 + 1) <= (others => '0');
177
                                        dmem_memory(i * 4 + 2) <= (others => '0');
178
                                        dmem_memory(i * 4 + 3) <= (others => '0');
179
                                end if;
180
                        end loop;
181
 
182
                        dmem_initialized <= true;
183
                end if;
184
 
185
                if rising_edge(clk) then
186
                        if dmem_write_ack = '1' then
187
                                dmem_write_ack <= '0';
188
                        elsif dmem_write_req = '1' then
189
                                case dmem_data_size is
190
                                        when b"00" => -- 32 bits
191
                                                dmem_memory(to_integer(unsigned(dmem_address)) + 0) <= dmem_data_out(7 downto 0);
192
                                                dmem_memory(to_integer(unsigned(dmem_address)) + 1) <= dmem_data_out(15 downto 8);
193
                                                dmem_memory(to_integer(unsigned(dmem_address)) + 2) <= dmem_data_out(23 downto 16);
194
                                                dmem_memory(to_integer(unsigned(dmem_address)) + 3) <= dmem_data_out(31 downto 24);
195
                                        when b"01" => -- 8 bits
196
                                                dmem_memory(to_integer(unsigned(dmem_address))) <= dmem_data_out(7 downto 0);
197
                                        when b"10" => -- 16 bits
198
                                                dmem_memory(to_integer(unsigned(dmem_address)) + 0) <= dmem_data_out( 7 downto 0);
199
                                                dmem_memory(to_integer(unsigned(dmem_address)) + 1) <= dmem_data_out(15 downto 8);
200 58 skordal
                                        when others =>
201 2 skordal
                                end case;
202
                                dmem_write_ack <= '1';
203
                        end if;
204
                end if;
205
        end process dmem_init_and_write;
206
 
207
        initialized <= imem_initialized and dmem_initialized;
208
 
209
        --! Instruction memory read process.
210
        imem_read: process(clk)
211
        begin
212
                if rising_edge(clk) then
213
                        if reset = '1' then
214
                                imem_ack <= '0';
215
                        else
216
                                if to_integer(unsigned(imem_address)) > IMEM_END then
217
                                        imem_data_in <= (others => 'X');
218
                                else
219
                                        imem_data_in <= imem_memory(to_integer(unsigned(imem_address)) + 3)
220
                                                & imem_memory(to_integer(unsigned(imem_address)) + 2)
221
                                                & imem_memory(to_integer(unsigned(imem_address)) + 1)
222
                                                & imem_memory(to_integer(unsigned(imem_address)) + 0);
223
                                end if;
224
 
225
                                imem_ack <= '1';
226
                        end if;
227
                end if;
228
        end process imem_read;
229
 
230
        --! Data memory read process.
231
        dmem_read: process(clk)
232
        begin
233
                if rising_edge(clk) then
234
                        if dmem_read_ack = '1' then
235
                                dmem_read_ack <= '0';
236
                        elsif dmem_read_req = '1' then
237
                                case dmem_data_size is
238
                                        when b"00" => -- 32 bits
239
                                                dmem_data_in <= dmem_memory(to_integer(unsigned(dmem_address) + 3))
240
                                                        & dmem_memory(to_integer(unsigned(dmem_address) + 2))
241
                                                        & dmem_memory(to_integer(unsigned(dmem_address) + 1))
242
                                                        & dmem_memory(to_integer(unsigned(dmem_address) + 0));
243
                                        when b"10" => -- 16 bits
244
                                                dmem_data_in(15 downto 8) <= dmem_memory(to_integer(unsigned(dmem_address)) + 1);
245
                                                dmem_data_in( 7 downto 0) <= dmem_memory(to_integer(unsigned(dmem_address)) + 0);
246
                                        when b"01" => -- 8  bits
247
                                                dmem_data_in(7 downto 0) <= dmem_memory(to_integer(unsigned(dmem_address)));
248 58 skordal
                                        when others =>
249 2 skordal
                                end case;
250
                                dmem_read_ack <= '1';
251
                        end if;
252
                end if;
253
        end process dmem_read;
254
 
255
        stimulus: process
256
        begin
257
                wait until initialized = true;
258
                report "Testbench initialized, starting behavioural simulation..." severity NOTE;
259
                wait for clk_period * 2;
260
 
261
                -- Release the processor from reset:
262
                reset <= '0';
263
                wait for clk_period;
264
 
265
                wait until tohost_write_en = '1';
266
                wait for clk_period; -- Let the signal "settle", because of clock edges
267
                if tohost_data = x"00000001" then
268
                        report "Success!" severity NOTE;
269
                else
270
                        report "Failure in test " & integer'image(to_integer(shift_right(unsigned(tohost_data), 1))) & "!" severity NOTE;
271
                end if;
272
 
273
                simulation_finished <= true;
274
                wait;
275
        end process stimulus;
276
 
277
end architecture testbench;

powered by: WebSVN 2.1.0

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