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

Subversion Repositories potato

[/] [potato/] [trunk/] [src/] [pp_execute.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 - 2015 <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
 
9
use work.pp_types.all;
10
use work.pp_csr.all;
11
use work.pp_utilities.all;
12
 
13
entity pp_execute is
14
        port(
15
                clk    : in std_logic;
16
                reset  : in std_logic;
17
 
18
                stall, flush : in std_logic;
19
 
20
                -- IRQ input:
21
                irq : in std_logic_vector(7 downto 0);
22
 
23
                -- Data memory outputs:
24
                dmem_address   : out std_logic_vector(31 downto 0);
25
                dmem_data_out  : out std_logic_vector(31 downto 0);
26
                dmem_data_size : out std_logic_vector( 1 downto 0);
27
                dmem_read_req  : out std_logic;
28
                dmem_write_req : out std_logic;
29
 
30
                -- Register addresses:
31
                rs1_addr_in, rs2_addr_in, rd_addr_in : in  register_address;
32
                rd_addr_out                          : out register_address;
33
 
34
                -- Register values:
35
                rs1_data_in, rs2_data_in : in std_logic_vector(31 downto 0);
36
                rd_data_out              : out std_logic_vector(31 downto 0);
37
 
38
                -- Constant values:
39
                shamt_in     : in std_logic_vector(4 downto 0);
40
                immediate_in : in std_logic_vector(31 downto 0);
41
 
42
                -- Instruction address:
43
                pc_in     : in  std_logic_vector(31 downto 0);
44
                pc_out    : out std_logic_vector(31 downto 0);
45
 
46
                -- Funct3 value from the instruction, used to choose which comparison
47
                -- is used when branching:
48
                funct3_in : in std_logic_vector(2 downto 0);
49
 
50
                -- CSR signals:
51
                csr_addr_in          : in  csr_address;
52
                csr_addr_out         : out csr_address;
53
                csr_write_in         : in  csr_write_mode;
54
                csr_write_out        : out csr_write_mode;
55
                csr_value_in         : in  std_logic_vector(31 downto 0);
56
                csr_value_out        : out std_logic_vector(31 downto 0);
57
                csr_writeable_in     : in  boolean;
58
                csr_use_immediate_in : in  std_logic;
59
 
60
                -- Control signals:
61
                alu_op_in    : in  alu_operation;
62
                alu_x_src_in : in  alu_operand_source;
63
                alu_y_src_in : in  alu_operand_source;
64
                rd_write_in  : in  std_logic;
65
                rd_write_out : out std_logic;
66
                branch_in    : in  branch_type;
67
                branch_out   : out branch_type;
68
 
69
                -- Memory control signals:
70
                mem_op_in    : in  memory_operation_type;
71
                mem_op_out   : out memory_operation_type;
72
                mem_size_in  : in  memory_operation_size;
73
                mem_size_out : out memory_operation_size;
74
 
75
                -- Whether the instruction should be counted:
76
                count_instruction_in  : in  std_logic;
77
                count_instruction_out : out std_logic;
78
 
79
                -- Exception control registers:
80
                status_in : in  csr_status_register;
81
                evec_in   : in  std_logic_vector(31 downto 0);
82
                evec_out  : out std_logic_vector(31 downto 0);
83
 
84
                -- Exception signals:
85
                decode_exception_in       : in std_logic;
86
                decode_exception_cause_in : in csr_exception_cause;
87
 
88
                -- Exception outputs:
89
                exception_out         : out std_logic;
90
                exception_context_out : out csr_exception_context;
91
 
92
                -- Control outputs:
93
                jump_out        : out std_logic;
94
                jump_target_out : out std_logic_vector(31 downto 0);
95
 
96
                -- Inputs to the forwarding logic from the MEM stage:
97
                mem_rd_write          : in std_logic;
98
                mem_rd_addr           : in register_address;
99
                mem_rd_value          : in std_logic_vector(31 downto 0);
100
                mem_csr_addr          : in csr_address;
101
                mem_csr_write         : in csr_write_mode;
102
                mem_csr_value         : in std_logic_vector(31 downto 0);
103
                mem_exception         : in std_logic;
104
                mem_exception_context : in csr_exception_context;
105
 
106
                -- Inputs to the forwarding logic from the WB stage:
107
                wb_rd_write          : in std_logic;
108
                wb_rd_addr           : in register_address;
109
                wb_rd_value          : in std_logic_vector(31 downto 0);
110
                wb_csr_addr          : in csr_address;
111
                wb_csr_write         : in csr_write_mode;
112
                wb_csr_value         : in std_logic_vector(31 downto 0);
113
                wb_exception         : in std_logic;
114
                wb_exception_context : in csr_exception_context;
115
 
116
                -- Hazard detection unit signals:
117
                mem_mem_op : in memory_operation_type;
118
                hazard_detected : out std_logic
119
        );
120
end entity pp_execute;
121
 
122
architecture behaviour of pp_execute is
123
        signal alu_op : alu_operation;
124
        signal alu_x_src, alu_y_src : alu_operand_source;
125
 
126
        signal alu_x, alu_y, alu_result : std_logic_vector(31 downto 0);
127
 
128
        signal rs1_addr, rs2_addr : register_address;
129
        signal rs1_data, rs2_data : std_logic_vector(31 downto 0);
130
 
131
        signal mem_op : memory_operation_type;
132
        signal mem_size : memory_operation_size;
133
 
134
        signal pc        : std_logic_vector(31 downto 0);
135
        signal immediate : std_logic_vector(31 downto 0);
136
        signal shamt     : std_logic_vector( 4 downto 0);
137
        signal funct3    : std_logic_vector( 2 downto 0);
138
 
139
        signal rs1_forwarded, rs2_forwarded : std_logic_vector(31 downto 0);
140
 
141
        signal branch : branch_type;
142
        signal branch_condition : std_logic;
143
        signal jump_target : std_logic_vector(31 downto 0);
144
 
145
        signal sr : csr_status_register;
146
        signal evec, evec_forwarded : std_logic_vector(31 downto 0);
147
 
148
        signal csr_write : csr_write_mode;
149
        signal csr_addr  : csr_address;
150
        signal csr_use_immediate : std_logic;
151
        signal csr_writeable : boolean;
152
 
153
        signal csr_value, csr_value_forwarded : std_logic_vector(31 downto 0);
154
 
155
        signal decode_exception : std_logic;
156
        signal decode_exception_cause : csr_exception_cause;
157
 
158
        signal exception_taken : std_logic;
159
        signal exception_cause : csr_exception_cause;
160
        signal exception_vaddr : std_logic_vector(31 downto 0);
161
 
162
        signal exception_context_forwarded : csr_exception_context;
163
 
164
        signal data_misaligned, instr_misaligned : std_logic;
165
 
166
        signal irq_asserted : std_logic;
167
        signal irq_asserted_num : std_logic_vector(3 downto 0);
168
begin
169
 
170
        -- Register values should not be latched in by a clocked process,
171
        -- this is already done in the register files.
172
        csr_value <= csr_value_in;
173
        rd_data_out <= alu_result;
174
 
175
        branch_out <= branch;
176
 
177
        mem_op_out <= mem_op;
178
        mem_size_out <= mem_size;
179
 
180
        csr_write_out <= csr_write;
181
        csr_addr_out  <= csr_addr;
182
 
183
        pc_out <= pc;
184
 
185
        exception_out <= exception_taken;
186
        exception_context_out <= (
187
                                status => exception_context_forwarded.status,
188
                                cause => exception_cause,
189
                                badvaddr => exception_vaddr
190
                        ) when exception_taken = '1' else exception_context_forwarded;
191
 
192
        jump_out <= to_std_logic(branch = BRANCH_JUMP or branch = BRANCH_JUMP_INDIRECT)
193
                or (to_std_logic(branch = BRANCH_CONDITIONAL) and branch_condition)
194
                or to_std_logic(branch = BRANCH_SRET);
195
        jump_target_out <= jump_target;
196
 
197
        evec_out <= evec_forwarded;
198
        exception_taken <= decode_exception or to_std_logic(exception_cause /= CSR_CAUSE_NONE) or irq_asserted;
199
 
200
        irq_asserted <= to_std_logic(exception_context_forwarded.status.ei = '1' and
201
                (irq and exception_context_forwarded.status.im) /= x"00");
202
 
203
        rs1_data <= rs1_data_in;
204
        rs2_data <= rs2_data_in;
205
 
206
        dmem_address <= alu_result;
207
        dmem_data_out <= rs2_forwarded;
208
        dmem_write_req <= '1' when mem_op = MEMOP_TYPE_STORE else '0';
209
        dmem_read_req <= '1' when memop_is_load(mem_op) else '0';
210
 
211
        pipeline_register: process(clk)
212
        begin
213
                if rising_edge(clk) then
214
                        if reset = '1' or flush = '1' then
215
                                rd_write_out <= '0';
216
                                branch <= BRANCH_NONE;
217
                                csr_write <= CSR_WRITE_NONE;
218
                                mem_op <= MEMOP_TYPE_NONE;
219
                                decode_exception <= '0';
220
                                count_instruction_out <= '0';
221
                        elsif stall = '0' then
222
                                pc <= pc_in;
223
                                count_instruction_out <= count_instruction_in;
224
 
225
                                -- Register signals:
226
                                rd_write_out <= rd_write_in;
227
                                rd_addr_out <= rd_addr_in;
228
                                rs1_addr <= rs1_addr_in;
229
                                rs2_addr <= rs2_addr_in;
230
 
231
                                -- ALU signals:
232
                                alu_op <= alu_op_in;
233
                                alu_x_src <= alu_x_src_in;
234
                                alu_y_src <= alu_y_src_in;
235
 
236
                                -- Control signals:
237
                                branch <= branch_in;
238
                                mem_op <= mem_op_in;
239
                                mem_size <= mem_size_in;
240
 
241
                                -- Constant values:
242
                                immediate <= immediate_in;
243
                                shamt <= shamt_in;
244
                                funct3 <= funct3_in;
245
 
246
                                -- CSR signals:
247
                                csr_write <= csr_write_in;
248
                                csr_addr <= csr_addr_in;
249
                                csr_use_immediate <= csr_use_immediate_in;
250
                                csr_writeable <= csr_writeable_in;
251
 
252
                                -- Status register;
253
                                sr <= status_in;
254
 
255
                                -- Exception vector base:
256
                                evec <= evec_in;
257
 
258
                                -- Instruction decoder exceptions:
259
                                decode_exception <= decode_exception_in;
260
                                decode_exception_cause <= decode_exception_cause_in;
261
                        end if;
262
                end if;
263
        end process pipeline_register;
264
 
265
        set_data_size: process(mem_size)
266
        begin
267
                case mem_size is
268
                        when MEMOP_SIZE_BYTE =>
269
                                dmem_data_size <= b"01";
270
                        when MEMOP_SIZE_HALFWORD =>
271
                                dmem_data_size <= b"10";
272
                        when MEMOP_SIZE_WORD =>
273
                                dmem_data_size <= b"00";
274
                        when others =>
275
                                dmem_data_size <= b"11";
276
                end case;
277
        end process set_data_size;
278
 
279
        get_irq_num: process(irq, exception_context_forwarded)
280
                variable temp : std_logic_vector(3 downto 0);
281
        begin
282
                temp := (others => '0');
283
 
284
                for i in 0 to 7 loop
285
                        if irq(i) = '1' and exception_context_forwarded.status.im(i) = '1' then
286
                                temp := std_logic_vector(to_unsigned(i, temp'length));
287
                                exit;
288
                        end if;
289
                end loop;
290
 
291
                irq_asserted_num <= temp;
292
        end process get_irq_num;
293
 
294
        data_misalign_check: process(mem_size, alu_result)
295
        begin
296
                case mem_size is
297
                        when MEMOP_SIZE_HALFWORD =>
298
                                if alu_result(0) /= '0' then
299
                                        data_misaligned <= '1';
300
                                else
301
                                        data_misaligned <= '0';
302
                                end if;
303
                        when MEMOP_SIZE_WORD =>
304
                                if alu_result(1 downto 0) /= b"00" then
305
                                        data_misaligned <= '1';
306
                                else
307
                                        data_misaligned <= '0';
308
                                end if;
309
                        when others =>
310
                                data_misaligned <= '0';
311
                end case;
312
        end process data_misalign_check;
313
 
314
        instr_misalign_check: instr_misaligned <= '1' when jump_target(1 downto 0) /= b"00" else '0';
315
 
316
        find_exception_cause: process(decode_exception, decode_exception_cause, mem_op,
317
                data_misaligned, instr_misaligned, irq_asserted, irq_asserted_num)
318
        begin
319
                if irq_asserted = '1' then
320
                        exception_cause <= std_logic_vector(unsigned(CSR_CAUSE_IRQ_BASE) + unsigned(irq_asserted_num));
321
                elsif decode_exception = '1' then
322
                        exception_cause <= decode_exception_cause;
323
                elsif mem_op = MEMOP_TYPE_INVALID then
324
                        exception_cause <= CSR_CAUSE_INVALID_INSTR;
325
                elsif instr_misaligned = '1' then
326
                        exception_cause <= CSR_CAUSE_INSTR_MISALIGN;
327
                elsif data_misaligned = '1' and mem_op = MEMOP_TYPE_STORE then
328
                        exception_cause <= CSR_CAUSE_STORE_MISALIGN;
329
                elsif data_misaligned = '1' and memop_is_load(mem_op) then
330
                        exception_cause <= CSR_CAUSE_LOAD_MISALIGN;
331
                else
332
                        exception_cause <= CSR_CAUSE_NONE;
333
                end if;
334
        end process find_exception_cause;
335
 
336
        find_exception_vaddr: process(instr_misaligned, data_misaligned, jump_target, alu_result)
337
        begin
338
                if instr_misaligned = '1' then
339
                        exception_vaddr <= jump_target;
340
                elsif data_misaligned = '1' then
341
                        exception_vaddr <= alu_result;
342
                else
343
                        exception_vaddr <= (others => '0');
344
                end if;
345
        end process find_exception_vaddr;
346
 
347
        calc_jump_tgt: process(branch, pc, rs1_forwarded, immediate, csr_value_forwarded)
348
        begin
349
                case branch is
350
                        when BRANCH_JUMP | BRANCH_CONDITIONAL =>
351
                                jump_target <= std_logic_vector(unsigned(pc) + unsigned(immediate));
352
                        when BRANCH_JUMP_INDIRECT =>
353
                                jump_target <= std_logic_vector(unsigned(rs1_forwarded) + unsigned(immediate));
354
                        when BRANCH_SRET =>
355
                                jump_target <= csr_value_forwarded; -- Will be the EPC value in the case of SRET
356
                        when others =>
357
                                jump_target <= (others => '0');
358
                end case;
359
        end process calc_jump_tgt;
360
 
361
        alu_x_mux: entity work.pp_alu_mux
362
                port map(
363
                        source => alu_x_src,
364
                        register_value => rs1_forwarded,
365
                        immediate_value => immediate,
366
                        shamt_value => shamt,
367
                        pc_value => pc,
368
                        csr_value => csr_value_forwarded,
369
                        output => alu_x
370
                );
371
 
372
        alu_y_mux: entity work.pp_alu_mux
373
                port map(
374
                        source => alu_y_src,
375
                        register_value => rs2_forwarded,
376
                        immediate_value => immediate,
377
                        shamt_value => shamt,
378
                        pc_value => pc,
379
                        csr_value => csr_value_forwarded,
380
                        output => alu_y
381
                );
382
 
383
        alu_x_forward: process(mem_rd_write, mem_rd_value, mem_rd_addr, rs1_addr,
384
                rs1_data, wb_rd_write, wb_rd_addr, wb_rd_value)
385
        begin
386
                if mem_rd_write = '1' and mem_rd_addr = rs1_addr and mem_rd_addr /= b"00000" then
387
                        rs1_forwarded <= mem_rd_value;
388
                elsif wb_rd_write = '1' and wb_rd_addr = rs1_addr and wb_rd_addr /= b"00000" then
389
                        rs1_forwarded <= wb_rd_value;
390
                else
391
                        rs1_forwarded <= rs1_data;
392
                end if;
393
        end process alu_x_forward;
394
 
395
        alu_y_forward: process(mem_rd_write, mem_rd_value, mem_rd_addr, rs2_addr,
396
                rs2_data, wb_rd_write, wb_rd_addr, wb_rd_value)
397
        begin
398
                if mem_rd_write = '1' and mem_rd_addr = rs2_addr and mem_rd_addr /= b"00000" then
399
                        rs2_forwarded <= mem_rd_value;
400
                elsif wb_rd_write = '1' and wb_rd_addr = rs2_addr and wb_rd_addr /= b"00000" then
401
                        rs2_forwarded <= wb_rd_value;
402
                else
403
                        rs2_forwarded <= rs2_data;
404
                end if;
405
        end process alu_y_forward;
406
 
407
        csr_forward: process(mem_csr_write, wb_csr_write, csr_addr, mem_csr_addr, wb_csr_addr,
408
                csr_value, mem_csr_value, wb_csr_value, csr_writeable, mem_exception, wb_exception,
409
                mem_exception_context, wb_exception_context)
410
        begin
411
                if csr_addr = CSR_CAUSE and mem_exception = '1' then
412
                        csr_value_forwarded <= to_std_logic_vector(mem_exception_context.cause);
413
                elsif csr_addr = CSR_STATUS and mem_exception = '1' then
414
                        csr_value_forwarded <= to_std_logic_vector(mem_exception_context.status);
415
                elsif csr_addr = CSR_BADVADDR and mem_exception = '1' then
416
                        csr_value_forwarded <= mem_exception_context.badvaddr;
417
                elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = csr_addr and csr_writeable then
418
                        csr_value_forwarded <= mem_csr_value;
419
                elsif csr_addr = CSR_CAUSE and wb_exception = '1' then
420
                        csr_value_forwarded <= to_std_logic_vector(wb_exception_context.cause);
421
                elsif csr_addr = CSR_STATUS and wb_exception = '1' then
422
                        csr_value_forwarded <= to_std_logic_vector(wb_exception_context.status);
423
                elsif csr_addr = CSR_BADVADDR and wb_exception = '1' then
424
                        csr_value_forwarded <= wb_exception_context.badvaddr;
425
                elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = csr_addr and csr_writeable then
426
                        csr_value_forwarded <= wb_csr_value;
427
                else
428
                        csr_value_forwarded <= csr_value;
429
                end if;
430
        end process csr_forward;
431
 
432
        evec_forward: process(mem_csr_write, mem_csr_addr, mem_csr_value,
433
                wb_csr_write, wb_csr_addr, wb_csr_value, evec)
434
        begin
435
                if mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_EVEC then
436
                        evec_forwarded <= mem_csr_value;
437
                elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_EVEC then
438
                        evec_forwarded <= wb_csr_value;
439
                else
440
                        evec_forwarded <= evec;
441
                end if;
442
        end process evec_forward;
443
 
444
        exception_ctx_forward: process(mem_exception, wb_exception, mem_exception_context, wb_exception_context,
445
                exception_cause, exception_vaddr, mem_csr_write, mem_csr_addr, mem_csr_value,
446
                wb_csr_write, wb_csr_addr, wb_csr_value, sr)
447
        begin
448
                if mem_exception = '1' then
449
                        exception_context_forwarded <= mem_exception_context;
450
                elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_STATUS then
451
                        exception_context_forwarded <= (
452
                                status => to_csr_status_register(mem_csr_value),
453
                                cause => mem_exception_context.cause,
454
                                badvaddr => mem_exception_context.badvaddr);
455
                elsif wb_exception = '1' then
456
                        exception_context_forwarded <= wb_exception_context;
457
                elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_STATUS then
458
                        exception_context_forwarded <= (
459
                                status => to_csr_status_register(wb_csr_value),
460
                                cause => wb_exception_context.cause,
461
                                badvaddr => wb_exception_context.badvaddr);
462
                else
463
                        exception_context_forwarded.status <= sr;
464
                        exception_context_forwarded.cause <= exception_cause;
465
                        exception_context_forwarded.badvaddr <= exception_vaddr;
466
                end if;
467
        end process exception_ctx_forward;
468
 
469
        detect_load_hazard: process(mem_mem_op, mem_rd_addr, rs1_addr, rs2_addr,
470
                alu_x_src, alu_y_src)
471
        begin
472
                if (mem_mem_op = MEMOP_TYPE_LOAD or mem_mem_op = MEMOP_TYPE_LOAD_UNSIGNED) and
473
                                ((alu_x_src = ALU_SRC_REG and mem_rd_addr = rs1_addr and rs1_addr /= b"00000")
474
                        or
475
                                (alu_y_src = ALU_SRC_REG and mem_rd_addr = rs2_addr and rs2_addr /= b"00000"))
476
                then
477
                        hazard_detected <= '1';
478
                else
479
                        hazard_detected <= '0';
480
                end if;
481
        end process detect_load_hazard;
482
 
483
        branch_comparator: entity work.pp_comparator
484
                port map(
485
                        funct3 => funct3,
486
                        rs1 => rs1_forwarded,
487
                        rs2 => rs2_forwarded,
488
                        result => branch_condition
489
                );
490
 
491
        alu_instance: entity work.pp_alu
492
                port map(
493
                        result => alu_result,
494
                        x => alu_x,
495
                        y => alu_y,
496
                        operation => alu_op
497
                );
498
 
499
        csr_alu_instance: entity work.pp_csr_alu
500
                port map(
501
                        x => csr_value_forwarded,
502
                        y => rs1_forwarded,
503
                        result => csr_value_out,
504
                        immediate => rs1_addr,
505
                        use_immediate => csr_use_immediate,
506
                        write_mode => csr_write
507
                );
508
 
509
 
510
end architecture behaviour;

powered by: WebSVN 2.1.0

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