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

Subversion Repositories potato

[/] [potato/] [trunk/] [src/] [pp_execute.vhd] - Blame information for rev 45

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 17 skordal
        signal do_jump : std_logic;
144 2 skordal
        signal jump_target : std_logic_vector(31 downto 0);
145
 
146
        signal sr : csr_status_register;
147
        signal evec, evec_forwarded : std_logic_vector(31 downto 0);
148
 
149
        signal csr_write : csr_write_mode;
150
        signal csr_addr  : csr_address;
151
        signal csr_use_immediate : std_logic;
152
        signal csr_writeable : boolean;
153
 
154
        signal csr_value, csr_value_forwarded : std_logic_vector(31 downto 0);
155
 
156
        signal decode_exception : std_logic;
157
        signal decode_exception_cause : csr_exception_cause;
158
 
159
        signal exception_taken : std_logic;
160
        signal exception_cause : csr_exception_cause;
161
        signal exception_vaddr : std_logic_vector(31 downto 0);
162
 
163
        signal exception_context_forwarded : csr_exception_context;
164
 
165
        signal data_misaligned, instr_misaligned : std_logic;
166
 
167
        signal irq_asserted : std_logic;
168
        signal irq_asserted_num : std_logic_vector(3 downto 0);
169
begin
170
 
171
        -- Register values should not be latched in by a clocked process,
172
        -- this is already done in the register files.
173
        csr_value <= csr_value_in;
174
        rd_data_out <= alu_result;
175
 
176
        branch_out <= branch;
177
 
178
        mem_op_out <= mem_op;
179
        mem_size_out <= mem_size;
180
 
181
        csr_write_out <= csr_write;
182
        csr_addr_out  <= csr_addr;
183
 
184
        pc_out <= pc;
185
 
186
        exception_out <= exception_taken;
187
        exception_context_out <= (
188
                                status => exception_context_forwarded.status,
189
                                cause => exception_cause,
190
                                badvaddr => exception_vaddr
191
                        ) when exception_taken = '1' else exception_context_forwarded;
192
 
193 35 skordal
        do_jump <= (to_std_logic(branch = BRANCH_JUMP or branch = BRANCH_JUMP_INDIRECT)
194 2 skordal
                or (to_std_logic(branch = BRANCH_CONDITIONAL) and branch_condition)
195 35 skordal
                or to_std_logic(branch = BRANCH_SRET)) and not stall;
196 17 skordal
        jump_out <= do_jump;
197 2 skordal
        jump_target_out <= jump_target;
198
 
199
        evec_out <= evec_forwarded;
200 45 skordal
        exception_taken <= (decode_exception or to_std_logic(exception_cause /= CSR_CAUSE_NONE) or irq_asserted) and not stall;
201 2 skordal
 
202 45 skordal
        irq_asserted <= to_std_logic(exception_context_forwarded.status.ei = '1' and
203 2 skordal
                (irq and exception_context_forwarded.status.im) /= x"00");
204
 
205
        rs1_data <= rs1_data_in;
206
        rs2_data <= rs2_data_in;
207
 
208
        dmem_address <= alu_result;
209
        dmem_data_out <= rs2_forwarded;
210
        dmem_write_req <= '1' when mem_op = MEMOP_TYPE_STORE else '0';
211
        dmem_read_req <= '1' when memop_is_load(mem_op) else '0';
212
 
213
        pipeline_register: process(clk)
214
        begin
215
                if rising_edge(clk) then
216
                        if reset = '1' or flush = '1' then
217
                                rd_write_out <= '0';
218
                                branch <= BRANCH_NONE;
219
                                csr_write <= CSR_WRITE_NONE;
220
                                mem_op <= MEMOP_TYPE_NONE;
221
                                decode_exception <= '0';
222
                                count_instruction_out <= '0';
223
                        elsif stall = '0' then
224
                                pc <= pc_in;
225
                                count_instruction_out <= count_instruction_in;
226
 
227
                                -- Register signals:
228
                                rd_write_out <= rd_write_in;
229
                                rd_addr_out <= rd_addr_in;
230
                                rs1_addr <= rs1_addr_in;
231
                                rs2_addr <= rs2_addr_in;
232
 
233
                                -- ALU signals:
234
                                alu_op <= alu_op_in;
235
                                alu_x_src <= alu_x_src_in;
236
                                alu_y_src <= alu_y_src_in;
237
 
238
                                -- Control signals:
239
                                branch <= branch_in;
240
                                mem_op <= mem_op_in;
241
                                mem_size <= mem_size_in;
242
 
243
                                -- Constant values:
244
                                immediate <= immediate_in;
245
                                shamt <= shamt_in;
246
                                funct3 <= funct3_in;
247
 
248
                                -- CSR signals:
249
                                csr_write <= csr_write_in;
250
                                csr_addr <= csr_addr_in;
251
                                csr_use_immediate <= csr_use_immediate_in;
252
                                csr_writeable <= csr_writeable_in;
253
 
254
                                -- Status register;
255
                                sr <= status_in;
256
 
257
                                -- Exception vector base:
258
                                evec <= evec_in;
259
 
260
                                -- Instruction decoder exceptions:
261
                                decode_exception <= decode_exception_in;
262
                                decode_exception_cause <= decode_exception_cause_in;
263
                        end if;
264
                end if;
265
        end process pipeline_register;
266
 
267
        set_data_size: process(mem_size)
268
        begin
269
                case mem_size is
270
                        when MEMOP_SIZE_BYTE =>
271
                                dmem_data_size <= b"01";
272
                        when MEMOP_SIZE_HALFWORD =>
273
                                dmem_data_size <= b"10";
274
                        when MEMOP_SIZE_WORD =>
275
                                dmem_data_size <= b"00";
276
                        when others =>
277
                                dmem_data_size <= b"11";
278
                end case;
279
        end process set_data_size;
280
 
281
        get_irq_num: process(irq, exception_context_forwarded)
282
                variable temp : std_logic_vector(3 downto 0);
283
        begin
284
                temp := (others => '0');
285
 
286
                for i in 0 to 7 loop
287
                        if irq(i) = '1' and exception_context_forwarded.status.im(i) = '1' then
288
                                temp := std_logic_vector(to_unsigned(i, temp'length));
289
                                exit;
290
                        end if;
291
                end loop;
292
 
293
                irq_asserted_num <= temp;
294
        end process get_irq_num;
295
 
296
        data_misalign_check: process(mem_size, alu_result)
297
        begin
298
                case mem_size is
299
                        when MEMOP_SIZE_HALFWORD =>
300
                                if alu_result(0) /= '0' then
301
                                        data_misaligned <= '1';
302
                                else
303
                                        data_misaligned <= '0';
304
                                end if;
305
                        when MEMOP_SIZE_WORD =>
306
                                if alu_result(1 downto 0) /= b"00" then
307
                                        data_misaligned <= '1';
308
                                else
309
                                        data_misaligned <= '0';
310
                                end if;
311
                        when others =>
312
                                data_misaligned <= '0';
313
                end case;
314
        end process data_misalign_check;
315
 
316 18 skordal
        instr_misalign_check: process(jump_target, branch, branch_condition, do_jump)
317 17 skordal
        begin
318
                if jump_target(1 downto 0) /= b"00" and do_jump = '1' then
319
                        instr_misaligned <= '1';
320
                else
321
                        instr_misaligned <= '0';
322
                end if;
323
        end process instr_misalign_check;
324 2 skordal
 
325
        find_exception_cause: process(decode_exception, decode_exception_cause, mem_op,
326
                data_misaligned, instr_misaligned, irq_asserted, irq_asserted_num)
327
        begin
328
                if irq_asserted = '1' then
329
                        exception_cause <= std_logic_vector(unsigned(CSR_CAUSE_IRQ_BASE) + unsigned(irq_asserted_num));
330
                elsif decode_exception = '1' then
331
                        exception_cause <= decode_exception_cause;
332
                elsif mem_op = MEMOP_TYPE_INVALID then
333
                        exception_cause <= CSR_CAUSE_INVALID_INSTR;
334
                elsif instr_misaligned = '1' then
335
                        exception_cause <= CSR_CAUSE_INSTR_MISALIGN;
336
                elsif data_misaligned = '1' and mem_op = MEMOP_TYPE_STORE then
337
                        exception_cause <= CSR_CAUSE_STORE_MISALIGN;
338
                elsif data_misaligned = '1' and memop_is_load(mem_op) then
339
                        exception_cause <= CSR_CAUSE_LOAD_MISALIGN;
340
                else
341
                        exception_cause <= CSR_CAUSE_NONE;
342
                end if;
343
        end process find_exception_cause;
344
 
345
        find_exception_vaddr: process(instr_misaligned, data_misaligned, jump_target, alu_result)
346
        begin
347
                if instr_misaligned = '1' then
348
                        exception_vaddr <= jump_target;
349
                elsif data_misaligned = '1' then
350
                        exception_vaddr <= alu_result;
351
                else
352
                        exception_vaddr <= (others => '0');
353
                end if;
354
        end process find_exception_vaddr;
355
 
356
        calc_jump_tgt: process(branch, pc, rs1_forwarded, immediate, csr_value_forwarded)
357
        begin
358
                case branch is
359
                        when BRANCH_JUMP | BRANCH_CONDITIONAL =>
360
                                jump_target <= std_logic_vector(unsigned(pc) + unsigned(immediate));
361
                        when BRANCH_JUMP_INDIRECT =>
362
                                jump_target <= std_logic_vector(unsigned(rs1_forwarded) + unsigned(immediate));
363
                        when BRANCH_SRET =>
364
                                jump_target <= csr_value_forwarded; -- Will be the EPC value in the case of SRET
365
                        when others =>
366
                                jump_target <= (others => '0');
367
                end case;
368
        end process calc_jump_tgt;
369
 
370
        alu_x_mux: entity work.pp_alu_mux
371
                port map(
372
                        source => alu_x_src,
373
                        register_value => rs1_forwarded,
374
                        immediate_value => immediate,
375
                        shamt_value => shamt,
376
                        pc_value => pc,
377
                        csr_value => csr_value_forwarded,
378
                        output => alu_x
379
                );
380
 
381
        alu_y_mux: entity work.pp_alu_mux
382
                port map(
383
                        source => alu_y_src,
384
                        register_value => rs2_forwarded,
385
                        immediate_value => immediate,
386
                        shamt_value => shamt,
387
                        pc_value => pc,
388
                        csr_value => csr_value_forwarded,
389
                        output => alu_y
390
                );
391
 
392
        alu_x_forward: process(mem_rd_write, mem_rd_value, mem_rd_addr, rs1_addr,
393
                rs1_data, wb_rd_write, wb_rd_addr, wb_rd_value)
394
        begin
395
                if mem_rd_write = '1' and mem_rd_addr = rs1_addr and mem_rd_addr /= b"00000" then
396
                        rs1_forwarded <= mem_rd_value;
397
                elsif wb_rd_write = '1' and wb_rd_addr = rs1_addr and wb_rd_addr /= b"00000" then
398
                        rs1_forwarded <= wb_rd_value;
399
                else
400
                        rs1_forwarded <= rs1_data;
401
                end if;
402
        end process alu_x_forward;
403
 
404
        alu_y_forward: process(mem_rd_write, mem_rd_value, mem_rd_addr, rs2_addr,
405
                rs2_data, wb_rd_write, wb_rd_addr, wb_rd_value)
406
        begin
407
                if mem_rd_write = '1' and mem_rd_addr = rs2_addr and mem_rd_addr /= b"00000" then
408
                        rs2_forwarded <= mem_rd_value;
409
                elsif wb_rd_write = '1' and wb_rd_addr = rs2_addr and wb_rd_addr /= b"00000" then
410
                        rs2_forwarded <= wb_rd_value;
411
                else
412
                        rs2_forwarded <= rs2_data;
413
                end if;
414
        end process alu_y_forward;
415
 
416
        csr_forward: process(mem_csr_write, wb_csr_write, csr_addr, mem_csr_addr, wb_csr_addr,
417
                csr_value, mem_csr_value, wb_csr_value, csr_writeable, mem_exception, wb_exception,
418
                mem_exception_context, wb_exception_context)
419
        begin
420
                if csr_addr = CSR_CAUSE and mem_exception = '1' then
421
                        csr_value_forwarded <= to_std_logic_vector(mem_exception_context.cause);
422
                elsif csr_addr = CSR_STATUS and mem_exception = '1' then
423
                        csr_value_forwarded <= to_std_logic_vector(mem_exception_context.status);
424
                elsif csr_addr = CSR_BADVADDR and mem_exception = '1' then
425
                        csr_value_forwarded <= mem_exception_context.badvaddr;
426
                elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = csr_addr and csr_writeable then
427
                        csr_value_forwarded <= mem_csr_value;
428
                elsif csr_addr = CSR_CAUSE and wb_exception = '1' then
429
                        csr_value_forwarded <= to_std_logic_vector(wb_exception_context.cause);
430
                elsif csr_addr = CSR_STATUS and wb_exception = '1' then
431
                        csr_value_forwarded <= to_std_logic_vector(wb_exception_context.status);
432
                elsif csr_addr = CSR_BADVADDR and wb_exception = '1' then
433
                        csr_value_forwarded <= wb_exception_context.badvaddr;
434
                elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = csr_addr and csr_writeable then
435
                        csr_value_forwarded <= wb_csr_value;
436
                else
437
                        csr_value_forwarded <= csr_value;
438
                end if;
439
        end process csr_forward;
440
 
441
        evec_forward: process(mem_csr_write, mem_csr_addr, mem_csr_value,
442
                wb_csr_write, wb_csr_addr, wb_csr_value, evec)
443
        begin
444
                if mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_EVEC then
445
                        evec_forwarded <= mem_csr_value;
446
                elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_EVEC then
447
                        evec_forwarded <= wb_csr_value;
448
                else
449
                        evec_forwarded <= evec;
450
                end if;
451
        end process evec_forward;
452
 
453
        exception_ctx_forward: process(mem_exception, wb_exception, mem_exception_context, wb_exception_context,
454
                exception_cause, exception_vaddr, mem_csr_write, mem_csr_addr, mem_csr_value,
455
                wb_csr_write, wb_csr_addr, wb_csr_value, sr)
456
        begin
457
                if mem_exception = '1' then
458
                        exception_context_forwarded <= mem_exception_context;
459
                elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_STATUS then
460
                        exception_context_forwarded <= (
461
                                status => to_csr_status_register(mem_csr_value),
462
                                cause => mem_exception_context.cause,
463
                                badvaddr => mem_exception_context.badvaddr);
464
                elsif wb_exception = '1' then
465
                        exception_context_forwarded <= wb_exception_context;
466
                elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_STATUS then
467
                        exception_context_forwarded <= (
468
                                status => to_csr_status_register(wb_csr_value),
469
                                cause => wb_exception_context.cause,
470
                                badvaddr => wb_exception_context.badvaddr);
471
                else
472
                        exception_context_forwarded.status <= sr;
473
                        exception_context_forwarded.cause <= exception_cause;
474
                        exception_context_forwarded.badvaddr <= exception_vaddr;
475
                end if;
476
        end process exception_ctx_forward;
477
 
478
        detect_load_hazard: process(mem_mem_op, mem_rd_addr, rs1_addr, rs2_addr,
479
                alu_x_src, alu_y_src)
480
        begin
481
                if (mem_mem_op = MEMOP_TYPE_LOAD or mem_mem_op = MEMOP_TYPE_LOAD_UNSIGNED) and
482
                                ((alu_x_src = ALU_SRC_REG and mem_rd_addr = rs1_addr and rs1_addr /= b"00000")
483
                        or
484
                                (alu_y_src = ALU_SRC_REG and mem_rd_addr = rs2_addr and rs2_addr /= b"00000"))
485
                then
486
                        hazard_detected <= '1';
487
                else
488
                        hazard_detected <= '0';
489
                end if;
490
        end process detect_load_hazard;
491
 
492
        branch_comparator: entity work.pp_comparator
493
                port map(
494
                        funct3 => funct3,
495
                        rs1 => rs1_forwarded,
496
                        rs2 => rs2_forwarded,
497
                        result => branch_condition
498
                );
499
 
500
        alu_instance: entity work.pp_alu
501
                port map(
502
                        result => alu_result,
503
                        x => alu_x,
504
                        y => alu_y,
505
                        operation => alu_op
506
                );
507
 
508
        csr_alu_instance: entity work.pp_csr_alu
509
                port map(
510
                        x => csr_value_forwarded,
511
                        y => rs1_forwarded,
512
                        result => csr_value_out,
513
                        immediate => rs1_addr,
514
                        use_immediate => csr_use_immediate,
515
                        write_mode => csr_write
516
                );
517
 
518
 
519
end architecture behaviour;

powered by: WebSVN 2.1.0

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