OpenCores
URL https://opencores.org/ocsvn/1g_ethernet_dpi/1g_ethernet_dpi/trunk

Subversion Repositories 1g_ethernet_dpi

[/] [1g_ethernet_dpi/] [tags/] [vmblite_base/] [hw/] [src/] [rtl/] [mblite/] [core/] [execute.vhd] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 kuzmi4
----------------------------------------------------------------------------------------------
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
    ena_i  : in std_logic;
36
    rst_i  : in std_logic;
37
    clk_i  : in std_logic
38
);
39
end execute;
40
 
41
architecture arch of execute is
42
 
43
    type execute_reg_type is record
44
        carry    : std_logic;
45
        flush_ex : std_logic;
46
    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_wrb,exec_i.ctrl_mem,
57
            exec_i.ctrl_mem.transfer_size,
58
            exec_i.ctrl_mem_wrb,exec_i.fwd_dec,
59
            r,r.ctrl_mem,r.ctrl_mem.transfer_size,
60
            r.ctrl_wrb,reg)
61
 
62
        variable v : execute_out_type;
63
        variable v_reg : execute_reg_type;
64
 
65
        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
 
69
        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
 
73
        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
 
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_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
 
85
        if reg.flush_ex = '1' then
86
            v.ctrl_mem.mem_write := '0';
87
            v.ctrl_mem.mem_read := '0';
88
            v.ctrl_wrb.reg_write := '0';
89
            v.ctrl_wrb.reg_d := (others => '0');
90
        else
91
            v.ctrl_mem := exec_i.ctrl_mem;
92
            v.ctrl_wrb := exec_i.ctrl_wrb;
93
        end if;
94
 
95
        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
            mem_result := exec_i.alu_result;
99
        end if;
100
 
101
        if forward_condition(r.ctrl_wrb.reg_write, r.ctrl_wrb.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_wrb.reg_write, r.ctrl_wrb.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_wrb.reg_write, r.ctrl_wrb.reg_d, exec_i.ctrl_wrb.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_wrb.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
                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
 
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_wrb.reg_d         <= (others => '0');
243
            r.ctrl_wrb.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.