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

Subversion Repositories mblite

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

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 8 takar
library ieee;
18
use ieee.std_logic_1164.all;
19
use ieee.std_logic_unsigned.all;
20 2 takar
 
21 8 takar
library mblite;
22
use mblite.config_Pkg.all;
23
use mblite.core_Pkg.all;
24
use mblite.std_Pkg.all;
25 2 takar
 
26 8 takar
entity execute is generic
27 2 takar
(
28
    G_USE_HW_MUL : boolean := CFG_USE_HW_MUL;
29
    G_USE_BARREL : boolean := CFG_USE_BARREL
30
);
31 8 takar
port
32 2 takar
(
33 8 takar
    exec_o : out execute_out_type;
34
    exec_i : in execute_in_type;
35
    ena_i  : in std_logic;
36
    rst_i  : in std_logic;
37
    clk_i  : in std_logic
38 2 takar
);
39 8 takar
end execute;
40 2 takar
 
41 8 takar
architecture arch of execute is
42 2 takar
 
43 8 takar
    type execute_reg_type is record
44
        carry    : std_logic;
45
        flush_ex : std_logic;
46
    end record;
47 2 takar
 
48 8 takar
    signal r, rin     : execute_out_type;
49
    signal reg, regin : execute_reg_type;
50 2 takar
 
51 8 takar
begin
52 2 takar
 
53
    exec_o <= r;
54
 
55 8 takar
    execute_comb: process(exec_i,exec_i.fwd_mem,exec_i.ctrl_ex,
56
            exec_i.ctrl_wrb,exec_i.ctrl_mem,
57 2 takar
            exec_i.ctrl_mem.transfer_size,
58 8 takar
            exec_i.ctrl_mem_wrb,exec_i.fwd_dec,
59 2 takar
            r,r.ctrl_mem,r.ctrl_mem.transfer_size,
60 8 takar
            r.ctrl_wrb,reg)
61 2 takar
 
62 8 takar
        variable v : execute_out_type;
63
        variable v_reg : execute_reg_type;
64 2 takar
 
65 8 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 8 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 8 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 8 takar
    begin
78 2 takar
 
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 8 takar
        sel_dat_d := select_register_data(exec_i.dat_d, exec_i.ctrl_wrb.reg_d, exec_i.fwd_dec_result, forward_condition(exec_i.fwd_dec.reg_write, exec_i.fwd_dec.reg_d, exec_i.ctrl_wrb.reg_d));
84 2 takar
 
85 8 takar
        if reg.flush_ex = '1' then
86 2 takar
            v.ctrl_mem.mem_write := '0';
87
            v.ctrl_mem.mem_read := '0';
88 8 takar
            v.ctrl_wrb.reg_write := '0';
89
            v.ctrl_wrb.reg_d := (others => '0');
90
        else
91 2 takar
            v.ctrl_mem := exec_i.ctrl_mem;
92 8 takar
            v.ctrl_wrb := exec_i.ctrl_wrb;
93
        end if;
94 2 takar
 
95 8 takar
        if exec_i.ctrl_mem_wrb.mem_read = '1' then
96
            mem_result := align_mem_load(exec_i.mem_result, exec_i.ctrl_mem_wrb.transfer_size, exec_i.alu_result(1 downto 0));
97
        else
98 2 takar
            mem_result := exec_i.alu_result;
99 8 takar
        end if;
100 2 takar
 
101 8 takar
        if forward_condition(r.ctrl_wrb.reg_write, r.ctrl_wrb.reg_d, exec_i.reg_a) = '1' then
102 2 takar
            -- Forward Execution Result to REG a
103
            dat_a := r.alu_result;
104 8 takar
        elsif forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.reg_a) = '1' then
105 2 takar
            -- Forward Memory Result to REG a
106
            dat_a := mem_result;
107 8 takar
        else
108 2 takar
            -- DEFAULT: value of REG a
109
            dat_a := sel_dat_a;
110 8 takar
        end if;
111 2 takar
 
112 8 takar
        if forward_condition(r.ctrl_wrb.reg_write, r.ctrl_wrb.reg_d, exec_i.reg_b) = '1' then
113 2 takar
            -- Forward (latched) Execution Result to REG b
114
            dat_b := r.alu_result;
115 8 takar
        elsif forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.reg_b) = '1' then
116 2 takar
            -- Forward Memory Result to REG b
117
            dat_b := mem_result;
118 8 takar
        else
119 2 takar
            -- DEFAULT: value of REG b
120
            dat_b := sel_dat_b;
121 8 takar
        end if;
122 2 takar
 
123 8 takar
        if forward_condition(r.ctrl_wrb.reg_write, r.ctrl_wrb.reg_d, exec_i.ctrl_wrb.reg_d) = '1' then
124 2 takar
            -- Forward Execution Result to REG d
125
            v.dat_d := align_mem_store(r.alu_result, exec_i.ctrl_mem.transfer_size);
126 8 takar
        elsif forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.ctrl_wrb.reg_d) = '1' then
127 2 takar
            -- Forward Memory Result to REG d
128
            v.dat_d := align_mem_store(mem_result, exec_i.ctrl_mem.transfer_size);
129 8 takar
        else
130 2 takar
            -- DEFAULT: value of REG d
131
            v.dat_d := align_mem_store(sel_dat_d, exec_i.ctrl_mem.transfer_size);
132 8 takar
        end if;
133 2 takar
 
134
        -- Set the first operand of the ALU
135 8 takar
        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 2 takar
 
142
        -- Set the second operand of the ALU
143 8 takar
        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 2 takar
 
150
        -- Determine value of carry in
151 8 takar
        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 2 takar
 
158
        result_add := add(alu_src_a, alu_src_b, carry);
159
 
160 8 takar
        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 2 takar
                    result := '0' & multiply(alu_src_a, alu_src_b);
171 8 takar
                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 2 takar
 
185
        -- Set carry register
186 8 takar
        if exec_i.ctrl_ex.carry_keep = CARRY_KEEP then
187 2 takar
            v_reg.carry := reg.carry;
188 8 takar
        else
189 2 takar
            v_reg.carry := result(CFG_DMEM_WIDTH);
190 8 takar
        end if;
191 2 takar
 
192
        zero := is_zero(dat_a);
193
 
194
        -- Overwrite branch condition
195 8 takar
        if reg.flush_ex = '1' then
196 2 takar
            v.branch := '0';
197 8 takar
        else
198 2 takar
            -- Determine branch condition
199 8 takar
            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
                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
                when others => v.branch := '0';
208
            end case;
209
        end if;
210 2 takar
 
211
        -- Handle CMPU
212 8 takar
        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 2 takar
            -- Set MSB
214 8 takar
            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 2 takar
            -- Use ALU result
217 8 takar
            v.alu_result := result(CFG_DMEM_WIDTH - 1 downto 0);
218
        end if;
219 2 takar
 
220
        v.program_counter := exec_i.program_counter;
221
 
222
        -- Determine flush signals
223
        v.flush_id := v.branch;
224 8 takar
        v_reg.flush_ex := v.branch and not exec_i.ctrl_ex.delay;
225 2 takar
 
226 8 takar
        rin   <= v;
227 2 takar
        regin <= v_reg;
228
 
229 8 takar
    end process;
230 2 takar
 
231 8 takar
    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 2 takar
            r.branch                 <= '0';
237 8 takar
            r.program_counter        <= (others => '0');
238 2 takar
            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 8 takar
            r.ctrl_wrb.reg_d         <= (others => '0');
243
            r.ctrl_wrb.reg_write     <= '0';
244 2 takar
            reg.carry                <= '0';
245
            reg.flush_ex             <= '0';
246 8 takar
        end procedure proc_execute_reset;
247
    begin
248
        if rising_edge(clk_i) then
249
            if rst_i = '1' then
250 2 takar
                proc_execute_reset;
251 8 takar
            elsif ena_i = '1' then
252
                r   <= rin;
253 2 takar
                reg <= regin;
254 8 takar
            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.