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

Subversion Repositories igor

[/] [igor/] [trunk/] [processor/] [mc/] [control.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 atypic
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
use ieee.std_logic_signed.all;
5
use work.leval_package.all;
6
 
7
entity control is
8
        port (
9
                clk                                     : in std_logic;
10
                rst                                     : in std_logic;
11
                -- status register
12
                status_in                       : in std_logic_vector(STATUS_REG_SIZE-1 downto 0);
13
                data_rdy                                : in std_logic; -- data ready on data bus signal
14
                sync                                    : in std_logic; -- AVR ready signal
15
                -- instruction signals
16
                opcode                          : in std_logic_vector(OPCODE_SIZE-1 downto 0);
17
                breakpoint                      : in std_logic;
18
                debug_en                                : in std_logic;
19
                break_mask                      : in std_logic_vector(STATUS_REG_SIZE-1 downto 0);
20
                break_flags                     : in std_logic_vector(STATUS_REG_SIZE-1 downto 0);
21
                indir_reg1                      : in std_logic;
22
                indir_reg2                      : in std_logic;
23
                -- scrath control signals
24
                write_reg_en            : out std_logic; -- enables writing of register file
25
                -- use address from indirect register-registers
26
                indir_reg1_sel          : out std_logic;
27
                indir_reg2_sel          : out std_logic;
28
                -- ALU
29
                alu_func                                : out std_logic_vector(FUNCT_SIZE-1 downto 0);
30
                alu_op1_sel                     : out std_logic; -- use r2 as first operand in ALU
31
                alu_op2_sel                     : out std_logic; -- when high use immidiate as second argument
32
                -- status register control line
33
                status_reg_w_en : out std_logic_vector(STATUS_REG_SIZE-1 downto 0);
34
                -- PC control
35
                pc_write_en                     : out std_logic; -- increment program counter
36
                branch_taken            : out std_logic; -- take branch
37
                -- memory control signals
38
                write                                   : out std_logic; -- write-signal
39
                read                                    : out std_logic; -- read-signal
40
                -- datapaths
41
                mem_to_reg_sel          : out std_logic; -- use databus instead of ALU result
42
                write_indir_addr_wr_en : out std_logic; -- udpate registers with indirect addresses
43
                state_out                       : out std_logic_vector(3 downto 0)); -- DEBUG SIGNAL
44
end entity;
45
 
46
architecture rtl of control is
47
        -- States
48
        type state_type is (st0_init,st1_fetch,st2_regfetch,st3_load_indir_regs,st4_load_indir_data,
49
                st5_execute,st6_wait_data,st7_wait_done,st8_io_done,st9_halt);
50
        signal state : state_type := st0_init;
51
        signal jump : boolean;
52
        signal stored : boolean := true; -- this is used only on LOAD operations to know if we
53
                                                                                                -- wrote result into register. So we can use the same
54
                                                                                                -- register for address and result
55
begin
56
 
57
        -- DECODE AND OUTPUT
58
        OUTPUT_DECODE: process (state,opcode,indir_reg1,indir_reg2,jump,stored,data_rdy)
59
        begin
60
                -- default values
61
                write_reg_en            <= '0'; -- disable register writing
62
                mem_to_reg_sel          <= '0'; -- use ALU's result
63
                alu_op1_sel             <= '0'; -- don't write result
64
                indir_reg1_sel          <= '0'; -- don't use indir-regs default
65
                indir_reg2_sel          <= '0';
66
                alu_func                                <= (others => '0');
67
                alu_op2_sel                     <= '0'; -- don't use immidiate default
68
                status_reg_w_en <= (others => '0'); -- don't write status register
69
                branch_taken            <= '0'; -- don't branch
70
                write                   <= '0';
71
                read                            <= '0';
72
                pc_write_en                     <= '0'; -- don't change PC
73
                write_indir_addr_wr_en <= '0';
74
                stored <= stored;
75
 
76
                case    (state) is
77
                        when st0_init =>
78
                                state_out <= X"0";
79
 
80
                        when st1_fetch =>
81
                                state_out <= X"1";
82
 
83
                        when st2_regfetch =>
84
                                -- do nothing, we're waiting for the registers to load
85
                                state_out <= X"2";
86
 
87
                        when st3_load_indir_regs =>
88
                                -- load the indirection registers with the current register-out values
89
                                state_out <= X"3";
90
                                write_indir_addr_wr_en <= '1';
91
                                 -- load indirect value
92
                                if indir_reg1 = '1' then
93
                                        indir_reg1_sel <= '1';
94
                                end if;
95
                                if indir_reg2 = '1' then
96
                                        indir_reg2_sel <= '1';
97
                                end if;
98
 
99
                        when st4_load_indir_data =>
100
                                -- do nothing
101
                                state_out <= X"4";
102
                                if indir_reg1 = '1' then
103
                                        indir_reg1_sel  <=      '1';
104
                                end if;
105
                                if      indir_reg2 = '1' then
106
                                        indir_reg2_sel  <=      '1';
107
                                end if;
108
 
109
                        when st5_execute =>
110
                                -- main execution state, sets signals according to input and state
111
                                state_out <= X"5";
112
                                status_reg_w_en <= (others => '1'); -- update status register on each operation
113
 
114
                                -- if we have load or store, we should wait with updating of PC
115
                                if (opcode = LOAD or opcode = STORE) then
116
                                        pc_write_en <= '0';
117
                                else
118
                                        pc_write_en <= '1';
119
                                end if;
120
 
121
                                -- indirect addressing
122
                                if indir_reg1 = '1' then
123
                                        indir_reg1_sel <= '1';
124
                                end if;
125
                                if indir_reg2 = '1' then
126
                                        indir_reg2_sel <= '1';
127
                                end if;
128
 
129
                                case opcode is
130
                                        -- Arithmetical / Logic functions
131
                                        when ADD =>
132
                                                alu_func <= ALU_ADD;
133
                                                write_reg_en <= '1';
134
 
135
                                        when SUBB =>
136
                                                alu_func <= ALU_SUB;
137
                                                write_reg_en <= '1';
138
 
139
                                        when MUL =>
140
                                                alu_func <= ALU_MUL;
141
                                                write_reg_en <= '1';
142
 
143
--                                      -- NOT IMPLEMENTED
144
--                                      when DIV =>
145
--                                              alu_func <= ALU_DIV;
146
--                                              write_reg_en <= '1';
147
--                                      when MODULO =>
148
--                                              alu_func <= ALU_MOD;
149
--                                              write_reg_en <= '1';
150
 
151
                                        when LAND =>
152
                                                alu_func <= ALU_AND;
153
                                                write_reg_en <= '1';
154
 
155
                                        when LOR =>
156
                                                alu_func <= ALU_OR;
157
                                                write_reg_en <= '1';
158
 
159
                                        when LXOR =>
160
                                                alu_func <= ALU_XOR;
161
                                                write_reg_en <= '1';
162
 
163
                                        when LOAD =>
164
                                                mem_to_reg_sel <= '1'; -- use data bus
165
                                                alu_func <= ALU_ADD;
166
                                                alu_op2_sel <= '1';
167
                                                alu_op1_sel <= '1';
168
                                                stored <= false;
169
 
170
                                        when STORE =>
171
                                                alu_func <= ALU_ADD;
172
                                                alu_op2_sel <= '1';
173
                                                alu_op1_sel <= '1';
174
                                                stored <= true;
175
 
176
                                        when BIDX =>
177
                                                if jump then
178
                                                        alu_func <= ALU_ADD;
179
                                                        branch_taken <= '1';
180
                                                        alu_op2_sel <= '1';
181
                                                end if;
182
 
183
                                        when GET_TYPE =>
184
                                                alu_func <= ALU_GET_TYPE;
185
                                                write_reg_en <= '1';
186
 
187
                                        when SET_TYPE =>
188
                                                alu_func <= ALU_SET_TYPE;
189
                                                write_reg_en <= '1';
190
 
191
                                        when SET_TYPE_IMM       =>
192
                                                alu_func <= ALU_SET_TYPE;
193
                                                write_reg_en <= '1';
194
                                                alu_op2_sel <= '1';
195
 
196
                                        when SET_DATUM =>
197
                                                alu_func <= ALU_SET_DATUM;
198
                                                write_reg_en <= '1';
199
 
200
                                        when SET_DATUM_IMM =>
201
                                                alu_func <= ALU_SET_DATUM;
202
                                                write_reg_en <= '1';
203
                                                alu_op2_sel <= '1';
204
 
205
                                        when SET_GC =>
206
                                                alu_func <= ALU_SET_GC;
207
                                                write_reg_en <= '1';
208
 
209
                                        when SET_GC_IMM =>
210
                                                alu_func <= ALU_SET_GC;
211
                                                write_reg_en <= '1';
212
                                                alu_op2_sel <= '1';
213
 
214
                                        when CPY =>
215
                                                alu_func <= ALU_CPY;
216
                                                write_reg_en <= '1';
217
 
218
                                        when CMP_TYPE =>
219
                                                alu_func <= ALU_CMP_TYPE;
220
 
221
                                        when CMP_TYPE_IMM =>
222
                                                alu_func <= ALU_CMP_TYPE_IMM;
223
                                                alu_op2_sel <= '1';
224
 
225
                                        when CMP_DATUM =>
226
                                                alu_func <= ALU_CMP_DATUM;
227
 
228
                                        when CMP_DATUM_IMM =>
229
                                                alu_func <= ALU_CMP_DATUM;
230
                                                alu_op2_sel <= '1';
231
 
232
                                        when CMP_GC =>
233
                                                alu_func <= ALU_CMP_GC;
234
 
235
                                        when CMP_GC_IMM =>
236
                                                alu_func <= ALU_CMP_GC_IMM;
237
                                                alu_op2_sel <= '1';
238
 
239
                                        when CMP =>
240
                                                alu_func <= ALU_CMP;
241
 
242
                                        when SHIFT_L =>
243
                                                alu_func <= ALU_SL;
244
                                                write_reg_en <= '1';
245
 
246
                                        when SHIFT_R =>
247
                                                alu_func <= ALU_SR;
248
                                                write_reg_en <= '1';
249
 
250
                                        when SETLED =>
251
                                                alu_func <= ALU_SETLED;
252
 
253
                                        when others =>
254
                                                -- unknown opcode, do nothing
255
                                                alu_func <= ALU_PASS;
256
                                        end case;
257
 
258
                        when st6_wait_data =>
259
                                -- HOLD load or store signals
260
                                state_out <= X"6";
261
                                if indir_reg1 = '1' then
262
                                        indir_reg1_sel <= '1';
263
                                end if;
264
                                if indir_reg2 = '1' then
265
                                        indir_reg2_sel <= '1';
266
                                end if;
267
 
268
                                alu_op2_sel <= '1'; -- use immediate value
269
                                alu_func <= ALU_ADD;  --calculate load/store address
270
                                alu_op1_sel <= '1'; -- use R2 with immidiate in ALU
271
 
272
                                if (opcode = LOAD) then
273
                                        mem_to_reg_sel <= '1'; -- load data from bus
274
                                        read <= '1'; -- set read control signal
275
                                        if data_rdy = '0' and stored = false then -- if data is not stored, but ready on the bus
276
                                                write_reg_en <= '1'; -- enable writing of the register
277
                                                stored <= true; -- remember that we stored data
278
                                        end if;
279
                                else -- means STORE
280
                                        stored <= true; -- we don't need to write anything in register memory
281
                                        write <= '1'; -- set write control signal
282
                                end if;
283
 
284
                        when st7_wait_done =>
285
                                -- remove read/write signal and wait till distanation unit clears ready control line
286
                                state_out <= X"7";
287
                                -- hold address values just to be sure
288
                                if indir_reg1 = '1' then
289
                                        indir_reg1_sel <= '1';
290
                                end if;
291
                                if indir_reg2 = '1' then
292
                                        indir_reg2_sel <= '1';
293
                                end if;
294
                                alu_op2_sel <= '1';
295
                                alu_func <= ALU_ADD;
296
                                alu_op1_sel <= '1';
297
 
298
                        when st8_io_done =>
299
                                -- one cycle to update PC
300
                                state_out <= X"8";
301
                                pc_write_en <= '1';
302
 
303
                        when st9_halt =>
304
                                -- HALT state (we can't get out of here unless reset)
305
                                state_out <= X"9";
306
 
307
                        when others =>
308
                                -- unknown state
309
                                state_out <= X"F";
310
                end case;
311
 
312
        end process;
313
 
314
        -- NEXT STATE FUNCTION
315
        NEXT_STATE_DECODE: process(clk)
316
        begin
317
        if rising_edge(clk) then
318
                if rst = '1' then
319
                        state <= st0_init;
320
                end if;
321
                case (state) is
322
                        when st0_init =>
323
                                if sync = '1' then
324
                                        state <= st1_fetch;
325
                                end if;
326
                        when st1_fetch =>
327
                                state <= st2_regfetch;
328
 
329
                        when st2_regfetch =>
330
                                if indir_reg1 = '1' or indir_reg2 = '1' then
331
                                        -- if we need to load indirect registers
332
                                        state <= st3_load_indir_regs;
333
                                else
334
                                        state <= st5_execute;
335
                                end if;
336
 
337
                        when st3_load_indir_regs =>
338
                                state <= st4_load_indir_data;
339
 
340
                        when st4_load_indir_data =>
341
                                state <= st5_execute;
342
 
343
                        when st5_execute =>
344
                                -- HALT conditions
345
                                if breakpoint = '1' or debug_en = '1' or opcode = HALT then
346
                                        state <= st9_halt;
347
                                -- LOAD/STORE
348
                                elsif opcode=LOAD or opcode = STORE then
349
                                        state <= st6_wait_data;
350
                                -- otherwise go to fetch next instruction
351
                                else
352
                                        state <= st1_fetch;
353
                                end if;
354
                        when st6_wait_data =>
355
                                if data_rdy = '0' and stored = true then
356
                                        state <= st7_wait_done;
357
                                end if;
358
 
359
                        when st7_wait_done =>
360
                                if data_rdy = '1' then
361
                                        state <= st8_io_done;
362
                                end if;
363
 
364
                        when st8_io_done =>
365
                                        state <= st1_fetch;
366
 
367
                        when st9_halt =>
368
                                -- We halt, program is over.
369
                end case;
370
        end if;
371
        end process;
372
 
373
        update_branch_evaluator : process(clk)
374
        begin
375
                if rising_edge(clk) then
376
                        -- compare status register with branch flags, filtered by branch mask
377
                        if (status_in and break_mask) = (break_flags and break_mask) then
378
                                jump <= true;
379
                        else
380
                                jump <= false;
381
                        end if;
382
                end if;
383
        end process;
384
end rtl;

powered by: WebSVN 2.1.0

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