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

Subversion Repositories mblite

[/] [mblite/] [trunk/] [hw/] [core/] [execute.vhd] - Blame information for rev 7

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 takar
----------------------------------------------------------------------------------------------
2
--
3
--      Input file         : execute.vhd
4
--      Design name        : execute
5
--      Author             : Tamar Kranenburg
6
--      Company            : Delft University of Technology
7
--                         : Faculty EEMCS, Department ME&CE
8
--                         : Systems and Circuits group
9
--
10
--      Description        : The Execution Unit performs all arithmetic operations and makes
11
--                           the branch decision. Furthermore the forwarding logic is located
12
--                           here. Everything is computed within a single clock-cycle
13
--
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 execute IS GENERIC
27
(
28
    G_USE_HW_MUL : boolean := CFG_USE_HW_MUL;
29
    G_USE_BARREL : boolean := CFG_USE_BARREL
30
);
31
PORT
32
(
33
    exec_o : OUT execute_out_type;
34
    exec_i : IN execute_in_type;
35 6 takar
    ena_i  : IN std_logic;
36
    rst_i  : IN std_logic;
37
    clk_i  : IN std_logic
38 2 takar
);
39
END execute;
40
 
41
ARCHITECTURE arch OF execute IS
42
 
43
    TYPE execute_reg_type IS RECORD
44 6 takar
        carry      : std_logic;
45
        flush_ex   : std_logic;
46 2 takar
    END RECORD;
47
 
48
    SIGNAL r, rin : execute_out_type;
49
    SIGNAL reg, regin : execute_reg_type;
50
 
51
BEGIN
52
 
53
    exec_o <= r;
54
 
55
    execute_comb: PROCESS(exec_i,exec_i.fwd_mem,exec_i.ctrl_ex,
56
            exec_i.ctrl_wb,exec_i.ctrl_mem,
57
            exec_i.ctrl_mem.transfer_size,
58
            exec_i.ctrl_mem_wb,exec_i.fwd_dec,
59
            r,r.ctrl_mem,r.ctrl_mem.transfer_size,
60
            r.ctrl_wb,reg)
61
 
62
        VARIABLE v : execute_out_type;
63
        VARIABLE v_reg : execute_reg_type;
64
 
65 6 takar
        VARIABLE alu_src_a : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0);
66
        VARIABLE alu_src_b : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0);
67
        VARIABLE carry : std_logic;
68 2 takar
 
69 6 takar
        VARIABLE result : std_logic_vector(CFG_DMEM_WIDTH DOWNTO 0);
70
        VARIABLE result_add : std_logic_vector(CFG_DMEM_WIDTH DOWNTO 0);
71
        VARIABLE zero : std_logic;
72 2 takar
 
73 6 takar
        VARIABLE dat_a, dat_b : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0);
74
        VARIABLE sel_dat_a, sel_dat_b, sel_dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0);
75
        VARIABLE mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0);
76 2 takar
 
77
    BEGIN
78
 
79
        v := r;
80
 
81
        sel_dat_a := select_register_data(exec_i.dat_a, exec_i.reg_a, exec_i.fwd_dec_result, forward_condition(exec_i.fwd_dec.reg_write, exec_i.fwd_dec.reg_d, exec_i.reg_a));
82
        sel_dat_b := select_register_data(exec_i.dat_b, exec_i.reg_b, exec_i.fwd_dec_result, forward_condition(exec_i.fwd_dec.reg_write, exec_i.fwd_dec.reg_d, exec_i.reg_b));
83
        sel_dat_d := select_register_data(exec_i.dat_d, exec_i.ctrl_wb.reg_d, exec_i.fwd_dec_result, forward_condition(exec_i.fwd_dec.reg_write, exec_i.fwd_dec.reg_d, exec_i.ctrl_wb.reg_d));
84
 
85
        IF reg.flush_ex = '1' THEN
86
            v.ctrl_mem.mem_write := '0';
87
            v.ctrl_mem.mem_read := '0';
88
            v.ctrl_wb.reg_write := '0';
89
            v.ctrl_wb.reg_d := (OTHERS => '0');
90
        ELSE
91
            v.ctrl_mem := exec_i.ctrl_mem;
92
            v.ctrl_wb := exec_i.ctrl_wb;
93
        END IF;
94
 
95
        IF exec_i.ctrl_mem_wb.mem_read = '1' THEN
96
            mem_result := align_mem_load(exec_i.mem_result, exec_i.ctrl_mem_wb.transfer_size, exec_i.alu_result(1 DOWNTO 0));
97
        ELSE
98
            mem_result := exec_i.alu_result;
99
        END IF;
100
 
101
        IF forward_condition(r.ctrl_wb.reg_write, r.ctrl_wb.reg_d, exec_i.reg_a) = '1' THEN
102
            -- Forward Execution Result to REG a
103
            dat_a := r.alu_result;
104
        ELSIF forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.reg_a) = '1' THEN
105
            -- Forward Memory Result to REG a
106
            dat_a := mem_result;
107
        ELSE
108
            -- DEFAULT: value of REG a
109
            dat_a := sel_dat_a;
110
        END IF;
111
 
112
        IF forward_condition(r.ctrl_wb.reg_write, r.ctrl_wb.reg_d, exec_i.reg_b) = '1' THEN
113
            -- Forward (latched) Execution Result to REG b
114
            dat_b := r.alu_result;
115
        ELSIF forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.reg_b) = '1' THEN
116
            -- Forward Memory Result to REG b
117
            dat_b := mem_result;
118
        ELSE
119
            -- DEFAULT: value of REG b
120
            dat_b := sel_dat_b;
121
        END IF;
122
 
123
        IF forward_condition(r.ctrl_wb.reg_write, r.ctrl_wb.reg_d, exec_i.ctrl_wb.reg_d) = '1' THEN
124
            -- Forward Execution Result to REG d
125
            v.dat_d := align_mem_store(r.alu_result, exec_i.ctrl_mem.transfer_size);
126
        ELSIF forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.ctrl_wb.reg_d) = '1' THEN
127
            -- Forward Memory Result to REG d
128
            v.dat_d := align_mem_store(mem_result, exec_i.ctrl_mem.transfer_size);
129
        ELSE
130
            -- DEFAULT: value of REG d
131
            v.dat_d := align_mem_store(sel_dat_d, exec_i.ctrl_mem.transfer_size);
132
        END IF;
133
 
134
        -- Set the first operand of the ALU
135
        CASE exec_i.ctrl_ex.alu_src_a IS
136
            WHEN ALU_SRC_PC       => alu_src_a := sign_extend(exec_i.program_counter, '0', 32);
137
            WHEN ALU_SRC_NOT_REGA => alu_src_a := NOT dat_a;
138
            WHEN ALU_SRC_ZERO     => alu_src_a := (OTHERS => '0');
139
            WHEN OTHERS           => alu_src_a := dat_a;
140
        END CASE;
141
 
142
        -- Set the second operand of the ALU
143
        CASE exec_i.ctrl_ex.alu_src_b IS
144
            WHEN ALU_SRC_IMM      => alu_src_b := exec_i.imm;
145
            WHEN ALU_SRC_NOT_IMM  => alu_src_b := NOT exec_i.imm;
146
            WHEN ALU_SRC_NOT_REGB => alu_src_b := NOT dat_b;
147
            WHEN OTHERS           => alu_src_b := dat_b;
148
        END CASE;
149
 
150
        -- Determine value of carry in
151
        CASE exec_i.ctrl_ex.carry IS
152
            WHEN CARRY_ALU   => carry := reg.carry;
153
            WHEN CARRY_ONE   => carry := '1';
154
            WHEN CARRY_ARITH => carry := alu_src_a(CFG_DMEM_WIDTH - 1);
155
            WHEN OTHERS      => carry := '0';
156
        END CASE;
157
 
158
        result_add := add(alu_src_a, alu_src_b, carry);
159
 
160
        CASE exec_i.ctrl_ex.alu_op IS
161
            WHEN ALU_ADD    => result := result_add;
162
            WHEN ALU_OR     => result := '0' & (alu_src_a OR alu_src_b);
163
            WHEN ALU_AND    => result := '0' & (alu_src_a AND alu_src_b);
164
            WHEN ALU_XOR    => result := '0' & (alu_src_a XOR alu_src_b);
165
            WHEN ALU_SHIFT  => result := alu_src_a(0) & carry & alu_src_a(CFG_DMEM_WIDTH - 1 DOWNTO 1);
166
            WHEN ALU_SEXT8  => result := '0' & sign_extend(alu_src_a(7 DOWNTO 0), alu_src_a(7), 32);
167
            WHEN ALU_SEXT16 => result := '0' & sign_extend(alu_src_a(15 DOWNTO 0), alu_src_a(15), 32);
168
            WHEN ALU_MUL =>
169
                IF G_USE_HW_MUL = true THEN
170
                    result := '0' & multiply(alu_src_a, alu_src_b);
171
                ELSE
172
                    result := (OTHERS => '0');
173
                END IF;
174
            WHEN ALU_BS =>
175
                IF G_USE_BARREL = true THEN
176
                    result := '0' & shift(alu_src_a, alu_src_b(4 DOWNTO 0), exec_i.imm(10), exec_i.imm(9));
177
                ELSE
178
                    result := (OTHERS => '0');
179
                END IF;
180
            WHEN OTHERS =>
181
                result := (OTHERS => '0');
182
                REPORT "Invalid ALU operation" SEVERITY FAILURE;
183
        END CASE;
184
 
185
        -- Set carry register
186
        IF exec_i.ctrl_ex.carry_keep = CARRY_KEEP THEN
187
            v_reg.carry := reg.carry;
188
        ELSE
189
            v_reg.carry := result(CFG_DMEM_WIDTH);
190
        END IF;
191
 
192
        zero := is_zero(dat_a);
193
 
194
        -- Overwrite branch condition
195
        IF reg.flush_ex = '1' THEN
196
            v.branch := '0';
197
        ELSE
198
            -- Determine branch condition
199
            CASE exec_i.ctrl_ex.branch_cond IS
200
                WHEN BNC => v.branch := '1';
201
                WHEN BEQ => v.branch := zero;
202
                WHEN BNE => v.branch := NOT zero;
203
                WHEN BLT => v.branch := dat_a(CFG_DMEM_WIDTH - 1);
204
                WHEN BLE => v.branch := dat_a(CFG_DMEM_WIDTH - 1) OR zero;
205 7 takar
                WHEN BGT => v.branch := NOT (dat_a(CFG_DMEM_WIDTH - 1) OR zero);
206
                WHEN BGE => v.branch := NOT dat_a(CFG_DMEM_WIDTH - 1);
207 2 takar
                WHEN OTHERS => v.branch := '0';
208
            END CASE;
209
        END IF;
210
 
211
        -- Handle CMPU
212
        IF ( exec_i.ctrl_ex.operation AND NOT (alu_src_a(CFG_DMEM_WIDTH - 1) XOR alu_src_b(CFG_DMEM_WIDTH - 1))) = '1' THEN
213
            -- Set MSB
214
            v.alu_result(CFG_DMEM_WIDTH - 1 DOWNTO 0) := (NOT result(CFG_DMEM_WIDTH - 1)) & result(CFG_DMEM_WIDTH - 2 DOWNTO 0);
215
        ELSE
216
            -- Use ALU result
217
            v.alu_result := result(CFG_DMEM_WIDTH - 1 DOWNTO 0);
218
        END IF;
219
 
220
        v.program_counter := exec_i.program_counter;
221
 
222
        -- Determine flush signals
223
        v.flush_id := v.branch;
224
        v_reg.flush_ex := v.branch AND NOT exec_i.ctrl_ex.delay;
225
 
226
        rin <= v;
227
        regin <= v_reg;
228
 
229
    END PROCESS;
230
 
231
    execute_seq: PROCESS(clk_i)
232
        PROCEDURE proc_execute_reset IS
233
        BEGIN
234
            r.alu_result             <= (OTHERS => '0');
235
            r.dat_d                  <= (OTHERS => '0');
236
            r.branch                 <= '0';
237
            r.program_counter        <= (OTHERS => '0');
238
            r.flush_id               <= '0';
239
            r.ctrl_mem.mem_write     <= '0';
240
            r.ctrl_mem.mem_read      <= '0';
241
            r.ctrl_mem.transfer_size <= WORD;
242
            r.ctrl_wb.reg_d          <= (OTHERS => '0');
243
            r.ctrl_wb.reg_write      <= '0';
244
            reg.carry                <= '0';
245
            reg.flush_ex             <= '0';
246
        END PROCEDURE proc_execute_reset;
247
    BEGIN
248
        IF rising_edge(clk_i) THEN
249
            IF rst_i = '1' THEN
250
                proc_execute_reset;
251
            ELSIF ena_i = '1' THEN
252
                r <= rin;
253
                reg <= regin;
254
            END IF;
255
        END IF;
256
    END PROCESS;
257
END arch;

powered by: WebSVN 2.1.0

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