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

Subversion Repositories potato

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

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

powered by: WebSVN 2.1.0

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