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

Subversion Repositories mblite

[/] [mblite/] [tags/] [1.0/] [hw/] [core/] [decode.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 takar
----------------------------------------------------------------------------------------------
2
--
3
--      Input file         : decode.vhd
4
--      Design name        : decode
5
--      Author             : Tamar Kranenburg
6
--      Company            : Delft University of Technology
7
--                         : Faculty EEMCS, Department ME&CE
8
--                         : Systems and Circuits group
9
--
10
--      Description        : This combined register file and decoder uses three Dual Port
11
--                           read after write Random Access Memory components. Every clock
12
--                           cycle three data values can be read (ra, rb and rd) and one value
13
--                           can be stored.
14
--
15
----------------------------------------------------------------------------------------------
16
 
17
LIBRARY ieee;
18
USE ieee.std_logic_1164.ALL;
19
USE ieee.std_logic_unsigned.ALL;
20
 
21
LIBRARY mblite;
22
USE mblite.config_Pkg.ALL;
23
USE mblite.core_Pkg.ALL;
24
USE mblite.std_Pkg.ALL;
25
 
26
ENTITY decode IS GENERIC
27
(
28
    G_INTERRUPT  : boolean := CFG_INTERRUPT;
29
    G_USE_HW_MUL : boolean := CFG_USE_HW_MUL;
30
    G_USE_BARREL : boolean := CFG_USE_BARREL;
31
    G_DEBUG      : boolean := CFG_DEBUG
32
);
33
PORT
34
(
35
    decode_o : OUT decode_out_type;
36
    gprf_o   : OUT gprf_out_type;
37
    decode_i : IN decode_in_type;
38
    ena_i    : IN std_ulogic;
39
    rst_i    : IN std_ulogic;
40
    clk_i    : IN std_ulogic
41
);
42
END decode;
43
 
44
ARCHITECTURE arch OF decode IS
45
 
46
    TYPE decode_reg_type IS RECORD
47
        instruction     : std_ulogic_vector(CFG_IMEM_WIDTH - 1 DOWNTO 0);
48
        program_counter : std_ulogic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0);
49
        immediate       : std_ulogic_vector(15 DOWNTO 0);
50
        is_immediate    : std_ulogic;
51
        msr_interrupt_enable : std_ulogic;
52
        interrupt       : std_ulogic;
53
        delay_interrupt : std_ulogic;
54
    END RECORD;
55
 
56
    SIGNAL r, rin : decode_out_type;
57
    SIGNAL reg, regin : decode_reg_type;
58
 
59
    SIGNAL wb_dat_d : std_ulogic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0);
60
 
61
BEGIN
62
 
63
    decode_o.imm <= r.imm;
64
 
65
    decode_o.ctrl_ex <= r.ctrl_ex;
66
    decode_o.ctrl_mem <= r.ctrl_mem;
67
    decode_o.ctrl_wb <= r.ctrl_wb;
68
 
69
    decode_o.reg_a <= r.reg_a;
70
    decode_o.reg_b <= r.reg_b;
71
    decode_o.hazard <= r.hazard;
72
    decode_o.program_counter <= r.program_counter;
73
 
74
    decode_o.fwd_dec_result <= r.fwd_dec_result;
75
    decode_o.fwd_dec <= r.fwd_dec;
76
 
77
    decode_comb: PROCESS(decode_i,decode_i.ctrl_wb,
78
                         decode_i.ctrl_mem_wb,
79
                         decode_i.ctrl_mem_wb.transfer_size,
80
                         r,r.ctrl_ex,r.ctrl_mem,
81
                         r.ctrl_mem.transfer_size,r.ctrl_wb,
82
                         r.fwd_dec,reg)
83
 
84
        VARIABLE v : decode_out_type;
85
        VARIABLE v_reg : decode_reg_type;
86
        VARIABLE opcode : std_ulogic_vector(5 DOWNTO 0);
87
        VARIABLE instruction : std_ulogic_vector(CFG_IMEM_WIDTH - 1 DOWNTO 0);
88
        VARIABLE program_counter : std_ulogic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0);
89
        VARIABLE mem_result : std_ulogic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0);
90
 
91
    BEGIN
92
        v := r;
93
        v_reg := reg;
94
 
95
        -- Default register values (NOP)
96
        v_reg.immediate := (OTHERS => '0');
97
        v_reg.is_immediate := '0';
98
        v_reg.program_counter := decode_i.program_counter;
99
        v_reg.instruction := decode_i.instruction;
100
 
101
        IF decode_i.ctrl_mem_wb.mem_read = '1' THEN
102
            mem_result := align_mem_load(decode_i.mem_result, decode_i.ctrl_mem_wb.transfer_size, decode_i.alu_result(1 DOWNTO 0));
103
        ELSE
104
            mem_result := decode_i.alu_result;
105
        END IF;
106
 
107
        wb_dat_d <= mem_result;
108
 
109
        IF G_INTERRUPT = true THEN
110
            v_reg.delay_interrupt := '0';
111
        END IF;
112
 
113
        IF CFG_REG_FWD_WB = true THEN
114
            v.fwd_dec_result    := mem_result;
115
            v.fwd_dec           := decode_i.ctrl_wb;
116
        ELSE
117
            v.fwd_dec_result    := (OTHERS => '0');
118
            v.fwd_dec.reg_d     := (OTHERS => '0');
119
            v.fwd_dec.reg_write := '0';
120
        END IF;
121
 
122
        IF (NOT decode_i.flush_id AND r.ctrl_mem.mem_read AND (compare(decode_i.instruction(20 DOWNTO 16), r.ctrl_wb.reg_d) OR compare(decode_i.instruction(15 DOWNTO 11), r.ctrl_wb.reg_d))) = '1' THEN
123
        -- A hazard occurred on register a or b
124
 
125
            -- set current instruction and program counter to 0
126
            instruction := (OTHERS => '0');
127
            program_counter := (OTHERS => '0');
128
 
129
            v.hazard := '1';
130
 
131
        ELSIF CFG_MEM_FWD_WB = false AND (NOT decode_i.flush_id AND r.ctrl_mem.mem_read AND compare(decode_i.instruction(25 DOWNTO 21), r.ctrl_wb.reg_d)) = '1' THEN
132
        -- A hazard occurred on register d
133
 
134
            -- set current instruction and program counter to 0
135
            instruction := (OTHERS => '0');
136
            program_counter := (OTHERS => '0');
137
 
138
            v.hazard := '1';
139
 
140
        ELSIF r.hazard = '1' THEN
141
        -- Recover from hazard. Insert latched instruction
142
 
143
            instruction := reg.instruction;
144
            program_counter := reg.program_counter;
145
            v.hazard := '0';
146
 
147
        ELSE
148
 
149
            instruction := decode_i.instruction;
150
            program_counter := decode_i.program_counter;
151
            v.hazard := '0';
152
 
153
        END IF;
154
 
155
        v.program_counter := program_counter;
156
        opcode := instruction(31 DOWNTO 26);
157
        v.ctrl_wb.reg_d := instruction(25 DOWNTO 21);
158
        v.reg_a := instruction(20 DOWNTO 16);
159
        v.reg_b := instruction(15 DOWNTO 11);
160
 
161
        -- SET IMM value
162
        IF reg.is_immediate = '1' THEN
163
            v.imm := reg.immediate & instruction(15 DOWNTO 0);
164
        ELSE
165
            v.imm := sign_extend(instruction(15 DOWNTO 0), instruction(15), 32);
166
        END IF;
167
 
168
        -- Register if an interrupt occurs
169
        IF G_INTERRUPT = true THEN
170
            IF v_reg.msr_interrupt_enable = '1' AND decode_i.interrupt = '1' THEN
171
                v_reg.interrupt := '1';
172
                v_reg.msr_interrupt_enable := '0';
173
            END IF;
174
        END IF;
175
 
176
        v.ctrl_ex.alu_op := ALU_ADD;
177
        v.ctrl_ex.alu_src_a := ALU_SRC_REGA;
178
        v.ctrl_ex.alu_src_b := ALU_SRC_REGB;
179
        v.ctrl_ex.operation := '0';
180
        v.ctrl_ex.carry := CARRY_ZERO;
181
        v.ctrl_ex.carry_keep := CARRY_NOT_KEEP;
182
        v.ctrl_ex.delay := '0';
183
        v.ctrl_ex.branch_cond := NOP;
184
        v.ctrl_mem.mem_write := '0';
185
        v.ctrl_mem.transfer_size := WORD;
186
        v.ctrl_mem.mem_read := '0';
187
        v.ctrl_wb.reg_write := '0';
188
 
189
        IF G_INTERRUPT = true AND (v_reg.interrupt = '1' AND reg.delay_interrupt = '0' AND decode_i.flush_id = '0' AND v.hazard = '0' AND r.ctrl_ex.delay = '0' AND reg.is_immediate = '0') THEN
190
        -- IF an interrupt occured
191
        --    AND the current instruction is not a branch or return instruction,
192
        --    AND the current instruction is not in a delay slot,
193
        --    AND this is instruction is not preceded by an IMM instruction, than handle the interrupt.
194
            v_reg.msr_interrupt_enable := '0';
195
            v_reg.interrupt := '0';
196
 
197
            v.reg_a := (OTHERS => '0');
198
            v.reg_b := (OTHERS => '0');
199
 
200
            v.imm   := X"00000010";
201
            v.ctrl_wb.reg_d := "01110";
202
 
203
            v.ctrl_ex.branch_cond := BNC;
204
            v.ctrl_ex.alu_src_a := ALU_SRC_ZERO;
205
            v.ctrl_ex.alu_src_b := ALU_SRC_IMM;
206
            v.ctrl_wb.reg_write := '1';
207
 
208
        ELSIF (decode_i.flush_id OR v.hazard) = '1' THEN
209
            -- clearing these registers is not necessary, but facilitates debugging.
210
            -- On the other hand performance improves when disabled.
211
            IF G_DEBUG = true THEN
212
                v.program_counter := (OTHERS => '0');
213
                v.ctrl_wb.reg_d   := (OTHERS => '0');
214
                v.reg_a           := (OTHERS => '0');
215
                v.reg_b           := (OTHERS => '0');
216
                v.imm             := (OTHERS => '0');
217
            END IF;
218
 
219
        ELSIF is_zero(opcode(5 DOWNTO 4)) = '1' THEN
220
        -- ADD, SUBTRACT OR COMPARE
221
 
222
            -- Alu operation
223
            v.ctrl_ex.alu_op := ALU_ADD;
224
 
225
            -- Source operand A
226
            IF opcode(0) = '1' THEN
227
                v.ctrl_ex.alu_src_a := ALU_SRC_NOT_REGA;
228
            ELSE
229
                v.ctrl_ex.alu_src_a := ALU_SRC_REGA;
230
            END IF;
231
 
232
            -- Source operand B
233
            IF opcode(3) = '1' THEN
234
                v.ctrl_ex.alu_src_b := ALU_SRC_IMM;
235
            ELSE
236
                v.ctrl_ex.alu_src_b := ALU_SRC_REGB;
237
            END IF;
238
 
239
            IF (compare(opcode, "000101") AND instruction(1)) = '1' THEN
240
                v.ctrl_ex.operation := '1';
241
            END IF;
242
 
243
            -- Carry
244
            CASE opcode(1 DOWNTO 0) IS
245
                WHEN "00" => v.ctrl_ex.carry := CARRY_ZERO;
246
                WHEN "01" => v.ctrl_ex.carry := CARRY_ONE;
247
                WHEN OTHERS => v.ctrl_ex.carry := CARRY_ALU;
248
            END CASE;
249
 
250
            -- Carry keep
251
            IF opcode(2) = '1' THEN
252
                v.ctrl_ex.carry_keep := CARRY_KEEP;
253
            ELSE
254
                v.ctrl_ex.carry_keep := CARRY_NOT_KEEP;
255
            END IF;
256
 
257
            -- Flag writeback if reg_d != 0
258
            v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d);
259
 
260
        ELSIF (compare(opcode(5 DOWNTO 2), "1000") OR compare(opcode(5 DOWNTO 2), "1010")) = '1' THEN
261
        -- OR, AND, XOR, ANDN
262
        -- ORI, ANDI, XORI, ANDNI
263
            CASE opcode(1 DOWNTO 0) IS
264
                WHEN "00" => v.ctrl_ex.alu_op := ALU_OR;
265
                WHEN "10" => v.ctrl_ex.alu_op := ALU_XOR;
266
                WHEN OTHERS => v.ctrl_ex.alu_op := ALU_AND;
267
            END CASE;
268
 
269
            IF opcode(3) = '1' AND compare(opcode(1 DOWNTO 0), "11") = '1' THEN
270
                v.ctrl_ex.alu_src_b := ALU_SRC_NOT_IMM;
271
            ELSIF opcode(3) = '1' THEN
272
                v.ctrl_ex.alu_src_b := ALU_SRC_IMM;
273
            ELSIF opcode(3) = '0' AND compare(opcode(1 DOWNTO 0), "11") = '1' THEN
274
                v.ctrl_ex.alu_src_b := ALU_SRC_NOT_REGB;
275
            ELSE
276
                v.ctrl_ex.alu_src_b := ALU_SRC_REGB;
277
            END IF;
278
 
279
            -- Flag writeback if reg_d != 0
280
            v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d);
281
 
282
        ELSIF compare(opcode, "101100") = '1' THEN
283
        -- IMM instruction
284
            v_reg.immediate := instruction(15 DOWNTO 0);
285
            v_reg.is_immediate := '1';
286
 
287
        ELSIF compare(opcode, "100100") = '1' THEN
288
        -- SHIFT, SIGN EXTEND
289
            IF compare(instruction(6 DOWNTO 5), "11") = '1' THEN
290
                IF instruction(0) = '1' THEN
291
                    v.ctrl_ex.alu_op:= ALU_SEXT16;
292
                ELSE
293
                    v.ctrl_ex.alu_op:= ALU_SEXT8;
294
                END IF;
295
            ELSE
296
                v.ctrl_ex.alu_op:= ALU_SHIFT;
297
                CASE instruction(6 DOWNTO 5) IS
298
                    WHEN "10"   => v.ctrl_ex.carry := CARRY_ZERO;
299
                    WHEN "01"   => v.ctrl_ex.carry := CARRY_ALU;
300
                    WHEN OTHERS => v.ctrl_ex.carry := CARRY_ARITH;
301
                END CASE;
302
            END IF;
303
 
304
            -- Flag writeback if reg_d != 0
305
            v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d);
306
 
307
        ELSIF (compare(opcode, "100110") OR compare(opcode, "101110")) = '1' THEN
308
        -- BRANCH UNCONDITIONAL
309
 
310
            v.ctrl_ex.branch_cond := BNC;
311
 
312
            IF opcode(3) = '1' THEN
313
                v.ctrl_ex.alu_src_b := ALU_SRC_IMM;
314
            ELSE
315
                v.ctrl_ex.alu_src_b := ALU_SRC_REGB;
316
            END IF;
317
 
318
            -- WRITE THE RESULT ALSO TO REGISTER D
319
            IF v.reg_a(2) = '1' THEN
320
                -- Flag writeback if reg_d != 0
321
                v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d);
322
            END IF;
323
 
324
            IF v.reg_a(3) = '1' THEN
325
                v.ctrl_ex.alu_src_a := ALU_SRC_ZERO;
326
            ELSE
327
                v.ctrl_ex.alu_src_a := ALU_SRC_PC;
328
            END IF;
329
 
330
            IF G_INTERRUPT = true THEN
331
                v_reg.delay_interrupt := '1';
332
            END IF;
333
            v.ctrl_ex.delay := v.reg_a(4);
334
 
335
        ELSIF (compare(opcode, "100111") OR compare(opcode, "101111")) = '1' THEN
336
        -- BRANCH CONDITIONAL
337
            v.ctrl_ex.alu_op := ALU_ADD;
338
            v.ctrl_ex.alu_src_a := ALU_SRC_PC;
339
 
340
            IF opcode(3) = '1' THEN
341
                v.ctrl_ex.alu_src_b := ALU_SRC_IMM;
342
            ELSE
343
                v.ctrl_ex.alu_src_b := ALU_SRC_REGB;
344
            END IF;
345
 
346
            CASE v.ctrl_wb.reg_d(2 DOWNTO 0) IS
347
                WHEN "000"  => v.ctrl_ex.branch_cond := BEQ;
348
                WHEN "001"  => v.ctrl_ex.branch_cond := BNE;
349
                WHEN "010"  => v.ctrl_ex.branch_cond := BLT;
350
                WHEN "011"  => v.ctrl_ex.branch_cond := BLE;
351
                WHEN "100"  => v.ctrl_ex.branch_cond := BGT;
352
                WHEN OTHERS => v.ctrl_ex.branch_cond := BGE;
353
            END CASE;
354
 
355
            IF G_INTERRUPT = true THEN
356
                v_reg.delay_interrupt := '1';
357
            END IF;
358
            v.ctrl_ex.delay := v.ctrl_wb.reg_d(4);
359
 
360
        ELSIF compare(opcode, "101101") = '1' THEN
361
        -- RETURN
362
 
363
            v.ctrl_ex.branch_cond := BNC;
364
            v.ctrl_ex.alu_src_b := ALU_SRC_IMM;
365
            v.ctrl_ex.delay := '1';
366
 
367
            IF G_INTERRUPT = true THEN
368
                IF v.ctrl_wb.reg_d(0) = '1' THEN
369
                    v_reg.msr_interrupt_enable := '1';
370
                END IF;
371
                v_reg.delay_interrupt := '1';
372
            END IF;
373
 
374
        ELSIF compare(opcode(5 DOWNTO 4), "11") = '1' THEN
375
            -- SW, LW
376
            v.ctrl_ex.alu_op := ALU_ADD;
377
            v.ctrl_ex.alu_src_a := ALU_SRC_REGA;
378
 
379
            IF opcode(3) = '1' THEN
380
                v.ctrl_ex.alu_src_b := ALU_SRC_IMM;
381
            ELSE
382
                v.ctrl_ex.alu_src_b := ALU_SRC_REGB;
383
            END IF;
384
 
385
            v.ctrl_ex.carry := CARRY_ZERO;
386
 
387
            IF opcode(2) = '1' THEN
388
                -- Store
389
                v.ctrl_mem.mem_write := '1';
390
                v.ctrl_mem.mem_read := '0';
391
                v.ctrl_wb.reg_write := '0';
392
            ELSE
393
                -- Load
394
                v.ctrl_mem.mem_write := '0';
395
                v.ctrl_mem.mem_read := '1';
396
                v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d);
397
            END IF;
398
 
399
            CASE opcode(1 DOWNTO 0) IS
400
                WHEN "00" => v.ctrl_mem.transfer_size := BYTE;
401
                WHEN "01" => v.ctrl_mem.transfer_size := HALFWORD;
402
                WHEN OTHERS => v.ctrl_mem.transfer_size := WORD;
403
            END CASE;
404
 
405
            v.ctrl_ex.delay := '0';
406
 
407
        ELSIF G_USE_HW_MUL = true AND (compare(opcode, "010000") OR compare(opcode, "011000")) = '1' THEN
408
 
409
            v.ctrl_ex.alu_op := ALU_MUL;
410
 
411
            IF opcode(3) = '1' THEN
412
                v.ctrl_ex.alu_src_b := ALU_SRC_IMM;
413
            ELSE
414
                v.ctrl_ex.alu_src_b := ALU_SRC_REGB;
415
            END IF;
416
 
417
            v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d);
418
 
419
        ELSIF G_USE_BARREL = true AND (compare(opcode, "010001") OR compare(opcode, "011001")) = '1' THEN
420
 
421
            v.ctrl_ex.alu_op := ALU_BS;
422
 
423
            IF opcode(3) = '1' THEN
424
                v.ctrl_ex.alu_src_b := ALU_SRC_IMM;
425
            ELSE
426
                v.ctrl_ex.alu_src_b := ALU_SRC_REGB;
427
            END IF;
428
 
429
            v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d);
430
 
431
        ELSE
432
            -- UNKNOWN OPCODE
433
            NULL;
434
        END IF;
435
 
436
        rin <= v;
437
        regin <= v_reg;
438
 
439
    END PROCESS;
440
 
441
    decode_seq: PROCESS(clk_i)
442
        PROCEDURE proc_reset_decode IS
443
        BEGIN
444
            r.reg_a                     <= (OTHERS => '0');
445
            r.reg_b                     <= (OTHERS => '0');
446
            r.imm                       <= (OTHERS => '0');
447
            r.program_counter           <= (OTHERS => '0');
448
            r.hazard                    <= '0';
449
            r.ctrl_ex.alu_op            <= ALU_ADD;
450
            r.ctrl_ex.alu_src_a         <= ALU_SRC_REGA;
451
            r.ctrl_ex.alu_src_b         <= ALU_SRC_REGB;
452
            r.ctrl_ex.operation         <= '0';
453
            r.ctrl_ex.carry             <= CARRY_ZERO;
454
            r.ctrl_ex.carry_keep        <= CARRY_NOT_KEEP;
455
            r.ctrl_ex.delay             <= '0';
456
            r.ctrl_ex.branch_cond       <= NOP;
457
            r.ctrl_mem.mem_write        <= '0';
458
            r.ctrl_mem.transfer_size    <= WORD;
459
            r.ctrl_mem.mem_read         <= '0';
460
            r.ctrl_wb.reg_d             <= (OTHERS => '0');
461
            r.ctrl_wb.reg_write         <= '0';
462
            r.fwd_dec_result            <= (OTHERS => '0');
463
            r.fwd_dec.reg_d             <= (OTHERS => '0');
464
            r.fwd_dec.reg_write         <= '0';
465
            reg.instruction             <= (OTHERS => '0');
466
            reg.program_counter         <= (OTHERS => '0');
467
            reg.immediate               <= (OTHERS => '0');
468
            reg.is_immediate            <= '0';
469
            reg.msr_interrupt_enable    <= '1';
470
            reg.interrupt               <= '0';
471
            reg.delay_interrupt         <= '0';
472
        END PROCEDURE proc_reset_decode;
473
    BEGIN
474
        IF rising_edge(clk_i) THEN
475
            IF rst_i = '1' THEN
476
                proc_reset_decode;
477
            ELSIF ena_i = '1' THEN
478
                r <= rin;
479
                reg <= regin;
480
            END IF;
481
        END IF;
482
    END PROCESS;
483
 
484
    gprf0 : gprf PORT MAP
485
    (
486
        gprf_o         => gprf_o,
487
        gprf_i.adr_a_i => rin.reg_a,
488
        gprf_i.adr_b_i => rin.reg_b,
489
        gprf_i.adr_d_i => rin.ctrl_wb.reg_d,
490
        gprf_i.dat_w_i => wb_dat_d,
491
        gprf_i.adr_w_i => decode_i.ctrl_wb.reg_d,
492
        gprf_i.wre_i   => decode_i.ctrl_wb.reg_write,
493
        ena_i          => ena_i,
494
        clk_i          => clk_i
495
    );
496
END arch;

powered by: WebSVN 2.1.0

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