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

Subversion Repositories neo430

[/] [neo430/] [trunk/] [neo430/] [rtl/] [core/] [neo430_control.vhd] - Blame information for rev 198

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 198 zero_gravi
-- #################################################################################################
2
-- #  << NEO430 - Main Control Unit >>                                                             #
3
-- # ********************************************************************************************* #
4
-- # Central CPU control unit (micro sequencer / FSM).                                             #
5
-- # ********************************************************************************************* #
6
-- # BSD 3-Clause License                                                                          #
7
-- #                                                                                               #
8
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
9
-- #                                                                                               #
10
-- # Redistribution and use in source and binary forms, with or without modification, are          #
11
-- # permitted provided that the following conditions are met:                                     #
12
-- #                                                                                               #
13
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
14
-- #    conditions and the following disclaimer.                                                   #
15
-- #                                                                                               #
16
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
17
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
18
-- #    provided with the distribution.                                                            #
19
-- #                                                                                               #
20
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
21
-- #    endorse or promote products derived from this software without specific prior written      #
22
-- #    permission.                                                                                #
23
-- #                                                                                               #
24
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
25
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
26
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
27
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
28
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
29
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
30
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
31
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
32
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
33
-- # ********************************************************************************************* #
34
-- # The NEO430 Processor - https://github.com/stnolting/neo430                                    #
35
-- #################################################################################################
36
 
37
library ieee;
38
use ieee.std_logic_1164.all;
39
use ieee.numeric_std.all;
40
 
41
library neo430;
42
use neo430.neo430_package.all;
43
 
44
entity neo430_control is
45
  port (
46
    -- global control --
47
    clk_i     : in  std_ulogic; -- global clock, rising edge
48
    rst_i     : in  std_ulogic; -- global reset, low-active, async
49
    -- memory interface --
50
    instr_i   : in  std_ulogic_vector(15 downto 0); -- instruction word from memory
51
    -- control --
52
    sreg_i    : in  std_ulogic_vector(15 downto 0); -- current status register
53
    ctrl_o    : out std_ulogic_vector(ctrl_width_c-1 downto 0); -- control signals
54
    irq_vec_o : out std_ulogic_vector(01 downto 0); -- irq channel address
55
    imm_o     : out std_ulogic_vector(15 downto 0); -- branch offset
56
    -- irq lines --
57
    irq_i     : in  std_ulogic_vector(03 downto 0)  -- IRQ lines^
58
  );
59
end neo430_control;
60
 
61
architecture neo430_control_rtl of neo430_control is
62
 
63
  -- instruction register --
64
  signal ir      : std_ulogic_vector(15 downto 0);
65
  signal ir_wren : std_ulogic;
66
 
67
  -- branch system --
68
  signal branch_taken : std_ulogic;
69
 
70
  -- state machine --
71
  type state_t is (RESET, IFETCH_0, IFETCH_1, DECODE,
72
    TRANS_0, TRANS_1, TRANS_2, TRANS_3, TRANS_4, TRANS_5, TRANS_6,
73
    PUSHCALL_0, PUSHCALL_1, PUSHCALL_2,
74
    RETI_0, RETI_1, RETI_2, RETI_3,
75
    IRQ_0, IRQ_1, IRQ_2, IRQ_3, IRQ_4, IRQ_5);
76
  signal state, state_nxt  : state_t;
77
  signal ctrl_nxt, ctrl    : std_ulogic_vector(ctrl_width_c-1 downto 0);
78
  signal am_nxt, am        : std_ulogic_vector(03 downto 0); -- addressing mode
79
  signal mem_rd, mem_rd_ff : std_ulogic; -- memory read buffers
80
  signal src_nxt, src      : std_ulogic_vector(03 downto 0); -- source reg
81
  signal sam_nxt, sam      : std_ulogic_vector(01 downto 0); -- CMD according SRC addressing mode
82
 
83
  -- irq system --
84
  signal irq_fire               : std_ulogic;
85
  signal irq_start, irq_ack     : std_ulogic;
86
  signal irq_ack_mask, irq_buf  : std_ulogic_vector(3 downto 0);
87
  signal irq_vec_nxt, irq_vec   : std_ulogic_vector(1 downto 0);
88
  signal i_flag_ff0, i_flag_ff1 : std_ulogic;
89
 
90
begin
91
 
92
  -- Branch Condition Check ---------------------------------------------------
93
  -- -----------------------------------------------------------------------------
94
  cond_check: process(instr_i, sreg_i)
95
  begin
96
    case instr_i(12 downto 10) is -- condition
97
      when cond_ne_c => branch_taken <= not sreg_i(sreg_z_c); -- JNE/JNZ
98
      when cond_eq_c => branch_taken <= sreg_i(sreg_z_c); -- JEQ/JZ
99
      when cond_lo_c => branch_taken <= not sreg_i(sreg_c_c); -- JNC/JLO
100
      when cond_hs_c => branch_taken <= sreg_i(sreg_c_c); -- JC/JHS
101
      when cond_mi_c => branch_taken <= sreg_i(sreg_n_c); -- JN
102
      when cond_ge_c => branch_taken <= not (sreg_i(sreg_n_c) xor sreg_i(sreg_v_c)); -- JGE
103
      when cond_le_c => branch_taken <= sreg_i(sreg_n_c) xor sreg_i(sreg_v_c); -- JL
104
      when cond_al_c => branch_taken <= '1'; -- JMP (always)
105
      when others    => branch_taken <= '0'; -- undefined
106
    end case;
107
  end process cond_check;
108
 
109
  -- branch offset (sign-extended) from instruction REGISTER --
110
  imm_o <= ir(9) & ir(9) & ir(9) & ir(9) & ir(9) & ir(9 downto 0) & '0';
111
 
112
 
113
  -- Arbiter State Machine Sync -----------------------------------------------
114
  -- -----------------------------------------------------------------------------
115
  arbiter_sync0: process(rst_i, clk_i)
116
  begin
117
    -- the arbiter requires a defined initial state
118
    if (rst_i = '0') then
119
      state <= RESET; -- this is crucial!
120
    elsif rising_edge(clk_i) then
121
      state <= state_nxt;
122
    end if;
123
  end process arbiter_sync0;
124
 
125
  arbiter_sync1: process(clk_i)
126
  begin
127
    if rising_edge(clk_i) then
128
      -- these signals do not need a specific reset state
129
      ctrl      <= ctrl_nxt;
130
      src       <= src_nxt;
131
      mem_rd_ff <= mem_rd;
132
      am        <= am_nxt;
133
      sam       <= sam_nxt;
134
      if (ir_wren = '1') then
135
        ir <= instr_i; -- instruction register
136
      end if;
137
    end if;
138
  end process arbiter_sync1;
139
 
140
  -- control bus output --
141
  ctrl_o <= ctrl;
142
 
143
  -- someone using the DADD instruction? --
144
  dadd_sanity_check: process(clk_i)
145
  begin
146
    if rising_edge(clk_i) then
147
      if (instr_i(15 downto 12) = "1010") then -- DADD
148
        assert false report "DADD instruction not supported!" severity error;
149
      end if;
150
    end if;
151
  end process dadd_sanity_check;
152
 
153
 
154
  -- Arbiter State Machine Comb -----------------------------------------------
155
  -- -----------------------------------------------------------------------------
156
  arbiter_comb: process(state, instr_i, ir, ctrl, branch_taken, src, am, sam, mem_rd_ff, irq_start, sreg_i)
157
    variable spec_cmd_v, valid_wb_v, move_cmd_v : std_ulogic;
158
  begin
159
 
160
    -- NOTES --
161
    -- Signals in states/sub states marked with a "-->" are moved out of case statement and are set as pseudo default.
162
    -- The general assigning of this signal does not effect states, which actually do not require this signal.
163
    -- However, this saves some mux logic in the states.
164
 
165
    -- arbiter defaults --
166
    state_nxt <= state;
167
    src_nxt   <= src; -- source reg
168
    am_nxt    <= am;  -- total addressing mode [OP class I/II, src_addr_mode(1), src_addr_mode(0), dst_addr_mode]
169
    sam_nxt   <= sam; -- default source addressing mode
170
    ir_wren   <= '0'; -- write to instruction register
171
    mem_rd    <= '0'; -- normal ("slow") memory read
172
    irq_ack   <= '0'; -- ack irq to irq-controller
173
 
174
    -- control defaults --
175
    ctrl_nxt <= (others => '0'); -- all off
176
    ctrl_nxt(ctrl_rf_adr3_c  downto ctrl_rf_adr0_c)  <= src; -- source reg A
177
    ctrl_nxt(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) <= ctrl(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c); -- keep ALU function
178
    ctrl_nxt(ctrl_rf_as1_c downto ctrl_rf_as0_c) <= sam; -- default SRC addressing mode
179
    ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2 as address offset
180
    ctrl_nxt(ctrl_mem_rd_c) <= mem_rd_ff; -- delayed memory read
181
    ctrl_nxt(ctrl_alu_bw_c) <= ctrl(ctrl_alu_bw_c); -- keep byte/word mode
182
 
183
    -- special single ALU operation? --
184
    spec_cmd_v := '0';
185
    if (ir(15 downto 9) = "0001001") then -- CALL or PUSH or RETI
186
      spec_cmd_v := '1';
187
    end if;
188
 
189
    -- is MOV operation? --
190
    move_cmd_v := '0';
191
    -- use ctrl's signals here, since MOV operation can be set by IR and by the FSM itself
192
    if (ctrl(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) = alu_mov_c) then
193
      move_cmd_v := '1';
194
    end if;
195
 
196
    -- valid write back? --
197
    valid_wb_v := '1';
198
    if (ir(15 downto 12) = alu_cmp_c) or (ir(15 downto 12) = alu_bit_c) then
199
      valid_wb_v := '0'; -- CMP and BIT instructions only write status flags
200
    end if;
201
 
202
    -- state machine --
203
    case state is
204
 
205
      when RESET => -- init PC with boot address
206
      -- ------------------------------------------------------------
207
        ctrl_nxt(ctrl_rf_boot_c) <= '1'; -- load boot address
208
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
209
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC
210
        state_nxt <= IFETCH_0;
211
 
212
 
213
      when IFETCH_0 => -- output and update PC & IRQ check (stay here for SLEEP)
214
      -- ------------------------------------------------------------
215
        sam_nxt <= "00"; -- SRC address mode = REG, required for all special operations + IRQ
216
        ctrl_nxt(ctrl_alu_bw_c) <= '0'; -- word mode, also required for all IRQ states
217
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC
218
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2
219
        ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback
220
        ctrl_nxt(ctrl_adr_bp_en_c) <= '1'; -- directly output PC/IRQ vector
221
        if (irq_start = '1') then -- execute IRQ
222
          state_nxt <= IRQ_0;
223
        elsif (sreg_i(sreg_s_c) = '0') then -- no sleep mode = normal execution
224
          ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast)
225
          ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
226
          state_nxt <= IFETCH_1;
227
        end if;
228
 
229
      when IFETCH_1 => -- wait for memory
230
      -- ------------------------------------------------------------
231
        state_nxt <= DECODE;
232
 
233
 
234
      when DECODE => -- decode applied instruction & store it to IR
235
      -- ------------------------------------------------------------
236
        ir_wren <= '1'; -- update instruction register
237
        ctrl_nxt(ctrl_alu_bw_c) <= instr_i(6); -- byte/word mode
238
        sam_nxt <= instr_i(5 downto 4);
239
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC (used by branch instructions only)
240
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "000"; -- add immediate offset (used by branch instructions only)
241
        ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback (used by branch instructions only)
242
 
243
        if (instr_i(15 downto 14) = "00") then -- branch or format II instruction
244
          if (instr_i(13) = '1') then -- BRANCH INSTRUCTION
245
          -- ------------------------------------------------------------
246
            ctrl_nxt(ctrl_rf_wb_en_c) <= branch_taken; -- valid RF write back if branch taken
247
            state_nxt <= IFETCH_0;
248
 
249
          elsif (instr_i(12 downto 10) = "100") then -- FORMAT II INSTRUCTION
250
            -- ------------------------------------------------------------
251
            am_nxt(0) <= instr_i(4) or instr_i(5); -- dst addressing mode
252
            am_nxt(3) <= '0'; -- class II
253
            if (instr_i(3 downto 0) = reg_cg_c) or ((instr_i(3 downto 0) = reg_sr_c) and (instr_i(5) = '1')) then -- source special?
254
              am_nxt(2 downto 1) <= "00"; -- source addressing mode
255
            else
256
              am_nxt(2 downto 1) <= instr_i(5 downto 4); -- source addressing mode
257
            end if;
258
            src_nxt <= instr_i(3 downto 0); -- src is also dst
259
            if (instr_i(15 downto 9) /= "0001001") then -- not PUSH/CALL/RETI?
260
              ctrl_nxt(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) <= "00" & instr_i(8 downto 7); -- ALU function (rrc/swpb/rra/sxt)
261
            else
262
              ctrl_nxt(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) <= alu_mov_c; -- to move OpA -> RF/MEM
263
            end if;
264
            case instr_i(9 downto 7) is
265
              when "100"  => state_nxt <= TRANS_0;  -- PUSH (via single ALU OP)
266
              when "101"  => state_nxt <= TRANS_0;  -- CALL (via single ALU OP)
267
              when "110"  => state_nxt <= RETI_0;   -- RETI
268
              when "111"  => state_nxt <= IFETCH_0; -- !!!UNDEFINED OPCODE!!!
269
              when others => state_nxt <= TRANS_0;  -- single ALU OP (FORMAT II)
270
            end case;
271
 
272
          else -- !!!UNDEFINED OPCODE!!!
273
            -- ------------------------------------------------------------
274
            state_nxt <= IFETCH_0;
275
          end if;
276
 
277
        else -- FORMAT I INSTRUCTION
278
        -- ------------------------------------------------------------
279
          am_nxt(3) <= '1'; -- class I
280
          if (instr_i(11 downto 8) = reg_cg_c) or ((instr_i(11 downto 8) = reg_sr_c) and (instr_i(5) = '1')) then -- source special?
281
            am_nxt(2 downto 1) <= "00"; -- source addressing mode for r2 & r3
282
          else
283
            am_nxt(2 downto 1) <= instr_i(5 downto 4); -- source addressing mode
284
          end if;
285
          am_nxt(0) <= instr_i(7); -- dst addressing mode
286
          ctrl_nxt(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) <= instr_i(15 downto 12); -- ALU function
287
          src_nxt <= instr_i(11 downto 8);
288
          if (instr_i(15 downto 12) = "1010") then -- !!!INVALID ALUOP!!!
289
            state_nxt <= IFETCH_0;
290
          else
291
            state_nxt <= TRANS_0;
292
          end if;
293
        end if;
294
 
295
 
296
      when TRANS_0 => -- operand transfer cycle 0
297
      -- ------------------------------------------------------------
298
        -- (pseudo) defaults 
299
        ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback (only relevant for when 2,3,5)
300
        ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast)
301
        ctrl_nxt(ctrl_adr_bp_en_c) <= '1'; -- directly output RF.out to address bus
302
        ctrl_nxt(ctrl_adr_mar_wr_c) <= am(0); -- write to MAR [relevant for memory writeback when using CLASS II operations]
303
        --
304
        case am is -- addressing mode
305
          when "0001" | "0000" | "1000" =>
306
            -- "0001" = CLASS II, SRC: Reg, DST: Indexed
307
            -- "0000" = CLASS II, SRC/DST: register direct
308
            -- "1000" = CLASS  I, SRC/DST: Reg
309
            ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= src; -- source: reg A
310
            ctrl_nxt(ctrl_alu_opa_wr_c) <= '1'; -- write OpA
311
            if (spec_cmd_v = '1') then -- push or call
312
              state_nxt <= PUSHCALL_0;
313
            elsif (am(3) = '0') then -- CLASS II operation
314
              state_nxt <= TRANS_6;
315
            else
316
              state_nxt <= TRANS_3;
317
            end if;
318
 
319
          when "1001"   |   "1010" | "0010"  | "0011" =>
320
            -- "1001" = CLASS  I, SRC: register direct, DST: indexed
321
            --
322
            -- "1010" = CLASS  I, SRC: indexed/symbolic/absolute, DST: register direct
323
            -- "001-" = CLASS II, SRC: indexed/symbolic/absolute, DST: indexed/symbolic/absolute OR register direct
324
            ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC
325
-->         ctrl_nxt(ctrl_adr_bp_en_c) <= '1'; -- directly output RF.out to address bus
326
-->         ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast)
327
            ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2
328
-->         ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback
329
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
330
            if (am(2 downto 1) = "00") then -- "1001" = CLASS  I, SRC: register direct, DST: indexed
331
              state_nxt <= TRANS_3;
332
            else
333
              state_nxt <= TRANS_2;
334
            end if;
335
 
336
          when "1011" =>
337
            -- "1011" = CLASS  I, SRC: indexed/symbolic/absolute, DST: indexed
338
            ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC
339
            ctrl_nxt(ctrl_adr_mar_wr_c) <= '1'; -- write to MAR
340
            mem_rd <= '1'; -- Memory read
341
-->         ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast)
342
            ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2
343
-->         ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback
344
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
345
            state_nxt <= TRANS_1;
346
 
347
          when "0100" | "0101" | "1100" | "1101" =>
348
            -- "010-" = CLASS II, SRC/DST: indirect
349
            -- "1100" = CLASS  I, SRC: indirect, DST: register direct
350
            -- "1101" = CLASS  I, SRC: indirect, DST: indexed
351
            ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= src; -- source: reg A
352
-->         cctrl_nxt(ctrl_adr_bp_en_c) <= '1'; -- directly output RF.out to address bus
353
-->         ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast)
354
            state_nxt <= TRANS_1;
355
 
356
          when others =>
357
            -- "011-" = CLASS II, SRC/DST: indirect auto inc
358
            -- "1110" = CLASS  I, SRC: indirect auto inc, DST: register direct
359
            -- "1111" = CLASS  I, SRC: indirect auto inc, DST: indexed
360
            ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= src; -- source: reg A
361
-->         cctrl_nxt(ctrl_adr_bp_en_c) <= '1'; -- directly output RF.out to address bus
362
-->         ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast)
363
            if (ir(6) = '0') or (src = reg_pc_c) then -- word mode (force if accessing PC)
364
              ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2
365
            else -- byte mode
366
              ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "001"; -- add +1
367
            end if;
368
-->         ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback
369
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
370
            state_nxt <= TRANS_1;
371
        end case;
372
 
373
      when TRANS_1 => -- operand transfer cycle 1
374
      -- ------------------------------------------------------------
375
        -- (pseudo) defaults 
376
        ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback (only relevant for last two 'when')
377
        ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast) (only relevant for last two 'when' 4)
378
        mem_rd <= '1'; -- Memory read (only relevant for last two 'when' 5)
379
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2
380
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC
381
        --
382
        case am is -- addressing mode
383
          -- "000-" = CLASS II, SRC/DST: register direct                   [ACTUAL DON'T CARE; STATE NOT USED]
384
          -- "1000" = CLASS  I, SRC: register direct, DST: register direct [ACTUAL DON'T CARE; STATE NOT USED]
385
          -- "1001" = CLASS  I, SRC: register direct, DST: indexed         [ACTUAL DON'T CARE; STATE NOT USED]
386
          -- ==> DONT CARE
387
 
388
          -- "001-" = CLASS II, SRC/DST: indexed/symbolic/absolute                   [ACTUAL DON'T CARE; STATE NOT USED]
389
          -- "1010" = CLASS  I, SRC: indexed/symbolic/absolute, DST: register direct [ACTUAL DON'T CARE; STATE NOT USED]
390
          -- ==> DONT CARE
391
 
392
          when "0100" | "0101" | "1100"   |   "0110" | "0111" | "1110" =>
393
            -- "010-" = CLASS II, SRC/DST: indirect
394
            -- "1100" = CLASS  I, SRC: indirect, DST: register direct
395
            --
396
            -- "011-" = CLASS II, SRC/DST: indirect auto inc,
397
            -- "1110" = CLASS  I, SRC: indirect auto inc, DST: register direct
398
            ctrl_nxt(ctrl_alu_in_sel_c) <= '1'; -- get data from memory
399
            ctrl_nxt(ctrl_alu_opa_wr_c) <= '1'; -- write OpA
400
            if (spec_cmd_v = '1') then -- push or call
401
              state_nxt <= PUSHCALL_0;
402
            else
403
              if (am(3) = '0') then -- CLASS II
404
                state_nxt <= TRANS_6;
405
              else -- CLASS I
406
                state_nxt <= TRANS_3;
407
              end if;
408
            end if;
409
 
410
          when "1101"  |  "1111" =>
411
            -- "1101" = CLASS  I, SRC: indirect, DST: indexed
412
            --
413
            -- "1111" = CLASS  I, SRC: indirect auto inc, DST: indexed
414
-->         ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC
415
            ctrl_nxt(ctrl_adr_bp_en_c) <= '1'; -- directly output RF.out to address bus
416
-->         ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast)
417
-->         ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2
418
-->         ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback 
419
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
420
            ctrl_nxt(ctrl_alu_in_sel_c) <= '1'; -- get data from memory
421
            ctrl_nxt(ctrl_alu_opa_wr_c) <= '1'; -- write OpA
422
            state_nxt <= TRANS_3; -- no PUSHCALL check required
423
 
424
          when others =>
425
            -- "1011" = CLASS  I, SRC: indexed/symbolic/absolute, DST: indexed
426
-->         ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC
427
            ctrl_nxt(ctrl_adr_mar_wr_c) <= '1'; -- write to MAR
428
-->         mem_rd <= '1'; -- Memory read
429
-->         ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2
430
-->         ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback 
431
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
432
            state_nxt <= TRANS_2;
433
        end case;
434
 
435
      when TRANS_2 => -- operand transfer cycle 2
436
      -- ------------------------------------------------------------
437
        -- "001-" = CLASS II: SRC/DST: indexed/symbolic/absolute
438
        -- "1010" = CLASS  I, SRC:     indexed/symbolic/absolute, DST: register direct
439
        -- "1011" = CLASS  I, SRC:     indexed/symbolic/absolute, DST: indexed
440
        -- OTHERS = DONT CARE [state not reachable]
441
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= src; -- source: reg A
442
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "1--"; -- add memory data in (only relevant for first 'when')
443
        ctrl_nxt(ctrl_adr_mar_sel_c) <= '1'; -- use result from adder
444
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "1--"; -- add memory data in
445
        ctrl_nxt(ctrl_adr_mar_wr_c) <= '1'; -- write to MAR
446
        mem_rd <= '1'; -- Memory read
447
        mem_rd <= '1'; -- Memory read
448
        state_nxt <= TRANS_3;
449
 
450
      when TRANS_3 => -- operand transfer cycle 3
451
      -- ------------------------------------------------------------
452
        -- (pseudo) defaults 
453
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= ir(3 downto 0); -- source: reg B
454
        ctrl_nxt(ctrl_adr_mar_sel_c) <= '1'; -- use result from adder
455
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "1--"; -- add memory data in
456
        --
457
        case am is -- addressing mode
458
          when "1001" | "1011" | "1101" | "1111" =>
459
            -- "1001" = CLASS  I, SRC: register direct, DST: indexed
460
            -- "1011" = CLASS  I, SRC: indexed/symbolic/absolute, DST: indexed
461
            -- "1101" = CLASS  I, SRC: indirect, DST: indexed
462
            -- "1111" = CLASS  I, SRC: indirect auto inc, DST: indexed
463
            ctrl_nxt(ctrl_rf_as1_c) <= '0'; -- DST address mode = REG or INDEXED
464
            ctrl_nxt(ctrl_rf_as0_c) <= ir(7); -- DST address mode = REG or INDEXED
465
-->         ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "1--"; -- add memory data in
466
-->         ctrl_nxt(ctrl_adr_mar_sel_c) <= '1'; -- use result from adder
467
            ctrl_nxt(ctrl_adr_mar_wr_c) <= '1'; -- write to MAR
468
            mem_rd <= '1'; -- Memory read
469
            state_nxt <= TRANS_4;
470
 
471
          when others =>
472
            ctrl_nxt(ctrl_rf_as1_c downto ctrl_rf_as0_c) <= "00"; -- DST address mode = REG
473
            ctrl_nxt(ctrl_alu_opb_wr_c) <= '1'; -- write OpB
474
            if (am(2 downto 1) = "01") then
475
              state_nxt <= TRANS_4;
476
            else
477
              state_nxt <= TRANS_6;
478
            end if;
479
        end case;
480
 
481
      when TRANS_4 => -- operand transfer cycle 4
482
      -- ------------------------------------------------------------
483
        -- (pseudo) defaults 
484
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= src; -- source: reg A (only relevant for 3rd 'when')
485
        --
486
        case am is -- addressing mode
487
          when "0010" | "0011" | "1010" | "1011" =>
488
            -- "001-" = CLASS II, SRC/DST: indexed/symbolic/absolute
489
            -- "1010" = CLASS  I, SRC: indexed/symbolic/absolute, DST: register direct
490
            -- "1011" = CLASS  I, SRC: indexed/symbolic/absolute, DST: indexed
491
            ctrl_nxt(ctrl_alu_in_sel_c) <= '1'; -- get data from memory
492
            ctrl_nxt(ctrl_alu_opa_wr_c) <= '1'; -- write to OpA
493
            if (spec_cmd_v = '1') then -- push or call
494
              state_nxt <= PUSHCALL_0;
495
            elsif ((am(3) and am(0)) = '1') and (move_cmd_v = '0') then -- skip processing of second operand when executing MOV instruction
496
              state_nxt <= TRANS_5;
497
            else
498
              state_nxt <= TRANS_6;
499
            end if;
500
 
501
          when "1001" =>
502
            -- "1001" = CLASS  I, SRC: register direct, DST: indexed
503
            ctrl_nxt(ctrl_alu_opa_wr_c) <= '1'; -- write OpA
504
            if (move_cmd_v = '1') then -- skip processing of second operand when executing MOV instruction
505
              state_nxt <= TRANS_6;
506
            else
507
              state_nxt <= TRANS_5;
508
            end if;
509
 
510
          when others => -- NOP / DONT CARE
511
            -- "000-" = CLASS II, SRD/DST:  DONT CARE
512
            -- "1000" = CLASS  I, SRC: register direct, DST: register direct = DONT CARE
513
            -- "-10-" : NOP
514
            -- "-11-" : NOP
515
            if (move_cmd_v = '1') then -- skip processing of second operand when executing MOV instruction
516
              state_nxt <= TRANS_6;
517
            else
518
              state_nxt <= TRANS_5;
519
            end if;
520
        end case;
521
 
522
      when TRANS_5 => -- operand transfer cycle 5
523
      -- ------------------------------------------------------------
524
        ctrl_nxt(ctrl_alu_in_sel_c) <= '1'; -- get data from memory
525
        ctrl_nxt(ctrl_alu_opb_wr_c) <= '1'; -- write to OpB
526
        state_nxt <= TRANS_6;
527
 
528
      when TRANS_6 => -- operand transfer cycle 6: RF or MEM write-back
529
      -- ------------------------------------------------------------
530
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= ir(3 downto 0); -- destination
531
        ctrl_nxt(ctrl_rf_fup_c) <= not spec_cmd_v; -- update ALU status flags
532
        if (am(0) = '0') then -- DST: register direct (register file)
533
          ctrl_nxt(ctrl_rf_wb_en_c) <= valid_wb_v; -- valid RF write back (not for CMP/BIT!)
534
        else -- DST: indexed (memory)
535
          ctrl_nxt(ctrl_mem_wr_c) <= valid_wb_v; -- valid MEM write back (not for CMP/BIT!)
536
        end if;
537
        state_nxt <= IFETCH_0; -- done!
538
 
539
 
540
      when PUSHCALL_0 => -- PUSH/CALL cycle 0 (stack update)
541
      -- ------------------------------------------------------------
542
        ctrl_nxt(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) <= alu_mov_c; -- keep this for all following states
543
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_sp_c; -- source/destination: SP
544
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "011"; -- add -2
545
        ctrl_nxt(ctrl_adr_mar_wr_c) <= '1'; -- write to MAR
546
        ctrl_nxt(ctrl_adr_mar_sel_c) <= '1'; -- use result from adder
547
        ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback
548
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
549
        if (ir(7) = '1') then -- CALL
550
          state_nxt <= PUSHCALL_1;
551
        else -- PUSH
552
          state_nxt <= PUSHCALL_2;
553
        end if;
554
 
555
      when PUSHCALL_1 => -- CALL cycle 1 (buffer PC so it can be written to memory)
556
      -- ------------------------------------------------------------
557
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source/destination: PC
558
        ctrl_nxt(ctrl_alu_opa_wr_c) <= '1'; -- write to OpA
559
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
560
        state_nxt <= PUSHCALL_2;
561
 
562
      when PUSHCALL_2 => -- PUSH/CALL cycle 2 (write data to memory)
563
      -- ------------------------------------------------------------
564
        ctrl_nxt(ctrl_mem_wr_c) <= '1'; -- memory write request
565
        state_nxt <= IFETCH_0; -- done!
566
 
567
 
568
      when RETI_0 => -- RETI cycle 0: Output address of old SR; SP=SP+2
569
      -- ------------------------------------------------------------
570
        ctrl_nxt(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) <= alu_mov_c; -- keep this for all following states
571
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_sp_c; -- source/destination: SP
572
        ctrl_nxt(ctrl_adr_bp_en_c) <= '1'; -- directly output RF.out to address bus
573
        ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast)
574
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2
575
        ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback
576
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
577
        state_nxt <= RETI_1;
578
 
579
      when RETI_1 => -- RETI cycle 1: Buffer status register from MEM in OpA; Output address of old PC; SP=SP+2
580
      -- ------------------------------------------------------------
581
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_sp_c; -- source/destination: SP
582
        ctrl_nxt(ctrl_adr_bp_en_c) <= '1'; -- directly output RF.out to address bus
583
        ctrl_nxt(ctrl_mem_rd_c) <= '1'; -- Memory read (fast)
584
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "010"; -- add +2
585
        ctrl_nxt(ctrl_rf_in_sel_c) <= '1'; -- select addr gen feedback
586
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
587
        ctrl_nxt(ctrl_alu_in_sel_c) <= '1'; -- get data from memory
588
        ctrl_nxt(ctrl_alu_opa_wr_c) <= '1'; -- write to OpA
589
        state_nxt <= RETI_2;
590
 
591
      when RETI_2 => -- RETI cycle 4: Write status register; buffer return address from MEM in OpA
592
      -- ------------------------------------------------------------
593
        ctrl_nxt(ctrl_alu_in_sel_c) <= '1'; -- get data from memory
594
        ctrl_nxt(ctrl_alu_opa_wr_c) <= '1'; -- write to OpA
595
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_sr_c; -- destination: SR
596
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
597
        state_nxt <= RETI_3;
598
 
599
      when RETI_3 => -- RETI cycle 5: Write return address to PC
600
      -- ------------------------------------------------------------
601
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- destination: PC
602
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
603
        state_nxt <= IFETCH_0; -- done!
604
 
605
 
606
      when IRQ_0 => -- IRQ processing cycle 0: SP=SP-2, disable sleep mode
607
      -- ------------------------------------------------------------
608
        ctrl_nxt(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) <= alu_mov_c; -- keep this for all following states
609
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_sp_c; -- source/destination: SP
610
        ctrl_nxt(ctrl_adr_mar_wr_c)  <= '1'; -- write to MAR
611
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "011"; -- add -2
612
        ctrl_nxt(ctrl_adr_mar_sel_c) <= '1'; -- use result from adder
613
        ctrl_nxt(ctrl_rf_in_sel_c)   <= '1'; -- select addr gen feedback
614
        ctrl_nxt(ctrl_rf_wb_en_c)    <= '1'; -- valid RF write back
615
        ctrl_nxt(ctrl_rf_dsleep_c)   <= '1'; -- disable sleep mode
616
        state_nxt <= IRQ_1;
617
 
618
      when IRQ_1 => -- IRQ processing cycle 1: Buffer PC for memory write
619
      -- ------------------------------------------------------------
620
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- source: PC
621
        ctrl_nxt(ctrl_alu_opa_wr_c) <= '1'; -- write PC to OpA
622
        state_nxt <= IRQ_2;
623
 
624
      when IRQ_2 => -- IRQ processing cycle 2: Write PC to memory (push), SP=SP-2
625
      -- ------------------------------------------------------------
626
        ctrl_nxt(ctrl_mem_wr_c)      <= '1'; -- write memory request (store PC)
627
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_sp_c; -- source/destination: SP
628
        ctrl_nxt(ctrl_adr_mar_wr_c)  <= '1'; -- write to MAR
629
        ctrl_nxt(ctrl_adr_off2_c downto ctrl_adr_off0_c) <= "011"; -- add -2
630
        ctrl_nxt(ctrl_adr_mar_sel_c) <= '1'; -- use result from adder
631
        ctrl_nxt(ctrl_rf_in_sel_c)   <= '1'; -- select addr gen feedback
632
        ctrl_nxt(ctrl_rf_wb_en_c)    <= '1'; -- valid RF write back
633
        state_nxt <= IRQ_3;
634
 
635
      when IRQ_3 => -- IRQ processing cycle 3: Buffer SR for memory write, set IRQ vector address, disable interrupt enable flag in SR
636
      -- ------------------------------------------------------------
637
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_sr_c; -- source: SR
638
        ctrl_nxt(ctrl_alu_opa_wr_c)  <= '1'; -- write SR to OpA
639
        ctrl_nxt(ctrl_adr_bp_en_c)   <= '1'; -- directly output PC/IRQ vector
640
        ctrl_nxt(ctrl_adr_ivec_oe_c) <= '1'; -- output IRQ vector
641
        ctrl_nxt(ctrl_mem_rd_c)      <= '1'; -- Memory read (fast)
642
        ctrl_nxt(ctrl_rf_dgie_c)     <= '1'; -- disable interrupt enable flag
643
        irq_ack                      <= '1'; -- acknowledge started IRQ handler
644
        state_nxt <= IRQ_4;
645
 
646
      when IRQ_4 => -- IRQ processing cycle 4: Write SR (push), get IRQ vector
647
      -- ------------------------------------------------------------
648
        ctrl_nxt(ctrl_mem_wr_c)     <= '1'; -- write memory request
649
        ctrl_nxt(ctrl_alu_in_sel_c) <= '1'; -- get data from memory
650
        ctrl_nxt(ctrl_alu_opa_wr_c) <= '1'; -- write to OpA
651
        state_nxt <= IRQ_5;
652
 
653
      when IRQ_5 => -- IRQ processing cycle 5: Store IRQ vector to PC
654
      -- ------------------------------------------------------------
655
        ctrl_nxt(ctrl_rf_adr3_c downto ctrl_rf_adr0_c) <= reg_pc_c; -- destination: PC
656
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write back
657
        state_nxt <= IFETCH_0; -- done!
658
 
659
 
660
      when others => -- invalid
661
      -- ------------------------------------------------------------
662
        state_nxt <= RESET;
663
 
664
    end case;
665
  end process arbiter_comb;
666
 
667
 
668
  -- Interrupt Controller -----------------------------------------------------
669
  -- -----------------------------------------------------------------------------
670
  irq_buffer: process(clk_i)
671
  begin
672
    if rising_edge(clk_i) then
673
      -- delay I flag 2 cycles to allow the interrupted program to execute at least one insruction even if we have
674
      -- a permanent interrupt request
675
      i_flag_ff0 <= sreg_i(sreg_i_c);
676
      i_flag_ff1 <= i_flag_ff0;
677
      -- interrupt vector and queue buffer --
678
      for i in 0 to 3 loop
679
        irq_buf(i) <= (irq_buf(i) or irq_i(i)) and (not sreg_i(sreg_q_c)) and (not irq_ack_mask(i));
680
      end loop; -- i
681
      -- interrupt control --
682
      if (irq_start = '0') or (sreg_i(sreg_i_c) = '0') then -- idle or IRQs disabled
683
        irq_start <= '0';
684
        if (irq_fire = '1') then -- IRQ triggered
685
          irq_vec   <= irq_vec_nxt; -- capture source
686
          irq_start <= '1';
687
        end if;
688
      else -- active IRQ
689
        if (irq_ack = '1') then -- handler started?
690
          irq_start <= '0';
691
        end if;
692
      end if;
693
    end if;
694
  end process irq_buffer;
695
 
696
  -- valid start of IRQ handler --
697
  irq_fire <= '1' when (irq_buf /= "0000") and (i_flag_ff1 = '1') and (sreg_i(sreg_i_c) = '1') else '0';
698
 
699
  -- acknowledge mask --
700
  irq_ack_mask_gen: process(irq_ack, irq_vec)
701
    variable irq_tmp_v : std_ulogic_vector(2 downto 0);
702
  begin
703
    irq_tmp_v := irq_ack & irq_vec;
704
    case irq_tmp_v is
705
      when "100"  => irq_ack_mask <= "0001";
706
      when "101"  => irq_ack_mask <= "0010";
707
      when "110"  => irq_ack_mask <= "0100";
708
      when "111"  => irq_ack_mask <= "1000";
709
      when others => irq_ack_mask <= "0000";
710
    end case;
711
  end process;
712
 
713
  -- interrupt priority encoder --
714
  irq_priority: process(irq_buf)
715
  begin
716
    -- use "case" here to avoid a MUX chain
717
    case irq_buf is
718
      when "0001" | "0011" | "0101" | "0111" | "1001" | "1011" | "1101" | "1111" => -- "---1"
719
        irq_vec_nxt <= "00";
720
      when "0010" | "0110" | "1010" | "1110" => -- "--10"
721
        irq_vec_nxt <= "01";
722
      when "0100" | "1100" => -- "-100"
723
        irq_vec_nxt <= "10";
724
      when others => -- "1000" ("0000" -> dont't care)
725
        irq_vec_nxt <= "11";
726
    end case;
727
  end process irq_priority;
728
 
729
  -- interrupt vector output --
730
  irq_vec_o <= irq_vec; -- the final address is constructed in the address generator
731
 
732
 
733
end neo430_control_rtl;

powered by: WebSVN 2.1.0

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